mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-10 02:05:08 +00:00
Removes essentials-framework as a submodule and brings the files back into the main repo
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Essentials Devices Common", "Essentials Devices Common\Essentials Devices Common.csproj", "{892B761C-E479-44CE-BD74-243E9214AF13}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{892B761C-E479-44CE-BD74-243E9214AF13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{892B761C-E479-44CE-BD74-243E9214AF13}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{892B761C-E479-44CE-BD74-243E9214AF13}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{892B761C-E479-44CE-BD74-243E9214AF13}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents and audio endpoint
|
||||
/// </summary>
|
||||
public class GenericAudioOut : Device, IRoutingSinkNoSwitching
|
||||
{
|
||||
public RoutingInputPort AnyAudioIn { get; private set; }
|
||||
|
||||
public GenericAudioOut(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
AnyAudioIn = new RoutingInputPort(RoutingPortNames.AnyAudioIn, eRoutingSignalType.Audio,
|
||||
eRoutingPortConnectionType.LineAudio, null, this);
|
||||
}
|
||||
|
||||
#region IRoutingInputs Members
|
||||
|
||||
public RoutingPortCollection<RoutingInputPort> InputPorts
|
||||
{
|
||||
get { return new RoutingPortCollection<RoutingInputPort> { AnyAudioIn }; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Allows a zone-device's audio control to be attached to the endpoint, for easy routing and
|
||||
/// control switching. Will also set the zone name on attached devices, like SWAMP or other
|
||||
/// hardware with names built in.
|
||||
/// </summary>
|
||||
public class GenericAudioOutWithVolume : GenericAudioOut, IHasVolumeDevice
|
||||
{
|
||||
public string VolumeDeviceKey { get; private set; }
|
||||
public uint VolumeZone { get; private set; }
|
||||
|
||||
public IBasicVolumeControls VolumeDevice
|
||||
{
|
||||
get
|
||||
{
|
||||
var dev = DeviceManager.GetDeviceForKey(VolumeDeviceKey);
|
||||
if (dev is IAudioZones)
|
||||
return (dev as IAudioZones).Zone[VolumeZone];
|
||||
else return dev as IBasicVolumeControls;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor - adds the name to the attached audio device, if appropriate.
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="audioDevice"></param>
|
||||
/// <param name="zone"></param>
|
||||
public GenericAudioOutWithVolume(string key, string name, string audioDevice, uint zone)
|
||||
: base(key, name)
|
||||
{
|
||||
VolumeDeviceKey = audioDevice;
|
||||
VolumeZone = zone;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
||||
{
|
||||
public abstract class AudioCodecBase : Device, IHasDialer, IUsageTracking, IAudioCodecInfo
|
||||
{
|
||||
|
||||
public event EventHandler<CodecCallStatusItemChangeEventArgs> CallStatusChange;
|
||||
|
||||
public AudioCodecInfo CodecInfo { get; protected set; }
|
||||
|
||||
#region IUsageTracking Members
|
||||
|
||||
/// <summary>
|
||||
/// This object can be added by outside users of this class to provide usage tracking
|
||||
/// for various services
|
||||
/// </summary>
|
||||
public UsageTracking UsageTracker { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Returns true when any call is not in state Unknown, Disconnecting, Disconnected
|
||||
/// </summary>
|
||||
public bool IsInCall
|
||||
{
|
||||
get
|
||||
{
|
||||
bool value;
|
||||
|
||||
if (ActiveCalls != null)
|
||||
value = ActiveCalls.Any(c => c.IsActiveCall);
|
||||
else
|
||||
value = false;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// In most cases only a single call can be active
|
||||
public List<CodecActiveCallItem> ActiveCalls { get; set; }
|
||||
|
||||
public AudioCodecBase(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
ActiveCalls = new List<CodecActiveCallItem>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to fire CallStatusChange event with old and new status
|
||||
/// </summary>
|
||||
protected void SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus newStatus, CodecActiveCallItem call)
|
||||
{
|
||||
call.Status = newStatus;
|
||||
|
||||
OnCallStatusChange(call);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="previousStatus"></param>
|
||||
/// <param name="newStatus"></param>
|
||||
/// <param name="item"></param>
|
||||
protected void OnCallStatusChange(CodecActiveCallItem item)
|
||||
{
|
||||
var handler = CallStatusChange;
|
||||
if (handler != null)
|
||||
handler(this, new CodecCallStatusItemChangeEventArgs(item));
|
||||
|
||||
if (UsageTracker != null)
|
||||
{
|
||||
if (IsInCall && !UsageTracker.UsageTrackingStarted)
|
||||
UsageTracker.StartDeviceUsage();
|
||||
else if (UsageTracker.UsageTrackingStarted && !IsInCall)
|
||||
UsageTracker.EndDeviceUsage();
|
||||
}
|
||||
}
|
||||
|
||||
#region IHasDialer Members
|
||||
|
||||
public abstract void Dial(string number);
|
||||
|
||||
public abstract void EndCall(CodecActiveCallItem activeCall);
|
||||
|
||||
public abstract void EndAllCalls();
|
||||
|
||||
public abstract void AcceptCall(CodecActiveCallItem item);
|
||||
|
||||
public abstract void RejectCall(CodecActiveCallItem item);
|
||||
|
||||
public abstract void SendDtmf(string digit);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements a common set of data about a codec
|
||||
/// </summary>
|
||||
public interface IAudioCodecInfo
|
||||
{
|
||||
AudioCodecInfo CodecInfo { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores general information about a codec
|
||||
/// </summary>
|
||||
public abstract class AudioCodecInfo
|
||||
{
|
||||
public abstract string PhoneNumber { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
||||
{
|
||||
/// <summary>
|
||||
/// For rooms that have audio codec
|
||||
/// </summary>
|
||||
public interface IHasAudioCodec
|
||||
{
|
||||
AudioCodecBase AudioCodec { get; }
|
||||
BoolFeedback InCallFeedback { get; }
|
||||
|
||||
///// <summary>
|
||||
///// Make this more specific
|
||||
///// </summary>
|
||||
//List<PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem> ActiveCalls { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
||||
{
|
||||
public class MockAC : AudioCodecBase
|
||||
{
|
||||
public MockAC(string key, string name, MockAcPropertiesConfig props)
|
||||
: base(key, name)
|
||||
{
|
||||
CodecInfo = new MockAudioCodecInfo();
|
||||
|
||||
CodecInfo.PhoneNumber = props.PhoneNumber;
|
||||
}
|
||||
|
||||
public override void Dial(string number)
|
||||
{
|
||||
if (!IsInCall)
|
||||
{
|
||||
Debug.Console(1, this, "Dial: {0}", number);
|
||||
var call = new CodecActiveCallItem()
|
||||
{
|
||||
Name = "Mock Outgoing Call",
|
||||
Number = number,
|
||||
Type = eCodecCallType.Audio,
|
||||
Status = eCodecCallStatus.Connected,
|
||||
Direction = eCodecCallDirection.Outgoing,
|
||||
Id = "mockAudioCall-1"
|
||||
};
|
||||
|
||||
ActiveCalls.Add(call);
|
||||
|
||||
OnCallStatusChange(call);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "Already in call. Cannot dial new call.");
|
||||
}
|
||||
}
|
||||
|
||||
public override void EndCall(CodecActiveCallItem call)
|
||||
{
|
||||
Debug.Console(1, this, "EndCall");
|
||||
ActiveCalls.Remove(call);
|
||||
SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call);
|
||||
}
|
||||
|
||||
public override void EndAllCalls()
|
||||
{
|
||||
Debug.Console(1, this, "EndAllCalls");
|
||||
for (int i = ActiveCalls.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var call = ActiveCalls[i];
|
||||
ActiveCalls.Remove(call);
|
||||
SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call);
|
||||
}
|
||||
}
|
||||
|
||||
public override void AcceptCall(CodecActiveCallItem call)
|
||||
{
|
||||
Debug.Console(1, this, "AcceptCall");
|
||||
SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connecting, call);
|
||||
}
|
||||
|
||||
public override void RejectCall(CodecActiveCallItem call)
|
||||
{
|
||||
Debug.Console(1, this, "RejectCall");
|
||||
ActiveCalls.Remove(call);
|
||||
SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call);
|
||||
}
|
||||
|
||||
public override void SendDtmf(string s)
|
||||
{
|
||||
Debug.Console(1, this, "BEEP BOOP SendDTMF: {0}", s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
public void TestIncomingAudioCall(string number)
|
||||
{
|
||||
Debug.Console(1, this, "TestIncomingAudioCall from {0}", number);
|
||||
var call = new CodecActiveCallItem() { Name = number, Id = number, Number = number, Type = eCodecCallType.Audio, Direction = eCodecCallDirection.Incoming };
|
||||
ActiveCalls.Add(call);
|
||||
SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Ringing, call);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class MockAudioCodecInfo : AudioCodecInfo
|
||||
{
|
||||
string _phoneNumber;
|
||||
|
||||
public override string PhoneNumber
|
||||
{
|
||||
get
|
||||
{
|
||||
return _phoneNumber;
|
||||
}
|
||||
set
|
||||
{
|
||||
_phoneNumber = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
||||
{
|
||||
public class MockAcPropertiesConfig
|
||||
{
|
||||
[JsonProperty("phoneNumber")]
|
||||
public string PhoneNumber { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
using System.Text.RegularExpressions;
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||
{
|
||||
public enum eCameraCapabilities
|
||||
{
|
||||
None = 0,
|
||||
Pan = 1,
|
||||
Tilt = 2,
|
||||
Zoom = 4,
|
||||
Focus = 8
|
||||
}
|
||||
|
||||
public abstract class CameraBase : Device
|
||||
{
|
||||
public bool CanPan
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Capabilities & eCameraCapabilities.Pan) == eCameraCapabilities.Pan;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanTilt
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Capabilities & eCameraCapabilities.Tilt) == eCameraCapabilities.Tilt;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanZoom
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Capabilities & eCameraCapabilities.Zoom) == eCameraCapabilities.Zoom;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanFocus
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Capabilities & eCameraCapabilities.Focus) == eCameraCapabilities.Focus;
|
||||
}
|
||||
}
|
||||
|
||||
// A bitmasked value to indicate the movement capabilites of this camera
|
||||
protected eCameraCapabilities Capabilities { get; set; }
|
||||
|
||||
public CameraBase(string key, string name) :
|
||||
base(key, name) { }
|
||||
}
|
||||
|
||||
public class CameraPropertiesConfig
|
||||
{
|
||||
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
||||
|
||||
public ControlPropertiesConfig Control { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
using System.Text.RegularExpressions;
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||
{
|
||||
public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor
|
||||
{
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
public CommunicationGather PortGather { get; private set; }
|
||||
|
||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||
|
||||
public byte PanSpeed = 0x10;
|
||||
public byte TiltSpeed = 0x10;
|
||||
private bool IsMoving;
|
||||
private bool IsZooming;
|
||||
public bool PowerIsOn { get; private set; }
|
||||
|
||||
byte[] IncomingBuffer = new byte[] { };
|
||||
public BoolFeedback PowerIsOnFeedback { get; private set; }
|
||||
|
||||
public CameraVisca(string key, string name, IBasicCommunication comm, CameraPropertiesConfig props) :
|
||||
base(key, name)
|
||||
{
|
||||
|
||||
// Default to all capabilties
|
||||
Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom | eCameraCapabilities.Focus;
|
||||
|
||||
Communication = comm;
|
||||
var socket = comm as ISocketStatus;
|
||||
if (socket != null)
|
||||
{
|
||||
// This instance uses IP control
|
||||
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This instance uses RS-232 control
|
||||
}
|
||||
PortGather = new CommunicationGather(Communication, "\xFF");
|
||||
|
||||
|
||||
Communication.BytesReceived += new EventHandler<GenericCommMethodReceiveBytesArgs>(Communication_BytesReceived);
|
||||
PowerIsOnFeedback = new BoolFeedback(() => { return PowerIsOn; });
|
||||
|
||||
if (props.CommunicationMonitorProperties != null)
|
||||
{
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 20000, 120000, 300000, "\x81\x09\x04\x00\xFF");
|
||||
}
|
||||
DeviceManager.AddDevice(CommunicationMonitor);
|
||||
|
||||
|
||||
}
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
Communication.Connect();
|
||||
|
||||
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
CommunicationMonitor.Start();
|
||||
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
return true;
|
||||
}
|
||||
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
||||
{
|
||||
Debug.Console(2, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
|
||||
|
||||
if (e.Client.IsConnected)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SendBytes(byte[] b)
|
||||
{
|
||||
|
||||
if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
|
||||
Debug.Console(2, this, "Sending:{0}", ComTextHelper.GetEscapedText(b));
|
||||
|
||||
Communication.SendBytes(b);
|
||||
}
|
||||
void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e)
|
||||
{
|
||||
// This is probably not thread-safe buffering
|
||||
// Append the incoming bytes with whatever is in the buffer
|
||||
var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length];
|
||||
IncomingBuffer.CopyTo(newBytes, 0);
|
||||
e.Bytes.CopyTo(newBytes, IncomingBuffer.Length);
|
||||
if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
|
||||
Debug.Console(2, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes));
|
||||
}
|
||||
|
||||
|
||||
private void SendPanTiltCommand (byte[] cmd)
|
||||
{
|
||||
var temp = new Byte[] { 0x81, 0x01, 0x06, 0x01, PanSpeed, TiltSpeed };
|
||||
int length = temp.Length + cmd.Length + 1;
|
||||
|
||||
byte[] sum = new byte[length];
|
||||
temp.CopyTo(sum, 0);
|
||||
cmd.CopyTo(sum, temp.Length);
|
||||
sum[length - 1] = 0xFF;
|
||||
SendBytes(sum);
|
||||
}
|
||||
|
||||
public void PowerOn()
|
||||
{
|
||||
|
||||
SendBytes(new Byte[] { 0x81, 0x01, 0x04, 0x00, 0x02, 0xFF });
|
||||
}
|
||||
|
||||
public void PowerOff()
|
||||
{
|
||||
SendBytes(new Byte[] {0x81, 0x01, 0x04, 0x00, 0x03, 0xFF});
|
||||
}
|
||||
public void PanLeft()
|
||||
{
|
||||
SendPanTiltCommand(new byte[] {0x01, 0x03});
|
||||
IsMoving = true;
|
||||
}
|
||||
public void PanRight()
|
||||
{
|
||||
SendPanTiltCommand(new byte[] { 0x02, 0x03 });
|
||||
IsMoving = true;
|
||||
}
|
||||
public void PanStop()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
public void TiltDown()
|
||||
{
|
||||
SendPanTiltCommand(new byte[] { 0x03, 0x02 });
|
||||
IsMoving = true;
|
||||
}
|
||||
public void TiltUp()
|
||||
{
|
||||
SendPanTiltCommand(new byte[] { 0x03, 0x01 });
|
||||
IsMoving = true;
|
||||
}
|
||||
public void TiltStop()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
private void SendZoomCommand (byte cmd)
|
||||
{
|
||||
SendBytes(new byte[] {0x81, 0x01, 0x04, 0x07, cmd, 0xFF} );
|
||||
}
|
||||
public void ZoomIn()
|
||||
{
|
||||
SendZoomCommand(0x02);
|
||||
IsZooming = true;
|
||||
}
|
||||
public void ZoomOut()
|
||||
{
|
||||
SendZoomCommand(0x03);
|
||||
IsZooming = true;
|
||||
}
|
||||
public void ZoomStop()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (IsZooming)
|
||||
{
|
||||
SendZoomCommand(0x00);
|
||||
IsZooming = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendPanTiltCommand(new byte[] {0x03, 0x03});
|
||||
IsMoving = false;
|
||||
}
|
||||
}
|
||||
public void PositionHome()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public void RecallPreset(int presetNumber)
|
||||
{
|
||||
SendBytes(new byte[] {0x81, 0x01, 0x04, 0x3F, 0x02, (byte)presetNumber, 0xFF} );
|
||||
}
|
||||
public void SavePreset(int presetNumber)
|
||||
{
|
||||
SendBytes(new byte[] { 0x81, 0x01, 0x04, 0x3F, 0x01, (byte)presetNumber, 0xFF });
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,740 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ClassDiagram MajorVersion="1" MinorVersion="1">
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.GenericAudioOut" Collapsed="true">
|
||||
<Position X="0.5" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAA=</HashCode>
|
||||
<FileName>Audio\GenericAudioOut.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.GenericAudioOutWithVolume" Collapsed="true">
|
||||
<Position X="0.5" Y="9" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAgAAAAQA=</HashCode>
|
||||
<FileName>Audio\GenericAudioOut.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.CenRfgwController" Collapsed="true">
|
||||
<Position X="19" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAIIAAAAAAACABAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Crestron\Gateways\CenRfgwController.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.IRBlurayBase" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="17.25" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gUyjAAoIAAAAxgYAABAAgAECABAoAEAQqcCAQHIABAI=</HashCode>
|
||||
<FileName>DiscPlayer\IRDiscPlayerBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.DeviceFactory" Collapsed="true">
|
||||
<Position X="15.5" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Factory\DeviceFactory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.GenericSource" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="12" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAgAAAAAAAACAAAAAAAAAAAAAAAgAAAAAAAAAAIAAAA=</HashCode>
|
||||
<FileName>Generic\GenericSource.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.InRoomPc" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="15.5" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAwAAAAAAAACAAAAAAACAAAAAQAgAAAAAAAAAAIAAAA=</HashCode>
|
||||
<FileName>PC\InRoomPc.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Laptop" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="22.5" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAwAAAAAAAACAAAAAAACAAAAAQAgAAAAAAAAAAIAAAA=</HashCode>
|
||||
<FileName>PC\Laptop.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.IRSetTopBoxBase" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="19" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AUgjCAqAEAASwgYAACAAoAECABAoAEAwrcCAQHKABAI=</HashCode>
|
||||
<FileName>SetTopBox\IRSetTopBoxBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.SetTopBoxPropertiesConfig" Collapsed="true">
|
||||
<Position X="13.75" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAEEAAQAAAAAAAAIAAAAAAAAAAAAAAAAACAAAA=</HashCode>
|
||||
<FileName>SetTopBox\SetTopBoxPropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.AppleTV" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="10.25" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAggAAIAAAAARAAAAAAAgAACABAoAEAQqACAQAAABAI=</HashCode>
|
||||
<FileName>Streaming\AppleTV.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Roku2" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="10.25" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAggAAIAAAAABAAAAAAAgAACABAoAEAQqACAQAAABAI=</HashCode>
|
||||
<FileName>Streaming\Roku.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem" Collapsed="true">
|
||||
<Position X="19" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAEAAAAAAAAAOAAAAQAAAAAAAAAAQAAAAAAAAA=</HashCode>
|
||||
<FileName>Codec\CodecActiveCallItem.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs" Collapsed="true">
|
||||
<Position X="15.5" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Codec\CodecActiveCallItem.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.CodecCallDirection" Collapsed="true">
|
||||
<Position X="20.75" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAA=</HashCode>
|
||||
<FileName>Codec\eCodecCallDirection.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.CodecCallStatus" Collapsed="true">
|
||||
<Position X="13.75" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAA=</HashCode>
|
||||
<FileName>Codec\eCodecCallStatus.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.CodecCallType" Collapsed="true">
|
||||
<Position X="17.25" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAA=</HashCode>
|
||||
<FileName>Codec\eCodecCallType.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.CodecCallPrivacy" Collapsed="true">
|
||||
<Position X="12" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAA=</HashCode>
|
||||
<FileName>Codec\eMeetingPrivacy.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.VideoCodecInfo" Collapsed="true">
|
||||
<Position X="5.5" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gIAAAAAAAAAAAACCAACAAAAAAAAAAAACAAAAAABAAAA=</HashCode>
|
||||
<FileName>Codec\iCodecInfo.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.CodecCallFavorites" Collapsed="true">
|
||||
<Position X="22.5" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAA=</HashCode>
|
||||
<FileName>Codec\iHasCallFavorites.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.CodecCallHistory" Collapsed="true">
|
||||
<Position X="10.25" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAQAAAAAgAAAAAAAAAAAAAAGAAAABAAAAAAACQ=</HashCode>
|
||||
<FileName>Codec\iHasCallHistory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.DirectoryEventArgs" Collapsed="true">
|
||||
<Position X="17.25" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Codec\iHasDirectory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.CodecDirectory" Collapsed="true">
|
||||
<Position X="20.75" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAIAAAAAAAAAAAABAAAAAIAAIAAQAAAAAA=</HashCode>
|
||||
<FileName>Codec\iHasDirectory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.DirectoryItem" Collapsed="true">
|
||||
<Position X="6.75" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Codec\iHasDirectory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.DirectoryFolder" Collapsed="true">
|
||||
<Position X="5.5" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAIAAAAAAAAA=</HashCode>
|
||||
<FileName>Codec\iHasDirectory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.DirectoryContact" Collapsed="true">
|
||||
<Position X="7.75" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAgAAAAAAAEAAAAAAAAAAAAAAAAEIAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Codec\iHasDirectory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.ContactMethod" Collapsed="true">
|
||||
<Position X="13.75" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAIAAAAAAAgAAAEAAAAAAAAAIAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Codec\iHasDirectory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.DirectorySearchResultEventArgs" Collapsed="true">
|
||||
<Position X="19" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Codec\iHasDirectory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.CodecScheduleAwareness" Collapsed="true">
|
||||
<Position X="10.25" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAABAAAAAEAAAAAAAgAAEAAAABAAAAAAAIQAAAAA=</HashCode>
|
||||
<FileName>Codec\iHasScheduleAwareness.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.Meeting" Collapsed="true">
|
||||
<Position X="13.75" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAACEEgAAAAAAAgQIAAoAQABAAQAAEgAAAA=</HashCode>
|
||||
<FileName>Codec\iHasScheduleAwareness.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.Call" Collapsed="true">
|
||||
<Position X="17.25" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAEAAAABAAAAIAAAAAAAAAAgAAAA=</HashCode>
|
||||
<FileName>Codec\iHasScheduleAwareness.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.MeetingEventArgs" Collapsed="true">
|
||||
<Position X="15.5" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAQAAAAA=</HashCode>
|
||||
<FileName>Codec\iHasScheduleAwareness.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.CiscoSparkCodecPropertiesConfig" Collapsed="true">
|
||||
<Position X="17.25" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAQAAAAAAAAAAAAAAAAAIQAAACAABAAAAA=</HashCode>
|
||||
<FileName>VideoCodec\CiscoCodec\CiscoSparkCodecPropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Codec.SharingProperties" Collapsed="true">
|
||||
<Position X="15.5" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAA=</HashCode>
|
||||
<FileName>VideoCodec\CiscoCodec\CiscoSparkCodecPropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Displays.AvocorDisplay" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="12" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>hC4gIEAIUAABoQAEgBACAAAdBC1gmsGRICKGdQNBACw=</HashCode>
|
||||
<FileName>Display\AvocorVTFDisplay.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Displays.ComTcpDisplayBase" Collapsed="true">
|
||||
<Position X="6.5" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAEQAAAAA=</HashCode>
|
||||
<FileName>Display\ComTcpDisplayBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Displays.DisplayDeviceFactory" Collapsed="true">
|
||||
<Position X="20.75" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Display\DeviceFactory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Displays.NecPaSeriesProjector" Collapsed="true">
|
||||
<Position X="6.5" Y="8" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>ogSIAAKIAAALCAAEABAQEAgABAAAAMIAAAAAEABAACA=</HashCode>
|
||||
<FileName>Display\NecPaSeriesProjector.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Displays.NecPSXMDisplay" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="22.5" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>hLQgIShIAABFQQRUAvICDRMQESwSEQKRKACCZQNAESY=</HashCode>
|
||||
<FileName>Display\NECPSXMDisplay.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Displays.SamsungMDC" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="12" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>hKwwIEAIQAABoUAGgBACAAAEBGxAmYORKCCGZQJAACw=</HashCode>
|
||||
<FileName>Display\SamsungMDCDisplay.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.DSP.BiampTesiraForteDsp" Collapsed="true">
|
||||
<Position X="3.5" Y="8" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gACAAIAAAAEAQYCigAAAAAAQAACgCAAAAAAAAAMAAAI=</HashCode>
|
||||
<FileName>DSP\BiampTesira\BiampTesiraForteDsp.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.DSP.TesiraForteLevelControl" Collapsed="true">
|
||||
<Position X="0.5" Y="6.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>RAAgJACAAAAAAYAAAkIAAAAAIAQCEACJABACRAAAAUQ=</HashCode>
|
||||
<FileName>DSP\BiampTesira\BiampTesiraForteDspLevel.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.DSP.BiampTesiraFortePropertiesConfig" Collapsed="true">
|
||||
<Position X="15.5" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>BAAAAAAEAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>DSP\BiampTesira\BiampTesiraFortePropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.DSP.BiampTesiraForteLevelControlBlockConfig" Collapsed="true">
|
||||
<Position X="13.75" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAEAAAAIAAAAAAAAAAAAAAAAAIAAEAAAAAAEQ=</HashCode>
|
||||
<FileName>DSP\BiampTesira\BiampTesiraFortePropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.DSP.TesiraForteControlPoint" Collapsed="true">
|
||||
<Position X="0.5" Y="4.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAIAAAAACAAQQAAAAAQAAAAAAAIAAAABEAAAAAAEA=</HashCode>
|
||||
<FileName>DSP\BiampTesira\TesiraForteControlPoint.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.DSP.DspBase" Collapsed="true">
|
||||
<Position X="3.5" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAEAIAgAAAAAAIAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>DSP\DspBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.DSP.DspControlPoint" Collapsed="true">
|
||||
<Position X="1.75" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>DSP\DspBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.DSP.DspMuteControl" Collapsed="true">
|
||||
<Position X="2.75" Y="4.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>BAAAAAAAAAAAAAAAAQAAAAAAAAAAAAABAAAAQAAAAAQ=</HashCode>
|
||||
<FileName>DSP\DspBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.DSP.SoundStructureBasics" Collapsed="true">
|
||||
<Position X="17.25" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAA=</HashCode>
|
||||
<FileName>DSP\PolycomSoundStructure\SoundStructureBasics.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Environment.Lutron.LutronQuantumArea" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="10.25" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gACAEBAAAoAABQBAASAAAAAAAAEgAAACAAACAAMAQAI=</HashCode>
|
||||
<FileName>Environment\Lutron\LutronQuantum.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Environment.Lutron.LutronQuantumPropertiesConfig" Collapsed="true">
|
||||
<Position X="12" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAEAAAAAAAAgQAAAAAAAAAAAAQCAAACAAAAAAA=</HashCode>
|
||||
<FileName>Environment\Lutron\LutronQuantum.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Microphones.MicrophonePrivacyController" Collapsed="true">
|
||||
<Position X="17.25" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gQAABAAAAxAAIACAgAgAgCBAUQAAQAgCIAEQAACBAAA=</HashCode>
|
||||
<FileName>Microphone\MicrophonePrivacyController.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Microphones.MicrophonePrivacyControllerConfig" Collapsed="true">
|
||||
<Position X="19" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAEAAAAAgAIAAAAAAAAAA=</HashCode>
|
||||
<FileName>Microphone\MicrophonePrivacyControllerConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Microphones.KeyedDevice" Collapsed="true">
|
||||
<Position X="20.75" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Microphone\MicrophonePrivacyControllerConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Occupancy.EssentialsGlsOccupancySensorBaseController" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="22.5" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAIAAAAAAAABAABgAAAAAASEABAAAAAAAAA=</HashCode>
|
||||
<FileName>Occupancy\EssentialsGlsOccupancySensorBaseController.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.Occupancy.EssentialsOccupancyAggregator" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="10.25" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACBAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Occupancy\EssentialsOccupancyAggregator.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.VideoCodec.CiscoCodecBookings" Collapsed="true">
|
||||
<Position X="22.5" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAg=</HashCode>
|
||||
<FileName>VideoCodec\CiscoCodec\BookingsDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.VideoCodec.CiscoCallHistory" Collapsed="true">
|
||||
<Position X="20.75" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>VideoCodec\CiscoCodec\CallHistoryDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.VideoCodec.CiscoCodecPhonebook" Collapsed="true">
|
||||
<Position X="13.75" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>EAAAABAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAA=</HashCode>
|
||||
<FileName>VideoCodec\CiscoCodec\PhonebookDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.VideoCodec.MockVC" Collapsed="true">
|
||||
<Position X="0.5" Y="2" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>BgYAIAACAQaKBACAAwAAUSQAAWYCEACDAAiAQBBCgQU=</HashCode>
|
||||
<FileName>VideoCodec\MockVC\MockVC.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.VideoCodec.MockCodecInfo" Collapsed="true">
|
||||
<Position X="5.5" Y="4.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gKAAAAAAAAAAAACCAACAAAAAAAAAAAACAAAAAABBAAA=</HashCode>
|
||||
<FileName>VideoCodec\MockVC\MockVC.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.VideoCodec.MockVcPropertiesConfig" Collapsed="true">
|
||||
<Position X="20.75" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAA=</HashCode>
|
||||
<FileName>VideoCodec\MockVC\MockVcPropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase" Collapsed="true">
|
||||
<Position X="1.75" Y="2" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>BiwgAAECAASAAECAgQEDIABAAAYiEBCpCEigQBZCAQU=</HashCode>
|
||||
<FileName>VideoCodec\VideoCodecBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.VideoCodec.CodecPhonebookSyncState" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="22.5" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>EAiCAAQAAgEAAQQAEAAAAAAAAAEAAAAAAACAAAAAAAM=</HashCode>
|
||||
<FileName>VideoCodec\VideoCodecBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CiscoSparkCodec" Collapsed="true">
|
||||
<Position X="2.75" Y="2" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>jhQEtAJaASb7kSCwAwtxECSABsf2n1GBJEmAVJFKWTc=</HashCode>
|
||||
<FileName>VideoCodec\CiscoCodec\CiscoSparkCodec.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CodecCommandWithLabel" Collapsed="true">
|
||||
<Position X="19" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAEAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>VideoCodec\CiscoCodec\CiscoSparkCodec.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CodecSyncState" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="12" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AIAAAAQACAEAAAQAEAAAAAAAAAAgAAAAAAAACAACACE=</HashCode>
|
||||
<FileName>VideoCodec\CiscoCodec\CiscoSparkCodec.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.HttpApiServer" Collapsed="true">
|
||||
<Position X="13.75" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAQAAAACAAAAABAAAAAAAIAIAAAAAAAQAAgAAAAAA=</HashCode>
|
||||
<FileName>VideoCodec\CiscoCodec\HttpApiServer.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CiscoCodecConfiguration" Collapsed="true">
|
||||
<Position X="10.25" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>VideoCodec\CiscoCodec\xConfiguration.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CiscoCodecEvents" Collapsed="true">
|
||||
<Position X="12" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>VideoCodec\CiscoCodec\xEvent.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CiscoCodecStatus" Collapsed="true">
|
||||
<Position X="15.5" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>VideoCodec\CiscoCodec\xStatus.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Devices.Common.VideoCodec.CiscoCodec.xStatusSparkPlus" Collapsed="true">
|
||||
<Position X="19" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>VideoCodec\CiscoCodec\xStatusSparkPlus.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Common.Codec.ICodecAudio" Collapsed="true">
|
||||
<Position X="10.25" Y="7.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Codec\iCodecAudio.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Common.Codec.iCodecInfo" Collapsed="true">
|
||||
<Position X="12" Y="7.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Codec\iCodecInfo.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Common.Codec.IHasCallFavorites" Collapsed="true">
|
||||
<Position X="15.5" Y="7.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Codec\iHasCallFavorites.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Common.Codec.IHasCallHistory" Collapsed="true">
|
||||
<Position X="17.25" Y="7.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Codec\iHasCallHistory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Common.Codec.IHasContentSharing" Collapsed="true">
|
||||
<Position X="22.5" Y="7.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAACAAAAAAAAAAAAAAAAAAAAAAAIAEAgABAAAAA=</HashCode>
|
||||
<FileName>Codec\iHasContentSharing.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Common.Codec.IHasDialer" Collapsed="true">
|
||||
<Position X="10.25" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAgAAAACAAAAAACAAAAAAAAAAAICAAAAAAAAAAQCAAA=</HashCode>
|
||||
<FileName>Codec\iHasDialer.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Common.Codec.IHasDirectory" Collapsed="true">
|
||||
<Position X="12" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAgAAAAAAAAAAAAgCAAAAABAAAEAAAAAA=</HashCode>
|
||||
<FileName>Codec\iHasDirectory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Common.Codec.IHasScheduleAwareness" Collapsed="true">
|
||||
<Position X="13.75" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Codec\iHasScheduleAwareness.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Displays.IInputHdmi1" Collapsed="true">
|
||||
<Position X="19" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAA=</HashCode>
|
||||
<FileName>Display\InputInterfaces.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Displays.IInputHdmi2" Collapsed="true">
|
||||
<Position X="20.75" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAA=</HashCode>
|
||||
<FileName>Display\InputInterfaces.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Displays.IInputHdmi3" Collapsed="true">
|
||||
<Position X="22.5" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAA=</HashCode>
|
||||
<FileName>Display\InputInterfaces.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Displays.IInputHdmi4" Collapsed="true">
|
||||
<Position X="10.25" Y="9.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAA=</HashCode>
|
||||
<FileName>Display\InputInterfaces.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Displays.IInputDisplayPort1" Collapsed="true">
|
||||
<Position X="15.5" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAA=</HashCode>
|
||||
<FileName>Display\InputInterfaces.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Displays.IInputDisplayPort2" Collapsed="true">
|
||||
<Position X="17.25" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Display\InputInterfaces.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Displays.IInputVga1" Collapsed="true">
|
||||
<Position X="12" Y="9.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Display\InputInterfaces.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Common.DSP.IDspLevelControl" Collapsed="true">
|
||||
<Position X="13.75" Y="7.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>QAAAAACAAAAAAAAAAAAAAAAAAAAAAAAIAAEAAAAAAAQ=</HashCode>
|
||||
<FileName>DSP\DspBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Common.Occupancy.IOccupancyStatusProvider" Collapsed="true">
|
||||
<Position X="13.75" Y="9.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Occupancy\iOccupancyStatusProvider.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Common.VideoCodec.IHasCodecLayouts" Collapsed="true">
|
||||
<Position X="19" Y="7.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAgAAAAAAAAAAAAAAAEEgAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>VideoCodec\Interfaces\IHasCodecLayouts.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Devices.Common.VideoCodec.IHasCodecSelfview" Collapsed="true">
|
||||
<Position X="20.75" Y="7.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>ABAAEAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAABAAAAI=</HashCode>
|
||||
<FileName>VideoCodec\Interfaces\IHasCodecSelfview.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Enum Name="PepperDash.Essentials.Devices.Common.eExGatewayType" Collapsed="true">
|
||||
<Position X="10.25" Y="11" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAgAAAAAAAAAAAAAIAAAEAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Crestron\Gateways\CenRfgwController.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.Devices.Common.Codec.eCodecCallDirection" Collapsed="true">
|
||||
<Position X="12" Y="10.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAAAAAAABA=</HashCode>
|
||||
<FileName>Codec\eCodecCallDirection.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.Devices.Common.Codec.eCodecCallStatus" Collapsed="true">
|
||||
<Position X="13.75" Y="10.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>CAgAAABAAAAAQAACAAABAAAAAAAAAAABCAAAAiAAQBA=</HashCode>
|
||||
<FileName>Codec\eCodecCallStatus.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.Devices.Common.Codec.eCodecCallType" Collapsed="true">
|
||||
<Position X="15.5" Y="10.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAoBg=</HashCode>
|
||||
<FileName>Codec\eCodecCallType.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.Devices.Common.Codec.eMeetingPrivacy" Collapsed="true">
|
||||
<Position X="13.75" Y="11" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAQBA=</HashCode>
|
||||
<FileName>Codec\eMeetingPrivacy.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.Devices.Common.Codec.eCodecOccurrenceType" Collapsed="true">
|
||||
<Position X="17.25" Y="10.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAABAAAAAIAAAAAAAAAAAAAAAAAAAEAAAAAAABA=</HashCode>
|
||||
<FileName>Codec\iHasCallHistory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.Devices.Common.Codec.eContactMethodDevice" Collapsed="true">
|
||||
<Position X="22.5" Y="10.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>BAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAIAAAAAAABg=</HashCode>
|
||||
<FileName>Codec\iHasDirectory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.Devices.Common.Codec.eContactMethodCallType" Collapsed="true">
|
||||
<Position X="20.75" Y="10.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAABg=</HashCode>
|
||||
<FileName>Codec\iHasDirectory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.Devices.Common.Codec.eMeetingEventChangeType" Collapsed="true">
|
||||
<Position X="12" Y="11" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>BAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAIACg=</HashCode>
|
||||
<FileName>Codec\iHasScheduleAwareness.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.Devices.Common.Environment.Lutron.eAction" Collapsed="true">
|
||||
<Position X="10.25" Y="10.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AACAACAAABAAgIAAgAAQAAAAAAAAIAAAIAAAACAEAAg=</HashCode>
|
||||
<FileName>Environment\Lutron\LutronQuantum.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eCommandType" Collapsed="true">
|
||||
<Position X="19" Y="10.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAACAQAAAAABAAEAAAAAAAAgAAAAAAAAAA=</HashCode>
|
||||
<FileName>VideoCodec\CiscoCodec\CiscoSparkCodec.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Font Name="Segoe UI" Size="9" />
|
||||
</ClassDiagram>
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
|
||||
{
|
||||
public class CodecActiveCallItem
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("number")]
|
||||
public string Number { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public eCodecCallType Type { get; set; }
|
||||
|
||||
[JsonProperty("status")]
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public eCodecCallStatus Status { get; set; }
|
||||
|
||||
[JsonProperty("direction")]
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public eCodecCallDirection Direction { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
//public object CallMetaData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true when this call is any status other than
|
||||
/// Unknown, Disconnected, Disconnecting
|
||||
/// </summary>
|
||||
[JsonProperty("isActiveCall")]
|
||||
public bool IsActiveCall
|
||||
{
|
||||
get
|
||||
{
|
||||
return !(Status == eCodecCallStatus.Disconnected
|
||||
|| Status == eCodecCallStatus.Disconnecting
|
||||
|| Status == eCodecCallStatus.Idle
|
||||
|| Status == eCodecCallStatus.Unknown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CodecCallStatusItemChangeEventArgs : EventArgs
|
||||
{
|
||||
public CodecActiveCallItem CallItem { get; private set; }
|
||||
|
||||
public CodecCallStatusItemChangeEventArgs(CodecActiveCallItem item)
|
||||
{
|
||||
CallItem = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
|
||||
{
|
||||
public class CodecActiveCallItem
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Number { get; set; }
|
||||
|
||||
<<<<<<< HEAD:Essentials Devices Common/Essentials Devices Common/Codec/CodecActiveCallItem.cs
|
||||
public eCodecCallType Type { get; set; }
|
||||
|
||||
public eCodecCallStatus Status { get; set; }
|
||||
|
||||
public string Id { get; set; }
|
||||
=======
|
||||
public eCodecCallType Type { get; set; }
|
||||
|
||||
public eCodecCallStatus Status { get; set; }
|
||||
|
||||
public string Id { get; set; }
|
||||
|
||||
public object CallMetaData { get; set; }
|
||||
>>>>>>> origin/feature/cisco-spark-2:Essentials Devices Common/Essentials Devices Common/VideoCodec/CodecActiveCallItem.cs
|
||||
}
|
||||
|
||||
public enum eCodecCallType
|
||||
{
|
||||
Unknown = 0, Audio, Video
|
||||
<<<<<<< HEAD:Essentials Devices Common/Essentials Devices Common/Codec/CodecActiveCallItem.cs
|
||||
}
|
||||
|
||||
public enum eCodecCallStatus
|
||||
{
|
||||
Unknown = 0, Dialing, Connected, Incoming, OnHold, Disconnected
|
||||
=======
|
||||
}
|
||||
|
||||
public enum eCodecCallStatus
|
||||
{
|
||||
Unknown = 0, Dialing, Connected, Incoming, OnHold, Disconnected
|
||||
>>>>>>> origin/feature/cisco-spark-2:Essentials Devices Common/Essentials Devices Common/VideoCodec/CodecActiveCallItem.cs
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
|
||||
{
|
||||
public enum eCodecCallDirection
|
||||
{
|
||||
Unknown = 0, Incoming, Outgoing
|
||||
}
|
||||
|
||||
public class CodecCallDirection
|
||||
{
|
||||
/// <summary>
|
||||
/// Takes the Cisco call type and converts to the matching enum
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
public static eCodecCallDirection ConvertToDirectionEnum(string s)
|
||||
{
|
||||
switch (s.ToLower())
|
||||
{
|
||||
case "incoming":
|
||||
{
|
||||
return eCodecCallDirection.Incoming;
|
||||
}
|
||||
case "outgoing":
|
||||
{
|
||||
return eCodecCallDirection.Outgoing;
|
||||
}
|
||||
default:
|
||||
return eCodecCallDirection.Unknown;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
{
|
||||
public enum eCodecCallStatus
|
||||
{
|
||||
Unknown = 0,
|
||||
Connected,
|
||||
Connecting,
|
||||
Dialing,
|
||||
Disconnected,
|
||||
Disconnecting,
|
||||
EarlyMedia,
|
||||
Idle,
|
||||
OnHold,
|
||||
Ringing,
|
||||
Preserved,
|
||||
RemotePreserved,
|
||||
}
|
||||
|
||||
|
||||
public class CodecCallStatus
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Takes the Cisco call type and converts to the matching enum
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
public static eCodecCallStatus ConvertToStatusEnum(string s)
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case "Connected":
|
||||
{
|
||||
return eCodecCallStatus.Connected;
|
||||
}
|
||||
case "Connecting":
|
||||
{
|
||||
return eCodecCallStatus.Connecting;
|
||||
}
|
||||
case "Dialling":
|
||||
{
|
||||
return eCodecCallStatus.Dialing;
|
||||
}
|
||||
case "Disconnected":
|
||||
{
|
||||
return eCodecCallStatus.Disconnected;
|
||||
}
|
||||
case "Disconnecting":
|
||||
{
|
||||
return eCodecCallStatus.Disconnecting;
|
||||
}
|
||||
case "EarlyMedia":
|
||||
{
|
||||
return eCodecCallStatus.EarlyMedia;
|
||||
}
|
||||
case "Idle":
|
||||
{
|
||||
return eCodecCallStatus.Idle;
|
||||
}
|
||||
case "OnHold":
|
||||
{
|
||||
return eCodecCallStatus.OnHold;
|
||||
}
|
||||
case "Ringing":
|
||||
{
|
||||
return eCodecCallStatus.Ringing;
|
||||
}
|
||||
case "Preserved":
|
||||
{
|
||||
return eCodecCallStatus.Preserved;
|
||||
}
|
||||
case "RemotePreserved":
|
||||
{
|
||||
return eCodecCallStatus.RemotePreserved;
|
||||
}
|
||||
default:
|
||||
return eCodecCallStatus.Unknown;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
|
||||
{
|
||||
public enum eCodecCallType
|
||||
{
|
||||
Unknown = 0,
|
||||
Audio,
|
||||
Video,
|
||||
AudioCanEscalate,
|
||||
ForwardAllCall
|
||||
}
|
||||
|
||||
public class CodecCallType
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Takes the Cisco call type and converts to the matching enum
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
public static eCodecCallType ConvertToTypeEnum(string s)
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case "Audio":
|
||||
{
|
||||
return eCodecCallType.Audio;
|
||||
}
|
||||
case "Video":
|
||||
{
|
||||
return eCodecCallType.Video;
|
||||
}
|
||||
case "AudioCanEscalate":
|
||||
{
|
||||
return eCodecCallType.AudioCanEscalate;
|
||||
}
|
||||
case "ForwardAllCall":
|
||||
{
|
||||
return eCodecCallType.ForwardAllCall;
|
||||
}
|
||||
default:
|
||||
return eCodecCallType.Unknown;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
{
|
||||
public enum eMeetingPrivacy
|
||||
{
|
||||
Unknown = 0,
|
||||
Public,
|
||||
Private
|
||||
}
|
||||
|
||||
public class CodecCallPrivacy
|
||||
{
|
||||
/// <summary>
|
||||
/// Takes the Cisco privacy type and converts to the matching enum
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
public static eMeetingPrivacy ConvertToDirectionEnum(string s)
|
||||
{
|
||||
switch (s.ToLower())
|
||||
{
|
||||
case "public":
|
||||
{
|
||||
return eMeetingPrivacy.Public;
|
||||
}
|
||||
case "private":
|
||||
{
|
||||
return eMeetingPrivacy.Private;
|
||||
}
|
||||
default:
|
||||
return eMeetingPrivacy.Unknown;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines minimum volume controls for a codec device with dialing capabilities
|
||||
/// </summary>
|
||||
public interface ICodecAudio : IBasicVolumeWithFeedback, IPrivacy
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
{
|
||||
public interface IHasCallFavorites
|
||||
{
|
||||
CodecCallFavorites CallFavorites { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents favorites entries for a codec device
|
||||
/// </summary>
|
||||
public class CodecCallFavorites
|
||||
{
|
||||
public List<CodecActiveCallItem> Favorites { get; set; }
|
||||
|
||||
public CodecCallFavorites()
|
||||
{
|
||||
Favorites = new List<CodecActiveCallItem>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
{
|
||||
public interface IHasCallHistory
|
||||
{
|
||||
CodecCallHistory CallHistory { get; }
|
||||
|
||||
void RemoveCallHistoryEntry(CodecCallHistory.CallHistoryEntry entry);
|
||||
}
|
||||
|
||||
public enum eCodecOccurrenceType
|
||||
{
|
||||
Unknown = 0,
|
||||
Placed,
|
||||
Received,
|
||||
NoAnswer
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the recent call history for a codec device
|
||||
/// </summary>
|
||||
public class CodecCallHistory
|
||||
{
|
||||
public event EventHandler<EventArgs> RecentCallsListHasChanged;
|
||||
|
||||
public List<CallHistoryEntry> RecentCalls { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Item that gets added to the list when there are no recent calls in history
|
||||
/// </summary>
|
||||
CallHistoryEntry ListEmptyEntry;
|
||||
|
||||
public CodecCallHistory()
|
||||
{
|
||||
ListEmptyEntry = new CallHistoryEntry() { Name = "No Recent Calls" };
|
||||
|
||||
RecentCalls = new List<CallHistoryEntry>();
|
||||
|
||||
RecentCalls.Add(ListEmptyEntry);
|
||||
}
|
||||
|
||||
void OnRecentCallsListChange()
|
||||
{
|
||||
var handler = RecentCallsListHasChanged;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveEntry(CallHistoryEntry entry)
|
||||
{
|
||||
RecentCalls.Remove(entry);
|
||||
OnRecentCallsListChange();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generic call history entry, not device specific
|
||||
/// </summary>
|
||||
public class CallHistoryEntry : CodecActiveCallItem
|
||||
{
|
||||
[JsonConverter(typeof(IsoDateTimeConverter))]
|
||||
[JsonProperty("startTime")]
|
||||
public DateTime StartTime { get; set; }
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
[JsonProperty("occurrenceType")]
|
||||
public eCodecOccurrenceType OccurrenceType { get; set; }
|
||||
[JsonProperty("occurrenceHistoryId")]
|
||||
public string OccurrenceHistoryId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a list of call history entries returned by a Cisco codec to the generic list type
|
||||
/// </summary>
|
||||
/// <param name="entries"></param>
|
||||
/// <returns></returns>
|
||||
public void ConvertCiscoCallHistoryToGeneric(List<CiscoCallHistory.Entry> entries)
|
||||
{
|
||||
var genericEntries = new List<CallHistoryEntry>();
|
||||
|
||||
foreach (CiscoCallHistory.Entry entry in entries)
|
||||
{
|
||||
|
||||
genericEntries.Add(new CallHistoryEntry()
|
||||
{
|
||||
Name = entry.DisplayName.Value,
|
||||
Number = entry.CallbackNumber.Value,
|
||||
StartTime = entry.LastOccurrenceStartTime.Value,
|
||||
OccurrenceHistoryId = entry.LastOccurrenceHistoryId.Value,
|
||||
OccurrenceType = ConvertToOccurenceTypeEnum(entry.OccurrenceType.Value)
|
||||
});
|
||||
}
|
||||
|
||||
// Check if list is empty and if so, add an item to display No Recent Calls
|
||||
if(genericEntries.Count == 0)
|
||||
genericEntries.Add(ListEmptyEntry);
|
||||
|
||||
RecentCalls = genericEntries;
|
||||
OnRecentCallsListChange();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes the Cisco occurence type and converts it to the matching enum
|
||||
/// </summary>
|
||||
/// <param name="s"></para
|
||||
public eCodecOccurrenceType ConvertToOccurenceTypeEnum(string s)
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case "Placed":
|
||||
{
|
||||
return eCodecOccurrenceType.Placed;
|
||||
}
|
||||
case "Received":
|
||||
{
|
||||
return eCodecOccurrenceType.Received;
|
||||
}
|
||||
case "NoAnswer":
|
||||
{
|
||||
return eCodecOccurrenceType.NoAnswer;
|
||||
}
|
||||
default:
|
||||
return eCodecOccurrenceType.Unknown;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
{
|
||||
public interface IHasContentSharing
|
||||
{
|
||||
BoolFeedback SharingContentIsOnFeedback { get; }
|
||||
StringFeedback SharingSourceFeedback { get; }
|
||||
|
||||
bool AutoShareContentWhileInCall { get; }
|
||||
|
||||
void StartSharing();
|
||||
void StopSharing();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
{
|
||||
/// <summary>
|
||||
/// Requirements for a device that has dialing capabilities
|
||||
/// </summary>
|
||||
public interface IHasDialer
|
||||
{
|
||||
// Add requirements for Dialer functionality
|
||||
|
||||
event EventHandler<CodecCallStatusItemChangeEventArgs> CallStatusChange;
|
||||
|
||||
void Dial(string number);
|
||||
void EndCall(CodecActiveCallItem activeCall);
|
||||
void EndAllCalls();
|
||||
void AcceptCall(CodecActiveCallItem item);
|
||||
void RejectCall(CodecActiveCallItem item);
|
||||
void SendDtmf(string digit);
|
||||
|
||||
bool IsInCall { get; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the API for codecs with a directory
|
||||
/// </summary>
|
||||
public interface IHasDirectory
|
||||
{
|
||||
event EventHandler<DirectoryEventArgs> DirectoryResultReturned;
|
||||
|
||||
CodecDirectory DirectoryRoot { get; }
|
||||
|
||||
CodecDirectory CurrentDirectoryResult { get; }
|
||||
|
||||
CodecPhonebookSyncState PhonebookSyncState { get; }
|
||||
|
||||
void SearchDirectory(string searchString);
|
||||
|
||||
void GetDirectoryFolderContents(string folderId);
|
||||
|
||||
void SetCurrentDirectoryToRoot();
|
||||
|
||||
void GetDirectoryParentFolderContents();
|
||||
|
||||
BoolFeedback CurrentDirectoryResultIsNotDirectoryRoot { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Tracks the directory browse history when browsing beyond the root directory
|
||||
/// </summary>
|
||||
List<CodecDirectory> DirectoryBrowseHistory { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class DirectoryEventArgs : EventArgs
|
||||
{
|
||||
public CodecDirectory Directory { get; set; }
|
||||
public bool DirectoryIsOnRoot { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a codec directory
|
||||
/// </summary>
|
||||
public class CodecDirectory
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the contents of the directory
|
||||
/// </summary>
|
||||
[JsonProperty("directoryResults")]
|
||||
public List<DirectoryItem> CurrentDirectoryResults { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to store the ID of the current folder for CurrentDirectoryResults
|
||||
/// </summary>
|
||||
[JsonProperty("resultsFolderId")]
|
||||
public string ResultsFolderId { get; set; }
|
||||
|
||||
public CodecDirectory()
|
||||
{
|
||||
CurrentDirectoryResults = new List<DirectoryItem>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds folders to the directory
|
||||
/// </summary>
|
||||
/// <param name="folders"></param>
|
||||
public void AddFoldersToDirectory(List<DirectoryItem> folders)
|
||||
{
|
||||
if(folders != null)
|
||||
CurrentDirectoryResults.AddRange(folders);
|
||||
|
||||
SortDirectory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds contacts to the directory
|
||||
/// </summary>
|
||||
/// <param name="contacts"></param>
|
||||
public void AddContactsToDirectory(List<DirectoryItem> contacts)
|
||||
{
|
||||
if(contacts != null)
|
||||
CurrentDirectoryResults.AddRange(contacts);
|
||||
|
||||
SortDirectory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sorts the DirectoryResults list to display all folders alphabetically, then all contacts alphabetically
|
||||
/// </summary>
|
||||
private void SortDirectory()
|
||||
{
|
||||
var sortedFolders = new List<DirectoryItem>();
|
||||
|
||||
sortedFolders.AddRange(CurrentDirectoryResults.Where(f => f is DirectoryFolder));
|
||||
|
||||
sortedFolders.OrderBy(f => f.Name);
|
||||
|
||||
var sortedContacts = new List<DirectoryItem>();
|
||||
|
||||
sortedContacts.AddRange(CurrentDirectoryResults.Where(c => c is DirectoryContact));
|
||||
|
||||
sortedFolders.OrderBy(c => c.Name);
|
||||
|
||||
CurrentDirectoryResults.Clear();
|
||||
|
||||
CurrentDirectoryResults.AddRange(sortedFolders);
|
||||
|
||||
CurrentDirectoryResults.AddRange(sortedContacts);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to decorate a contact to indicate it can be invided to a meeting
|
||||
/// </summary>
|
||||
public interface IInvitableContact
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an item in the directory
|
||||
/// </summary>
|
||||
public class DirectoryItem : ICloneable
|
||||
{
|
||||
public object Clone()
|
||||
{
|
||||
return this.MemberwiseClone();
|
||||
}
|
||||
|
||||
[JsonProperty("folderId")]
|
||||
public string FolderId { get; set; }
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a folder type DirectoryItem
|
||||
/// </summary>
|
||||
public class DirectoryFolder : DirectoryItem
|
||||
{
|
||||
[JsonProperty("contacts")]
|
||||
public List<DirectoryContact> Contacts { get; set; }
|
||||
|
||||
[JsonProperty("parentFolderId")]
|
||||
public string ParentFolderId { get; set; }
|
||||
|
||||
public DirectoryFolder()
|
||||
{
|
||||
Contacts = new List<DirectoryContact>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a contact type DirectoryItem
|
||||
/// </summary>
|
||||
public class DirectoryContact : DirectoryItem
|
||||
{
|
||||
[JsonProperty("contactId")]
|
||||
public string ContactId { get; set; }
|
||||
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
|
||||
[JsonProperty("contactMethods")]
|
||||
public List<ContactMethod> ContactMethods { get; set; }
|
||||
|
||||
public DirectoryContact()
|
||||
{
|
||||
ContactMethods = new List<ContactMethod>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a method of contact for a contact
|
||||
/// </summary>
|
||||
public class ContactMethod
|
||||
{
|
||||
[JsonProperty("contactMethodId")]
|
||||
public string ContactMethodId { get; set; }
|
||||
|
||||
[JsonProperty("number")]
|
||||
public string Number { get; set; }
|
||||
|
||||
[JsonProperty("device")]
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public eContactMethodDevice Device { get; set; }
|
||||
|
||||
[JsonProperty("callType")]
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public eContactMethodCallType CallType { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public enum eContactMethodDevice
|
||||
{
|
||||
Unknown = 0,
|
||||
Mobile,
|
||||
Other,
|
||||
Telephone,
|
||||
Video
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public enum eContactMethodCallType
|
||||
{
|
||||
Unknown = 0,
|
||||
Audio,
|
||||
Video
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
{
|
||||
public enum eMeetingEventChangeType
|
||||
{
|
||||
Unkown = 0,
|
||||
MeetingStartWarning,
|
||||
MeetingStart,
|
||||
MeetingEndWarning,
|
||||
MeetingEnd
|
||||
}
|
||||
|
||||
public interface IHasScheduleAwareness
|
||||
{
|
||||
CodecScheduleAwareness CodecSchedule { get; }
|
||||
|
||||
void GetSchedule();
|
||||
}
|
||||
|
||||
public class CodecScheduleAwareness
|
||||
{
|
||||
List<Meeting> _Meetings;
|
||||
|
||||
public event EventHandler<MeetingEventArgs> MeetingEventChange;
|
||||
|
||||
public event EventHandler<EventArgs> MeetingsListHasChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Setter triggers MeetingsListHasChanged event
|
||||
/// </summary>
|
||||
public List<Meeting> Meetings
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Meetings;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Meetings = value;
|
||||
|
||||
var handler = MeetingsListHasChanged;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CTimer ScheduleChecker;
|
||||
|
||||
public CodecScheduleAwareness()
|
||||
{
|
||||
Meetings = new List<Meeting>();
|
||||
|
||||
ScheduleChecker = new CTimer(CheckSchedule, null, 1000, 1000);
|
||||
}
|
||||
|
||||
private void OnMeetingChange(eMeetingEventChangeType changeType, Meeting meeting)
|
||||
{
|
||||
var handler = MeetingEventChange;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting });
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckSchedule(object o)
|
||||
{
|
||||
// Iterate the meeting list and check if any meeting need to do anythingk
|
||||
|
||||
foreach (Meeting m in Meetings)
|
||||
{
|
||||
eMeetingEventChangeType changeType = eMeetingEventChangeType.Unkown;
|
||||
|
||||
if (m.TimeToMeetingStart.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes) // Meeting is about to start
|
||||
changeType = eMeetingEventChangeType.MeetingStartWarning;
|
||||
else if (m.TimeToMeetingStart.TotalMinutes == 0) // Meeting Start
|
||||
changeType = eMeetingEventChangeType.MeetingStart;
|
||||
else if (m.TimeToMeetingEnd.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes) // Meeting is about to end
|
||||
changeType = eMeetingEventChangeType.MeetingEndWarning;
|
||||
else if (m.TimeToMeetingEnd.TotalMinutes == 0) // Meeting has ended
|
||||
changeType = eMeetingEventChangeType.MeetingEnd;
|
||||
|
||||
if (changeType != eMeetingEventChangeType.Unkown)
|
||||
OnMeetingChange(changeType, m);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generic class to represent a meeting (Cisco or Polycom OBTP or Fusion)
|
||||
/// </summary>
|
||||
public class Meeting
|
||||
{
|
||||
public TimeSpan MeetingWarningMinutes = TimeSpan.FromMinutes(5);
|
||||
|
||||
public string Id { get; set; }
|
||||
public string Organizer { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Agenda { get; set; }
|
||||
public TimeSpan TimeToMeetingStart
|
||||
{
|
||||
get
|
||||
{
|
||||
return StartTime - DateTime.Now;
|
||||
}
|
||||
}
|
||||
public TimeSpan TimeToMeetingEnd
|
||||
{
|
||||
get
|
||||
{
|
||||
return EndTime - DateTime.Now;
|
||||
}
|
||||
}
|
||||
public DateTime StartTime { get; set; }
|
||||
public DateTime EndTime { get; set; }
|
||||
public TimeSpan Duration
|
||||
{
|
||||
get
|
||||
{
|
||||
return EndTime - StartTime;
|
||||
}
|
||||
}
|
||||
public eMeetingPrivacy Privacy { get; set; }
|
||||
public bool Joinable
|
||||
{
|
||||
get
|
||||
{
|
||||
return StartTime.AddMinutes(-5) <= DateTime.Now
|
||||
&& DateTime.Now <= EndTime; //.AddMinutes(-5);
|
||||
}
|
||||
}
|
||||
//public string ConferenceNumberToDial { get; set; }
|
||||
public string ConferencePassword { get; set; }
|
||||
public bool IsOneButtonToPushMeeting { get; set; }
|
||||
|
||||
public List<Call> Calls { get; private set; }
|
||||
|
||||
public Meeting()
|
||||
{
|
||||
Calls = new List<Call>();
|
||||
}
|
||||
}
|
||||
|
||||
public class Call
|
||||
{
|
||||
public string Number { get; set; }
|
||||
public string Protocol { get; set; }
|
||||
public string CallRate { get; set; }
|
||||
public string CallType { get; set; }
|
||||
}
|
||||
|
||||
public class MeetingEventArgs : EventArgs
|
||||
{
|
||||
public eMeetingEventChangeType ChangeType { get; set; }
|
||||
public Meeting Meeting { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.Gateways;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
public class CenRfgwController : CrestronGenericBaseDevice
|
||||
{
|
||||
public GatewayBase Gateway { get { return Hardware as GatewayBase; } }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for the on-board gateway
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
public CenRfgwController(string key, string name, GatewayBase gateway) :
|
||||
base(key, name, gateway)
|
||||
{
|
||||
}
|
||||
|
||||
public static CenRfgwController GetNewExGatewayController(string key, string name, string id, string gatewayType)
|
||||
{
|
||||
uint uid;
|
||||
eExGatewayType type;
|
||||
try
|
||||
{
|
||||
uid = Convert.ToUInt32(id, 16);
|
||||
type = (eExGatewayType)Enum.Parse(typeof(eExGatewayType), gatewayType, true);
|
||||
var cs = Global.ControlSystem;
|
||||
|
||||
GatewayBase gw = null;
|
||||
switch (type)
|
||||
{
|
||||
case eExGatewayType.Ethernet:
|
||||
gw = new CenRfgwEx(uid, cs);
|
||||
break;
|
||||
case eExGatewayType.EthernetShared:
|
||||
gw = new CenRfgwExEthernetSharable(uid, cs);
|
||||
break;
|
||||
case eExGatewayType.Cresnet:
|
||||
gw = new CenRfgwExCresnet(uid, cs);
|
||||
break;
|
||||
}
|
||||
return new CenRfgwController(key, name, gw);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Debug.Console(0, "ERROR: Cannot create EX Gateway, id {0}, type {1}", id, gatewayType);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static CenRfgwController GetNewErGatewayController(string key, string name, string id, string gatewayType)
|
||||
{
|
||||
uint uid;
|
||||
eExGatewayType type;
|
||||
try
|
||||
{
|
||||
uid = Convert.ToUInt32(id, 16);
|
||||
type = (eExGatewayType)Enum.Parse(typeof(eExGatewayType), gatewayType, true);
|
||||
var cs = Global.ControlSystem;
|
||||
|
||||
GatewayBase gw = null;
|
||||
switch (type)
|
||||
{
|
||||
case eExGatewayType.Ethernet:
|
||||
gw = new CenErfgwPoe(uid, cs);
|
||||
break;
|
||||
case eExGatewayType.EthernetShared:
|
||||
gw = new CenErfgwPoeEthernetSharable(uid, cs);
|
||||
break;
|
||||
case eExGatewayType.Cresnet:
|
||||
gw = new CenErfgwPoeCresnet(uid, cs);
|
||||
break;
|
||||
}
|
||||
return new CenRfgwController(key, name, gw);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Debug.Console(0, "ERROR: Cannot create EX Gateway, id {0}, type {1}", id, gatewayType);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the actual Crestron EX gateway for a given key. "processor" or the key of
|
||||
/// a CenRfgwExController in DeviceManager
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns>Either processor GW or Gateway property of CenRfgwExController</returns>
|
||||
public static GatewayBase GetExGatewayBaseForKey(string key)
|
||||
{
|
||||
key = key.ToLower();
|
||||
if (key == "processor" && Global.ControlSystem.SupportsInternalRFGateway)
|
||||
return Global.ControlSystem.ControllerRFGatewayDevice;
|
||||
var gwCont = DeviceManager.GetDeviceForKey(key) as CenRfgwController;
|
||||
if (gwCont != null)
|
||||
return gwCont.Gateway;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public enum eExGatewayType
|
||||
{
|
||||
Ethernet, EthernetShared, Cresnet
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,376 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
|
||||
// QUESTIONS:
|
||||
//
|
||||
// When subscribing, just use the Instance ID for Custom Name?
|
||||
|
||||
// Verbose on subscriptions?
|
||||
|
||||
// Example subscription feedback responses
|
||||
// ! "publishToken":"name" "value":-77.0
|
||||
// ! "myLevelName" -77
|
||||
|
||||
public class BiampTesiraForteDsp : DspBase
|
||||
{
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
public CommunicationGather PortGather { get; private set; }
|
||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||
|
||||
new public Dictionary<string, TesiraForteLevelControl> LevelControlPoints { get; private set; }
|
||||
|
||||
public bool isSubscribed;
|
||||
|
||||
private CTimer SubscriptionTimer;
|
||||
|
||||
CrestronQueue CommandQueue;
|
||||
|
||||
bool CommandQueueInProgress = false;
|
||||
|
||||
//new public Dictionary<string, DspControlPoint> DialerControlPoints { get; private set; }
|
||||
|
||||
//new public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Shows received lines as hex
|
||||
/// </summary>
|
||||
public bool ShowHexResponse { get; set; }
|
||||
|
||||
public BiampTesiraForteDsp(string key, string name, IBasicCommunication comm, BiampTesiraFortePropertiesConfig props) :
|
||||
base(key, name)
|
||||
{
|
||||
CommandQueue = new CrestronQueue(100);
|
||||
|
||||
Communication = comm;
|
||||
var socket = comm as ISocketStatus;
|
||||
if (socket != null)
|
||||
{
|
||||
// This instance uses IP control
|
||||
|
||||
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This instance uses RS-232 control
|
||||
}
|
||||
PortGather = new CommunicationGather(Communication, "\x0d\x0a");
|
||||
PortGather.LineReceived += this.Port_LineReceived;
|
||||
if (props.CommunicationMonitorProperties != null)
|
||||
{
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
//#warning Need to deal with this poll string
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 120000, 120000, 300000, "SESSION get aliases\x0d\x0a");
|
||||
}
|
||||
|
||||
LevelControlPoints = new Dictionary<string, TesiraForteLevelControl>();
|
||||
|
||||
foreach (KeyValuePair<string, BiampTesiraForteLevelControlBlockConfig> block in props.LevelControlBlocks)
|
||||
{
|
||||
this.LevelControlPoints.Add(block.Key, new TesiraForteLevelControl(block.Key, block.Value, this));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
Communication.Connect();
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
CommunicationMonitor.Start();
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(SendLine, "send" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
return true;
|
||||
}
|
||||
|
||||
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
||||
{
|
||||
Debug.Console(2, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
|
||||
|
||||
if (e.Client.IsConnected)
|
||||
{
|
||||
// Tasks on connect
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cleanup items from this session
|
||||
|
||||
if (SubscriptionTimer != null)
|
||||
{
|
||||
SubscriptionTimer.Stop();
|
||||
SubscriptionTimer = null;
|
||||
}
|
||||
|
||||
isSubscribed = false;
|
||||
CommandQueue.Clear();
|
||||
CommandQueueInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initiates the subscription process to the DSP
|
||||
/// </summary>
|
||||
void SubscribeToAttributes()
|
||||
{
|
||||
SendLine("SESSION set verbose true");
|
||||
|
||||
foreach (KeyValuePair<string, TesiraForteLevelControl> level in LevelControlPoints)
|
||||
{
|
||||
level.Value.Subscribe();
|
||||
}
|
||||
|
||||
if (!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
|
||||
ResetSubscriptionTimer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets or Sets the subscription timer
|
||||
/// </summary>
|
||||
void ResetSubscriptionTimer()
|
||||
{
|
||||
isSubscribed = true;
|
||||
|
||||
if (SubscriptionTimer != null)
|
||||
{
|
||||
SubscriptionTimer = new CTimer(o => SubscribeToAttributes(), 30000);
|
||||
SubscriptionTimer.Reset();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles a response message from the DSP
|
||||
/// </summary>
|
||||
/// <param name="dev"></param>
|
||||
/// <param name="args"></param>
|
||||
void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "RX: '{0}'",
|
||||
ShowHexResponse ? ComTextHelper.GetEscapedText(args.Text) : args.Text);
|
||||
|
||||
Debug.Console(1, this, "RX: '{0}'", args.Text);
|
||||
|
||||
try
|
||||
{
|
||||
if (args.Text.IndexOf("Welcome to the Tesira Text Protocol Server...") > -1)
|
||||
{
|
||||
// Indicates a new TTP session
|
||||
|
||||
SubscribeToAttributes();
|
||||
}
|
||||
else if (args.Text.IndexOf("publishToken") > -1)
|
||||
{
|
||||
// response is from a subscribed attribute
|
||||
|
||||
string pattern = "! \"publishToken\":[\"](.*)[\"] \"value\":(.*)";
|
||||
|
||||
Match match = Regex.Match(args.Text, pattern);
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
|
||||
string key;
|
||||
|
||||
string customName;
|
||||
|
||||
string value;
|
||||
|
||||
customName = match.Groups[1].Value;
|
||||
|
||||
// Finds the key (everything before the '~' character
|
||||
key = customName.Substring(0, customName.IndexOf("~", 0) - 1);
|
||||
|
||||
value = match.Groups[2].Value;
|
||||
|
||||
foreach (KeyValuePair<string, TesiraForteLevelControl> controlPoint in LevelControlPoints)
|
||||
{
|
||||
if (customName == controlPoint.Value.LevelCustomName || customName == controlPoint.Value.MuteCustomName)
|
||||
{
|
||||
controlPoint.Value.ParseSubscriptionMessage(customName, value);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// same for dialers
|
||||
/// same for switchers
|
||||
|
||||
}
|
||||
else if (args.Text.IndexOf("+OK") > -1)
|
||||
{
|
||||
if (args.Text == "+OK" || args.Text.IndexOf("list\":") > -1 ) // Check for a simple "+OK" only 'ack' repsonse or a list response and ignore
|
||||
return;
|
||||
|
||||
// response is not from a subscribed attribute. From a get/set/toggle/increment/decrement command
|
||||
|
||||
if (!CommandQueue.IsEmpty)
|
||||
{
|
||||
if (CommandQueue.Peek() is QueuedCommand)
|
||||
{
|
||||
// Expected response belongs to a child class
|
||||
QueuedCommand tempCommand = (QueuedCommand)CommandQueue.TryToDequeue();
|
||||
//Debug.Console(1, this, "Command Dequeued. CommandQueue Size: {0}", CommandQueue.Count);
|
||||
|
||||
tempCommand.ControlPoint.ParseGetMessage(tempCommand.AttributeCode, args.Text);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Expected response belongs to this class
|
||||
string temp = (string)CommandQueue.TryToDequeue();
|
||||
//Debug.Console(1, this, "Command Dequeued. CommandQueue Size: {0}", CommandQueue.Count);
|
||||
|
||||
}
|
||||
|
||||
if (CommandQueue.IsEmpty)
|
||||
CommandQueueInProgress = false;
|
||||
else
|
||||
SendNextQueuedCommand();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if (args.Text.IndexOf("-ERR") > -1)
|
||||
{
|
||||
// Error response
|
||||
|
||||
switch (args.Text)
|
||||
{
|
||||
case "-ERR ALREADY_SUBSCRIBED":
|
||||
{
|
||||
ResetSubscriptionTimer();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Debug.Console(0, this, "Error From DSP: '{0}'", args.Text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "Error parsing response: '{0}'\n{1}", args.Text, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command to the DSP (with delimiter appended)
|
||||
/// </summary>
|
||||
/// <param name="s">Command to send</param>
|
||||
public void SendLine(string s)
|
||||
{
|
||||
Debug.Console(1, this, "TX: '{0}'", s);
|
||||
Communication.SendText(s + "\x0a");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a command from a child module to the queue
|
||||
/// </summary>
|
||||
/// <param name="command">Command object from child module</param>
|
||||
public void EnqueueCommand(QueuedCommand commandToEnqueue)
|
||||
{
|
||||
CommandQueue.Enqueue(commandToEnqueue);
|
||||
//Debug.Console(1, this, "Command (QueuedCommand) Enqueued '{0}'. CommandQueue has '{1}' Elements.", commandToEnqueue.Command, CommandQueue.Count);
|
||||
|
||||
if(!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a raw string command to the queue
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
public void EnqueueCommand(string command)
|
||||
{
|
||||
CommandQueue.Enqueue(command);
|
||||
//Debug.Console(1, this, "Command (string) Enqueued '{0}'. CommandQueue has '{1}' Elements.", command, CommandQueue.Count);
|
||||
|
||||
if (!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the next queued command to the DSP
|
||||
/// </summary>
|
||||
void SendNextQueuedCommand()
|
||||
{
|
||||
//Debug.Console(2, this, "Attempting to send next queued command. CommandQueueInProgress: {0} Communication isConnected: {1}", CommandQueueInProgress, Communication.IsConnected);
|
||||
|
||||
//if (CommandQueue.IsEmpty)
|
||||
// CommandQueueInProgress = false;
|
||||
|
||||
//Debug.Console(1, this, "CommandQueue has {0} Elements:\n", CommandQueue.Count);
|
||||
|
||||
//foreach (object o in CommandQueue)
|
||||
//{
|
||||
// if (o is string)
|
||||
// Debug.Console(1, this, "{0}", o);
|
||||
// else if(o is QueuedCommand)
|
||||
// {
|
||||
// var item = (QueuedCommand)o;
|
||||
// Debug.Console(1, this, "{0}", item.Command);
|
||||
// }
|
||||
//}
|
||||
|
||||
//Debug.Console(1, this, "End of CommandQueue");
|
||||
|
||||
if (Communication.IsConnected && !CommandQueue.IsEmpty)
|
||||
{
|
||||
CommandQueueInProgress = true;
|
||||
|
||||
if (CommandQueue.Peek() is QueuedCommand)
|
||||
{
|
||||
QueuedCommand nextCommand = new QueuedCommand();
|
||||
|
||||
nextCommand = (QueuedCommand)CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand.Command);
|
||||
}
|
||||
else
|
||||
{
|
||||
string nextCommand = (string)CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command to execute a preset
|
||||
/// </summary>
|
||||
/// <param name="name">Preset Name</param>
|
||||
public override void RunPreset(string name)
|
||||
{
|
||||
SendLine(string.Format("DEVICE recallPreset {0}", name));
|
||||
}
|
||||
|
||||
public class QueuedCommand
|
||||
{
|
||||
public string Command { get; set; }
|
||||
public string AttributeCode { get; set; }
|
||||
public TesiraForteControlPoint ControlPoint { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
public class TesiraForteLevelControl : TesiraForteControlPoint, IBiampTesiraDspLevelControl, IKeyed
|
||||
{
|
||||
bool _IsMuted;
|
||||
ushort _VolumeLevel;
|
||||
|
||||
public BoolFeedback MuteFeedback { get; private set; }
|
||||
|
||||
public IntFeedback VolumeLevelFeedback { get; private set; }
|
||||
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
public string ControlPointTag { get { return base.InstanceTag; } }
|
||||
|
||||
/// <summary>
|
||||
/// Used for to identify level subscription values
|
||||
/// </summary>
|
||||
public string LevelCustomName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used for to identify mute subscription values
|
||||
/// </summary>
|
||||
public string MuteCustomName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Minimum fader level
|
||||
/// </summary>
|
||||
double MinLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum fader level
|
||||
/// </summary>
|
||||
double MaxLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a valid subscription string has been recieved for all subscriptions
|
||||
/// </summary>
|
||||
public bool IsSubsribed
|
||||
{
|
||||
get
|
||||
{
|
||||
bool isSubscribed = false;
|
||||
|
||||
if (HasMute && MuteIsSubscribed)
|
||||
isSubscribed = true;
|
||||
|
||||
if (HasLevel && LevelIsSubscribed)
|
||||
isSubscribed = true;
|
||||
|
||||
return isSubscribed;
|
||||
}
|
||||
}
|
||||
|
||||
public bool AutomaticUnmuteOnVolumeUp { get; private set; }
|
||||
|
||||
public bool HasMute { get; private set; }
|
||||
|
||||
public bool HasLevel { get; private set; }
|
||||
|
||||
bool MuteIsSubscribed;
|
||||
|
||||
bool LevelIsSubscribed;
|
||||
|
||||
//public TesiraForteLevelControl(string label, string id, int index1, int index2, bool hasMute, bool hasLevel, BiampTesiraForteDsp parent)
|
||||
// : base(id, index1, index2, parent)
|
||||
//{
|
||||
// Initialize(label, hasMute, hasLevel);
|
||||
//}
|
||||
|
||||
public TesiraForteLevelControl(string key, BiampTesiraForteLevelControlBlockConfig config, BiampTesiraForteDsp parent)
|
||||
: base(config.InstanceTag, config.Index1, config.Index2, parent)
|
||||
{
|
||||
Initialize(key, config.Label, config.HasMute, config.HasLevel);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this attribute based on config values and generates subscriptions commands and adds commands to the parent's queue.
|
||||
/// </summary>
|
||||
public void Initialize(string key, string label, bool hasMute, bool hasLevel)
|
||||
{
|
||||
Key = string.Format("{0}--{1}", Parent.Key, key);
|
||||
|
||||
DeviceManager.AddDevice(this);
|
||||
|
||||
Debug.Console(2, this, "Adding LevelControl '{0}'", Key);
|
||||
|
||||
this.IsSubscribed = false;
|
||||
|
||||
MuteFeedback = new BoolFeedback(() => _IsMuted);
|
||||
|
||||
VolumeLevelFeedback = new IntFeedback(() => _VolumeLevel);
|
||||
|
||||
HasMute = hasMute;
|
||||
HasLevel = hasLevel;
|
||||
}
|
||||
|
||||
public void Subscribe()
|
||||
{
|
||||
// Do subscriptions and blah blah
|
||||
|
||||
// Subscribe to mute
|
||||
if (this.HasMute)
|
||||
{
|
||||
MuteCustomName = string.Format("{0}~mute{1}", this.InstanceTag, this.Index1);
|
||||
|
||||
SendSubscriptionCommand(MuteCustomName, "mute", 500);
|
||||
}
|
||||
|
||||
// Subscribe to level
|
||||
if (this.HasLevel)
|
||||
{
|
||||
LevelCustomName = string.Format("{0}~level{1}", this.InstanceTag, this.Index1);
|
||||
|
||||
SendSubscriptionCommand(LevelCustomName, "level", 250);
|
||||
|
||||
SendFullCommand("get", "minLevel", null);
|
||||
|
||||
SendFullCommand("get", "maxLevel", null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Parses the response from the DspBase
|
||||
/// </summary>
|
||||
/// <param name="customName"></param>
|
||||
/// <param name="value"></param>
|
||||
public void ParseSubscriptionMessage(string customName, string value)
|
||||
{
|
||||
|
||||
// Check for valid subscription response
|
||||
|
||||
if (this.HasMute && customName == MuteCustomName)
|
||||
{
|
||||
//if (value.IndexOf("+OK") > -1)
|
||||
//{
|
||||
// int pointer = value.IndexOf(" +OK");
|
||||
|
||||
// MuteIsSubscribed = true;
|
||||
|
||||
// // Removes the +OK
|
||||
// value = value.Substring(0, value.Length - (value.Length - (pointer - 1)));
|
||||
//}
|
||||
|
||||
if (value.IndexOf("true") > -1)
|
||||
{
|
||||
_IsMuted = true;
|
||||
MuteIsSubscribed = true;
|
||||
|
||||
}
|
||||
else if (value.IndexOf("false") > -1)
|
||||
{
|
||||
_IsMuted = false;
|
||||
MuteIsSubscribed = true;
|
||||
}
|
||||
|
||||
MuteFeedback.FireUpdate();
|
||||
}
|
||||
else if (this.HasLevel && customName == LevelCustomName)
|
||||
{
|
||||
//if (value.IndexOf("+OK") > -1)
|
||||
//{
|
||||
// int pointer = value.IndexOf(" +OK");
|
||||
|
||||
// LevelIsSubscribed = true;
|
||||
|
||||
//}
|
||||
|
||||
var _value = Double.Parse(value);
|
||||
|
||||
_VolumeLevel = (ushort)Scale(_value, MinLevel, MaxLevel, 0, 65535);
|
||||
|
||||
LevelIsSubscribed = true;
|
||||
|
||||
VolumeLevelFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a non subscription response
|
||||
/// </summary>
|
||||
/// <param name="attributeCode">The attribute code of the command</param>
|
||||
/// <param name="message">The message to parse</param>
|
||||
public override void ParseGetMessage(string attributeCode, string message)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parse an "+OK" message
|
||||
string pattern = @"\+OK ""value"":(.*)";
|
||||
|
||||
Match match = Regex.Match(message, pattern);
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
|
||||
string value = match.Groups[1].Value;
|
||||
|
||||
Debug.Console(1, this, "Response: '{0}' Value: '{1}'", attributeCode, value);
|
||||
|
||||
if (message.IndexOf("\"value\":") > -1)
|
||||
{
|
||||
switch (attributeCode)
|
||||
{
|
||||
case "minLevel":
|
||||
{
|
||||
MinLevel = Double.Parse(value);
|
||||
|
||||
Debug.Console(1, this, "MinLevel is '{0}'", MinLevel);
|
||||
|
||||
break;
|
||||
}
|
||||
case "maxLevel":
|
||||
{
|
||||
MaxLevel = Double.Parse(value);
|
||||
|
||||
Debug.Console(1, this, "MaxLevel is '{0}'", MaxLevel);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Debug.Console(2, "Response does not match expected attribute codes: '{0}'", message);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(2, "Unable to parse message: '{0}'\n{1}", message, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turns the mute off
|
||||
/// </summary>
|
||||
public void MuteOff()
|
||||
{
|
||||
SendFullCommand("set", "mute", "false");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turns the mute on
|
||||
/// </summary>
|
||||
public void MuteOn()
|
||||
{
|
||||
SendFullCommand("set", "mute", "true");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the volume to a specified level
|
||||
/// </summary>
|
||||
/// <param name="level"></param>
|
||||
public void SetVolume(ushort level)
|
||||
{
|
||||
Debug.Console(1, this, "volume: {0}", level);
|
||||
// Unmute volume if new level is higher than existing
|
||||
if (level > _VolumeLevel && AutomaticUnmuteOnVolumeUp)
|
||||
if(_IsMuted)
|
||||
MuteOff();
|
||||
|
||||
double volumeLevel = Scale(level, 0, 65535, MinLevel, MaxLevel);
|
||||
|
||||
SendFullCommand("set", "level", string.Format("{0:0.000000}", volumeLevel));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles mute status
|
||||
/// </summary>
|
||||
public void MuteToggle()
|
||||
{
|
||||
SendFullCommand("toggle", "mute", "");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrements volume level
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void VolumeDown(bool pressRelease)
|
||||
{
|
||||
SendFullCommand("decrement", "level", "");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increments volume level
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void VolumeUp(bool pressRelease)
|
||||
{
|
||||
SendFullCommand("increment", "level", "");
|
||||
|
||||
if (AutomaticUnmuteOnVolumeUp)
|
||||
if (!_IsMuted)
|
||||
MuteOff();
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// Scales the input from the input range to the output range
|
||||
///// </summary>
|
||||
///// <param name="input"></param>
|
||||
///// <param name="inMin"></param>
|
||||
///// <param name="inMax"></param>
|
||||
///// <param name="outMin"></param>
|
||||
///// <param name="outMax"></param>
|
||||
///// <returns></returns>
|
||||
//int Scale(int input, int inMin, int inMax, int outMin, int outMax)
|
||||
//{
|
||||
// Debug.Console(1, this, "Scaling (int) input '{0}' with min '{1}'/max '{2}' to output range min '{3}'/max '{4}'", input, inMin, inMax, outMin, outMax);
|
||||
|
||||
// int inputRange = inMax - inMin;
|
||||
|
||||
// int outputRange = outMax - outMin;
|
||||
|
||||
// var output = (((input-inMin) * outputRange) / inputRange ) - outMin;
|
||||
|
||||
// Debug.Console(1, this, "Scaled output '{0}'", output);
|
||||
|
||||
// return output;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the input from the input range to the output range
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <param name="inMin"></param>
|
||||
/// <param name="inMax"></param>
|
||||
/// <param name="outMin"></param>
|
||||
/// <param name="outMax"></param>
|
||||
/// <returns></returns>
|
||||
double Scale(double input, double inMin, double inMax, double outMin, double outMax)
|
||||
{
|
||||
Debug.Console(1, this, "Scaling (double) input '{0}' with min '{1}'/max '{2}' to output range min '{3}'/max '{4}'",input ,inMin ,inMax ,outMin, outMax);
|
||||
|
||||
double inputRange = inMax - inMin;
|
||||
|
||||
if (inputRange <= 0)
|
||||
{
|
||||
throw new ArithmeticException(string.Format("Invalid Input Range '{0}' for Scaling. Min '{1}' Max '{2}'.", inputRange, inMin, inMax));
|
||||
}
|
||||
|
||||
double outputRange = outMax - outMin;
|
||||
|
||||
var output = (((input - inMin) * outputRange) / inputRange) + outMin;
|
||||
|
||||
Debug.Console(1, this, "Scaled output '{0}'", output);
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class BiampTesiraFortePropertiesConfig
|
||||
{
|
||||
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
||||
|
||||
public ControlPropertiesConfig Control { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// These are key-value pairs, string id, string type.
|
||||
/// Valid types are level and mute.
|
||||
/// Need to include the index values somehow
|
||||
/// </summary>
|
||||
public Dictionary<string, BiampTesiraForteLevelControlBlockConfig> LevelControlBlocks { get; set; }
|
||||
// public Dictionary<string, BiampTesiraForteDialerControlBlockConfig> DialerControlBlocks {get; set;}
|
||||
}
|
||||
|
||||
public class BiampTesiraForteLevelControlBlockConfig
|
||||
{
|
||||
public bool Enabled { get; set; }
|
||||
public string Label { get; set; }
|
||||
public string InstanceTag { get; set; }
|
||||
public int Index1 { get; set; }
|
||||
public int Index2 { get; set; }
|
||||
public bool HasMute { get; set; }
|
||||
public bool HasLevel { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
public abstract class TesiraForteControlPoint : DspControlPoint
|
||||
{
|
||||
public string Key { get; protected set; }
|
||||
|
||||
public string InstanceTag { get; set; }
|
||||
public int Index1 { get; private set; }
|
||||
public int Index2 { get; private set; }
|
||||
public BiampTesiraForteDsp Parent { get; private set; }
|
||||
|
||||
public bool IsSubscribed { get; protected set; }
|
||||
|
||||
protected TesiraForteControlPoint(string id, int index1, int index2, BiampTesiraForteDsp parent)
|
||||
{
|
||||
InstanceTag = id;
|
||||
Index1 = index1;
|
||||
Index2 = index2;
|
||||
Parent = parent;
|
||||
}
|
||||
|
||||
virtual public void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command to the DSP
|
||||
/// </summary>
|
||||
/// <param name="command">command</param>
|
||||
/// <param name="attribute">attribute code</param>
|
||||
/// <param name="value">value (use "" if not applicable)</param>
|
||||
public virtual void SendFullCommand(string command, string attributeCode, string value)
|
||||
{
|
||||
// Command Format: InstanceTag get/set/toggle/increment/decrement/subscribe/unsubscribe attributeCode [index] [value]
|
||||
// Ex: "RoomLevel set level 1.00"
|
||||
|
||||
string cmd;
|
||||
|
||||
if (attributeCode == "level" || attributeCode == "mute" || attributeCode == "minLevel" || attributeCode == "maxLevel" || attributeCode == "label" || attributeCode == "rampInterval" || attributeCode == "rampStep")
|
||||
{
|
||||
//Command requires Index
|
||||
|
||||
if (String.IsNullOrEmpty(value))
|
||||
{
|
||||
// format command without value
|
||||
cmd = string.Format("{0} {1} {2} {3}", InstanceTag, command, attributeCode, Index1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// format commadn with value
|
||||
cmd = string.Format("{0} {1} {2} {3} {4}", InstanceTag, command, attributeCode, Index1, value);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//Command does not require Index
|
||||
|
||||
if (String.IsNullOrEmpty(value))
|
||||
{
|
||||
cmd = string.Format("{0} {1} {2} {3}", InstanceTag, command, attributeCode, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd = string.Format("{0} {1} {2}", InstanceTag, command, attributeCode);
|
||||
}
|
||||
}
|
||||
|
||||
if (command == "get")
|
||||
{
|
||||
// This command will generate a return value response so it needs to be queued
|
||||
Parent.EnqueueCommand(new BiampTesiraForteDsp.QueuedCommand{ Command = cmd, AttributeCode = attributeCode, ControlPoint = this });
|
||||
}
|
||||
else
|
||||
{
|
||||
// This command will generate a simple "+OK" response and doesn't need to be queued
|
||||
Parent.SendLine(cmd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual public void ParseGetMessage(string attributeCode, string message)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
public virtual void SendSubscriptionCommand(string customName, string attributeCode, int responseRate)
|
||||
{
|
||||
// Subscription string format: InstanceTag subscribe attributeCode Index1 customName responseRate
|
||||
// Ex: "RoomLevel subscribe level 1 MyRoomLevel 500"
|
||||
|
||||
string cmd;
|
||||
|
||||
if (responseRate > 0)
|
||||
{
|
||||
cmd = string.Format("{0} subscribe {1} {2} {3} {4}", InstanceTag, attributeCode, Index1, customName, responseRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd = string.Format("{0} subscribe {1} {2} {3}", InstanceTag, attributeCode, Index1, customName);
|
||||
}
|
||||
|
||||
Parent.SendLine(cmd);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
|
||||
//QUESTIONS:
|
||||
|
||||
//When subscribing, just use the Instance ID for Custom Name?
|
||||
|
||||
//Verbose on subscriptions?
|
||||
|
||||
//! "publishToken":"name" "value":-77.0
|
||||
//! "myLevelName" -77
|
||||
|
||||
//public class TesiraForteMuteControl : IDspLevelControl
|
||||
//{
|
||||
// BiampTesiraForteDsp Parent;
|
||||
// bool _IsMuted;
|
||||
// ushort _VolumeLevel;
|
||||
|
||||
// public TesiraForteMuteControl(string id, BiampTesiraForteDsp parent)
|
||||
// : base(id)
|
||||
// {
|
||||
// Parent = parent;
|
||||
// }
|
||||
|
||||
// public void Initialize()
|
||||
// {
|
||||
|
||||
// }
|
||||
|
||||
// protected override Func<bool> MuteFeedbackFunc
|
||||
// {
|
||||
// get { return () => _IsMuted; }
|
||||
// }
|
||||
|
||||
// protected override Func<int> VolumeLevelFeedbackFunc
|
||||
// {
|
||||
// get { return () => _VolumeLevel; }
|
||||
// }
|
||||
|
||||
// public override void MuteOff()
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
|
||||
// public override void MuteOn()
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
|
||||
// public override void SetVolume(ushort level)
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
|
||||
// public override void MuteToggle()
|
||||
// {
|
||||
// }
|
||||
|
||||
// public override void VolumeDown(bool pressRelease)
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
|
||||
// public override void VolumeUp(bool pressRelease)
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
public abstract class DspBase : Device
|
||||
{
|
||||
public Dictionary<string, DspControlPoint> LevelControlPoints { get; private set; }
|
||||
|
||||
public Dictionary<string, DspControlPoint> DialerControlPoints { get; private set; }
|
||||
|
||||
public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
|
||||
|
||||
public abstract void RunPreset(string name);
|
||||
|
||||
public DspBase(string key, string name) :
|
||||
base(key, name) { }
|
||||
|
||||
|
||||
// in audio call feedback
|
||||
|
||||
// VOIP
|
||||
// Phone dialer
|
||||
}
|
||||
|
||||
// Fusion
|
||||
// Privacy state
|
||||
// Online state
|
||||
// level/mutes ?
|
||||
|
||||
// AC Log call stats
|
||||
|
||||
// Typical presets:
|
||||
// call default preset to restore levels and mutes
|
||||
|
||||
public abstract class DspControlPoint
|
||||
{
|
||||
string Key { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class DspDialerBase
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Main program
|
||||
// VTC
|
||||
// ATC
|
||||
// Mics, unusual
|
||||
|
||||
public interface IBiampTesiraDspLevelControl : IBasicVolumeWithFeedback
|
||||
{
|
||||
/// <summary>
|
||||
/// In BiAmp: Instance Tag, QSC: Named Control, Polycom:
|
||||
/// </summary>
|
||||
string ControlPointTag { get; }
|
||||
#warning I dont think index1 and index2 should be a part of the interface. JTA 2018-07-17
|
||||
int Index1 { get; }
|
||||
int Index2 { get; }
|
||||
bool HasMute { get; }
|
||||
bool HasLevel { get; }
|
||||
bool AutomaticUnmuteOnVolumeUp { get; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
public class SoundStructureBasics
|
||||
{
|
||||
// public Dictionary<string, IBiampTesiraDspLevelControl> Levels { get; private set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,328 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
using System.Text.RegularExpressions;
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
|
||||
// QUESTIONS:
|
||||
//
|
||||
// When subscribing, just use the Instance ID for Custom Name?
|
||||
|
||||
// Verbose on subscriptions?
|
||||
|
||||
// Example subscription feedback responses
|
||||
// ! "publishToken":"name" "value":-77.0
|
||||
// ! "myLevelName" -77
|
||||
|
||||
public class QscDsp : DspBase
|
||||
{
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
public CommunicationGather PortGather { get; private set; }
|
||||
public GenericCommunicationMonitor CommunicationMonitor { get; private set; }
|
||||
|
||||
new public Dictionary<string, QscDspLevelControl> LevelControlPoints { get; private set; }
|
||||
new public Dictionary<string, QscDspDialer> Dialers { get; set; }
|
||||
public List<QscDspPresets> PresetList = new List<QscDspPresets>();
|
||||
|
||||
public bool isSubscribed;
|
||||
|
||||
|
||||
|
||||
CrestronQueue CommandQueue;
|
||||
|
||||
bool CommandQueueInProgress = false;
|
||||
|
||||
|
||||
public bool ShowHexResponse { get; set; }
|
||||
|
||||
public QscDsp(string key, string name, IBasicCommunication comm, QscDspPropertiesConfig props) :
|
||||
base(key, name)
|
||||
{
|
||||
CommandQueue = new CrestronQueue(100);
|
||||
|
||||
Communication = comm;
|
||||
var socket = comm as ISocketStatus;
|
||||
if (socket != null)
|
||||
{
|
||||
// This instance uses IP control
|
||||
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This instance uses RS-232 control
|
||||
}
|
||||
PortGather = new CommunicationGather(Communication, "\x0a");
|
||||
PortGather.LineReceived += this.Port_LineReceived;
|
||||
|
||||
LevelControlPoints = new Dictionary<string, QscDspLevelControl>();
|
||||
Dialers = new Dictionary<string, QscDspDialer>();
|
||||
|
||||
if (props.CommunicationMonitorProperties != null)
|
||||
{
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 20000, 120000, 300000, "cgp 1\x0D\x0A");
|
||||
}
|
||||
|
||||
|
||||
foreach (KeyValuePair<string, QscDspLevelControlBlockConfig> block in props.LevelControlBlocks)
|
||||
{
|
||||
this.LevelControlPoints.Add(block.Key, new QscDspLevelControl(block.Key, block.Value, this));
|
||||
Debug.Console(2, this, "Added LevelControlPoint {0}", block.Key);
|
||||
|
||||
|
||||
}
|
||||
foreach (KeyValuePair<string, QscDspPresets> preset in props.presets)
|
||||
{
|
||||
this.addPreset(preset.Value);
|
||||
Debug.Console(2, this, "Added Preset {0} {1}", preset.Value.label, preset.Value.preset);
|
||||
}
|
||||
foreach (KeyValuePair<string, QscDialerConfig> dialerConfig in props.dialerControlBlocks)
|
||||
{
|
||||
Debug.Console(2, this, "Added Dialer {0}\n {1}", dialerConfig.Key, dialerConfig.Value);
|
||||
this.Dialers.Add(dialerConfig.Key, new QscDspDialer(dialerConfig.Value, this));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
Communication.Connect();
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
CommunicationMonitor.Start();
|
||||
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(SendLine, "send" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
return true;
|
||||
}
|
||||
|
||||
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
||||
{
|
||||
Debug.Console(2, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
|
||||
|
||||
if (e.Client.IsConnected)
|
||||
{
|
||||
SubscribeToAttributes();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cleanup items from this session
|
||||
CommandQueue.Clear();
|
||||
CommandQueueInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initiates the subscription process to the DSP
|
||||
/// </summary>
|
||||
void SubscribeToAttributes()
|
||||
{
|
||||
SendLine("cgd 1");
|
||||
|
||||
SendLine("cgc 1");
|
||||
|
||||
foreach (KeyValuePair<string, QscDspLevelControl> level in LevelControlPoints)
|
||||
{
|
||||
level.Value.Subscribe();
|
||||
}
|
||||
|
||||
foreach (var dialer in Dialers)
|
||||
{
|
||||
dialer.Value.Subscribe();
|
||||
}
|
||||
|
||||
if (CommunicationMonitor != null)
|
||||
{
|
||||
|
||||
CommunicationMonitor.Start();
|
||||
//CommunicationMonitor = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
//CommunicationMonitor.Message = "cgp 1\x0D\x0A";
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
//CommunicationMonitor.Start();
|
||||
if (!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
|
||||
// ResetSubscriptionTimer();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handles a response message from the DSP
|
||||
/// </summary>
|
||||
/// <param name="dev"></param>
|
||||
/// <param name="args"></param>
|
||||
void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
|
||||
{
|
||||
Debug.Console(2, this, "RX: '{0}'", args.Text);
|
||||
try
|
||||
{
|
||||
if (args.Text.IndexOf("sr ") > -1)
|
||||
{
|
||||
}
|
||||
else if (args.Text.IndexOf("cv") > -1)
|
||||
{
|
||||
|
||||
var changeMessage = args.Text.Split(null);
|
||||
|
||||
string changedInstance = changeMessage[1].Replace("\"", "");
|
||||
Debug.Console(1, this, "cv parse Instance: {0}", changedInstance);
|
||||
bool foundItFlag = false;
|
||||
foreach (KeyValuePair<string, QscDspLevelControl> controlPoint in LevelControlPoints)
|
||||
{
|
||||
if (changedInstance == controlPoint.Value.LevelInstanceTag)
|
||||
{
|
||||
controlPoint.Value.ParseSubscriptionMessage(changedInstance, changeMessage[4]);
|
||||
foundItFlag = true;
|
||||
return;
|
||||
}
|
||||
else if (changedInstance == controlPoint.Value.MuteInstanceTag)
|
||||
{
|
||||
controlPoint.Value.ParseSubscriptionMessage(changedInstance, changeMessage[2].Replace("\"", ""));
|
||||
foundItFlag = true;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
if (!foundItFlag)
|
||||
{
|
||||
foreach (var dialer in Dialers)
|
||||
{
|
||||
PropertyInfo[] properties = dialer.Value.Tags.GetType().GetCType().GetProperties();
|
||||
//GetPropertyValues(Tags);
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
var propValue = prop.GetValue(dialer.Value.Tags, null) as string;
|
||||
if (changedInstance == propValue)
|
||||
{
|
||||
dialer.Value.ParseSubscriptionMessage(changedInstance, changeMessage[2].Replace("\"", ""));
|
||||
foundItFlag = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (foundItFlag)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "Error parsing response: '{0}'\n{1}", args.Text, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command to the DSP (with delimiter appended)
|
||||
/// </summary>
|
||||
/// <param name="s">Command to send</param>
|
||||
public void SendLine(string s)
|
||||
{
|
||||
Debug.Console(1, this, "TX: '{0}'", s);
|
||||
Communication.SendText(s + "\x0a");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a command from a child module to the queue
|
||||
/// </summary>
|
||||
/// <param name="command">Command object from child module</param>
|
||||
public void EnqueueCommand(QueuedCommand commandToEnqueue)
|
||||
{
|
||||
CommandQueue.Enqueue(commandToEnqueue);
|
||||
//Debug.Console(1, this, "Command (QueuedCommand) Enqueued '{0}'. CommandQueue has '{1}' Elements.", commandToEnqueue.Command, CommandQueue.Count);
|
||||
|
||||
if(!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a raw string command to the queue
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
public void EnqueueCommand(string command)
|
||||
{
|
||||
CommandQueue.Enqueue(command);
|
||||
//Debug.Console(1, this, "Command (string) Enqueued '{0}'. CommandQueue has '{1}' Elements.", command, CommandQueue.Count);
|
||||
|
||||
if (!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the next queued command to the DSP
|
||||
/// </summary>
|
||||
void SendNextQueuedCommand()
|
||||
{
|
||||
if (Communication.IsConnected && !CommandQueue.IsEmpty)
|
||||
{
|
||||
CommandQueueInProgress = true;
|
||||
|
||||
if (CommandQueue.Peek() is QueuedCommand)
|
||||
{
|
||||
QueuedCommand nextCommand = new QueuedCommand();
|
||||
|
||||
nextCommand = (QueuedCommand)CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand.Command);
|
||||
}
|
||||
else
|
||||
{
|
||||
string nextCommand = (string)CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void RunPresetNumber(ushort n)
|
||||
{
|
||||
RunPreset(PresetList[n].preset);
|
||||
}
|
||||
|
||||
public void addPreset(QscDspPresets s)
|
||||
{
|
||||
PresetList.Add(s);
|
||||
}
|
||||
/// <summary>
|
||||
/// Sends a command to execute a preset
|
||||
/// </summary>
|
||||
/// <param name="name">Preset Name</param>
|
||||
public override void RunPreset(string name)
|
||||
{
|
||||
SendLine(string.Format("ssl {0}", name));
|
||||
SendLine("cgp 1");
|
||||
}
|
||||
|
||||
public class QueuedCommand
|
||||
{
|
||||
public string Command { get; set; }
|
||||
public string AttributeCode { get; set; }
|
||||
public QscDspControlPoint ControlPoint { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
public abstract class QscDspControlPoint : DspControlPoint
|
||||
{
|
||||
public string Key { get; protected set; }
|
||||
|
||||
public string LevelInstanceTag { get; set; }
|
||||
public string MuteInstanceTag { get; set; }
|
||||
public QscDsp Parent { get; private set; }
|
||||
|
||||
public bool IsSubscribed { get; protected set; }
|
||||
|
||||
protected QscDspControlPoint(string levelInstanceTag, string muteInstanceTag, QscDsp parent)
|
||||
{
|
||||
LevelInstanceTag = levelInstanceTag;
|
||||
MuteInstanceTag = muteInstanceTag;
|
||||
Parent = parent;
|
||||
}
|
||||
|
||||
virtual public void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command to the DSP
|
||||
/// </summary>
|
||||
/// <param name="command">command</param>
|
||||
/// <param name="attribute">attribute code</param>
|
||||
/// <param name="value">value (use "" if not applicable)</param>
|
||||
public virtual void SendFullCommand(string cmd, string instance, string value)
|
||||
{
|
||||
|
||||
var cmdToSemd = string.Format("{0} {1} {2}", cmd, instance, value);
|
||||
|
||||
Parent.SendLine(cmdToSemd);
|
||||
|
||||
}
|
||||
|
||||
virtual public void ParseGetMessage(string attributeCode, string message)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
public virtual void SendSubscriptionCommand(string instanceTag, string changeGroup)
|
||||
{
|
||||
// Subscription string format: InstanceTag subscribe attributeCode Index1 customName responseRate
|
||||
// Ex: "RoomLevel subscribe level 1 MyRoomLevel 500"
|
||||
|
||||
string cmd;
|
||||
|
||||
cmd = string.Format("cga {0} {1}", changeGroup, instanceTag);
|
||||
|
||||
Parent.SendLine(cmd);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
using Crestron.SimplSharpPro.CrestronThread;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
public class QscDspDialer : DspDialerBase, IHasDialer
|
||||
{
|
||||
public QscDialerConfig Tags;
|
||||
public bool IsInCall { get; private set; }
|
||||
public QscDsp Parent { get; private set; }
|
||||
public string DialString { get; private set; }
|
||||
public bool OffHook { get; private set; }
|
||||
public bool AutoAnswerState { get; private set; }
|
||||
public bool DoNotDisturbState { get; private set; }
|
||||
|
||||
public BoolFeedback OffHookFeedback;
|
||||
public BoolFeedback AutoAnswerFeedback;
|
||||
public BoolFeedback DoNotDisturbFeedback;
|
||||
public StringFeedback DialStringFeedback;
|
||||
|
||||
// Add requirements for Dialer functionality
|
||||
|
||||
public QscDspDialer(QscDialerConfig Config, QscDsp parent)
|
||||
{
|
||||
Tags = Config;
|
||||
Parent = parent;
|
||||
DialStringFeedback = new StringFeedback(() => { return DialString; });
|
||||
OffHookFeedback = new BoolFeedback(() => { return OffHook; });
|
||||
AutoAnswerFeedback = new BoolFeedback(() => { return AutoAnswerState; });
|
||||
DoNotDisturbFeedback = new BoolFeedback(() => { return DoNotDisturbState; });
|
||||
}
|
||||
|
||||
public event EventHandler<CodecCallStatusItemChangeEventArgs> CallStatusChange;
|
||||
|
||||
public void Subscribe()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Do subscriptions and blah blah
|
||||
// This would be better using reflection JTA 2018-08-28
|
||||
PropertyInfo[] properties = Tags.GetType().GetCType().GetProperties();
|
||||
//GetPropertyValues(Tags);
|
||||
|
||||
Debug.Console(2, "QscDspDialer Subscribe");
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
//var val = prop.GetValue(obj, null);
|
||||
|
||||
|
||||
Debug.Console(2, "Property {0}, {1}, {2}\n", prop.GetType().Name, prop.Name, prop.PropertyType.FullName);
|
||||
if (prop.Name.Contains("Tag") && !prop.Name.Contains("keypad"))
|
||||
{
|
||||
var propValue = prop.GetValue(Tags, null) as string;
|
||||
Debug.Console(2, "Property {0}, {1}, {2}\n", prop.GetType().Name, prop.Name, propValue);
|
||||
SendSubscriptionCommand(propValue, "1");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
Debug.Console(2, "QscDspDialer Subscription Error: '{0}'\n", e);
|
||||
}
|
||||
|
||||
|
||||
// SendSubscriptionCommand(, "1");
|
||||
// SendSubscriptionCommand(config. , "mute", 500);
|
||||
}
|
||||
public void ParseSubscriptionMessage(string customName, string value)
|
||||
{
|
||||
|
||||
// Check for valid subscription response
|
||||
Debug.Console(1, "QscDialerTag {0} Response: '{1}'", customName, value);
|
||||
if (customName == Tags.dialStringTag)
|
||||
{
|
||||
Debug.Console(2, "QscDialerTag DialStringChanged ", value);
|
||||
this.DialString = value;
|
||||
this.DialStringFeedback.FireUpdate();
|
||||
}
|
||||
else if (customName == Tags.doNotDisturbTag)
|
||||
{
|
||||
if (value == "on")
|
||||
{
|
||||
this.DoNotDisturbState = true;
|
||||
}
|
||||
else if (value == "off")
|
||||
{
|
||||
this.DoNotDisturbState = false;
|
||||
}
|
||||
DoNotDisturbFeedback.FireUpdate();
|
||||
}
|
||||
else if (customName == Tags.callStatusTag)
|
||||
{
|
||||
if (value == "Dialing")
|
||||
{
|
||||
this.OffHook = true;
|
||||
}
|
||||
else if (value == "Disconnected")
|
||||
{
|
||||
this.OffHook = false;
|
||||
if (Tags.ClearOnHangup)
|
||||
{
|
||||
this.SendKeypad(eKeypadKeys.Clear);
|
||||
}
|
||||
}
|
||||
this.OffHookFeedback.FireUpdate();
|
||||
}
|
||||
else if (customName == Tags.autoAnswerTag)
|
||||
{
|
||||
if (value == "on")
|
||||
{
|
||||
this.AutoAnswerState = true;
|
||||
}
|
||||
else if (value == "off")
|
||||
{
|
||||
this.AutoAnswerState = false;
|
||||
}
|
||||
AutoAnswerFeedback.FireUpdate();
|
||||
}
|
||||
else if (customName == Tags.hookStatusTag)
|
||||
{
|
||||
if (value == "true")
|
||||
{
|
||||
this.OffHook = true;
|
||||
}
|
||||
else if (value == "false")
|
||||
{
|
||||
this.OffHook = false;
|
||||
}
|
||||
this.OffHookFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void DoNotDisturbToggle()
|
||||
{
|
||||
int dndStateInt = !DoNotDisturbState ? 1 : 0;
|
||||
Parent.SendLine(string.Format("csv {0} {1}", Tags.doNotDisturbTag, dndStateInt));
|
||||
}
|
||||
public void DoNotDisturbOn()
|
||||
{
|
||||
Parent.SendLine(string.Format("csv {0} 1", Tags.doNotDisturbTag));
|
||||
}
|
||||
public void DoNotDisturbOff()
|
||||
{
|
||||
Parent.SendLine(string.Format("csv {0} 0", Tags.doNotDisturbTag));
|
||||
}
|
||||
public void AutoAnswerToggle()
|
||||
{
|
||||
int autoAnswerStateInt = !AutoAnswerState ? 1 : 0;
|
||||
Parent.SendLine(string.Format("csv {0} {1}", Tags.autoAnswerTag, autoAnswerStateInt));
|
||||
}
|
||||
public void AutoAnswerOn()
|
||||
{
|
||||
Parent.SendLine(string.Format("csv {0} 1", Tags.autoAnswerTag));
|
||||
}
|
||||
public void AutoAnswerOff()
|
||||
{
|
||||
Parent.SendLine(string.Format("csv {0} 0", Tags.autoAnswerTag));
|
||||
}
|
||||
|
||||
private void PollKeypad()
|
||||
{
|
||||
Thread.Sleep(50);
|
||||
Parent.SendLine(string.Format("cg {0}", Tags.dialStringTag));
|
||||
}
|
||||
|
||||
public void SendKeypad(eKeypadKeys button)
|
||||
{
|
||||
string keypadTag = null;
|
||||
switch (button)
|
||||
{
|
||||
case eKeypadKeys.Num0: keypadTag = Tags.keypad0Tag; break;
|
||||
case eKeypadKeys.Num1: keypadTag = Tags.keypad1Tag; break;
|
||||
case eKeypadKeys.Num2: keypadTag = Tags.keypad2Tag; break;
|
||||
case eKeypadKeys.Num3: keypadTag = Tags.keypad3Tag; break;
|
||||
case eKeypadKeys.Num4: keypadTag = Tags.keypad4Tag; break;
|
||||
case eKeypadKeys.Num5: keypadTag = Tags.keypad5Tag; break;
|
||||
case eKeypadKeys.Num6: keypadTag = Tags.keypad6Tag; break;
|
||||
case eKeypadKeys.Num7: keypadTag = Tags.keypad7Tag; break;
|
||||
case eKeypadKeys.Num8: keypadTag = Tags.keypad8Tag; break;
|
||||
case eKeypadKeys.Num9: keypadTag = Tags.keypad9Tag; break;
|
||||
case eKeypadKeys.Pound: keypadTag = Tags.keypadPoundTag; break;
|
||||
case eKeypadKeys.Star: keypadTag = Tags.keypadStarTag; break;
|
||||
case eKeypadKeys.Backspace: keypadTag = Tags.keypadBackspaceTag; break;
|
||||
case eKeypadKeys.Clear: keypadTag = Tags.keypadClearTag; break;
|
||||
}
|
||||
if (keypadTag != null)
|
||||
{
|
||||
var cmdToSend = string.Format("ct {0}", keypadTag);
|
||||
Parent.SendLine(cmdToSend);
|
||||
PollKeypad();
|
||||
}
|
||||
}
|
||||
public void SendSubscriptionCommand(string instanceTag, string changeGroup)
|
||||
{
|
||||
// Subscription string format: InstanceTag subscribe attributeCode Index1 customName responseRate
|
||||
// Ex: "RoomLevel subscribe level 1 MyRoomLevel 500"
|
||||
|
||||
var cmd = string.Format("cga {0} {1}", changeGroup, instanceTag);
|
||||
|
||||
Parent.SendLine(cmd);
|
||||
}
|
||||
public void Dial()
|
||||
{
|
||||
if (!this.OffHook)
|
||||
{
|
||||
Parent.SendLine(string.Format("ct {0}", Tags.connectTag));
|
||||
}
|
||||
else
|
||||
{
|
||||
Parent.SendLine(string.Format("ct {0}", Tags.disconnectTag));
|
||||
}
|
||||
Thread.Sleep(50);
|
||||
Parent.SendLine(string.Format("cg {0}", Tags.callStatusTag));
|
||||
}
|
||||
public void Dial(string number)
|
||||
{
|
||||
}
|
||||
public void EndCall(CodecActiveCallItem activeCall)
|
||||
{
|
||||
}
|
||||
public void EndAllCalls()
|
||||
{
|
||||
}
|
||||
public void AcceptCall(CodecActiveCallItem item)
|
||||
{
|
||||
}
|
||||
|
||||
public void RejectCall(CodecActiveCallItem item)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void SendDtmf(string digit)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public enum eKeypadKeys
|
||||
{
|
||||
Num1,
|
||||
Num2,
|
||||
Num3,
|
||||
Num4,
|
||||
Num5,
|
||||
Num6,
|
||||
Num7,
|
||||
Num8,
|
||||
Num9,
|
||||
Num0,
|
||||
Star,
|
||||
Pound,
|
||||
Clear,
|
||||
Backspace
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
public class QscDspLevelControl : QscDspControlPoint, IBasicVolumeWithFeedback, IKeyed
|
||||
{
|
||||
bool _IsMuted;
|
||||
ushort _VolumeLevel;
|
||||
|
||||
public BoolFeedback MuteFeedback { get; private set; }
|
||||
|
||||
public IntFeedback VolumeLevelFeedback { get; private set; }
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
public ePdtLevelTypes Type;
|
||||
CTimer VolumeUpRepeatTimer;
|
||||
CTimer VolumeDownRepeatTimer;
|
||||
|
||||
/// <summary>
|
||||
/// Used for to identify level subscription values
|
||||
/// </summary>
|
||||
public string LevelCustomName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used for to identify mute subscription values
|
||||
/// </summary>
|
||||
public string MuteCustomName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Minimum fader level
|
||||
/// </summary>
|
||||
double MinLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum fader level
|
||||
/// </summary>
|
||||
double MaxLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a valid subscription string has been recieved for all subscriptions
|
||||
/// </summary>
|
||||
public bool IsSubsribed
|
||||
{
|
||||
get
|
||||
{
|
||||
bool isSubscribed = false;
|
||||
|
||||
if (HasMute && MuteIsSubscribed)
|
||||
isSubscribed = true;
|
||||
|
||||
if (HasLevel && LevelIsSubscribed)
|
||||
isSubscribed = true;
|
||||
|
||||
return isSubscribed;
|
||||
}
|
||||
}
|
||||
|
||||
public bool AutomaticUnmuteOnVolumeUp { get; private set; }
|
||||
|
||||
public bool HasMute { get; private set; }
|
||||
|
||||
public bool HasLevel { get; private set; }
|
||||
|
||||
bool MuteIsSubscribed;
|
||||
|
||||
bool LevelIsSubscribed;
|
||||
|
||||
//public TesiraForteLevelControl(string label, string id, int index1, int index2, bool hasMute, bool hasLevel, BiampTesiraForteDsp parent)
|
||||
// : base(id, index1, index2, parent)
|
||||
//{
|
||||
// Initialize(label, hasMute, hasLevel);
|
||||
//}
|
||||
|
||||
public QscDspLevelControl(string key, QscDspLevelControlBlockConfig config, QscDsp parent)
|
||||
: base(config.LevelInstanceTag, config.MuteInstanceTag, parent)
|
||||
{
|
||||
if (!config.Disabled)
|
||||
{
|
||||
Initialize(key, config);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this attribute based on config values and generates subscriptions commands and adds commands to the parent's queue.
|
||||
/// </summary>
|
||||
public void Initialize(string key, QscDspLevelControlBlockConfig config)
|
||||
{
|
||||
Key = string.Format("{0}--{1}", Parent.Key, key);
|
||||
Enabled = true;
|
||||
DeviceManager.AddDevice(this);
|
||||
if (config.IsMic)
|
||||
{
|
||||
Type = ePdtLevelTypes.microphone;
|
||||
}
|
||||
else
|
||||
{
|
||||
Type = ePdtLevelTypes.speaker;
|
||||
}
|
||||
|
||||
Debug.Console(2, this, "Adding LevelControl '{0}'", Key);
|
||||
|
||||
this.IsSubscribed = false;
|
||||
|
||||
MuteFeedback = new BoolFeedback(() => _IsMuted);
|
||||
|
||||
VolumeLevelFeedback = new IntFeedback(() => _VolumeLevel);
|
||||
|
||||
VolumeUpRepeatTimer = new CTimer(VolumeUpRepeat, Timeout.Infinite);
|
||||
VolumeDownRepeatTimer = new CTimer(VolumeDownRepeat, Timeout.Infinite);
|
||||
LevelCustomName = config.Label;
|
||||
HasMute = config.HasMute;
|
||||
HasLevel = config.HasLevel;
|
||||
}
|
||||
|
||||
public void Subscribe()
|
||||
{
|
||||
// Do subscriptions and blah blah
|
||||
|
||||
// Subscribe to mute
|
||||
if (this.HasMute)
|
||||
{
|
||||
|
||||
SendSubscriptionCommand(this.MuteInstanceTag, "1");
|
||||
// SendSubscriptionCommand(config. , "mute", 500);
|
||||
}
|
||||
|
||||
// Subscribe to level
|
||||
if (this.HasLevel)
|
||||
{
|
||||
|
||||
SendSubscriptionCommand(this.LevelInstanceTag, "1");
|
||||
// SendSubscriptionCommand(this.con, "level", 250);
|
||||
|
||||
//SendFullCommand("get", "minLevel", null);
|
||||
|
||||
//SendFullCommand("get", "maxLevel", null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Parses the response from the DspBase
|
||||
/// </summary>
|
||||
/// <param name="customName"></param>
|
||||
/// <param name="value"></param>
|
||||
public void ParseSubscriptionMessage(string customName, string value)
|
||||
{
|
||||
|
||||
// Check for valid subscription response
|
||||
Debug.Console(1, this, "Level {0} Response: '{1}'", customName, value);
|
||||
if (customName == MuteInstanceTag)
|
||||
{
|
||||
if (value == "muted")
|
||||
{
|
||||
_IsMuted = true;
|
||||
MuteIsSubscribed = true;
|
||||
|
||||
}
|
||||
else if (value == "unmuted")
|
||||
{
|
||||
_IsMuted = false;
|
||||
MuteIsSubscribed = true;
|
||||
}
|
||||
|
||||
MuteFeedback.FireUpdate();
|
||||
}
|
||||
else if (customName == LevelInstanceTag)
|
||||
{
|
||||
|
||||
|
||||
var _value = Double.Parse(value);
|
||||
|
||||
_VolumeLevel = (ushort)(_value * 65535);
|
||||
Debug.Console(1, this, "Level {0} VolumeLevel: '{1}'", customName, _VolumeLevel);
|
||||
LevelIsSubscribed = true;
|
||||
|
||||
VolumeLevelFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Turns the mute off
|
||||
/// </summary>
|
||||
public void MuteOff()
|
||||
{
|
||||
SendFullCommand("csv", this.MuteInstanceTag, "0");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turns the mute on
|
||||
/// </summary>
|
||||
public void MuteOn()
|
||||
{
|
||||
SendFullCommand("csv", this.MuteInstanceTag, "1");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the volume to a specified level
|
||||
/// </summary>
|
||||
/// <param name="level"></param>
|
||||
public void SetVolume(ushort level)
|
||||
{
|
||||
Debug.Console(1, this, "volume: {0}", level);
|
||||
// Unmute volume if new level is higher than existing
|
||||
if (AutomaticUnmuteOnVolumeUp && _IsMuted)
|
||||
{
|
||||
MuteOff();
|
||||
}
|
||||
double newLevel = Scale(level);
|
||||
Debug.Console(1, this, "newVolume: {0}", newLevel);
|
||||
SendFullCommand("csp", this.LevelInstanceTag, string.Format("{0}", newLevel));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles mute status
|
||||
/// </summary>
|
||||
public void MuteToggle()
|
||||
{
|
||||
|
||||
if (_IsMuted)
|
||||
{
|
||||
SendFullCommand("csv", this.MuteInstanceTag, "0");
|
||||
}
|
||||
else
|
||||
{
|
||||
SendFullCommand("csv", this.MuteInstanceTag, "1");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void VolumeUpRepeat(object callbackObject)
|
||||
{
|
||||
this.VolumeUp(true);
|
||||
}
|
||||
public void VolumeDownRepeat(object callbackObject)
|
||||
{
|
||||
this.VolumeDown(true);
|
||||
}
|
||||
|
||||
public void VolumeDown(bool press)
|
||||
{
|
||||
|
||||
|
||||
if (press)
|
||||
{
|
||||
VolumeDownRepeatTimer.Reset(100);
|
||||
SendFullCommand("css ", this.LevelInstanceTag, "--");
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
VolumeDownRepeatTimer.Stop();
|
||||
// VolumeDownRepeatTimer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increments volume level
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void VolumeUp(bool press)
|
||||
{
|
||||
if (press)
|
||||
{
|
||||
VolumeUpRepeatTimer.Reset(100);
|
||||
SendFullCommand("css ", this.LevelInstanceTag, "++");
|
||||
|
||||
if (AutomaticUnmuteOnVolumeUp)
|
||||
if (!_IsMuted)
|
||||
MuteOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
VolumeUpRepeatTimer.Stop();
|
||||
}
|
||||
}
|
||||
/// <returns></returns>
|
||||
double Scale(double input)
|
||||
{
|
||||
Debug.Console(1, this, "Scaling (double) input '{0}'",input );
|
||||
|
||||
var output = (input / 65535);
|
||||
|
||||
Debug.Console(1, this, "Scaled output '{0}'", output);
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
public enum ePdtLevelTypes
|
||||
{
|
||||
speaker = 0,
|
||||
microphone = 1
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class QscDspPropertiesConfig
|
||||
{
|
||||
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
||||
|
||||
public ControlPropertiesConfig Control { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// These are key-value pairs, string id, string type.
|
||||
/// Valid types are level and mute.
|
||||
/// Need to include the index values somehow
|
||||
/// </summary>
|
||||
public Dictionary<string, QscDspLevelControlBlockConfig> LevelControlBlocks { get; set; }
|
||||
public Dictionary<string, QscDialerConfig> dialerControlBlocks { get; set; }
|
||||
public Dictionary<string, QscDspPresets> presets { get; set; }
|
||||
// public Dictionary<string, BiampTesiraForteDialerControlBlockConfig> DialerControlBlocks {get; set;}
|
||||
}
|
||||
public interface IQscDspBasicLevel : IBasicVolumeWithFeedback
|
||||
{
|
||||
/// <summary>
|
||||
/// In BiAmp: Instance Tag, QSC: Named Control, Polycom:
|
||||
/// </summary>
|
||||
string LevelInstanceTag { get; set; }
|
||||
string MuteInstanceTag { get; set; }
|
||||
bool HasMute { get; }
|
||||
bool HasLevel { get; }
|
||||
bool AutomaticUnmuteOnVolumeUp { get; }
|
||||
}
|
||||
public class QscDspLevelControlBlockConfig
|
||||
{
|
||||
public bool Disabled { get; set; }
|
||||
public string Label { get; set; }
|
||||
public string LevelInstanceTag { get; set; }
|
||||
public string MuteInstanceTag { get; set; }
|
||||
public bool HasMute { get; set; }
|
||||
public bool HasLevel { get; set; }
|
||||
public bool IsMic { get; set; }
|
||||
}
|
||||
|
||||
public class QscDialerConfig
|
||||
{
|
||||
public string incomingCallRingerTag {get; set;}
|
||||
public string dialStringTag {get; set;}
|
||||
public string disconnectTag {get; set;}
|
||||
public string connectTag {get; set;}
|
||||
public string callStatusTag {get; set;}
|
||||
public string hookStatusTag {get; set;}
|
||||
public string doNotDisturbTag { get; set; }
|
||||
public string autoAnswerTag { get; set; }
|
||||
|
||||
public string keypadBackspaceTag {get; set;}
|
||||
public string keypadClearTag {get; set;}
|
||||
public string keypad1Tag {get; set;}
|
||||
public string keypad2Tag {get; set;}
|
||||
public string keypad3Tag {get; set;}
|
||||
public string keypad4Tag {get; set;}
|
||||
public string keypad5Tag {get; set;}
|
||||
public string keypad6Tag {get; set;}
|
||||
public string keypad7Tag {get; set;}
|
||||
public string keypad8Tag {get; set;}
|
||||
public string keypad9Tag {get; set;}
|
||||
public string keypad0Tag {get; set;}
|
||||
public string keypadPoundTag {get; set;}
|
||||
public string keypadStarTag {get; set;}
|
||||
|
||||
public bool ClearOnHangup { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class QscDspPresets
|
||||
{
|
||||
public string label { get; set; }
|
||||
public string preset { get; set; }
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,328 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
using System.Text.RegularExpressions;
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
|
||||
// QUESTIONS:
|
||||
//
|
||||
// When subscribing, just use the Instance ID for Custom Name?
|
||||
|
||||
// Verbose on subscriptions?
|
||||
|
||||
// Example subscription feedback responses
|
||||
// ! "publishToken":"name" "value":-77.0
|
||||
// ! "myLevelName" -77
|
||||
|
||||
public class QscDsp : DspBase
|
||||
{
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
public CommunicationGather PortGather { get; private set; }
|
||||
public GenericCommunicationMonitor CommunicationMonitor { get; private set; }
|
||||
|
||||
new public Dictionary<string, QscDspLevelControl> LevelControlPoints { get; private set; }
|
||||
new public Dictionary<string, QscDspDialer> Dialers { get; set; }
|
||||
public List<QscDspPresets> PresetList = new List<QscDspPresets>();
|
||||
|
||||
public bool isSubscribed;
|
||||
|
||||
|
||||
|
||||
CrestronQueue CommandQueue;
|
||||
|
||||
bool CommandQueueInProgress = false;
|
||||
|
||||
|
||||
public bool ShowHexResponse { get; set; }
|
||||
|
||||
public QscDsp(string key, string name, IBasicCommunication comm, QscDspPropertiesConfig props) :
|
||||
base(key, name)
|
||||
{
|
||||
CommandQueue = new CrestronQueue(100);
|
||||
|
||||
Communication = comm;
|
||||
var socket = comm as ISocketStatus;
|
||||
if (socket != null)
|
||||
{
|
||||
// This instance uses IP control
|
||||
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This instance uses RS-232 control
|
||||
}
|
||||
PortGather = new CommunicationGather(Communication, "\x0a");
|
||||
PortGather.LineReceived += this.Port_LineReceived;
|
||||
|
||||
LevelControlPoints = new Dictionary<string, QscDspLevelControl>();
|
||||
Dialers = new Dictionary<string, QscDspDialer>();
|
||||
|
||||
if (props.CommunicationMonitorProperties != null)
|
||||
{
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 20000, 120000, 300000, "cgp 1\x0D\x0A");
|
||||
}
|
||||
|
||||
|
||||
foreach (KeyValuePair<string, QscDspLevelControlBlockConfig> block in props.LevelControlBlocks)
|
||||
{
|
||||
this.LevelControlPoints.Add(block.Key, new QscDspLevelControl(block.Key, block.Value, this));
|
||||
Debug.Console(2, this, "Added LevelControlPoint {0}", block.Key);
|
||||
|
||||
|
||||
}
|
||||
foreach (KeyValuePair<string, QscDspPresets> preset in props.presets)
|
||||
{
|
||||
this.addPreset(preset.Value);
|
||||
Debug.Console(2, this, "Added Preset {0} {1}", preset.Value.label, preset.Value.preset);
|
||||
}
|
||||
foreach (KeyValuePair<string, QscDialerConfig> dialerConfig in props.dialerControlBlocks)
|
||||
{
|
||||
Debug.Console(2, this, "Added Dialer {0}\n {1}", dialerConfig.Key, dialerConfig.Value);
|
||||
this.Dialers.Add(dialerConfig.Key, new QscDspDialer(dialerConfig.Value, this));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
Communication.Connect();
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
CommunicationMonitor.Start();
|
||||
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(SendLine, "send" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
return true;
|
||||
}
|
||||
|
||||
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
||||
{
|
||||
Debug.Console(2, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
|
||||
|
||||
if (e.Client.IsConnected)
|
||||
{
|
||||
SubscribeToAttributes();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cleanup items from this session
|
||||
CommandQueue.Clear();
|
||||
CommandQueueInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initiates the subscription process to the DSP
|
||||
/// </summary>
|
||||
void SubscribeToAttributes()
|
||||
{
|
||||
SendLine("cgd 1");
|
||||
|
||||
SendLine("cgc 1");
|
||||
|
||||
foreach (KeyValuePair<string, QscDspLevelControl> level in LevelControlPoints)
|
||||
{
|
||||
level.Value.Subscribe();
|
||||
}
|
||||
|
||||
foreach (var dialer in Dialers)
|
||||
{
|
||||
dialer.Value.Subscribe();
|
||||
}
|
||||
|
||||
if (CommunicationMonitor != null)
|
||||
{
|
||||
|
||||
CommunicationMonitor.Start();
|
||||
//CommunicationMonitor = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
//CommunicationMonitor.Message = "cgp 1\x0D\x0A";
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
//CommunicationMonitor.Start();
|
||||
if (!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
|
||||
// ResetSubscriptionTimer();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handles a response message from the DSP
|
||||
/// </summary>
|
||||
/// <param name="dev"></param>
|
||||
/// <param name="args"></param>
|
||||
void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
|
||||
{
|
||||
Debug.Console(2, this, "RX: '{0}'", args.Text);
|
||||
try
|
||||
{
|
||||
if (args.Text.IndexOf("sr ") > -1)
|
||||
{
|
||||
}
|
||||
else if (args.Text.IndexOf("cv") > -1)
|
||||
{
|
||||
|
||||
var changeMessage = args.Text.Split(null);
|
||||
|
||||
string changedInstance = changeMessage[1].Replace("\"", "");
|
||||
Debug.Console(1, this, "cv parse Instance: {0}", changedInstance);
|
||||
bool foundItFlag = false;
|
||||
foreach (KeyValuePair<string, QscDspLevelControl> controlPoint in LevelControlPoints)
|
||||
{
|
||||
if (changedInstance == controlPoint.Value.LevelInstanceTag)
|
||||
{
|
||||
controlPoint.Value.ParseSubscriptionMessage(changedInstance, changeMessage[4]);
|
||||
foundItFlag = true;
|
||||
return;
|
||||
}
|
||||
else if (changedInstance == controlPoint.Value.MuteInstanceTag)
|
||||
{
|
||||
controlPoint.Value.ParseSubscriptionMessage(changedInstance, changeMessage[2].Replace("\"", ""));
|
||||
foundItFlag = true;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
if (!foundItFlag)
|
||||
{
|
||||
foreach (var dialer in Dialers)
|
||||
{
|
||||
PropertyInfo[] properties = dialer.Value.Tags.GetType().GetCType().GetProperties();
|
||||
//GetPropertyValues(Tags);
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
var propValue = prop.GetValue(dialer.Value.Tags, null) as string;
|
||||
if (changedInstance == propValue)
|
||||
{
|
||||
dialer.Value.ParseSubscriptionMessage(changedInstance, changeMessage[2].Replace("\"", ""));
|
||||
foundItFlag = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (foundItFlag)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "Error parsing response: '{0}'\n{1}", args.Text, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command to the DSP (with delimiter appended)
|
||||
/// </summary>
|
||||
/// <param name="s">Command to send</param>
|
||||
public void SendLine(string s)
|
||||
{
|
||||
Debug.Console(1, this, "TX: '{0}'", s);
|
||||
Communication.SendText(s + "\x0a");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a command from a child module to the queue
|
||||
/// </summary>
|
||||
/// <param name="command">Command object from child module</param>
|
||||
public void EnqueueCommand(QueuedCommand commandToEnqueue)
|
||||
{
|
||||
CommandQueue.Enqueue(commandToEnqueue);
|
||||
//Debug.Console(1, this, "Command (QueuedCommand) Enqueued '{0}'. CommandQueue has '{1}' Elements.", commandToEnqueue.Command, CommandQueue.Count);
|
||||
|
||||
if(!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a raw string command to the queue
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
public void EnqueueCommand(string command)
|
||||
{
|
||||
CommandQueue.Enqueue(command);
|
||||
//Debug.Console(1, this, "Command (string) Enqueued '{0}'. CommandQueue has '{1}' Elements.", command, CommandQueue.Count);
|
||||
|
||||
if (!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the next queued command to the DSP
|
||||
/// </summary>
|
||||
void SendNextQueuedCommand()
|
||||
{
|
||||
if (Communication.IsConnected && !CommandQueue.IsEmpty)
|
||||
{
|
||||
CommandQueueInProgress = true;
|
||||
|
||||
if (CommandQueue.Peek() is QueuedCommand)
|
||||
{
|
||||
QueuedCommand nextCommand = new QueuedCommand();
|
||||
|
||||
nextCommand = (QueuedCommand)CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand.Command);
|
||||
}
|
||||
else
|
||||
{
|
||||
string nextCommand = (string)CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void RunPresetNumber(ushort n)
|
||||
{
|
||||
RunPreset(PresetList[n].preset);
|
||||
}
|
||||
|
||||
public void addPreset(QscDspPresets s)
|
||||
{
|
||||
PresetList.Add(s);
|
||||
}
|
||||
/// <summary>
|
||||
/// Sends a command to execute a preset
|
||||
/// </summary>
|
||||
/// <param name="name">Preset Name</param>
|
||||
public override void RunPreset(string name)
|
||||
{
|
||||
SendLine(string.Format("ssl {0}", name));
|
||||
SendLine("cgp 1");
|
||||
}
|
||||
|
||||
public class QueuedCommand
|
||||
{
|
||||
public string Command { get; set; }
|
||||
public string AttributeCode { get; set; }
|
||||
public QscDspControlPoint ControlPoint { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
public abstract class QscDspControlPoint : DspControlPoint
|
||||
{
|
||||
public string Key { get; protected set; }
|
||||
|
||||
public string LevelInstanceTag { get; set; }
|
||||
public string MuteInstanceTag { get; set; }
|
||||
public QscDsp Parent { get; private set; }
|
||||
|
||||
public bool IsSubscribed { get; protected set; }
|
||||
|
||||
protected QscDspControlPoint(string levelInstanceTag, string muteInstanceTag, QscDsp parent)
|
||||
{
|
||||
LevelInstanceTag = levelInstanceTag;
|
||||
MuteInstanceTag = muteInstanceTag;
|
||||
Parent = parent;
|
||||
}
|
||||
|
||||
virtual public void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command to the DSP
|
||||
/// </summary>
|
||||
/// <param name="command">command</param>
|
||||
/// <param name="attribute">attribute code</param>
|
||||
/// <param name="value">value (use "" if not applicable)</param>
|
||||
public virtual void SendFullCommand(string cmd, string instance, string value)
|
||||
{
|
||||
|
||||
var cmdToSemd = string.Format("{0} {1} {2}", cmd, instance, value);
|
||||
|
||||
Parent.SendLine(cmdToSemd);
|
||||
|
||||
}
|
||||
|
||||
virtual public void ParseGetMessage(string attributeCode, string message)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
public virtual void SendSubscriptionCommand(string instanceTag, string changeGroup)
|
||||
{
|
||||
// Subscription string format: InstanceTag subscribe attributeCode Index1 customName responseRate
|
||||
// Ex: "RoomLevel subscribe level 1 MyRoomLevel 500"
|
||||
|
||||
string cmd;
|
||||
|
||||
cmd = string.Format("cga {0} {1}", changeGroup, instanceTag);
|
||||
|
||||
Parent.SendLine(cmd);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
using Crestron.SimplSharpPro.CrestronThread;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
public class QscDspDialer : DspDialerBase, IHasDialer
|
||||
{
|
||||
public QscDialerConfig Tags;
|
||||
public bool IsInCall { get; private set; }
|
||||
public QscDsp Parent { get; private set; }
|
||||
public string DialString { get; private set; }
|
||||
public bool OffHook { get; private set; }
|
||||
public bool AutoAnswerState { get; private set; }
|
||||
public bool DoNotDisturbState { get; private set; }
|
||||
|
||||
public BoolFeedback OffHookFeedback;
|
||||
public BoolFeedback AutoAnswerFeedback;
|
||||
public BoolFeedback DoNotDisturbFeedback;
|
||||
public StringFeedback DialStringFeedback;
|
||||
|
||||
// Add requirements for Dialer functionality
|
||||
|
||||
public QscDspDialer(QscDialerConfig Config, QscDsp parent)
|
||||
{
|
||||
Tags = Config;
|
||||
Parent = parent;
|
||||
DialStringFeedback = new StringFeedback(() => { return DialString; });
|
||||
OffHookFeedback = new BoolFeedback(() => { return OffHook; });
|
||||
AutoAnswerFeedback = new BoolFeedback(() => { return AutoAnswerState; });
|
||||
DoNotDisturbFeedback = new BoolFeedback(() => { return DoNotDisturbState; });
|
||||
}
|
||||
|
||||
public event EventHandler<CodecCallStatusItemChangeEventArgs> CallStatusChange;
|
||||
|
||||
public void Subscribe()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Do subscriptions and blah blah
|
||||
// This would be better using reflection JTA 2018-08-28
|
||||
PropertyInfo[] properties = Tags.GetType().GetCType().GetProperties();
|
||||
//GetPropertyValues(Tags);
|
||||
|
||||
Debug.Console(2, "QscDspDialer Subscribe");
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
//var val = prop.GetValue(obj, null);
|
||||
|
||||
|
||||
Debug.Console(2, "Property {0}, {1}, {2}\n", prop.GetType().Name, prop.Name, prop.PropertyType.FullName);
|
||||
if (prop.Name.Contains("Tag") && !prop.Name.Contains("keypad"))
|
||||
{
|
||||
var propValue = prop.GetValue(Tags, null) as string;
|
||||
Debug.Console(2, "Property {0}, {1}, {2}\n", prop.GetType().Name, prop.Name, propValue);
|
||||
SendSubscriptionCommand(propValue, "1");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
Debug.Console(2, "QscDspDialer Subscription Error: '{0}'\n", e);
|
||||
}
|
||||
|
||||
|
||||
// SendSubscriptionCommand(, "1");
|
||||
// SendSubscriptionCommand(config. , "mute", 500);
|
||||
}
|
||||
public void ParseSubscriptionMessage(string customName, string value)
|
||||
{
|
||||
|
||||
// Check for valid subscription response
|
||||
Debug.Console(1, "QscDialerTag {0} Response: '{1}'", customName, value);
|
||||
if (customName == Tags.dialStringTag)
|
||||
{
|
||||
Debug.Console(2, "QscDialerTag DialStringChanged ", value);
|
||||
this.DialString = value;
|
||||
this.DialStringFeedback.FireUpdate();
|
||||
}
|
||||
else if (customName == Tags.doNotDisturbTag)
|
||||
{
|
||||
if (value == "on")
|
||||
{
|
||||
this.DoNotDisturbState = true;
|
||||
}
|
||||
else if (value == "off")
|
||||
{
|
||||
this.DoNotDisturbState = false;
|
||||
}
|
||||
DoNotDisturbFeedback.FireUpdate();
|
||||
}
|
||||
else if (customName == Tags.callStatusTag)
|
||||
{
|
||||
if (value == "Dialing")
|
||||
{
|
||||
this.OffHook = true;
|
||||
}
|
||||
else if (value == "Disconnected")
|
||||
{
|
||||
this.OffHook = false;
|
||||
if (Tags.ClearOnHangup)
|
||||
{
|
||||
this.SendKeypad(eKeypadKeys.Clear);
|
||||
}
|
||||
}
|
||||
this.OffHookFeedback.FireUpdate();
|
||||
}
|
||||
else if (customName == Tags.autoAnswerTag)
|
||||
{
|
||||
if (value == "on")
|
||||
{
|
||||
this.AutoAnswerState = true;
|
||||
}
|
||||
else if (value == "off")
|
||||
{
|
||||
this.AutoAnswerState = false;
|
||||
}
|
||||
AutoAnswerFeedback.FireUpdate();
|
||||
}
|
||||
else if (customName == Tags.hookStatusTag)
|
||||
{
|
||||
if (value == "true")
|
||||
{
|
||||
this.OffHook = true;
|
||||
}
|
||||
else if (value == "false")
|
||||
{
|
||||
this.OffHook = false;
|
||||
}
|
||||
this.OffHookFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void DoNotDisturbToggle()
|
||||
{
|
||||
int dndStateInt = !DoNotDisturbState ? 1 : 0;
|
||||
Parent.SendLine(string.Format("csv {0} {1}", Tags.doNotDisturbTag, dndStateInt));
|
||||
}
|
||||
public void DoNotDisturbOn()
|
||||
{
|
||||
Parent.SendLine(string.Format("csv {0} 1", Tags.doNotDisturbTag));
|
||||
}
|
||||
public void DoNotDisturbOff()
|
||||
{
|
||||
Parent.SendLine(string.Format("csv {0} 0", Tags.doNotDisturbTag));
|
||||
}
|
||||
public void AutoAnswerToggle()
|
||||
{
|
||||
int autoAnswerStateInt = !AutoAnswerState ? 1 : 0;
|
||||
Parent.SendLine(string.Format("csv {0} {1}", Tags.autoAnswerTag, autoAnswerStateInt));
|
||||
}
|
||||
public void AutoAnswerOn()
|
||||
{
|
||||
Parent.SendLine(string.Format("csv {0} 1", Tags.autoAnswerTag));
|
||||
}
|
||||
public void AutoAnswerOff()
|
||||
{
|
||||
Parent.SendLine(string.Format("csv {0} 0", Tags.autoAnswerTag));
|
||||
}
|
||||
|
||||
private void PollKeypad()
|
||||
{
|
||||
Thread.Sleep(50);
|
||||
Parent.SendLine(string.Format("cg {0}", Tags.dialStringTag));
|
||||
}
|
||||
|
||||
public void SendKeypad(eKeypadKeys button)
|
||||
{
|
||||
string keypadTag = null;
|
||||
switch (button)
|
||||
{
|
||||
case eKeypadKeys.Num0: keypadTag = Tags.keypad0Tag; break;
|
||||
case eKeypadKeys.Num1: keypadTag = Tags.keypad1Tag; break;
|
||||
case eKeypadKeys.Num2: keypadTag = Tags.keypad2Tag; break;
|
||||
case eKeypadKeys.Num3: keypadTag = Tags.keypad3Tag; break;
|
||||
case eKeypadKeys.Num4: keypadTag = Tags.keypad4Tag; break;
|
||||
case eKeypadKeys.Num5: keypadTag = Tags.keypad5Tag; break;
|
||||
case eKeypadKeys.Num6: keypadTag = Tags.keypad6Tag; break;
|
||||
case eKeypadKeys.Num7: keypadTag = Tags.keypad7Tag; break;
|
||||
case eKeypadKeys.Num8: keypadTag = Tags.keypad8Tag; break;
|
||||
case eKeypadKeys.Num9: keypadTag = Tags.keypad9Tag; break;
|
||||
case eKeypadKeys.Pound: keypadTag = Tags.keypadPoundTag; break;
|
||||
case eKeypadKeys.Star: keypadTag = Tags.keypadStarTag; break;
|
||||
case eKeypadKeys.Backspace: keypadTag = Tags.keypadBackspaceTag; break;
|
||||
case eKeypadKeys.Clear: keypadTag = Tags.keypadClearTag; break;
|
||||
}
|
||||
if (keypadTag != null)
|
||||
{
|
||||
var cmdToSend = string.Format("ct {0}", keypadTag);
|
||||
Parent.SendLine(cmdToSend);
|
||||
PollKeypad();
|
||||
}
|
||||
}
|
||||
public void SendSubscriptionCommand(string instanceTag, string changeGroup)
|
||||
{
|
||||
// Subscription string format: InstanceTag subscribe attributeCode Index1 customName responseRate
|
||||
// Ex: "RoomLevel subscribe level 1 MyRoomLevel 500"
|
||||
|
||||
var cmd = string.Format("cga {0} {1}", changeGroup, instanceTag);
|
||||
|
||||
Parent.SendLine(cmd);
|
||||
}
|
||||
public void Dial()
|
||||
{
|
||||
if (!this.OffHook)
|
||||
{
|
||||
Parent.SendLine(string.Format("ct {0}", Tags.connectTag));
|
||||
}
|
||||
else
|
||||
{
|
||||
Parent.SendLine(string.Format("ct {0}", Tags.disconnectTag));
|
||||
}
|
||||
Thread.Sleep(50);
|
||||
Parent.SendLine(string.Format("cg {0}", Tags.callStatusTag));
|
||||
}
|
||||
public void Dial(string number)
|
||||
{
|
||||
}
|
||||
public void EndCall(CodecActiveCallItem activeCall)
|
||||
{
|
||||
}
|
||||
public void EndAllCalls()
|
||||
{
|
||||
}
|
||||
public void AcceptCall(CodecActiveCallItem item)
|
||||
{
|
||||
}
|
||||
|
||||
public void RejectCall(CodecActiveCallItem item)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void SendDtmf(string digit)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public enum eKeypadKeys
|
||||
{
|
||||
Num1,
|
||||
Num2,
|
||||
Num3,
|
||||
Num4,
|
||||
Num5,
|
||||
Num6,
|
||||
Num7,
|
||||
Num8,
|
||||
Num9,
|
||||
Num0,
|
||||
Star,
|
||||
Pound,
|
||||
Clear,
|
||||
Backspace
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
public class QscDspLevelControl : QscDspControlPoint, IBasicVolumeWithFeedback, IKeyed
|
||||
{
|
||||
bool _IsMuted;
|
||||
ushort _VolumeLevel;
|
||||
|
||||
public BoolFeedback MuteFeedback { get; private set; }
|
||||
|
||||
public IntFeedback VolumeLevelFeedback { get; private set; }
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
public ePdtLevelTypes Type;
|
||||
CTimer VolumeUpRepeatTimer;
|
||||
CTimer VolumeDownRepeatTimer;
|
||||
|
||||
/// <summary>
|
||||
/// Used for to identify level subscription values
|
||||
/// </summary>
|
||||
public string LevelCustomName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used for to identify mute subscription values
|
||||
/// </summary>
|
||||
public string MuteCustomName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Minimum fader level
|
||||
/// </summary>
|
||||
double MinLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum fader level
|
||||
/// </summary>
|
||||
double MaxLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a valid subscription string has been recieved for all subscriptions
|
||||
/// </summary>
|
||||
public bool IsSubsribed
|
||||
{
|
||||
get
|
||||
{
|
||||
bool isSubscribed = false;
|
||||
|
||||
if (HasMute && MuteIsSubscribed)
|
||||
isSubscribed = true;
|
||||
|
||||
if (HasLevel && LevelIsSubscribed)
|
||||
isSubscribed = true;
|
||||
|
||||
return isSubscribed;
|
||||
}
|
||||
}
|
||||
|
||||
public bool AutomaticUnmuteOnVolumeUp { get; private set; }
|
||||
|
||||
public bool HasMute { get; private set; }
|
||||
|
||||
public bool HasLevel { get; private set; }
|
||||
|
||||
bool MuteIsSubscribed;
|
||||
|
||||
bool LevelIsSubscribed;
|
||||
|
||||
//public TesiraForteLevelControl(string label, string id, int index1, int index2, bool hasMute, bool hasLevel, BiampTesiraForteDsp parent)
|
||||
// : base(id, index1, index2, parent)
|
||||
//{
|
||||
// Initialize(label, hasMute, hasLevel);
|
||||
//}
|
||||
|
||||
public QscDspLevelControl(string key, QscDspLevelControlBlockConfig config, QscDsp parent)
|
||||
: base(config.LevelInstanceTag, config.MuteInstanceTag, parent)
|
||||
{
|
||||
if (!config.Disabled)
|
||||
{
|
||||
Initialize(key, config);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this attribute based on config values and generates subscriptions commands and adds commands to the parent's queue.
|
||||
/// </summary>
|
||||
public void Initialize(string key, QscDspLevelControlBlockConfig config)
|
||||
{
|
||||
Key = string.Format("{0}--{1}", Parent.Key, key);
|
||||
Enabled = true;
|
||||
DeviceManager.AddDevice(this);
|
||||
if (config.IsMic)
|
||||
{
|
||||
Type = ePdtLevelTypes.microphone;
|
||||
}
|
||||
else
|
||||
{
|
||||
Type = ePdtLevelTypes.speaker;
|
||||
}
|
||||
|
||||
Debug.Console(2, this, "Adding LevelControl '{0}'", Key);
|
||||
|
||||
this.IsSubscribed = false;
|
||||
|
||||
MuteFeedback = new BoolFeedback(() => _IsMuted);
|
||||
|
||||
VolumeLevelFeedback = new IntFeedback(() => _VolumeLevel);
|
||||
|
||||
VolumeUpRepeatTimer = new CTimer(VolumeUpRepeat, Timeout.Infinite);
|
||||
VolumeDownRepeatTimer = new CTimer(VolumeDownRepeat, Timeout.Infinite);
|
||||
LevelCustomName = config.Label;
|
||||
HasMute = config.HasMute;
|
||||
HasLevel = config.HasLevel;
|
||||
}
|
||||
|
||||
public void Subscribe()
|
||||
{
|
||||
// Do subscriptions and blah blah
|
||||
|
||||
// Subscribe to mute
|
||||
if (this.HasMute)
|
||||
{
|
||||
|
||||
SendSubscriptionCommand(this.MuteInstanceTag, "1");
|
||||
// SendSubscriptionCommand(config. , "mute", 500);
|
||||
}
|
||||
|
||||
// Subscribe to level
|
||||
if (this.HasLevel)
|
||||
{
|
||||
|
||||
SendSubscriptionCommand(this.LevelInstanceTag, "1");
|
||||
// SendSubscriptionCommand(this.con, "level", 250);
|
||||
|
||||
//SendFullCommand("get", "minLevel", null);
|
||||
|
||||
//SendFullCommand("get", "maxLevel", null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Parses the response from the DspBase
|
||||
/// </summary>
|
||||
/// <param name="customName"></param>
|
||||
/// <param name="value"></param>
|
||||
public void ParseSubscriptionMessage(string customName, string value)
|
||||
{
|
||||
|
||||
// Check for valid subscription response
|
||||
Debug.Console(1, this, "Level {0} Response: '{1}'", customName, value);
|
||||
if (customName == MuteInstanceTag)
|
||||
{
|
||||
if (value == "muted")
|
||||
{
|
||||
_IsMuted = true;
|
||||
MuteIsSubscribed = true;
|
||||
|
||||
}
|
||||
else if (value == "unmuted")
|
||||
{
|
||||
_IsMuted = false;
|
||||
MuteIsSubscribed = true;
|
||||
}
|
||||
|
||||
MuteFeedback.FireUpdate();
|
||||
}
|
||||
else if (customName == LevelInstanceTag)
|
||||
{
|
||||
|
||||
|
||||
var _value = Double.Parse(value);
|
||||
|
||||
_VolumeLevel = (ushort)(_value * 65535);
|
||||
Debug.Console(1, this, "Level {0} VolumeLevel: '{1}'", customName, _VolumeLevel);
|
||||
LevelIsSubscribed = true;
|
||||
|
||||
VolumeLevelFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Turns the mute off
|
||||
/// </summary>
|
||||
public void MuteOff()
|
||||
{
|
||||
SendFullCommand("csv", this.MuteInstanceTag, "0");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turns the mute on
|
||||
/// </summary>
|
||||
public void MuteOn()
|
||||
{
|
||||
SendFullCommand("csv", this.MuteInstanceTag, "1");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the volume to a specified level
|
||||
/// </summary>
|
||||
/// <param name="level"></param>
|
||||
public void SetVolume(ushort level)
|
||||
{
|
||||
Debug.Console(1, this, "volume: {0}", level);
|
||||
// Unmute volume if new level is higher than existing
|
||||
if (AutomaticUnmuteOnVolumeUp && _IsMuted)
|
||||
{
|
||||
MuteOff();
|
||||
}
|
||||
double newLevel = Scale(level);
|
||||
Debug.Console(1, this, "newVolume: {0}", newLevel);
|
||||
SendFullCommand("csp", this.LevelInstanceTag, string.Format("{0}", newLevel));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles mute status
|
||||
/// </summary>
|
||||
public void MuteToggle()
|
||||
{
|
||||
|
||||
if (_IsMuted)
|
||||
{
|
||||
SendFullCommand("csv", this.MuteInstanceTag, "0");
|
||||
}
|
||||
else
|
||||
{
|
||||
SendFullCommand("csv", this.MuteInstanceTag, "1");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void VolumeUpRepeat(object callbackObject)
|
||||
{
|
||||
this.VolumeUp(true);
|
||||
}
|
||||
public void VolumeDownRepeat(object callbackObject)
|
||||
{
|
||||
this.VolumeDown(true);
|
||||
}
|
||||
|
||||
public void VolumeDown(bool press)
|
||||
{
|
||||
|
||||
|
||||
if (press)
|
||||
{
|
||||
VolumeDownRepeatTimer.Reset(100);
|
||||
SendFullCommand("css ", this.LevelInstanceTag, "--");
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
VolumeDownRepeatTimer.Stop();
|
||||
// VolumeDownRepeatTimer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increments volume level
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void VolumeUp(bool press)
|
||||
{
|
||||
if (press)
|
||||
{
|
||||
VolumeUpRepeatTimer.Reset(100);
|
||||
SendFullCommand("css ", this.LevelInstanceTag, "++");
|
||||
|
||||
if (AutomaticUnmuteOnVolumeUp)
|
||||
if (!_IsMuted)
|
||||
MuteOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
VolumeUpRepeatTimer.Stop();
|
||||
}
|
||||
}
|
||||
/// <returns></returns>
|
||||
double Scale(double input)
|
||||
{
|
||||
Debug.Console(1, this, "Scaling (double) input '{0}'",input );
|
||||
|
||||
var output = (input / 65535);
|
||||
|
||||
Debug.Console(1, this, "Scaled output '{0}'", output);
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
public enum ePdtLevelTypes
|
||||
{
|
||||
speaker = 0,
|
||||
microphone = 1
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class QscDspPropertiesConfig
|
||||
{
|
||||
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
||||
|
||||
public ControlPropertiesConfig Control { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// These are key-value pairs, string id, string type.
|
||||
/// Valid types are level and mute.
|
||||
/// Need to include the index values somehow
|
||||
/// </summary>
|
||||
public Dictionary<string, QscDspLevelControlBlockConfig> LevelControlBlocks { get; set; }
|
||||
public Dictionary<string, QscDialerConfig> dialerControlBlocks { get; set; }
|
||||
public Dictionary<string, QscDspPresets> presets { get; set; }
|
||||
// public Dictionary<string, BiampTesiraForteDialerControlBlockConfig> DialerControlBlocks {get; set;}
|
||||
}
|
||||
public interface IQscDspBasicLevel : IBasicVolumeWithFeedback
|
||||
{
|
||||
/// <summary>
|
||||
/// In BiAmp: Instance Tag, QSC: Named Control, Polycom:
|
||||
/// </summary>
|
||||
string LevelInstanceTag { get; set; }
|
||||
string MuteInstanceTag { get; set; }
|
||||
bool HasMute { get; }
|
||||
bool HasLevel { get; }
|
||||
bool AutomaticUnmuteOnVolumeUp { get; }
|
||||
}
|
||||
public class QscDspLevelControlBlockConfig
|
||||
{
|
||||
public bool Disabled { get; set; }
|
||||
public string Label { get; set; }
|
||||
public string LevelInstanceTag { get; set; }
|
||||
public string MuteInstanceTag { get; set; }
|
||||
public bool HasMute { get; set; }
|
||||
public bool HasLevel { get; set; }
|
||||
public bool IsMic { get; set; }
|
||||
}
|
||||
|
||||
public class QscDialerConfig
|
||||
{
|
||||
public string incomingCallRingerTag {get; set;}
|
||||
public string dialStringTag {get; set;}
|
||||
public string disconnectTag {get; set;}
|
||||
public string connectTag {get; set;}
|
||||
public string callStatusTag {get; set;}
|
||||
public string hookStatusTag {get; set;}
|
||||
public string doNotDisturbTag { get; set; }
|
||||
public string autoAnswerTag { get; set; }
|
||||
|
||||
public string keypadBackspaceTag {get; set;}
|
||||
public string keypadClearTag {get; set;}
|
||||
public string keypad1Tag {get; set;}
|
||||
public string keypad2Tag {get; set;}
|
||||
public string keypad3Tag {get; set;}
|
||||
public string keypad4Tag {get; set;}
|
||||
public string keypad5Tag {get; set;}
|
||||
public string keypad6Tag {get; set;}
|
||||
public string keypad7Tag {get; set;}
|
||||
public string keypad8Tag {get; set;}
|
||||
public string keypad9Tag {get; set;}
|
||||
public string keypad0Tag {get; set;}
|
||||
public string keypadPoundTag {get; set;}
|
||||
public string keypadStarTag {get; set;}
|
||||
|
||||
public bool ClearOnHangup { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class QscDspPresets
|
||||
{
|
||||
public string label { get; set; }
|
||||
public string preset { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
public class IRBlurayBase : Device, IDiscPlayerControls, IUiDisplayInfo, IRoutingOutputs, IUsageTracking
|
||||
{
|
||||
public IrOutputPortController IrPort { get; private set; }
|
||||
|
||||
public uint DisplayUiType { get { return DisplayUiConstants.TypeBluray; } }
|
||||
|
||||
public IRBlurayBase(string key, string name, IrOutputPortController portCont)
|
||||
: base(key, name)
|
||||
{
|
||||
IrPort = portCont;
|
||||
DeviceManager.AddDevice(portCont);
|
||||
|
||||
HasKeypadAccessoryButton1 = true;
|
||||
KeypadAccessoryButton1Command = "Clear";
|
||||
KeypadAccessoryButton1Label = "Clear";
|
||||
|
||||
HasKeypadAccessoryButton2 = true;
|
||||
KeypadAccessoryButton2Command = "NumericEnter";
|
||||
KeypadAccessoryButton2Label = "Enter";
|
||||
|
||||
PowerIsOnFeedback = new BoolFeedback(() => _PowerIsOn);
|
||||
|
||||
HdmiOut = new RoutingOutputPort(RoutingPortNames.HdmiOut, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, null, this);
|
||||
AnyAudioOut = new RoutingOutputPort(RoutingPortNames.AnyAudioOut, eRoutingSignalType.Audio,
|
||||
eRoutingPortConnectionType.DigitalAudio, null, this);
|
||||
OutputPorts = new RoutingPortCollection<RoutingOutputPort> { HdmiOut, AnyAudioOut };
|
||||
}
|
||||
|
||||
|
||||
#region IDPad Members
|
||||
|
||||
public void Up(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_UP_ARROW, pressRelease);
|
||||
}
|
||||
|
||||
public void Down(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_DN_ARROW, pressRelease);
|
||||
}
|
||||
|
||||
public void Left(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_LEFT_ARROW, pressRelease);
|
||||
}
|
||||
|
||||
public void Right(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_RIGHT_ARROW, pressRelease);
|
||||
}
|
||||
|
||||
public void Select(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_ENTER, pressRelease);
|
||||
}
|
||||
|
||||
public void Menu(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_MENU, pressRelease);
|
||||
}
|
||||
|
||||
public void Exit(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_EXIT, pressRelease);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region INumericKeypad Members
|
||||
|
||||
public void Digit0(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_0, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit1(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_1, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit2(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_2, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit3(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_3, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit4(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_4, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit5(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_5, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit6(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_6, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit7(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_7, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit8(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_8, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit9(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_9, pressRelease);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defaults to true
|
||||
/// </summary>
|
||||
public bool HasKeypadAccessoryButton1 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defaults to "-"
|
||||
/// </summary>
|
||||
public string KeypadAccessoryButton1Label { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Defaults to "Dash"
|
||||
/// </summary>
|
||||
public string KeypadAccessoryButton1Command { get; set; }
|
||||
|
||||
public void KeypadAccessoryButton1(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(KeypadAccessoryButton1Command, pressRelease);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defaults to true
|
||||
/// </summary>
|
||||
public bool HasKeypadAccessoryButton2 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defaults to "Enter"
|
||||
/// </summary>
|
||||
public string KeypadAccessoryButton2Label { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Defaults to "Enter"
|
||||
/// </summary>
|
||||
public string KeypadAccessoryButton2Command { get; set; }
|
||||
|
||||
public void KeypadAccessoryButton2(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(KeypadAccessoryButton2Command, pressRelease);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IChannelFunctions Members
|
||||
|
||||
public void ChannelUp(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_CH_PLUS, pressRelease);
|
||||
}
|
||||
|
||||
public void ChannelDown(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_CH_MINUS, pressRelease);
|
||||
}
|
||||
|
||||
public void LastChannel(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_LAST, pressRelease);
|
||||
}
|
||||
|
||||
public void Guide(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_GUIDE, pressRelease);
|
||||
}
|
||||
|
||||
public void Info(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_INFO, pressRelease);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IColorFunctions Members
|
||||
|
||||
public void Red(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_RED, pressRelease);
|
||||
}
|
||||
|
||||
public void Green(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_GREEN, pressRelease);
|
||||
}
|
||||
|
||||
public void Yellow(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_YELLOW, pressRelease);
|
||||
}
|
||||
|
||||
public void Blue(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_BLUE, pressRelease);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IRoutingOutputs Members
|
||||
|
||||
public RoutingOutputPort HdmiOut { get; private set; }
|
||||
public RoutingOutputPort AnyAudioOut { get; private set; }
|
||||
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region IPower Members
|
||||
|
||||
public void PowerOn()
|
||||
{
|
||||
IrPort.Pulse(IROutputStandardCommands.IROut_POWER_ON, 200);
|
||||
_PowerIsOn = true;
|
||||
}
|
||||
|
||||
public void PowerOff()
|
||||
{
|
||||
IrPort.Pulse(IROutputStandardCommands.IROut_POWER_OFF, 200);
|
||||
_PowerIsOn = false;
|
||||
}
|
||||
|
||||
public void PowerToggle()
|
||||
{
|
||||
IrPort.Pulse(IROutputStandardCommands.IROut_POWER, 200);
|
||||
_PowerIsOn = false;
|
||||
}
|
||||
|
||||
public BoolFeedback PowerIsOnFeedback { get; set; }
|
||||
bool _PowerIsOn;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ITransport Members
|
||||
|
||||
public void Play(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_PLAY, pressRelease);
|
||||
}
|
||||
|
||||
public void Pause(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_PAUSE, pressRelease);
|
||||
}
|
||||
|
||||
public void Rewind(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_RSCAN, pressRelease);
|
||||
}
|
||||
|
||||
public void FFwd(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_FSCAN, pressRelease);
|
||||
}
|
||||
|
||||
public void ChapMinus(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_TRACK_MINUS, pressRelease);
|
||||
}
|
||||
|
||||
public void ChapPlus(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_TRACK_PLUS, pressRelease);
|
||||
}
|
||||
|
||||
public void Stop(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_STOP, pressRelease);
|
||||
}
|
||||
|
||||
public void Record(bool pressRelease)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IUsageTracking Members
|
||||
|
||||
public UsageTracking UsageTracker { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,720 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro.CrestronThread;
|
||||
using Crestron.SimplSharpPro;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Displays
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class AvocorDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, ICommunicationMonitor, IInputDisplayPort1,
|
||||
IInputHdmi1, IInputHdmi2, IInputHdmi3, IInputHdmi4, IInputVga1
|
||||
{
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
public CommunicationGather PortGather { get; private set; }
|
||||
|
||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||
|
||||
public byte ID { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 0x08
|
||||
/// </summary>
|
||||
const byte InputVga1Value = 0x00;
|
||||
/// <summary>
|
||||
/// 0x09
|
||||
/// </summary>
|
||||
const byte InputHdmi1Value = 0x09;
|
||||
/// <summary>
|
||||
/// 0x0a
|
||||
/// </summary>
|
||||
const byte InputHdmi2Value = 0x0a;
|
||||
/// <summary>
|
||||
/// 0x0b
|
||||
/// </summary>
|
||||
const byte InputHdmi3Value = 0x0b;
|
||||
/// <summary>
|
||||
/// 0x0c
|
||||
/// </summary>
|
||||
const byte InputHdmi4Value = 0x0c;
|
||||
/// <summary>
|
||||
/// 0c0d
|
||||
/// </summary>
|
||||
const byte InputDisplayPort1Value = 0x0d;
|
||||
/// <summary>
|
||||
/// 0x0e
|
||||
/// </summary>
|
||||
const byte InputIpcOpsValue = 0x0e;
|
||||
/// <summary>
|
||||
/// 0x11
|
||||
/// </summary>
|
||||
const byte InputHdmi5Value = 0x11;
|
||||
/// <summary>
|
||||
/// 0x12
|
||||
/// </summary>
|
||||
const byte InputMediaPlayerValue = 0x12;
|
||||
|
||||
|
||||
bool _PowerIsOn;
|
||||
bool _IsWarmingUp;
|
||||
bool _IsCoolingDown;
|
||||
ushort _VolumeLevelForSig;
|
||||
int _LastVolumeSent;
|
||||
ushort _PreMuteVolumeLevel;
|
||||
bool _IsMuted;
|
||||
RoutingInputPort _CurrentInputPort;
|
||||
ActionIncrementer VolumeIncrementer;
|
||||
bool VolumeIsRamping;
|
||||
public bool IsInStandby { get; private set; }
|
||||
|
||||
protected override Func<bool> PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } }
|
||||
protected override Func<bool> IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } }
|
||||
protected override Func<bool> IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } }
|
||||
protected override Func<string> CurrentInputFeedbackFunc { get { return () => _CurrentInputPort.Key; } }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for IBasicCommunication
|
||||
/// </summary>
|
||||
public AvocorDisplay(string key, string name, IBasicCommunication comm, string id)
|
||||
: base(key, name)
|
||||
{
|
||||
Communication = comm;
|
||||
//Communication.BytesReceived += new EventHandler<GenericCommMethodReceiveBytesArgs>(Communication_BytesReceived);
|
||||
|
||||
PortGather = new CommunicationGather(Communication, '\x08');
|
||||
PortGather.IncludeDelimiter = true;
|
||||
PortGather.LineReceived += new EventHandler<GenericCommMethodReceiveTextArgs>(PortGather_LineReceived);
|
||||
|
||||
ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for TCP
|
||||
/// </summary>
|
||||
public AvocorDisplay(string key, string name, string hostname, int port, string id)
|
||||
: base(key, name)
|
||||
{
|
||||
Communication = new GenericTcpIpClient(key + "-tcp", hostname, port, 5000);
|
||||
|
||||
PortGather = new CommunicationGather(Communication, '\x0d');
|
||||
PortGather.IncludeDelimiter = true;
|
||||
PortGather.LineReceived += new EventHandler<GenericCommMethodReceiveTextArgs>(PortGather_LineReceived);
|
||||
|
||||
ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for COM
|
||||
/// </summary>
|
||||
public AvocorDisplay(string key, string name, ComPort port, ComPort.ComPortSpec spec, string id)
|
||||
: base(key, name)
|
||||
{
|
||||
Communication = new ComPortController(key + "-com", port, spec);
|
||||
|
||||
PortGather = new CommunicationGather(Communication, '\x0d');
|
||||
PortGather.IncludeDelimiter = true;
|
||||
PortGather.LineReceived += new EventHandler<GenericCommMethodReceiveTextArgs>(PortGather_LineReceived);
|
||||
|
||||
ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor
|
||||
Init();
|
||||
}
|
||||
|
||||
void AddRoutingInputPort(RoutingInputPort port, byte fbMatch)
|
||||
{
|
||||
port.FeedbackMatchObject = fbMatch;
|
||||
InputPorts.Add(port);
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
WarmupTime = 10000;
|
||||
CooldownTime = 8000;
|
||||
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, StatusGet);
|
||||
DeviceManager.AddDevice(CommunicationMonitor);
|
||||
|
||||
VolumeIncrementer = new ActionIncrementer(655, 0, 65535, 800, 80,
|
||||
v => SetVolume((ushort)v),
|
||||
() => _LastVolumeSent);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi1), this), InputHdmi1Value);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi2), this), InputHdmi2Value);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi3), this), InputHdmi3Value);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi4), this), InputHdmi4Value);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn5, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi5), this), InputHdmi5Value);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.DisplayPortIn1, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.DisplayPort, new Action(InputDisplayPort1), this), InputDisplayPort1Value);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.VgaIn, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Dvi, new Action(InputVga1), this), InputVga1Value);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.IpcOps, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Composite, new Action(InputIpcOps), this), InputIpcOpsValue);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.MediaPlayer, eRoutingSignalType.Video,
|
||||
eRoutingPortConnectionType.Vga, new Action(InputMediaPlayer), this), InputMediaPlayerValue);
|
||||
|
||||
VolumeLevelFeedback = new IntFeedback(() => { return _VolumeLevelForSig; });
|
||||
MuteFeedback = new BoolFeedback(() => _IsMuted);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
Communication.Connect();
|
||||
|
||||
var socket = Communication as ISocketStatus;
|
||||
if (socket != null)
|
||||
{
|
||||
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
|
||||
}
|
||||
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
CommunicationMonitor.Start();
|
||||
|
||||
StatusGet();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
||||
{
|
||||
if (e.Client.IsConnected)
|
||||
StatusGet();
|
||||
}
|
||||
|
||||
public override FeedbackCollection<Feedback> Feedbacks
|
||||
{
|
||||
get
|
||||
{
|
||||
var list = base.Feedbacks;
|
||||
list.AddRange(new List<Feedback>
|
||||
{
|
||||
VolumeLevelFeedback,
|
||||
MuteFeedback,
|
||||
CurrentInputFeedback
|
||||
});
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// /
|
||||
///// </summary>
|
||||
///// <param name="sender"></param>
|
||||
//void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e)
|
||||
//{
|
||||
// // This is probably not thread-safe buffering
|
||||
// // Append the incoming bytes with whatever is in the buffer
|
||||
// var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length];
|
||||
// IncomingBuffer.CopyTo(newBytes, 0);
|
||||
// e.Bytes.CopyTo(newBytes, IncomingBuffer.Length);
|
||||
|
||||
// if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
|
||||
// Debug.Console(2, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes));
|
||||
|
||||
// // Need to find AA FF and have
|
||||
// for (int i = 0; i < newBytes.Length; i++)
|
||||
// {
|
||||
// if (newBytes[i] == 0xAA && newBytes[i + 1] == 0xFF)
|
||||
// {
|
||||
// newBytes = newBytes.Skip(i).ToArray(); // Trim off junk if there's "dirt" in the buffer
|
||||
|
||||
// // parse it
|
||||
// // If it's at least got the header, then process it,
|
||||
// while (newBytes.Length > 4 && newBytes[0] == 0xAA && newBytes[1] == 0xFF)
|
||||
// {
|
||||
// var msgLen = newBytes[3];
|
||||
// // if the buffer is shorter than the header (3) + message (msgLen) + checksum (1),
|
||||
// // give and save it for next time
|
||||
// if (newBytes.Length < msgLen + 4)
|
||||
// break;
|
||||
|
||||
// // Good length, grab the message
|
||||
// var message = newBytes.Skip(4).Take(msgLen).ToArray();
|
||||
|
||||
// // At this point, the ack/nak is the first byte
|
||||
// if (message[0] == 0x41)
|
||||
// {
|
||||
// switch (message[1]) // type byte
|
||||
// {
|
||||
// case 0x00: // General status
|
||||
// UpdatePowerFB(message[2], message[5]); // "power" can be misrepresented when the display sleeps
|
||||
// UpdateInputFb(message[5]);
|
||||
// UpdateVolumeFB(message[3]);
|
||||
// UpdateMuteFb(message[4]);
|
||||
// UpdateInputFb(message[5]);
|
||||
// break;
|
||||
|
||||
// case 0x11:
|
||||
// UpdatePowerFB(message[2]);
|
||||
// break;
|
||||
|
||||
// case 0x12:
|
||||
// UpdateVolumeFB(message[2]);
|
||||
// break;
|
||||
|
||||
// case 0x13:
|
||||
// UpdateMuteFb(message[2]);
|
||||
// break;
|
||||
|
||||
// case 0x14:
|
||||
// UpdateInputFb(message[2]);
|
||||
// break;
|
||||
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// // Skip over what we've used and save the rest for next time
|
||||
// newBytes = newBytes.Skip(5 + msgLen).ToArray();
|
||||
// }
|
||||
|
||||
// break; // parsing will mean we can stop looking for header in loop
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Save whatever partial message is here
|
||||
// IncomingBuffer = newBytes;
|
||||
//}
|
||||
|
||||
void PortGather_LineReceived(object sender, GenericCommMethodReceiveTextArgs e)
|
||||
{
|
||||
Debug.Console(1, this, "Receivied: '{0}'", ComTextHelper.GetEscapedText(e.Text));
|
||||
|
||||
if (e.Text.IndexOf("\x50\x4F\x57") > -1)
|
||||
{
|
||||
// Power Status Response
|
||||
|
||||
var value = e.Text.ToCharArray();
|
||||
|
||||
switch (value[6])
|
||||
{
|
||||
case '\x00':
|
||||
{
|
||||
_PowerIsOn = false;
|
||||
break;
|
||||
}
|
||||
case '\x01':
|
||||
{
|
||||
_PowerIsOn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PowerIsOnFeedback.FireUpdate();
|
||||
Debug.Console(1, this, "PowerIsOn State: {0}", PowerIsOnFeedback.BoolValue);
|
||||
|
||||
}
|
||||
else if (e.Text.IndexOf("\x4D\x49\x4E") > -1)
|
||||
{
|
||||
var value = e.Text.ToCharArray();
|
||||
|
||||
var b = value[6];
|
||||
|
||||
var newInput = InputPorts.FirstOrDefault(i => i.FeedbackMatchObject.Equals(b));
|
||||
if (newInput != null && newInput != _CurrentInputPort)
|
||||
{
|
||||
_CurrentInputPort = newInput;
|
||||
CurrentInputFeedback.FireUpdate();
|
||||
Debug.Console(1, this, "Current Input: {0}", CurrentInputFeedback.StringValue);
|
||||
}
|
||||
|
||||
}
|
||||
else if (e.Text.IndexOf("\x56\x4F\x4C") > -1)
|
||||
{
|
||||
// Volume Status Response
|
||||
|
||||
var value = e.Text.ToCharArray();
|
||||
|
||||
var b = value[6];
|
||||
|
||||
var newVol = (ushort)NumericalHelpers.Scale((double)b, 0, 100, 0, 65535);
|
||||
if (!VolumeIsRamping)
|
||||
_LastVolumeSent = newVol;
|
||||
if (newVol != _VolumeLevelForSig)
|
||||
{
|
||||
_VolumeLevelForSig = newVol;
|
||||
VolumeLevelFeedback.FireUpdate();
|
||||
|
||||
if (_VolumeLevelForSig > 0)
|
||||
_IsMuted = false;
|
||||
else
|
||||
_IsMuted = true;
|
||||
|
||||
MuteFeedback.FireUpdate();
|
||||
|
||||
Debug.Console(1, this, "Volume Level: {0}", VolumeLevelFeedback.IntValue);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void UpdatePowerFB(byte powerByte)
|
||||
{
|
||||
var newVal = powerByte == 1;
|
||||
if (newVal != _PowerIsOn)
|
||||
{
|
||||
_PowerIsOn = newVal;
|
||||
PowerIsOnFeedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates power status from general updates where source is included.
|
||||
/// Compensates for errant standby / power off hiccups by ignoring
|
||||
/// power off states with input < 0x10
|
||||
/// </summary>
|
||||
void UpdatePowerFB(byte powerByte, byte inputByte)
|
||||
{
|
||||
// This should reject errant power feedbacks when switching away from input on standby.
|
||||
if (powerByte == 0x01 && inputByte < 0x10)
|
||||
IsInStandby = true;
|
||||
if (powerByte == 0x00 && IsInStandby) // Ignore power off if coming from standby - glitch
|
||||
{
|
||||
IsInStandby = false;
|
||||
return;
|
||||
}
|
||||
|
||||
UpdatePowerFB(powerByte);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void UpdateVolumeFB(byte b)
|
||||
{
|
||||
var newVol = (ushort)NumericalHelpers.Scale((double)b, 0, 100, 0, 65535);
|
||||
if (!VolumeIsRamping)
|
||||
_LastVolumeSent = newVol;
|
||||
if (newVol != _VolumeLevelForSig)
|
||||
{
|
||||
_VolumeLevelForSig = newVol;
|
||||
VolumeLevelFeedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void UpdateMuteFb(byte b)
|
||||
{
|
||||
var newMute = b == 1;
|
||||
if (newMute != _IsMuted)
|
||||
{
|
||||
_IsMuted = newMute;
|
||||
MuteFeedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void UpdateInputFb(byte b)
|
||||
{
|
||||
var newInput = InputPorts.FirstOrDefault(i => i.FeedbackMatchObject.Equals(b));
|
||||
if (newInput != null && newInput != _CurrentInputPort)
|
||||
{
|
||||
_CurrentInputPort = newInput;
|
||||
CurrentInputFeedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats an outgoing message. Replaces third byte with ID and replaces last byte with checksum
|
||||
/// </summary>
|
||||
/// <param name="b"></param>
|
||||
void SendBytes(byte[] b)
|
||||
{
|
||||
b[1] = ID;
|
||||
|
||||
var command = b.ToString();
|
||||
|
||||
Debug.Console(1, this, "Sending: '{0}'",ComTextHelper.GetEscapedText(b));
|
||||
|
||||
Communication.SendBytes(b);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void StatusGet()
|
||||
{
|
||||
PowerGet();
|
||||
|
||||
CrestronEnvironment.Sleep(100);
|
||||
|
||||
InputGet();
|
||||
|
||||
CrestronEnvironment.Sleep(100);
|
||||
|
||||
VolumeGet();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public override void PowerOn()
|
||||
{
|
||||
//Send(PowerOnCmd);
|
||||
SendBytes(new byte[] { 0x07, ID, 0x02, 0x50, 0x4F, 0x57, 0x01, 0x08, 0x0d });
|
||||
if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
|
||||
{
|
||||
_IsWarmingUp = true;
|
||||
IsWarmingUpFeedback.FireUpdate();
|
||||
// Fake power-up cycle
|
||||
WarmupTimer = new CTimer(o =>
|
||||
{
|
||||
_IsWarmingUp = false;
|
||||
_PowerIsOn = true;
|
||||
IsWarmingUpFeedback.FireUpdate();
|
||||
PowerIsOnFeedback.FireUpdate();
|
||||
}, WarmupTime);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public override void PowerOff()
|
||||
{
|
||||
// If a display has unreliable-power off feedback, just override this and
|
||||
// remove this check.
|
||||
if (!_IsWarmingUp && !_IsCoolingDown) // PowerIsOnFeedback.BoolValue &&
|
||||
{
|
||||
//Send(PowerOffCmd);
|
||||
SendBytes(new byte[] { 0x07, ID, 0x02, 0x50, 0x4F, 0x57, 0x00, 0x08, 0x0d });
|
||||
_IsCoolingDown = true;
|
||||
_PowerIsOn = false;
|
||||
PowerIsOnFeedback.FireUpdate();
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
// Fake cool-down cycle
|
||||
CooldownTimer = new CTimer(o =>
|
||||
{
|
||||
_IsCoolingDown = false;
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
}, CooldownTime);
|
||||
}
|
||||
}
|
||||
|
||||
public override void PowerToggle()
|
||||
{
|
||||
if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue)
|
||||
PowerOff();
|
||||
else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue)
|
||||
PowerOn();
|
||||
}
|
||||
|
||||
public void PowerGet()
|
||||
{
|
||||
SendBytes(new byte[] { 0x07, ID, 0x01, 0x50, 0x4F, 0x57, 0x08, 0x0d });
|
||||
}
|
||||
|
||||
public void InputHdmi1()
|
||||
{
|
||||
SendBytes(new byte[] { 0x07, ID, 0x02, 0x4D, 0x49, 0x4E, InputHdmi1Value, 0x08, 0x0d });
|
||||
}
|
||||
|
||||
public void InputHdmi2()
|
||||
{
|
||||
SendBytes(new byte[] { 0x07, ID, 0x02, 0x4D, 0x49, 0x4E, InputHdmi2Value, 0x08, 0x0d });
|
||||
}
|
||||
|
||||
public void InputHdmi3()
|
||||
{
|
||||
SendBytes(new byte[] { 0x07, ID, 0x02, 0x4D, 0x49, 0x4E, InputHdmi3Value, 0x08, 0x0d });
|
||||
}
|
||||
|
||||
public void InputHdmi4()
|
||||
{
|
||||
SendBytes(new byte[] { 0x07, ID, 0x02, 0x4D, 0x49, 0x4E, InputHdmi4Value, 0x08, 0x0d });
|
||||
}
|
||||
|
||||
public void InputHdmi5()
|
||||
{
|
||||
SendBytes(new byte[] { 0x07, ID, 0x02, 0x4D, 0x49, 0x4E, InputHdmi5Value, 0x08, 0x0d });
|
||||
}
|
||||
|
||||
public void InputDisplayPort1()
|
||||
{
|
||||
SendBytes(new byte[] { 0x07, ID, 0x02, 0x4D, 0x49, 0x4E, InputDisplayPort1Value, 0x08, 0x0d });
|
||||
}
|
||||
|
||||
public void InputVga1()
|
||||
{
|
||||
SendBytes(new byte[] { 0x07, ID, 0x02, 0x4D, 0x49, 0x4E, InputVga1Value, 0x08, 0x0d });
|
||||
}
|
||||
|
||||
public void InputIpcOps()
|
||||
{
|
||||
SendBytes(new byte[] { 0x07, ID, 0x02, 0x4D, 0x49, 0x4E, InputIpcOpsValue, 0x08, 0x0d });
|
||||
}
|
||||
|
||||
public void InputMediaPlayer()
|
||||
{
|
||||
SendBytes(new byte[] { 0x07, ID, 0x02, 0x4D, 0x49, 0x4E, InputMediaPlayerValue, 0x08, 0x0d });
|
||||
}
|
||||
|
||||
public void InputGet()
|
||||
{
|
||||
SendBytes(new byte[] { 0x07, ID, 0x01, 0x4D, 0x49, 0x4E, 0x08, 0x0d });
|
||||
}
|
||||
|
||||
public void VolumeGet()
|
||||
{
|
||||
SendBytes(new byte[] { 0x07, ID, 0x01, 0x56, 0x4F, 0x4C, 0x08, 0x0d });
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Executes a switch, turning on display if necessary.
|
||||
/// </summary>
|
||||
/// <param name="selector"></param>
|
||||
public override void ExecuteSwitch(object selector)
|
||||
{
|
||||
//if (!(selector is Action))
|
||||
// Debug.Console(1, this, "WARNING: ExecuteSwitch cannot handle type {0}", selector.GetType());
|
||||
|
||||
if (_PowerIsOn)
|
||||
(selector as Action)();
|
||||
else // if power is off, wait until we get on FB to send it.
|
||||
{
|
||||
// One-time event handler to wait for power on before executing switch
|
||||
EventHandler<FeedbackEventArgs> handler = null; // necessary to allow reference inside lambda to handler
|
||||
handler = (o, a) =>
|
||||
{
|
||||
if (!_IsWarmingUp) // Done warming
|
||||
{
|
||||
IsWarmingUpFeedback.OutputChange -= handler;
|
||||
(selector as Action)();
|
||||
}
|
||||
};
|
||||
IsWarmingUpFeedback.OutputChange += handler; // attach and wait for on FB
|
||||
PowerOn();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the level to the range of the display and sends the command
|
||||
/// </summary>
|
||||
/// <param name="level"></param>
|
||||
public void SetVolume(ushort level)
|
||||
{
|
||||
_LastVolumeSent = level;
|
||||
var scaled = (int)NumericalHelpers.Scale(level, 0, 65535, 0, 100);
|
||||
// The inputs to Scale ensure that byte won't overflow
|
||||
SendBytes(new byte[] { 0x07, ID, 0x02, 0x56, 0x4F, 0x4C, Convert.ToByte(scaled), 0x08, 0x0d });
|
||||
}
|
||||
|
||||
#region IBasicVolumeWithFeedback Members
|
||||
|
||||
public IntFeedback VolumeLevelFeedback { get; private set; }
|
||||
|
||||
public BoolFeedback MuteFeedback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void MuteOff()
|
||||
{
|
||||
SetVolume(_PreMuteVolumeLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void MuteOn()
|
||||
{
|
||||
_PreMuteVolumeLevel = _VolumeLevelForSig;
|
||||
|
||||
SetVolume(0);
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
/////
|
||||
///// </summary>
|
||||
//public void MuteGet()
|
||||
//{
|
||||
// SendBytes(new byte[] { 0x07, ID, 0x01, });
|
||||
//}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IBasicVolumeControls Members
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void MuteToggle()
|
||||
{
|
||||
if (_IsMuted)
|
||||
MuteOff();
|
||||
else
|
||||
MuteOn();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void VolumeDown(bool pressRelease)
|
||||
{
|
||||
if (pressRelease)
|
||||
{
|
||||
VolumeIncrementer.StartDown();
|
||||
VolumeIsRamping = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VolumeIsRamping = false;
|
||||
VolumeIncrementer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void VolumeUp(bool pressRelease)
|
||||
{
|
||||
if (pressRelease)
|
||||
{
|
||||
VolumeIncrementer.StartUp();
|
||||
VolumeIsRamping = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VolumeIsRamping = false;
|
||||
VolumeIncrementer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Displays
|
||||
{
|
||||
public abstract class ComTcpDisplayBase : DisplayBase, IPower
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the communication method for this - swaps out event handlers and output handlers
|
||||
/// </summary>
|
||||
public IBasicCommunication CommunicationMethod
|
||||
{
|
||||
get { return _CommunicationMethod; }
|
||||
set
|
||||
{
|
||||
if (_CommunicationMethod != null)
|
||||
_CommunicationMethod.BytesReceived -= this.CommunicationMethod_BytesReceived;
|
||||
// Outputs???
|
||||
_CommunicationMethod = value;
|
||||
if (_CommunicationMethod != null)
|
||||
_CommunicationMethod.BytesReceived += this.CommunicationMethod_BytesReceived;
|
||||
// Outputs?
|
||||
}
|
||||
}
|
||||
IBasicCommunication _CommunicationMethod;
|
||||
|
||||
public ComTcpDisplayBase(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected abstract void CommunicationMethod_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharpPro;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Displays
|
||||
{
|
||||
public class DisplayDeviceFactory
|
||||
{
|
||||
public static IKeyed GetDevice(DeviceConfig dc)
|
||||
{
|
||||
var key = dc.Key;
|
||||
var name = dc.Name;
|
||||
var type = dc.Type;
|
||||
var properties = dc.Properties;
|
||||
|
||||
var typeName = dc.Type.ToLower();
|
||||
|
||||
try
|
||||
{
|
||||
if (typeName == "necmpsx")
|
||||
{
|
||||
var comm = CommFactory.CreateCommForDevice(dc);
|
||||
if (comm != null)
|
||||
return new NecPSXMDisplay(dc.Key, dc.Name, comm);
|
||||
}
|
||||
if (typeName == "panasonicthef")
|
||||
{
|
||||
var comm = CommFactory.CreateCommForDevice(dc);
|
||||
if (comm != null)
|
||||
return new PanasonicThefDisplay(dc.Key, dc.Name, comm);
|
||||
}
|
||||
else if(typeName == "samsungmdc")
|
||||
{
|
||||
var comm = CommFactory.CreateCommForDevice(dc);
|
||||
if (comm != null)
|
||||
return new SamsungMDC(dc.Key, dc.Name, comm, dc.Properties["id"].Value<string>());
|
||||
}
|
||||
if (typeName == "avocorvtf")
|
||||
{
|
||||
var comm = CommFactory.CreateCommForDevice(dc);
|
||||
if (comm != null)
|
||||
return new AvocorDisplay(dc.Key, dc.Name, comm, null);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, "Displays factory: Exception creating device type {0}, key {1}: \nCONFIG JSON: {2} \nERROR: {3}\n\n",
|
||||
dc.Type, dc.Key, JsonConvert.SerializeObject(dc), e);
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Displays
|
||||
{
|
||||
public interface IInputHdmi1 { void InputHdmi1(); }
|
||||
public interface IInputHdmi2 { void InputHdmi2(); }
|
||||
public interface IInputHdmi3 { void InputHdmi3(); }
|
||||
public interface IInputHdmi4 { void InputHdmi4(); }
|
||||
public interface IInputDisplayPort1 { void InputDisplayPort1(); }
|
||||
public interface IInputDisplayPort2 { void InputDisplayPort2(); }
|
||||
public interface IInputVga1 { void InputVga1(); }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,356 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Displays
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class NecPSXMDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, ICommunicationMonitor
|
||||
{
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
public CommunicationGather PortGather { get; private set; }
|
||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||
|
||||
#region Command constants
|
||||
public const string InputGetCmd = "\x01\x30\x41\x30\x43\x30\x36\x02\x30\x30\x36\x30\x03\x03\x0D";
|
||||
public const string Hdmi1Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x31\x31\x03\x72\x0d";
|
||||
public const string Hdmi2Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x31\x32\x03\x71\x0D";
|
||||
public const string Hdmi3Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x38\x32\x03\x78\x0D";
|
||||
public const string Hdmi4Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x38\x33\x03\x79\x0D";
|
||||
public const string Dp1Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x46\x03\x04\x0D";
|
||||
public const string Dp2Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x31\x30\x03\x73\x0D";
|
||||
public const string Dvi1Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x33\x03\x71\x0d";
|
||||
public const string Video1Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x35\x03\x77\x0D";
|
||||
public const string VgaCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x31\x03\x73\x0D";
|
||||
public const string RgbCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x32\x03\x70\x0D";
|
||||
|
||||
public const string PowerOnCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x30\x33\x44\x36\x30\x30\x30\x31\x03\x73\x0D";
|
||||
public const string PowerOffCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x30\x33\x44\x36\x30\x30\x30\x34\x03\x76\x0D";
|
||||
public const string PowerToggleIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x30\x33\x30\x33\x03\x02\x0D";
|
||||
|
||||
public const string MuteOffCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x38\x44\x30\x30\x30\x30\x03\x08\x0D";
|
||||
public const string MuteOnCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x38\x44\x30\x30\x30\x31\x03\x09\x0D";
|
||||
public const string MuteToggleIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x31\x42\x30\x33\x03\x72\x0D";
|
||||
public const string MuteGetCmd = "\x01\x30\x41\x30\x43\x30\x36\x02\x30\x30\x38\x44\x03\x79\x0D";
|
||||
|
||||
public const string VolumeGetCmd = "\x01\x30\x41\x30\x43\x30\x36\x02\x30\x30\x36\x32\x03\x01\x0D";
|
||||
public const string VolumeLevelPartialCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x32"; //\x46\x46\x46\x46\x03\xNN\x0D
|
||||
public const string VolumeUpCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x31\x30\x41\x44\x30\x30\x30\x31\x03\x71\x0D";
|
||||
public const string VolumeDownCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x31\x30\x41\x44\x30\x30\x30\x32\x03\x72\x0D";
|
||||
|
||||
public const string MenuIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x32\x30\x30\x33\x03\x03\x0D";
|
||||
public const string UpIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x31\x35\x30\x33\x03\x05\x0D";
|
||||
public const string DownIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x31\x34\x30\x33\x03\x04\x0D";
|
||||
public const string LeftIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x32\x31\x30\x33\x03\x02\x0D";
|
||||
public const string RightIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x32\x32\x30\x33\x03\x01\x0D";
|
||||
public const string SelectIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x32\x33\x30\x33\x03\x00\x0D";
|
||||
public const string ExitIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x31\x46\x30\x33\x03\x76\x0D";
|
||||
#endregion
|
||||
|
||||
bool _PowerIsOn;
|
||||
bool _IsWarmingUp;
|
||||
bool _IsCoolingDown;
|
||||
ushort _VolumeLevel;
|
||||
bool _IsMuted;
|
||||
|
||||
protected override Func<bool> PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } }
|
||||
protected override Func<bool> IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } }
|
||||
protected override Func<bool> IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } }
|
||||
protected override Func<string> CurrentInputFeedbackFunc { get { return () => "Not Implemented"; } }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for IBasicCommunication
|
||||
/// </summary>
|
||||
public NecPSXMDisplay(string key, string name, IBasicCommunication comm)
|
||||
: base(key, name)
|
||||
{
|
||||
Communication = comm;
|
||||
Init();
|
||||
}
|
||||
/// <summary>
|
||||
/// Constructor for TCP
|
||||
/// </summary>
|
||||
public NecPSXMDisplay(string key, string name, string hostname, int port)
|
||||
: base(key, name)
|
||||
{
|
||||
Communication = new GenericTcpIpClient(key + "-tcp", hostname, port, 5000);
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for COM
|
||||
/// </summary>
|
||||
public NecPSXMDisplay(string key, string name, ComPort port, ComPort.ComPortSpec spec)
|
||||
: base(key, name)
|
||||
{
|
||||
Communication = new ComPortController(key + "-com", port, spec);
|
||||
Init();
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
PortGather = new CommunicationGather(Communication, '\x0d');
|
||||
PortGather.LineReceived += this.Port_LineReceived;
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, "xx\x0d");
|
||||
|
||||
InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi1), this));
|
||||
InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi2), this));
|
||||
InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi3), this));
|
||||
InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi4), this));
|
||||
InputPorts.Add(new RoutingInputPort(RoutingPortNames.DisplayPortIn1, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.DisplayPort, new Action(InputDisplayPort1), this));
|
||||
InputPorts.Add(new RoutingInputPort(RoutingPortNames.DisplayPortIn2, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.DisplayPort, new Action(InputDisplayPort2), this));
|
||||
InputPorts.Add(new RoutingInputPort(RoutingPortNames.DviIn, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Dvi, new Action(InputDvi1), this));
|
||||
InputPorts.Add(new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Composite, new Action(InputVideo1), this));
|
||||
InputPorts.Add(new RoutingInputPort(RoutingPortNames.VgaIn, eRoutingSignalType.Video,
|
||||
eRoutingPortConnectionType.Vga, new Action(InputVga), this));
|
||||
InputPorts.Add(new RoutingInputPort(RoutingPortNames.RgbIn, eRoutingSignalType.Video,
|
||||
eRoutingPortConnectionType.Rgb, new Action(new Action(InputRgb)), this));
|
||||
|
||||
VolumeLevelFeedback = new IntFeedback(() => { return _VolumeLevel; });
|
||||
MuteFeedback = new BoolFeedback(() => _IsMuted);
|
||||
|
||||
// new BoolCueActionPair(CommonBoolCue.Menu, b => { if(b) Send(MenuIrCmd); }),
|
||||
// new BoolCueActionPair(CommonBoolCue.Up, b => { if(b) Send(UpIrCmd); }),
|
||||
// new BoolCueActionPair(CommonBoolCue.Down, b => { if(b) Send(DownIrCmd); }),
|
||||
// new BoolCueActionPair(CommonBoolCue.Left, b => { if(b) Send(LeftIrCmd); }),
|
||||
// new BoolCueActionPair(CommonBoolCue.Right, b => { if(b) Send(RightIrCmd); }),
|
||||
// new BoolCueActionPair(CommonBoolCue.Select, b => { if(b) Send(SelectIrCmd); }),
|
||||
// new BoolCueActionPair(CommonBoolCue.Exit, b => { if(b) Send(ExitIrCmd); }),
|
||||
//};
|
||||
}
|
||||
|
||||
~NecPSXMDisplay()
|
||||
{
|
||||
PortGather = null;
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
Communication.Connect();
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
CommunicationMonitor.Start();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override FeedbackCollection<Feedback> Feedbacks
|
||||
{
|
||||
get
|
||||
{
|
||||
var list = base.Feedbacks;
|
||||
list.AddRange(new List<Feedback>
|
||||
{
|
||||
|
||||
});
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "Received: '{0}'", ComTextHelper.GetEscapedText(args.Text));
|
||||
|
||||
if (args.Text=="DO SOMETHING HERE EVENTUALLY")
|
||||
{
|
||||
_IsMuted = true;
|
||||
MuteFeedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void AppendChecksumAndSend(string s)
|
||||
{
|
||||
int x = 0;
|
||||
for (int i = 1; i < s.Length; i++)
|
||||
x = x ^ s[i];
|
||||
|
||||
string send = s + (char)x + '\x0d';
|
||||
Send(send);
|
||||
}
|
||||
|
||||
void Send(string s)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "Send: '{0}'", ComTextHelper.GetEscapedText(s));
|
||||
Communication.SendText(s);
|
||||
}
|
||||
|
||||
|
||||
public override void PowerOn()
|
||||
{
|
||||
Send(PowerOnCmd);
|
||||
if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
|
||||
{
|
||||
_IsWarmingUp = true;
|
||||
IsWarmingUpFeedback.FireUpdate();
|
||||
// Fake power-up cycle
|
||||
WarmupTimer = new CTimer(o =>
|
||||
{
|
||||
_IsWarmingUp = false;
|
||||
_PowerIsOn = true;
|
||||
IsWarmingUpFeedback.FireUpdate();
|
||||
PowerIsOnFeedback.FireUpdate();
|
||||
}, WarmupTime);
|
||||
}
|
||||
}
|
||||
|
||||
public override void PowerOff()
|
||||
{
|
||||
// If a display has unreliable-power off feedback, just override this and
|
||||
// remove this check.
|
||||
if (PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
|
||||
{
|
||||
Send(PowerOffCmd);
|
||||
_IsCoolingDown = true;
|
||||
_PowerIsOn = false;
|
||||
PowerIsOnFeedback.FireUpdate();
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
// Fake cool-down cycle
|
||||
CooldownTimer = new CTimer(o =>
|
||||
{
|
||||
Debug.Console(2, this, "Cooldown timer ending");
|
||||
_IsCoolingDown = false;
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
}, CooldownTime);
|
||||
}
|
||||
}
|
||||
|
||||
public override void PowerToggle()
|
||||
{
|
||||
if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue)
|
||||
PowerOff();
|
||||
else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue)
|
||||
PowerOn();
|
||||
}
|
||||
|
||||
public void InputHdmi1()
|
||||
{
|
||||
Send(Hdmi1Cmd);
|
||||
}
|
||||
|
||||
public void InputHdmi2()
|
||||
{
|
||||
Send(Hdmi2Cmd);
|
||||
}
|
||||
|
||||
public void InputHdmi3()
|
||||
{
|
||||
Send(Hdmi3Cmd);
|
||||
}
|
||||
|
||||
public void InputHdmi4()
|
||||
{
|
||||
Send(Hdmi4Cmd);
|
||||
}
|
||||
|
||||
public void InputDisplayPort1()
|
||||
{
|
||||
Send(Dp1Cmd);
|
||||
}
|
||||
|
||||
public void InputDisplayPort2()
|
||||
{
|
||||
Send(Dp2Cmd);
|
||||
}
|
||||
|
||||
public void InputDvi1()
|
||||
{
|
||||
Send(Dvi1Cmd);
|
||||
}
|
||||
|
||||
public void InputVideo1()
|
||||
{
|
||||
Send(Video1Cmd);
|
||||
}
|
||||
|
||||
public void InputVga()
|
||||
{
|
||||
Send(VgaCmd);
|
||||
}
|
||||
|
||||
public void InputRgb()
|
||||
{
|
||||
Send(RgbCmd);
|
||||
}
|
||||
|
||||
public override void ExecuteSwitch(object selector)
|
||||
{
|
||||
if (selector is Action)
|
||||
(selector as Action).Invoke();
|
||||
else
|
||||
Debug.Console(1, this, "WARNING: ExecuteSwitch cannot handle type {0}", selector.GetType());
|
||||
//Send((string)selector);
|
||||
}
|
||||
|
||||
void SetVolume(ushort level)
|
||||
{
|
||||
var levelString = string.Format("{0}{1:X4}\x03", VolumeLevelPartialCmd, level);
|
||||
AppendChecksumAndSend(levelString);
|
||||
//Debug.Console(2, this, "Volume:{0}", ComTextHelper.GetEscapedText(levelString));
|
||||
_VolumeLevel = level;
|
||||
VolumeLevelFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
#region IBasicVolumeWithFeedback Members
|
||||
|
||||
public IntFeedback VolumeLevelFeedback { get; private set; }
|
||||
|
||||
public BoolFeedback MuteFeedback { get; private set; }
|
||||
|
||||
public void MuteOff()
|
||||
{
|
||||
Send(MuteOffCmd);
|
||||
}
|
||||
|
||||
public void MuteOn()
|
||||
{
|
||||
Send(MuteOnCmd);
|
||||
}
|
||||
|
||||
void IBasicVolumeWithFeedback.SetVolume(ushort level)
|
||||
{
|
||||
SetVolume(level);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IBasicVolumeControls Members
|
||||
|
||||
public void MuteToggle()
|
||||
{
|
||||
Send(MuteToggleIrCmd);
|
||||
}
|
||||
|
||||
public void VolumeDown(bool pressRelease)
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
//#warning need incrementer for these
|
||||
SetVolume(_VolumeLevel++);
|
||||
}
|
||||
|
||||
public void VolumeUp(bool pressRelease)
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
SetVolume(_VolumeLevel--);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Displays
|
||||
{
|
||||
public class NecPaSeriesProjector : ComTcpDisplayBase
|
||||
{
|
||||
public readonly IntFeedback Lamp1RemainingPercent;
|
||||
int _Lamp1RemainingPercent;
|
||||
public readonly IntFeedback Lamp2RemainingPercent;
|
||||
int _Lamp2RemainingPercent;
|
||||
protected override Func<bool> PowerIsOnFeedbackFunc
|
||||
{
|
||||
get { return () => _PowerIsOn; }
|
||||
}
|
||||
bool _PowerIsOn;
|
||||
|
||||
protected override Func<bool> IsCoolingDownFeedbackFunc
|
||||
{
|
||||
get { return () => false; }
|
||||
}
|
||||
|
||||
protected override Func<bool> IsWarmingUpFeedbackFunc
|
||||
{
|
||||
get { return () => false; }
|
||||
}
|
||||
|
||||
public override void PowerToggle()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void ExecuteSwitch(object selector)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Dictionary<string, string> InputMap;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public NecPaSeriesProjector(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
Lamp1RemainingPercent = new IntFeedback("Lamp1RemainingPercent", () => _Lamp1RemainingPercent);
|
||||
Lamp2RemainingPercent = new IntFeedback("Lamp2RemainingPercent", () => _Lamp2RemainingPercent);
|
||||
|
||||
InputMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{ "computer1", "\x02\x03\x00\x00\x02\x01\x01\x09" },
|
||||
{ "computer2", "\x02\x03\x00\x00\x02\x01\x02\x0a" },
|
||||
{ "computer3", "\x02\x03\x00\x00\x02\x01\x03\x0b" },
|
||||
{ "hdmi", "\x02\x03\x00\x00\x02\x01\x1a\x22" },
|
||||
{ "dp", "\x02\x03\x00\x00\x02\x01\x1b\x23" },
|
||||
{ "video", "\x02\x03\x00\x00\x02\x01\x06\x0e" },
|
||||
{ "viewer", "\x02\x03\x00\x00\x02\x01\x1f\x27" },
|
||||
{ "network", "\x02\x03\x00\x00\x02\x01\x20\x28" },
|
||||
};
|
||||
}
|
||||
|
||||
void IsConnected_OutputChange(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void SetEnable(bool state)
|
||||
{
|
||||
var tcp = CommunicationMethod as GenericTcpIpClient;
|
||||
if (tcp != null)
|
||||
{
|
||||
tcp.Connect();
|
||||
}
|
||||
}
|
||||
|
||||
public override void PowerOn()
|
||||
{
|
||||
SendText("\x02\x00\x00\x00\x00\x02");
|
||||
}
|
||||
|
||||
public override void PowerOff()
|
||||
{
|
||||
SendText("\x02\x01\x00\x00\x00\x03");
|
||||
}
|
||||
|
||||
public void PictureMuteOn()
|
||||
{
|
||||
SendText("\x02\x10\x00\x00\x00\x12");
|
||||
}
|
||||
|
||||
public void PictureMuteOff()
|
||||
{
|
||||
SendText("\x02\x11\x00\x00\x00\x13");
|
||||
}
|
||||
|
||||
public void GetRunningStatus()
|
||||
{
|
||||
SendText("\x00\x85\x00\x00\x01\x01\x87");
|
||||
}
|
||||
|
||||
public void GetLampRemaining(int lampNum)
|
||||
{
|
||||
if (!_PowerIsOn) return;
|
||||
|
||||
var bytes = new byte[]{0x03,0x96,0x00,0x00,0x02,0x00,0x04};
|
||||
if (lampNum == 2)
|
||||
bytes[5] = 0x01;
|
||||
SendBytes(AppendChecksum(bytes));
|
||||
}
|
||||
|
||||
public void SelectInput(string inputKey)
|
||||
{
|
||||
if (InputMap.ContainsKey(inputKey))
|
||||
SendText(InputMap[inputKey]);
|
||||
}
|
||||
|
||||
void SendText(string text)
|
||||
{
|
||||
if (CommunicationMethod != null)
|
||||
CommunicationMethod.SendText(text);
|
||||
}
|
||||
|
||||
void SendBytes(byte[] bytes)
|
||||
{
|
||||
if (CommunicationMethod != null)
|
||||
CommunicationMethod.SendBytes(bytes);
|
||||
}
|
||||
|
||||
byte[] AppendChecksum(byte[] bytes)
|
||||
{
|
||||
byte sum = unchecked((byte)bytes.Sum(x => (int)x));
|
||||
var retVal = new byte[bytes.Length + 1];
|
||||
bytes.CopyTo(retVal, 0);
|
||||
retVal[retVal.Length - 1] = sum;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
protected override void CommunicationMethod_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs args)
|
||||
{
|
||||
var bytes = args.Bytes;
|
||||
ParseBytes(args.Bytes);
|
||||
}
|
||||
|
||||
void ParseBytes(byte[] bytes)
|
||||
{
|
||||
if (bytes[0] == 0x22)
|
||||
{
|
||||
// Power on
|
||||
if (bytes[1] == 0x00)
|
||||
{
|
||||
_PowerIsOn = true;
|
||||
PowerIsOnFeedback.FireUpdate();
|
||||
}
|
||||
// Power off
|
||||
else if (bytes[1] == 0x01)
|
||||
{
|
||||
_PowerIsOn = false;
|
||||
PowerIsOnFeedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
// Running Status
|
||||
else if (bytes[0] == 0x20 && bytes[1] == 0x85 && bytes[4] == 0x10)
|
||||
{
|
||||
var operationStates = new Dictionary<int, string>
|
||||
{
|
||||
{ 0x00, "Standby" },
|
||||
{ 0x04, "Power On" },
|
||||
{ 0x05, "Cooling" },
|
||||
{ 0x06, "Standby (error)" },
|
||||
{ 0x0f, "Standby (power saving" },
|
||||
{ 0x10, "Network Standby" },
|
||||
{ 0xff, "Not supported" }
|
||||
};
|
||||
|
||||
var newPowerIsOn = bytes[7] == 0x01;
|
||||
if (newPowerIsOn != _PowerIsOn)
|
||||
{
|
||||
_PowerIsOn = newPowerIsOn;
|
||||
PowerIsOnFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
Debug.Console(2, this, "PowerIsOn={0}\rCooling={1}\rPowering on/off={2}\rStatus={3}",
|
||||
_PowerIsOn,
|
||||
bytes[8] == 0x01,
|
||||
bytes[9] == 0x01,
|
||||
operationStates[bytes[10]]);
|
||||
|
||||
}
|
||||
// Lamp remaining
|
||||
else if (bytes[0] == 0x23 && bytes[1] == 0x96 && bytes[4] == 0x06 && bytes[6] == 0x04)
|
||||
{
|
||||
var newValue = bytes[7];
|
||||
if (bytes[5] == 0x00)
|
||||
{
|
||||
if (newValue != _Lamp1RemainingPercent)
|
||||
{
|
||||
_Lamp1RemainingPercent = newValue;
|
||||
Lamp1RemainingPercent.FireUpdate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newValue != _Lamp2RemainingPercent)
|
||||
{
|
||||
_Lamp2RemainingPercent = newValue;
|
||||
Lamp2RemainingPercent.FireUpdate();
|
||||
}
|
||||
}
|
||||
Debug.Console(0, this, "Lamp {0}, {1}% remaining", (bytes[5] + 1), bytes[7]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#region INonStandardControls Members
|
||||
|
||||
public Dictionary<Cue, Action<object>> GetNonStandardControls()
|
||||
{
|
||||
return new Dictionary<Cue, Action<object>>
|
||||
{
|
||||
{ CommonBoolCue.PowerOn, o => PowerOn() },
|
||||
{ CommonBoolCue.PowerOff, o => PowerOff() },
|
||||
{ Cue.BoolCue("PictureMute", 0), o =>
|
||||
{
|
||||
if((bool)o)
|
||||
PictureMuteOn();
|
||||
else
|
||||
PictureMuteOff(); } },
|
||||
{ Cue.UShortCue("GetLampRemaining", 0), o => GetLampRemaining((int) o) },
|
||||
{ Cue.StringCue("SelectInput", 0), o => SelectInput((String)o) }
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Displays
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class PanasonicThefDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, ICommunicationMonitor
|
||||
{
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
public CommunicationGather PortGather { get; private set; }
|
||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||
|
||||
#region Command constants
|
||||
public const string InputGetCmd = "\x02QMI\x03";
|
||||
public const string Hdmi1Cmd = "\x02IMS:HM1\x03";
|
||||
public const string Hdmi2Cmd = "\x02IMS:HM2\x03";
|
||||
public const string Hdmi3Cmd = "";
|
||||
public const string Hdmi4Cmd = "";
|
||||
public const string Dp1Cmd = "";
|
||||
public const string Dp2Cmd = "";
|
||||
public const string Dvi1Cmd = "\x02IMS:DV1";
|
||||
public const string Video1Cmd = "";
|
||||
public const string VgaCmd = "";
|
||||
public const string RgbCmd = "";
|
||||
|
||||
public const string PowerOnCmd = "\x02PON\x03";
|
||||
public const string PowerOffCmd = "\x02POF\x03";
|
||||
public const string PowerToggleIrCmd = "";
|
||||
|
||||
public const string MuteOffCmd = "\x02AMT:0\x03";
|
||||
public const string MuteOnCmd = "\x02AMT:1\x03";
|
||||
public const string MuteToggleIrCmd = "\x02AMT\x03";
|
||||
public const string MuteGetCmd = "\x02QAM\x03";
|
||||
|
||||
public const string VolumeGetCmd = "\x02QAV\x03";
|
||||
public const string VolumeLevelPartialCmd = "\x02AVL:"; //
|
||||
public const string VolumeUpCmd = "\x02AUU\x03";
|
||||
public const string VolumeDownCmd = "\x02AUD\x03";
|
||||
|
||||
public const string MenuIrCmd = "";
|
||||
public const string UpIrCmd = "";
|
||||
public const string DownIrCmd = "";
|
||||
public const string LeftIrCmd = "";
|
||||
public const string RightIrCmd = "";
|
||||
public const string SelectIrCmd = "";
|
||||
public const string ExitIrCmd = "";
|
||||
#endregion
|
||||
|
||||
bool _PowerIsOn;
|
||||
bool _IsWarmingUp;
|
||||
bool _IsCoolingDown;
|
||||
ushort _VolumeLevel;
|
||||
bool _IsMuted;
|
||||
|
||||
protected override Func<bool> PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } }
|
||||
protected override Func<bool> IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } }
|
||||
protected override Func<bool> IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } }
|
||||
protected override Func<string> CurrentInputFeedbackFunc { get { return () => "Not Implemented"; } }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for IBasicCommunication
|
||||
/// </summary>
|
||||
public PanasonicThefDisplay(string key, string name, IBasicCommunication comm)
|
||||
: base(key, name)
|
||||
{
|
||||
Communication = comm;
|
||||
Init();
|
||||
}
|
||||
/// <summary>
|
||||
/// Constructor for TCP
|
||||
/// </summary>
|
||||
public PanasonicThefDisplay(string key, string name, string hostname, int port)
|
||||
: base(key, name)
|
||||
{
|
||||
Communication = new GenericTcpIpClient(key + "-tcp", hostname, port, 5000);
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for COM
|
||||
/// </summary>
|
||||
public PanasonicThefDisplay(string key, string name, ComPort port, ComPort.ComPortSpec spec)
|
||||
: base(key, name)
|
||||
{
|
||||
Communication = new ComPortController(key + "-com", port, spec);
|
||||
Init();
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
PortGather = new CommunicationGather(Communication, '\x0d');
|
||||
PortGather.LineReceived += this.Port_LineReceived;
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, "\x02QPW\x03"); // Query Power
|
||||
|
||||
InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi1), this));
|
||||
InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi2), this));
|
||||
|
||||
InputPorts.Add(new RoutingInputPort(RoutingPortNames.DviIn, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Dvi, new Action(InputDvi1), this));
|
||||
InputPorts.Add(new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Composite, new Action(InputVideo1), this));
|
||||
InputPorts.Add(new RoutingInputPort(RoutingPortNames.VgaIn, eRoutingSignalType.Video,
|
||||
eRoutingPortConnectionType.Vga, new Action(InputVga), this));
|
||||
|
||||
|
||||
VolumeLevelFeedback = new IntFeedback(() => { return _VolumeLevel; });
|
||||
MuteFeedback = new BoolFeedback(() => _IsMuted);
|
||||
|
||||
// new BoolCueActionPair(CommonBoolCue.Menu, b => { if(b) Send(MenuIrCmd); }),
|
||||
// new BoolCueActionPair(CommonBoolCue.Up, b => { if(b) Send(UpIrCmd); }),
|
||||
// new BoolCueActionPair(CommonBoolCue.Down, b => { if(b) Send(DownIrCmd); }),
|
||||
// new BoolCueActionPair(CommonBoolCue.Left, b => { if(b) Send(LeftIrCmd); }),
|
||||
// new BoolCueActionPair(CommonBoolCue.Right, b => { if(b) Send(RightIrCmd); }),
|
||||
// new BoolCueActionPair(CommonBoolCue.Select, b => { if(b) Send(SelectIrCmd); }),
|
||||
// new BoolCueActionPair(CommonBoolCue.Exit, b => { if(b) Send(ExitIrCmd); }),
|
||||
//};
|
||||
}
|
||||
|
||||
~PanasonicThefDisplay()
|
||||
{
|
||||
PortGather = null;
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
Communication.Connect();
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
CommunicationMonitor.Start();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override FeedbackCollection<Feedback> Feedbacks
|
||||
{
|
||||
get
|
||||
{
|
||||
var list = base.Feedbacks;
|
||||
list.AddRange(new List<Feedback>
|
||||
{
|
||||
|
||||
});
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "Received: '{0}'", ComTextHelper.GetEscapedText(args.Text));
|
||||
|
||||
if (args.Text=="DO SOMETHING HERE EVENTUALLY")
|
||||
{
|
||||
_IsMuted = true;
|
||||
MuteFeedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void Send(string s)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "Send: '{0}'", ComTextHelper.GetEscapedText(s));
|
||||
Communication.SendText(s);
|
||||
}
|
||||
|
||||
|
||||
public override void PowerOn()
|
||||
{
|
||||
Send(PowerOnCmd);
|
||||
if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
|
||||
{
|
||||
_IsWarmingUp = true;
|
||||
IsWarmingUpFeedback.FireUpdate();
|
||||
// Fake power-up cycle
|
||||
WarmupTimer = new CTimer(o =>
|
||||
{
|
||||
_IsWarmingUp = false;
|
||||
_PowerIsOn = true;
|
||||
IsWarmingUpFeedback.FireUpdate();
|
||||
PowerIsOnFeedback.FireUpdate();
|
||||
}, WarmupTime);
|
||||
}
|
||||
}
|
||||
|
||||
public override void PowerOff()
|
||||
{
|
||||
// If a display has unreliable-power off feedback, just override this and
|
||||
// remove this check.
|
||||
if (PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
|
||||
{
|
||||
Send(PowerOffCmd);
|
||||
_IsCoolingDown = true;
|
||||
_PowerIsOn = false;
|
||||
PowerIsOnFeedback.FireUpdate();
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
// Fake cool-down cycle
|
||||
CooldownTimer = new CTimer(o =>
|
||||
{
|
||||
Debug.Console(2, this, "Cooldown timer ending");
|
||||
_IsCoolingDown = false;
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
}, CooldownTime);
|
||||
}
|
||||
}
|
||||
|
||||
public override void PowerToggle()
|
||||
{
|
||||
if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue)
|
||||
PowerOff();
|
||||
else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue)
|
||||
PowerOn();
|
||||
}
|
||||
|
||||
public void InputHdmi1()
|
||||
{
|
||||
Send(Hdmi1Cmd);
|
||||
}
|
||||
|
||||
public void InputHdmi2()
|
||||
{
|
||||
Send(Hdmi2Cmd);
|
||||
}
|
||||
|
||||
public void InputHdmi3()
|
||||
{
|
||||
Send(Hdmi3Cmd);
|
||||
}
|
||||
|
||||
public void InputHdmi4()
|
||||
{
|
||||
Send(Hdmi4Cmd);
|
||||
}
|
||||
|
||||
public void InputDisplayPort1()
|
||||
{
|
||||
Send(Dp1Cmd);
|
||||
}
|
||||
|
||||
public void InputDisplayPort2()
|
||||
{
|
||||
Send(Dp2Cmd);
|
||||
}
|
||||
|
||||
public void InputDvi1()
|
||||
{
|
||||
Send(Dvi1Cmd);
|
||||
}
|
||||
|
||||
public void InputVideo1()
|
||||
{
|
||||
Send(Video1Cmd);
|
||||
}
|
||||
|
||||
public void InputVga()
|
||||
{
|
||||
Send(VgaCmd);
|
||||
}
|
||||
|
||||
public void InputRgb()
|
||||
{
|
||||
Send(RgbCmd);
|
||||
}
|
||||
|
||||
public override void ExecuteSwitch(object selector)
|
||||
{
|
||||
if (selector is Action)
|
||||
(selector as Action).Invoke();
|
||||
else
|
||||
Debug.Console(1, this, "WARNING: ExecuteSwitch cannot handle type {0}", selector.GetType());
|
||||
//Send((string)selector);
|
||||
}
|
||||
|
||||
void SetVolume(ushort level)
|
||||
{
|
||||
var levelString = string.Format("{0}{1:X3}\x03", VolumeLevelPartialCmd, level);
|
||||
|
||||
//Debug.Console(2, this, "Volume:{0}", ComTextHelper.GetEscapedText(levelString));
|
||||
_VolumeLevel = level;
|
||||
VolumeLevelFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
#region IBasicVolumeWithFeedback Members
|
||||
|
||||
public IntFeedback VolumeLevelFeedback { get; private set; }
|
||||
|
||||
public BoolFeedback MuteFeedback { get; private set; }
|
||||
|
||||
public void MuteOff()
|
||||
{
|
||||
Send(MuteOffCmd);
|
||||
}
|
||||
|
||||
public void MuteOn()
|
||||
{
|
||||
Send(MuteOnCmd);
|
||||
}
|
||||
|
||||
void IBasicVolumeWithFeedback.SetVolume(ushort level)
|
||||
{
|
||||
SetVolume(level);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IBasicVolumeControls Members
|
||||
|
||||
public void MuteToggle()
|
||||
{
|
||||
Send(MuteToggleIrCmd);
|
||||
}
|
||||
|
||||
public void VolumeDown(bool pressRelease)
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
//#warning need incrementer for these
|
||||
SetVolume(_VolumeLevel++);
|
||||
}
|
||||
|
||||
public void VolumeUp(bool pressRelease)
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
SetVolume(_VolumeLevel--);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,620 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro.CrestronThread;
|
||||
using Crestron.SimplSharpPro;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Displays
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class SamsungMDC : TwoWayDisplayBase, IBasicVolumeWithFeedback, ICommunicationMonitor, IInputDisplayPort1, IInputDisplayPort2,
|
||||
IInputHdmi1, IInputHdmi2, IInputHdmi3, IInputHdmi4
|
||||
{
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
|
||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||
|
||||
public byte ID { get; private set; }
|
||||
|
||||
bool LastCommandSentWasVolume;
|
||||
|
||||
bool _PowerIsOn;
|
||||
bool _IsWarmingUp;
|
||||
bool _IsCoolingDown;
|
||||
ushort _VolumeLevelForSig;
|
||||
int _LastVolumeSent;
|
||||
bool _IsMuted;
|
||||
RoutingInputPort _CurrentInputPort;
|
||||
byte[] IncomingBuffer = new byte[]{};
|
||||
ActionIncrementer VolumeIncrementer;
|
||||
bool VolumeIsRamping;
|
||||
public bool IsInStandby { get; private set; }
|
||||
bool IsPoweringOnIgnorePowerFb;
|
||||
|
||||
protected override Func<bool> PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } }
|
||||
protected override Func<bool> IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } }
|
||||
protected override Func<bool> IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } }
|
||||
protected override Func<string> CurrentInputFeedbackFunc { get { return () => _CurrentInputPort.Key; } }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for IBasicCommunication
|
||||
/// </summary>
|
||||
public SamsungMDC(string key, string name, IBasicCommunication comm, string id)
|
||||
: base(key, name)
|
||||
{
|
||||
Communication = comm;
|
||||
Communication.BytesReceived += new EventHandler<GenericCommMethodReceiveBytesArgs>(Communication_BytesReceived);
|
||||
|
||||
ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for TCP
|
||||
/// </summary>
|
||||
public SamsungMDC(string key, string name, string hostname, int port, string id)
|
||||
: base(key, name)
|
||||
{
|
||||
Communication = new GenericTcpIpClient(key + "-tcp", hostname, port, 5000);
|
||||
ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for COM
|
||||
/// </summary>
|
||||
public SamsungMDC(string key, string name, ComPort port, ComPort.ComPortSpec spec, string id)
|
||||
: base(key, name)
|
||||
{
|
||||
Communication = new ComPortController(key + "-com", port, spec);
|
||||
//Communication.TextReceived += new EventHandler<GenericCommMethodReceiveTextArgs>(Communication_TextReceived);
|
||||
|
||||
ID = id == null ? (byte)0x01 : Convert.ToByte(id, 16); // If id is null, set default value of 0x01, otherwise assign value passed in constructor
|
||||
Init();
|
||||
}
|
||||
|
||||
void AddRoutingInputPort(RoutingInputPort port, byte fbMatch)
|
||||
{
|
||||
port.FeedbackMatchObject = fbMatch;
|
||||
InputPorts.Add(port);
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
WarmupTime = 10000;
|
||||
CooldownTime = 8000;
|
||||
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 2000, 120000, 300000, StatusGet);
|
||||
DeviceManager.AddDevice(CommunicationMonitor);
|
||||
|
||||
VolumeIncrementer = new ActionIncrementer(655, 0, 65535, 800, 80,
|
||||
v => SetVolume((ushort)v),
|
||||
() => _LastVolumeSent);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi1), this), 0x21);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn1PC, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi1PC), this), 0x22);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi2), this), 0x23);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn2PC, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi2PC), this), 0x24);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi3), this), 0x32);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.DisplayPortIn1, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.DisplayPort, new Action(InputDisplayPort1), this), 0x25);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.DviIn, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Dvi, new Action(InputDvi1), this), 0x18);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Composite, new Action(InputVideo1), this), 0x08);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.RgbIn1, eRoutingSignalType.Video,
|
||||
eRoutingPortConnectionType.Vga, new Action(InputRgb1), this), 0x14);
|
||||
|
||||
AddRoutingInputPort(new RoutingInputPort(RoutingPortNames.RgbIn2, eRoutingSignalType.Video,
|
||||
eRoutingPortConnectionType.Rgb, new Action(new Action(InputRgb2)), this), 0x1E);
|
||||
|
||||
VolumeLevelFeedback = new IntFeedback(() => { return _VolumeLevelForSig; });
|
||||
MuteFeedback = new BoolFeedback(() => _IsMuted);
|
||||
|
||||
StatusGet();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
Communication.Connect();
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
CommunicationMonitor.Start();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override FeedbackCollection<Feedback> Feedbacks
|
||||
{
|
||||
get
|
||||
{
|
||||
var list = base.Feedbacks;
|
||||
list.AddRange(new List<Feedback>
|
||||
{
|
||||
VolumeLevelFeedback,
|
||||
MuteFeedback,
|
||||
CurrentInputFeedback
|
||||
});
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// /
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e)
|
||||
{
|
||||
// This is probably not thread-safe buffering
|
||||
// Append the incoming bytes with whatever is in the buffer
|
||||
var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length];
|
||||
IncomingBuffer.CopyTo(newBytes, 0);
|
||||
e.Bytes.CopyTo(newBytes, IncomingBuffer.Length);
|
||||
|
||||
if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
|
||||
Debug.Console(2, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes));
|
||||
|
||||
// Need to find AA FF and have
|
||||
for (int i = 0; i < newBytes.Length; i++)
|
||||
{
|
||||
if (newBytes[i] == 0xAA && newBytes[i + 1] == 0xFF)
|
||||
{
|
||||
newBytes = newBytes.Skip(i).ToArray(); // Trim off junk if there's "dirt" in the buffer
|
||||
|
||||
// parse it
|
||||
// If it's at least got the header, then process it,
|
||||
while (newBytes.Length > 4 && newBytes[0] == 0xAA && newBytes[1] == 0xFF)
|
||||
{
|
||||
var msgLen = newBytes[3];
|
||||
// if the buffer is shorter than the header (3) + message (msgLen) + checksum (1),
|
||||
// give and save it for next time
|
||||
if (newBytes.Length < msgLen + 4)
|
||||
break;
|
||||
|
||||
// Good length, grab the message
|
||||
var message = newBytes.Skip(4).Take(msgLen).ToArray();
|
||||
|
||||
// At this point, the ack/nak is the first byte
|
||||
if (message[0] == 0x41)
|
||||
{
|
||||
switch (message[1]) // type byte
|
||||
{
|
||||
case 0x00: // General status
|
||||
//UpdatePowerFB(message[2], message[5]); // "power" can be misrepresented when the display sleeps
|
||||
|
||||
// Handle the first power on fb when waiting for it.
|
||||
if (IsPoweringOnIgnorePowerFb && message[2] == 0x01)
|
||||
IsPoweringOnIgnorePowerFb = false;
|
||||
// Ignore general-status power off messages when powering up
|
||||
if (!(IsPoweringOnIgnorePowerFb && message[2] == 0x00))
|
||||
UpdatePowerFB(message[2]);
|
||||
UpdateVolumeFB(message[3]);
|
||||
UpdateMuteFb(message[4]);
|
||||
UpdateInputFb(message[5]);
|
||||
break;
|
||||
|
||||
case 0x11:
|
||||
UpdatePowerFB(message[2]);
|
||||
break;
|
||||
|
||||
case 0x12:
|
||||
UpdateVolumeFB(message[2]);
|
||||
break;
|
||||
|
||||
case 0x13:
|
||||
UpdateMuteFb(message[2]);
|
||||
break;
|
||||
|
||||
case 0x14:
|
||||
UpdateInputFb(message[2]);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Skip over what we've used and save the rest for next time
|
||||
newBytes = newBytes.Skip(5 + msgLen).ToArray();
|
||||
}
|
||||
|
||||
break; // parsing will mean we can stop looking for header in loop
|
||||
}
|
||||
}
|
||||
|
||||
// Save whatever partial message is here
|
||||
IncomingBuffer = newBytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void UpdatePowerFB(byte powerByte)
|
||||
{
|
||||
var newVal = powerByte == 1;
|
||||
if (newVal != _PowerIsOn)
|
||||
{
|
||||
_PowerIsOn = newVal;
|
||||
PowerIsOnFeedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates power status from general updates where source is included.
|
||||
/// Compensates for errant standby / power off hiccups by ignoring
|
||||
/// power off states with input < 0x10
|
||||
/// </summary>
|
||||
void UpdatePowerFB(byte powerByte, byte inputByte)
|
||||
{
|
||||
// This should reject errant power feedbacks when switching away from input on standby.
|
||||
if (powerByte == 0x01 && inputByte < 0x10)
|
||||
IsInStandby = true;
|
||||
if (powerByte == 0x00 && IsInStandby) // Ignore power off if coming from standby - glitch
|
||||
{
|
||||
IsInStandby = false;
|
||||
return;
|
||||
}
|
||||
|
||||
UpdatePowerFB(powerByte);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void UpdateVolumeFB(byte b)
|
||||
{
|
||||
var newVol = (ushort)NumericalHelpers.Scale((double)b, 0, 100, 0, 65535);
|
||||
if (!VolumeIsRamping)
|
||||
_LastVolumeSent = newVol;
|
||||
if (newVol != _VolumeLevelForSig)
|
||||
{
|
||||
_VolumeLevelForSig = newVol;
|
||||
VolumeLevelFeedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void UpdateMuteFb(byte b)
|
||||
{
|
||||
var newMute = b == 1;
|
||||
if (newMute != _IsMuted)
|
||||
{
|
||||
_IsMuted = newMute;
|
||||
MuteFeedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void UpdateInputFb(byte b)
|
||||
{
|
||||
var newInput = InputPorts.FirstOrDefault(i => i.FeedbackMatchObject.Equals(b));
|
||||
if (newInput != null && newInput != _CurrentInputPort)
|
||||
{
|
||||
_CurrentInputPort = newInput;
|
||||
CurrentInputFeedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats an outgoing message. Replaces third byte with ID and replaces last byte with checksum
|
||||
/// </summary>
|
||||
/// <param name="b"></param>
|
||||
void SendBytes(byte[] b)
|
||||
{
|
||||
if (LastCommandSentWasVolume) // If the last command sent was volume
|
||||
if (b[1] != 0x12) // Check if this command is volume, and if not, delay this command
|
||||
CrestronEnvironment.Sleep(100);
|
||||
|
||||
b[2] = ID;
|
||||
// append checksum by adding all bytes, except last which should be 00
|
||||
int checksum = 0;
|
||||
for (var i = 1; i < b.Length - 1; i++) // add 2nd through 2nd-to-last bytes
|
||||
{
|
||||
checksum += b[i];
|
||||
}
|
||||
checksum = checksum & 0x000000FF; // mask off MSBs
|
||||
b[b.Length - 1] = (byte)checksum;
|
||||
if(Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
|
||||
Debug.Console(2, this, "Sending:{0}", ComTextHelper.GetEscapedText(b));
|
||||
|
||||
if (b[1] == 0x12)
|
||||
LastCommandSentWasVolume = true;
|
||||
else
|
||||
LastCommandSentWasVolume = false;
|
||||
|
||||
Communication.SendBytes(b);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void StatusGet()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x00, 0x00, 0x00, 0x00 });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public override void PowerOn()
|
||||
{
|
||||
IsPoweringOnIgnorePowerFb = true;
|
||||
//Send(PowerOnCmd);
|
||||
SendBytes(new byte[] { 0xAA, 0x11, 0x00, 0x01, 0x01, 0x00 });
|
||||
if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
|
||||
{
|
||||
_IsWarmingUp = true;
|
||||
IsWarmingUpFeedback.FireUpdate();
|
||||
// Fake power-up cycle
|
||||
WarmupTimer = new CTimer(o =>
|
||||
{
|
||||
_IsWarmingUp = false;
|
||||
_PowerIsOn = true;
|
||||
IsWarmingUpFeedback.FireUpdate();
|
||||
PowerIsOnFeedback.FireUpdate();
|
||||
}, WarmupTime);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public override void PowerOff()
|
||||
{
|
||||
IsPoweringOnIgnorePowerFb = false;
|
||||
// If a display has unreliable-power off feedback, just override this and
|
||||
// remove this check.
|
||||
if (!_IsWarmingUp && !_IsCoolingDown) // PowerIsOnFeedback.BoolValue &&
|
||||
{
|
||||
//Send(PowerOffCmd);
|
||||
SendBytes(new byte[] { 0xAA, 0x11, 0x00, 0x01, 0x00, 0x00 });
|
||||
_IsCoolingDown = true;
|
||||
_PowerIsOn = false;
|
||||
PowerIsOnFeedback.FireUpdate();
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
// Fake cool-down cycle
|
||||
CooldownTimer = new CTimer(o =>
|
||||
{
|
||||
_IsCoolingDown = false;
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
}, CooldownTime);
|
||||
}
|
||||
}
|
||||
|
||||
public override void PowerToggle()
|
||||
{
|
||||
if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue)
|
||||
PowerOff();
|
||||
else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue)
|
||||
PowerOn();
|
||||
}
|
||||
|
||||
public void PowerGet()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x11, 0x00, 0x00, 0x00 });
|
||||
}
|
||||
|
||||
public void InputHdmi1()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x21, 0x00 });
|
||||
}
|
||||
|
||||
public void InputHdmi1PC()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x22, 0x00 });
|
||||
}
|
||||
|
||||
public void InputHdmi2()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x23, 0x00 });
|
||||
}
|
||||
|
||||
public void InputHdmi2PC()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x24, 0x00 });
|
||||
}
|
||||
|
||||
public void InputHdmi3()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x32, 0x00 });
|
||||
}
|
||||
|
||||
public void InputHdmi4()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x34, 0x00 });
|
||||
}
|
||||
|
||||
public void InputDisplayPort1()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x25, 0x00 });
|
||||
}
|
||||
|
||||
public void InputDisplayPort2()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x26, 0x00 });
|
||||
}
|
||||
|
||||
public void InputDvi1()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x18, 0x00 });
|
||||
}
|
||||
|
||||
public void InputVideo1()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x08, 0x00 });
|
||||
}
|
||||
|
||||
public void InputRgb1()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x14, 0x00 });
|
||||
}
|
||||
|
||||
public void InputRgb2()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x1E, 0x00 });
|
||||
}
|
||||
|
||||
public void InputGet()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x00, 0x00 });
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Executes a switch, turning on display if necessary.
|
||||
/// </summary>
|
||||
/// <param name="selector"></param>
|
||||
public override void ExecuteSwitch(object selector)
|
||||
{
|
||||
//if (!(selector is Action))
|
||||
// Debug.Console(1, this, "WARNING: ExecuteSwitch cannot handle type {0}", selector.GetType());
|
||||
|
||||
if (_PowerIsOn)
|
||||
(selector as Action)();
|
||||
else // if power is off, wait until we get on FB to send it.
|
||||
{
|
||||
// One-time event handler to wait for power on before executing switch
|
||||
EventHandler<FeedbackEventArgs> handler = null; // necessary to allow reference inside lambda to handler
|
||||
handler = (o, a) =>
|
||||
{
|
||||
if (!_IsWarmingUp) // Done warming
|
||||
{
|
||||
IsWarmingUpFeedback.OutputChange -= handler;
|
||||
(selector as Action)();
|
||||
}
|
||||
};
|
||||
IsWarmingUpFeedback.OutputChange += handler; // attach and wait for on FB
|
||||
PowerOn();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the level to the range of the display and sends the command
|
||||
/// </summary>
|
||||
/// <param name="level"></param>
|
||||
public void SetVolume(ushort level)
|
||||
{
|
||||
_LastVolumeSent = level;
|
||||
var scaled = (int)NumericalHelpers.Scale(level, 0, 65535, 0, 100);
|
||||
// The inputs to Scale ensure that byte won't overflow
|
||||
SendBytes(new byte[] { 0xAA, 0x12, 0x00, 0x01, Convert.ToByte(scaled), 0x00 });
|
||||
}
|
||||
|
||||
#region IBasicVolumeWithFeedback Members
|
||||
|
||||
public IntFeedback VolumeLevelFeedback { get; private set; }
|
||||
|
||||
public BoolFeedback MuteFeedback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void MuteOff()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x13, 0x00, 0x01, 0x00, 0x00 });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void MuteOn()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x13, 0x00, 0x01, 0x01, 0x00 });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void MuteGet()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x13, 0x00, 0x00, 0x00 });
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IBasicVolumeControls Members
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void MuteToggle()
|
||||
{
|
||||
if (_IsMuted)
|
||||
MuteOff();
|
||||
else
|
||||
MuteOn();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void VolumeDown(bool pressRelease)
|
||||
{
|
||||
if (pressRelease)
|
||||
{
|
||||
VolumeIncrementer.StartDown();
|
||||
VolumeIsRamping = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VolumeIsRamping = false;
|
||||
VolumeIncrementer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void VolumeUp(bool pressRelease)
|
||||
{
|
||||
if (pressRelease)
|
||||
{
|
||||
VolumeIncrementer.StartUp();
|
||||
VolumeIsRamping = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VolumeIsRamping = false;
|
||||
VolumeIncrementer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void VolumeGet()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x12, 0x00, 0x00, 0x00 });
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
using Crestron.SimplSharpPro.Lighting;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.CrestronIO;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Environment.Lighting
|
||||
{
|
||||
public class Din8sw8Controller : Device, ISwitchedOutputCollection
|
||||
{
|
||||
// Need to figure out some sort of interface to make these switched outputs behave like processor relays so they can be used interchangably
|
||||
|
||||
public Din8Sw8 SwitchModule { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Collection of generic switched outputs
|
||||
/// </summary>
|
||||
public Dictionary<uint, ISwitchedOutput> SwitchedOutputs { get; private set; }
|
||||
|
||||
public Din8sw8Controller(string key, uint cresnetId)
|
||||
: base(key)
|
||||
{
|
||||
SwitchedOutputs = new Dictionary<uint, ISwitchedOutput>();
|
||||
|
||||
SwitchModule = new Din8Sw8(cresnetId, Global.ControlSystem);
|
||||
|
||||
if (SwitchModule.Register() != eDeviceRegistrationUnRegistrationResponse.Success)
|
||||
{
|
||||
Debug.Console(2, this, "Error registering Din8sw8. Reason: {0}", SwitchModule.RegistrationFailureReason);
|
||||
}
|
||||
|
||||
PopulateDictionary();
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
|
||||
|
||||
return base.CustomActivate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates the generic collection with the loads from the Crestron collection
|
||||
/// </summary>
|
||||
void PopulateDictionary()
|
||||
{
|
||||
foreach (var item in SwitchModule.SwitchedLoads)
|
||||
{
|
||||
SwitchedOutputs.Add(item.Number, new Din8sw8Output(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper class to
|
||||
/// </summary>
|
||||
public class Din8sw8Output : ISwitchedOutput
|
||||
{
|
||||
SwitchedLoadWithOverrideParameter SwitchedOutput;
|
||||
|
||||
public BoolFeedback OutputIsOnFeedback { get; protected set; }
|
||||
|
||||
public Din8sw8Output(SwitchedLoadWithOverrideParameter switchedOutput)
|
||||
{
|
||||
SwitchedOutput = switchedOutput;
|
||||
|
||||
OutputIsOnFeedback = new BoolFeedback(new Func<bool>(() => SwitchedOutput.IsOn));
|
||||
}
|
||||
|
||||
public void On()
|
||||
{
|
||||
SwitchedOutput.FullOn();
|
||||
}
|
||||
|
||||
public void Off()
|
||||
{
|
||||
SwitchedOutput.FullOff();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Lighting;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Environment.Lutron
|
||||
{
|
||||
public class LutronQuantumArea : LightingBase, ILightingMasterRaiseLower, ICommunicationMonitor
|
||||
{
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
public CommunicationGather PortGather { get; private set; }
|
||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||
|
||||
CTimer SubscribeAfterLogin;
|
||||
|
||||
public string IntegrationId;
|
||||
string Username;
|
||||
string Password;
|
||||
|
||||
const string Delimiter = "\x0d\x0a";
|
||||
const string Set = "#";
|
||||
const string Get = "?";
|
||||
|
||||
public LutronQuantumArea(string key, string name, IBasicCommunication comm, LutronQuantumPropertiesConfig props)
|
||||
: base(key, name)
|
||||
{
|
||||
Communication = comm;
|
||||
|
||||
IntegrationId = props.IntegrationId;
|
||||
|
||||
if (props.Control.Method != eControlMethod.Com)
|
||||
{
|
||||
|
||||
Username = props.Control.TcpSshProperties.Username;
|
||||
Password = props.Control.TcpSshProperties.Password;
|
||||
}
|
||||
|
||||
|
||||
LightingScenes = props.Scenes;
|
||||
|
||||
var socket = comm as ISocketStatus;
|
||||
if (socket != null)
|
||||
{
|
||||
// IP Control
|
||||
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
|
||||
}
|
||||
else
|
||||
{
|
||||
// RS-232 Control
|
||||
}
|
||||
|
||||
Communication.TextReceived += new EventHandler<GenericCommMethodReceiveTextArgs>(Communication_TextReceived);
|
||||
|
||||
PortGather = new CommunicationGather(Communication, Delimiter);
|
||||
PortGather.LineReceived += new EventHandler<GenericCommMethodReceiveTextArgs>(PortGather_LineReceived);
|
||||
|
||||
if (props.CommunicationMonitorProperties != null)
|
||||
{
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 120000, 120000, 300000, "?ETHERNET,0\x0d\x0a");
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
Communication.Connect();
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
CommunicationMonitor.Start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
||||
{
|
||||
Debug.Console(2, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
|
||||
|
||||
if (e.Client.IsConnected)
|
||||
{
|
||||
// Tasks on connect
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks for responses that do not contain the delimiter
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="args"></param>
|
||||
void Communication_TextReceived(object sender, GenericCommMethodReceiveTextArgs args)
|
||||
{
|
||||
Debug.Console(2, this, "Text Received: '{0}'", args.Text);
|
||||
|
||||
if (args.Text.Contains("login:"))
|
||||
{
|
||||
// Login
|
||||
SendLine(Username);
|
||||
}
|
||||
else if (args.Text.Contains("password:"))
|
||||
{
|
||||
// Login
|
||||
SendLine(Password);
|
||||
SubscribeAfterLogin = new CTimer(x => SubscribeToFeedback(), null, 5000);
|
||||
|
||||
}
|
||||
else if (args.Text.Contains("Access Granted"))
|
||||
{
|
||||
if (SubscribeAfterLogin != null)
|
||||
{
|
||||
SubscribeAfterLogin.Stop();
|
||||
}
|
||||
SubscribeToFeedback();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles all responses that contain the delimiter
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="args"></param>
|
||||
void PortGather_LineReceived(object sender, GenericCommMethodReceiveTextArgs args)
|
||||
{
|
||||
Debug.Console(2, this, "Line Received: '{0}'", args.Text);
|
||||
|
||||
try
|
||||
{
|
||||
if (args.Text.Contains("~AREA"))
|
||||
{
|
||||
var response = args.Text.Split(',');
|
||||
|
||||
var integrationId = response[1];
|
||||
|
||||
if (integrationId != IntegrationId)
|
||||
{
|
||||
Debug.Console(2, this, "Response is not for correct Integration ID");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
var action = Int32.Parse(response[2]);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case (int)eAction.Scene:
|
||||
{
|
||||
var scene = response[3];
|
||||
CurrentLightingScene = LightingScenes.FirstOrDefault(s => s.ID.Equals(scene));
|
||||
|
||||
OnLightingSceneChange();
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(2, this, "Error parsing response:\n{0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes to feedback
|
||||
/// </summary>
|
||||
public void SubscribeToFeedback()
|
||||
{
|
||||
Debug.Console(1, "Sending Monitoring Subscriptions");
|
||||
SendLine("#MONITORING,6,1");
|
||||
SendLine("#MONITORING,8,1");
|
||||
SendLine("#MONITORING,5,2");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recalls the specified scene
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
///
|
||||
|
||||
public override void SelectScene(LightingScene scene)
|
||||
{
|
||||
Debug.Console(1, this, "Selecting Scene: '{0}'", scene.Name);
|
||||
SendLine(string.Format("{0}AREA,{1},{2},{3}", Set, IntegrationId, (int)eAction.Scene, scene.ID));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begins raising the lights in the area
|
||||
/// </summary>
|
||||
public void MasterRaise()
|
||||
{
|
||||
SendLine(string.Format("{0}AREA,{1},{2}", Set, IntegrationId, (int)eAction.Raise));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begins lowering the lights in the area
|
||||
/// </summary>
|
||||
public void MasterLower()
|
||||
{
|
||||
SendLine(string.Format("{0}AREA,{1},{2}", Set, IntegrationId, (int)eAction.Lower));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the current raise/lower action
|
||||
/// </summary>
|
||||
public void MasterRaiseLowerStop()
|
||||
{
|
||||
SendLine(string.Format("{0}AREA,{1},{2}", Set, IntegrationId, (int)eAction.Stop));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the delimiter and sends the string
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
public void SendLine(string s)
|
||||
{
|
||||
Debug.Console(2, this, "TX: '{0}'", s);
|
||||
Communication.SendText(s + Delimiter);
|
||||
}
|
||||
}
|
||||
|
||||
public enum eAction : int
|
||||
{
|
||||
SetLevel = 1,
|
||||
Raise = 2,
|
||||
Lower = 3,
|
||||
Stop = 4,
|
||||
Scene = 6,
|
||||
DaylightMode = 7,
|
||||
OccupancyState = 8,
|
||||
OccupancyMode = 9,
|
||||
OccupiedLevelOrScene = 12,
|
||||
UnoccupiedLevelOrScene = 13,
|
||||
HyperionShaddowSensorOverrideState = 26,
|
||||
HyperionBrightnessSensorOverrideStatue = 27
|
||||
}
|
||||
|
||||
public class LutronQuantumPropertiesConfig
|
||||
{
|
||||
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
||||
public ControlPropertiesConfig Control { get; set; }
|
||||
|
||||
public string IntegrationId { get; set; }
|
||||
public List<LightingScene> Scenes { get; set; }
|
||||
|
||||
// Moved to use existing properties in Control object
|
||||
// public string Username { get; set; }
|
||||
// public string Password { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.CrestronIO;
|
||||
using PepperDash.Essentials.Core.Shades;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Environment.Somfy
|
||||
{
|
||||
/// <summary>
|
||||
/// Controls a single shade using three relays
|
||||
/// </summary>
|
||||
public class RelayControlledShade : ShadeBase, IShadesOpenCloseStop
|
||||
{
|
||||
RelayControlledShadeConfigProperties Config;
|
||||
|
||||
ISwitchedOutput OpenRelay;
|
||||
ISwitchedOutput StopOrPresetRelay;
|
||||
ISwitchedOutput CloseRelay;
|
||||
|
||||
int RelayPulseTime;
|
||||
|
||||
public string StopOrPresetButtonLabel { get; set; }
|
||||
|
||||
public RelayControlledShade(string key, string name, RelayControlledShadeConfigProperties config)
|
||||
: base(key, name)
|
||||
{
|
||||
Config = config;
|
||||
|
||||
RelayPulseTime = Config.RelayPulseTime;
|
||||
|
||||
StopOrPresetButtonLabel = Config.StopOrPresetLabel;
|
||||
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
//Create ISwitchedOutput objects based on props
|
||||
OpenRelay = GetSwitchedOutputFromDevice(Config.Relays.Open);
|
||||
StopOrPresetRelay = GetSwitchedOutputFromDevice(Config.Relays.StopOrPreset);
|
||||
CloseRelay = GetSwitchedOutputFromDevice(Config.Relays.Close);
|
||||
|
||||
|
||||
return base.CustomActivate();
|
||||
}
|
||||
|
||||
public override void Open()
|
||||
{
|
||||
Debug.Console(1, this, "Opening Shade: '{0}'", this.Name);
|
||||
|
||||
PulseOutput(OpenRelay, RelayPulseTime);
|
||||
}
|
||||
|
||||
public override void StopOrPreset()
|
||||
{
|
||||
Debug.Console(1, this, "Stopping or recalling preset on Shade: '{0}'", this.Name);
|
||||
|
||||
PulseOutput(StopOrPresetRelay, RelayPulseTime);
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
Debug.Console(1, this, "Closing Shade: '{0}'", this.Name);
|
||||
|
||||
PulseOutput(CloseRelay, RelayPulseTime);
|
||||
}
|
||||
|
||||
void PulseOutput(ISwitchedOutput output, int pulseTime)
|
||||
{
|
||||
output.On();
|
||||
CTimer pulseTimer = new CTimer(new CTimerCallbackFunction((o) => output.Off()), pulseTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to get the port on teh specified device from config
|
||||
/// </summary>
|
||||
/// <param name="relayConfig"></param>
|
||||
/// <returns></returns>
|
||||
ISwitchedOutput GetSwitchedOutputFromDevice(IOPortConfig relayConfig)
|
||||
{
|
||||
var portDevice = DeviceManager.GetDeviceForKey(relayConfig.PortDeviceKey);
|
||||
|
||||
if (portDevice != null)
|
||||
{
|
||||
return (portDevice as ISwitchedOutputCollection).SwitchedOutputs[relayConfig.PortNumber];
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "Error: Unable to get relay on port '{0}' from device with key '{1}'", relayConfig.PortNumber, relayConfig.PortDeviceKey);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class RelayControlledShadeConfigProperties
|
||||
{
|
||||
public int RelayPulseTime { get; set; }
|
||||
public ShadeRelaysConfig Relays { get; set; }
|
||||
public string StopOrPresetLabel { get; set; }
|
||||
|
||||
public class ShadeRelaysConfig
|
||||
{
|
||||
public IOPortConfig Open { get; set; }
|
||||
public IOPortConfig StopOrPreset { get; set; }
|
||||
public IOPortConfig Close { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{892B761C-E479-44CE-BD74-243E9214AF13}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>PepperDash.Essentials.Devices.Common</RootNamespace>
|
||||
<AssemblyName>Essentials Devices Common</AssemblyName>
|
||||
<ProjectTypeGuids>{0B4745B0-194B-4BB6-8E21-E9057CA92300};{4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<PlatformFamilyName>WindowsCE</PlatformFamilyName>
|
||||
<PlatformID>E2BECB1F-8C8C-41ba-B736-9BE7D946A398</PlatformID>
|
||||
<OSVersion>5.0</OSVersion>
|
||||
<DeployDirSuffix>SmartDeviceProject1</DeployDirSuffix>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<NativePlatformName>Windows CE</NativePlatformName>
|
||||
<FormFactorID>
|
||||
</FormFactorID>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<AllowedReferenceRelatedFileExtensions>.allowedReferenceRelatedFileExtensions</AllowedReferenceRelatedFileExtensions>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<GenerateSerializationAssemblies>off</GenerateSerializationAssemblies>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<AllowedReferenceRelatedFileExtensions>.allowedReferenceRelatedFileExtensions</AllowedReferenceRelatedFileExtensions>
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<GenerateSerializationAssemblies>off</GenerateSerializationAssemblies>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Crestron.SimplSharpPro.DeviceSupport, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DeviceSupport.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Crestron.SimplSharpPro.Gateways, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Gateways.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Crestron.SimplSharpPro.GeneralIO, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.GeneralIO.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Crestron.SimplSharpPro.Lighting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Lighting.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="PepperDash_Core, Version=1.0.4.20530, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\references\PepperDash_Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SimplSharpCustomAttributesInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="SimplSharpHelperInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="SimplSharpNewtonsoft, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SimplSharpPro, Version=1.5.3.17, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="SimplSharpReflectionInterface, Version=1.0.5583.25238, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AudioCodec\AudioCodecBase.cs" />
|
||||
<Compile Include="AudioCodec\Interfaces\IAudioCodecInfo.cs" />
|
||||
<Compile Include="AudioCodec\Interfaces\IHasAudioCodec.cs" />
|
||||
<Compile Include="AudioCodec\MockAC\MockAC.cs" />
|
||||
<Compile Include="AudioCodec\MockAC\MockAcPropertiesConfig.cs" />
|
||||
<Compile Include="Cameras\CameraBase.cs" />
|
||||
<Compile Include="Cameras\CameraVisca.cs" />
|
||||
<Compile Include="Codec\eCodecCallDirection.cs" />
|
||||
<Compile Include="Codec\eCodecCallType.cs" />
|
||||
<Compile Include="Codec\eCodecCallStatus.cs" />
|
||||
<Compile Include="Codec\eMeetingPrivacy.cs" />
|
||||
<Compile Include="Codec\iCodecAudio.cs" />
|
||||
<Compile Include="ImageProcessors\TVOneCorio.cs" />
|
||||
<Compile Include="ImageProcessors\TVOneCorioPropertiesConfig.cs" />
|
||||
<Compile Include="Power Controllers\Digitallogger.cs" />
|
||||
<Compile Include="Power Controllers\DigitalLoggerPropertiesConfig.cs" />
|
||||
<Compile Include="Evertz\EvertsEndpointStatusServer.cs" />
|
||||
<Compile Include="Evertz\EvertzEndpointVarIds.cs" />
|
||||
<Compile Include="Evertz\EvertzEndpoint.cs" />
|
||||
<Compile Include="Evertz\EvertzEndpointPropertiesConfig.cs" />
|
||||
<Compile Include="Evertz\GenericHttpClient.cs" />
|
||||
<Compile Include="ImageProcessors\AnalogWay\AnalongWayLiveCore.cs" />
|
||||
<Compile Include="ImageProcessors\AnalogWay\AnalogWayLiveCorePropertiesConfig.cs" />
|
||||
<Compile Include="VideoCodec\CiscoCodec\CiscoCamera.cs" />
|
||||
<Compile Include="VideoCodec\CiscoCodec\RoomPresets.cs" />
|
||||
<Compile Include="VideoCodec\Interfaces\CameraControl.cs" />
|
||||
<Compile Include="Display\PanasonicThDisplay.cs" />
|
||||
<Compile Include="VideoCodec\Interfaces\iVideoCodecInfo.cs" />
|
||||
<Compile Include="Codec\iHasCallFavorites.cs" />
|
||||
<Compile Include="Codec\iHasCallHistory.cs" />
|
||||
<Compile Include="Codec\iHasContentSharing.cs" />
|
||||
<Compile Include="Codec\iHasDialer.cs" />
|
||||
<Compile Include="Codec\iHasDirectory.cs" />
|
||||
<Compile Include="Codec\iHasScheduleAwareness.cs" />
|
||||
<Compile Include="Crestron\Gateways\CenRfgwController.cs" />
|
||||
<Compile Include="Display\ComTcpDisplayBase.cs" />
|
||||
<Compile Include="Display\AvocorVTFDisplay.cs" />
|
||||
<Compile Include="Display\InputInterfaces.cs" />
|
||||
<Compile Include="Display\SamsungMDCDisplay.cs" />
|
||||
<Compile Include="Display\DeviceFactory.cs" />
|
||||
<Compile Include="Display\NecPaSeriesProjector.cs" />
|
||||
<Compile Include="Display\NECPSXMDisplay.cs" />
|
||||
<Compile Include="DSP\BiampTesira\BiampTesiraForteDspLevel.cs" />
|
||||
<Compile Include="DSP\BiampTesira\TesiraForteControlPoint.cs" />
|
||||
<Compile Include="DSP\BiampTesira\TesiraForteMuteControl.cs" />
|
||||
<Compile Include="DSP\DspBase.cs" />
|
||||
<Compile Include="DSP\BiampTesira\BiampTesiraForteDsp.cs" />
|
||||
<Compile Include="DSP\BiampTesira\BiampTesiraFortePropertiesConfig.cs" />
|
||||
<Compile Include="DSP\PolycomSoundStructure\SoundStructureBasics.cs" />
|
||||
<Compile Include="Environment\Crestron Lighting\Din8sw8.cs" />
|
||||
<Compile Include="Environment\Lutron\LutronQuantum.cs" />
|
||||
<Compile Include="Environment\Somfy\RelayControlledShade.cs" />
|
||||
<Compile Include="Factory\DeviceFactory.cs" />
|
||||
<Compile Include="Generic\GenericSource.cs" />
|
||||
<Compile Include="Microphone\MicrophonePrivacyController.cs" />
|
||||
<Compile Include="Microphone\MicrophonePrivacyControllerConfig.cs" />
|
||||
<Compile Include="Occupancy\EssentialsGlsOccupancySensorBaseController.cs" />
|
||||
<Compile Include="Occupancy\EssentialsOccupancyAggregator.cs" />
|
||||
<Compile Include="Occupancy\iOccupancyStatusProvider.cs" />
|
||||
<Compile Include="PC\InRoomPc.cs" />
|
||||
<Compile Include="PC\Laptop.cs" />
|
||||
<Compile Include="SetTopBox\SetTopBoxPropertiesConfig.cs" />
|
||||
<Compile Include="Streaming\AppleTV.cs" />
|
||||
<Compile Include="Audio\GenericAudioOut.cs" />
|
||||
<Compile Include="DiscPlayer\IRDiscPlayerBase.cs" />
|
||||
<Compile Include="SetTopBox\IRSetTopBoxBase.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Streaming\Roku.cs" />
|
||||
<Compile Include="VideoCodec\CiscoCodec\BookingsDataClasses.cs" />
|
||||
<Compile Include="VideoCodec\CiscoCodec\CallHistoryDataClasses.cs" />
|
||||
<Compile Include="VideoCodec\CiscoCodec\CiscoSparkCodec.cs" />
|
||||
<Compile Include="VideoCodec\CiscoCodec\CiscoSparkCodecPropertiesConfig.cs" />
|
||||
<Compile Include="VideoCodec\CiscoCodec\xStatusSparkPlus.cs" />
|
||||
<Compile Include="VideoCodec\Interfaces\IHasVideoCodec.cs" />
|
||||
<Compile Include="VideoCodec\MockVC\MockCodecDirectory.cs" />
|
||||
<Compile Include="VideoCodec\MockVC\MockVCCamera.cs" />
|
||||
<Compile Include="VideoCodec\MockVC\MockVcPropertiesConfig.cs" />
|
||||
<Compile Include="VideoCodec\CiscoCodec\PhonebookDataClasses.cs" />
|
||||
<Compile Include="VideoCodec\CiscoCodec\xConfiguration.cs" />
|
||||
<Compile Include="VideoCodec\CiscoCodec\xEvent.cs" />
|
||||
<Compile Include="VideoCodec\CiscoCodec\HttpApiServer.cs" />
|
||||
<Compile Include="Codec\CodecActiveCallItem.cs" />
|
||||
<Compile Include="VideoCodec\Interfaces\IHasCodecLayouts.cs" />
|
||||
<Compile Include="VideoCodec\Interfaces\IHasCodecSelfview.cs" />
|
||||
<Compile Include="VideoCodec\MockVC\MockVC.cs" />
|
||||
<Compile Include="VideoCodec\CiscoCodec\xStatus.cs" />
|
||||
<Compile Include="VideoCodec\VideoCodecBase.cs" />
|
||||
<Compile Include="VideoCodec\ZoomRoom\ResponseObjects.cs" />
|
||||
<Compile Include="VideoCodec\ZoomRoom\ZoomRoom.cs" />
|
||||
<Compile Include="VideoCodec\ZoomRoom\ZoomRoomCamera.cs" />
|
||||
<Compile Include="VideoCodec\ZoomRoom\ZoomRoomPropertiesConfig.cs" />
|
||||
<None Include="Properties\ControlSystem.cfg" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Essentials Core\PepperDashEssentialsBase\PepperDash_Essentials_Core.csproj">
|
||||
<Project>{A49AD6C8-FC0A-4CC0-9089-DFB4CF92D2B5}</Project>
|
||||
<Name>PepperDash_Essentials_Core</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CompactFramework.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>rem S# Pro preparation will execute after these operations</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,152 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using System.Text.RegularExpressions;
|
||||
using Crestron.SimplSharp.Net.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
using Crestron.SimplSharp.CrestronSockets;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
|
||||
/*****
|
||||
* TODO JTA: Add Polling
|
||||
* TODO JTA: Move all the registration commnads to the EvertEndpoint class.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
public class EvertzEndpointStatusServer : Device
|
||||
{
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
public CommunicationGather PortGather { get; private set; }
|
||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||
public bool isSubscribed;
|
||||
public string Address;
|
||||
public GenericUdpServer Server;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Shows received lines as hex
|
||||
/// </summary>
|
||||
public bool ShowHexResponse { get; set; }
|
||||
public Dictionary<string, EvertzEndpoint> Endpoints;
|
||||
public Dictionary<string, string> ServerIdByEndpointIp;
|
||||
|
||||
public EvertzEndpointStatusServer(string key, string name, GenericUdpServer server, EvertzEndpointStatusServerPropertiesConfig props) :
|
||||
base(key, name)
|
||||
{
|
||||
Server = server;
|
||||
Address = props.serverHostname;
|
||||
Server.DataRecievedExtra += new EventHandler<GenericUdpReceiveTextExtraArgs>(_Server_DataRecievedExtra);
|
||||
|
||||
Server.Connect();
|
||||
Endpoints = new Dictionary<string,EvertzEndpoint>();
|
||||
|
||||
//CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//TODO JTA: Move this method and process over to the endpoint itself. return a bool.
|
||||
public bool RegisterEvertzEndpoint (EvertzEndpoint device)
|
||||
{
|
||||
|
||||
if (Endpoints.ContainsKey(device.Address) == false)
|
||||
{
|
||||
Endpoints.Add(device.Address, device);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void _Server_DataRecievedExtra(object sender, GenericUdpReceiveTextExtraArgs e)
|
||||
{
|
||||
Debug.Console(2, this, "_Server_DataRecievedExtra:\nIP:{0}\nPort:{1}\nText{2}\nBytes:{3} ", e.IpAddress, e.Port, e.Text, e.Bytes);
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
/*
|
||||
Communication.Connect();
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
CommunicationMonitor.Start();
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public class EvertzPortRestResponse
|
||||
{
|
||||
public string id;
|
||||
public string name;
|
||||
public string type;
|
||||
public string value;
|
||||
|
||||
}
|
||||
|
||||
public class EvertsStatusRequesstResponse
|
||||
{
|
||||
public EvertzStatusDataResponse data;
|
||||
public string error;
|
||||
}
|
||||
|
||||
public class EvertzStatusDataResponse
|
||||
{
|
||||
public List<EvertzServerStatusResponse> servers;
|
||||
}
|
||||
|
||||
public class EvertzServerStatusResponse
|
||||
{
|
||||
public string id;
|
||||
public string name;
|
||||
public EvertsServerStausNotificationsResponse notify;
|
||||
|
||||
}
|
||||
public class EvertsServerStausNotificationsResponse
|
||||
{
|
||||
public string ip;
|
||||
public List<string> parameters;
|
||||
public string port;
|
||||
public string protocol;
|
||||
}
|
||||
public class EvertzEndpointStatusServerPropertiesConfig
|
||||
{
|
||||
|
||||
public ControlPropertiesConfig control { get; set; }
|
||||
public string serverHostname { get; set; }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,337 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using System.Text.RegularExpressions;
|
||||
using Crestron.SimplSharp.Net.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
|
||||
public class EvertzEndpoint : Device
|
||||
{
|
||||
|
||||
|
||||
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
public CommunicationGather PortGather { get; private set; }
|
||||
public GenericCommunicationMonitor CommunicationMonitor { get; private set; }
|
||||
|
||||
private GenericHttpClient Client;
|
||||
public string userName;
|
||||
public string password;
|
||||
public string Address;
|
||||
private bool OnlineStatus;
|
||||
public BoolFeedback OnlineFeedback;
|
||||
public IntFeedback PresetFeedback;
|
||||
|
||||
|
||||
public bool isSubscribed;
|
||||
|
||||
|
||||
|
||||
CrestronQueue CommandQueue;
|
||||
|
||||
public Dictionary<string, EvertzEndpointPort> Ports;
|
||||
|
||||
private string _ControllerKey;
|
||||
|
||||
|
||||
private EvertzEndpointStatusServer StatusServer;
|
||||
private String StatusServerId;
|
||||
|
||||
/// <summary>
|
||||
/// Shows received lines as hex
|
||||
/// </summary>
|
||||
public bool ShowHexResponse { get; set; }
|
||||
|
||||
public EvertzEndpoint(string key, string name, EvertzEndpointPropertiesConfig props, string type) :
|
||||
base(key, name)
|
||||
{
|
||||
|
||||
|
||||
this.Address = props.address;
|
||||
Client = new GenericHttpClient(string.Format("{0}-GenericWebClient", name), string.Format("{0}-GenericWebClient", name), this.Address);
|
||||
Client.ResponseRecived += new EventHandler<GenericHttpClientEventArgs>(Client_ResponseRecived);
|
||||
Ports = new Dictionary<string, EvertzEndpointPort>();
|
||||
if (type.ToLower() == "mma10g-trs4k")
|
||||
{
|
||||
//create port hdmi 01
|
||||
EvertzEndpointPort hdmi1 = new EvertzEndpointPort("HDMI01", "131.0@s", "136.0@s");
|
||||
EvertzEndpointPort hdmi2 = new EvertzEndpointPort("HDMI02", "131.1@s", "136.1@s");
|
||||
// add to dictionay with all keys
|
||||
addPortToDictionary(hdmi1);
|
||||
addPortToDictionary(hdmi2);
|
||||
}
|
||||
_ControllerKey = null;
|
||||
if (props.controllerKey != null)
|
||||
{
|
||||
_ControllerKey = props.controllerKey;
|
||||
}
|
||||
AddPostActivationAction( () => {PostActivation();});
|
||||
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
|
||||
if (props.CommunicationMonitorProperties != null)
|
||||
{
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Client, props.CommunicationMonitorProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Client, 40000, 120000, 300000, "v.api/apis/EV/SERVERSTATUS");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method
|
||||
/// </summary>
|
||||
/// <param name="port"></param>
|
||||
private void addPortToDictionary(EvertzEndpointPort port)
|
||||
{
|
||||
Ports.Add(port.PortName, port);
|
||||
Ports.Add(port.ResolutionVarID, port);
|
||||
Ports.Add(port.SyncVarID, port);
|
||||
//PollForState(port.SyncVarID);
|
||||
//PollForState(port.ResolutionVarID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
|
||||
// Create Device -> Constructor fires
|
||||
// PreActivations get called
|
||||
// CustomActivate Gets Called Anything that is involved with this single class Ex: Connection, Setup Feedback, Etc.
|
||||
// After this point all devices are ready for interaction
|
||||
// PostActivation gets called. Use this for interClass activation.
|
||||
CommunicationMonitor.Start();
|
||||
OnlineFeedback = new BoolFeedback(() => { return OnlineStatus; });
|
||||
|
||||
|
||||
//CrestronConsole.AddNewConsoleCommand(SendLine, "send" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private void PostActivation()
|
||||
{
|
||||
Debug.Console(2, this, "EvertzEndpoint Post Activation");
|
||||
if (_ControllerKey != null)
|
||||
{
|
||||
StatusServer = DeviceManager.GetDeviceForKey(_ControllerKey) as EvertzEndpointStatusServer;
|
||||
StatusServer.RegisterEvertzEndpoint(this);
|
||||
|
||||
// RegisterStatusServer();
|
||||
// SendStatusRequest();
|
||||
}
|
||||
// PollAll();
|
||||
}
|
||||
|
||||
void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
|
||||
{
|
||||
if (programEventType == eProgramStatusEventType.Stopping)
|
||||
{
|
||||
Debug.Console(1, this, "Program stopping. Disabling EvertzStatusServer");
|
||||
if (StatusServerId != null)
|
||||
{
|
||||
//UnregisterServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessServerStatusRequest(EvertsStatusRequesstResponse status)
|
||||
{
|
||||
// var status = JsonConvert.DeserializeObject<EvertsStatusRequesstResponse>(SendStatusRequest());
|
||||
if (status.error != null)
|
||||
{
|
||||
|
||||
}
|
||||
else if (status.data != null)
|
||||
{
|
||||
foreach (var server in status.data.servers)
|
||||
{
|
||||
if (server.name == string.Format("{0}-{1}", this.Name, StatusServer.Address))
|
||||
{
|
||||
StatusServerId = server.id;
|
||||
Debug.Console(2, this, "EvertzEndpoint {0} StatusServer {1} Registered ID {2}", Name, StatusServer.Name, StatusServerId);
|
||||
/*
|
||||
|
||||
foreach (var port in Ports)
|
||||
{
|
||||
// TODO JTA: This needs a better check
|
||||
// you get a {"status": "success"} or "error": "error to register notification- Variable exists.."
|
||||
if (!server.notify.parameters.Contains(port.Value.ResolutionVarID))
|
||||
{
|
||||
RegisterForNotification(StatusServerId, port.Value.ResolutionVarID);
|
||||
}
|
||||
if (!server.notify.parameters.Contains(port.Value.ResolutionVarID))
|
||||
{
|
||||
RegisterForNotification(StatusServerId, port.Value.SyncVarID);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
StatusServerId = null;
|
||||
}
|
||||
}
|
||||
private void RegisterServerWithEndpoint()
|
||||
{
|
||||
/*
|
||||
var registrationResult = RegisterServer(StatusServer.Address, string.Format("{0}-{1}", this.Name, StatusServer.Address), StatusServer.Server.Port.ToString());
|
||||
Debug.Console(2, this, "EvertzEndpointStatusServer Registration Result with device {0}\n{1}", Address, registrationResult);
|
||||
if (registrationResult.Contains("success"))
|
||||
{
|
||||
RegisterStatusServer();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(0, this, "EvertzEndpointStatusServer RegisterServerWithEndpoint with device {0}\n{1}", Address, registrationResult);
|
||||
|
||||
}
|
||||
* */
|
||||
}
|
||||
|
||||
public void PollAll()
|
||||
{
|
||||
string collection = "";
|
||||
foreach (var parameter in Ports)
|
||||
{
|
||||
if (parameter.Key.Contains("@"))
|
||||
{
|
||||
collection = collection + parameter.Key + ",";
|
||||
}
|
||||
}
|
||||
collection = collection.Substring(0, collection.Length - 1);
|
||||
SendGetRequest(collection);
|
||||
}
|
||||
public void PollForState(string varId)
|
||||
{
|
||||
try
|
||||
{
|
||||
SendGetRequest(varId);
|
||||
//var returnState = JsonConvert.DeserializeObject<EvertzPortRestResponse>(SendGetRequest(varId));
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, this, "PollForState {0}", e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void ProcessGetParameterResponse(EvertzPortRestResponse response)
|
||||
{
|
||||
var PortObject = Ports[response.id];
|
||||
if (response.name == "Input Status")
|
||||
{
|
||||
if (response.value == "Missing") { PortObject.SyncDetected = false; }
|
||||
else { PortObject.SyncDetected = true; }
|
||||
}
|
||||
}
|
||||
public void SendGetRequest(string s)
|
||||
{
|
||||
Client.SendText("v.api/apis/EV/GET/parameter/{0}", s);
|
||||
}
|
||||
|
||||
public void SendStatusRequest()
|
||||
{
|
||||
Client.SendText("/v.api/apis/EV/SERVERSTATUS");
|
||||
}
|
||||
public void RegisterServer(string hostname, string servername, string port)
|
||||
{
|
||||
Client.SendText("v.api/apis/EV/SERVERADD/server/{0}/{1}/{2}/udp", hostname, servername, port);
|
||||
}
|
||||
public void UnregisterServer()
|
||||
{
|
||||
if (StatusServerId != null)
|
||||
{
|
||||
Client.SendTextNoResponse("v.api/apis/EV/SERVERDEL/server/{0}", StatusServerId);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO JTA: Craete a UnregisterServerFast using DispatchASync.
|
||||
public void RegisterForNotification(string varId)
|
||||
{
|
||||
Client.SendText("v.api/apis/EV/NOTIFYADD/parameter/{0}/{1}", StatusServerId, varId);
|
||||
}
|
||||
|
||||
|
||||
void Client_ResponseRecived(object sender, GenericHttpClientEventArgs e)
|
||||
{
|
||||
if (e.Error == HTTP_CALLBACK_ERROR.COMPLETED)
|
||||
{
|
||||
if (e.RequestPath.Contains("GET/parameter/"))
|
||||
{
|
||||
// Get Parameter response
|
||||
if (!e.ResponseText.Contains("["))
|
||||
ProcessGetParameterResponse(JsonConvert.DeserializeObject<EvertzPortRestResponse>(e.ResponseText));
|
||||
else if (e.ResponseText.Contains("["))
|
||||
{
|
||||
List<EvertzPortRestResponse> test = JsonConvert.DeserializeObject<List<EvertzPortRestResponse>>(e.ResponseText);
|
||||
foreach (var thing in test)
|
||||
{
|
||||
ProcessGetParameterResponse(thing);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if (e.RequestPath.Contains("SERVERSTATUS"))
|
||||
{
|
||||
PollAll();
|
||||
ProcessServerStatusRequest(JsonConvert.DeserializeObject<EvertsStatusRequesstResponse>(e.ResponseText));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public class EvertzPortsRestResponse
|
||||
{
|
||||
List<EvertzPortRestResponse> test;
|
||||
}
|
||||
public class EvertzPortRestResponse
|
||||
{
|
||||
public string id;
|
||||
public string name;
|
||||
public string type;
|
||||
public string value;
|
||||
|
||||
}
|
||||
|
||||
public class EvertzEndpointPort
|
||||
{
|
||||
public string PortName;
|
||||
public string SyncVarID;
|
||||
public string ResolutionVarID;
|
||||
public bool SyncDetected;
|
||||
public string Resolution;
|
||||
public BoolFeedback SyncDetectedFeedback;
|
||||
|
||||
public EvertzEndpointPort (string portName, string syncVarId, string resolutionVarId)
|
||||
{
|
||||
PortName = portName;
|
||||
SyncVarID = syncVarId;
|
||||
ResolutionVarID = resolutionVarId;
|
||||
SyncDetectedFeedback = new BoolFeedback(() => { return SyncDetected; });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class EvertzEndpointPropertiesConfig
|
||||
{
|
||||
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
||||
|
||||
public ControlPropertiesConfig Control { get; set; }
|
||||
public string userName { get; set; }
|
||||
public string password { get; set; }
|
||||
public string address { get; set; }
|
||||
public string controllerKey { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
public class EvertzEndpointVarIds
|
||||
{
|
||||
private string HdmiPort01SyncStatus = "136.0";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.Net.Http;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Core.DebugThings;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
public class GenericHttpClient : Device, IBasicCommunication
|
||||
{
|
||||
public HttpClient Client;
|
||||
public event EventHandler<GenericHttpClientEventArgs> ResponseRecived;
|
||||
|
||||
public GenericHttpClient(string key, string name, string hostname)
|
||||
: base(key, name)
|
||||
{
|
||||
Client = new HttpClient();
|
||||
Client.HostName = hostname;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
public void SendText(string path)
|
||||
{
|
||||
HttpClientRequest request = new HttpClientRequest();
|
||||
string url = string.Format("http://{0}/{1}", Client.HostName, path);
|
||||
request.Url = new UrlParser(url);
|
||||
HttpClient.DISPATCHASYNC_ERROR error = Client.DispatchAsyncEx(request, Response, request);
|
||||
Debug.Console(2, this, "GenericHttpClient SentRequest TX:'{0}'", url);
|
||||
}
|
||||
public void SendText(string format, params object[] items)
|
||||
{
|
||||
HttpClientRequest request = new HttpClientRequest();
|
||||
string url = string.Format("http://{0}/{1}", Client.HostName, string.Format(format, items));
|
||||
request.Url = new UrlParser(url);
|
||||
HttpClient.DISPATCHASYNC_ERROR error = Client.DispatchAsyncEx(request, Response, request);
|
||||
Debug.Console(2, this, "GenericHttpClient SentRequest TX:'{0}'", url);
|
||||
}
|
||||
|
||||
public void SendTextNoResponse(string format, params object[] items)
|
||||
{
|
||||
HttpClientRequest request = new HttpClientRequest();
|
||||
string url = string.Format("http://{0}/{1}", Client.HostName, string.Format(format, items));
|
||||
request.Url = new UrlParser(url);
|
||||
Client.Dispatch(request);
|
||||
Debug.Console(2, this, "GenericHttpClient SentRequest TX:'{0}'", url);
|
||||
}
|
||||
private void Response(HttpClientResponse response, HTTP_CALLBACK_ERROR error, object request)
|
||||
{
|
||||
if (error == HTTP_CALLBACK_ERROR.COMPLETED)
|
||||
{
|
||||
var responseReceived = response;
|
||||
|
||||
if (responseReceived.ContentString.Length > 0)
|
||||
{
|
||||
if (ResponseRecived != null)
|
||||
ResponseRecived(this, new GenericHttpClientEventArgs(responseReceived.ContentString, (request as HttpClientRequest).Url.ToString(), error));
|
||||
|
||||
Debug.Console(2, this, "GenericHttpClient ResponseReceived");
|
||||
Debug.Console(2, this, "RX:{0}", responseReceived.ContentString);
|
||||
Debug.Console(2, this, "TX:{0}", (request as HttpClientRequest).Url.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#region IBasicCommunication Members
|
||||
|
||||
public void SendBytes(byte[] bytes)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region ICommunicationReceiver Members
|
||||
|
||||
public event EventHandler<GenericCommMethodReceiveBytesArgs> BytesReceived;
|
||||
|
||||
public void Connect()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsConnected
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public event EventHandler<GenericCommMethodReceiveTextArgs> TextReceived;
|
||||
|
||||
#endregion
|
||||
}
|
||||
public class GenericHttpClientEventArgs : EventArgs
|
||||
{
|
||||
public string ResponseText { get; private set; }
|
||||
public string RequestPath { get; private set; }
|
||||
public HTTP_CALLBACK_ERROR Error { get; set; }
|
||||
public GenericHttpClientEventArgs(string response, string request, HTTP_CALLBACK_ERROR error)
|
||||
{
|
||||
ResponseText = response;
|
||||
RequestPath = request;
|
||||
Error = error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,407 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.GeneralIO;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
using PepperDash.Essentials.Core.CrestronIO;
|
||||
|
||||
using PepperDash.Essentials.Devices.Common;
|
||||
using PepperDash.Essentials.Devices.Common.DSP;
|
||||
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||
using PepperDash.Essentials.Devices.Common.Occupancy;
|
||||
using PepperDash.Essentials.Devices.Common.Environment;
|
||||
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
public class DeviceFactory
|
||||
{
|
||||
public static IKeyed GetDevice(DeviceConfig dc)
|
||||
{
|
||||
var key = dc.Key;
|
||||
var name = dc.Name;
|
||||
var type = dc.Type;
|
||||
var properties = dc.Properties;
|
||||
var propAnon = new {};
|
||||
JsonConvert.DeserializeAnonymousType(dc.Properties.ToString(), propAnon);
|
||||
|
||||
var typeName = dc.Type.ToLower();
|
||||
var groupName = dc.Group.ToLower();
|
||||
|
||||
if (typeName == "appletv")
|
||||
{
|
||||
var irCont = IRPortHelper.GetIrOutputPortController(dc);
|
||||
return new AppleTV(key, name, irCont);
|
||||
}
|
||||
else if (typeName == "analogwaylivecore")
|
||||
{
|
||||
var comm = CommFactory.CreateCommForDevice(dc);
|
||||
var props = JsonConvert.DeserializeObject<AnalogWayLiveCorePropertiesConfig>(
|
||||
properties.ToString());
|
||||
return new AnalogWayLiveCore(key, name, comm, props);
|
||||
}
|
||||
else if (typeName == "basicirdisplay")
|
||||
{
|
||||
var ir = IRPortHelper.GetIrPort(properties);
|
||||
if (ir != null)
|
||||
{
|
||||
var display = new BasicIrDisplay(key, name, ir.Port, ir.FileName);
|
||||
display.IrPulseTime = 200; // Set default pulse time for IR commands.
|
||||
return display;
|
||||
}
|
||||
}
|
||||
|
||||
else if (typeName == "biamptesira")
|
||||
{
|
||||
var comm = CommFactory.CreateCommForDevice(dc);
|
||||
var props = JsonConvert.DeserializeObject<BiampTesiraFortePropertiesConfig>(
|
||||
properties.ToString());
|
||||
return new BiampTesiraForteDsp(key, name, comm, props);
|
||||
}
|
||||
|
||||
|
||||
else if (typeName == "cameravisca")
|
||||
{
|
||||
var comm = CommFactory.CreateCommForDevice(dc);
|
||||
var props = JsonConvert.DeserializeObject<Cameras.CameraPropertiesConfig>(
|
||||
properties.ToString());
|
||||
return new Cameras.CameraVisca(key, name, comm, props);
|
||||
}
|
||||
|
||||
else if (typeName == "cenrfgwex")
|
||||
{
|
||||
return CenRfgwController.GetNewExGatewayController(key, name,
|
||||
properties.Value<string>("id"), properties.Value<string>("gatewayType"));
|
||||
}
|
||||
|
||||
else if (typeName == "cenerfgwpoe")
|
||||
{
|
||||
return CenRfgwController.GetNewErGatewayController(key, name,
|
||||
properties.Value<string>("id"), properties.Value<string>("gatewayType"));
|
||||
}
|
||||
|
||||
else if (groupName == "discplayer") // (typeName == "irbluray")
|
||||
{
|
||||
if (properties["control"]["method"].Value<string>() == "ir")
|
||||
{
|
||||
var irCont = IRPortHelper.GetIrOutputPortController(dc);
|
||||
return new IRBlurayBase(key, name, irCont);
|
||||
}
|
||||
else if (properties["control"]["method"].Value<string>() == "com")
|
||||
{
|
||||
Debug.Console(0, "[{0}] COM Device type not implemented YET!", key);
|
||||
}
|
||||
}
|
||||
else if (typeName == "digitallogger")
|
||||
{
|
||||
// var comm = CommFactory.CreateCommForDevice(dc);
|
||||
var props = JsonConvert.DeserializeObject<DigitalLoggerPropertiesConfig>(
|
||||
properties.ToString());
|
||||
return new DigitalLogger(key, name, props);
|
||||
}
|
||||
else if (groupName == "evertzendpoint")
|
||||
{
|
||||
// var comm = CommFactory.CreateCommForDevice(dc);
|
||||
var props = JsonConvert.DeserializeObject<EvertzEndpointPropertiesConfig>(
|
||||
properties.ToString());
|
||||
return new EvertzEndpoint(key, name, props, typeName);
|
||||
}
|
||||
else if (typeName == "evertzendpointstatusserver")
|
||||
{
|
||||
var server = CommFactory.CreateCommForDevice(dc) as GenericUdpServer;
|
||||
|
||||
var props = JsonConvert.DeserializeObject<EvertzEndpointStatusServerPropertiesConfig>(
|
||||
properties.ToString());
|
||||
return new EvertzEndpointStatusServer(key, name, server, props);
|
||||
}
|
||||
else if (typeName == "genericaudiooutwithvolume")
|
||||
{
|
||||
var zone = dc.Properties.Value<uint>("zone");
|
||||
return new GenericAudioOutWithVolume(key, name,
|
||||
dc.Properties.Value<string>("volumeDeviceKey"), zone);
|
||||
}
|
||||
|
||||
else if (groupName == "genericsource")
|
||||
{
|
||||
return new GenericSource(key, name);
|
||||
}
|
||||
|
||||
else if (typeName == "inroompc")
|
||||
{
|
||||
return new InRoomPc(key, name);
|
||||
}
|
||||
|
||||
else if (typeName == "laptop")
|
||||
{
|
||||
return new Laptop(key, name);
|
||||
}
|
||||
|
||||
else if (typeName == "mockvc")
|
||||
{
|
||||
return new VideoCodec.MockVC(dc);
|
||||
}
|
||||
|
||||
else if (typeName == "mockac")
|
||||
{
|
||||
var props = JsonConvert.DeserializeObject<AudioCodec.MockAcPropertiesConfig>(properties.ToString());
|
||||
return new AudioCodec.MockAC(key, name, props);
|
||||
}
|
||||
|
||||
else if (typeName.StartsWith("ciscospark"))
|
||||
{
|
||||
var comm = CommFactory.CreateCommForDevice(dc);
|
||||
return new VideoCodec.Cisco.CiscoSparkCodec(dc, comm);
|
||||
}
|
||||
|
||||
else if (typeName == "zoomroom")
|
||||
{
|
||||
var comm = CommFactory.CreateCommForDevice(dc);
|
||||
return new VideoCodec.ZoomRoom.ZoomRoom(dc, comm);
|
||||
}
|
||||
|
||||
else if (typeName == "digitalinput")
|
||||
{
|
||||
var props = JsonConvert.DeserializeObject<IOPortConfig>(properties.ToString());
|
||||
|
||||
IDigitalInputPorts portDevice;
|
||||
|
||||
if (props.PortDeviceKey == "processor")
|
||||
portDevice = Global.ControlSystem as IDigitalInputPorts;
|
||||
else
|
||||
portDevice = DeviceManager.GetDeviceForKey(props.PortDeviceKey) as IDigitalInputPorts;
|
||||
|
||||
if (portDevice == null)
|
||||
Debug.Console(0, "ERROR: Unable to add digital input device with key '{0}'. Port Device does not support digital inputs", key);
|
||||
else
|
||||
{
|
||||
var cs = (portDevice as CrestronControlSystem);
|
||||
if (cs == null)
|
||||
{
|
||||
Debug.Console(0, "ERROR: Port device for [{0}] is not control system", props.PortDeviceKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (cs.SupportsVersiport)
|
||||
{
|
||||
Debug.Console(1, "Attempting to add Digital Input device to Versiport port '{0}'", props.PortNumber);
|
||||
|
||||
if (props.PortNumber > cs.NumberOfVersiPorts)
|
||||
{
|
||||
Debug.Console(0, "WARNING: Cannot add Vesiport {0} on {1}. Out of range",
|
||||
props.PortNumber, props.PortDeviceKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
Versiport vp = cs.VersiPorts[props.PortNumber];
|
||||
|
||||
if (!vp.Registered)
|
||||
{
|
||||
var regSuccess = vp.Register();
|
||||
if (regSuccess == eDeviceRegistrationUnRegistrationResponse.Success)
|
||||
{
|
||||
Debug.Console(1, "Successfully Created Digital Input Device on Versiport");
|
||||
return new GenericVersiportDigitalInputDevice(key, vp, props);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(0, "WARNING: Attempt to register versiport {0} on device with key '{1}' failed: {2}",
|
||||
props.PortNumber, props.PortDeviceKey, regSuccess);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cs.SupportsDigitalInput)
|
||||
{
|
||||
Debug.Console(1, "Attempting to add Digital Input device to Digital Input port '{0}'", props.PortNumber);
|
||||
|
||||
if (props.PortNumber > cs.NumberOfDigitalInputPorts)
|
||||
{
|
||||
Debug.Console(0, "WARNING: Cannot register DIO port {0} on {1}. Out of range",
|
||||
props.PortNumber, props.PortDeviceKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
DigitalInput digitalInput = cs.DigitalInputPorts[props.PortNumber];
|
||||
|
||||
if (!digitalInput.Registered)
|
||||
{
|
||||
if (digitalInput.Register() == eDeviceRegistrationUnRegistrationResponse.Success)
|
||||
{
|
||||
Debug.Console(1, "Successfully Created Digital Input Device on Digital Input");
|
||||
return new GenericDigitalInputDevice(key, digitalInput);
|
||||
}
|
||||
else
|
||||
Debug.Console(0, "WARNING: Attempt to register digital input {0} on device with key '{1}' failed.",
|
||||
props.PortNumber, props.PortDeviceKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (typeName == "relayoutput")
|
||||
{
|
||||
var props = JsonConvert.DeserializeObject<IOPortConfig>(properties.ToString());
|
||||
|
||||
IRelayPorts portDevice;
|
||||
|
||||
if (props.PortDeviceKey == "processor")
|
||||
portDevice = Global.ControlSystem as IRelayPorts;
|
||||
else
|
||||
portDevice = DeviceManager.GetDeviceForKey(props.PortDeviceKey) as IRelayPorts;
|
||||
|
||||
if (portDevice == null)
|
||||
Debug.Console(0, "Unable to add relay device with key '{0}'. Port Device does not support relays", key);
|
||||
else
|
||||
{
|
||||
var cs = (portDevice as CrestronControlSystem);
|
||||
|
||||
if (cs != null)
|
||||
{
|
||||
// The relay is on a control system processor
|
||||
if (!cs.SupportsRelay || props.PortNumber > cs.NumberOfRelayPorts)
|
||||
{
|
||||
Debug.Console(0, "Port Device: {0} does not support relays or does not have enough relays");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The relay is on another device type
|
||||
|
||||
if (props.PortNumber > portDevice.NumberOfRelayPorts)
|
||||
{
|
||||
Debug.Console(0, "Port Device: {0} does not have enough relays");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Relay relay = portDevice.RelayPorts[props.PortNumber];
|
||||
|
||||
if (!relay.Registered)
|
||||
{
|
||||
if (relay.Register() == eDeviceRegistrationUnRegistrationResponse.Success)
|
||||
return new GenericRelayDevice(key, relay);
|
||||
else
|
||||
Debug.Console(0, "Attempt to register relay {0} on device with key '{1}' failed.", props.PortNumber, props.PortDeviceKey);
|
||||
}
|
||||
|
||||
// Future: Check if portDevice is 3-series card or other non control system that supports versiports
|
||||
}
|
||||
}
|
||||
|
||||
else if (typeName == "microphoneprivacycontroller")
|
||||
{
|
||||
var props = JsonConvert.DeserializeObject<Microphones.MicrophonePrivacyControllerConfig>(properties.ToString());
|
||||
|
||||
return new Microphones.MicrophonePrivacyController(key, props);
|
||||
}
|
||||
else if (typeName == "roku")
|
||||
{
|
||||
var irCont = IRPortHelper.GetIrOutputPortController(dc);
|
||||
return new Roku2(key, name, irCont);
|
||||
}
|
||||
|
||||
else if (groupName == "settopbox") //(typeName == "irstbbase")
|
||||
{
|
||||
var irCont = IRPortHelper.GetIrOutputPortController(dc);
|
||||
var config = dc.Properties.ToObject<SetTopBoxPropertiesConfig>();
|
||||
var stb = new IRSetTopBoxBase(key, name, irCont, config);
|
||||
|
||||
//stb.HasDvr = properties.Value<bool>("hasDvr");
|
||||
var listName = properties.Value<string>("presetsList");
|
||||
if (listName != null)
|
||||
stb.LoadPresets(listName);
|
||||
return stb;
|
||||
}
|
||||
else if (typeName == "tvonecorio")
|
||||
{
|
||||
var comm = CommFactory.CreateCommForDevice(dc);
|
||||
var props = JsonConvert.DeserializeObject<TVOneCorioPropertiesConfig>(
|
||||
properties.ToString());
|
||||
return new TVOneCorio(key, name, comm, props);
|
||||
}
|
||||
|
||||
|
||||
else if (typeName == "glsoirccn")
|
||||
{
|
||||
var comm = CommFactory.GetControlPropertiesConfig(dc);
|
||||
|
||||
GlsOccupancySensorBase occSensor = null;
|
||||
|
||||
occSensor = new GlsOirCCn(comm.CresnetIdInt, Global.ControlSystem);
|
||||
|
||||
if (occSensor != null)
|
||||
return new EssentialsGlsOccupancySensorBaseController(key, name, occSensor);
|
||||
else
|
||||
Debug.Console(0, "ERROR: Unable to create Occupancy Sensor Device. Key: '{0}'", key);
|
||||
}
|
||||
|
||||
else if (typeName == "glsodtccn")
|
||||
{
|
||||
var comm = CommFactory.GetControlPropertiesConfig(dc);
|
||||
|
||||
GlsOccupancySensorBase occSensor = null;
|
||||
|
||||
occSensor = new GlsOdtCCn(comm.CresnetIdInt, Global.ControlSystem);
|
||||
|
||||
if (occSensor != null)
|
||||
return new EssentialsGlsOccupancySensorBaseController(key, name, occSensor);
|
||||
else
|
||||
Debug.Console(0, "ERROR: Unable to create Occupancy Sensor Device. Key: '{0}'", key);
|
||||
}
|
||||
|
||||
else if (groupName == "lighting")
|
||||
{
|
||||
if (typeName == "lutronqs")
|
||||
{
|
||||
var comm = CommFactory.CreateCommForDevice(dc);
|
||||
|
||||
var props = JsonConvert.DeserializeObject<Environment.Lutron.LutronQuantumPropertiesConfig>(properties.ToString());
|
||||
|
||||
return new Environment.Lutron.LutronQuantumArea(key, name, comm, props);
|
||||
}
|
||||
else if (typeName == "din8sw8")
|
||||
{
|
||||
var comm = CommFactory.GetControlPropertiesConfig(dc);
|
||||
|
||||
return new Environment.Lighting.Din8sw8Controller(key, comm.CresnetIdInt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if (groupName == "environment")
|
||||
{
|
||||
if (typeName == "shadecontroller")
|
||||
{
|
||||
var props = JsonConvert.DeserializeObject<Core.Shades.ShadeControllerConfigProperties>(properties.ToString());
|
||||
|
||||
return new Core.Shades.ShadeController(key, name, props);
|
||||
}
|
||||
else if (typeName == "relaycontrolledshade")
|
||||
{
|
||||
var props = JsonConvert.DeserializeObject<Environment.Somfy.RelayControlledShadeConfigProperties>(properties.ToString());
|
||||
|
||||
return new Environment.Somfy.RelayControlledShade(key, name, props);
|
||||
}
|
||||
|
||||
}
|
||||
//else if (typeName == "qscdsp")
|
||||
//{
|
||||
// var comm = CommFactory.CreateCommForDevice(dc);
|
||||
// var props = JsonConvert.DeserializeObject<QscDspPropertiesConfig>(
|
||||
// properties.ToString());
|
||||
// return new QscDsp(key, name, comm, props);
|
||||
//}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
public class GenericSource : Device, IUiDisplayInfo, IRoutingOutputs, IUsageTracking
|
||||
{
|
||||
|
||||
public uint DisplayUiType { get { return DisplayUiConstants.TypeNoControls; } }
|
||||
|
||||
public GenericSource(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
|
||||
AnyOut = new RoutingOutputPort(RoutingPortNames.AnyOut, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, null, this);
|
||||
OutputPorts = new RoutingPortCollection<RoutingOutputPort> { AnyOut };
|
||||
}
|
||||
|
||||
#region IRoutingOutputs Members
|
||||
|
||||
public RoutingOutputPort AnyOut { get; private set; }
|
||||
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region IUsageTracking Members
|
||||
|
||||
public UsageTracking UsageTracker { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class AnalogWayLiveCorePropertiesConfig
|
||||
{
|
||||
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
||||
|
||||
public ControlPropertiesConfig Control { get; set; }
|
||||
public string userName { get; set; }
|
||||
public string password { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
|
||||
public class AnalogWayLiveCore : Device
|
||||
{
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
public CommunicationGather PortGather { get; private set; }
|
||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||
public string userName;
|
||||
public string password;
|
||||
private bool OnlineStatus;
|
||||
public BoolFeedback OnlineFeedback;
|
||||
private ushort CurrentPreset;
|
||||
public IntFeedback PresetFeedback;
|
||||
|
||||
// new public Dictionary<string, QscDspLevelControl> LevelControlPoints { get; private set; }
|
||||
// public List<QscDspPresets> PresetList = new List<QscDspPresets>();
|
||||
|
||||
public bool isSubscribed;
|
||||
|
||||
private CTimer SubscriptionTimer;
|
||||
|
||||
CrestronQueue CommandQueue;
|
||||
|
||||
bool CommandQueueInProgress = false;
|
||||
|
||||
//new public Dictionary<string, DspControlPoint> DialerControlPoints { get; private set; }
|
||||
|
||||
//new public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Shows received lines as hex
|
||||
/// </summary>
|
||||
public bool ShowHexResponse { get; set; }
|
||||
|
||||
public AnalogWayLiveCore(string key, string name, IBasicCommunication comm, AnalogWayLiveCorePropertiesConfig props) :
|
||||
base(key, name)
|
||||
{
|
||||
|
||||
this.userName = props.userName;
|
||||
this.password = props.password;
|
||||
CommandQueue = new CrestronQueue(100);
|
||||
|
||||
|
||||
Communication = comm;
|
||||
|
||||
var socket = comm as ISocketStatus;
|
||||
if (socket != null)
|
||||
{
|
||||
// This instance uses IP control
|
||||
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This instance uses RS-232 control
|
||||
}
|
||||
PortGather = new CommunicationGather(Communication, "\x0a");
|
||||
PortGather.LineReceived += this.Port_LineReceived;
|
||||
if (props.CommunicationMonitorProperties != null)
|
||||
{
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
//#warning Need to deal with this poll string
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 120000, 120000, 300000, "System.Status\x0A\x0D");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
|
||||
Communication.Connect();
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
CommunicationMonitor.Start();
|
||||
|
||||
OnlineFeedback = new BoolFeedback(() => { return OnlineStatus; });
|
||||
PresetFeedback = new IntFeedback(() => { return CurrentPreset; });
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(SendLine, "send" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
return true;
|
||||
}
|
||||
|
||||
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
||||
{
|
||||
Debug.Console(2, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
|
||||
|
||||
if (e.Client.IsConnected)
|
||||
{
|
||||
OnlineStatus = true;
|
||||
OnlineFeedback.FireUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
OnlineStatus = false;
|
||||
OnlineFeedback.FireUpdate();
|
||||
if (SubscriptionTimer != null)
|
||||
{
|
||||
SubscriptionTimer.Stop();
|
||||
SubscriptionTimer = null;
|
||||
}
|
||||
|
||||
isSubscribed = false;
|
||||
CommandQueue.Clear();
|
||||
CommandQueueInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initiates the subscription process to the DSP
|
||||
/// </summary>
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handles a response message from the DSP
|
||||
/// </summary>
|
||||
/// <param name="dev"></param>
|
||||
/// <param name="args"></param>
|
||||
void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
|
||||
{
|
||||
Debug.Console(2, this, "TVOneCurio RX: '{0}'", args.Text);
|
||||
try
|
||||
{
|
||||
if (args.Text.IndexOf("login") > -1)
|
||||
{
|
||||
SendLine(string.Format("Login({0},{1})", this.userName, this.password));
|
||||
}
|
||||
else if (args.Text.IndexOf("!Done Preset.Take =") > -1)
|
||||
{
|
||||
|
||||
string presetNumberParse = args.Text.Remove(0, args.Text.IndexOf("=") + 2);
|
||||
|
||||
Debug.Console(1, this, "Preset Parse: {0}", presetNumberParse);
|
||||
CurrentPreset = ushort.Parse(presetNumberParse);
|
||||
PresetFeedback.FireUpdate();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "Error parsing response: '{0}'\n{1}", args.Text, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command to the DSP (with delimiter appended)
|
||||
/// </summary>
|
||||
/// <param name="s">Command to send</param>
|
||||
public void SendLine(string s)
|
||||
{
|
||||
Debug.Console(1, this, "TVOne Cusio TX: '{0}'", s);
|
||||
Communication.SendText(s + "\x0d\x0a");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a command from a child module to the queue
|
||||
/// </summary>
|
||||
/// <param name="command">Command object from child module</param>
|
||||
public void EnqueueCommand(QueuedCommand commandToEnqueue)
|
||||
{
|
||||
CommandQueue.Enqueue(commandToEnqueue);
|
||||
//Debug.Console(1, this, "Command (QueuedCommand) Enqueued '{0}'. CommandQueue has '{1}' Elements.", commandToEnqueue.Command, CommandQueue.Count);
|
||||
|
||||
if(!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a raw string command to the queue
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
public void EnqueueCommand(string command)
|
||||
{
|
||||
CommandQueue.Enqueue(command);
|
||||
//Debug.Console(1, this, "Command (string) Enqueued '{0}'. CommandQueue has '{1}' Elements.", command, CommandQueue.Count);
|
||||
|
||||
if (!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the next queued command to the DSP
|
||||
/// </summary>
|
||||
void SendNextQueuedCommand()
|
||||
{
|
||||
if (Communication.IsConnected && !CommandQueue.IsEmpty)
|
||||
{
|
||||
CommandQueueInProgress = true;
|
||||
|
||||
if (CommandQueue.Peek() is QueuedCommand)
|
||||
{
|
||||
QueuedCommand nextCommand = new QueuedCommand();
|
||||
|
||||
nextCommand = (QueuedCommand)CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand.Command);
|
||||
}
|
||||
else
|
||||
{
|
||||
string nextCommand = (string)CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void CallPreset(ushort presetNumber)
|
||||
{
|
||||
SendLine(string.Format("Preset.Take = {0}", presetNumber));
|
||||
// SendLine("cgp 1");
|
||||
}
|
||||
|
||||
public class QueuedCommand
|
||||
{
|
||||
public string Command { get; set; }
|
||||
public string AttributeCode { get; set; }
|
||||
// public QscDspControlPoint ControlPoint { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
|
||||
public class TVOneCorio : Device
|
||||
{
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
public CommunicationGather PortGather { get; private set; }
|
||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||
public string userName;
|
||||
public string password;
|
||||
private bool OnlineStatus;
|
||||
public BoolFeedback OnlineFeedback;
|
||||
private ushort CurrentPreset;
|
||||
public IntFeedback PresetFeedback;
|
||||
|
||||
// new public Dictionary<string, QscDspLevelControl> LevelControlPoints { get; private set; }
|
||||
// public List<QscDspPresets> PresetList = new List<QscDspPresets>();
|
||||
|
||||
public bool isSubscribed;
|
||||
|
||||
private CTimer SubscriptionTimer;
|
||||
|
||||
CrestronQueue CommandQueue;
|
||||
|
||||
bool CommandQueueInProgress = false;
|
||||
|
||||
//new public Dictionary<string, DspControlPoint> DialerControlPoints { get; private set; }
|
||||
|
||||
//new public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Shows received lines as hex
|
||||
/// </summary>
|
||||
public bool ShowHexResponse { get; set; }
|
||||
|
||||
public TVOneCorio(string key, string name, IBasicCommunication comm, TVOneCorioPropertiesConfig props) :
|
||||
base(key, name)
|
||||
{
|
||||
|
||||
this.userName = props.userName;
|
||||
this.password = props.password;
|
||||
CommandQueue = new CrestronQueue(100);
|
||||
|
||||
|
||||
Communication = comm;
|
||||
|
||||
var socket = comm as ISocketStatus;
|
||||
if (socket != null)
|
||||
{
|
||||
// This instance uses IP control
|
||||
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This instance uses RS-232 control
|
||||
}
|
||||
PortGather = new CommunicationGather(Communication, "\x0a");
|
||||
PortGather.LineReceived += this.Port_LineReceived;
|
||||
if (props.CommunicationMonitorProperties != null)
|
||||
{
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
//#warning Need to deal with this poll string
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 120000, 120000, 300000, "System.Status\x0A\x0D");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
|
||||
Communication.Connect();
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
CommunicationMonitor.Start();
|
||||
|
||||
OnlineFeedback = new BoolFeedback(() => { return OnlineStatus; });
|
||||
PresetFeedback = new IntFeedback(() => { return CurrentPreset; });
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(SendLine, "send" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
return true;
|
||||
}
|
||||
|
||||
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
||||
{
|
||||
Debug.Console(2, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
|
||||
|
||||
if (e.Client.IsConnected)
|
||||
{
|
||||
OnlineStatus = true;
|
||||
OnlineFeedback.FireUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
OnlineStatus = false;
|
||||
OnlineFeedback.FireUpdate();
|
||||
if (SubscriptionTimer != null)
|
||||
{
|
||||
SubscriptionTimer.Stop();
|
||||
SubscriptionTimer = null;
|
||||
}
|
||||
|
||||
isSubscribed = false;
|
||||
CommandQueue.Clear();
|
||||
CommandQueueInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initiates the subscription process to the DSP
|
||||
/// </summary>
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handles a response message from the DSP
|
||||
/// </summary>
|
||||
/// <param name="dev"></param>
|
||||
/// <param name="args"></param>
|
||||
void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
|
||||
{
|
||||
Debug.Console(2, this, "TVOneCurio RX: '{0}'", args.Text);
|
||||
try
|
||||
{
|
||||
if (args.Text.IndexOf("login") > -1)
|
||||
{
|
||||
SendLine(string.Format("Login({0},{1})", this.userName, this.password));
|
||||
}
|
||||
else if (args.Text.IndexOf("!Done Preset.Take =") > -1)
|
||||
{
|
||||
|
||||
string presetNumberParse = args.Text.Remove(0, args.Text.IndexOf("=") + 2);
|
||||
|
||||
Debug.Console(1, this, "Preset Parse: {0}", presetNumberParse);
|
||||
CurrentPreset = ushort.Parse(presetNumberParse);
|
||||
PresetFeedback.FireUpdate();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "Error parsing response: '{0}'\n{1}", args.Text, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command to the DSP (with delimiter appended)
|
||||
/// </summary>
|
||||
/// <param name="s">Command to send</param>
|
||||
public void SendLine(string s)
|
||||
{
|
||||
Debug.Console(1, this, "TVOne Cusio TX: '{0}'", s);
|
||||
Communication.SendText(s + "\x0d\x0a");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a command from a child module to the queue
|
||||
/// </summary>
|
||||
/// <param name="command">Command object from child module</param>
|
||||
public void EnqueueCommand(QueuedCommand commandToEnqueue)
|
||||
{
|
||||
CommandQueue.Enqueue(commandToEnqueue);
|
||||
//Debug.Console(1, this, "Command (QueuedCommand) Enqueued '{0}'. CommandQueue has '{1}' Elements.", commandToEnqueue.Command, CommandQueue.Count);
|
||||
|
||||
if(!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a raw string command to the queue
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
public void EnqueueCommand(string command)
|
||||
{
|
||||
CommandQueue.Enqueue(command);
|
||||
//Debug.Console(1, this, "Command (string) Enqueued '{0}'. CommandQueue has '{1}' Elements.", command, CommandQueue.Count);
|
||||
|
||||
if (!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the next queued command to the DSP
|
||||
/// </summary>
|
||||
void SendNextQueuedCommand()
|
||||
{
|
||||
if (Communication.IsConnected && !CommandQueue.IsEmpty)
|
||||
{
|
||||
CommandQueueInProgress = true;
|
||||
|
||||
if (CommandQueue.Peek() is QueuedCommand)
|
||||
{
|
||||
QueuedCommand nextCommand = new QueuedCommand();
|
||||
|
||||
nextCommand = (QueuedCommand)CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand.Command);
|
||||
}
|
||||
else
|
||||
{
|
||||
string nextCommand = (string)CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void CallPreset(ushort presetNumber)
|
||||
{
|
||||
SendLine(string.Format("Preset.Take = {0}", presetNumber));
|
||||
// SendLine("cgp 1");
|
||||
}
|
||||
|
||||
public class QueuedCommand
|
||||
{
|
||||
public string Command { get; set; }
|
||||
public string AttributeCode { get; set; }
|
||||
// public QscDspControlPoint ControlPoint { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class TVOneCorioPropertiesConfig
|
||||
{
|
||||
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
||||
|
||||
public ControlPropertiesConfig Control { get; set; }
|
||||
public string userName { get; set; }
|
||||
public string password { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
|
||||
public class TVOneCorio : Device
|
||||
{
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
public CommunicationGather PortGather { get; private set; }
|
||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||
public string userName;
|
||||
public string password;
|
||||
private bool OnlineStatus;
|
||||
public BoolFeedback OnlineFeedback;
|
||||
private ushort CurrentPreset;
|
||||
public IntFeedback PresetFeedback;
|
||||
|
||||
// new public Dictionary<string, QscDspLevelControl> LevelControlPoints { get; private set; }
|
||||
// public List<QscDspPresets> PresetList = new List<QscDspPresets>();
|
||||
|
||||
public bool isSubscribed;
|
||||
|
||||
private CTimer SubscriptionTimer;
|
||||
|
||||
CrestronQueue CommandQueue;
|
||||
|
||||
bool CommandQueueInProgress = false;
|
||||
|
||||
//new public Dictionary<string, DspControlPoint> DialerControlPoints { get; private set; }
|
||||
|
||||
//new public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Shows received lines as hex
|
||||
/// </summary>
|
||||
public bool ShowHexResponse { get; set; }
|
||||
|
||||
public TVOneCorio(string key, string name, IBasicCommunication comm, TVOneCorioPropertiesConfig props) :
|
||||
base(key, name)
|
||||
{
|
||||
|
||||
this.userName = props.userName;
|
||||
this.password = props.password;
|
||||
CommandQueue = new CrestronQueue(100);
|
||||
|
||||
|
||||
Communication = comm;
|
||||
|
||||
var socket = comm as ISocketStatus;
|
||||
if (socket != null)
|
||||
{
|
||||
// This instance uses IP control
|
||||
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This instance uses RS-232 control
|
||||
}
|
||||
PortGather = new CommunicationGather(Communication, "\x0a");
|
||||
PortGather.LineReceived += this.Port_LineReceived;
|
||||
if (props.CommunicationMonitorProperties != null)
|
||||
{
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties);
|
||||
}
|
||||
else
|
||||
{
|
||||
//#warning Need to deal with this poll string
|
||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 120000, 120000, 300000, "System.Status\x0A\x0D");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
|
||||
Communication.Connect();
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
CommunicationMonitor.Start();
|
||||
|
||||
OnlineFeedback = new BoolFeedback(() => { return OnlineStatus; });
|
||||
PresetFeedback = new IntFeedback(() => { return CurrentPreset; });
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(SendLine, "send" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
return true;
|
||||
}
|
||||
|
||||
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
||||
{
|
||||
Debug.Console(2, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
|
||||
|
||||
if (e.Client.IsConnected)
|
||||
{
|
||||
OnlineStatus = true;
|
||||
OnlineFeedback.FireUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
OnlineStatus = false;
|
||||
OnlineFeedback.FireUpdate();
|
||||
if (SubscriptionTimer != null)
|
||||
{
|
||||
SubscriptionTimer.Stop();
|
||||
SubscriptionTimer = null;
|
||||
}
|
||||
|
||||
isSubscribed = false;
|
||||
CommandQueue.Clear();
|
||||
CommandQueueInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initiates the subscription process to the DSP
|
||||
/// </summary>
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handles a response message from the DSP
|
||||
/// </summary>
|
||||
/// <param name="dev"></param>
|
||||
/// <param name="args"></param>
|
||||
void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
|
||||
{
|
||||
Debug.Console(2, this, "TVOneCurio RX: '{0}'", args.Text);
|
||||
try
|
||||
{
|
||||
if (args.Text.IndexOf("login") > -1)
|
||||
{
|
||||
SendLine(string.Format("Login({0},{1})", this.userName, this.password));
|
||||
}
|
||||
else if (args.Text.IndexOf("!Done Preset.Take =") > -1)
|
||||
{
|
||||
|
||||
string presetNumberParse = args.Text.Remove(0, args.Text.IndexOf("=") + 2);
|
||||
|
||||
Debug.Console(1, this, "Preset Parse: {0}", presetNumberParse);
|
||||
CurrentPreset = ushort.Parse(presetNumberParse);
|
||||
PresetFeedback.FireUpdate();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "Error parsing response: '{0}'\n{1}", args.Text, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command to the DSP (with delimiter appended)
|
||||
/// </summary>
|
||||
/// <param name="s">Command to send</param>
|
||||
public void SendLine(string s)
|
||||
{
|
||||
Debug.Console(1, this, "TVOne Cusio TX: '{0}'", s);
|
||||
Communication.SendText(s + "\x0d\x0a");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a command from a child module to the queue
|
||||
/// </summary>
|
||||
/// <param name="command">Command object from child module</param>
|
||||
public void EnqueueCommand(QueuedCommand commandToEnqueue)
|
||||
{
|
||||
CommandQueue.Enqueue(commandToEnqueue);
|
||||
//Debug.Console(1, this, "Command (QueuedCommand) Enqueued '{0}'. CommandQueue has '{1}' Elements.", commandToEnqueue.Command, CommandQueue.Count);
|
||||
|
||||
if(!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a raw string command to the queue
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
public void EnqueueCommand(string command)
|
||||
{
|
||||
CommandQueue.Enqueue(command);
|
||||
//Debug.Console(1, this, "Command (string) Enqueued '{0}'. CommandQueue has '{1}' Elements.", command, CommandQueue.Count);
|
||||
|
||||
if (!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the next queued command to the DSP
|
||||
/// </summary>
|
||||
void SendNextQueuedCommand()
|
||||
{
|
||||
if (Communication.IsConnected && !CommandQueue.IsEmpty)
|
||||
{
|
||||
CommandQueueInProgress = true;
|
||||
|
||||
if (CommandQueue.Peek() is QueuedCommand)
|
||||
{
|
||||
QueuedCommand nextCommand = new QueuedCommand();
|
||||
|
||||
nextCommand = (QueuedCommand)CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand.Command);
|
||||
}
|
||||
else
|
||||
{
|
||||
string nextCommand = (string)CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void CallPreset(ushort presetNumber)
|
||||
{
|
||||
SendLine(string.Format("Preset.Take = {0}", presetNumber));
|
||||
// SendLine("cgp 1");
|
||||
}
|
||||
|
||||
public class QueuedCommand
|
||||
{
|
||||
public string Command { get; set; }
|
||||
public string AttributeCode { get; set; }
|
||||
// public QscDspControlPoint ControlPoint { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class TVOneCorioPropertiesConfig
|
||||
{
|
||||
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
||||
|
||||
public ControlPropertiesConfig Control { get; set; }
|
||||
public string userName { get; set; }
|
||||
public string password { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.CrestronIO;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Microphones
|
||||
{
|
||||
/// <summary>
|
||||
/// Used for applications where one or more microphones with momentary contact closure outputs are used to
|
||||
/// toggle the privacy state of the room. Privacy state feedback is represented
|
||||
/// </summary>
|
||||
public class MicrophonePrivacyController : Device
|
||||
{
|
||||
MicrophonePrivacyControllerConfig Config;
|
||||
|
||||
bool initialized;
|
||||
|
||||
public bool EnableLeds
|
||||
{
|
||||
get
|
||||
{
|
||||
return _enableLeds;
|
||||
}
|
||||
set
|
||||
{
|
||||
_enableLeds = value;
|
||||
|
||||
if (initialized)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
CheckPrivacyMode();
|
||||
SetLedStates();
|
||||
}
|
||||
else
|
||||
TurnOffAllLeds();
|
||||
}
|
||||
}
|
||||
}
|
||||
bool _enableLeds;
|
||||
|
||||
public List<IDigitalInput> Inputs { get; private set; }
|
||||
|
||||
public GenericRelayDevice RedLedRelay { get; private set; }
|
||||
bool _redLedRelayState;
|
||||
|
||||
public GenericRelayDevice GreenLedRelay { get; private set; }
|
||||
bool _greenLedRelayState;
|
||||
|
||||
public IPrivacy PrivacyDevice { get; private set; }
|
||||
|
||||
public MicrophonePrivacyController(string key, MicrophonePrivacyControllerConfig config) :
|
||||
base(key)
|
||||
{
|
||||
Config = config;
|
||||
|
||||
Inputs = new List<IDigitalInput>();
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
foreach (var i in Config.Inputs)
|
||||
{
|
||||
var input = DeviceManager.GetDeviceForKey(i.DeviceKey) as IDigitalInput;
|
||||
|
||||
if(input != null)
|
||||
AddInput(input);
|
||||
}
|
||||
|
||||
var greenLed = DeviceManager.GetDeviceForKey(Config.GreenLedRelay.DeviceKey) as GenericRelayDevice;
|
||||
|
||||
if (greenLed != null)
|
||||
GreenLedRelay = greenLed;
|
||||
else
|
||||
Debug.Console(0, this, "Unable to add Green LED device");
|
||||
|
||||
var redLed = DeviceManager.GetDeviceForKey(Config.RedLedRelay.DeviceKey) as GenericRelayDevice;
|
||||
|
||||
if (redLed != null)
|
||||
RedLedRelay = redLed;
|
||||
else
|
||||
Debug.Console(0, this, "Unable to add Red LED device");
|
||||
|
||||
CheckPrivacyMode();
|
||||
|
||||
initialized = true;
|
||||
|
||||
return base.CustomActivate();
|
||||
}
|
||||
|
||||
public void SetPrivacyDevice(IPrivacy privacyDevice)
|
||||
{
|
||||
PrivacyDevice = privacyDevice;
|
||||
|
||||
PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange;
|
||||
}
|
||||
|
||||
void PrivacyModeIsOnFeedback_OutputChange(object sender, EventArgs e)
|
||||
{
|
||||
Debug.Console(1, this, "Privacy mode change: {0}", sender as BoolFeedback);
|
||||
CheckPrivacyMode();
|
||||
}
|
||||
|
||||
void CheckPrivacyMode()
|
||||
{
|
||||
if (PrivacyDevice != null)
|
||||
{
|
||||
var privacyState = PrivacyDevice.PrivacyModeIsOnFeedback.BoolValue;
|
||||
|
||||
if (privacyState)
|
||||
TurnOnRedLeds();
|
||||
else
|
||||
TurnOnGreenLeds();
|
||||
}
|
||||
}
|
||||
|
||||
void AddInput(IDigitalInput input)
|
||||
{
|
||||
Inputs.Add(input);
|
||||
|
||||
input.InputStateFeedback.OutputChange += InputStateFeedback_OutputChange;
|
||||
}
|
||||
|
||||
void RemoveInput(IDigitalInput input)
|
||||
{
|
||||
var tempInput = Inputs.FirstOrDefault(i => i.Equals(input));
|
||||
|
||||
if (tempInput != null)
|
||||
tempInput.InputStateFeedback.OutputChange -= InputStateFeedback_OutputChange;
|
||||
|
||||
Inputs.Remove(input);
|
||||
}
|
||||
|
||||
void SetRedLedRelay(GenericRelayDevice relay)
|
||||
{
|
||||
RedLedRelay = relay;
|
||||
}
|
||||
|
||||
void SetGreenLedRelay(GenericRelayDevice relay)
|
||||
{
|
||||
GreenLedRelay = relay;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check the state of the input change and handle accordingly
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void InputStateFeedback_OutputChange(object sender, EventArgs e)
|
||||
{
|
||||
if ((sender as BoolFeedback).BoolValue == true)
|
||||
TogglePrivacyMute();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles the state of the privacy mute
|
||||
/// </summary>
|
||||
public void TogglePrivacyMute()
|
||||
{
|
||||
PrivacyDevice.PrivacyModeToggle();
|
||||
}
|
||||
|
||||
void TurnOnRedLeds()
|
||||
{
|
||||
_greenLedRelayState = false;
|
||||
_redLedRelayState = true;
|
||||
SetLedStates();
|
||||
}
|
||||
|
||||
void TurnOnGreenLeds()
|
||||
{
|
||||
_redLedRelayState = false;
|
||||
_greenLedRelayState = true;
|
||||
SetLedStates();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If enabled, sets the actual state of the relays
|
||||
/// </summary>
|
||||
void SetLedStates()
|
||||
{
|
||||
if (_enableLeds)
|
||||
{
|
||||
SetRelayStates();
|
||||
}
|
||||
else
|
||||
TurnOffAllLeds();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turns off all LEDs
|
||||
/// </summary>
|
||||
void TurnOffAllLeds()
|
||||
{
|
||||
_redLedRelayState = false;
|
||||
_greenLedRelayState = false;
|
||||
|
||||
SetRelayStates();
|
||||
}
|
||||
|
||||
void SetRelayStates()
|
||||
{
|
||||
if (RedLedRelay != null)
|
||||
{
|
||||
if (_redLedRelayState)
|
||||
RedLedRelay.CloseRelay();
|
||||
else
|
||||
RedLedRelay.OpenRelay();
|
||||
}
|
||||
|
||||
if(GreenLedRelay != null)
|
||||
{
|
||||
if (_greenLedRelayState)
|
||||
GreenLedRelay.CloseRelay();
|
||||
else
|
||||
GreenLedRelay.OpenRelay();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Essentials.Core.CrestronIO;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Microphones
|
||||
{
|
||||
public class MicrophonePrivacyControllerConfig
|
||||
{
|
||||
public List<KeyedDevice> Inputs { get; set; }
|
||||
public KeyedDevice GreenLedRelay { get; set; }
|
||||
public KeyedDevice RedLedRelay { get; set; }
|
||||
}
|
||||
|
||||
public class KeyedDevice
|
||||
{
|
||||
public string DeviceKey { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro.GeneralIO;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Occupancy
|
||||
{
|
||||
public class EssentialsGlsOccupancySensorBaseController : CrestronGenericBaseDevice, IOccupancyStatusProvider
|
||||
{
|
||||
public GlsOccupancySensorBase OccSensor { get; private set; }
|
||||
|
||||
public BoolFeedback RoomIsOccupiedFeedback { get; private set; }
|
||||
|
||||
// Debug properties
|
||||
public bool InTestMode { get; private set; }
|
||||
|
||||
public bool TestRoomIsOccupiedFeedback { get; private set; }
|
||||
|
||||
public Func<bool> RoomIsOccupiedFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () => InTestMode ? TestRoomIsOccupiedFeedback : OccSensor.OccupancyDetectedFeedback.BoolValue;
|
||||
}
|
||||
}
|
||||
|
||||
public EssentialsGlsOccupancySensorBaseController(string key, string name, GlsOccupancySensorBase sensor)
|
||||
: base(key, name, sensor)
|
||||
{
|
||||
OccSensor = sensor;
|
||||
|
||||
RoomIsOccupiedFeedback = new BoolFeedback(RoomIsOccupiedFeedbackFunc);
|
||||
|
||||
OccSensor.BaseEvent += new Crestron.SimplSharpPro.BaseEventHandler(OccSensor_BaseEvent);
|
||||
}
|
||||
|
||||
void OccSensor_BaseEvent(Crestron.SimplSharpPro.GenericBase device, Crestron.SimplSharpPro.BaseEventArgs args)
|
||||
{
|
||||
Debug.Console(2, this, "GlsOccupancySensorChange EventId: {0}", args.EventId);
|
||||
|
||||
if (args.EventId == Crestron.SimplSharpPro.GeneralIO.GlsOccupancySensorBase.RoomOccupiedFeedbackEventId
|
||||
|| args.EventId == Crestron.SimplSharpPro.GeneralIO.GlsOccupancySensorBase.RoomVacantFeedbackEventId)
|
||||
{
|
||||
Debug.Console(1, this, "Occupancy State: {0}", OccSensor.OccupancyDetectedFeedback.BoolValue);
|
||||
RoomIsOccupiedFeedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTestMode(bool mode)
|
||||
{
|
||||
InTestMode = mode;
|
||||
|
||||
Debug.Console(1, this, "In Mock Mode: '{0}'", InTestMode);
|
||||
}
|
||||
|
||||
public void SetTestOccupiedState(bool state)
|
||||
{
|
||||
if (!InTestMode)
|
||||
Debug.Console(1, "Mock mode not enabled");
|
||||
else
|
||||
{
|
||||
TestRoomIsOccupiedFeedback = state;
|
||||
|
||||
RoomIsOccupiedFeedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro.GeneralIO;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Occupancy
|
||||
{
|
||||
public class EssentialsGlsOccupancySensorBaseController : CrestronGenericBaseDevice, IOccupancyStatusProvider
|
||||
{
|
||||
public GlsOccupancySensorBase OccSensor { get; private set; }
|
||||
|
||||
public BoolFeedback RoomIsOccupiedFeedback { get; private set; }
|
||||
|
||||
<<<<<<< HEAD
|
||||
/// <summary>
|
||||
/// Set by debugging functions
|
||||
/// </summary>
|
||||
public bool InMockMode { get; private set; }
|
||||
|
||||
public bool MockRoomIsOccupiedFeedback { get; private set; }
|
||||
=======
|
||||
// Debug properties
|
||||
public bool InTestMode { get; private set; }
|
||||
|
||||
public bool TestRoomIsOccupiedFeedback { get; private set; }
|
||||
>>>>>>> origin/feature/ecs-342-neil
|
||||
|
||||
public Func<bool> RoomIsOccupiedFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
return () => InMockMode ? MockRoomIsOccupiedFeedback : OccSensor.OccupancyDetectedFeedback.BoolValue;
|
||||
=======
|
||||
return () => InTestMode ? TestRoomIsOccupiedFeedback : OccSensor.OccupancyDetectedFeedback.BoolValue;
|
||||
>>>>>>> origin/feature/ecs-342-neil
|
||||
}
|
||||
}
|
||||
|
||||
public EssentialsGlsOccupancySensorBaseController(string key, string name, GlsOccupancySensorBase sensor, GlsOccupancySensorConfigurationProperties props)
|
||||
: base(key, name, sensor)
|
||||
{
|
||||
OccSensor = sensor;
|
||||
RoomIsOccupiedFeedback = new BoolFeedback(RoomIsOccupiedFeedbackFunc);
|
||||
|
||||
OccSensor.GlsOccupancySensorChange += new GlsOccupancySensorChangeEventHandler(sensor_GlsOccupancySensorChange);
|
||||
}
|
||||
|
||||
void sensor_GlsOccupancySensorChange(GlsOccupancySensorBase device, GlsOccupancySensorChangeEventArgs args)
|
||||
{
|
||||
RoomIsOccupiedFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
public void SetTestMode(bool mode)
|
||||
{
|
||||
InTestMode = mode;
|
||||
|
||||
Debug.Console(1, this, "In Mock Mode: '{0}'", InTestMode);
|
||||
}
|
||||
|
||||
public void SetTestOccupiedState(bool state)
|
||||
{
|
||||
if (!InTestMode)
|
||||
Debug.Console(1, "Mock mode not enabled");
|
||||
else
|
||||
{
|
||||
TestRoomIsOccupiedFeedback = state;
|
||||
|
||||
RoomIsOccupiedFeedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class GlsOccupancySensorConfigurationProperties
|
||||
{
|
||||
public string CresnetId { get; set; }
|
||||
public string Model { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Occupancy
|
||||
{
|
||||
/// <summary>
|
||||
/// Aggregates the RoomIsOccupied feedbacks of one or more IOccupancyStatusProvider objects
|
||||
/// </summary>
|
||||
public class EssentialsOccupancyAggregator : Device, IOccupancyStatusProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Aggregated feedback of all linked IOccupancyStatusProvider devices
|
||||
/// </summary>
|
||||
public BoolFeedback RoomIsOccupiedFeedback
|
||||
{
|
||||
get
|
||||
{
|
||||
return AggregatedOccupancyStatus.Output;
|
||||
}
|
||||
}
|
||||
|
||||
private BoolFeedbackOr AggregatedOccupancyStatus;
|
||||
|
||||
public EssentialsOccupancyAggregator(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
AggregatedOccupancyStatus = new BoolFeedbackOr();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an IOccupancyStatusProvider device
|
||||
/// </summary>
|
||||
/// <param name="statusProvider"></param>
|
||||
public void AddOccupancyStatusProvider(IOccupancyStatusProvider statusProvider)
|
||||
{
|
||||
AggregatedOccupancyStatus.AddOutputIn(statusProvider.RoomIsOccupiedFeedback);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Occupancy
|
||||
{
|
||||
public interface IOccupancyStatusProvider
|
||||
{
|
||||
BoolFeedback RoomIsOccupiedFeedback { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Crestron.SimplSharpPro;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// This DVD class should cover most IR, one-way DVD and Bluray fuctions
|
||||
/// </summary>
|
||||
public class InRoomPc : Device, IHasFeedback, IRoutingOutputs, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking
|
||||
{
|
||||
public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } }
|
||||
public string IconName { get; set; }
|
||||
public BoolFeedback HasPowerOnFeedback { get; private set; }
|
||||
|
||||
public RoutingOutputPort AnyVideoOut { get; private set; }
|
||||
|
||||
#region IRoutingOutputs Members
|
||||
|
||||
/// <summary>
|
||||
/// Options: hdmi
|
||||
/// </summary>
|
||||
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public InRoomPc(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
IconName = "PC";
|
||||
HasPowerOnFeedback = new BoolFeedback("HasPowerFeedback",
|
||||
() => this.GetVideoStatuses() != VideoStatusOutputs.NoStatus);
|
||||
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
|
||||
OutputPorts.Add(AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.None, 0, this));
|
||||
}
|
||||
|
||||
#region IHasFeedback Members
|
||||
|
||||
/// <summary>
|
||||
/// Passes through the VideoStatuses list
|
||||
/// </summary>
|
||||
public FeedbackCollection<Feedback> Feedbacks
|
||||
{
|
||||
get
|
||||
{
|
||||
var newList = new FeedbackCollection<Feedback>();
|
||||
newList.AddRange(this.GetVideoStatuses().ToList());
|
||||
return newList;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IUsageTracking Members
|
||||
|
||||
public UsageTracking UsageTracker { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Crestron.SimplSharpPro;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// This DVD class should cover most IR, one-way DVD and Bluray fuctions
|
||||
/// </summary>
|
||||
public class Laptop : Device, IHasFeedback, IRoutingOutputs, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking
|
||||
{
|
||||
public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } }
|
||||
public string IconName { get; set; }
|
||||
public BoolFeedback HasPowerOnFeedback { get; private set; }
|
||||
|
||||
public RoutingOutputPort AnyVideoOut { get; private set; }
|
||||
|
||||
#region IRoutingOutputs Members
|
||||
|
||||
/// <summary>
|
||||
/// Options: hdmi
|
||||
/// </summary>
|
||||
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public Laptop(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
IconName = "Laptop";
|
||||
HasPowerOnFeedback = new BoolFeedback("HasPowerFeedback",
|
||||
() => this.GetVideoStatuses() != VideoStatusOutputs.NoStatus);
|
||||
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
|
||||
OutputPorts.Add(AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyOut, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.None, 0, this));
|
||||
}
|
||||
|
||||
#region IHasFeedback Members
|
||||
|
||||
/// <summary>
|
||||
/// Passes through the VideoStatuses list
|
||||
/// </summary>
|
||||
public FeedbackCollection<Feedback> Feedbacks
|
||||
{
|
||||
get
|
||||
{
|
||||
var newList = new FeedbackCollection<Feedback>();
|
||||
newList.AddRange(this.GetVideoStatuses().ToList());
|
||||
return newList;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IUsageTracking Members
|
||||
|
||||
public UsageTracking UsageTracker { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class DigitalLoggerPropertiesConfig
|
||||
{
|
||||
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
||||
|
||||
public ControlPropertiesConfig Control { get; set; }
|
||||
public string userName { get; set; }
|
||||
public string password { get; set; }
|
||||
public string address { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using System.Text.RegularExpressions;
|
||||
using Crestron.SimplSharp.Net.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
|
||||
public class DigitalLogger : Device
|
||||
{
|
||||
public IBasicCommunication Communication { get; private set; }
|
||||
public CommunicationGather PortGather { get; private set; }
|
||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||
|
||||
private HttpClient WebClient;
|
||||
public string userName;
|
||||
public string password;
|
||||
public string address;
|
||||
private bool OnlineStatus;
|
||||
public BoolFeedback OnlineFeedback;
|
||||
private ushort CurrentPreset;
|
||||
public IntFeedback PresetFeedback;
|
||||
|
||||
public Dictionary<uint, DigitalLoggerCircuit> CircuitStatus;
|
||||
public uint CircuitCount;
|
||||
|
||||
public Dictionary<uint, StringFeedback> CircuitNameFeedbacks { get; private set; }
|
||||
public Dictionary<uint, BoolFeedback> CircuitIsCritical{ get; private set; }
|
||||
public Dictionary<uint, BoolFeedback> CircuitState { get; private set; }
|
||||
|
||||
// new public Dictionary<string, QscDspLevelControl> LevelControlPoints { get; private set; }
|
||||
// public List<QscDspPresets> PresetList = new List<QscDspPresets>();
|
||||
|
||||
public bool isSubscribed;
|
||||
|
||||
private CTimer SubscriptionTimer;
|
||||
|
||||
CrestronQueue CommandQueue;
|
||||
|
||||
bool CommandQueueInProgress = false;
|
||||
|
||||
//new public Dictionary<string, DspControlPoint> DialerControlPoints { get; private set; }
|
||||
|
||||
//new public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Shows received lines as hex
|
||||
/// </summary>
|
||||
public bool ShowHexResponse { get; set; }
|
||||
|
||||
public DigitalLogger(string key, string name, DigitalLoggerPropertiesConfig props) :
|
||||
base(key, name)
|
||||
{
|
||||
CircuitCount = 8;
|
||||
this.userName = props.userName;
|
||||
this.password = props.password;
|
||||
CommandQueue = new CrestronQueue(100);
|
||||
|
||||
WebClient = new HttpClient();
|
||||
WebClient.UserName = this.userName;
|
||||
WebClient.Password = this.password;
|
||||
this.address = props.address;
|
||||
WebClient.HostAddress = props.address;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
/*
|
||||
Communication.Connect();
|
||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||
CommunicationMonitor.Start();
|
||||
*/
|
||||
|
||||
OnlineFeedback = new BoolFeedback(() => { return OnlineStatus; });
|
||||
CircuitStatus = new Dictionary<uint, DigitalLoggerCircuit>();
|
||||
CircuitNameFeedbacks = new Dictionary<uint, StringFeedback>();
|
||||
CircuitIsCritical = new Dictionary<uint, BoolFeedback>();
|
||||
CircuitState = new Dictionary<uint, BoolFeedback>();
|
||||
for (uint i = 0; i < CircuitCount; i++)
|
||||
{
|
||||
uint circuit = i;
|
||||
CircuitStatus[circuit] = new DigitalLoggerCircuit();
|
||||
CircuitNameFeedbacks[circuit] = new StringFeedback(() => {
|
||||
if (CircuitStatus[circuit].name != null)
|
||||
{
|
||||
return CircuitStatus[circuit].name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
});
|
||||
CircuitIsCritical[circuit] = new BoolFeedback(() =>
|
||||
{
|
||||
if (CircuitStatus[circuit].critical != null)
|
||||
{
|
||||
return CircuitStatus[circuit].critical;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
CircuitState[circuit] = new BoolFeedback(() =>
|
||||
{
|
||||
if (CircuitStatus[circuit].state != null)
|
||||
{
|
||||
return CircuitStatus[circuit].state;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
PollCircuit(circuit);
|
||||
}
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(SendLine, "send" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
||||
{
|
||||
Debug.Console(2, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
|
||||
|
||||
if (e.Client.IsConnected)
|
||||
{
|
||||
OnlineStatus = true;
|
||||
OnlineFeedback.FireUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
OnlineStatus = false;
|
||||
OnlineFeedback.FireUpdate();
|
||||
if (SubscriptionTimer != null)
|
||||
{
|
||||
SubscriptionTimer.Stop();
|
||||
SubscriptionTimer = null;
|
||||
}
|
||||
|
||||
isSubscribed = false;
|
||||
CommandQueue.Clear();
|
||||
CommandQueueInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void PollCircuit(uint circuit)
|
||||
{
|
||||
try
|
||||
{
|
||||
string PollCircuitResponse = SendRequest(String.Format("/restapi/relay/outlets/{0}/", circuit));
|
||||
CircuitStatus[circuit] = JsonConvert.DeserializeObject<DigitalLoggerCircuit>(PollCircuitResponse);
|
||||
DigitalLoggerCircuit temp = CircuitStatus[circuit];
|
||||
Debug.Console(2, this, "DigitalLogger Circuit {0} Name: {1} State:{2}'", circuit, CircuitStatus[circuit].name, CircuitStatus[circuit].state);
|
||||
CircuitNameFeedbacks[circuit].FireUpdate();
|
||||
CircuitState[circuit].FireUpdate();
|
||||
CircuitIsCritical[circuit].FireUpdate();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, this, "PollCircuit {0}", e);
|
||||
|
||||
}
|
||||
}
|
||||
void Port_LineReceived(string response, HTTP_CALLBACK_ERROR error)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
public string SendRequest(string s)
|
||||
{
|
||||
HttpClientRequest request = new HttpClientRequest();
|
||||
string url = string.Format("http://{0}{1}", this.address, s);
|
||||
request.Url = new UrlParser(url);
|
||||
HttpClientResponse response = WebClient.Dispatch(request);
|
||||
|
||||
Debug.Console(2, this, "DigitalLogger TX:\n'{0}'\nRX:\n'{1}'", url, response.ContentString);
|
||||
return response.ContentString;
|
||||
}
|
||||
/// <summary>
|
||||
/// Sends a command to the DSP (with delimiter appended)
|
||||
/// </summary>
|
||||
/// <param name="s">Command to send</param>
|
||||
///
|
||||
public void SendLine(string s)
|
||||
{
|
||||
|
||||
HttpClientRequest request = new HttpClientRequest();
|
||||
string url = string.Format("http://{0}{1}", this.address, s);
|
||||
request.Url = new UrlParser(url);
|
||||
|
||||
HttpClientResponse response = WebClient.Dispatch(request);
|
||||
|
||||
Debug.Console(2, this, "DigitalLogger TX:\n'{0}'\nRX:\n'{1}'", url, response.ContentString);
|
||||
|
||||
}
|
||||
|
||||
public void CycleCircuit(uint circuit)
|
||||
{
|
||||
SendLine(String.Format("/outlet?{0}=CCL", circuit));
|
||||
//PollCircuit(circuit);
|
||||
|
||||
}
|
||||
|
||||
public void TurnOnCircuit(uint circuit)
|
||||
{
|
||||
SendLine(String.Format("/outlet?{0}=ON", circuit));
|
||||
//PollCircuit(circuit);
|
||||
}
|
||||
|
||||
public void TurnOffCircuit(uint circuit)
|
||||
{
|
||||
SendLine(String.Format("/outlet?{0}=Off", circuit));
|
||||
//PollCircuit(circuit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a command from a child module to the queue
|
||||
/// </summary>
|
||||
/// <param name="command">Command object from child module</param>
|
||||
public void EnqueueCommand(QueuedCommand commandToEnqueue)
|
||||
{
|
||||
CommandQueue.Enqueue(commandToEnqueue);
|
||||
//Debug.Console(1, this, "Command (QueuedCommand) Enqueued '{0}'. CommandQueue has '{1}' Elements.", commandToEnqueue.Command, CommandQueue.Count);
|
||||
|
||||
if(!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a raw string command to the queue
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
public void EnqueueCommand(string command)
|
||||
{
|
||||
CommandQueue.Enqueue(command);
|
||||
//Debug.Console(1, this, "Command (string) Enqueued '{0}'. CommandQueue has '{1}' Elements.", command, CommandQueue.Count);
|
||||
|
||||
if (!CommandQueueInProgress)
|
||||
SendNextQueuedCommand();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the next queued command to the DSP
|
||||
/// </summary>
|
||||
void SendNextQueuedCommand()
|
||||
{
|
||||
if (Communication.IsConnected && !CommandQueue.IsEmpty)
|
||||
{
|
||||
CommandQueueInProgress = true;
|
||||
|
||||
if (CommandQueue.Peek() is QueuedCommand)
|
||||
{
|
||||
QueuedCommand nextCommand = new QueuedCommand();
|
||||
|
||||
nextCommand = (QueuedCommand)CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand.Command);
|
||||
}
|
||||
else
|
||||
{
|
||||
string nextCommand = (string)CommandQueue.Peek();
|
||||
|
||||
SendLine(nextCommand);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void CallPreset(ushort presetNumber)
|
||||
{
|
||||
SendLine(string.Format("Preset.Take = {0}", presetNumber));
|
||||
// SendLine("cgp 1");
|
||||
}
|
||||
|
||||
public class QueuedCommand
|
||||
{
|
||||
public string Command { get; set; }
|
||||
public string AttributeCode { get; set; }
|
||||
// public QscDspControlPoint ControlPoint { get; set; }
|
||||
}
|
||||
|
||||
public class DigitalLoggerCircuit
|
||||
{
|
||||
public string name;
|
||||
public bool locked;
|
||||
public bool critical;
|
||||
public bool transient_state;
|
||||
public bool physical_state;
|
||||
//public int cycle_delay;
|
||||
public bool state;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyTitle("Essentials_Devices_Common")]
|
||||
[assembly: AssemblyCompany("PepperDash Technology Corp")]
|
||||
[assembly: AssemblyProduct("Essentials_Devices_Common")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[assembly: AssemblyVersion("1.3.*")]
|
||||
@@ -0,0 +1,343 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Presets;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
public class IRSetTopBoxBase : Device, ISetTopBoxControls, IUiDisplayInfo, IRoutingOutputs, IUsageTracking
|
||||
{
|
||||
public IrOutputPortController IrPort { get; private set; }
|
||||
|
||||
public uint DisplayUiType { get { return DisplayUiConstants.TypeDirecTv; } }
|
||||
|
||||
|
||||
public bool HasPresets { get; set; }
|
||||
public bool HasDvr { get; set; }
|
||||
public bool HasDpad { get; set; }
|
||||
public bool HasNumeric { get; set; }
|
||||
|
||||
public DevicePresetsModel PresetsModel { get; private set; }
|
||||
|
||||
public IRSetTopBoxBase(string key, string name, IrOutputPortController portCont,
|
||||
SetTopBoxPropertiesConfig props)
|
||||
: base(key, name)
|
||||
{
|
||||
IrPort = portCont;
|
||||
DeviceManager.AddDevice(portCont);
|
||||
|
||||
HasPresets = props.HasPresets;
|
||||
HasDvr = props.HasDvr;
|
||||
HasDpad = props.HasDpad;
|
||||
HasNumeric = props.HasNumeric;
|
||||
|
||||
HasKeypadAccessoryButton1 = true;
|
||||
KeypadAccessoryButton1Command = "Dash";
|
||||
KeypadAccessoryButton1Label = "-";
|
||||
|
||||
HasKeypadAccessoryButton2 = true;
|
||||
KeypadAccessoryButton2Command = "NumericEnter";
|
||||
KeypadAccessoryButton2Label = "Enter";
|
||||
|
||||
AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyVideoOut, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, null, this);
|
||||
AnyAudioOut = new RoutingOutputPort(RoutingPortNames.AnyAudioOut, eRoutingSignalType.Audio,
|
||||
eRoutingPortConnectionType.DigitalAudio, null, this);
|
||||
OutputPorts = new RoutingPortCollection<RoutingOutputPort> { AnyVideoOut, AnyAudioOut };
|
||||
|
||||
}
|
||||
|
||||
public void LoadPresets(string filePath)
|
||||
{
|
||||
PresetsModel = new DevicePresetsModel(Key + "-presets", this, filePath);
|
||||
DeviceManager.AddDevice(PresetsModel);
|
||||
}
|
||||
|
||||
|
||||
#region ISetTopBoxControls Members
|
||||
|
||||
public void DvrList(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_DVR, pressRelease);
|
||||
}
|
||||
|
||||
public void Replay(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_REPLAY, pressRelease);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDPad Members
|
||||
|
||||
public void Up(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_UP_ARROW, pressRelease);
|
||||
}
|
||||
|
||||
public void Down(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_DN_ARROW, pressRelease);
|
||||
}
|
||||
|
||||
public void Left(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_LEFT_ARROW, pressRelease);
|
||||
}
|
||||
|
||||
public void Right(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_RIGHT_ARROW, pressRelease);
|
||||
}
|
||||
|
||||
public void Select(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_ENTER, pressRelease);
|
||||
}
|
||||
|
||||
public void Menu(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_MENU, pressRelease);
|
||||
}
|
||||
|
||||
public void Exit(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_EXIT, pressRelease);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region INumericKeypad Members
|
||||
|
||||
public void Digit0(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_0, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit1(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_1, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit2(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_2, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit3(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_3, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit4(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_4, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit5(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_5, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit6(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_6, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit7(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_7, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit8(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_8, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit9(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_9, pressRelease);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defaults to true
|
||||
/// </summary>
|
||||
public bool HasKeypadAccessoryButton1 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defaults to "-"
|
||||
/// </summary>
|
||||
public string KeypadAccessoryButton1Label { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Defaults to "Dash"
|
||||
/// </summary>
|
||||
public string KeypadAccessoryButton1Command { get; set; }
|
||||
|
||||
public void KeypadAccessoryButton1(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(KeypadAccessoryButton1Command, pressRelease);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defaults to true
|
||||
/// </summary>
|
||||
public bool HasKeypadAccessoryButton2 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defaults to "Enter"
|
||||
/// </summary>
|
||||
public string KeypadAccessoryButton2Label { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Defaults to "Enter"
|
||||
/// </summary>
|
||||
public string KeypadAccessoryButton2Command { get; set; }
|
||||
|
||||
public void KeypadAccessoryButton2(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(KeypadAccessoryButton2Command, pressRelease);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ISetTopBoxNumericKeypad Members
|
||||
|
||||
/// <summary>
|
||||
/// Corresponds to "dash" IR command
|
||||
/// </summary>
|
||||
public void Dash(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease("dash", pressRelease);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Corresponds to "numericEnter" IR command
|
||||
/// </summary>
|
||||
public void KeypadEnter(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease("numericEnter", pressRelease);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IChannelFunctions Members
|
||||
|
||||
public void ChannelUp(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_CH_PLUS, pressRelease);
|
||||
}
|
||||
|
||||
public void ChannelDown(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_CH_MINUS, pressRelease);
|
||||
}
|
||||
|
||||
public void LastChannel(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_LAST, pressRelease);
|
||||
}
|
||||
|
||||
public void Guide(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_GUIDE, pressRelease);
|
||||
}
|
||||
|
||||
public void Info(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_INFO, pressRelease);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IColorFunctions Members
|
||||
|
||||
public void Red(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_RED, pressRelease);
|
||||
}
|
||||
|
||||
public void Green(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_GREEN, pressRelease);
|
||||
}
|
||||
|
||||
public void Yellow(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_YELLOW, pressRelease);
|
||||
}
|
||||
|
||||
public void Blue(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_BLUE, pressRelease);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IRoutingOutputs Members
|
||||
|
||||
public RoutingOutputPort AnyVideoOut { get; private set; }
|
||||
public RoutingOutputPort AnyAudioOut { get; private set; }
|
||||
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region ITransport Members
|
||||
|
||||
public void ChapMinus(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_REPLAY, pressRelease);
|
||||
}
|
||||
|
||||
public void ChapPlus(bool pressRelease)
|
||||
{
|
||||
}
|
||||
|
||||
public void FFwd(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_FSCAN, pressRelease);
|
||||
}
|
||||
|
||||
public void Pause(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_RSCAN, pressRelease);
|
||||
}
|
||||
|
||||
public void Play(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_PLAY, pressRelease);
|
||||
}
|
||||
|
||||
public void Record(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_RECORD, pressRelease);
|
||||
}
|
||||
|
||||
public void Rewind(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_RSCAN, pressRelease);
|
||||
}
|
||||
|
||||
public void Stop(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_STOP, pressRelease);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IUsageTracking Members
|
||||
|
||||
public UsageTracking UsageTracker { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
public class SetTopBoxPropertiesConfig : PepperDash.Essentials.Core.Config.SourceDevicePropertiesConfigBase
|
||||
{
|
||||
public bool HasPresets { get; set; }
|
||||
public bool HasDvr { get; set; }
|
||||
public bool HasDpad { get; set; }
|
||||
public bool HasNumeric { get; set; }
|
||||
|
||||
public ControlPropertiesConfig Control { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
public class AppleTV : Device, IDPad, ITransport, IUiDisplayInfo, IRoutingOutputs
|
||||
{
|
||||
|
||||
public IrOutputPortController IrPort { get; private set; }
|
||||
public const string StandardDriverName = "Apple AppleTV-v2.ir";
|
||||
public uint DisplayUiType { get { return DisplayUiConstants.TypeAppleTv; } }
|
||||
|
||||
public AppleTV(string key, string name, IrOutputPortController portCont)
|
||||
: base(key, name)
|
||||
{
|
||||
IrPort = portCont;
|
||||
DeviceManager.AddDevice(portCont);
|
||||
|
||||
HdmiOut = new RoutingOutputPort(RoutingPortNames.HdmiOut, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, null, this);
|
||||
AnyAudioOut = new RoutingOutputPort(RoutingPortNames.AnyAudioOut, eRoutingSignalType.Audio,
|
||||
eRoutingPortConnectionType.DigitalAudio, null, this);
|
||||
OutputPorts = new RoutingPortCollection<RoutingOutputPort> { HdmiOut, AnyAudioOut };
|
||||
}
|
||||
|
||||
|
||||
#region IDPad Members
|
||||
|
||||
public void Up(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease("+", pressRelease);
|
||||
}
|
||||
|
||||
public void Down(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease("-", pressRelease);
|
||||
}
|
||||
|
||||
public void Left(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_TRACK_MINUS, pressRelease);
|
||||
}
|
||||
|
||||
public void Right(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_TRACK_PLUS, pressRelease);
|
||||
}
|
||||
|
||||
public void Select(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_ENTER, pressRelease);
|
||||
}
|
||||
|
||||
public void Menu(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease("Menu", pressRelease);
|
||||
}
|
||||
|
||||
public void Exit(bool pressRelease)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ITransport Members
|
||||
|
||||
public void Play(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease("PLAY/PAUSE", pressRelease);
|
||||
}
|
||||
|
||||
public void Pause(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease("PLAY/PAUSE", pressRelease);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not implemented
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void Rewind(bool pressRelease)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not implemented
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void FFwd(bool pressRelease)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not implemented
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void ChapMinus(bool pressRelease)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not implemented
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void ChapPlus(bool pressRelease)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not implemented
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void Stop(bool pressRelease)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not implemented
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void Record(bool pressRelease)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IRoutingOutputs Members
|
||||
|
||||
public RoutingOutputPort HdmiOut { get; private set; }
|
||||
public RoutingOutputPort AnyAudioOut { get; private set; }
|
||||
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
public class Roku2 : Device, IDPad, ITransport, IUiDisplayInfo, IRoutingOutputs
|
||||
{
|
||||
[Api]
|
||||
public IrOutputPortController IrPort { get; private set; }
|
||||
public const string StandardDriverName = "Roku XD_S.ir";
|
||||
[Api]
|
||||
public uint DisplayUiType { get { return DisplayUiConstants.TypeRoku; } }
|
||||
|
||||
public Roku2(string key, string name, IrOutputPortController portCont)
|
||||
: base(key, name)
|
||||
{
|
||||
IrPort = portCont;
|
||||
DeviceManager.AddDevice(portCont);;
|
||||
|
||||
HdmiOut = new RoutingOutputPort(RoutingPortNames.HdmiOut, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, null, this);
|
||||
OutputPorts = new RoutingPortCollection<RoutingOutputPort> { HdmiOut };
|
||||
}
|
||||
|
||||
#region IDPad Members
|
||||
|
||||
[Api]
|
||||
public void Up(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_UP_ARROW, pressRelease);
|
||||
}
|
||||
|
||||
[Api]
|
||||
public void Down(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_DN_ARROW, pressRelease);
|
||||
}
|
||||
|
||||
[Api]
|
||||
public void Left(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_LEFT_ARROW, pressRelease);
|
||||
}
|
||||
|
||||
[Api]
|
||||
public void Right(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_RIGHT_ARROW, pressRelease);
|
||||
}
|
||||
|
||||
[Api]
|
||||
public void Select(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_ENTER, pressRelease);
|
||||
}
|
||||
|
||||
[Api]
|
||||
public void Menu(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_MENU, pressRelease);
|
||||
}
|
||||
|
||||
[Api]
|
||||
public void Exit(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_EXIT, pressRelease);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ITransport Members
|
||||
|
||||
[Api]
|
||||
public void Play(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_PLAY, pressRelease);
|
||||
}
|
||||
|
||||
[Api]
|
||||
public void Pause(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_PAUSE, pressRelease);
|
||||
}
|
||||
|
||||
[Api]
|
||||
public void Rewind(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_RSCAN, pressRelease);
|
||||
}
|
||||
|
||||
[Api]
|
||||
public void FFwd(bool pressRelease)
|
||||
{
|
||||
IrPort.PressRelease(IROutputStandardCommands.IROut_FSCAN, pressRelease);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not implemented
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void ChapMinus(bool pressRelease)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not implemented
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void ChapPlus(bool pressRelease)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not implemented
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void Stop(bool pressRelease)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not implemented
|
||||
/// </summary>
|
||||
/// <param name="pressRelease"></param>
|
||||
public void Record(bool pressRelease)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IRoutingOutputs Members
|
||||
|
||||
public RoutingOutputPort HdmiOut { get; private set; }
|
||||
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.VideoCodec
|
||||
{
|
||||
public class CiscoCodecBookings
|
||||
{
|
||||
public class TotalRows
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class ResultInfo
|
||||
{
|
||||
public TotalRows TotalRows { get; set; }
|
||||
}
|
||||
|
||||
public class LastUpdated
|
||||
{
|
||||
string _value;
|
||||
|
||||
public DateTime Value {
|
||||
get
|
||||
{
|
||||
DateTime _valueDateTime;
|
||||
try
|
||||
{
|
||||
_valueDateTime = DateTime.Parse(_value);
|
||||
return _valueDateTime;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new DateTime();
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
_value = value.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Id
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Title
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Agenda
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Privacy
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class FirstName
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class LastName
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Email
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Id2
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Organizer
|
||||
{
|
||||
public FirstName FirstName { get; set; }
|
||||
public LastName LastName { get; set; }
|
||||
public Email Email { get; set; }
|
||||
public Id2 Id { get; set; }
|
||||
|
||||
public Organizer()
|
||||
{
|
||||
FirstName = new FirstName();
|
||||
LastName = new LastName();
|
||||
Email = new Email();
|
||||
}
|
||||
}
|
||||
|
||||
public class StartTime
|
||||
{
|
||||
public DateTime Value { get; set; }
|
||||
}
|
||||
|
||||
public class StartTimeBuffer
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class EndTime
|
||||
{
|
||||
public DateTime Value { get; set; }
|
||||
}
|
||||
|
||||
public class EndTimeBuffer
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Time
|
||||
{
|
||||
public StartTime StartTime { get; set; }
|
||||
public StartTimeBuffer StartTimeBuffer { get; set; }
|
||||
public EndTime EndTime { get; set; }
|
||||
public EndTimeBuffer EndTimeBuffer { get; set; }
|
||||
|
||||
public Time()
|
||||
{
|
||||
StartTime = new StartTime();
|
||||
EndTime = new EndTime();
|
||||
}
|
||||
}
|
||||
|
||||
public class MaximumMeetingExtension
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class MeetingExtensionAvailability
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class BookingStatus
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class BookingStatusMessage
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Enabled
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Url
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class MeetingNumber
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Password
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class HostKey
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class DialInNumbers
|
||||
{
|
||||
}
|
||||
|
||||
public class Webex
|
||||
{
|
||||
public Enabled Enabled { get; set; }
|
||||
public Url Url { get; set; }
|
||||
public MeetingNumber MeetingNumber { get; set; }
|
||||
public Password Password { get; set; }
|
||||
public HostKey HostKey { get; set; }
|
||||
public DialInNumbers DialInNumbers { get; set; }
|
||||
}
|
||||
|
||||
public class Encryption
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Role
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Recording
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Number
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Protocol
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class CallRate
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class CallType
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Call
|
||||
{
|
||||
public string id { get; set; }
|
||||
public Number Number { get; set; }
|
||||
public Protocol Protocol { get; set; }
|
||||
public CallRate CallRate { get; set; }
|
||||
public CallType CallType { get; set; }
|
||||
}
|
||||
|
||||
public class Calls
|
||||
{
|
||||
public List<Call> Call {get; set;}
|
||||
}
|
||||
|
||||
public class ConnectMode
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class DialInfo
|
||||
{
|
||||
public Calls Calls { get; set; }
|
||||
public ConnectMode ConnectMode { get; set; }
|
||||
|
||||
public DialInfo()
|
||||
{
|
||||
Calls = new Calls();
|
||||
ConnectMode = new ConnectMode();
|
||||
}
|
||||
}
|
||||
|
||||
public class Booking
|
||||
{
|
||||
public string id { get; set; }
|
||||
public Id Id { get; set; }
|
||||
public Title Title { get; set; }
|
||||
public Agenda Agenda { get; set; }
|
||||
public Privacy Privacy { get; set; }
|
||||
public Organizer Organizer { get; set; }
|
||||
public Time Time { get; set; }
|
||||
public MaximumMeetingExtension MaximumMeetingExtension { get; set; }
|
||||
public MeetingExtensionAvailability MeetingExtensionAvailability { get; set; }
|
||||
public BookingStatus BookingStatus { get; set; }
|
||||
public BookingStatusMessage BookingStatusMessage { get; set; }
|
||||
public Webex Webex { get; set; }
|
||||
public Encryption Encryption { get; set; }
|
||||
public Role Role { get; set; }
|
||||
public Recording Recording { get; set; }
|
||||
public DialInfo DialInfo { get; set; }
|
||||
|
||||
public Booking()
|
||||
{
|
||||
Time = new Time();
|
||||
Id = new Id();
|
||||
Organizer = new Organizer();
|
||||
Title = new Title();
|
||||
Agenda = new Agenda();
|
||||
Privacy = new Privacy();
|
||||
DialInfo = new DialInfo();
|
||||
}
|
||||
}
|
||||
|
||||
public class BookingsListResult
|
||||
{
|
||||
public string status { get; set; }
|
||||
public ResultInfo ResultInfo { get; set; }
|
||||
//public LastUpdated LastUpdated { get; set; }
|
||||
public List<Booking> Booking { get; set; }
|
||||
}
|
||||
|
||||
public class CommandResponse
|
||||
{
|
||||
public BookingsListResult BookingsListResult { get; set; }
|
||||
}
|
||||
|
||||
public class RootObject
|
||||
{
|
||||
public CommandResponse CommandResponse { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the necessary meeting values from the Cisco bookings response ans converts them to the generic class
|
||||
/// </summary>
|
||||
/// <param name="bookings"></param>
|
||||
/// <returns></returns>
|
||||
public static List<Meeting> GetGenericMeetingsFromBookingResult(List<Booking> bookings)
|
||||
{
|
||||
var meetings = new List<Meeting>();
|
||||
|
||||
if (Debug.Level > 0)
|
||||
{
|
||||
Debug.Console(1, "Meetings List:\n");
|
||||
}
|
||||
|
||||
foreach(Booking b in bookings)
|
||||
{
|
||||
var meeting = new Meeting();
|
||||
|
||||
if(b.Id != null)
|
||||
meeting.Id = b.Id.Value;
|
||||
if(b.Organizer != null)
|
||||
meeting.Organizer = string.Format("{0}, {1}", b.Organizer.LastName.Value, b.Organizer.FirstName.Value);
|
||||
if(b.Title != null)
|
||||
meeting.Title = b.Title.Value;
|
||||
if(b.Agenda != null)
|
||||
meeting.Agenda = b.Agenda.Value;
|
||||
if(b.Time != null)
|
||||
meeting.StartTime = b.Time.StartTime.Value;
|
||||
meeting.EndTime = b.Time.EndTime.Value;
|
||||
if(b.Privacy != null)
|
||||
meeting.Privacy = CodecCallPrivacy.ConvertToDirectionEnum(b.Privacy.Value);
|
||||
|
||||
//#warning Update this ConnectMode conversion after testing onsite. Expected value is "OBTP", but in PD NYC Test scenarios, "Manual" is being returned for OBTP meetings
|
||||
if (b.DialInfo.ConnectMode != null)
|
||||
if (b.DialInfo.ConnectMode.Value.ToLower() == "obtp" || b.DialInfo.ConnectMode.Value.ToLower() == "manual")
|
||||
meeting.IsOneButtonToPushMeeting = true;
|
||||
|
||||
if (b.DialInfo.Calls.Call != null)
|
||||
{
|
||||
foreach (Call c in b.DialInfo.Calls.Call)
|
||||
{
|
||||
meeting.Calls.Add(new PepperDash.Essentials.Devices.Common.Codec.Call()
|
||||
{
|
||||
Number = c.Number.Value,
|
||||
Protocol = c.Protocol.Value,
|
||||
CallRate = c.CallRate.Value,
|
||||
CallType = c.CallType.Value
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
meetings.Add(meeting);
|
||||
|
||||
if(Debug.Level > 0)
|
||||
{
|
||||
Debug.Console(1, "Title: {0}, ID: {1}, Organizer: {2}, Agenda: {3}", meeting.Title, meeting.Id, meeting.Organizer, meeting.Agenda);
|
||||
Debug.Console(1, " Start Time: {0}, End Time: {1}, Duration: {2}", meeting.StartTime, meeting.EndTime, meeting.Duration);
|
||||
Debug.Console(1, " Joinable: {0}\n", meeting.Joinable);
|
||||
}
|
||||
}
|
||||
|
||||
meetings.OrderBy(m => m.StartTime);
|
||||
|
||||
return meetings;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.VideoCodec
|
||||
{
|
||||
public class CiscoCallHistory
|
||||
{
|
||||
public class CallbackNumber
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class DisplayName
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class LastOccurrenceStartTime
|
||||
{
|
||||
public DateTime Value { get; set; }
|
||||
}
|
||||
|
||||
public class LastOccurrenceDaysAgo
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class LastOccurrenceHistoryId
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class OccurrenceType
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class IsAcknowledged
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class OccurrenceCount
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Entry
|
||||
{
|
||||
public string id { get; set; }
|
||||
public CallbackNumber CallbackNumber { get; set; }
|
||||
public DisplayName DisplayName { get; set; }
|
||||
public LastOccurrenceStartTime LastOccurrenceStartTime { get; set; }
|
||||
public LastOccurrenceDaysAgo LastOccurrenceDaysAgo { get; set; }
|
||||
public LastOccurrenceHistoryId LastOccurrenceHistoryId { get; set; }
|
||||
public OccurrenceType OccurrenceType { get; set; }
|
||||
public IsAcknowledged IsAcknowledged { get; set; }
|
||||
public OccurrenceCount OccurrenceCount { get; set; }
|
||||
}
|
||||
|
||||
public class Offset
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Limit
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class ResultInfo
|
||||
{
|
||||
public Offset Offset { get; set; }
|
||||
public Limit Limit { get; set; }
|
||||
}
|
||||
|
||||
public class CallHistoryRecentsResult
|
||||
{
|
||||
public string status { get; set; }
|
||||
public List<Entry> Entry { get; set; }
|
||||
public ResultInfo ResultInfo { get; set; }
|
||||
}
|
||||
|
||||
public class CommandResponse
|
||||
{
|
||||
public CallHistoryRecentsResult CallHistoryRecentsResult { get; set; }
|
||||
}
|
||||
|
||||
public class RootObject
|
||||
{
|
||||
public CommandResponse CommandResponse { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Essentials.Devices.Common.Cameras;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
|
||||
{
|
||||
public class CiscoFarEndCamera : CameraBase, IHasCameraPtzControl, IAmFarEndCamera
|
||||
{
|
||||
protected CiscoSparkCodec ParentCodec { get; private set; }
|
||||
|
||||
protected string CallId {
|
||||
get
|
||||
{
|
||||
return (ParentCodec as CiscoSparkCodec).GetCallId();
|
||||
}
|
||||
}
|
||||
|
||||
public CiscoFarEndCamera(string key, string name, CiscoSparkCodec codec)
|
||||
: base(key, name)
|
||||
{
|
||||
Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom;
|
||||
|
||||
ParentCodec = codec;
|
||||
}
|
||||
|
||||
#region IHasCameraPtzControl Members
|
||||
|
||||
public void PositionHome()
|
||||
{
|
||||
// Not supported on far end camera
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IHasCameraPanControl Members
|
||||
|
||||
public void PanLeft()
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: Left CallId: {0}", CallId));
|
||||
}
|
||||
|
||||
public void PanRight()
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: Right CallId: {0}", CallId));
|
||||
}
|
||||
|
||||
public void PanStop()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IHasCameraTiltControl Members
|
||||
|
||||
public void TiltDown()
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: Down CallId: {0}", CallId));
|
||||
}
|
||||
|
||||
public void TiltUp()
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: Up CallId: {0}", CallId));
|
||||
}
|
||||
|
||||
public void TiltStop()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IHasCameraZoomControl Members
|
||||
|
||||
public void ZoomIn()
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: ZoomIn CallId: {0}", CallId));
|
||||
}
|
||||
|
||||
public void ZoomOut()
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Move Value: ZoomOut CallId: {0}", CallId));
|
||||
}
|
||||
|
||||
public void ZoomStop()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
void Stop()
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Call FarEndControl Camera Stop CallId: {0}", CallId));
|
||||
}
|
||||
}
|
||||
|
||||
public class CiscoSparkCamera : CameraBase, IHasCameraPtzControl, IHasCameraFocusControl
|
||||
{
|
||||
/// <summary>
|
||||
/// The codec this camera belongs to
|
||||
/// </summary>
|
||||
protected CiscoSparkCodec ParentCodec { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the camera on the codec
|
||||
/// </summary>
|
||||
protected uint CameraId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Valid range 1-15
|
||||
/// </summary>
|
||||
protected uint PanSpeed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Valid range 1-15
|
||||
/// </summary>
|
||||
protected uint TiltSpeed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Valid range 1-15
|
||||
/// </summary>
|
||||
protected uint ZoomSpeed { get; private set; }
|
||||
|
||||
private bool isPanning;
|
||||
|
||||
private bool isTilting;
|
||||
|
||||
private bool isZooming;
|
||||
|
||||
private bool isFocusing;
|
||||
|
||||
private bool isMoving
|
||||
{
|
||||
get
|
||||
{
|
||||
return isPanning || isTilting || isZooming || isFocusing;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public CiscoSparkCamera(string key, string name, CiscoSparkCodec codec, uint id)
|
||||
: base(key, name)
|
||||
{
|
||||
// Default to all capabilties
|
||||
Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom | eCameraCapabilities.Focus;
|
||||
|
||||
ParentCodec = codec;
|
||||
|
||||
CameraId = id;
|
||||
|
||||
// Set default speeds
|
||||
PanSpeed = 7;
|
||||
TiltSpeed = 7;
|
||||
ZoomSpeed = 7;
|
||||
}
|
||||
|
||||
|
||||
// Takes a string from the camera capabilities value and converts from "ptzf" to enum bitmask
|
||||
public void SetCapabilites(string capabilites)
|
||||
{
|
||||
var c = capabilites.ToLower();
|
||||
|
||||
if (c.Contains("p"))
|
||||
Capabilities = Capabilities | eCameraCapabilities.Pan;
|
||||
|
||||
if (c.Contains("t"))
|
||||
Capabilities = Capabilities | eCameraCapabilities.Tilt;
|
||||
|
||||
if (c.Contains("z"))
|
||||
Capabilities = Capabilities | eCameraCapabilities.Zoom;
|
||||
|
||||
if (c.Contains("f"))
|
||||
Capabilities = Capabilities | eCameraCapabilities.Focus;
|
||||
}
|
||||
|
||||
#region IHasCameraPtzControl Members
|
||||
|
||||
public void PositionHome()
|
||||
{
|
||||
// Not supported on Internal Spark Camera
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IHasCameraPanControl Members
|
||||
|
||||
public void PanLeft()
|
||||
{
|
||||
if (!isMoving)
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Left PanSpeed: {1}", CameraId, PanSpeed));
|
||||
isPanning = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void PanRight()
|
||||
{
|
||||
if (!isMoving)
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Right PanSpeed: {1}", CameraId, PanSpeed));
|
||||
isPanning = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void PanStop()
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Pan: Stop", CameraId));
|
||||
isPanning = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region IHasCameraTiltControl Members
|
||||
|
||||
public void TiltDown()
|
||||
{
|
||||
if (!isMoving)
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Down TiltSpeed: {1}", CameraId, TiltSpeed));
|
||||
isTilting = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void TiltUp()
|
||||
{
|
||||
if (!isMoving)
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Up TiltSpeed: {1}", CameraId, TiltSpeed));
|
||||
isTilting = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void TiltStop()
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Tilt: Stop", CameraId));
|
||||
isTilting = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IHasCameraZoomControl Members
|
||||
|
||||
public void ZoomIn()
|
||||
{
|
||||
if (!isMoving)
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: In ZoomSpeed: {1}", CameraId, ZoomSpeed));
|
||||
isZooming = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void ZoomOut()
|
||||
{
|
||||
if (!isMoving)
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: Out ZoomSpeed: {1}", CameraId, ZoomSpeed));
|
||||
isZooming = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void ZoomStop()
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Zoom: Stop", CameraId));
|
||||
isZooming = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IHasCameraFocusControl Members
|
||||
|
||||
public void FocusNear()
|
||||
{
|
||||
if (!isMoving)
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Near", CameraId));
|
||||
isFocusing = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void FocusFar()
|
||||
{
|
||||
if (!isMoving)
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Far", CameraId));
|
||||
isFocusing = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void FocusStop()
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Camera Ramp CameraId: {0} Focus: Stop", CameraId));
|
||||
isFocusing = false;
|
||||
}
|
||||
|
||||
public void TriggerAutoFocus()
|
||||
{
|
||||
ParentCodec.SendText(string.Format("xCommand Camera TriggerAutofocus CameraId: {0}", CameraId));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
{
|
||||
public class CiscoSparkCodecPropertiesConfig
|
||||
{
|
||||
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
||||
|
||||
public List<CodecActiveCallItem> Favorites { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Valid values: "Local" or "Corporate"
|
||||
/// </summary>
|
||||
public string PhonebookMode { get; set; }
|
||||
|
||||
public bool ShowSelfViewByDefault { get; set; }
|
||||
|
||||
public SharingProperties Sharing { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class SharingProperties
|
||||
{
|
||||
public bool AutoShareContentWhileInCall { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.Net.Http;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
|
||||
{
|
||||
public class HttpApiServer
|
||||
{
|
||||
public static Dictionary<string, string> ExtensionContentTypes;
|
||||
|
||||
public event EventHandler<OnHttpRequestArgs> ApiRequest;
|
||||
public Crestron.SimplSharp.Net.Http.HttpServer HttpServer { get; private set; }
|
||||
|
||||
public string HtmlRoot { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// SIMPL+ can only execute the default constructor. If you have variables that require initialization, please
|
||||
/// use an Initialize method
|
||||
/// </summary>
|
||||
public HttpApiServer()
|
||||
{
|
||||
ExtensionContentTypes = new Dictionary<string, string>
|
||||
{
|
||||
{ ".css", "text/css" },
|
||||
{ ".htm", "text/html" },
|
||||
{ ".html", "text/html" },
|
||||
{ ".jpg", "image/jpeg" },
|
||||
{ ".jpeg", "image/jpeg" },
|
||||
{ ".js", "application/javascript" },
|
||||
{ ".json", "application/json" },
|
||||
{ ".xml", "text/xml" },
|
||||
{ ".map", "application/x-navimap" },
|
||||
{ ".pdf", "application.pdf" },
|
||||
{ ".png", "image/png" },
|
||||
{ ".txt", "text/plain" },
|
||||
};
|
||||
HtmlRoot = @"\HTML";
|
||||
}
|
||||
|
||||
|
||||
public void Start(int port)
|
||||
{
|
||||
// TEMP - this should be inserted by configuring class
|
||||
|
||||
HttpServer = new Crestron.SimplSharp.Net.Http.HttpServer();
|
||||
HttpServer.ServerName = "Cisco API Server";
|
||||
HttpServer.KeepAlive = true;
|
||||
HttpServer.Port = port;
|
||||
HttpServer.OnHttpRequest += Server_Request;
|
||||
HttpServer.Open();
|
||||
|
||||
CrestronEnvironment.ProgramStatusEventHandler += (a) =>
|
||||
{
|
||||
if (a == eProgramStatusEventType.Stopping)
|
||||
{
|
||||
HttpServer.Close();
|
||||
Debug.Console(1, "Shutting down HTTP Server on port {0}", HttpServer.Port);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void Server_Request(object sender, OnHttpRequestArgs args)
|
||||
{
|
||||
if (args.Request.Header.RequestType == "OPTIONS")
|
||||
{
|
||||
Debug.Console(2, "Asking for OPTIONS");
|
||||
args.Response.Header.SetHeaderValue("Access-Control-Allow-Origin", "*");
|
||||
args.Response.Header.SetHeaderValue("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS");
|
||||
return;
|
||||
}
|
||||
|
||||
string path = Uri.UnescapeDataString(args.Request.Path);
|
||||
var host = args.Request.DataConnection.RemoteEndPointAddress;
|
||||
//string authToken;
|
||||
|
||||
Debug.Console(2, "HTTP Request: {2}: Path='{0}' ?'{1}'", path, args.Request.QueryString, host);
|
||||
|
||||
// ----------------------------------- ADD AUTH HERE
|
||||
if (path.StartsWith("/cisco/api"))
|
||||
{
|
||||
var handler = ApiRequest;
|
||||
if (ApiRequest != null)
|
||||
ApiRequest(this, args);
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetContentType(string extension)
|
||||
{
|
||||
string type;
|
||||
if (ExtensionContentTypes.ContainsKey(extension))
|
||||
type = ExtensionContentTypes[extension];
|
||||
else
|
||||
type = "text/plain";
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,397 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.VideoCodec
|
||||
{
|
||||
public class CiscoCodecPhonebook
|
||||
{
|
||||
public class Offset
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Limit
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class TotalRows
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class ResultInfo
|
||||
{
|
||||
public Offset Offset { get; set; }
|
||||
public Limit Limit { get; set; }
|
||||
public TotalRows TotalRows { get; set; }
|
||||
}
|
||||
|
||||
public class LocalId
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class FolderId
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class ParentFolderId
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Name
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Folder
|
||||
{
|
||||
public string id { get; set; }
|
||||
public LocalId LocalId { get; set; }
|
||||
public FolderId FolderId { get; set; }
|
||||
public Name Name { get; set; }
|
||||
public ParentFolderId ParentFolderId { get; set; }
|
||||
}
|
||||
|
||||
public class Name2
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class ContactId
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class FolderId2
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Title
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class ContactMethodId
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Number
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Device
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class CallType
|
||||
{
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class ContactMethod
|
||||
{
|
||||
public string id { get; set; }
|
||||
public ContactMethodId ContactMethodId { get; set; }
|
||||
public Number Number { get; set; }
|
||||
public Device Device { get; set; }
|
||||
public CallType CallType { get; set; }
|
||||
|
||||
public ContactMethod()
|
||||
{
|
||||
ContactMethodId = new ContactMethodId();
|
||||
Number = new Number();
|
||||
Device = new Device();
|
||||
CallType = new CallType();
|
||||
}
|
||||
}
|
||||
|
||||
public class Contact
|
||||
{
|
||||
public string id { get; set; }
|
||||
public Name2 Name { get; set; }
|
||||
public ContactId ContactId { get; set; }
|
||||
public FolderId2 FolderId { get; set; }
|
||||
public Title Title { get; set; }
|
||||
public List<ContactMethod> ContactMethod { get; set; }
|
||||
|
||||
public Contact()
|
||||
{
|
||||
Name = new Name2();
|
||||
ContactId = new ContactId();
|
||||
FolderId = new FolderId2();
|
||||
Title = new Title();
|
||||
ContactMethod = new List<ContactMethod>();
|
||||
}
|
||||
}
|
||||
|
||||
public class PhonebookSearchResult
|
||||
{
|
||||
public string status { get; set; }
|
||||
public ResultInfo ResultInfo { get; set; }
|
||||
public List<Folder> Folder { get; set; }
|
||||
public List<Contact> Contact { get; set; }
|
||||
|
||||
public PhonebookSearchResult()
|
||||
{
|
||||
Folder = new List<Folder>();
|
||||
Contact = new List<Contact>();
|
||||
ResultInfo = new ResultInfo();
|
||||
}
|
||||
}
|
||||
|
||||
public class CommandResponse
|
||||
{
|
||||
public PhonebookSearchResult PhonebookSearchResult { get; set; }
|
||||
}
|
||||
|
||||
public class RootObject
|
||||
{
|
||||
public CommandResponse CommandResponse { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the folders with no ParentFolder and returns them sorted alphabetically
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public static List<DirectoryItem> GetRootFoldersFromSearchResult(PhonebookSearchResult result)
|
||||
{
|
||||
var rootFolders = new List<DirectoryItem>();
|
||||
|
||||
if (result.Folder.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if (result.Folder.Count > 0)
|
||||
{
|
||||
if (Debug.Level > 0)
|
||||
Debug.Console(1, "Phonebook Folders:\n");
|
||||
|
||||
foreach (Folder f in result.Folder)
|
||||
{
|
||||
var folder = new DirectoryFolder();
|
||||
|
||||
folder.Name = f.Name.Value;
|
||||
folder.FolderId = f.FolderId.Value;
|
||||
|
||||
if (f.ParentFolderId == null)
|
||||
rootFolders.Add(folder);
|
||||
|
||||
if (Debug.Level > 0)
|
||||
Debug.Console(1, "+ {0}", folder.Name);
|
||||
}
|
||||
}
|
||||
|
||||
rootFolders.OrderBy(f => f.Name);
|
||||
|
||||
return rootFolders;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the contacts with no FolderId and returns them sorted alphabetically
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public static List<DirectoryItem> GetRootContactsFromSearchResult(PhonebookSearchResult result)
|
||||
{
|
||||
var rootContacts = new List<DirectoryItem>();
|
||||
|
||||
if (result.Contact.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if (result.Contact.Count > 0)
|
||||
{
|
||||
if (Debug.Level > 0)
|
||||
Debug.Console(1, "Root Contacts:\n");
|
||||
|
||||
foreach (Contact c in result.Contact)
|
||||
{
|
||||
var contact = new DirectoryContact();
|
||||
|
||||
if (string.IsNullOrEmpty(c.FolderId.Value))
|
||||
{
|
||||
contact.Name = c.Name.Value;
|
||||
contact.ContactId = c.ContactId.Value;
|
||||
|
||||
if(!string.IsNullOrEmpty(c.Title.Value))
|
||||
contact.Title = c.Title.Value;
|
||||
|
||||
if (Debug.Level > 0)
|
||||
Debug.Console(1, "{0}\nContact Methods:", contact.Name);
|
||||
|
||||
foreach (ContactMethod m in c.ContactMethod)
|
||||
{
|
||||
|
||||
var tempContactMethod = new PepperDash.Essentials.Devices.Common.Codec.ContactMethod();
|
||||
|
||||
eContactMethodCallType callType = eContactMethodCallType.Unknown;
|
||||
if (!string.IsNullOrEmpty(m.CallType.Value))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(m.CallType.Value))
|
||||
{
|
||||
if (m.CallType.Value.ToLower() == "audio")
|
||||
callType = eContactMethodCallType.Audio;
|
||||
else if (m.CallType.Value.ToLower() == "video")
|
||||
callType = eContactMethodCallType.Video;
|
||||
|
||||
tempContactMethod.CallType = callType;
|
||||
}
|
||||
}
|
||||
|
||||
eContactMethodDevice device = eContactMethodDevice.Unknown;
|
||||
if (!string.IsNullOrEmpty(m.Device.Value))
|
||||
{
|
||||
|
||||
if (m.Device.Value.ToLower() == "mobile")
|
||||
device = eContactMethodDevice.Mobile;
|
||||
else if (m.Device.Value.ToLower() == "telephone")
|
||||
device = eContactMethodDevice.Telephone;
|
||||
else if (m.Device.Value.ToLower() == "video")
|
||||
device = eContactMethodDevice.Video;
|
||||
else if (m.Device.Value.ToLower() == "other")
|
||||
device = eContactMethodDevice.Other;
|
||||
|
||||
tempContactMethod.Device = device;
|
||||
}
|
||||
|
||||
if (Debug.Level > 0)
|
||||
Debug.Console(1, "Number: {0}", m.Number.Value);
|
||||
|
||||
tempContactMethod.Number = m.Number.Value;
|
||||
tempContactMethod.ContactMethodId = m.ContactMethodId.Value;
|
||||
|
||||
contact.ContactMethods.Add(tempContactMethod);
|
||||
}
|
||||
rootContacts.Add(contact);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rootContacts.OrderBy(f => f.Name);
|
||||
|
||||
return rootContacts;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Converts data returned from a cisco codec to the generic Directory format.
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <param name="resultFolder"></param>
|
||||
/// <returns></returns>
|
||||
public static CodecDirectory ConvertCiscoPhonebookToGeneric(PhonebookSearchResult result)
|
||||
{
|
||||
var directory = new Codec.CodecDirectory();
|
||||
|
||||
var folders = new List<Codec.DirectoryItem>();
|
||||
|
||||
var contacts = new List<Codec.DirectoryItem>();
|
||||
|
||||
try
|
||||
{
|
||||
if (result.Folder.Count > 0)
|
||||
{
|
||||
foreach (Folder f in result.Folder)
|
||||
{
|
||||
var folder = new DirectoryFolder();
|
||||
|
||||
folder.Name = f.Name.Value;
|
||||
folder.FolderId = f.FolderId.Value;
|
||||
|
||||
if (f.ParentFolderId != null)
|
||||
{
|
||||
folder.ParentFolderId = f.ParentFolderId.Value;
|
||||
}
|
||||
|
||||
folders.Add(folder);
|
||||
}
|
||||
|
||||
folders.OrderBy(f => f.Name);
|
||||
|
||||
directory.AddFoldersToDirectory(folders);
|
||||
}
|
||||
|
||||
if (result.Contact.Count > 0)
|
||||
{
|
||||
foreach (Contact c in result.Contact)
|
||||
{
|
||||
var contact = new DirectoryContact();
|
||||
|
||||
contact.Name = c.Name.Value;
|
||||
contact.ContactId = c.ContactId.Value;
|
||||
if (!string.IsNullOrEmpty(c.Title.Value))
|
||||
contact.Title = c.Title.Value;
|
||||
|
||||
if (c.FolderId != null)
|
||||
{
|
||||
contact.FolderId = c.FolderId.Value;
|
||||
}
|
||||
|
||||
foreach (ContactMethod m in c.ContactMethod)
|
||||
{
|
||||
eContactMethodCallType callType = eContactMethodCallType.Unknown;
|
||||
if (!string.IsNullOrEmpty(m.CallType.Value))
|
||||
{
|
||||
if (m.CallType.Value.ToLower() == "audio")
|
||||
callType = eContactMethodCallType.Audio;
|
||||
else if (m.CallType.Value.ToLower() == "video")
|
||||
callType = eContactMethodCallType.Video;
|
||||
}
|
||||
|
||||
eContactMethodDevice device = eContactMethodDevice.Unknown;
|
||||
|
||||
if (!string.IsNullOrEmpty(m.Device.Value))
|
||||
{
|
||||
if (m.Device.Value.ToLower() == "mobile")
|
||||
device = eContactMethodDevice.Mobile;
|
||||
else if (m.Device.Value.ToLower() == "telephone")
|
||||
device = eContactMethodDevice.Telephone;
|
||||
else if (m.Device.Value.ToLower() == "video")
|
||||
device = eContactMethodDevice.Video;
|
||||
else if (m.Device.Value.ToLower() == "other")
|
||||
device = eContactMethodDevice.Other;
|
||||
}
|
||||
|
||||
contact.ContactMethods.Add(new PepperDash.Essentials.Devices.Common.Codec.ContactMethod()
|
||||
{
|
||||
Number = m.Number.Value,
|
||||
ContactMethodId = m.ContactMethodId.Value,
|
||||
CallType = callType,
|
||||
Device = device
|
||||
});
|
||||
}
|
||||
contacts.Add(contact);
|
||||
}
|
||||
|
||||
contacts.OrderBy(c => c.Name);
|
||||
|
||||
directory.AddContactsToDirectory(contacts);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(1, "Error converting Cisco Phonebook results to generic: {0}", e);
|
||||
}
|
||||
|
||||
return directory;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.VideoCodec
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for camera presets
|
||||
/// </summary>
|
||||
public interface IHasCodecRoomPresets
|
||||
{
|
||||
event EventHandler<EventArgs> CodecRoomPresetsListHasChanged;
|
||||
|
||||
List<CodecRoomPreset> NearEndPresets { get; }
|
||||
|
||||
List<CodecRoomPreset> FarEndRoomPresets { get; }
|
||||
|
||||
void CodecRoomPresetSelect(int preset);
|
||||
|
||||
void CodecRoomPresetStore(int preset, string description);
|
||||
}
|
||||
|
||||
public static class RoomPresets
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts Cisco RoomPresets to generic CameraPresets
|
||||
/// </summary>
|
||||
/// <param name="presets"></param>
|
||||
/// <returns></returns>
|
||||
public static List<CodecRoomPreset> GetGenericPresets(List<CiscoCodecStatus.RoomPreset> presets)
|
||||
{
|
||||
var cameraPresets = new List<CodecRoomPreset>();
|
||||
|
||||
if (Debug.Level > 0)
|
||||
{
|
||||
Debug.Console(1, "Presets List:");
|
||||
}
|
||||
|
||||
foreach (CiscoCodecStatus.RoomPreset preset in presets)
|
||||
{
|
||||
try
|
||||
{
|
||||
var cameraPreset = new CodecRoomPreset(UInt16.Parse(preset.id), preset.Description.Value, preset.Defined.BoolValue, true);
|
||||
|
||||
cameraPresets.Add(cameraPreset);
|
||||
|
||||
if (Debug.Level > 0)
|
||||
{
|
||||
Debug.Console(1, "Added Preset ID: {0}, Description: {1}, IsDefined: {2}, isDefinable: {3}", cameraPreset.ID, cameraPreset.Description, cameraPreset.Defined, cameraPreset.IsDefinable);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(2, "Unable to convert preset: {0}. Error: {1}", preset.id, e);
|
||||
}
|
||||
}
|
||||
|
||||
return cameraPresets;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a room preset on a video coded. Typically stores camera position(s) and video routing. Can be recalled by Far End if enabled.
|
||||
/// </summary>
|
||||
public class CodecRoomPreset
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int ID { get; set; }
|
||||
/// <summary>
|
||||
/// Used to store the name of the preset
|
||||
/// </summary>
|
||||
[JsonProperty("description")]
|
||||
public string Description { get; set; }
|
||||
/// <summary>
|
||||
/// Indicates if the preset is defined(stored) in the codec
|
||||
/// </summary>
|
||||
[JsonProperty("defined")]
|
||||
public bool Defined { get; set; }
|
||||
/// <summary>
|
||||
/// Indicates if the preset has the capability to be defined
|
||||
/// </summary>
|
||||
[JsonProperty("isDefinable")]
|
||||
public bool IsDefinable { get; set; }
|
||||
|
||||
public CodecRoomPreset(int id, string description, bool def, bool isDef)
|
||||
{
|
||||
ID = id;
|
||||
Description = description;
|
||||
Defined = def;
|
||||
IsDefinable = isDef;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,141 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
|
||||
{
|
||||
/// <summary>
|
||||
/// This class exists to capture serialized data sent back by a Cisco codec in JSON output mode
|
||||
/// </summary>
|
||||
public class CiscoCodecEvents
|
||||
{
|
||||
public class CauseValue
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class CauseType
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class CauseString
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class OrigCallDirection
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class RemoteURI
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class DisplayName
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class CallId
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class CauseCode
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class CauseOrigin
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Protocol
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Duration
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class CallType
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class CallRate
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Encryption
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class RequestedURI
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class PeopleCountAverage
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class CallDisconnect
|
||||
{
|
||||
public string id { get; set; }
|
||||
public CauseValue CauseValue { get; set; }
|
||||
public CauseType CauseType { get; set; }
|
||||
public CauseString CauseString { get; set; }
|
||||
public OrigCallDirection OrigCallDirection { get; set; }
|
||||
public RemoteURI RemoteURI { get; set; }
|
||||
public DisplayName DisplayName { get; set; }
|
||||
public CallId CallId { get; set; }
|
||||
public CauseCode CauseCode { get; set; }
|
||||
public CauseOrigin CauseOrigin { get; set; }
|
||||
public Protocol Protocol { get; set; }
|
||||
public Duration Duration { get; set; }
|
||||
public CallType CallType { get; set; }
|
||||
public CallRate CallRate { get; set; }
|
||||
public Encryption Encryption { get; set; }
|
||||
public RequestedURI RequestedURI { get; set; }
|
||||
public PeopleCountAverage PeopleCountAverage { get; set; }
|
||||
}
|
||||
|
||||
public class Event
|
||||
{
|
||||
public CallDisconnect CallDisconnect { get; set; }
|
||||
}
|
||||
|
||||
public class RootObject
|
||||
{
|
||||
public Event Event { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.VideoCodec
|
||||
|
||||
{
|
||||
public class CodecActiveCallItem
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Number { get; set; }
|
||||
|
||||
<<<<<<< HEAD
|
||||
public eCodecCallType Type { get; private set; }
|
||||
|
||||
public CodecActiveCallItem(string name, string number, eCodecCallType type)
|
||||
{
|
||||
Name = name;
|
||||
Number = number;
|
||||
Type = type;
|
||||
}
|
||||
=======
|
||||
public eCodecCallType Type { get; set; }
|
||||
|
||||
public eCodecCallStatus Status { get; set; }
|
||||
|
||||
public string Id { get; set; }
|
||||
>>>>>>> origin/feature/cisco-spark-2
|
||||
}
|
||||
|
||||
public enum eCodecCallType
|
||||
{
|
||||
None, Audio, Video
|
||||
}
|
||||
|
||||
public enum eCodecCallStatus
|
||||
{
|
||||
Dialing, Established, Incoming
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||
{
|
||||
public enum eCameraControlMode
|
||||
{
|
||||
Off = 0,
|
||||
Manual,
|
||||
Auto
|
||||
}
|
||||
|
||||
|
||||
public interface IHasCameras
|
||||
{
|
||||
event EventHandler<CameraSelectedEventArgs> CameraSelected;
|
||||
|
||||
List<CameraBase> Cameras { get; }
|
||||
|
||||
CameraBase SelectedCamera { get; }
|
||||
|
||||
StringFeedback SelectedCameraFeedback { get; }
|
||||
|
||||
void SelectCamera(string key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aggregates far end cameras with near end cameras
|
||||
/// </summary>
|
||||
public interface IHasCodecCameras : IHasCameras, IHasFarEndCameraControl
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To be implmented on codecs that can disable their camera(s) to blank the near end video
|
||||
/// </summary>
|
||||
public interface IHasCameraOff
|
||||
{
|
||||
BoolFeedback CameraIsOffFeedback { get; }
|
||||
void CameraOff();
|
||||
}
|
||||
|
||||
public class CameraSelectedEventArgs : EventArgs
|
||||
{
|
||||
public CameraBase SelectedCamera { get; private set; }
|
||||
|
||||
public CameraSelectedEventArgs(CameraBase camera)
|
||||
{
|
||||
SelectedCamera = camera;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IHasFarEndCameraControl
|
||||
{
|
||||
CameraBase FarEndCamera { get; }
|
||||
|
||||
BoolFeedback ControllingFarEndCameraFeedback { get; }
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to decorate a camera as a far end
|
||||
/// </summary>
|
||||
public interface IAmFarEndCamera
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aggregates the pan, tilt and zoom interfaces
|
||||
/// </summary>
|
||||
public interface IHasCameraPtzControl : IHasCameraPanControl, IHasCameraTiltControl, IHasCameraZoomControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Resets the camera position
|
||||
/// </summary>
|
||||
void PositionHome();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface for camera pan control
|
||||
/// </summary>
|
||||
public interface IHasCameraPanControl
|
||||
{
|
||||
void PanLeft();
|
||||
void PanRight();
|
||||
void PanStop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface for camera tilt control
|
||||
/// </summary>
|
||||
public interface IHasCameraTiltControl
|
||||
{
|
||||
void TiltDown();
|
||||
void TiltUp();
|
||||
void TiltStop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface for camera zoom control
|
||||
/// </summary>
|
||||
public interface IHasCameraZoomControl
|
||||
{
|
||||
void ZoomIn();
|
||||
void ZoomOut();
|
||||
void ZoomStop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface for camera focus control
|
||||
/// </summary>
|
||||
public interface IHasCameraFocusControl
|
||||
{
|
||||
void FocusNear();
|
||||
void FocusFar();
|
||||
void FocusStop();
|
||||
|
||||
void TriggerAutoFocus();
|
||||
}
|
||||
|
||||
public interface IHasCameraAutoMode
|
||||
{
|
||||
void CameraAutoModeOn();
|
||||
void CameraAutoModeOff();
|
||||
void CameraAutoModeToggle();
|
||||
BoolFeedback CameraAutoModeIsOnFeedback { get; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user