mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-01-18 15:05:01 +00:00
Compare commits
134 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca9da1ef79 | ||
|
|
e0bfb8f091 | ||
|
|
97db1f35a1 | ||
|
|
2b6a13271f | ||
|
|
4686799371 | ||
|
|
cb750a2fd0 | ||
|
|
6d81e8d21e | ||
|
|
600b9f11ff | ||
|
|
c20036cfe9 | ||
|
|
005b3f0843 | ||
|
|
fbe5df84be | ||
|
|
8e4c84dd02 | ||
|
|
dace2a57c2 | ||
|
|
3cf188f820 | ||
|
|
80377a41d0 | ||
|
|
a0ebc08838 | ||
|
|
0de4fbb69c | ||
|
|
c88b259c71 | ||
|
|
20660c561a | ||
|
|
b44613b91f | ||
|
|
58de8ce8ad | ||
|
|
33f0a1fe32 | ||
|
|
4b0f8abd9f | ||
|
|
4defea55f0 | ||
|
|
9c8f85555e | ||
|
|
62e2c3d19f | ||
|
|
e1c8b54434 | ||
|
|
6d913e8a72 | ||
|
|
afa1cff0e0 | ||
|
|
ce6cecbb79 | ||
|
|
69314bb1f1 | ||
|
|
fb19b5894b | ||
|
|
82fad55c1e | ||
|
|
8d03e81431 | ||
|
|
fa8ea4cef6 | ||
|
|
97a44ffa4f | ||
|
|
ee55be86e0 | ||
|
|
ced1efdb47 | ||
|
|
5129b19748 | ||
|
|
525881ebe1 | ||
|
|
856a81ded4 | ||
|
|
ef8298ccd6 | ||
|
|
cdbab152f6 | ||
|
|
359bd508e5 | ||
|
|
62e5e6f176 | ||
|
|
2d375ed2d7 | ||
|
|
2e78191e33 | ||
|
|
45ac17622a | ||
|
|
e7e6ae98cf | ||
|
|
2fbd645bf0 | ||
|
|
2a4ed67bee | ||
|
|
17c448e309 | ||
|
|
5afa626fb3 | ||
|
|
ba1e8646e5 | ||
|
|
88e82fb398 | ||
|
|
53ee87c9be | ||
|
|
032bb2b8e5 | ||
|
|
6ee56dd66c | ||
|
|
d887b448c9 | ||
|
|
f099c88352 | ||
|
|
f98a429b55 | ||
|
|
645816c75f | ||
|
|
491fff2793 | ||
|
|
952e7f4083 | ||
|
|
56c418580c | ||
|
|
4134622b28 | ||
|
|
09b3f7c5e7 | ||
|
|
9fa2b22448 | ||
|
|
62d8190eef | ||
|
|
19284b171a | ||
|
|
29c60548cc | ||
|
|
17f147b5e0 | ||
|
|
7aa3d50cd6 | ||
|
|
b85abe1b79 | ||
|
|
b7bab6cfd1 | ||
|
|
b83b3737e9 | ||
|
|
42c4c705c9 | ||
|
|
cb41b31018 | ||
|
|
6f028c06ae | ||
|
|
bc25c31860 | ||
|
|
32b548eba0 | ||
|
|
f83e64ee7e | ||
|
|
2ee365447c | ||
|
|
e5ac725b85 | ||
|
|
d0cbb8d096 | ||
|
|
91f6235441 | ||
|
|
3c256564c6 | ||
|
|
53de4f32eb | ||
|
|
9effa78fdf | ||
|
|
ba5036e400 | ||
|
|
cd747a01ea | ||
|
|
ac4ef972fe | ||
|
|
857d10f0b2 | ||
|
|
b45fb57cb2 | ||
|
|
e1e2627f56 | ||
|
|
d1646f8216 | ||
|
|
02cfc46f90 | ||
|
|
0fb946c7d5 | ||
|
|
026ab438ad | ||
|
|
51afb966d5 | ||
|
|
68fb82f801 | ||
|
|
0830fb8943 | ||
|
|
2ed63e7c84 | ||
|
|
08a4497f2c | ||
|
|
85d79c5265 | ||
|
|
fe76b257b2 | ||
|
|
800de511ce | ||
|
|
82784f00a4 | ||
|
|
289a33451f | ||
|
|
ae496f556b | ||
|
|
762f13c708 | ||
|
|
a61bfc4173 | ||
|
|
c3d455a7c2 | ||
|
|
864e65fe92 | ||
|
|
385dd8a482 | ||
|
|
19860be486 | ||
|
|
4d6a680f23 | ||
|
|
f9cb4e8a34 | ||
|
|
07e77f2ce4 | ||
|
|
6dbc152810 | ||
|
|
a3580ca15c | ||
|
|
7a1ead7b56 | ||
|
|
f9d1a737c4 | ||
|
|
d9013157ad | ||
|
|
43f0ae0533 | ||
|
|
6d66c7d896 | ||
|
|
f327ab1590 | ||
|
|
47fc2f3371 | ||
|
|
d1197329f3 | ||
|
|
a0817307b1 | ||
|
|
43c3b83637 | ||
|
|
2a485e36c8 | ||
|
|
bc47c65e48 | ||
|
|
1ad5bc68e5 |
@@ -26,16 +26,24 @@ namespace PepperDash.Essentials.Core
|
||||
public ComPortController(string key, ComPort port, ComPort.ComPortSpec spec)
|
||||
: base(key)
|
||||
{
|
||||
if (port == null)
|
||||
{
|
||||
Debug.Console(0, this, "ERROR: Invalid com port, continuing but comms will not function");
|
||||
return;
|
||||
}
|
||||
|
||||
Port = port;
|
||||
Spec = spec;
|
||||
//IsConnected = new BoolFeedback(CommonBoolCue.IsConnected, () => true);
|
||||
|
||||
if (Port.Parent is CrestronControlSystem)
|
||||
{
|
||||
|
||||
|
||||
var result = Port.Register();
|
||||
if (result != eDeviceRegistrationUnRegistrationResponse.Success)
|
||||
{
|
||||
Debug.Console(0, this, "WARNING: Cannot register Com port: {0}", result);
|
||||
Debug.Console(0, this, "ERROR: Cannot register Com port: {0}", result);
|
||||
return; // false
|
||||
}
|
||||
}
|
||||
@@ -80,11 +88,15 @@ namespace PepperDash.Essentials.Core
|
||||
|
||||
public void SendText(string text)
|
||||
{
|
||||
if (Port == null)
|
||||
return;
|
||||
Port.Send(text);
|
||||
}
|
||||
|
||||
public void SendBytes(byte[] bytes)
|
||||
{
|
||||
if (Port == null)
|
||||
return;
|
||||
var text = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length);
|
||||
Port.Send(text);
|
||||
}
|
||||
|
||||
@@ -1,178 +1,198 @@
|
||||
using System;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CommFactory
|
||||
{
|
||||
public static EssentialsControlPropertiesConfig GetControlPropertiesConfig(DeviceConfig deviceConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
return JsonConvert.DeserializeObject<EssentialsControlPropertiesConfig>
|
||||
(deviceConfig.Properties["control"].ToString());
|
||||
//Debug.Console(2, "Control TEST: {0}", JsonConvert.SerializeObject(controlConfig));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
Debug.Console(0, "ERROR: [{0}] Control properties deserialize failed:\r{1}", deviceConfig.Key, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a comm method of either com port, TCP, SSH
|
||||
/// </summary>
|
||||
/// <param name="deviceConfig">The Device config object</param>
|
||||
public static IBasicCommunication CreateCommForDevice(DeviceConfig deviceConfig)
|
||||
{
|
||||
EssentialsControlPropertiesConfig controlConfig = GetControlPropertiesConfig(deviceConfig);
|
||||
if (controlConfig == null)
|
||||
return null;
|
||||
|
||||
IBasicCommunication comm = null;
|
||||
try
|
||||
{
|
||||
var c = controlConfig.TcpSshProperties;
|
||||
switch (controlConfig.Method)
|
||||
{
|
||||
case eControlMethod.Com:
|
||||
comm = new ComPortController(deviceConfig.Key + "-com", GetComPort(controlConfig), controlConfig.ComParams);
|
||||
break;
|
||||
case eControlMethod.IR:
|
||||
break;
|
||||
case eControlMethod.Ssh:
|
||||
{
|
||||
var ssh = new GenericSshClient(deviceConfig.Key + "-ssh", c.Address, c.Port, c.Username, c.Password);
|
||||
ssh.AutoReconnect = c.AutoReconnect;
|
||||
if(ssh.AutoReconnect)
|
||||
ssh.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
|
||||
comm = ssh;
|
||||
break;
|
||||
}
|
||||
case eControlMethod.Tcpip:
|
||||
{
|
||||
var tcp = new GenericTcpIpClient(deviceConfig.Key + "-tcp", c.Address, c.Port, c.BufferSize);
|
||||
tcp.AutoReconnect = c.AutoReconnect;
|
||||
if (tcp.AutoReconnect)
|
||||
tcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
|
||||
comm = tcp;
|
||||
break;
|
||||
}
|
||||
case eControlMethod.Telnet:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, "Cannot create communication from JSON:\r{0}\r\rException:\r{1}",
|
||||
deviceConfig.Properties.ToString(), e);
|
||||
}
|
||||
|
||||
// put it in the device manager if it's the right flavor
|
||||
var comDev = comm as Device;
|
||||
if (comDev != null)
|
||||
DeviceManager.AddDevice(comDev);
|
||||
return comm;
|
||||
}
|
||||
|
||||
public static ComPort GetComPort(EssentialsControlPropertiesConfig config)
|
||||
{
|
||||
var comPar = config.ComParams;
|
||||
var dev = GetIComPortsDeviceFromManagedDevice(config.ControlPortDevKey);
|
||||
if (dev != null && config.ControlPortNumber <= dev.NumberOfComPorts)
|
||||
return dev.ComPorts[config.ControlPortNumber];
|
||||
Debug.Console(0, "GetComPort: Device '{0}' does not have com port {1}", config.ControlPortDevKey, config.ControlPortNumber);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper to grab the IComPorts device for this PortDeviceKey. Key "controlSystem" will
|
||||
/// return the ControlSystem object from the Global class.
|
||||
/// </summary>
|
||||
/// <returns>IComPorts device or null if the device is not found or does not implement IComPorts</returns>
|
||||
public static IComPorts GetIComPortsDeviceFromManagedDevice(string ComPortDevKey)
|
||||
{
|
||||
if ((ComPortDevKey.Equals("controlSystem", System.StringComparison.OrdinalIgnoreCase)
|
||||
|| ComPortDevKey.Equals("processor", System.StringComparison.OrdinalIgnoreCase))
|
||||
&& Global.ControlSystem is IComPorts)
|
||||
return Global.ControlSystem;
|
||||
else
|
||||
{
|
||||
var dev = DeviceManager.GetDeviceForKey(ComPortDevKey) as IComPorts;
|
||||
if (dev == null)
|
||||
Debug.Console(0, "ComPortConfig: Cannot find com port device '{0}'", ComPortDevKey);
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class EssentialsControlPropertiesConfig :
|
||||
PepperDash.Core.ControlPropertiesConfig
|
||||
{
|
||||
// ****** All of these things, except for #Pro-specific com stuff, were
|
||||
// moved into PepperDash.Core to help non-pro PortalSync.
|
||||
|
||||
//public eControlMethod Method { get; set; }
|
||||
|
||||
//public string ControlPortDevKey { get; set; }
|
||||
|
||||
//[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] // In case "null" is present in config on this value
|
||||
//public uint ControlPortNumber { get; set; }
|
||||
|
||||
//public TcpSshPropertiesConfig TcpSshProperties { get; set; }
|
||||
|
||||
//public string IrFile { get; set; }
|
||||
|
||||
//public ComPortConfig ComParams { get; set; }
|
||||
|
||||
[JsonConverter(typeof(ComSpecJsonConverter))]
|
||||
public ComPort.ComPortSpec ComParams { get; set; }
|
||||
|
||||
//public string IpId { get; set; }
|
||||
|
||||
//[JsonIgnore]
|
||||
//public uint IpIdInt { get { return Convert.ToUInt32(IpId, 16); } }
|
||||
|
||||
//public char EndOfLineChar { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// Defaults to Environment.NewLine;
|
||||
///// </summary>
|
||||
//public string EndOfLineString { get; set; }
|
||||
|
||||
//public string DeviceReadyResponsePattern { get; set; }
|
||||
|
||||
//public EssentialsControlPropertiesConfig()
|
||||
//{
|
||||
// EndOfLineString = CrestronEnvironment.NewLine;
|
||||
//}
|
||||
}
|
||||
|
||||
public class IrControlSpec
|
||||
{
|
||||
public string PortDeviceKey { get; set; }
|
||||
public uint PortNumber { get; set; }
|
||||
public string File { get; set; }
|
||||
}
|
||||
|
||||
//public enum eControlMethod
|
||||
//{
|
||||
// None = 0, Com, IpId, IR, Ssh, Tcpip, Telnet
|
||||
//}
|
||||
using System;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CommFactory
|
||||
{
|
||||
public static EssentialsControlPropertiesConfig GetControlPropertiesConfig(DeviceConfig deviceConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
return JsonConvert.DeserializeObject<EssentialsControlPropertiesConfig>
|
||||
(deviceConfig.Properties["control"].ToString());
|
||||
//Debug.Console(2, "Control TEST: {0}", JsonConvert.SerializeObject(controlConfig));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
Debug.Console(0, "ERROR: [{0}] Control properties deserialize failed:\r{1}", deviceConfig.Key, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a comm method of either com port, TCP, SSH
|
||||
/// </summary>
|
||||
/// <param name="deviceConfig">The Device config object</param>
|
||||
public static IBasicCommunication CreateCommForDevice(DeviceConfig deviceConfig)
|
||||
{
|
||||
EssentialsControlPropertiesConfig controlConfig = GetControlPropertiesConfig(deviceConfig);
|
||||
if (controlConfig == null)
|
||||
return null;
|
||||
|
||||
IBasicCommunication comm = null;
|
||||
try
|
||||
{
|
||||
var c = controlConfig.TcpSshProperties;
|
||||
switch (controlConfig.Method)
|
||||
{
|
||||
case eControlMethod.Com:
|
||||
comm = new ComPortController(deviceConfig.Key + "-com", GetComPort(controlConfig), controlConfig.ComParams);
|
||||
break;
|
||||
case eControlMethod.IR:
|
||||
break;
|
||||
case eControlMethod.Ssh:
|
||||
{
|
||||
var ssh = new GenericSshClient(deviceConfig.Key + "-ssh", c.Address, c.Port, c.Username, c.Password);
|
||||
ssh.AutoReconnect = c.AutoReconnect;
|
||||
if(ssh.AutoReconnect)
|
||||
ssh.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
|
||||
comm = ssh;
|
||||
break;
|
||||
}
|
||||
case eControlMethod.Tcpip:
|
||||
{
|
||||
var tcp = new GenericTcpIpClient(deviceConfig.Key + "-tcp", c.Address, c.Port, c.BufferSize);
|
||||
tcp.AutoReconnect = c.AutoReconnect;
|
||||
if (tcp.AutoReconnect)
|
||||
tcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
|
||||
comm = tcp;
|
||||
break;
|
||||
}
|
||||
case eControlMethod.Telnet:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, "Cannot create communication from JSON:\r{0}\r\rException:\r{1}",
|
||||
deviceConfig.Properties.ToString(), e);
|
||||
}
|
||||
|
||||
// put it in the device manager if it's the right flavor
|
||||
var comDev = comm as Device;
|
||||
if (comDev != null)
|
||||
DeviceManager.AddDevice(comDev);
|
||||
return comm;
|
||||
}
|
||||
|
||||
public static ComPort GetComPort(EssentialsControlPropertiesConfig config)
|
||||
{
|
||||
var comPar = config.ComParams;
|
||||
var dev = GetIComPortsDeviceFromManagedDevice(config.ControlPortDevKey);
|
||||
if (dev != null && config.ControlPortNumber <= dev.NumberOfComPorts)
|
||||
return dev.ComPorts[config.ControlPortNumber];
|
||||
Debug.Console(0, "GetComPort: Device '{0}' does not have com port {1}", config.ControlPortDevKey, config.ControlPortNumber);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper to grab the IComPorts device for this PortDeviceKey. Key "controlSystem" will
|
||||
/// return the ControlSystem object from the Global class.
|
||||
/// </summary>
|
||||
/// <returns>IComPorts device or null if the device is not found or does not implement IComPorts</returns>
|
||||
public static IComPorts GetIComPortsDeviceFromManagedDevice(string ComPortDevKey)
|
||||
{
|
||||
if ((ComPortDevKey.Equals("controlSystem", System.StringComparison.OrdinalIgnoreCase)
|
||||
|| ComPortDevKey.Equals("processor", System.StringComparison.OrdinalIgnoreCase))
|
||||
&& Global.ControlSystem is IComPorts)
|
||||
return Global.ControlSystem;
|
||||
else
|
||||
{
|
||||
var dev = DeviceManager.GetDeviceForKey(ComPortDevKey) as IComPorts;
|
||||
if (dev == null)
|
||||
Debug.Console(0, "ComPortConfig: Cannot find com port device '{0}'", ComPortDevKey);
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class EssentialsControlPropertiesConfig :
|
||||
PepperDash.Core.ControlPropertiesConfig
|
||||
{
|
||||
// ****** All of these things, except for #Pro-specific com stuff, were
|
||||
// moved into PepperDash.Core to help non-pro PortalSync.
|
||||
|
||||
//public eControlMethod Method { get; set; }
|
||||
|
||||
//public string ControlPortDevKey { get; set; }
|
||||
|
||||
//[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] // In case "null" is present in config on this value
|
||||
//public uint ControlPortNumber { get; set; }
|
||||
|
||||
//public TcpSshPropertiesConfig TcpSshProperties { get; set; }
|
||||
|
||||
//public string IrFile { get; set; }
|
||||
|
||||
//public ComPortConfig ComParams { get; set; }
|
||||
|
||||
[JsonConverter(typeof(ComSpecJsonConverter))]
|
||||
public ComPort.ComPortSpec ComParams { get; set; }
|
||||
|
||||
public string CresnetId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to provide uint conversion of string CresnetId
|
||||
/// </summary>
|
||||
public uint CresnetIdInt
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ToUInt32(CresnetId, 16);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new FormatException(string.Format("ERROR:Unable to convert Cresnet ID: {0} to hex. Error:\n{1}", CresnetId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//public string IpId { get; set; }
|
||||
|
||||
//[JsonIgnore]
|
||||
//public uint IpIdInt { get { return Convert.ToUInt32(IpId, 16); } }
|
||||
|
||||
//public char EndOfLineChar { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// Defaults to Environment.NewLine;
|
||||
///// </summary>
|
||||
//public string EndOfLineString { get; set; }
|
||||
|
||||
//public string DeviceReadyResponsePattern { get; set; }
|
||||
|
||||
//public EssentialsControlPropertiesConfig()
|
||||
//{
|
||||
// EndOfLineString = CrestronEnvironment.NewLine;
|
||||
//}
|
||||
}
|
||||
|
||||
public class IrControlSpec
|
||||
{
|
||||
public string PortDeviceKey { get; set; }
|
||||
public uint PortNumber { get; set; }
|
||||
public string File { get; set; }
|
||||
}
|
||||
|
||||
//public enum eControlMethod
|
||||
//{
|
||||
// None = 0, Com, IpId, IR, Ssh, Tcpip, Telnet
|
||||
//}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace PepperDash.Essentials.Core
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Format(@"\NVRAM\Program{0}\IR\", InitialParametersClass.ApplicationNumber);
|
||||
return Global.FilePathPrefix + "IR" + Global.DirectorySeparator;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,6 @@ namespace PepperDash.Essentials.Core.Config
|
||||
[JsonProperty("info")]
|
||||
public InfoConfig Info { get; set; }
|
||||
|
||||
//[JsonProperty("roomLists")]
|
||||
//public Dictionary<string, List<string>> RoomLists { get; set; }
|
||||
|
||||
[JsonProperty("devices")]
|
||||
public List<DeviceConfig> Devices { get; set; }
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
@@ -19,7 +21,10 @@ namespace PepperDash.Essentials.Core.Config
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("version")]
|
||||
public string Version { get; set; }
|
||||
public string Version { get; set; }
|
||||
|
||||
[JsonProperty("runtimeInfo")]
|
||||
public RuntimeInfo RuntimeInfo { get; set; }
|
||||
|
||||
[JsonProperty("comment")]
|
||||
public string Comment { get; set; }
|
||||
@@ -30,7 +35,34 @@ namespace PepperDash.Essentials.Core.Config
|
||||
Date = DateTime.Now;
|
||||
Type = "";
|
||||
Version = "";
|
||||
Comment = "";
|
||||
Comment = "";
|
||||
|
||||
RuntimeInfo = new RuntimeInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents runtime information about the program/processor
|
||||
/// </summary>
|
||||
public class RuntimeInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the running application
|
||||
/// </summary>
|
||||
[JsonProperty("appName")]
|
||||
public string AppName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Assembly version of the running application
|
||||
/// </summary>
|
||||
[JsonProperty("assemblyVersion")]
|
||||
public string AssemblyVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The OS Version of the processor (Firmware Version)
|
||||
/// </summary>
|
||||
[JsonProperty("osVersion")]
|
||||
public string OsVersion { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Config
|
||||
{
|
||||
public class SourceDevicePropertiesConfigBase
|
||||
{
|
||||
public bool DisableSharing { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Core.CrestronIO
|
||||
{
|
||||
public class IOPortConfig
|
||||
{
|
||||
public string PortDeviceKey { get; set; }
|
||||
public uint PortNumber { get; set; }
|
||||
public bool DisablePullUpResistor { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
namespace PepperDash.Essentials.Core.CrestronIO
|
||||
{
|
||||
public class GenericDigitalInputDevice : Device, IDigitalInput
|
||||
{
|
||||
public DigitalInput InputPort { get; private set; }
|
||||
|
||||
public BoolFeedback InputStateFeedback { get; private set; }
|
||||
|
||||
Func<bool> InputStateFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () => InputPort.State;
|
||||
}
|
||||
}
|
||||
|
||||
public GenericDigitalInputDevice(string key, DigitalInput inputPort):
|
||||
base(key)
|
||||
{
|
||||
InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc);
|
||||
|
||||
InputPort = inputPort;
|
||||
|
||||
InputPort.StateChange += new DigitalInputEventHandler(InputPort_StateChange);
|
||||
|
||||
}
|
||||
|
||||
void InputPort_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args)
|
||||
{
|
||||
InputStateFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -5,39 +5,46 @@ using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Crestron_IO
|
||||
namespace PepperDash.Essentials.Core.CrestronIO
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a generic digital input deviced tied to a versiport
|
||||
/// </summary>
|
||||
public class GenericVersiportInputDevice
|
||||
public class GenericVersiportDigitalInputDevice : Device, IDigitalInput
|
||||
{
|
||||
//Versiport InputPort {get; private set;}
|
||||
public Versiport InputPort { get; private set; }
|
||||
|
||||
//BoolFeedback InputStateFeedback {get; private set;}
|
||||
public BoolFeedback InputStateFeedback { get; private set; }
|
||||
|
||||
//Func<bool> InputStateFeedbackFunc
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// return () => InputPort.DigitalIn;
|
||||
// }
|
||||
//}
|
||||
Func<bool> InputStateFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () => InputPort.DigitalIn;
|
||||
}
|
||||
}
|
||||
|
||||
//public GenericVersiportInputDevice(Versiport inputPort)
|
||||
//{
|
||||
// InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc);
|
||||
public GenericVersiportDigitalInputDevice(string key, Versiport inputPort, IOPortConfig props):
|
||||
base(key)
|
||||
{
|
||||
InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc);
|
||||
InputPort = inputPort;
|
||||
InputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput);
|
||||
if (props.DisablePullUpResistor)
|
||||
InputPort.DisablePullUpResistor = true;
|
||||
InputPort.VersiportChange += new VersiportEventHandler(InputPort_VersiportChange);
|
||||
|
||||
// InputPort = inputPort;
|
||||
Debug.Console(1, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", props.PortNumber, InputPort.DisablePullUpResistor);
|
||||
}
|
||||
|
||||
// InputPort.VersiportChange += new VersiportEventHandler(InputPort_VersiportChange);
|
||||
void InputPort_VersiportChange(Versiport port, VersiportEventArgs args)
|
||||
{
|
||||
Debug.Console(1, this, "Versiport change: {0}", args.Event);
|
||||
|
||||
//}
|
||||
|
||||
//void InputPort_VersiportChange(Versiport port, VersiportEventArgs args)
|
||||
//{
|
||||
// InputStateFeedback.FireUpdate();
|
||||
//}
|
||||
if(args.Event == eVersiportEvent.DigitalInChange)
|
||||
InputStateFeedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,13 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Crestron_IO
|
||||
namespace PepperDash.Essentials.Core.CrestronIO
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a device that provides digital input
|
||||
/// </summary>
|
||||
public interface IDigitalInput
|
||||
{
|
||||
|
||||
BoolFeedback InputStateFeedback { get; }
|
||||
}
|
||||
}
|
||||
@@ -3,41 +3,67 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using Crestron.SimplSharpPro;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Crestron_IO
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Core.CrestronIO
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a generic device controlled by relays
|
||||
/// </summary>
|
||||
public class GenericRelayDevice
|
||||
public class GenericRelayDevice : Device, ISwitchedOutput
|
||||
{
|
||||
//Relay RelayOutput { get; private set; }
|
||||
public Relay RelayOutput { get; private set; }
|
||||
|
||||
//public boolfeedback relaystatefeedback { get; private set; }
|
||||
public BoolFeedback OutputIsOnFeedback { get; private set; }
|
||||
|
||||
//func<bool> relaystatefeedbackfunc
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// return () => relayoutput.state;
|
||||
// }
|
||||
//}
|
||||
public GenericRelayDevice(string key, Relay relay):
|
||||
base(key)
|
||||
{
|
||||
OutputIsOnFeedback = new BoolFeedback(new Func<bool>(() => RelayOutput.State));
|
||||
|
||||
//public genericrelaydevice(relay relay)
|
||||
//{
|
||||
// relaystatefeedback = new boolfeedback(relaystatefeedbackfunc);
|
||||
if (relay.AvailableForUse)
|
||||
RelayOutput = relay;
|
||||
|
||||
// if(relay.availableforuse)
|
||||
// relayoutput = relay;
|
||||
RelayOutput.StateChange += new RelayEventHandler(RelayOutput_StateChange);
|
||||
}
|
||||
|
||||
// relayoutput.statechange += new relayeventhandler(relayoutput_statechange);
|
||||
//}
|
||||
void RelayOutput_StateChange(Relay relay, RelayEventArgs args)
|
||||
{
|
||||
OutputIsOnFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
//void relayoutput_statechange(relay relay, relayeventargs args)
|
||||
//{
|
||||
// relaystatefeedback.fireupdate();
|
||||
//}
|
||||
public void OpenRelay()
|
||||
{
|
||||
RelayOutput.State = false;
|
||||
}
|
||||
|
||||
public void CloseRelay()
|
||||
{
|
||||
RelayOutput.State = true;
|
||||
}
|
||||
|
||||
public void ToggleRelayState()
|
||||
{
|
||||
if (RelayOutput.State == true)
|
||||
OpenRelay();
|
||||
else
|
||||
CloseRelay();
|
||||
}
|
||||
|
||||
#region ISwitchedOutput Members
|
||||
|
||||
void ISwitchedOutput.On()
|
||||
{
|
||||
CloseRelay();
|
||||
}
|
||||
|
||||
void ISwitchedOutput.Off()
|
||||
{
|
||||
OpenRelay();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Core.CrestronIO
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes an output capable of switching on and off
|
||||
/// </summary>
|
||||
public interface ISwitchedOutput
|
||||
{
|
||||
BoolFeedback OutputIsOnFeedback {get;}
|
||||
|
||||
void On();
|
||||
void Off();
|
||||
}
|
||||
|
||||
public interface ISwitchedOutputCollection
|
||||
{
|
||||
Dictionary<uint, ISwitchedOutput> SwitchedOutputs { get; }
|
||||
}
|
||||
}
|
||||
@@ -38,16 +38,16 @@ namespace PepperDash.Essentials.Core
|
||||
/// </summary>
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
new CTimer(o =>
|
||||
Debug.Console(0, this, "Activating");
|
||||
var response = Hardware.RegisterWithLogging(Key);
|
||||
if (response != eDeviceRegistrationUnRegistrationResponse.Success)
|
||||
{
|
||||
Debug.Console(1, this, "Activating");
|
||||
var response = Hardware.RegisterWithLogging(Key);
|
||||
if (response == eDeviceRegistrationUnRegistrationResponse.Success)
|
||||
{
|
||||
Hardware.OnlineStatusChange += new OnlineStatusChangeEventHandler(Hardware_OnlineStatusChange);
|
||||
CommunicationMonitor.Start();
|
||||
}
|
||||
}, 0);
|
||||
Debug.Console(0, this, "ERROR: Cannot register Crestron device: {0}", response);
|
||||
return false;
|
||||
}
|
||||
Hardware.OnlineStatusChange += new OnlineStatusChangeEventHandler(Hardware_OnlineStatusChange);
|
||||
CommunicationMonitor.Start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// A bridge class to cover the basic features of GenericBase hardware
|
||||
/// </summary>
|
||||
public class CrestronGenericBaseDevice : Device, IOnline, IHasFeedback, ICommunicationMonitor, IUsageTracking
|
||||
{
|
||||
public virtual GenericBase Hardware { get; protected set; }
|
||||
|
||||
public BoolFeedback IsOnline { get; private set; }
|
||||
public BoolFeedback IsRegistered { get; private set; }
|
||||
public StringFeedback IpConnectionsText { get; private set; }
|
||||
|
||||
public CrestronGenericBaseDevice(string key, string name, GenericBase hardware)
|
||||
: base(key, name)
|
||||
{
|
||||
Hardware = hardware;
|
||||
IsOnline = new BoolFeedback(CommonBoolCue.IsOnlineFeedback, () => Hardware.IsOnline);
|
||||
IsRegistered = new BoolFeedback(new Cue("IsRegistered", 0, eCueType.Bool), () => Hardware.Registered);
|
||||
IpConnectionsText = new StringFeedback(CommonStringCue.IpConnectionsText, () =>
|
||||
string.Join(",", Hardware.ConnectedIpList.Select(cip => cip.DeviceIpAddress).ToArray()));
|
||||
CommunicationMonitor = new CrestronGenericBaseCommunicationMonitor(this, hardware, 120000, 300000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure that overriding classes call this!
|
||||
/// Registers the Crestron device, connects up to the base events, starts communication monitor
|
||||
/// </summary>
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
Debug.Console(0, this, "Activating");
|
||||
var response = Hardware.RegisterWithLogging(Key);
|
||||
if (response != eDeviceRegistrationUnRegistrationResponse.Success)
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
Debug.Console(0, this, "ERROR: Cannot register Crestron device: {0}", response);
|
||||
return false;
|
||||
}
|
||||
=======
|
||||
Debug.Console(0, this, "ERROR: Cannot register Crestron device: {0}", response);
|
||||
return false;
|
||||
}
|
||||
>>>>>>> origin/feature/ecs-342-neil
|
||||
Hardware.OnlineStatusChange += new OnlineStatusChangeEventHandler(Hardware_OnlineStatusChange);
|
||||
CommunicationMonitor.Start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This disconnects events and unregisters the base hardware device.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override bool Deactivate()
|
||||
{
|
||||
CommunicationMonitor.Stop();
|
||||
Hardware.OnlineStatusChange -= Hardware_OnlineStatusChange;
|
||||
|
||||
return Hardware.UnRegister() == eDeviceRegistrationUnRegistrationResponse.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list containing the Outputs that we want to expose.
|
||||
/// </summary>
|
||||
public virtual List<Feedback> Feedbacks
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<Feedback>
|
||||
{
|
||||
IsOnline,
|
||||
IsRegistered,
|
||||
IpConnectionsText
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void Hardware_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
|
||||
{
|
||||
IsOnline.FireUpdate();
|
||||
}
|
||||
|
||||
#region IStatusMonitor Members
|
||||
|
||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region IUsageTracking Members
|
||||
|
||||
public UsageTracking UsageTracker { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
//***********************************************************************************
|
||||
public class CrestronGenericBaseDeviceEventIds
|
||||
{
|
||||
public const uint IsOnline = 1;
|
||||
public const uint IpConnectionsText =2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds logging to Register() failure
|
||||
/// </summary>
|
||||
public static class GenericBaseExtensions
|
||||
{
|
||||
public static eDeviceRegistrationUnRegistrationResponse RegisterWithLogging(this GenericBase device, string key)
|
||||
{
|
||||
var result = device.Register();
|
||||
if (result != eDeviceRegistrationUnRegistrationResponse.Success)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Error, "Cannot register device '{0}': {1}", key, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -56,8 +56,6 @@ namespace PepperDash.Essentials.Core
|
||||
System.Globalization.CultureInfo.InvariantCulture))
|
||||
.ToArray();
|
||||
object ret = method.Invoke(obj, convertedParams);
|
||||
//Debug.Console(0, JsonConvert.SerializeObject(ret));
|
||||
// return something?
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -29,10 +29,6 @@ namespace PepperDash.Essentials.Core
|
||||
|
||||
public static void Initialize(CrestronControlSystem cs)
|
||||
{
|
||||
//CrestronConsole.AddNewConsoleCommand(ListDeviceCommands, "devcmdlist", "Lists commands",
|
||||
// ConsoleAccessLevelEnum.AccessOperator);
|
||||
//CrestronConsole.AddNewConsoleCommand(DoDeviceCommand, "devcmd", "Runs a command on device - key Name value",
|
||||
// ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(ListDeviceCommStatuses, "devcommstatus", "Lists the communication status of all devices",
|
||||
ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(ListDeviceFeedbacks, "devfb", "Lists current feedbacks",
|
||||
@@ -64,8 +60,15 @@ namespace PepperDash.Essentials.Core
|
||||
{
|
||||
foreach (var d in Devices.Values)
|
||||
{
|
||||
if (d is Device)
|
||||
(d as Device).Activate();
|
||||
try
|
||||
{
|
||||
if (d is Device)
|
||||
(d as Device).Activate();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, d, "ERROR: Device activation failure:\r{0}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
using Crestron.SimplSharpPro.EthernetCommunication;
|
||||
using Crestron.SimplSharpPro.UI;
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
public static class DeviceManager
|
||||
{
|
||||
//public static List<Device> Devices { get { return _Devices; } }
|
||||
//static List<Device> _Devices = new List<Device>();
|
||||
|
||||
static Dictionary<string, IKeyed> Devices = new Dictionary<string, IKeyed>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of all the devices in a list
|
||||
/// </summary>
|
||||
public static List<IKeyed> AllDevices { get { return new List<IKeyed>(Devices.Values); } }
|
||||
|
||||
public static void Initialize(CrestronControlSystem cs)
|
||||
{
|
||||
CrestronConsole.AddNewConsoleCommand(ListDeviceCommStatuses, "devcommstatus", "Lists the communication status of all devices",
|
||||
ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(ListDeviceFeedbacks, "devfb", "Lists current feedbacks",
|
||||
ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(ListDevices, "devlist", "Lists current managed devices",
|
||||
ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(DeviceJsonApi.DoDeviceActionWithJson, "devjson", "",
|
||||
ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s =>
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetProperties(s));
|
||||
}, "devprops", "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s =>
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetMethods(s));
|
||||
}, "devmethods", "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s =>
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s));
|
||||
}, "apimethods", "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(SimulateComReceiveOnDevice, "devsimreceive",
|
||||
"Simulates incoming data on a com device", ConsoleAccessLevelEnum.AccessOperator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls activate on all Device class items
|
||||
/// </summary>
|
||||
public static void ActivateAll()
|
||||
{
|
||||
foreach (var d in Devices.Values)
|
||||
<<<<<<< HEAD
|
||||
{
|
||||
try
|
||||
{
|
||||
if (d is Device)
|
||||
(d as Device).Activate();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, d, "ERROR: Device activation failure:\r{0}", e);
|
||||
}
|
||||
}
|
||||
=======
|
||||
{
|
||||
try
|
||||
{
|
||||
if (d is Device)
|
||||
(d as Device).Activate();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, d, "ERROR: Device activation failure:\r{0}", e);
|
||||
}
|
||||
}
|
||||
>>>>>>> origin/feature/ecs-342-neil
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls activate on all Device class items
|
||||
/// </summary>
|
||||
public static void DeactivateAll()
|
||||
{
|
||||
foreach (var d in Devices.Values)
|
||||
{
|
||||
if (d is Device)
|
||||
(d as Device).Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
//static void ListMethods(string devKey)
|
||||
//{
|
||||
// var dev = GetDeviceForKey(devKey);
|
||||
// if(dev != null)
|
||||
// {
|
||||
// var type = dev.GetType().GetCType();
|
||||
// var methods = type.GetMethods(BindingFlags.Public|BindingFlags.Instance);
|
||||
// var sb = new StringBuilder();
|
||||
// sb.AppendLine(string.Format("{2} methods on [{0}] ({1}):", dev.Key, type.Name, methods.Length));
|
||||
// foreach (var m in methods)
|
||||
// {
|
||||
// sb.Append(string.Format("{0}(", m.Name));
|
||||
// var pars = m.GetParameters();
|
||||
// foreach (var p in pars)
|
||||
// sb.Append(string.Format("({1}){0} ", p.Name, p.ParameterType.Name));
|
||||
// sb.AppendLine(")");
|
||||
// }
|
||||
// CrestronConsole.ConsoleCommandResponse(sb.ToString());
|
||||
// }
|
||||
//}
|
||||
|
||||
static void ListDevices(string s)
|
||||
{
|
||||
Debug.Console(0, "{0} Devices registered with Device Mangager:",Devices.Count);
|
||||
var sorted = Devices.Values.ToList();
|
||||
sorted.Sort((a, b) => a.Key.CompareTo(b.Key));
|
||||
|
||||
foreach (var d in sorted)
|
||||
{
|
||||
var name = d is IKeyName ? (d as IKeyName).Name : "---";
|
||||
Debug.Console(0, " [{0}] {1}", d.Key, name);
|
||||
}
|
||||
}
|
||||
|
||||
static void ListDeviceFeedbacks(string devKey)
|
||||
{
|
||||
var dev = GetDeviceForKey(devKey);
|
||||
if(dev == null)
|
||||
{
|
||||
Debug.Console(0, "Device '{0}' not found", devKey);
|
||||
return;
|
||||
}
|
||||
var statusDev = dev as IHasFeedback;
|
||||
if(statusDev == null)
|
||||
{
|
||||
Debug.Console(0, "Device '{0}' does not have visible feedbacks", devKey);
|
||||
return;
|
||||
}
|
||||
statusDev.DumpFeedbacksToConsole(true);
|
||||
}
|
||||
|
||||
//static void ListDeviceCommands(string devKey)
|
||||
//{
|
||||
// var dev = GetDeviceForKey(devKey);
|
||||
// if (dev == null)
|
||||
// {
|
||||
// Debug.Console(0, "Device '{0}' not found", devKey);
|
||||
// return;
|
||||
// }
|
||||
// Debug.Console(0, "This needs to be reworked. Stay tuned.", devKey);
|
||||
//}
|
||||
|
||||
static void ListDeviceCommStatuses(string input)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
foreach (var dev in Devices.Values)
|
||||
{
|
||||
if (dev is ICommunicationMonitor)
|
||||
sb.Append(string.Format("{0}: {1}\r", dev.Key, (dev as ICommunicationMonitor).CommunicationMonitor.Status));
|
||||
}
|
||||
CrestronConsole.ConsoleCommandResponse(sb.ToString());
|
||||
}
|
||||
|
||||
|
||||
//static void DoDeviceCommand(string command)
|
||||
//{
|
||||
// Debug.Console(0, "Not yet implemented. Stay tuned");
|
||||
//}
|
||||
|
||||
public static void AddDevice(IKeyed newDev)
|
||||
{
|
||||
// Check for device with same key
|
||||
//var existingDevice = _Devices.FirstOrDefault(d => d.Key.Equals(newDev.Key, StringComparison.OrdinalIgnoreCase));
|
||||
////// If it exists, remove or warn??
|
||||
//if (existingDevice != null)
|
||||
if(Devices.ContainsKey(newDev.Key))
|
||||
{
|
||||
Debug.Console(0, newDev, "WARNING: A device with this key already exists. Not added to manager");
|
||||
return;
|
||||
}
|
||||
Devices.Add(newDev.Key, newDev);
|
||||
//if (!(_Devices.Contains(newDev)))
|
||||
// _Devices.Add(newDev);
|
||||
}
|
||||
|
||||
public static void RemoveDevice(IKeyed newDev)
|
||||
{
|
||||
if(newDev == null)
|
||||
return;
|
||||
if (Devices.ContainsKey(newDev.Key))
|
||||
Devices.Remove(newDev.Key);
|
||||
//if (_Devices.Contains(newDev))
|
||||
// _Devices.Remove(newDev);
|
||||
else
|
||||
Debug.Console(0, "Device manager: Device '{0}' does not exist in manager. Cannot remove", newDev.Key);
|
||||
}
|
||||
|
||||
public static IEnumerable<string> GetDeviceKeys()
|
||||
{
|
||||
//return _Devices.Select(d => d.Key).ToList();
|
||||
return Devices.Keys;
|
||||
}
|
||||
|
||||
public static IEnumerable<IKeyed> GetDevices()
|
||||
{
|
||||
//return _Devices.Select(d => d.Key).ToList();
|
||||
return Devices.Values;
|
||||
}
|
||||
|
||||
public static IKeyed GetDeviceForKey(string key)
|
||||
{
|
||||
//return _Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
|
||||
if (key != null && Devices.ContainsKey(key))
|
||||
return Devices[key];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Console handler that simulates com port data receive
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
public static void SimulateComReceiveOnDevice(string s)
|
||||
{
|
||||
// devcomsim:1 xyzabc
|
||||
var match = Regex.Match(s, @"(\S*)\s*(.*)");
|
||||
if (match.Groups.Count < 3)
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse(" Format: devsimreceive:P <device key> <string to send>");
|
||||
return;
|
||||
}
|
||||
//Debug.Console(2, "**** {0} - {1} ****", match.Groups[1].Value, match.Groups[2].Value);
|
||||
|
||||
ComPortController com = GetDeviceForKey(match.Groups[1].Value) as ComPortController;
|
||||
if (com == null)
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("'{0}' is not a comm port device", match.Groups[1].Value);
|
||||
return;
|
||||
}
|
||||
com.SimulateReceive(match.Groups[2].Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,15 @@ namespace PepperDash.Essentials.Core
|
||||
BoolFeedback MuteFeedback { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A class that implements this contains a reference to a current IBasicVolumeControls device.
|
||||
/// The class may have multiple IBasicVolumeControls.
|
||||
/// </summary>
|
||||
public interface IHasCurrentVolumeControls
|
||||
{
|
||||
IBasicVolumeControls CurrentVolumeControls { get; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace PepperDash.Essentials.Core
|
||||
/// </summary>
|
||||
public class SourceListItem
|
||||
{
|
||||
[JsonProperty("sourceKey")]
|
||||
public string SourceKey { get; set; }
|
||||
/// <summary>
|
||||
/// Returns the source Device for this, if it exists in DeviceManager
|
||||
@@ -43,6 +44,7 @@ namespace PepperDash.Essentials.Core
|
||||
/// Gets either the source's Name or this AlternateName property, if
|
||||
/// defined. If source doesn't exist, returns "Missing source"
|
||||
/// </summary>
|
||||
[JsonProperty("preferredName")]
|
||||
public string PreferredName
|
||||
{
|
||||
get
|
||||
@@ -60,15 +62,36 @@ namespace PepperDash.Essentials.Core
|
||||
/// <summary>
|
||||
/// A name that will override the source's name on the UI
|
||||
/// </summary>
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("icon")]
|
||||
public string Icon { get; set; }
|
||||
|
||||
[JsonProperty("altIcon")]
|
||||
public string AltIcon { get; set; }
|
||||
|
||||
[JsonProperty("includeInSourceList")]
|
||||
public bool IncludeInSourceList { get; set; }
|
||||
public int Order { get; set; }
|
||||
|
||||
[JsonProperty("order")]
|
||||
public int Order { get; set; }
|
||||
|
||||
[JsonProperty("volumeControlKey")]
|
||||
public string VolumeControlKey { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public eSourceListItemType Type { get; set; }
|
||||
|
||||
[JsonProperty("routeList")]
|
||||
public List<SourceRouteListItem> RouteList { get; set; }
|
||||
|
||||
[JsonProperty("disableCodecSharing")]
|
||||
public bool DisableCodecSharing { get; set; }
|
||||
|
||||
[JsonProperty("disableRoutedSharing")]
|
||||
public bool DisableRoutedSharing { get; set; }
|
||||
|
||||
public SourceListItem()
|
||||
{
|
||||
Icon = "Blank";
|
||||
|
||||
@@ -64,14 +64,14 @@ namespace PepperDash.Essentials.Core
|
||||
if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
|
||||
{
|
||||
_IsWarmingUp = true;
|
||||
IsWarmingUpFeedback.FireUpdate();
|
||||
IsWarmingUpFeedback.InvokeFireUpdate();
|
||||
// Fake power-up cycle
|
||||
WarmupTimer = new CTimer(o =>
|
||||
{
|
||||
_IsWarmingUp = false;
|
||||
_PowerIsOn = true;
|
||||
IsWarmingUpFeedback.FireUpdate();
|
||||
PowerIsOnFeedback.FireUpdate();
|
||||
IsWarmingUpFeedback.InvokeFireUpdate();
|
||||
PowerIsOnFeedback.InvokeFireUpdate();
|
||||
}, WarmupTime);
|
||||
}
|
||||
}
|
||||
@@ -84,14 +84,14 @@ namespace PepperDash.Essentials.Core
|
||||
{
|
||||
_IsCoolingDown = true;
|
||||
_PowerIsOn = false;
|
||||
PowerIsOnFeedback.FireUpdate();
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
PowerIsOnFeedback.InvokeFireUpdate();
|
||||
IsCoolingDownFeedback.InvokeFireUpdate();
|
||||
// Fake cool-down cycle
|
||||
CooldownTimer = new CTimer(o =>
|
||||
{
|
||||
Debug.Console(2, this, "Cooldown timer ending");
|
||||
_IsCoolingDown = false;
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
IsCoolingDownFeedback.InvokeFireUpdate();
|
||||
}, CooldownTime);
|
||||
}
|
||||
}
|
||||
@@ -117,20 +117,20 @@ namespace PepperDash.Essentials.Core
|
||||
|
||||
public void SetVolume(ushort level)
|
||||
{
|
||||
_FakeVolumeLevel = level;
|
||||
VolumeLevelFeedback.FireUpdate();
|
||||
_FakeVolumeLevel = level;
|
||||
VolumeLevelFeedback.InvokeFireUpdate();
|
||||
}
|
||||
|
||||
public void MuteOn()
|
||||
{
|
||||
_IsMuted = true;
|
||||
MuteFeedback.FireUpdate();
|
||||
MuteFeedback.InvokeFireUpdate();
|
||||
}
|
||||
|
||||
public void MuteOff()
|
||||
{
|
||||
_IsMuted = false;
|
||||
MuteFeedback.FireUpdate();
|
||||
MuteFeedback.InvokeFireUpdate();
|
||||
}
|
||||
|
||||
public BoolFeedback MuteFeedback { get; private set; }
|
||||
@@ -170,7 +170,7 @@ namespace PepperDash.Essentials.Core
|
||||
public void MuteToggle()
|
||||
{
|
||||
_IsMuted = !_IsMuted;
|
||||
MuteFeedback.FireUpdate();
|
||||
MuteFeedback.InvokeFireUpdate();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -19,6 +19,16 @@ namespace PepperDash.Essentials.Core
|
||||
|
||||
public abstract eCueType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Feedbacks can be put into test mode for simulation of events without real data.
|
||||
/// Using JSON debugging methods and the Set/ClearTestValue methods, we can simulate
|
||||
/// Feedback behaviors
|
||||
/// </summary>
|
||||
public bool InTestMode { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Base Constructor - empty
|
||||
/// </summary>
|
||||
protected Feedback()
|
||||
{
|
||||
}
|
||||
@@ -28,8 +38,31 @@ namespace PepperDash.Essentials.Core
|
||||
Cue = cue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears test mode and fires update.
|
||||
/// </summary>
|
||||
public void ClearTestValue()
|
||||
{
|
||||
InTestMode = false;
|
||||
FireUpdate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires an update synchronously
|
||||
/// </summary>
|
||||
public abstract void FireUpdate();
|
||||
|
||||
/// <summary>
|
||||
/// Fires the update asynchronously within a CrestronInvoke
|
||||
/// </summary>
|
||||
public void InvokeFireUpdate()
|
||||
{
|
||||
CrestronInvoke.BeginInvoke(o => FireUpdate());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method that fires event. Use this intstead of calling OutputChange
|
||||
/// </summary>
|
||||
protected void OnOutputChange()
|
||||
{
|
||||
if (OutputChange != null) OutputChange(this, EventArgs.Empty);
|
||||
@@ -42,18 +75,24 @@ namespace PepperDash.Essentials.Core
|
||||
public class BoolFeedback : Feedback
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the current value of the feedback, derived from the ValueFunc
|
||||
/// Returns the current value of the feedback, derived from the ValueFunc. The ValueFunc is
|
||||
/// evaluated whenever FireUpdate() is called
|
||||
/// </summary>
|
||||
public override bool BoolValue { get { return _BoolValue; } }
|
||||
bool _BoolValue;
|
||||
|
||||
public override eCueType Type { get { return eCueType.Bool; } }
|
||||
|
||||
/// <summary>
|
||||
/// Fake value to be used in test mode
|
||||
/// </summary>
|
||||
public bool TestValue { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Func that evaluates on FireUpdate
|
||||
/// </summary>
|
||||
public Func<bool> ValueFunc { get; private set; }
|
||||
/// <summary>
|
||||
/// The last value delivered on FireUpdate
|
||||
/// </summary>
|
||||
//public bool PreviousValue { get; private set; }
|
||||
|
||||
List<BoolInputSig> LinkedInputSigs = new List<BoolInputSig>();
|
||||
List<BoolInputSig> LinkedComplementInputSigs = new List<BoolInputSig>();
|
||||
|
||||
@@ -71,7 +110,7 @@ namespace PepperDash.Essentials.Core
|
||||
|
||||
public override void FireUpdate()
|
||||
{
|
||||
var newValue = ValueFunc.Invoke();
|
||||
bool newValue = InTestMode ? TestValue : ValueFunc.Invoke();
|
||||
if (newValue != _BoolValue)
|
||||
{
|
||||
_BoolValue = newValue;
|
||||
@@ -105,9 +144,20 @@ namespace PepperDash.Essentials.Core
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return BoolValue.ToString();
|
||||
return (InTestMode ? "TEST -- " : "") + BoolValue.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Puts this in test mode, sets the test value and fires an update.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void SetTestValue(bool value)
|
||||
{
|
||||
TestValue = value;
|
||||
InTestMode = true;
|
||||
FireUpdate();
|
||||
}
|
||||
|
||||
void UpdateSig(BoolInputSig sig)
|
||||
{
|
||||
sig.BoolValue = _BoolValue;
|
||||
@@ -125,9 +175,14 @@ namespace PepperDash.Essentials.Core
|
||||
public override int IntValue { get { return _IntValue; } } // ValueFunc.Invoke(); } }
|
||||
int _IntValue;
|
||||
public ushort UShortValue { get { return (ushort)_IntValue; } }
|
||||
public override eCueType Type { get { return eCueType.Int; } }
|
||||
//public int PreviousValue { get; private set; }
|
||||
|
||||
public override eCueType Type { get { return eCueType.Int; } }
|
||||
|
||||
public int TestValue { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Func evaluated on FireUpdate
|
||||
/// </summary>
|
||||
Func<int> ValueFunc;
|
||||
List<UShortInputSig> LinkedInputSigs = new List<UShortInputSig>();
|
||||
|
||||
@@ -145,7 +200,7 @@ namespace PepperDash.Essentials.Core
|
||||
|
||||
public override void FireUpdate()
|
||||
{
|
||||
var newValue = ValueFunc.Invoke();
|
||||
var newValue = InTestMode ? TestValue : ValueFunc.Invoke();
|
||||
if (newValue != _IntValue)
|
||||
{
|
||||
_IntValue = newValue;
|
||||
@@ -167,9 +222,20 @@ namespace PepperDash.Essentials.Core
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return IntValue.ToString();
|
||||
return (InTestMode ? "TEST -- " : "") + IntValue.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Puts this in test mode, sets the test value and fires an update.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void SetTestValue(int value)
|
||||
{
|
||||
TestValue = value;
|
||||
InTestMode = true;
|
||||
FireUpdate();
|
||||
}
|
||||
|
||||
void UpdateSig(UShortInputSig sig)
|
||||
{
|
||||
sig.UShortValue = UShortValue;
|
||||
@@ -182,8 +248,17 @@ namespace PepperDash.Essentials.Core
|
||||
{
|
||||
public override string StringValue { get { return _StringValue; } } // ValueFunc.Invoke(); } }
|
||||
string _StringValue;
|
||||
|
||||
public override eCueType Type { get { return eCueType.String; } }
|
||||
//public string PreviousValue { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used in testing. Set/Clear functions
|
||||
/// </summary>
|
||||
public string TestValue { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Evalutated on FireUpdate
|
||||
/// </summary>
|
||||
public Func<string> ValueFunc { get; private set; }
|
||||
List<StringInputSig> LinkedInputSigs = new List<StringInputSig>();
|
||||
|
||||
@@ -202,7 +277,7 @@ namespace PepperDash.Essentials.Core
|
||||
|
||||
public override void FireUpdate()
|
||||
{
|
||||
var newValue = ValueFunc.Invoke();
|
||||
var newValue = InTestMode ? TestValue : ValueFunc.Invoke();
|
||||
if (newValue != _StringValue)
|
||||
{
|
||||
_StringValue = newValue;
|
||||
@@ -224,9 +299,20 @@ namespace PepperDash.Essentials.Core
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return StringValue;
|
||||
return (InTestMode ? "TEST -- " : "") + StringValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Puts this in test mode, sets the test value and fires an update.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void SetTestValue(string value)
|
||||
{
|
||||
TestValue = value;
|
||||
InTestMode = true;
|
||||
FireUpdate();
|
||||
}
|
||||
|
||||
void UpdateSig(StringInputSig sig)
|
||||
{
|
||||
sig.StringValue = _StringValue;
|
||||
|
||||
@@ -1,42 +1,49 @@
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronDataStore;
|
||||
using Crestron.SimplSharpPro;
|
||||
|
||||
//using PepperDash.Essentials.Core.Http;
|
||||
using PepperDash.Essentials.License;
|
||||
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
public static class Global
|
||||
{
|
||||
public static CrestronControlSystem ControlSystem { get; set; }
|
||||
|
||||
public static LicenseManager LicenseManager { get; set; }
|
||||
|
||||
//public static EssentialsHttpServer HttpConfigServer
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// if (_HttpConfigServer == null)
|
||||
// _HttpConfigServer = new EssentialsHttpServer();
|
||||
// return _HttpConfigServer;
|
||||
// }
|
||||
//}
|
||||
//static EssentialsHttpServer _HttpConfigServer;
|
||||
|
||||
|
||||
static Global()
|
||||
{
|
||||
// Fire up CrestronDataStoreStatic
|
||||
var err = CrestronDataStoreStatic.InitCrestronDataStore();
|
||||
if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
|
||||
{
|
||||
CrestronConsole.PrintLine("Error starting CrestronDataStoreStatic: {0}", err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronDataStore;
|
||||
using Crestron.SimplSharpPro;
|
||||
|
||||
//using PepperDash.Essentials.Core.Http;
|
||||
using PepperDash.Essentials.License;
|
||||
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
public static class Global
|
||||
{
|
||||
public static CrestronControlSystem ControlSystem { get; set; }
|
||||
|
||||
public static LicenseManager LicenseManager { get; set; }
|
||||
|
||||
public static string FilePathPrefix { get; private set; }
|
||||
|
||||
public static char DirectorySeparator
|
||||
{
|
||||
get
|
||||
{
|
||||
return System.IO.Path.DirectorySeparatorChar;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the file path prefix
|
||||
/// </summary>
|
||||
/// <param name="prefix"></param>
|
||||
public static void SetFilePathPrefix(string prefix)
|
||||
{
|
||||
FilePathPrefix = prefix;
|
||||
}
|
||||
|
||||
static Global()
|
||||
{
|
||||
// Fire up CrestronDataStoreStatic
|
||||
var err = CrestronDataStoreStatic.InitCrestronDataStore();
|
||||
if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
|
||||
{
|
||||
CrestronConsole.PrintLine("Error starting CrestronDataStoreStatic: {0}", err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,7 @@ namespace PepperDash.Essentials.Core
|
||||
|
||||
public enum eJobTimerCycleTypes
|
||||
{
|
||||
RunEveryDay,
|
||||
RunEveryHour,
|
||||
RunEveryHalfHour,
|
||||
RunEveryMinute
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Lighting
|
||||
{
|
||||
/// <summary>
|
||||
/// Requirements for a device that implements lighting scene control
|
||||
/// </summary>
|
||||
public interface ILightingScenes
|
||||
{
|
||||
event EventHandler<LightingSceneChangeEventArgs> LightingSceneChange;
|
||||
|
||||
List<LightingScene> LightingScenes { get; }
|
||||
|
||||
void SelectScene(LightingScene scene);
|
||||
|
||||
LightingScene CurrentLightingScene { get; }
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Requirements for a device that implements master raise/lower
|
||||
/// </summary>
|
||||
public interface ILightingMasterRaiseLower
|
||||
{
|
||||
void MasterRaise();
|
||||
void MasterLower();
|
||||
void MasterRaiseLowerStop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Requiremnts for controlling a lighting load
|
||||
/// </summary>
|
||||
public interface ILightingLoad
|
||||
{
|
||||
void SetLoadLevel(int level);
|
||||
void Raise();
|
||||
void Lower();
|
||||
|
||||
IntFeedback LoadLevelFeedback { get; }
|
||||
BoolFeedback LoadIsOnFeedback { get; }
|
||||
}
|
||||
|
||||
public class LightingSceneChangeEventArgs : EventArgs
|
||||
{
|
||||
public LightingScene CurrentLightingScene { get; private set; }
|
||||
|
||||
public LightingSceneChangeEventArgs(LightingScene scene)
|
||||
{
|
||||
CurrentLightingScene = scene;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Lighting
|
||||
{
|
||||
public abstract class LightingBase : Device, ILightingScenes
|
||||
{
|
||||
#region ILightingScenes Members
|
||||
|
||||
public event EventHandler<LightingSceneChangeEventArgs> LightingSceneChange;
|
||||
|
||||
public List<LightingScene> LightingScenes { get; protected set; }
|
||||
|
||||
public LightingScene CurrentLightingScene { get; protected set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public LightingBase(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
LightingScenes = new List<LightingScene>();
|
||||
|
||||
CurrentLightingScene = new LightingScene();
|
||||
}
|
||||
|
||||
public abstract void SelectScene(LightingScene scene);
|
||||
|
||||
public void SimulateSceneSelect(string sceneName)
|
||||
{
|
||||
Debug.Console(1, this, "Simulating selection of scene '{0}'", sceneName);
|
||||
|
||||
var scene = LightingScenes.FirstOrDefault(s => s.Name.Equals(sceneName));
|
||||
|
||||
if (scene != null)
|
||||
{
|
||||
CurrentLightingScene = scene;
|
||||
OnLightingSceneChange();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the IsActive property on each scene and fires the LightingSceneChange event
|
||||
/// </summary>
|
||||
protected void OnLightingSceneChange()
|
||||
{
|
||||
foreach (var scene in LightingScenes)
|
||||
{
|
||||
if (scene == CurrentLightingScene)
|
||||
scene.IsActive = true;
|
||||
else
|
||||
scene.IsActive = false;
|
||||
}
|
||||
|
||||
var handler = LightingSceneChange;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, new LightingSceneChangeEventArgs(CurrentLightingScene));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class LightingScene
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string ID { get; set; }
|
||||
bool _IsActive;
|
||||
public bool IsActive
|
||||
{
|
||||
get
|
||||
{
|
||||
return _IsActive;
|
||||
}
|
||||
set
|
||||
{
|
||||
_IsActive = value;
|
||||
IsActiveFeedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
public BoolFeedback IsActiveFeedback { get; set; }
|
||||
|
||||
public LightingScene()
|
||||
{
|
||||
IsActiveFeedback = new BoolFeedback(new Func<bool>(() => IsActive));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,7 @@
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="PepperDash_Core, Version=1.0.1.26313, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\PepperDash.Core\Pepperdash Core\Pepperdash Core\bin\PepperDash_Core.dll</HintPath>
|
||||
<HintPath>..\..\..\pepperdash-simplsharp-core\Pepperdash Core\CLZ Builds\PepperDash_Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SimplSharpCustomAttributesInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
@@ -103,11 +103,17 @@
|
||||
<Reference Include="System.Data" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Config\SourceDevicePropertiesConfigBase.cs" />
|
||||
<Compile Include="Crestron IO\Inputs\GenericDigitalInputDevice.cs" />
|
||||
<Compile Include="Crestron IO\Inputs\GenericVersiportInputDevice.cs" />
|
||||
<Compile Include="Crestron IO\Inputs\IDigitalInput.cs" />
|
||||
<Compile Include="Crestron IO\IOPortConfig.cs" />
|
||||
<Compile Include="Crestron IO\Relay\GenericRelayDevice.cs" />
|
||||
<Compile Include="Crestron IO\Relay\ISwitchedOutput.cs" />
|
||||
<Compile Include="Devices\CodecInterfaces.cs" />
|
||||
<Compile Include="Global\JobTimer.cs" />
|
||||
<Compile Include="Lighting\Lighting Interfaces.cs" />
|
||||
<Compile Include="Lighting\LightingBase.cs" />
|
||||
<Compile Include="Ramps and Increments\ActionIncrementer.cs" />
|
||||
<Compile Include="Comm and IR\CommFactory.cs" />
|
||||
<Compile Include="Comm and IR\CommunicationExtras.cs" />
|
||||
@@ -177,6 +183,9 @@
|
||||
<Compile Include="Feedbacks\BoolFeedbackPulseExtender.cs" />
|
||||
<Compile Include="Routing\RoutingPortNames.cs" />
|
||||
<Compile Include="Routing\TieLineConfig.cs" />
|
||||
<Compile Include="Shades\Shade Interfaces.cs" />
|
||||
<Compile Include="Shades\ShadeBase.cs" />
|
||||
<Compile Include="Shades\ShadeController.cs" />
|
||||
<Compile Include="SmartObjects\SmartObjectNumeric.cs" />
|
||||
<Compile Include="SmartObjects\SmartObjectDynamicList.cs" />
|
||||
<Compile Include="SmartObjects\SmartObjectDPad.cs" />
|
||||
|
||||
@@ -4,5 +4,4 @@
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("PepperDashEssentialsBase")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyVersion("1.0.0.*")]
|
||||
|
||||
[assembly: AssemblyVersion("1.0.3.*")]
|
||||
@@ -108,10 +108,18 @@ namespace PepperDash.Essentials.Core.Routing
|
||||
/// </summary>
|
||||
public const string HdmiIn1 = "hdmiIn1";
|
||||
/// <summary>
|
||||
/// hdmiIn1PC
|
||||
/// </summary>
|
||||
public const string HdmiIn1PC = "hdmiIn1PC";
|
||||
/// <summary>
|
||||
/// hdmiIn2
|
||||
/// </summary>
|
||||
public const string HdmiIn2 = "hdmiIn2";
|
||||
/// <summary>
|
||||
/// hdmiIn2PC
|
||||
/// </summary>
|
||||
public const string HdmiIn2PC = "hdmiIn2PC";
|
||||
/// <summary>
|
||||
/// hdmiIn3
|
||||
/// </summary>
|
||||
public const string HdmiIn3 = "hdmiIn3";
|
||||
@@ -176,8 +184,20 @@ namespace PepperDash.Essentials.Core.Routing
|
||||
/// </summary>
|
||||
public const string VgaIn = "vgaIn";
|
||||
/// <summary>
|
||||
/// vgaIn1
|
||||
/// </summary>
|
||||
public const string VgaIn1 = "vgaIn1";
|
||||
/// <summary>
|
||||
/// vgaOut
|
||||
/// </summary>
|
||||
public const string VgaOut = "vgaOut";
|
||||
/// <summary>
|
||||
/// IPC/OPS
|
||||
/// </summary>
|
||||
public const string IpcOps = "ipcOps";
|
||||
/// <summary>
|
||||
/// MediaPlayer
|
||||
/// </summary>
|
||||
public const string MediaPlayer = "mediaPlayer";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Shades
|
||||
{
|
||||
public interface IShades
|
||||
{
|
||||
List<ShadeBase> Shades { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Requirements for a device that implements basic Open/Close shade control
|
||||
/// </summary>
|
||||
public interface IShadesOpenClose
|
||||
{
|
||||
void Open();
|
||||
void Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Requirements for a device that implements basic Open/Close/Stop shade control (Uses 3 relays)
|
||||
/// </summary>
|
||||
public interface IShadesOpenCloseStop : IShadesOpenClose
|
||||
{
|
||||
void StopOrPreset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Requirements for a shade device that provides open/closed feedback
|
||||
/// </summary>
|
||||
public interface iShadesRaiseLowerFeedback
|
||||
{
|
||||
BoolFeedback ShadeIsOpenFeedback { get; }
|
||||
BoolFeedback ShadeIsClosedFeedback { get; }
|
||||
}
|
||||
|
||||
}
|
||||
31
Essentials Core/PepperDashEssentialsBase/Shades/ShadeBase.cs
Normal file
31
Essentials Core/PepperDashEssentialsBase/Shades/ShadeBase.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.CrestronIO;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Shades
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for a shade device
|
||||
/// </summary>
|
||||
public abstract class ShadeBase : Device, IShadesOpenClose
|
||||
{
|
||||
public ShadeBase(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#region iShadesOpenClose Members
|
||||
|
||||
public abstract void Open();
|
||||
public abstract void StopOrPreset();
|
||||
public abstract void Close();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Shades
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that contains the shades to be controlled in a room
|
||||
/// </summary>
|
||||
public class ShadeController : Device, IShades
|
||||
{
|
||||
ShadeControllerConfigProperties Config;
|
||||
|
||||
public List<ShadeBase> Shades { get; private set; }
|
||||
|
||||
public ShadeController(string key, string name, ShadeControllerConfigProperties config)
|
||||
: base(key, name)
|
||||
{
|
||||
Config = config;
|
||||
|
||||
Shades = new List<ShadeBase>();
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
foreach (var shadeConfig in Config.Shades)
|
||||
{
|
||||
var shade = DeviceManager.GetDeviceForKey(shadeConfig.Key) as ShadeBase;
|
||||
|
||||
if (shade != null)
|
||||
{
|
||||
AddShade(shade);
|
||||
}
|
||||
}
|
||||
return base.CustomActivate();
|
||||
}
|
||||
|
||||
void AddShade(ShadeBase shade)
|
||||
{
|
||||
Shades.Add(shade);
|
||||
}
|
||||
}
|
||||
|
||||
public class ShadeControllerConfigProperties
|
||||
{
|
||||
public List<ShadeConfig> Shades { get; set; }
|
||||
|
||||
|
||||
public class ShadeConfig
|
||||
{
|
||||
public string Key { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@ namespace PepperDash.Essentials.Core
|
||||
// Count the enable lines to see what max items is
|
||||
MaxDefinedItems = (ushort)SRL.BooleanInput
|
||||
.Where(s => s.Name.Contains("Enable")).Count();
|
||||
Debug.Console(0, "SRL {0} contains max {1} items", SRL.ID, MaxDefinedItems);
|
||||
Debug.Console(2, "SRL {0} contains max {1} items", SRL.ID, MaxDefinedItems);
|
||||
|
||||
SRL.SigChange -= new SmartObjectSigChangeEventHandler(SRL_SigChange);
|
||||
SRL.SigChange += new SmartObjectSigChangeEventHandler(SRL_SigChange);
|
||||
|
||||
@@ -144,23 +144,47 @@ namespace PepperDash.Essentials.Core
|
||||
sig.UserObject = a;
|
||||
return sig;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="tl"></param>
|
||||
/// <param name="sigNum"></param>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
public static UShortOutputSig SetUShortSigAction(this BasicTriList tl, uint sigNum, Action<ushort> a)
|
||||
{
|
||||
return tl.UShortOutput[sigNum].SetUShortSigAction(a);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sig"></param>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
public static StringOutputSig SetStringSigAction(this StringOutputSig sig, Action<string> a)
|
||||
{
|
||||
sig.UserObject = a;
|
||||
return sig;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="tl"></param>
|
||||
/// <param name="sigNum"></param>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
public static StringOutputSig SetStringSigAction(this BasicTriList tl, uint sigNum, Action<string> a)
|
||||
{
|
||||
return tl.SetStringSigAction(sigNum, a);
|
||||
return tl.StringOutput[sigNum].SetStringSigAction(a);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sig"></param>
|
||||
/// <returns></returns>
|
||||
public static Sig ClearSigAction(this Sig sig)
|
||||
{
|
||||
sig.UserObject = null;
|
||||
@@ -190,6 +214,27 @@ namespace PepperDash.Essentials.Core
|
||||
tl.BooleanInput[sigNum].BoolValue = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends an true-false pulse to the sig
|
||||
/// </summary>
|
||||
/// <param name="tl"></param>
|
||||
/// <param name="sigNum"></param>
|
||||
public static void PulseBool(this BasicTriList tl, uint sigNum)
|
||||
{
|
||||
tl.BooleanInput[sigNum].Pulse();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a timed pulse to the sig
|
||||
/// </summary>
|
||||
/// <param name="tl"></param>
|
||||
/// <param name="sigNum"></param>
|
||||
/// <param name="ms"></param>
|
||||
public static void PulseBool(this BasicTriList tl, uint sigNum, int ms)
|
||||
{
|
||||
tl.BooleanInput[sigNum].Pulse(ms);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to set the value of a ushort Sig on TriList
|
||||
/// </summary>
|
||||
|
||||
127
Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEController.cs
Normal file
127
Essentials DM/Essentials_DM/Chassis/HdMdNxM4kEController.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro.DM;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.DM.Config;
|
||||
|
||||
namespace PepperDash.Essentials.DM.Chassis
|
||||
{
|
||||
public class HdMdNxM4kEController : Device, IRoutingInputsOutputs, IRouting
|
||||
{
|
||||
public HdMdNxM Chassis { get; private set; }
|
||||
|
||||
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
|
||||
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="chassis"></param>
|
||||
public HdMdNxM4kEController(string key, string name, HdMdNxM chassis,
|
||||
HdMdNxM4kEPropertiesConfig props)
|
||||
: base(key, name)
|
||||
{
|
||||
Chassis = chassis;
|
||||
|
||||
// logical ports
|
||||
InputPorts = new RoutingPortCollection<RoutingInputPort>();
|
||||
for (uint i = 1; i <= 4; i++)
|
||||
{
|
||||
InputPorts.Add(new RoutingInputPort("hdmiIn" + i, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, i, this));
|
||||
}
|
||||
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
|
||||
OutputPorts.Add(new RoutingOutputPort(DmPortName.HdmiOut, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, null, this));
|
||||
|
||||
// physical settings
|
||||
if (props != null && props.Inputs != null)
|
||||
{
|
||||
foreach (var kvp in props.Inputs)
|
||||
{
|
||||
// strip "hdmiIn"
|
||||
var inputNum = Convert.ToUInt32(kvp.Key.Substring(6));
|
||||
|
||||
var port = chassis.HdmiInputs[inputNum].HdmiInputPort;
|
||||
// set hdcp disables
|
||||
if (kvp.Value.DisableHdcp)
|
||||
{
|
||||
Debug.Console(0, this, "Configuration disables HDCP support on {0}", kvp.Key);
|
||||
port.HdcpSupportOff();
|
||||
}
|
||||
else
|
||||
port.HdcpSupportOn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
var result = Chassis.Register();
|
||||
if (result != Crestron.SimplSharpPro.eDeviceRegistrationUnRegistrationResponse.Success)
|
||||
{
|
||||
Debug.Console(0, this, "Device registration failed: {0}", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.CustomActivate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region IRouting Members
|
||||
|
||||
public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType)
|
||||
{
|
||||
// Try to make switch only when necessary. The unit appears to toggle when already selected.
|
||||
var current = Chassis.HdmiOutputs[1].VideoOut;
|
||||
if(current != Chassis.HdmiInputs[(uint)inputSelector])
|
||||
Chassis.HdmiOutputs[1].VideoOut = Chassis.HdmiInputs[(uint)inputSelector];
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="properties"></param>
|
||||
/// <returns></returns>
|
||||
public static HdMdNxM4kEController GetController(string key, string name,
|
||||
string type, HdMdNxM4kEPropertiesConfig properties)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ipid = properties.Control.IpIdInt;
|
||||
var address = properties.Control.TcpSshProperties.Address;
|
||||
|
||||
type = type.ToLower();
|
||||
if (type == "hdmd4x14ke")
|
||||
{
|
||||
var chassis = new HdMd4x14kE(ipid, address, Global.ControlSystem);
|
||||
return new HdMdNxM4kEController(key, name, chassis, properties);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, "ERROR Creating device key {0}: \r{1}", key, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,13 @@ namespace PepperDash.Essentials.DM
|
||||
return PepperDash.Essentials.DM.DmRmcHelper.GetDmRmcController(key, name, type, props);
|
||||
}
|
||||
|
||||
else if (typeName.Equals("hdmd4x14ke"))
|
||||
{
|
||||
var props = JsonConvert.DeserializeObject
|
||||
<PepperDash.Essentials.DM.Config.HdMdNxM4kEPropertiesConfig>(properties.ToString());
|
||||
return PepperDash.Essentials.DM.Chassis.HdMdNxM4kEController.GetController(key, name, type, props);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.DM.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the properties section of HdMdNxM boxes
|
||||
/// </summary>
|
||||
public class HdMdNxM4kEPropertiesConfig
|
||||
{
|
||||
[JsonProperty("control")]
|
||||
public ControlPropertiesConfig Control { get; set; }
|
||||
|
||||
[JsonProperty("inputs")]
|
||||
public Dictionary<string, InputPropertiesConfig> Inputs { get; set; }
|
||||
}
|
||||
}
|
||||
15
Essentials DM/Essentials_DM/Config/InputPropertiesConfig.cs
Normal file
15
Essentials DM/Essentials_DM/Config/InputPropertiesConfig.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.DM.Config
|
||||
{
|
||||
public class InputPropertiesConfig
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public bool DisableHdcp { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -55,13 +55,9 @@
|
||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DM.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="PepperDash_Core, Version=1.0.0.15153, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="PepperDash_Core, Version=1.0.4.20530, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\pepperdash-simplsharp-core\Pepperdash Core\CLZ Builds\PepperDash_Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PepperDash_Essentials_Core, Version=1.0.0.24289, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\Essentials Core\PepperDashEssentialsBase\bin\PepperDash_Essentials_Core.dll</HintPath>
|
||||
<HintPath>..\..\..\PepperDash.Core\Pepperdash Core\Pepperdash Core\bin\PepperDash_Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SimplSharpCustomAttributesInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
@@ -95,9 +91,12 @@
|
||||
<Compile Include="Cards REMOVE\DmInputCardBase.cs" />
|
||||
<Compile Include="Chassis\DmCardAudioOutput.cs" />
|
||||
<Compile Include="Chassis\DmChassisController.cs" />
|
||||
<Compile Include="Chassis\HdMdNxM4kEController.cs" />
|
||||
<Compile Include="Config\DmRmcConfig.cs" />
|
||||
<Compile Include="Config\DmTxConfig.cs" />
|
||||
<Compile Include="Config\DMChassisConfig.cs" />
|
||||
<Compile Include="Config\HdMdNxM4kEPropertiesConfig.cs" />
|
||||
<Compile Include="Config\InputPropertiesConfig.cs" />
|
||||
<Compile Include="DmPortName.cs" />
|
||||
<Compile Include="Endpoints\Receivers\DmRmc4KScalerCController.cs" />
|
||||
<Compile Include="Endpoints\Receivers\DmRmcScalerCController.cs" />
|
||||
@@ -115,6 +114,12 @@
|
||||
<Compile Include="VideoStatusHelpers.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>
|
||||
|
||||
@@ -4,5 +4,4 @@
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Essentials_DM")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyVersion("1.0.0.*")]
|
||||
|
||||
[assembly: AssemblyVersion("1.0.3.*")]
|
||||
@@ -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>
|
||||
@@ -38,4 +38,17 @@ namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CodecCallStatusItemChangeEventArgs : EventArgs
|
||||
{
|
||||
public CodecActiveCallItem CallItem { get; private set; }
|
||||
|
||||
public CodecCallStatusItemChangeEventArgs(CodecActiveCallItem item)
|
||||
{
|
||||
CallItem = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,27 +24,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
void RejectCall(CodecActiveCallItem item);
|
||||
void SendDtmf(string digit);
|
||||
|
||||
//BoolFeedback IncomingCallFeedback { get; }
|
||||
bool IsInCall { get; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CodecCallStatusItemChangeEventArgs : EventArgs
|
||||
{
|
||||
public CodecActiveCallItem CallItem { get; private set; }
|
||||
|
||||
//public eCodecCallStatus PreviousStatus { get; private set; }
|
||||
|
||||
//public eCodecCallStatus NewStatus { get; private set; }
|
||||
|
||||
public CodecCallStatusItemChangeEventArgs(/*eCodecCallStatus previousStatus,
|
||||
eCodecCallStatus newStatus,*/ CodecActiveCallItem item)
|
||||
{
|
||||
//PreviousStatus = previousStatus;
|
||||
//NewStatus = newStatus;
|
||||
CallItem = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,9 @@ namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
|
||||
public event EventHandler<EventArgs> MeetingsListHasChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Setter triggers MeetingsListHasChanged event
|
||||
/// </summary>
|
||||
public List<Meeting> Meetings
|
||||
{
|
||||
get
|
||||
@@ -131,7 +134,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec
|
||||
get
|
||||
{
|
||||
return StartTime.AddMinutes(-5) <= DateTime.Now
|
||||
&& DateTime.Now <= EndTime.AddMinutes(-5);
|
||||
&& DateTime.Now <= EndTime; //.AddMinutes(-5);
|
||||
}
|
||||
}
|
||||
//public string ConferenceNumberToDial { get; set; }
|
||||
|
||||
@@ -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 List<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<EventArgs> 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
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,12 @@ namespace PepperDash.Essentials.Devices.Displays
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace PepperDash.Essentials.Devices.Displays
|
||||
public interface IInputHdmi3 { void InputHdmi3(); }
|
||||
public interface IInputHdmi4 { void InputHdmi4(); }
|
||||
public interface IInputDisplayPort1 { void InputDisplayPort1(); }
|
||||
public interface IInputDisplayPort2 { void InputDisplayPort2(); }
|
||||
public interface IInputDisplayPort2 { void InputDisplayPort2(); }
|
||||
public interface IInputVga1 { void InputVga1(); }
|
||||
|
||||
}
|
||||
@@ -23,6 +23,7 @@ namespace PepperDash.Essentials.Devices.Displays
|
||||
|
||||
public byte ID { get; private set; }
|
||||
|
||||
bool LastCommandSentWasVolume;
|
||||
|
||||
bool _PowerIsOn;
|
||||
bool _IsWarmingUp;
|
||||
@@ -99,9 +100,15 @@ namespace PepperDash.Essentials.Devices.Displays
|
||||
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);
|
||||
|
||||
@@ -165,6 +172,9 @@ namespace PepperDash.Essentials.Devices.Displays
|
||||
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++)
|
||||
{
|
||||
@@ -309,6 +319,10 @@ namespace PepperDash.Essentials.Devices.Displays
|
||||
/// <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;
|
||||
@@ -320,6 +334,12 @@ namespace PepperDash.Essentials.Devices.Displays
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -393,11 +413,21 @@ namespace PepperDash.Essentials.Devices.Displays
|
||||
|
||||
public void InputHdmi1()
|
||||
{
|
||||
SendBytes(new byte[] { 0xAA, 0x14, 0x00, 0x01, 0x22, 0x00 });
|
||||
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 });
|
||||
}
|
||||
|
||||
|
||||
@@ -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,249 @@
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,14 +58,14 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.GeneralIO.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="PepperDash_Core, Version=1.0.6284.20368, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Crestron.SimplSharpPro.Lighting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\pepperdash-simplsharp-core\Pepperdash Core\CLZ Builds\PepperDash_Core.dll</HintPath>
|
||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Lighting.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PepperDash_Essentials_Core, Version=1.0.0.24289, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="PepperDash_Core, Version=1.0.4.20530, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\Essentials Core\PepperDashEssentialsBase\bin\PepperDash_Essentials_Core.dll</HintPath>
|
||||
<HintPath>..\..\..\PepperDash.Core\Pepperdash Core\Pepperdash Core\bin\PepperDash_Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SimplSharpCustomAttributesInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
@@ -109,6 +109,7 @@
|
||||
<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" />
|
||||
@@ -121,8 +122,13 @@
|
||||
<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" />
|
||||
@@ -154,6 +160,12 @@
|
||||
<Compile Include="VideoCodec\VideoCodecBase.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>
|
||||
|
||||
@@ -3,17 +3,22 @@ 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.Devices.Common.DSP;
|
||||
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||
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
|
||||
{
|
||||
@@ -25,6 +30,8 @@ namespace PepperDash.Essentials.Devices.Common
|
||||
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();
|
||||
@@ -103,17 +110,136 @@ namespace PepperDash.Essentials.Devices.Common
|
||||
|
||||
else if (typeName == "mockvc")
|
||||
{
|
||||
var props = JsonConvert.DeserializeObject
|
||||
<PepperDash.Essentials.Devices.Common.VideoCodec.MockVcPropertiesConfig>(properties.ToString());
|
||||
return new PepperDash.Essentials.Devices.Common.VideoCodec
|
||||
.MockVC(key, name, props);
|
||||
var props = JsonConvert.DeserializeObject<VideoCodec.MockVcPropertiesConfig>(properties.ToString());
|
||||
return new VideoCodec.MockVC(key, name, props);
|
||||
}
|
||||
|
||||
else if (typeName.StartsWith("ciscospark"))
|
||||
{
|
||||
var comm = CommFactory.CreateCommForDevice(dc);
|
||||
var props = JsonConvert.DeserializeObject<Codec.CiscoSparkCodecPropertiesConfig>(properties.ToString());
|
||||
return new PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CiscoSparkCodec(key, name, comm, props);
|
||||
return new VideoCodec.Cisco.CiscoSparkCodec(key, name, comm, props);
|
||||
}
|
||||
|
||||
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)
|
||||
if (cs.SupportsRelay && props.PortNumber <= cs.NumberOfRelayPorts)
|
||||
{
|
||||
Relay relay = cs.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 (groupName == "settopbox") //(typeName == "irstbbase")
|
||||
@@ -135,6 +261,71 @@ namespace PepperDash.Essentials.Devices.Common
|
||||
return new Roku2(key, name, irCont);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 += new EventHandler<EventArgs>(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 += new EventHandler<EventArgs>(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; }
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro.GeneralIO;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common.Occupancy
|
||||
@@ -15,15 +16,51 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy
|
||||
|
||||
public BoolFeedback RoomIsOccupiedFeedback { get; private set; }
|
||||
|
||||
public EssentialsGlsOccupancySensorBaseController(string key, string name, GlsOccupancySensorBase sensor, GlsOccupancySensorConfigurationProperties props)
|
||||
// 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.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class GlsOccupancySensorConfigurationProperties
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -4,5 +4,4 @@
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Essentials_Devices_Common")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyVersion("1.0.0.*")]
|
||||
|
||||
[assembly: AssemblyVersion("1.0.3.*")]
|
||||
@@ -8,7 +8,7 @@ using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices.Common
|
||||
{
|
||||
public class SetTopBoxPropertiesConfig
|
||||
public class SetTopBoxPropertiesConfig : PepperDash.Essentials.Core.Config.SourceDevicePropertiesConfigBase
|
||||
{
|
||||
public bool HasPresets { get; set; }
|
||||
public bool HasDvr { get; set; }
|
||||
|
||||
@@ -33,6 +33,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
|
||||
|
||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||
|
||||
public BoolFeedback PresentationViewMaximizedFeedback { get; private set; }
|
||||
|
||||
string CurrentPresentationView;
|
||||
|
||||
public BoolFeedback RoomIsOccupiedFeedback { get; private set; }
|
||||
|
||||
public IntFeedback PeopleCountFeedback { get; private set; }
|
||||
@@ -45,6 +49,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
|
||||
|
||||
public StringFeedback LocalLayoutFeedback { get; private set; }
|
||||
|
||||
public BoolFeedback LocalLayoutIsProminentFeedback { get; private set; }
|
||||
|
||||
public BoolFeedback FarEndIsSharingContentFeedback { get; private set; }
|
||||
|
||||
private CodecCommandWithLabel CurrentSelfviewPipPosition;
|
||||
|
||||
private CodecCommandWithLabel CurrentLocalLayout;
|
||||
@@ -68,15 +76,15 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
|
||||
/// </summary>
|
||||
public List<CodecCommandWithLabel> LocalLayouts = new List<CodecCommandWithLabel>()
|
||||
{
|
||||
new CodecCommandWithLabel("auto", "Auto"),
|
||||
//new CodecCommandWithLabel("auto", "Auto"),
|
||||
//new CiscoCodecLocalLayout("custom", "Custom"), // Left out for now
|
||||
new CodecCommandWithLabel("equal","Equal"),
|
||||
new CodecCommandWithLabel("overlay","Overlay"),
|
||||
new CodecCommandWithLabel("prominent","Prominent"),
|
||||
new CodecCommandWithLabel("single","Single")
|
||||
};
|
||||
|
||||
private CiscoCodecConfiguration.RootObject CodecConfiguration;
|
||||
|
||||
private CiscoCodecConfiguration.RootObject CodecConfiguration = new CiscoCodecConfiguration.RootObject();
|
||||
|
||||
private CiscoCodecStatus.RootObject CodecStatus = new CiscoCodecStatus.RootObject();
|
||||
|
||||
@@ -134,6 +142,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
|
||||
}
|
||||
}
|
||||
|
||||
protected Func<bool> FarEndIsSharingContentFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () => CodecStatus.Status.Conference.Presentation.Mode.Value == "Receiving";
|
||||
}
|
||||
}
|
||||
|
||||
protected override Func<bool> MuteFeedbackFunc
|
||||
{
|
||||
get
|
||||
@@ -190,6 +206,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
|
||||
}
|
||||
}
|
||||
|
||||
protected Func<bool> LocalLayoutIsProminentFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () => CurrentLocalLayout.Label == "Prominent";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string CliFeedbackRegistrationExpression;
|
||||
|
||||
@@ -241,6 +265,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
|
||||
SelfviewIsOnFeedback = new BoolFeedback(SelfViewIsOnFeedbackFunc);
|
||||
SelfviewPipPositionFeedback = new StringFeedback(SelfviewPipPositionFeedbackFunc);
|
||||
LocalLayoutFeedback = new StringFeedback(LocalLayoutFeedbackFunc);
|
||||
LocalLayoutIsProminentFeedback = new BoolFeedback(LocalLayoutIsProminentFeedbackFunc);
|
||||
FarEndIsSharingContentFeedback = new BoolFeedback(FarEndIsSharingContentFeedbackFunc);
|
||||
|
||||
PresentationViewMaximizedFeedback = new BoolFeedback(() => CurrentPresentationView == "Maximized");
|
||||
|
||||
Communication = comm;
|
||||
|
||||
@@ -272,9 +300,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
|
||||
PortGather.IncludeDelimiter = true;
|
||||
PortGather.LineReceived += this.Port_LineReceived;
|
||||
|
||||
CodecConfiguration = new CiscoCodecConfiguration.RootObject();
|
||||
//CodecStatus = new CiscoCodecStatus.RootObject();
|
||||
|
||||
CodecInfo = new CiscoCodecInfo(CodecStatus, CodecConfiguration);
|
||||
|
||||
CallHistory = new CodecCallHistory();
|
||||
@@ -300,7 +325,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
|
||||
CodecStatus.Status.Video.Selfview.Mode.ValueChangedAction = SelfviewIsOnFeedback.FireUpdate;
|
||||
CodecStatus.Status.Video.Selfview.PIPPosition.ValueChangedAction = ComputeSelfviewPipStatus;
|
||||
CodecStatus.Status.Video.Layout.LayoutFamily.Local.ValueChangedAction = ComputeLocalLayout;
|
||||
CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction = SharingContentIsOnFeedback.FireUpdate;
|
||||
CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction += SharingContentIsOnFeedback.FireUpdate;
|
||||
CodecStatus.Status.Conference.Presentation.Mode.ValueChangedAction += FarEndIsSharingContentFeedback.FireUpdate;
|
||||
|
||||
CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, eRoutingSignalType.AudioVideo,
|
||||
eRoutingPortConnectionType.Hdmi, new Action(StopSharing), this);
|
||||
@@ -671,6 +697,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
|
||||
|
||||
EvalutateDisconnectEvent(eventReceived);
|
||||
}
|
||||
else if (response.IndexOf("\"Bookings\":{") > -1) // The list has changed, reload it
|
||||
{
|
||||
GetBookings(null);
|
||||
}
|
||||
}
|
||||
else if (response.IndexOf("\"CommandResponse\":{") > -1)
|
||||
{
|
||||
@@ -1229,6 +1259,35 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles between single/prominent layouts
|
||||
/// </summary>
|
||||
public void LocalLayoutToggleSingleProminent()
|
||||
{
|
||||
if (CurrentLocalLayout != null)
|
||||
{
|
||||
if (CurrentLocalLayout.Label != "Prominent")
|
||||
LocalLayoutSet(LocalLayouts.FirstOrDefault(l => l.Label.Equals("Prominent")));
|
||||
else
|
||||
LocalLayoutSet(LocalLayouts.FirstOrDefault(l => l.Label.Equals("Single")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void MinMaxLayoutToggle()
|
||||
{
|
||||
if (PresentationViewMaximizedFeedback.BoolValue)
|
||||
CurrentPresentationView = "Minimized";
|
||||
else
|
||||
CurrentPresentationView = "Maximized";
|
||||
|
||||
SendText(string.Format("xCommand Video PresentationView Set View: {0}", CurrentPresentationView));
|
||||
PresentationViewMaximizedFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the current selfview PIP position
|
||||
/// </summary>
|
||||
@@ -1264,7 +1323,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
|
||||
|
||||
public override bool MultiSiteOptionIsEnabled
|
||||
{
|
||||
get
|
||||
get
|
||||
{
|
||||
if (CodecStatus.Status.SystemUnit.Software.OptionKeys.MultiSite.Value.ToLower() == "true")
|
||||
return true;
|
||||
@@ -1300,7 +1359,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
|
||||
get
|
||||
{
|
||||
if (CodecConfiguration.Configuration.H323.H323Alias.ID != null)
|
||||
return CodecConfiguration.Configuration.H323.H323Alias.E164.Value;
|
||||
return CodecConfiguration.Configuration.H323.H323Alias.ID.Value;
|
||||
else
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -16,5 +16,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
|
||||
StringFeedback LocalLayoutFeedback { get; }
|
||||
|
||||
void LocalLayoutToggle();
|
||||
void LocalLayoutToggleSingleProminent();
|
||||
void MinMaxLayoutToggle();
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,12 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
|
||||
{
|
||||
get
|
||||
{
|
||||
var value = ActiveCalls.Any(c => c.IsActiveCall);
|
||||
bool value;
|
||||
|
||||
if (ActiveCalls != null)
|
||||
value = ActiveCalls.Any(c => c.IsActiveCall);
|
||||
else
|
||||
value = false;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
881
Essentials/PepperDashEssentials/ClassDiagram1.cd
Normal file
881
Essentials/PepperDashEssentials/ClassDiagram1.cd
Normal file
@@ -0,0 +1,881 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ClassDiagram MajorVersion="1" MinorVersion="1">
|
||||
<Class Name="PepperDash.Essentials.EssentialsRoomVolumesConfig" Collapsed="true">
|
||||
<Position X="19.25" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAQAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAIAgA=</HashCode>
|
||||
<FileName>Audio\EssentialsVolumeLevelConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsVolumeLevelConfig" Collapsed="true">
|
||||
<Position X="22.75" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAEAAAAAAAAAAAAAAAAIAAAAgBAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Audio\EssentialsVolumeLevelConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.ConfigReader" Collapsed="true">
|
||||
<Position X="26.25" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAIAAAAAAAABAAAACAAIAAAAQAAAAAAAAAAEAA=</HashCode>
|
||||
<FileName>Config\ConfigReader.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.DeviceFactory" Collapsed="true">
|
||||
<Position X="29.75" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Config\DeviceFactory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsConfig" Collapsed="true">
|
||||
<Position X="33.25" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAEAAAAAQAIAAAAAAAACAAAAAAAAAAAAAAEAAAA=</HashCode>
|
||||
<FileName>Config\EssentialsConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SystemTemplateConfigs" Collapsed="true">
|
||||
<Position X="33.25" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Config\EssentialsConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.ConfigTieLine" Collapsed="true">
|
||||
<Position X="31.5" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAgEAAAAAAEAAAAAAAAAAAAAAAAAAAAAEAIAIA=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\ConfigTieLine.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Configuration" Collapsed="true">
|
||||
<Position X="33.25" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AEAAAAAAAAAAgQAAAAAAgAAAAAAAAAAAAAAgEDAADAQ=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\Configuration.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.ConfigSourceList" Collapsed="true">
|
||||
<Position X="29.75" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAQAAAAAAAQAAACAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\Configuration.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.ConfigSourceItem" Collapsed="true">
|
||||
<Position X="28" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAgAAAAAAAEAAAAAAAAAAAAAAAAAgAAAAAAA=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\Configuration.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.ConfigInfo" Collapsed="true">
|
||||
<Position X="24.5" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>IQAAAAAEAAAAAAADAAACABQAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\Configuration.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SourceListConfigProperties" Collapsed="true">
|
||||
<Position X="24.5" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAEAAAAAAAAAAAIAAAAAgAAAIAAA=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\ConfigurationHelpers.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.DmFactory" Collapsed="true">
|
||||
<Position X="31.5" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAQAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\Factories\DmFactory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.FactoryHelper" Collapsed="true">
|
||||
<Position X="26.25" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAEDAAKAA=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\Factories\FactoryHelper.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.IrOutPortConfig" Collapsed="true">
|
||||
<Position X="31.5" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAABAAAA=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\Factories\FactoryHelper.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.ControlSystem" Collapsed="true">
|
||||
<Position X="35" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAoAgAAIAEAACAAEAIEIBICAAAAAAABAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>ControlSystem.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Amplifier" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="21" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAA=</HashCode>
|
||||
<FileName>Devices\Amplifier.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.CotijaConfig" Collapsed="true">
|
||||
<Position X="19.25" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\CotijaConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.CotijaDdvc01RoomBridgePropertiesConfig" Collapsed="true">
|
||||
<Position X="22.75" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\CotijaConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.CotijaSystemController" Collapsed="true">
|
||||
<Position X="24.5" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>CAAABAABAgACCAKGBIAAEyBAFAAACYSAgIAAAAJkAAA=</HashCode>
|
||||
<FileName>Room\Cotija\CotijaSystemController.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.CotijaBridgeBase" Collapsed="true">
|
||||
<Position X="9.5" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAQIQAAAAAAAAgAAAAAAQAAAAAAAAAAAAAAAABAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\RoomBridges\CotijaBridgeBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.CotijaEssentialsHuddleSpaceRoomBridge" Collapsed="true">
|
||||
<Position X="8.25" Y="5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAIAAAAIABAAkgAABgIAAAAAAAAAEAAAAAAgBAAACA=</HashCode>
|
||||
<FileName>Room\Cotija\RoomBridges\CotijaEssentialsHuddleSpaceRoomBridge.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SourceSelectMessageContent" Collapsed="true">
|
||||
<Position X="26.25" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\RoomBridges\CotijaEssentialsHuddleSpaceRoomBridge.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsHuddleSpaceRoom" Collapsed="true">
|
||||
<Position X="0.5" Y="9" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>iQFBQAIAAgAAgQAEQACAMABAAABAACAQUAAQAAgCgBA=</HashCode>
|
||||
<FileName>Room\Types\EssentialsHuddleSpaceRoom.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsHuddleVtc1Room" Collapsed="true">
|
||||
<Position X="2.75" Y="9" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>iQFBQAIAIgQMgQAEQAigMABAAABAADIwUACQAAgCgTE=</HashCode>
|
||||
<FileName>Room\Types\EssentialsHuddleVtc1Room.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsPresentationRoom" Collapsed="true">
|
||||
<Position X="5" Y="9" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>iQAEAAIACkAAAQAOQASgMAAJAABgAAAQQAAQAAgCgBA=</HashCode>
|
||||
<FileName>Room\Types\EssentialsPresentationRoom.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsRoomBase" Collapsed="true">
|
||||
<Position X="2.75" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gQAAEAICECgCAQAEAAAUIwIyAAAAgACiAgAAAQECAgA=</HashCode>
|
||||
<FileName>Room\Types\EssentialsRoomBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.CrestronTouchpanelPropertiesConfig" Collapsed="true">
|
||||
<Position X="26.25" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AICCIAAIGIAAAAAgCAAIAEAAAAAAAAAAAAEAIAAAAAA=</HashCode>
|
||||
<FileName>UI\CrestronTouchpanelPropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.UiSetupPropertiesConfig" Collapsed="true">
|
||||
<Position X="19.25" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UI\CrestronTouchpanelPropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsTouchpanelController" Collapsed="true">
|
||||
<Position X="21" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAIAEAAAAAAAAAAAAAAAAEAAAAACKIBAAgACAAAAAA=</HashCode>
|
||||
<FileName>UI\EssentialsTouchpanelController.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.HttpLogoServer" Collapsed="true">
|
||||
<Position X="19.25" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAQAAAACAAAAABAAAAAAAAAABAAAAAAAAAAkAAAAA=</HashCode>
|
||||
<FileName>UI\HttpLogoServer.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.UIBoolJoin" Collapsed="true">
|
||||
<Position X="35" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>j+jWCNqEIGzi4UTaTgyn37kpncQJK7L42VMLmMgTE5A=</HashCode>
|
||||
<FileName>UI\JoinConstants\UIBoolJoin.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.UISmartObjectJoin" Collapsed="true">
|
||||
<Position X="21" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>BAggBIABCQAAGAAQAAAACAACAAAAAAAAAAIAAAAAAAA=</HashCode>
|
||||
<FileName>UI\JoinConstants\UISmartObjectJoin.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.UIStringJoin" Collapsed="true">
|
||||
<Position X="22.75" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>BkBgIAgAAggOQAFGAYQIABACgCEBjkSQAUEAASIABCE=</HashCode>
|
||||
<FileName>UI\JoinConstants\UIStringlJoin.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.UIUshortJoin" Collapsed="true">
|
||||
<Position X="24.5" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAQAAAACAAAACAEAAIAAAAAAIABAIAAAABAAAEAAAAA=</HashCode>
|
||||
<FileName>UI\JoinConstants\UIUshortJoin.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SubpageReferenceListActivityItem" Collapsed="true">
|
||||
<Position X="28" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA=</HashCode>
|
||||
<FileName>UI\SubpageReferenceListActivityItem.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SubpageReferenceListButtonAndModeItem" Collapsed="true">
|
||||
<Position X="29.75" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA=</HashCode>
|
||||
<FileName>UI\SubpageReferenceListCallStagingItem.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SubpageReferenceListSourceItem" Collapsed="true">
|
||||
<Position X="31.5" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAABAAAAAAAAAAAAAAAAAAAAgAAAAACAAAAAABgAAA=</HashCode>
|
||||
<FileName>UI\SubpageReferenceListSourceItem.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.PanelDriverBase" Collapsed="true">
|
||||
<Position X="8.75" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>CAAIkAAAAAAQEAAAEAACAAAAAIAEABAAAgAACAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\enums and base.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsPanelMainInterfaceDriver" Collapsed="true">
|
||||
<Position X="1" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>ABAAAAAAAhgAAAAAEAAAAAAAAIAEAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\Essentials\EssentialsPanelMainInterfaceDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsPresentationPanelAvFunctionsDriver" Collapsed="true">
|
||||
<Position X="3.25" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gTEAIIAiCggFNCQ4EA4AWBkAKJCEqAAOS4CKMAQQJQA=</HashCode>
|
||||
<FileName>UIDrivers\Essentials\EssentialsPresentationPanelAvFunctionsDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsHuddlePanelAvFunctionsDriver" Collapsed="true">
|
||||
<Position X="7.75" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gRQAIICuAghENHQpEA4IWCkBMJDEsEAEC4CAMARQIBA=</HashCode>
|
||||
<FileName>UIDrivers\EssentialsHuddle\EssentialsHuddlePanelAvFunctionsDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsHuddleVtc1PanelAvFunctionsDriver" Collapsed="true">
|
||||
<Position X="12.25" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>GRwAIYC+oghAeHStEDAIWCdBMADEsBAcDwCAMARYIBg=</HashCode>
|
||||
<FileName>UIDrivers\EssentialsHuddleVTC\EssentialsHuddleVtc1PanelAvFunctionsDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.JoinedSigInterlock" Collapsed="true">
|
||||
<Position X="19.25" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAQgAIAAAAAAAAAEAAAAAQAAAAEAAAAAAAAEAAAgAA=</HashCode>
|
||||
<FileName>UIDrivers\JoinedSigInterlock.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SingleSubpageModalAndBackDriver" Collapsed="true">
|
||||
<Position X="14.5" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAEAAAQAAABIAEAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\Page Drivers\SingleSubpageModalAndBackDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SingleSubpageModalDriver" Collapsed="true">
|
||||
<Position X="16.75" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAEAAAAAAABAAEAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\Page Drivers\SingleSubpageModalDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SigInterlock" Collapsed="true">
|
||||
<Position X="19.25" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAQAAIAAAAAAAAIEAAAAAAAAAAEAAAAAAAAEAAAgAA=</HashCode>
|
||||
<FileName>UIDrivers\SigInterlock.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SmartObjectRoomsList" Collapsed="true">
|
||||
<Position X="21" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAACAAACBAAAAAAAAAAAAAAAAAAAAIAAAAAAQA=</HashCode>
|
||||
<FileName>UIDrivers\SmartObjectRoomsList.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SmartObjectRoomsListItem" Collapsed="true">
|
||||
<Position X="22.75" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAQAAAAAAAAAAAABAAQAAAAAAAAAACAAEAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\SmartObjectRoomsList.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.VolumeDeviceChangeEventArgs" Collapsed="true">
|
||||
<Position X="26.25" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAABAAAAAEAAAAAAAAAAAAAAAAAAAQAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\VolumeAndSourceChangeArgs.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase" Collapsed="true">
|
||||
<Position X="8.25" Y="9.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>IAGigRBpCgZwAIMSBBIbIgAAImAPtEBiAAgECpJgKQo=</HashCode>
|
||||
<FileName>OTHER\Fusion\EssentialsHuddleSpaceFusionSystemControllerBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.FusionRoomExtensions" Collapsed="true">
|
||||
<Position X="31.5" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAACgAIQAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\EssentialsHuddleSpaceFusionSystemControllerBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.FusionStaticAssetExtensions" Collapsed="true">
|
||||
<Position X="35" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAQAAACAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\EssentialsHuddleSpaceFusionSystemControllerBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.EssentialsHuddleVtc1FusionController" Collapsed="true">
|
||||
<Position X="8.25" Y="11" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AACAAAAAAgAAAIAAAAAAAAAgIBAQAAAAAAAAAAAAAQA=</HashCode>
|
||||
<FileName>OTHER\Fusion\EssentialsHuddleVtc1FusionController.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.ScheduleChangeEventArgs" Collapsed="true">
|
||||
<Position X="33.25" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionEventHandlers.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.MeetingChangeEventArgs" Collapsed="true">
|
||||
<Position X="26.25" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionEventHandlers.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.ProcessorProgReg" Collapsed="true">
|
||||
<Position X="19.25" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionProcessorQueries.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.ProcessorProgramItem" Collapsed="true">
|
||||
<Position X="35" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAEAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionProcessorQueries.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.FusionRoomGuids" Collapsed="true">
|
||||
<Position X="33.25" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAICAAAAAAAAAAAAAAAAAACAAAATQAAAAAAAABAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.FusionOccupancySensorAsset" Collapsed="true">
|
||||
<Position X="29.75" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAQAQAAAAAAAAQAAAAAAQAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.FusionAsset" Collapsed="true">
|
||||
<Position X="28" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAQAQAAAAAAAAQAAAAAAQAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.RoomSchedule" Collapsed="true">
|
||||
<Position X="31.5" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.LocalTimeRequest" Collapsed="true">
|
||||
<Position X="24.5" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.RequestSchedule" Collapsed="true">
|
||||
<Position X="22.75" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAACACAAAAQAAAAAAAAAAAAAAAAAAAACAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.RequestAction" Collapsed="true">
|
||||
<Position X="21" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAACAAAgAAQAAAAAAAAAAAAAAAAAAIAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.ActionResponse" Collapsed="true">
|
||||
<Position X="19.25" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAgAAQAAAAAAAAAAAAAAAAAAIAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.Parameter" Collapsed="true">
|
||||
<Position X="33.25" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAgAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.ScheduleResponse" Collapsed="true">
|
||||
<Position X="35" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAACAAAAAAQAAAAAAAAAAgAAAAAAAAAAABAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.Event" Collapsed="true">
|
||||
<Position X="24.5" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AABCAAAAYEAAEBIBAIAAJAQAQKAYAAAIEAAAEAACCgg=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.Resources" Collapsed="true">
|
||||
<Position X="26.25" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.Rooms" Collapsed="true">
|
||||
<Position X="29.75" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.Room" Collapsed="true">
|
||||
<Position X="28" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAgAAAAAAAAAQAAAAAAAAAAAAAAAAEAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.Attendees" Collapsed="true">
|
||||
<Position X="22.75" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAABAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.Required" Collapsed="true">
|
||||
<Position X="24.5" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.Optional" Collapsed="true">
|
||||
<Position X="31.5" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.MeetingType" Collapsed="true">
|
||||
<Position X="28" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAgAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.MeetingTypes" Collapsed="true">
|
||||
<Position X="29.75" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.LiveMeeting" Collapsed="true">
|
||||
<Position X="21" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAgAQAAIAAAAAAACAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.LiveMeetingURL" Collapsed="true">
|
||||
<Position X="22.75" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.DDVC01RoomPropertiesConfig" Collapsed="true">
|
||||
<Position X="5" Y="6.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAIAgAAQAAAAAAAAEAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\DDVC01RoomPropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.DDVC01SpeedDial" Collapsed="true">
|
||||
<Position X="28" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAEAAAAQAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\DDVC01RoomPropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsHuddleRoomPropertiesConfig" Collapsed="true">
|
||||
<Position X="2.75" Y="4.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAgAAAAAAAAAAACAAAAAABAAAAAAAAABA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsHuddleRoomPropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsHuddleVtc1PropertiesConfig" Collapsed="true">
|
||||
<Position X="5" Y="4.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAgAAAAAAAAAAACIAAAAABAAAAAAAAABA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsHuddleVtc1PropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsPresentationRoomPropertiesConfig" Collapsed="true">
|
||||
<Position X="0.5" Y="4.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAACAIAAAAAAAAAAABAACAAAAAABAAAAAAAAABA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsPresentationPropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomConfig" Collapsed="true">
|
||||
<Position X="26.25" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAEAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomPropertiesConfig" Collapsed="true">
|
||||
<Position X="2.75" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AABAEQAAAAEoAAEEAAQAAAACAAAAAAgggAAAAQAAAgA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsLightingPropertiesConfig" Collapsed="true">
|
||||
<Position X="19.25" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomMicrophonePrivacyConfig" Collapsed="true">
|
||||
<Position X="31.5" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAEAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsHelpPropertiesConfig" Collapsed="true">
|
||||
<Position X="35" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAgABAAAAAIAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsOneButtonMeetingPropertiesConfig" Collapsed="true">
|
||||
<Position X="22.75" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomAddressPropertiesConfig" Collapsed="true">
|
||||
<Position X="24.5" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAQAAAgAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsLogoPropertiesConfig" Collapsed="true">
|
||||
<Position X="21" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIACQAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomOccSensorConfig" Collapsed="true">
|
||||
<Position X="33.25" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AACAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomTechConfig" Collapsed="true">
|
||||
<Position X="35" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomEmergencyConfig" Collapsed="true">
|
||||
<Position X="28" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAABAACAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomEmergencyConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomEmergencyTriggerConfig" Collapsed="true">
|
||||
<Position X="29.75" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAABQAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomEmergencyConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.CotijaDdvc01DeviceBridge" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="21" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AUAAAAgAAAACwAYAAAAAAAEAAAAAAAAAIcAAAEAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\CotijaDdvc01DeviceBridge.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.IChannelExtensions" Collapsed="true">
|
||||
<Position X="21" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\DeviceTypeInterfaces\IChannelExtensions.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.IColorExtensions" Collapsed="true">
|
||||
<Position X="22.75" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\DeviceTypeInterfaces\IColorExtensions.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.IDPadExtensions" Collapsed="true">
|
||||
<Position X="24.5" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\DeviceTypeInterfaces\IDPadExtensions.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.IDvrExtensions" Collapsed="true">
|
||||
<Position X="26.25" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\DeviceTypeInterfaces\IDvrExtensions.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.INumericExtensions" Collapsed="true">
|
||||
<Position X="28" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\DeviceTypeInterfaces\INumericExtensions.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.IPowerExtensions" Collapsed="true">
|
||||
<Position X="29.75" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\DeviceTypeInterfaces\IPowerExtensions.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.ISetTopBoxControlsExtensions" Collapsed="true">
|
||||
<Position X="33.25" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\DeviceTypeInterfaces\ISetTopBoxControlsExtensions.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.ITransportExtensions" Collapsed="true">
|
||||
<Position X="35" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\DeviceTypeInterfaces\ITransportExtensions.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.CotijaDdvc01RoomBridge" Collapsed="true">
|
||||
<Position X="10.5" Y="5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gACIAAAAAAICAFAAAACAAAEIIAAAAAQAQAAAABAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\RoomBridges\CotijaDdvc01RoomBridge.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.EssentialsRoomEmergencyBase" Collapsed="true">
|
||||
<Position X="8.25" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Emergency\EsentialsRoomEmergencyContactClosure.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.EssentialsRoomEmergencyContactClosure" Collapsed="true">
|
||||
<Position X="8.25" Y="7.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAASBAAAAAAAAAAAAAABAAAAAAAEAA=</HashCode>
|
||||
<FileName>Room\Emergency\EsentialsRoomEmergencyContactClosure.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.UIDrivers.EssentialsHuddleTechPageDriver" Collapsed="true">
|
||||
<Position X="5.5" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAQAAAAAiACDAAAGCAACgAIAABECBAgQAAAAQAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\EssentialsHuddle\EssentialsHuddleTechPageDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver" Collapsed="true">
|
||||
<Position X="10" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>XAASAoAiAagwAcBAGAUURWQEOHQFAKCmAABCNSSEDPA=</HashCode>
|
||||
<FileName>UIDrivers\VC\EssentialsVideoCodecUiDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Interface Name="PepperDash.Essentials.IHasCurrentSourceInfoChange" Collapsed="true">
|
||||
<Position X="22.75" Y="9.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Types\EssentialsRoomBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.IAVDriver" Collapsed="true">
|
||||
<Position X="19.25" Y="9.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAgAAAAAAAAACBAAACAAAAIBAAAEAAAEAgAAAAAAIAA=</HashCode>
|
||||
<FileName>UIDrivers\EssentialsHuddleVTC\EssentialsHuddleVtc1PanelAvFunctionsDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Room.Cotija.IDelayedConfiguration" Collapsed="true">
|
||||
<Position X="21" Y="9.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\Interfaces.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Enum Name="PepperDash.Essentials.eShutdownType" Collapsed="true">
|
||||
<Position X="29.75" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAQAAAAAAACAAAAAAAAAAAAAAAAAAAAAEACAA=</HashCode>
|
||||
<FileName>Room\Types\EssentialsRoomBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.eVacancyMode" Collapsed="true">
|
||||
<Position X="31.5" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAACAAAAAAAAAAAAAAAAACAAAAAAAAAAEAAAA=</HashCode>
|
||||
<FileName>Room\Types\EssentialsRoomBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.eWarmingCoolingMode" Collapsed="true">
|
||||
<Position X="33.25" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAIEAAAA=</HashCode>
|
||||
<FileName>Room\Types\EssentialsRoomBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.eAvSubpageType" Collapsed="true">
|
||||
<Position X="24.5" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AIAAAAAAAAAAAAAAAhBAAAAAAAAAAACYAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\enums and base.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.eAvSourceSubpageType" Collapsed="true">
|
||||
<Position X="22.75" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAABAAAAAAAAAAAAAAACAAAEAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\enums and base.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.eCommonSubpageType" Collapsed="true">
|
||||
<Position X="28" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAEAAAAAAAAAIAAAAAAAAQAAAAQAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\enums and base.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.eAvSmartObjects" Collapsed="true">
|
||||
<Position X="21" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAABAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\enums and base.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.eCommonSmartObjects" Collapsed="true">
|
||||
<Position X="26.25" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\enums and base.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.ChangeType" Collapsed="true">
|
||||
<Position X="19.25" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\VolumeAndSourceChangeArgs.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Delegate Name="PepperDash.Essentials.PressAndHoldAction" Collapsed="true">
|
||||
<Position X="19.25" Y="11.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\RoomBridges\CotijaEssentialsHuddleSpaceRoomBridge.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Delegate>
|
||||
<Delegate Name="PepperDash.Essentials.SourceInfoChangeHandler" Collapsed="true">
|
||||
<Position X="21" Y="11.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAACAAACAAAAAAAAAAAAAAAAAAACAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\VolumeAndSourceChangeArgs.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Delegate>
|
||||
<Font Name="Segoe UI" Size="9" />
|
||||
</ClassDiagram>
|
||||
@@ -5,6 +5,7 @@ using Crestron.SimplSharp.CrestronIO;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
@@ -16,18 +17,28 @@ namespace PepperDash.Essentials
|
||||
{
|
||||
public static EssentialsConfig ConfigObject { get; private set; }
|
||||
|
||||
public static void LoadConfig2()
|
||||
public static bool LoadConfig2()
|
||||
{
|
||||
Debug.Console(0, "Using unmerged system/template configs.");
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading unmerged system/template portal configuration file.");
|
||||
try
|
||||
{
|
||||
using (StreamReader fs = new StreamReader(string.Format(@"\NVRAM\program{0}\ConfigurationFile.json",
|
||||
InitialParametersClass.ApplicationNumber)))
|
||||
var filePath = Global.FilePathPrefix + "configurationFile.json";
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to load config file: '{0}'", filePath);
|
||||
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Error,
|
||||
"ERROR: Configuration file not present. Please load file to {0} and reset program", filePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
using (StreamReader fs = new StreamReader(filePath))
|
||||
{
|
||||
var doubleObj = JObject.Parse(fs.ReadToEnd());
|
||||
ConfigObject = MergeConfigs(doubleObj).ToObject<EssentialsConfig>();
|
||||
|
||||
// Extract SystemUrl and TemplateUrl
|
||||
// Extract SystemUrl and TemplateUrl into final config output
|
||||
|
||||
if (doubleObj["system_url"] != null)
|
||||
{
|
||||
@@ -38,13 +49,16 @@ namespace PepperDash.Essentials
|
||||
{
|
||||
ConfigObject.TemplateUrl= doubleObj["template_url"].Value<string>();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Successfully Loaded Merged Config");
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, "Config failed: \r{0}", e);
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Error, "ERROR: Config load failed: \r{0}", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +70,8 @@ namespace PepperDash.Essentials
|
||||
var merged = new JObject();
|
||||
|
||||
// Put together top-level objects
|
||||
// skip any objects that don't have template objects
|
||||
|
||||
if (system["info"] != null)
|
||||
merged.Add("info", Merge(template["info"], system["info"]));
|
||||
else
|
||||
@@ -64,27 +80,33 @@ namespace PepperDash.Essentials
|
||||
merged.Add("devices", MergeArraysOnTopLevelProperty(template["devices"] as JArray,
|
||||
system["devices"] as JArray, "uid"));
|
||||
|
||||
if (system["rooms"] == null)
|
||||
merged.Add("rooms", template["rooms"]);
|
||||
else
|
||||
merged.Add("rooms", MergeArraysOnTopLevelProperty(template["rooms"] as JArray,
|
||||
system["rooms"] as JArray, "key"));
|
||||
if (template["rooms"] != null)
|
||||
{
|
||||
if (system["rooms"] == null)
|
||||
merged.Add("rooms", template["rooms"]);
|
||||
else
|
||||
merged.Add("rooms", MergeArraysOnTopLevelProperty(template["rooms"] as JArray,
|
||||
system["rooms"] as JArray, "key"));
|
||||
}
|
||||
|
||||
if (system["sourceLists"] == null)
|
||||
merged.Add("sourceLists", template["sourceLists"]);
|
||||
else
|
||||
merged.Add("sourceLists", Merge(template["sourceLists"], system["sourceLists"]));
|
||||
if (template["sourceLists"] != null)
|
||||
{
|
||||
if (system["sourceLists"] == null)
|
||||
merged.Add("sourceLists", template["sourceLists"]);
|
||||
else
|
||||
merged.Add("sourceLists", Merge(template["sourceLists"], system["sourceLists"]));
|
||||
}
|
||||
|
||||
// Template tie lines take precdence. Config tool probably can't do them at system
|
||||
// Template tie lines take precdence. Config tool doesn't do them at system
|
||||
// level anyway...
|
||||
if (template["tieLines"] != null)
|
||||
merged.Add("tieLines", template["tieLines"]);
|
||||
else if (system["tieLines"] != null)
|
||||
merged.Add("tieLines", system["tieLines"]);
|
||||
else
|
||||
merged.Add("tieLines", new JArray());
|
||||
//else if (system["tieLines"] != null)
|
||||
// merged.Add("tieLines", system["tieLines"]);
|
||||
//else
|
||||
// merged.Add("tieLines", new JArray());
|
||||
|
||||
//Debug.Console(0, "MERGED RESULT: \x0d\x0a{0}", merged);
|
||||
Debug.Console(2, "MERGED CONFIG RESULT: \x0d\x0a{0}", merged);
|
||||
return merged;
|
||||
}
|
||||
|
||||
@@ -133,7 +155,6 @@ namespace PepperDash.Essentials
|
||||
/// <param name="b"></param>
|
||||
static JObject Merge(JObject o1, JObject o2)
|
||||
{
|
||||
//Console.WriteLine("Merging {0}\ronto {1}", o2, o1);
|
||||
foreach (var o2Prop in o2)
|
||||
{
|
||||
var o1Value = o1[o2Prop.Key];
|
||||
@@ -152,6 +173,11 @@ namespace PepperDash.Essentials
|
||||
return o1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the group for a given device key in config
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetGroupForDeviceKey(string key)
|
||||
{
|
||||
var dev = ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
@@ -16,16 +16,21 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
public class EssentialsConfig : BasicConfig
|
||||
{
|
||||
[JsonProperty("system_url")]
|
||||
public string SystemUrl { get; set; }
|
||||
|
||||
[JsonProperty("template_url")]
|
||||
public string TemplateUrl { get; set; }
|
||||
|
||||
public CotijaConfig Cotija { get; private set; }
|
||||
|
||||
public string SystemUuid
|
||||
//public CotijaConfig Cotija { get; private set; }
|
||||
|
||||
[JsonProperty("systemUuid")]
|
||||
public string SystemUuid
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/templates\/(.*)#.*");
|
||||
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/#.*");
|
||||
|
||||
string uuid = result.Groups[1].Value;
|
||||
|
||||
@@ -33,11 +38,12 @@ namespace PepperDash.Essentials
|
||||
}
|
||||
}
|
||||
|
||||
public string TemplateUuid
|
||||
[JsonProperty("templateUuid")]
|
||||
public string TemplateUuid
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/templates\/(.*)#.*");
|
||||
var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/templates\/(.*)\/#.*");
|
||||
|
||||
string uuid = result.Groups[1].Value;
|
||||
|
||||
@@ -46,9 +52,9 @@ namespace PepperDash.Essentials
|
||||
}
|
||||
|
||||
[JsonProperty("rooms")]
|
||||
public List<EssentialsRoomConfig> Rooms { get; private set; }
|
||||
public List<EssentialsRoomConfig> Rooms { get; set; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
@@ -57,7 +63,5 @@ namespace PepperDash.Essentials
|
||||
public EssentialsConfig System { get; set; }
|
||||
|
||||
public EssentialsConfig Template { get; set; }
|
||||
|
||||
//public CotijaConfig Cotija { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace PepperDash.Essentials
|
||||
{
|
||||
public static class FactoryHelper
|
||||
{
|
||||
public static string IrDriverPathPrefix = @"\NVRAM\IR\";
|
||||
public static string IrDriverPathPrefix = Global.FilePathPrefix + "IR" + Global.DirectorySeparator;
|
||||
|
||||
public static void HandleUnknownType(JToken devToken, string type)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.CrestronThread;
|
||||
using PepperDash.Core;
|
||||
@@ -9,6 +10,7 @@ using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common;
|
||||
using PepperDash.Essentials.DM;
|
||||
using PepperDash.Essentials.Fusion;
|
||||
using PepperDash.Essentials.Room.Cotija;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
@@ -30,10 +32,11 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
public override void InitializeSystem()
|
||||
{
|
||||
//CrestronConsole.AddNewConsoleCommand(s => GoWithLoad(), "go", "Reloads configuration file",
|
||||
// ConsoleAccessLevelEnum.AccessOperator);
|
||||
//CrestronConsole.AddNewConsoleCommand(s => TearDown(), "ungo", "Unloads configuration file",
|
||||
DeterminePlatform();
|
||||
|
||||
//CrestronConsole.AddNewConsoleCommand(s => GoWithLoad(), "go", "Loads configuration file",
|
||||
// ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(s =>
|
||||
{
|
||||
foreach (var tl in TieLineCollection.Default)
|
||||
@@ -41,41 +44,129 @@ namespace PepperDash.Essentials
|
||||
},
|
||||
"listtielines", "Prints out all tie lines", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(s =>
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse
|
||||
("Current running configuration. This is the merged system and template configuration");
|
||||
CrestronConsole.ConsoleCommandResponse(Newtonsoft.Json.JsonConvert.SerializeObject
|
||||
(ConfigReader.ConfigObject, Newtonsoft.Json.Formatting.Indented));
|
||||
}, "showconfig", "Shows the current running merged config", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(s =>
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("This system can be found at the following URLs:\r" +
|
||||
"System URL: {0}\r" +
|
||||
"Template URL: {1}", ConfigReader.ConfigObject.SystemUrl, ConfigReader.ConfigObject.TemplateUrl);
|
||||
}, "portalinfo", "Shows portal URLS from configuration", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
GoWithLoad();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the program is running on a processor (appliance) or server (XiO Edge).
|
||||
///
|
||||
/// Sets Global.FilePathPrefix based on platform
|
||||
/// </summary>
|
||||
public void DeterminePlatform()
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Determining Platform....");
|
||||
|
||||
string filePathPrefix;
|
||||
|
||||
var dirSeparator = Global.DirectorySeparator;
|
||||
|
||||
var version = Crestron.SimplSharp.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
||||
|
||||
var versionString = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
|
||||
|
||||
string directoryPrefix;
|
||||
|
||||
//directoryPrefix = Crestron.SimplSharp.CrestronIO.Directory.GetApplicationRootDirectory();
|
||||
#warning ^ For use with beta Include4.dat for XiO Edge
|
||||
directoryPrefix = "";
|
||||
|
||||
if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server)
|
||||
{
|
||||
filePathPrefix = directoryPrefix + dirSeparator + "NVRAM"
|
||||
+ dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator;
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on 3-series Appliance", versionString);
|
||||
}
|
||||
else
|
||||
{
|
||||
filePathPrefix = directoryPrefix + dirSeparator + "User" + dirSeparator;
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on XiO Edge Server", versionString);
|
||||
}
|
||||
|
||||
Global.SetFilePathPrefix(filePathPrefix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Do it, yo
|
||||
/// </summary>
|
||||
public void GoWithLoad()
|
||||
{
|
||||
// var thread = new Thread(o =>
|
||||
// {
|
||||
try
|
||||
try
|
||||
{
|
||||
CrestronConsole.AddNewConsoleCommand(EnablePortalSync, "portalsync", "Loads Portal Sync",
|
||||
ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
//PortalSync = new PepperDashPortalSyncClient();
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials load from configuration");
|
||||
|
||||
var filesReady = SetupFilesystem();
|
||||
if (filesReady)
|
||||
{
|
||||
CrestronConsole.AddNewConsoleCommand(EnablePortalSync, "portalsync", "Loads Portal Sync",
|
||||
ConsoleAccessLevelEnum.AccessOperator);
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Folder structure verified. Loading config...");
|
||||
if (!ConfigReader.LoadConfig2())
|
||||
return;
|
||||
|
||||
//PortalSync = new PepperDashPortalSyncClient();
|
||||
|
||||
Debug.Console(0, "Starting Essentials load from configuration");
|
||||
ConfigReader.LoadConfig2();
|
||||
LoadDevices();
|
||||
LoadTieLines();
|
||||
LoadRooms();
|
||||
|
||||
LogoServer = new HttpLogoServer(8080, @"\html\logo");
|
||||
|
||||
DeviceManager.ActivateAll();
|
||||
Debug.Console(0, "Essentials load complete\r" +
|
||||
"-------------------------------------------------------------");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, "FATAL INITIALIZE ERROR. System is in an inconsistent state:\r{0}", e);
|
||||
Load();
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Essentials load complete\r" +
|
||||
"-------------------------------------------------------------");
|
||||
}
|
||||
// return null;
|
||||
// }, null);
|
||||
else
|
||||
{
|
||||
Debug.Console(0,
|
||||
"------------------------------------------------\r" +
|
||||
"------------------------------------------------\r" +
|
||||
"------------------------------------------------\r" +
|
||||
"Essentials file structure setup completed.\r" +
|
||||
"Please load config, sgd and ir files and\r" +
|
||||
"restart program.\r" +
|
||||
"------------------------------------------------\r" +
|
||||
"------------------------------------------------\r" +
|
||||
"------------------------------------------------");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, "FATAL INITIALIZE ERROR. System is in an inconsistent state:\r{0}", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies filesystem is set up. IR, SGD, and program1 folders
|
||||
/// </summary>
|
||||
bool SetupFilesystem()
|
||||
{
|
||||
Debug.Console(0, "Verifying and/or creating folder structure");
|
||||
var configDir = Global.FilePathPrefix;
|
||||
var configExists = Directory.Exists(configDir);
|
||||
if (!configExists)
|
||||
Directory.Create(configDir);
|
||||
|
||||
var irDir = Global.FilePathPrefix + "ir";
|
||||
if (!Directory.Exists(irDir))
|
||||
Directory.Create(irDir);
|
||||
|
||||
var sgdDir = Global.FilePathPrefix + "sgd";
|
||||
if (!Directory.Exists(sgdDir))
|
||||
Directory.Create(sgdDir);
|
||||
|
||||
return configExists;
|
||||
}
|
||||
|
||||
public void EnablePortalSync(string s)
|
||||
@@ -100,6 +191,19 @@ namespace PepperDash.Essentials
|
||||
Debug.Console(0, "Tear down COMPLETE");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void Load()
|
||||
{
|
||||
LoadDevices();
|
||||
LoadTieLines();
|
||||
LoadRooms();
|
||||
LoadLogoServer();
|
||||
|
||||
DeviceManager.ActivateAll();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads all devices from config and adds them to DeviceManager
|
||||
@@ -108,53 +212,37 @@ namespace PepperDash.Essentials
|
||||
{
|
||||
foreach (var devConf in ConfigReader.ConfigObject.Devices)
|
||||
{
|
||||
Debug.Console(0, "Creating device '{0}'", devConf.Key);
|
||||
// Skip this to prevent unnecessary warnings
|
||||
if (devConf.Key == "processor")
|
||||
continue;
|
||||
|
||||
// Try local factory first
|
||||
var newDev = DeviceFactory.GetDevice(devConf);
|
||||
|
||||
// Then associated library factories
|
||||
if (newDev == null)
|
||||
newDev = PepperDash.Essentials.Devices.Common.DeviceFactory.GetDevice(devConf);
|
||||
if (newDev == null)
|
||||
newDev = PepperDash.Essentials.DM.DeviceFactory.GetDevice(devConf);
|
||||
if (newDev == null)
|
||||
newDev = PepperDash.Essentials.Devices.Displays.DisplayDeviceFactory.GetDevice(devConf);
|
||||
try
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Creating device '{0}'", devConf.Key);
|
||||
// Skip this to prevent unnecessary warnings
|
||||
if (devConf.Key == "processor")
|
||||
continue;
|
||||
|
||||
if (newDev != null)
|
||||
DeviceManager.AddDevice(newDev);
|
||||
else
|
||||
Debug.Console(0, "WARNING: Cannot load unknown device type '{0}', key '{1}'.", devConf.Type, devConf.Key);
|
||||
// Try local factory first
|
||||
var newDev = DeviceFactory.GetDevice(devConf);
|
||||
|
||||
// Then associated library factories
|
||||
if (newDev == null)
|
||||
newDev = PepperDash.Essentials.Devices.Common.DeviceFactory.GetDevice(devConf);
|
||||
if (newDev == null)
|
||||
newDev = PepperDash.Essentials.DM.DeviceFactory.GetDevice(devConf);
|
||||
if (newDev == null)
|
||||
newDev = PepperDash.Essentials.Devices.Displays.DisplayDeviceFactory.GetDevice(devConf);
|
||||
|
||||
if (newDev != null)
|
||||
DeviceManager.AddDevice(newDev);
|
||||
else
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "ERROR: Cannot load unknown device type '{0}', key '{1}'.", devConf.Type, devConf.Key);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "ERROR: Creating device {0}. Skipping device. \r{1}", devConf.Key, e);
|
||||
}
|
||||
}
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Devices Loaded.");
|
||||
|
||||
// CODEC TESTING
|
||||
/*
|
||||
try
|
||||
{
|
||||
GenericSshClient TestCodecClient = new GenericSshClient("TestCodec-1--SshClient", "10.11.50.135", 22, "crestron", "2H3Zu&OvgXp6");
|
||||
|
||||
var props = new PepperDash.Essentials.Devices.Common.Codec.CiscoCodecPropertiesConfig();
|
||||
|
||||
props.PhonebookMode = "Local";
|
||||
props.Favorites = new System.Collections.Generic.List<PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem>();
|
||||
props.Favorites.Add(new PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem() { Name = "NYU Cisco Webex", Number = "10.11.50.211" });
|
||||
|
||||
PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CiscoCodec TestCodec =
|
||||
new PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.CiscoCodec("TestCodec-1", "Cisco Spark Room Kit", TestCodecClient, props);
|
||||
|
||||
TestCodec.CommDebuggingIsOn = true;
|
||||
|
||||
TestCodec.CustomActivate();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, "Error in something Neil is working on ;) \r{0}", e);
|
||||
}
|
||||
*/
|
||||
// CODEC TESTING
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -167,12 +255,20 @@ namespace PepperDash.Essentials
|
||||
|
||||
var tlc = TieLineCollection.Default;
|
||||
//tlc.Clear();
|
||||
if (ConfigReader.ConfigObject.TieLines == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var tieLineConfig in ConfigReader.ConfigObject.TieLines)
|
||||
{
|
||||
var newTL = tieLineConfig.GetTieLine();
|
||||
if (newTL != null)
|
||||
tlc.Add(newTL);
|
||||
}
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Tie Lines Loaded.");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -180,6 +276,12 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
public void LoadRooms()
|
||||
{
|
||||
if (ConfigReader.ConfigObject.Rooms == null)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Warning, "WARNING: Configuration contains no rooms");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var roomConfig in ConfigReader.ConfigObject.Rooms)
|
||||
{
|
||||
var room = roomConfig.GetRoomObject();
|
||||
@@ -189,32 +291,71 @@ namespace PepperDash.Essentials
|
||||
{
|
||||
DeviceManager.AddDevice(room);
|
||||
|
||||
Debug.Console(1, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion");
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion");
|
||||
DeviceManager.AddDevice(new EssentialsHuddleSpaceFusionSystemControllerBase((EssentialsHuddleSpaceRoom)room, 0xf1));
|
||||
|
||||
var cotija = DeviceManager.GetDeviceForKey("cotijaServer") as CotijaSystemController;
|
||||
|
||||
if (cotija != null)
|
||||
{
|
||||
cotija.CotijaRooms.Add(new CotijaEssentialsHuddleSpaceRoomBridge(cotija, room as EssentialsHuddleSpaceRoom));
|
||||
}
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Cotija Bridge...");
|
||||
// Cotija bridge
|
||||
var bridge = new CotijaEssentialsHuddleSpaceRoomBridge(room as EssentialsHuddleSpaceRoom);
|
||||
AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present
|
||||
DeviceManager.AddDevice(bridge);
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Cotija Bridge Added...");
|
||||
}
|
||||
else if (room is EssentialsHuddleVtc1Room)
|
||||
{
|
||||
DeviceManager.AddDevice(room);
|
||||
|
||||
Debug.Console(1, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion");
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion");
|
||||
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, 0xf1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(1, "Room is NOT EssentialsHuddleSpaceRoom, attempting to add to DeviceManager w/o Fusion");
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is NOT EssentialsHuddleSpaceRoom, attempting to add to DeviceManager w/o Fusion");
|
||||
DeviceManager.AddDevice(room);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
Debug.Console(0, "WARNING: Cannot create room from config, key '{0}'", roomConfig.Key);
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create room from config, key '{0}'", roomConfig.Key);
|
||||
}
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Rooms Loaded.");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helps add the post activation steps that link bridges to main controller
|
||||
/// </summary>
|
||||
/// <param name="bridge"></param>
|
||||
void AddBridgePostActivationHelper(CotijaBridgeBase bridge)
|
||||
{
|
||||
bridge.AddPostActivationAction(() =>
|
||||
{
|
||||
var parent = DeviceManager.AllDevices.FirstOrDefault(d => d.Key == "appServer") as CotijaSystemController;
|
||||
if (parent == null)
|
||||
{
|
||||
Debug.Console(0, bridge, "ERROR: Cannot connect bridge. System controller not present");
|
||||
}
|
||||
Debug.Console(0, bridge, "Linking to parent controller");
|
||||
bridge.AddParent(parent);
|
||||
parent.AddBridge(bridge);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires up a logo server if not already running
|
||||
/// </summary>
|
||||
void LoadLogoServer()
|
||||
{
|
||||
try
|
||||
{
|
||||
LogoServer = new HttpLogoServer(8080, Global.FilePathPrefix + "html" + Global.DirectorySeparator + "logo");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "NOTICE: Logo server cannot be started. Likely already running in another program");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
367
Essentials/PepperDashEssentials/ControlSystem.cs.orig
Normal file
367
Essentials/PepperDashEssentials/ControlSystem.cs.orig
Normal file
@@ -0,0 +1,367 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.CrestronThread;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Core.PortalSync;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common;
|
||||
using PepperDash.Essentials.DM;
|
||||
using PepperDash.Essentials.Fusion;
|
||||
using PepperDash.Essentials.Room.Cotija;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class ControlSystem : CrestronControlSystem
|
||||
{
|
||||
PepperDashPortalSyncClient PortalSync;
|
||||
HttpLogoServer LogoServer;
|
||||
|
||||
public ControlSystem()
|
||||
: base()
|
||||
{
|
||||
Thread.MaxNumberOfUserThreads = 400;
|
||||
Global.ControlSystem = this;
|
||||
DeviceManager.Initialize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Git 'er goin'
|
||||
/// </summary>
|
||||
public override void InitializeSystem()
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
DeterminePlatform();
|
||||
|
||||
//CrestronConsole.AddNewConsoleCommand(s => GoWithLoad(), "go", "Loads configuration file",
|
||||
// ConsoleAccessLevelEnum.AccessOperator);
|
||||
=======
|
||||
CrestronConsole.AddNewConsoleCommand(s => GoWithLoad(), "go", "Loads configuration file",
|
||||
ConsoleAccessLevelEnum.AccessOperator);
|
||||
>>>>>>> 600b9f11ff1bbc186f7c2a2945955731b3523b3c
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(s =>
|
||||
{
|
||||
foreach (var tl in TieLineCollection.Default)
|
||||
CrestronConsole.ConsoleCommandResponse(" {0}\r", tl);
|
||||
},
|
||||
"listtielines", "Prints out all tie lines", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(s =>
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse
|
||||
("Current running configuration. This is the merged system and template configuration");
|
||||
CrestronConsole.ConsoleCommandResponse(Newtonsoft.Json.JsonConvert.SerializeObject
|
||||
(ConfigReader.ConfigObject, Newtonsoft.Json.Formatting.Indented));
|
||||
}, "showconfig", "Shows the current running merged config", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(s =>
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("This system can be found at the following URLs:\r" +
|
||||
"System URL: {0}\r" +
|
||||
"Template URL: {1}", ConfigReader.ConfigObject.SystemUrl, ConfigReader.ConfigObject.TemplateUrl);
|
||||
}, "portalinfo", "Shows portal URLS from configuration", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
//GoWithLoad();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the program is running on a processor (appliance) or server (XiO Edge).
|
||||
///
|
||||
/// Sets Global.FilePathPrefix based on platform
|
||||
/// </summary>
|
||||
public void DeterminePlatform()
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Determining Platform....");
|
||||
|
||||
string filePathPrefix;
|
||||
|
||||
var dirSeparator = Global.DirectorySeparator;
|
||||
|
||||
var version = Crestron.SimplSharp.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
||||
|
||||
var versionString = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
|
||||
|
||||
string directoryPrefix;
|
||||
|
||||
//directoryPrefix = Crestron.SimplSharp.CrestronIO.Directory.GetApplicationRootDirectory();
|
||||
#warning ^ For use with beta Include4.dat for XiO Edge
|
||||
directoryPrefix = "";
|
||||
|
||||
if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server)
|
||||
{
|
||||
filePathPrefix = directoryPrefix + dirSeparator + "NVRAM"
|
||||
+ dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator;
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on 3-series Appliance", versionString);
|
||||
}
|
||||
else
|
||||
{
|
||||
filePathPrefix = directoryPrefix + dirSeparator + "User" + dirSeparator;
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on XiO Edge Server", versionString);
|
||||
}
|
||||
|
||||
Global.SetFilePathPrefix(filePathPrefix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Do it, yo
|
||||
/// </summary>
|
||||
public void GoWithLoad()
|
||||
{
|
||||
try
|
||||
{
|
||||
CrestronConsole.AddNewConsoleCommand(EnablePortalSync, "portalsync", "Loads Portal Sync",
|
||||
ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
//PortalSync = new PepperDashPortalSyncClient();
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials load from configuration");
|
||||
|
||||
var filesReady = SetupFilesystem();
|
||||
if (filesReady)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Folder structure verified. Loading config...");
|
||||
if (!ConfigReader.LoadConfig2())
|
||||
return;
|
||||
|
||||
Load();
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Essentials load complete\r" +
|
||||
"-------------------------------------------------------------");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(0,
|
||||
"------------------------------------------------\r" +
|
||||
"------------------------------------------------\r" +
|
||||
"------------------------------------------------\r" +
|
||||
"Essentials file structure setup completed.\r" +
|
||||
"Please load config, sgd and ir files and\r" +
|
||||
"restart program.\r" +
|
||||
"------------------------------------------------\r" +
|
||||
"------------------------------------------------\r" +
|
||||
"------------------------------------------------");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, "FATAL INITIALIZE ERROR. System is in an inconsistent state:\r{0}", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies filesystem is set up. IR, SGD, and program1 folders
|
||||
/// </summary>
|
||||
bool SetupFilesystem()
|
||||
{
|
||||
Debug.Console(0, "Verifying and/or creating folder structure");
|
||||
var configDir = Global.FilePathPrefix;
|
||||
var configExists = Directory.Exists(configDir);
|
||||
if (!configExists)
|
||||
Directory.Create(configDir);
|
||||
|
||||
var irDir = Global.FilePathPrefix + "ir";
|
||||
if (!Directory.Exists(irDir))
|
||||
Directory.Create(irDir);
|
||||
|
||||
var sgdDir = Global.FilePathPrefix + "sgd";
|
||||
if (!Directory.Exists(sgdDir))
|
||||
Directory.Create(sgdDir);
|
||||
|
||||
return configExists;
|
||||
}
|
||||
|
||||
public void EnablePortalSync(string s)
|
||||
{
|
||||
if (s.ToLower() == "enable")
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Portal Sync features enabled");
|
||||
PortalSync = new PepperDashPortalSyncClient();
|
||||
}
|
||||
}
|
||||
|
||||
public void TearDown()
|
||||
{
|
||||
Debug.Console(0, "Tearing down existing system");
|
||||
DeviceManager.DeactivateAll();
|
||||
|
||||
TieLineCollection.Default.Clear();
|
||||
|
||||
foreach (var key in DeviceManager.GetDevices())
|
||||
DeviceManager.RemoveDevice(key);
|
||||
|
||||
Debug.Console(0, "Tear down COMPLETE");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void Load()
|
||||
{
|
||||
LoadDevices();
|
||||
LoadTieLines();
|
||||
LoadRooms();
|
||||
LoadLogoServer();
|
||||
|
||||
DeviceManager.ActivateAll();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads all devices from config and adds them to DeviceManager
|
||||
/// </summary>
|
||||
public void LoadDevices()
|
||||
{
|
||||
foreach (var devConf in ConfigReader.ConfigObject.Devices)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Creating device '{0}'", devConf.Key);
|
||||
// Skip this to prevent unnecessary warnings
|
||||
if (devConf.Key == "processor")
|
||||
continue;
|
||||
|
||||
// Try local factory first
|
||||
var newDev = DeviceFactory.GetDevice(devConf);
|
||||
|
||||
// Then associated library factories
|
||||
if (newDev == null)
|
||||
newDev = PepperDash.Essentials.Devices.Common.DeviceFactory.GetDevice(devConf);
|
||||
if (newDev == null)
|
||||
newDev = PepperDash.Essentials.DM.DeviceFactory.GetDevice(devConf);
|
||||
if (newDev == null)
|
||||
newDev = PepperDash.Essentials.Devices.Displays.DisplayDeviceFactory.GetDevice(devConf);
|
||||
|
||||
if (newDev != null)
|
||||
DeviceManager.AddDevice(newDev);
|
||||
else
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "ERROR: Cannot load unknown device type '{0}', key '{1}'.", devConf.Type, devConf.Key);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "ERROR: Creating device {0}. Skipping device. \r{1}", devConf.Key, e);
|
||||
}
|
||||
}
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Devices Loaded.");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to load tie lines. This should run after devices have loaded
|
||||
/// </summary>
|
||||
public void LoadTieLines()
|
||||
{
|
||||
// In the future, we can't necessarily just clear here because devices
|
||||
// might be making their own internal sources/tie lines
|
||||
|
||||
var tlc = TieLineCollection.Default;
|
||||
//tlc.Clear();
|
||||
if (ConfigReader.ConfigObject.TieLines == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var tieLineConfig in ConfigReader.ConfigObject.TieLines)
|
||||
{
|
||||
var newTL = tieLineConfig.GetTieLine();
|
||||
if (newTL != null)
|
||||
tlc.Add(newTL);
|
||||
}
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Tie Lines Loaded.");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads all rooms from config and adds them to DeviceManager
|
||||
/// </summary>
|
||||
public void LoadRooms()
|
||||
{
|
||||
if (ConfigReader.ConfigObject.Rooms == null)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Warning, "WARNING: Configuration contains no rooms");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var roomConfig in ConfigReader.ConfigObject.Rooms)
|
||||
{
|
||||
var room = roomConfig.GetRoomObject();
|
||||
if (room != null)
|
||||
{
|
||||
if (room is EssentialsHuddleSpaceRoom)
|
||||
{
|
||||
DeviceManager.AddDevice(room);
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion");
|
||||
DeviceManager.AddDevice(new EssentialsHuddleSpaceFusionSystemControllerBase((EssentialsHuddleSpaceRoom)room, 0xf1));
|
||||
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Cotija Bridge...");
|
||||
// Cotija bridge
|
||||
var bridge = new CotijaEssentialsHuddleSpaceRoomBridge(room as EssentialsHuddleSpaceRoom);
|
||||
AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present
|
||||
DeviceManager.AddDevice(bridge);
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Cotija Bridge Added...");
|
||||
}
|
||||
else if (room is EssentialsHuddleVtc1Room)
|
||||
{
|
||||
DeviceManager.AddDevice(room);
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion");
|
||||
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, 0xf1));
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is NOT EssentialsHuddleSpaceRoom, attempting to add to DeviceManager w/o Fusion");
|
||||
DeviceManager.AddDevice(room);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create room from config, key '{0}'", roomConfig.Key);
|
||||
}
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Rooms Loaded.");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helps add the post activation steps that link bridges to main controller
|
||||
/// </summary>
|
||||
/// <param name="bridge"></param>
|
||||
void AddBridgePostActivationHelper(CotijaBridgeBase bridge)
|
||||
{
|
||||
bridge.AddPostActivationAction(() =>
|
||||
{
|
||||
var parent = DeviceManager.AllDevices.FirstOrDefault(d => d.Key == "appServer") as CotijaSystemController;
|
||||
if (parent == null)
|
||||
{
|
||||
Debug.Console(0, bridge, "ERROR: Cannot connect bridge. System controller not present");
|
||||
}
|
||||
Debug.Console(0, bridge, "Linking to parent controller");
|
||||
bridge.AddParent(parent);
|
||||
parent.AddBridge(bridge);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires up a logo server if not already running
|
||||
/// </summary>
|
||||
void LoadLogoServer()
|
||||
{
|
||||
try
|
||||
{
|
||||
LogoServer = new HttpLogoServer(8080, Global.FilePathPrefix + "html" + Global.DirectorySeparator + "logo");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "NOTICE: Logo server cannot be started. Likely already running in another program");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharpPro;
|
||||
@@ -29,11 +30,7 @@ namespace PepperDash.Essentials
|
||||
}
|
||||
else if (dc.Group.ToLower() == "touchpanel") // typeName.StartsWith("tsw"))
|
||||
{
|
||||
var comm = CommFactory.GetControlPropertiesConfig(dc);
|
||||
|
||||
var props = JsonConvert.DeserializeObject<CrestronTouchpanelPropertiesConfig>(
|
||||
properties.ToString());
|
||||
return new EssentialsTouchpanelController(key, name, typeName, props, comm.IpIdInt);
|
||||
return UiDeviceFactory.GetUiDevice(dc);
|
||||
}
|
||||
|
||||
else if (typeName == "mockdisplay")
|
||||
@@ -62,13 +59,34 @@ namespace PepperDash.Essentials
|
||||
return new ConsoleCommMockDevice(key, name, props, comm);
|
||||
}
|
||||
|
||||
else if (typeName == "webserver")
|
||||
else if (typeName == "appserver")
|
||||
{
|
||||
var props = JsonConvert.DeserializeObject<CotijaConfig>(properties.ToString());
|
||||
return new CotijaSystemController(key, name, props);
|
||||
}
|
||||
|
||||
else if (typeName == "mobilecontrolbridge-ddvc01")
|
||||
{
|
||||
var comm = CommFactory.GetControlPropertiesConfig(dc);
|
||||
|
||||
var bridge = new PepperDash.Essentials.Room.Cotija.CotijaDdvc01RoomBridge(key, name, comm.IpIdInt);
|
||||
bridge.AddPreActivationAction(() =>
|
||||
{
|
||||
var parent = DeviceManager.AllDevices.FirstOrDefault(d => d.Key == "appServer") as CotijaSystemController;
|
||||
if (parent == null)
|
||||
{
|
||||
Debug.Console(0, bridge, "ERROR: Cannot connect bridge. System controller not present");
|
||||
}
|
||||
Debug.Console(0, bridge, "Linking to parent controller");
|
||||
bridge.AddParent(parent);
|
||||
parent.AddBridge(bridge);
|
||||
});
|
||||
|
||||
return bridge;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
162
Essentials/PepperDashEssentials/Factory/UiDeviceFactory.cs
Normal file
162
Essentials/PepperDashEssentials/Factory/UiDeviceFactory.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
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.UI;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
using PepperDash.Essentials.Core.PageManagers;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class UiDeviceFactory
|
||||
{
|
||||
public static IKeyed GetUiDevice(DeviceConfig config)
|
||||
{
|
||||
var comm = CommFactory.GetControlPropertiesConfig(config);
|
||||
|
||||
var props = JsonConvert.DeserializeObject<CrestronTouchpanelPropertiesConfig>(config.Properties.ToString());
|
||||
|
||||
EssentialsTouchpanelController panelController = new EssentialsTouchpanelController(config.Key, config.Name, config.Type, props, comm.IpIdInt);
|
||||
|
||||
panelController.AddPostActivationAction(() =>
|
||||
{
|
||||
var mainDriver = new EssentialsPanelMainInterfaceDriver(panelController.Panel, props);
|
||||
// Then the sub drivers
|
||||
|
||||
// spin up different room drivers depending on room type
|
||||
var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey);
|
||||
if (room is EssentialsHuddleSpaceRoom)
|
||||
{
|
||||
|
||||
// Header Driver
|
||||
Debug.Console(0, panelController, "Adding header driver");
|
||||
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, props);
|
||||
|
||||
// AV Driver
|
||||
Debug.Console(0, panelController, "Adding huddle space AV driver");
|
||||
var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, props);
|
||||
avDriver.CurrentRoom = room as EssentialsHuddleSpaceRoom;
|
||||
avDriver.DefaultRoomKey = props.DefaultRoomKey;
|
||||
mainDriver.AvDriver = avDriver;
|
||||
|
||||
// Environment Driver
|
||||
if (avDriver.CurrentRoom.Config.Environment != null && avDriver.CurrentRoom.Config.Environment.DeviceKeys.Count > 0)
|
||||
{
|
||||
Debug.Console(0, panelController, "Adding environment driver");
|
||||
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, props);
|
||||
|
||||
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.Config.Environment);
|
||||
}
|
||||
|
||||
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
|
||||
|
||||
panelController.LoadAndShowDriver(mainDriver); // This is a little convoluted.
|
||||
|
||||
if (panelController.Panel is TswFt5ButtonSystem)
|
||||
{
|
||||
var tsw = panelController.Panel as TswFt5ButtonSystem;
|
||||
// Wire up hard keys
|
||||
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
|
||||
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
|
||||
if(mainDriver.EnvironmentDriver != null)
|
||||
tsw.Lights.UserObject = new Action<bool>(b =>
|
||||
{
|
||||
if (!b)
|
||||
{
|
||||
//mainDriver.AvDriver.PopupInterlock.ShowInterlockedWithToggle(mainDriver.EnvironmentDriver.BackgroundSubpageJoin);
|
||||
mainDriver.EnvironmentDriver.Toggle();
|
||||
}
|
||||
});
|
||||
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
|
||||
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
|
||||
}
|
||||
}
|
||||
//else if (room is EssentialsPresentationRoom)
|
||||
//{
|
||||
// Debug.Console(0, panelController, "Adding presentation room driver");
|
||||
// var avDriver = new EssentialsPresentationPanelAvFunctionsDriver(mainDriver, props);
|
||||
// avDriver.CurrentRoom = room as EssentialsPresentationRoom;
|
||||
// avDriver.DefaultRoomKey = props.DefaultRoomKey;
|
||||
// mainDriver.AvDriver = avDriver ;
|
||||
// mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, props);
|
||||
// panelController.LoadAndShowDriver(mainDriver);
|
||||
|
||||
// if (panelController.Panel is TswFt5ButtonSystem)
|
||||
// {
|
||||
// var tsw = panelController.Panel as TswFt5ButtonSystem;
|
||||
// // Wire up hard keys
|
||||
// tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
|
||||
// //tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
|
||||
// tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
|
||||
// tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
|
||||
// }
|
||||
//}
|
||||
else if (room is EssentialsHuddleVtc1Room)
|
||||
{
|
||||
Debug.Console(0, panelController, "Adding huddle space VTC AV driver");
|
||||
|
||||
// Header Driver
|
||||
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, props);
|
||||
|
||||
// AV Driver
|
||||
var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, props);
|
||||
|
||||
var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(panelController.Panel, avDriver,
|
||||
(room as EssentialsHuddleVtc1Room).VideoCodec, mainDriver.HeaderDriver);
|
||||
avDriver.SetVideoCodecDriver(codecDriver);
|
||||
avDriver.CurrentRoom = room as EssentialsHuddleVtc1Room;
|
||||
avDriver.DefaultRoomKey = props.DefaultRoomKey;
|
||||
mainDriver.AvDriver = avDriver;
|
||||
|
||||
// Environment Driver
|
||||
if (avDriver.CurrentRoom.Config.Environment != null && avDriver.CurrentRoom.Config.Environment.DeviceKeys.Count > 0)
|
||||
{
|
||||
Debug.Console(0, panelController, "Adding environment driver");
|
||||
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, props);
|
||||
|
||||
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.Config.Environment);
|
||||
}
|
||||
|
||||
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
|
||||
|
||||
panelController.LoadAndShowDriver(mainDriver); // This is a little convoluted.
|
||||
|
||||
if (panelController.Panel is TswFt5ButtonSystem)
|
||||
{
|
||||
var tsw = panelController.Panel as TswFt5ButtonSystem;
|
||||
// Wire up hard keys
|
||||
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.EndMeetingPress(); });
|
||||
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
|
||||
if (mainDriver.EnvironmentDriver != null)
|
||||
tsw.Lights.UserObject = new Action<bool>(b =>
|
||||
{
|
||||
if (!b)
|
||||
{
|
||||
//mainDriver.AvDriver.PopupInterlock.ShowInterlockedWithToggle(mainDriver.EnvironmentDriver.BackgroundSubpageJoin);
|
||||
mainDriver.EnvironmentDriver.Toggle();
|
||||
}
|
||||
});
|
||||
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
|
||||
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(0, panelController, "ERROR: Cannot load AvFunctionsDriver for room '{0}'", props.DefaultRoomKey);
|
||||
}
|
||||
});
|
||||
|
||||
return panelController;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -97,6 +97,8 @@ namespace PepperDash.Essentials.Fusion
|
||||
|
||||
CTimer PushNotificationTimer = null;
|
||||
|
||||
CTimer DailyTimeRequestTimer = null;
|
||||
|
||||
// Default poll time is 5 min unless overridden by config value
|
||||
public long SchedulePollInterval = 300000;
|
||||
|
||||
@@ -126,52 +128,63 @@ namespace PepperDash.Essentials.Fusion
|
||||
: base(room.Key + "-fusion")
|
||||
{
|
||||
|
||||
Room = room;
|
||||
|
||||
IpId = ipId;
|
||||
|
||||
FusionStaticAssets = new Dictionary<int, FusionAsset>();
|
||||
|
||||
GUIDs = new FusionRoomGuids();
|
||||
|
||||
var mac = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0);
|
||||
|
||||
var slot = Global.ControlSystem.ProgramNumber;
|
||||
|
||||
string guidFilePath = string.Format(@"\NVRAM\Program{0}\{1}-FusionGuids.json", Global.ControlSystem.ProgramNumber, InitialParametersClass.ProgramIDTag);
|
||||
|
||||
GuidFileExists = File.Exists(guidFilePath);
|
||||
|
||||
if (GuidFileExists)
|
||||
try
|
||||
{
|
||||
ReadGuidFile(guidFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUIDs = new FusionRoomGuids(Room.Name, ipId, GUIDs.GenerateNewRoomGuid(slot, mac), FusionStaticAssets);
|
||||
}
|
||||
|
||||
CreateSymbolAndBasicSigs(IpId);
|
||||
SetUpSources();
|
||||
SetUpCommunitcationMonitors();
|
||||
SetUpDisplay();
|
||||
SetUpError();
|
||||
ExecuteCustomSteps();
|
||||
Room = room;
|
||||
|
||||
if(Room.RoomOccupancy != null)
|
||||
{
|
||||
if(Room.OccupancyStatusProviderIsRemote)
|
||||
SetUpRemoteOccupancy();
|
||||
IpId = ipId;
|
||||
|
||||
FusionStaticAssets = new Dictionary<int, FusionAsset>();
|
||||
|
||||
GUIDs = new FusionRoomGuids();
|
||||
|
||||
var mac = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0);
|
||||
|
||||
var slot = Global.ControlSystem.ProgramNumber;
|
||||
|
||||
string guidFilePath = Global.FilePathPrefix + string.Format(@"{0}-FusionGuids.json", InitialParametersClass.ProgramIDTag);
|
||||
|
||||
GuidFileExists = File.Exists(guidFilePath);
|
||||
|
||||
// Check if file exists
|
||||
if (!GuidFileExists)
|
||||
{
|
||||
// Does not exist. Create GUIDs
|
||||
GUIDs = new FusionRoomGuids(Room.Name, ipId, GUIDs.GenerateNewRoomGuid(slot, mac), FusionStaticAssets);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetUpLocalOccupancy();
|
||||
// Exists. Read GUIDs
|
||||
ReadGuidFile(guidFilePath);
|
||||
}
|
||||
|
||||
CreateSymbolAndBasicSigs(IpId);
|
||||
SetUpSources();
|
||||
SetUpCommunitcationMonitors();
|
||||
SetUpDisplay();
|
||||
SetUpError();
|
||||
ExecuteCustomSteps();
|
||||
|
||||
if (Room.RoomOccupancy != null)
|
||||
{
|
||||
if (Room.OccupancyStatusProviderIsRemote)
|
||||
SetUpRemoteOccupancy();
|
||||
else
|
||||
{
|
||||
SetUpLocalOccupancy();
|
||||
}
|
||||
}
|
||||
|
||||
// Make it so!
|
||||
FusionRVI.GenerateFileForAllFusionDevices();
|
||||
|
||||
GenerateGuidFile(guidFilePath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Error Building Fusion System Controller: {0}", e);
|
||||
}
|
||||
|
||||
// Make it so!
|
||||
FusionRVI.GenerateFileForAllFusionDevices();
|
||||
|
||||
GenerateGuidFile(guidFilePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -240,7 +253,7 @@ namespace PepperDash.Essentials.Fusion
|
||||
{
|
||||
if(string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
Debug.Console(0, this, "Error reading guid file. No path specified.");
|
||||
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Error reading guid file. No path specified.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -265,18 +278,18 @@ namespace PepperDash.Essentials.Fusion
|
||||
|
||||
}
|
||||
|
||||
Debug.Console(0, this, "Fusion Guids successfully read from file:");
|
||||
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Fusion Guids successfully read from file: {0}", filePath);
|
||||
|
||||
Debug.Console(1, this, "\nRoom Name: {0}\nIPID: {1:x}\n RoomGuid: {2}", Room.Name, IpId, RoomGuid);
|
||||
|
||||
foreach (KeyValuePair<int, FusionAsset> item in FusionStaticAssets)
|
||||
foreach (var item in FusionStaticAssets)
|
||||
{
|
||||
Debug.Console(1, this, "\nAsset Name: {0}\nAsset No: {1}\n Guid: {2}", item.Value.Name, item.Value.SlotNumber, item.Value.InstanceId);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, this, "Error reading guid file: {0}", e);
|
||||
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Error reading guid file: {0}", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -288,7 +301,7 @@ namespace PepperDash.Essentials.Fusion
|
||||
|
||||
protected virtual void CreateSymbolAndBasicSigs(uint ipId)
|
||||
{
|
||||
Debug.Console(1, this, "Creating Fusion Room symbol with GUID: {0}", RoomGuid);
|
||||
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating Fusion Room symbol with GUID: {0}", RoomGuid);
|
||||
|
||||
FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
|
||||
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();
|
||||
@@ -390,31 +403,20 @@ namespace PepperDash.Essentials.Fusion
|
||||
|
||||
protected void GetProcessorInfo()
|
||||
{
|
||||
//SystemName = FusionRoom.CreateOffsetStringSig(50, "Info - Processor - System Name", eSigIoMask.InputSigOnly);
|
||||
//Model = FusionRoom.CreateOffsetStringSig(51, "Info - Processor - Model", eSigIoMask.InputSigOnly);
|
||||
//SerialNumber = FusionRoom.CreateOffsetStringSig(52, "Info - Processor - Serial Number", eSigIoMask.InputSigOnly);
|
||||
//Uptime = FusionRoom.CreateOffsetStringSig(53, "Info - Processor - Uptime", eSigIoMask.InputSigOnly);
|
||||
|
||||
Firmware = FusionRoom.CreateOffsetStringSig(61, "Info - Processor - Firmware", eSigIoMask.InputSigOnly);
|
||||
|
||||
for (int i = 0; i < Global.ControlSystem.NumProgramsSupported; i++)
|
||||
if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server)
|
||||
{
|
||||
var join = 62 + i;
|
||||
var progNum = i + 1;
|
||||
Program[i] = FusionRoom.CreateOffsetStringSig((uint)join, string.Format("Info - Processor - Program {0}", progNum), eSigIoMask.InputSigOnly);
|
||||
for (int i = 0; i < Global.ControlSystem.NumProgramsSupported; i++)
|
||||
{
|
||||
var join = 62 + i;
|
||||
var progNum = i + 1;
|
||||
Program[i] = FusionRoom.CreateOffsetStringSig((uint)join, string.Format("Info - Processor - Program {0}", progNum), eSigIoMask.InputSigOnly);
|
||||
}
|
||||
}
|
||||
|
||||
Firmware.InputSig.StringValue = InitialParametersClass.FirmwareVersion;
|
||||
|
||||
//var programs = ProcessorProgReg.GetProcessorProgReg();
|
||||
|
||||
//for (int i = 1; i < Global.ControlSystem.NumProgramsSupported; i++)
|
||||
//{
|
||||
// var join = 62 + i;
|
||||
// var progNum = i + 1;
|
||||
// if (programs[i].Exists)
|
||||
// Program[i].InputSig.StringValue = programs[i].Name;
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
@@ -465,16 +467,35 @@ namespace PepperDash.Essentials.Fusion
|
||||
|
||||
|
||||
// Request current Fusion Server Time
|
||||
RequestLocalDateTime(null);
|
||||
|
||||
string timeRequestID = "TimeRequest";
|
||||
// Setup timer to request time daily
|
||||
if (DailyTimeRequestTimer != null && !DailyTimeRequestTimer.Disposed)
|
||||
{
|
||||
DailyTimeRequestTimer.Stop();
|
||||
DailyTimeRequestTimer.Dispose();
|
||||
}
|
||||
|
||||
string timeRequest = string.Format("<LocalTimeRequest><RequestID>{0}</RequestID></LocalTimeRequest>", timeRequestID);
|
||||
DailyTimeRequestTimer = new CTimer(RequestLocalDateTime, null, 86400000, 86400000);
|
||||
|
||||
FusionRoom.ExtenderFusionRoomDataReservedSigs.LocalDateTimeQuery.StringValue = timeRequest;
|
||||
DailyTimeRequestTimer.Reset(86400000, 86400000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Requests the local date and time from the Fusion Server
|
||||
/// </summary>
|
||||
/// <param name="callbackObject"></param>
|
||||
public void RequestLocalDateTime(object callbackObject)
|
||||
{
|
||||
string timeRequestID = "TimeRequest";
|
||||
|
||||
string timeRequest = string.Format("<LocalTimeRequest><RequestID>{0}</RequestID></LocalTimeRequest>", timeRequestID);
|
||||
|
||||
FusionRoom.ExtenderFusionRoomDataReservedSigs.LocalDateTimeQuery.StringValue = timeRequest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a room schedule request for this room for the next 24 hours.
|
||||
/// </summary>
|
||||
@@ -984,6 +1005,10 @@ namespace PepperDash.Essentials.Fusion
|
||||
/// </summary>
|
||||
void SetUpCommunitcationMonitors()
|
||||
{
|
||||
uint displayNum = 0;
|
||||
uint touchpanelNum = 0;
|
||||
uint xpanelNum = 0;
|
||||
|
||||
// Attach to all room's devices with monitors.
|
||||
//foreach (var dev in DeviceManager.Devices)
|
||||
foreach (var dev in DeviceManager.GetDevices())
|
||||
@@ -991,41 +1016,56 @@ namespace PepperDash.Essentials.Fusion
|
||||
if (!(dev is ICommunicationMonitor))
|
||||
continue;
|
||||
|
||||
var keyNum = ExtractNumberFromKey(dev.Key);
|
||||
if (keyNum == -1)
|
||||
{
|
||||
Debug.Console(1, this, "WARNING: Cannot link device '{0}' to numbered Fusion monitoring attributes",
|
||||
dev.Key);
|
||||
continue;
|
||||
}
|
||||
string attrName = null;
|
||||
uint attrNum = Convert.ToUInt32(keyNum);
|
||||
string attrName = null;
|
||||
uint attrNum = 1;
|
||||
|
||||
if (dev is EssentialsTouchpanelController)
|
||||
//var keyNum = ExtractNumberFromKey(dev.Key);
|
||||
//if (keyNum == -1)
|
||||
//{
|
||||
// Debug.Console(1, this, "WARNING: Cannot link device '{0}' to numbered Fusion monitoring attributes",
|
||||
// dev.Key);
|
||||
// continue;
|
||||
//}
|
||||
//uint attrNum = Convert.ToUInt32(keyNum);
|
||||
|
||||
// Check for UI devices
|
||||
var uiDev = dev as EssentialsTouchpanelController;
|
||||
if (uiDev != null)
|
||||
{
|
||||
if ((dev as EssentialsTouchpanelController).Panel is Crestron.SimplSharpPro.DeviceSupport.TswFt5Button)
|
||||
{
|
||||
if (attrNum > 10)
|
||||
continue;
|
||||
attrName = "Online - Touch Panel " + attrNum;
|
||||
attrNum += 150;
|
||||
}
|
||||
else if ((dev as EssentialsTouchpanelController).Panel is Crestron.SimplSharpPro.UI.XpanelForSmartGraphics)
|
||||
if (uiDev.Panel is Crestron.SimplSharpPro.UI.XpanelForSmartGraphics)
|
||||
{
|
||||
attrNum = attrNum + touchpanelNum;
|
||||
|
||||
if (attrNum > 10)
|
||||
continue;
|
||||
attrName = "Online - XPanel " + attrNum;
|
||||
attrNum += 160;
|
||||
|
||||
touchpanelNum++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
attrNum = attrNum + xpanelNum;
|
||||
|
||||
if (attrNum > 10)
|
||||
continue;
|
||||
attrName = "Online - Touch Panel " + attrNum;
|
||||
attrNum += 150;
|
||||
|
||||
xpanelNum++;
|
||||
}
|
||||
}
|
||||
|
||||
//else
|
||||
if (dev is DisplayBase)
|
||||
{
|
||||
attrNum = attrNum + displayNum;
|
||||
if (attrNum > 10)
|
||||
continue;
|
||||
attrName = "Online - Display " + attrNum;
|
||||
attrNum += 170;
|
||||
|
||||
displayNum++;
|
||||
}
|
||||
//else if (dev is DvdDeviceBase)
|
||||
//{
|
||||
@@ -1187,14 +1227,23 @@ namespace PepperDash.Essentials.Fusion
|
||||
{
|
||||
RoomIsOccupiedFeedback = new BoolFeedback(RoomIsOccupiedFeedbackFunc);
|
||||
|
||||
FusionRoom.FusionAssetStateChange += new FusionAssetStateEventHandler(FusionRoom_FusionAssetStateChange);
|
||||
|
||||
// Build Occupancy Asset?
|
||||
// Link sigs?
|
||||
|
||||
Room.SetRoomOccupancy(this);
|
||||
//Room.SetRoomOccupancy(this as IOccupancyStatusProvider, 0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void FusionRoom_FusionAssetStateChange(FusionBase device, FusionAssetStateEventArgs args)
|
||||
{
|
||||
if (args.EventId == FusionAssetEventId.RoomOccupiedReceivedEventId || args.EventId == FusionAssetEventId.RoomUnoccupiedReceivedEventId)
|
||||
RoomIsOccupiedFeedback.FireUpdate();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets up remote occupancy that will relay the occupancy status determined by local system devices to Fusion
|
||||
/// </summary>
|
||||
@@ -1235,7 +1284,7 @@ namespace PepperDash.Essentials.Fusion
|
||||
/// <returns>-1 if no number matched</returns>
|
||||
int ExtractNumberFromKey(string key)
|
||||
{
|
||||
var capture = System.Text.RegularExpressions.Regex.Match(key, @"\D+(\d+)");
|
||||
var capture = System.Text.RegularExpressions.Regex.Match(key, @"\b(\d+)");
|
||||
if (!capture.Success)
|
||||
return -1;
|
||||
else return Convert.ToInt32(capture.Groups[1].Value);
|
||||
|
||||
19857
Essentials/PepperDashEssentials/PepperDash Essentials TSW-760.sgd
Normal file
19857
Essentials/PepperDashEssentials/PepperDash Essentials TSW-760.sgd
Normal file
File diff suppressed because it is too large
Load Diff
20901
Essentials/PepperDashEssentials/PepperDash Essentials iPad.sgd
Normal file
20901
Essentials/PepperDashEssentials/PepperDash Essentials iPad.sgd
Normal file
File diff suppressed because it is too large
Load Diff
@@ -70,22 +70,14 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Essentials Devices Common, Version=1.0.0.18129, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\Essentials Devices Common\Essentials Devices Common\bin\Essentials Devices Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="PepperDashCorePortalSync, Version=1.0.0.27069, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\pepperdash-portal-sync\SspPortalSync\SspPortalSync\bin\PepperDashCorePortalSync.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PepperDash_Core, Version=1.0.1.26313, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="PepperDash_Core, Version=1.0.3.27452, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\PepperDash.Core\Pepperdash Core\Pepperdash Core\bin\PepperDash_Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PepperDash_Essentials_Core, Version=1.0.0.18243, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\Essentials Core\PepperDashEssentialsBase\bin\PepperDash_Essentials_Core.dll</HintPath>
|
||||
<HintPath>..\..\Release Package\PepperDash_Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PepperDash_Essentials_DM, Version=1.0.0.19343, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
@@ -107,6 +99,10 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe</HintPath>
|
||||
</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" />
|
||||
@@ -129,11 +125,12 @@
|
||||
<Compile Include="Configuration ORIGINAL\Factories\FactoryHelper.cs" />
|
||||
<Compile Include="Config\ConfigReader.cs" />
|
||||
<Compile Include="Config\EssentialsConfig.cs" />
|
||||
<Compile Include="Config\DeviceFactory.cs" />
|
||||
<Compile Include="Factory\DeviceFactory.cs" />
|
||||
<Compile Include="Devices\Amplifier.cs" />
|
||||
<Compile Include="Devices\DiscPlayer\OppoExtendedBdp.cs" />
|
||||
<Compile Include="Devices\NUMERIC AppleTV.cs" />
|
||||
<Compile Include="ControlSystem.cs" />
|
||||
<Compile Include="Factory\UiDeviceFactory.cs" />
|
||||
<Compile Include="OTHER\Fusion\EssentialsHuddleVtc1FusionController.cs" />
|
||||
<Compile Include="OTHER\Fusion\FusionEventHandlers.cs" />
|
||||
<Compile Include="OTHER\Fusion\FusionProcessorQueries.cs" />
|
||||
@@ -142,12 +139,17 @@
|
||||
<Compile Include="OTHER\Fusion\EssentialsHuddleSpaceFusionSystemControllerBase.cs" />
|
||||
<Compile Include="HttpApiHandler.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Room\Config\DDVC01RoomPropertiesConfig.cs" />
|
||||
<Compile Include="Room\Config\EssentialsPresentationPropertiesConfig.cs" />
|
||||
<Compile Include="Room\Config\EssentialsHuddleRoomPropertiesConfig.cs" />
|
||||
<Compile Include="Room\Config\EssentialsHuddleVtc1PropertiesConfig.cs" />
|
||||
<Compile Include="Room\Config\EssentialsRoomEmergencyConfig.cs" />
|
||||
<Compile Include="Room\Cotija\CotijaConfig.cs" />
|
||||
<Compile Include="Room\Cotija\CotijaRoomBridge.cs" />
|
||||
<Compile Include="Room\Cotija\CotijaDdvc01DeviceBridge.cs" />
|
||||
<Compile Include="Room\Cotija\Interfaces.cs" />
|
||||
<Compile Include="Room\Cotija\RoomBridges\CotijaBridgeBase.cs" />
|
||||
<Compile Include="Room\Cotija\RoomBridges\CotijaDdvc01RoomBridge.cs" />
|
||||
<Compile Include="Room\Cotija\RoomBridges\CotijaEssentialsHuddleSpaceRoomBridge.cs" />
|
||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IChannelExtensions.cs" />
|
||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IColorExtensions.cs" />
|
||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IDPadExtensions.cs" />
|
||||
@@ -167,6 +169,10 @@
|
||||
<Compile Include="FOR REFERENCE UI\PageControllers\PageControllerLargeSetTopBoxGeneric.cs" />
|
||||
<Compile Include="FOR REFERENCE UI\PageControllers\LargeTouchpanelControllerBase.cs" />
|
||||
<Compile Include="FOR REFERENCE UI\Panels\SmartGraphicsTouchpanelControllerBase.cs" />
|
||||
<Compile Include="UIDrivers\Environment Drivers\EssentialsLightingDriver.cs" />
|
||||
<Compile Include="UIDrivers\Environment Drivers\EssentialsEnvironmentDriver.cs" />
|
||||
<Compile Include="UIDrivers\Environment Drivers\EssentialsShadeDriver.cs" />
|
||||
<Compile Include="UIDrivers\Essentials\EssentialsHeaderDriver.cs" />
|
||||
<Compile Include="UIDrivers\SigInterlock.cs" />
|
||||
<Compile Include="UIDrivers\EssentialsHuddleVTC\EssentialsHuddlePresentationUiDriver.cs" />
|
||||
<Compile Include="UIDrivers\EssentialsHuddle\EssentialsHuddleTechPageDriver.cs" />
|
||||
@@ -200,6 +206,19 @@
|
||||
<Compile Include="UI\SubpageReferenceListSourceItem.cs" />
|
||||
<None Include="app.config" />
|
||||
<None Include="Properties\ControlSystem.cfg" />
|
||||
<EmbeddedResource Include="SGD\PepperDash Essentials iPad.sgd" />
|
||||
<EmbeddedResource Include="SGD\PepperDash Essentials TSW-560.sgd" />
|
||||
<EmbeddedResource Include="SGD\PepperDash Essentials TSW-760.sgd" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Essentials Core\PepperDashEssentialsBase\PepperDash_Essentials_Core.csproj">
|
||||
<Project>{A49AD6C8-FC0A-4CC0-9089-DFB4CF92D2B5}</Project>
|
||||
<Name>PepperDash_Essentials_Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Essentials Devices Common\Essentials Devices Common\Essentials Devices Common.csproj">
|
||||
<Project>{892B761C-E479-44CE-BD74-243E9214AF13}</Project>
|
||||
<Name>Essentials Devices Common</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CompactFramework.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
[assembly: AssemblyCompany("PepperDash Technology Corp")]
|
||||
[assembly: AssemblyProduct("PepperDashEssentials")]
|
||||
[assembly: AssemblyCopyright("Copyright © PepperDash Technology Corp 2017")]
|
||||
[assembly: AssemblyVersion("1.0.2.*")]
|
||||
[assembly: AssemblyVersion("1.2.0.*")]
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyTitle("PepperDashEssentials")]
|
||||
[assembly: AssemblyCompany("PepperDash Technology Corp")]
|
||||
[assembly: AssemblyProduct("PepperDashEssentials")]
|
||||
[assembly: AssemblyCopyright("Copyright © PepperDash Technology Corp 2017")]
|
||||
<<<<<<< HEAD
|
||||
[assembly: AssemblyVersion("1.1.8.*")]
|
||||
=======
|
||||
[assembly: AssemblyVersion("1.3.0.*")]
|
||||
|
||||
>>>>>>> feature/ecs-684
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ControlSystem>
|
||||
<Name>Desk MC3</Name>
|
||||
<Address>ssh 10.0.0.15</Address>
|
||||
<ProgramSlot>Program01</ProgramSlot>
|
||||
<Storage>Internal Flash</Storage>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ControlSystem>
|
||||
<Name>Test RMC3</Name>
|
||||
<Address>auto 192.168.1.40</Address>
|
||||
<ProgramSlot>Program01</ProgramSlot>
|
||||
<Storage>Internal Flash</Storage>
|
||||
</ControlSystem>
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Config
|
||||
{
|
||||
public class DDVC01RoomPropertiesConfig : EssentialsHuddleVtc1PropertiesConfig
|
||||
{
|
||||
[JsonProperty("roomPhoneNumber")]
|
||||
public string RoomPhoneNumber { get; set; }
|
||||
[JsonProperty("roomURI")]
|
||||
public string RoomURI { get; set; }
|
||||
[JsonProperty("speedDials")]
|
||||
public List<DDVC01SpeedDial> SpeedDials { get; set; }
|
||||
[JsonProperty("volumeSliderNames")]
|
||||
public List<string> VolumeSliderNames { get; set; }
|
||||
}
|
||||
|
||||
public class DDVC01SpeedDial
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("number")]
|
||||
public string Number { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -3,16 +3,22 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Config
|
||||
{
|
||||
|
||||
public class EssentialsHuddleVtc1PropertiesConfig : EssentialsRoomPropertiesConfig
|
||||
{
|
||||
public string DefaultDisplayKey { get; set; }
|
||||
public string DefaultAudioKey { get; set; }
|
||||
public string SourceListKey { get; set; }
|
||||
public string DefaultSourceItem { get; set; }
|
||||
public string VideoCodecKey { get; set; }
|
||||
[JsonProperty("defaultDisplayKey")]
|
||||
public string DefaultDisplayKey { get; set; }
|
||||
[JsonProperty("defaultAudioKey")]
|
||||
public string DefaultAudioKey { get; set; }
|
||||
[JsonProperty("sourceListKey")]
|
||||
public string SourceListKey { get; set; }
|
||||
[JsonProperty("defaultSourceItem")]
|
||||
public string DefaultSourceItem { get; set; }
|
||||
[JsonProperty("videoCodecKey")]
|
||||
public string VideoCodecKey { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,10 @@ namespace PepperDash.Essentials.Room.Config
|
||||
var disp = DeviceManager.GetDeviceForKey(props.DefaultDisplayKey) as IRoutingSinkWithSwitching;
|
||||
var audio = DeviceManager.GetDeviceForKey(props.DefaultAudioKey) as IRoutingSinkNoSwitching;
|
||||
var huddle = new EssentialsHuddleSpaceRoom(Key, Name, disp, audio, props);
|
||||
|
||||
if (props.Occupancy != null)
|
||||
huddle.SetRoomOccupancy(DeviceManager.GetDeviceForKey(props.Occupancy.DeviceKey) as
|
||||
PepperDash.Essentials.Devices.Common.Occupancy.IOccupancyStatusProvider, props.Occupancy.TimoutMinutes);
|
||||
huddle.LogoUrl = props.Logo.GetUrl();
|
||||
huddle.SourceListKey = props.SourceListKey;
|
||||
huddle.DefaultSourceItem = props.DefaultSourceItem;
|
||||
@@ -67,16 +71,23 @@ namespace PepperDash.Essentials.Room.Config
|
||||
// Add Occupancy object from config
|
||||
|
||||
if (props.Occupancy != null)
|
||||
rm.SetRoomOccupancy(DeviceManager.GetDeviceForKey(props.Occupancy.DeviceKey) as PepperDash.Essentials.Devices.Common.Occupancy.IOccupancyStatusProvider);
|
||||
rm.SetRoomOccupancy(DeviceManager.GetDeviceForKey(props.Occupancy.DeviceKey) as
|
||||
PepperDash.Essentials.Devices.Common.Occupancy.IOccupancyStatusProvider, props.Occupancy.TimoutMinutes);
|
||||
rm.LogoUrl = props.Logo.GetUrl();
|
||||
rm.SourceListKey = props.SourceListKey;
|
||||
rm.DefaultSourceItem = props.DefaultSourceItem;
|
||||
rm.DefaultVolume = (ushort)(props.Volumes.Master.Level * 65535 / 100);
|
||||
|
||||
rm.MicrophonePrivacy = GetMicrophonePrivacy(props, rm); // Get Microphone Privacy object, if any
|
||||
|
||||
rm.Emergency = GetEmergency(props, rm); // Get emergency object, if any
|
||||
|
||||
return rm;
|
||||
}
|
||||
else if (typeName == "ddvc01Bridge")
|
||||
{
|
||||
return new Device(Key, Name); // placeholder device that does nothing.
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -97,6 +108,70 @@ namespace PepperDash.Essentials.Room.Config
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="props"></param>
|
||||
/// <param name="room"></param>
|
||||
/// <returns></returns>
|
||||
PepperDash.Essentials.Devices.Common.Microphones.MicrophonePrivacyController GetMicrophonePrivacy(
|
||||
EssentialsRoomPropertiesConfig props, EssentialsHuddleVtc1Room room)
|
||||
{
|
||||
var microphonePrivacy = props.MicrophonePrivacy;
|
||||
if (microphonePrivacy == null)
|
||||
{
|
||||
Debug.Console(0, "ERROR: Cannot create microphone privacy with null properties");
|
||||
return null;
|
||||
}
|
||||
// Get the MicrophonePrivacy device from the device manager
|
||||
var mP = (DeviceManager.GetDeviceForKey(props.MicrophonePrivacy.DeviceKey) as
|
||||
PepperDash.Essentials.Devices.Common.Microphones.MicrophonePrivacyController);
|
||||
// Set this room as the IPrivacy device
|
||||
if (mP == null)
|
||||
{
|
||||
Debug.Console(0, "ERROR: Selected device {0} is not MicrophonePrivacyController", props.MicrophonePrivacy.DeviceKey);
|
||||
return null;
|
||||
}
|
||||
mP.SetPrivacyDevice(room);
|
||||
|
||||
var behaviour = props.MicrophonePrivacy.Behaviour.ToLower();
|
||||
|
||||
if (behaviour == null)
|
||||
{
|
||||
Debug.Console(0, "WARNING: No behaviour defined for MicrophonePrivacyController");
|
||||
return null;
|
||||
}
|
||||
if (behaviour == "trackroomstate")
|
||||
{
|
||||
// Tie LED enable to room power state
|
||||
room.OnFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
if (room.OnFeedback.BoolValue)
|
||||
mP.EnableLeds = true;
|
||||
else
|
||||
mP.EnableLeds = false;
|
||||
};
|
||||
|
||||
mP.EnableLeds = room.OnFeedback.BoolValue;
|
||||
}
|
||||
else if (behaviour == "trackcallstate")
|
||||
{
|
||||
// Tie LED enable to room power state
|
||||
room.InCallFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
if (room.InCallFeedback.BoolValue)
|
||||
mP.EnableLeds = true;
|
||||
else
|
||||
mP.EnableLeds = false;
|
||||
};
|
||||
|
||||
mP.EnableLeds = room.InCallFeedback.BoolValue;
|
||||
}
|
||||
|
||||
return mP;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -104,31 +179,91 @@ namespace PepperDash.Essentials.Room.Config
|
||||
/// </summary>
|
||||
public class EssentialsRoomPropertiesConfig
|
||||
{
|
||||
public EssentialsRoomEmergencyConfig Emergency { get; set; }
|
||||
[JsonProperty("addresses")]
|
||||
public EssentialsRoomAddressPropertiesConfig Addresses { get; set; }
|
||||
|
||||
[JsonProperty("description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
[JsonProperty("emergency")]
|
||||
public EssentialsRoomEmergencyConfig Emergency { get; set; }
|
||||
|
||||
[JsonProperty("help")]
|
||||
public EssentialsHelpPropertiesConfig Help { get; set; }
|
||||
|
||||
[JsonProperty("helpMessage")]
|
||||
public string HelpMessage { get; set; }
|
||||
public string Description { get; set; }
|
||||
public int ShutdownVacancySeconds { get; set; }
|
||||
public int ShutdownPromptSeconds { get; set; }
|
||||
public EssentialsHelpPropertiesConfig Help { get; set; }
|
||||
public EssentialsOneButtonMeetingPropertiesConfig OneButtonMeeting { get; set; }
|
||||
public EssentialsRoomAddressPropertiesConfig Addresses { get; set; }
|
||||
public EssentialsRoomOccSensorConfig Occupancy { get; set; }
|
||||
public EssentialsLogoPropertiesConfig Logo { get; set; }
|
||||
|
||||
[JsonProperty("environment")]
|
||||
public EssentialsEnvironmentPropertiesConfig Environment { get; set; }
|
||||
|
||||
[JsonProperty("logo")]
|
||||
public EssentialsLogoPropertiesConfig Logo { get; set; }
|
||||
|
||||
[JsonProperty("microphonePrivacy")]
|
||||
public EssentialsRoomMicrophonePrivacyConfig MicrophonePrivacy { get; set; }
|
||||
|
||||
[JsonProperty("occupancy")]
|
||||
public EssentialsRoomOccSensorConfig Occupancy { get; set; }
|
||||
|
||||
[JsonProperty("oneButtonMeeting")]
|
||||
public EssentialsOneButtonMeetingPropertiesConfig OneButtonMeeting { get; set; }
|
||||
|
||||
[JsonProperty("shutdownVacancySeconds")]
|
||||
public int ShutdownVacancySeconds { get; set; }
|
||||
|
||||
[JsonProperty("shutdownPromptSeconds")]
|
||||
public int ShutdownPromptSeconds { get; set; }
|
||||
|
||||
[JsonProperty("tech")]
|
||||
public EssentialsRoomTechConfig Tech { get; set; }
|
||||
public EssentialsRoomVolumesConfig Volumes { get; set; }
|
||||
|
||||
[JsonProperty("volumes")]
|
||||
public EssentialsRoomVolumesConfig Volumes { get; set; }
|
||||
|
||||
[JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")]
|
||||
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; }
|
||||
}
|
||||
|
||||
public class EssentialsEnvironmentPropertiesConfig
|
||||
{
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
[JsonProperty("deviceKeys")]
|
||||
public List<string> DeviceKeys { get; set; }
|
||||
|
||||
public EssentialsEnvironmentPropertiesConfig()
|
||||
{
|
||||
DeviceKeys = new List<string>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class EssentialsRoomMicrophonePrivacyConfig
|
||||
{
|
||||
[JsonProperty("deviceKey")]
|
||||
public string DeviceKey { get; set; }
|
||||
|
||||
[JsonProperty("behaviour")]
|
||||
public string Behaviour { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Properties for the help text box
|
||||
/// </summary>
|
||||
public class EssentialsHelpPropertiesConfig
|
||||
{
|
||||
public string Message { get; set; }
|
||||
public bool ShowCallButton { get; set; }
|
||||
/// <summary>
|
||||
[JsonProperty("message")]
|
||||
public string Message { get; set; }
|
||||
|
||||
[JsonProperty("showCallButton")]
|
||||
public bool ShowCallButton { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defaults to "Call Help Desk"
|
||||
/// </summary>
|
||||
public string CallButtonText { get; set; }
|
||||
[JsonProperty("callButtonText")]
|
||||
public string CallButtonText { get; set; }
|
||||
|
||||
public EssentialsHelpPropertiesConfig()
|
||||
{
|
||||
@@ -141,13 +276,17 @@ namespace PepperDash.Essentials.Room.Config
|
||||
/// </summary>
|
||||
public class EssentialsOneButtonMeetingPropertiesConfig
|
||||
{
|
||||
public bool Enable { get; set; }
|
||||
[JsonProperty("enable")]
|
||||
public bool Enable { get; set; }
|
||||
}
|
||||
|
||||
public class EssentialsRoomAddressPropertiesConfig
|
||||
{
|
||||
public string PhoneNumber { get; set; }
|
||||
public string SipAddress { get; set; }
|
||||
[JsonProperty("phoneNumber")]
|
||||
public string PhoneNumber { get; set; }
|
||||
|
||||
[JsonProperty("sipAddress")]
|
||||
public string SipAddress { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -156,8 +295,11 @@ namespace PepperDash.Essentials.Room.Config
|
||||
/// </summary>
|
||||
public class EssentialsLogoPropertiesConfig
|
||||
{
|
||||
public string Type { get; set; }
|
||||
public string Url { get; set; }
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
/// <summary>
|
||||
/// Gets either the custom URL, a local-to-processor URL, or null if it's a default logo
|
||||
/// </summary>
|
||||
@@ -177,12 +319,16 @@ namespace PepperDash.Essentials.Room.Config
|
||||
/// </summary>
|
||||
public class EssentialsRoomOccSensorConfig
|
||||
{
|
||||
public string DeviceKey { get; set; }
|
||||
[JsonProperty("deviceKey")]
|
||||
public string DeviceKey { get; set; }
|
||||
|
||||
[JsonProperty("timoutMinutes")]
|
||||
public int TimoutMinutes { get; set; }
|
||||
}
|
||||
|
||||
public class EssentialsRoomTechConfig
|
||||
{
|
||||
[JsonProperty("password")]
|
||||
public string Password { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,10 +5,29 @@ using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class CotijaConfig : DeviceConfig
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CotijaConfig
|
||||
{
|
||||
public string serverUrl { get; set; }
|
||||
[JsonProperty("serverUrl")]
|
||||
public string ServerUrl { get; set; }
|
||||
|
||||
[JsonProperty("clientAppUrl")]
|
||||
public string ClientAppUrl { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CotijaDdvc01RoomBridgePropertiesConfig
|
||||
{
|
||||
[JsonProperty("eiscId")]
|
||||
public string EiscId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro.EthernetCommunication;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Cotija
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a generic device connection through to and EISC for DDVC01
|
||||
/// </summary>
|
||||
public class CotijaDdvc01DeviceBridge : Device, IChannel, INumericKeypad
|
||||
{
|
||||
/// <summary>
|
||||
/// EISC used to talk to Simpl
|
||||
/// </summary>
|
||||
ThreeSeriesTcpIpEthernetIntersystemCommunications EISC;
|
||||
|
||||
public CotijaDdvc01DeviceBridge(string key, string name, ThreeSeriesTcpIpEthernetIntersystemCommunications eisc)
|
||||
: base(key, name)
|
||||
{
|
||||
EISC = eisc;
|
||||
}
|
||||
|
||||
|
||||
#region IChannel Members
|
||||
|
||||
public void ChannelUp(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void ChannelDown(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void LastChannel(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Guide(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Info(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Exit(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region INumericKeypad Members
|
||||
|
||||
public void Digit0(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit1(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit2(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit3(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit4(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit5(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit6(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit7(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit8(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit9(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public bool HasKeypadAccessoryButton1
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public string KeypadAccessoryButton1Label
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public void KeypadAccessoryButton1(bool pressRelease)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool HasKeypadAccessoryButton2
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public string KeypadAccessoryButton2Label
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public void KeypadAccessoryButton2(bool pressRelease)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -5,53 +5,83 @@ using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
using Crestron.SimplSharpPro.CrestronThread;
|
||||
using Crestron.SimplSharp.CrestronWebSocketClient;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharp.Net.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Room.Cotija;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class CotijaSystemController : Device
|
||||
{
|
||||
GenericHttpSseClient SseClient;
|
||||
WebSocketClient WSClient;
|
||||
|
||||
CCriticalSection FileLock;
|
||||
/// <summary>
|
||||
/// Prevents post operations from stomping on each other and getting lost
|
||||
/// </summary>
|
||||
CEvent PostLockEvent = new CEvent(true, true);
|
||||
|
||||
CotijaConfig Config;
|
||||
CEvent RegisterLockEvent = new CEvent(true, true);
|
||||
|
||||
HttpClient Client;
|
||||
public CotijaConfig Config { get; private set; }
|
||||
|
||||
Dictionary<string, Object> ActionDictionary = new Dictionary<string, Object>(StringComparer.InvariantCultureIgnoreCase);
|
||||
|
||||
Dictionary<string, CTimer> PushedActions = new Dictionary<string, CTimer>();
|
||||
|
||||
CTimer ServerHeartbeat;
|
||||
CTimer ServerHeartbeatCheckTimer;
|
||||
|
||||
long ServerHeartbeatInterval = 20000;
|
||||
|
||||
CTimer ServerReconnect;
|
||||
CTimer ServerReconnectTimer;
|
||||
|
||||
long ServerReconnectInterval = 5000;
|
||||
|
||||
string SystemUuid;
|
||||
|
||||
public List<CotijaEssentialsHuddleSpaceRoomBridge> CotijaRooms { get; private set; }
|
||||
List<CotijaBridgeBase> RoomBridges = new List<CotijaBridgeBase>();
|
||||
|
||||
long ButtonHeartbeatInterval = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// Used for tracking HTTP debugging
|
||||
/// </summary>
|
||||
bool HttpDebugEnabled;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="config"></param>
|
||||
public CotijaSystemController(string key, string name, CotijaConfig config) : base(key, name)
|
||||
{
|
||||
Config = config;
|
||||
Debug.Console(0, this, "Mobile UI controller initializing for server:{0}", config.ServerUrl);
|
||||
|
||||
CotijaRooms = new List<CotijaEssentialsHuddleSpaceRoomBridge>();
|
||||
CrestronConsole.AddNewConsoleCommand(AuthorizeSystem,
|
||||
"mobileauth", "Authorizes system to talk to cotija server", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => ShowInfo(),
|
||||
"mobileinfo", "Shows information for current mobile control session", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => {
|
||||
s = s.Trim();
|
||||
if(!string.IsNullOrEmpty(s))
|
||||
{
|
||||
HttpDebugEnabled = (s.Trim() != "0");
|
||||
}
|
||||
CrestronConsole.ConsoleCommandResponse("HTTP Debug {0}", HttpDebugEnabled ? "Enabled" : "Disabled");
|
||||
},
|
||||
"mobilehttpdebug", "1 enables more verbose HTTP response debugging", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(TestHttpRequest,
|
||||
"mobilehttprequest", "Tests an HTTP get to URL given", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(RegisterSystemToServer, "InitializeHttpClient", "Initializes a new HTTP client connection to a specified URL", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(DisconnectSseClient, "CloseHttpClient", "Closes the active HTTP client", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
AddPostActivationAction(() => RegisterSystemToServer(null));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -67,12 +97,12 @@ namespace PepperDash.Essentials
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "Cannot add action with key '{0}' because key already exists in ActionDictionary.");
|
||||
Debug.Console(1, this, "Cannot add action with key '{0}' because key already exists in ActionDictionary.", key);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes and action from the dictionary
|
||||
/// Removes an action from the dictionary
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
public void RemoveAction(string key)
|
||||
@@ -81,130 +111,226 @@ namespace PepperDash.Essentials
|
||||
ActionDictionary.Remove(key);
|
||||
}
|
||||
|
||||
void ReconnectToServer(object o)
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="bridge"></param>
|
||||
public void AddBridge(CotijaBridgeBase bridge)
|
||||
{
|
||||
RoomBridges.Add(bridge);
|
||||
var b = bridge as IDelayedConfiguration;
|
||||
if (b != null)
|
||||
{
|
||||
Debug.Console(0, this, "Adding room bridge with delayed configuration");
|
||||
b.ConfigurationIsReady += new EventHandler<EventArgs>(bridge_ConfigurationIsReady);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(0, this, "Adding room bridge and sending configuration");
|
||||
RegisterSystemToServer();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void bridge_ConfigurationIsReady(object sender, EventArgs e)
|
||||
{
|
||||
Debug.Console(1, this, "Bridge ready. Registering");
|
||||
// send the configuration object to the server
|
||||
RegisterSystemToServer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
void ReconnectToServerTimerCallback(object o)
|
||||
{
|
||||
RegisterSystemToServer(null);
|
||||
RegisterSystemToServer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies system connection with servers
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
void AuthorizeSystem(string code)
|
||||
{
|
||||
if (string.IsNullOrEmpty(code))
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Please enter a user code to authorize a system");
|
||||
return;
|
||||
}
|
||||
|
||||
var req = new HttpClientRequest();
|
||||
string url = string.Format("http://{0}/api/system/grantcode/{1}/{2}", Config.ServerUrl, code, SystemUuid);
|
||||
Debug.Console(0, this, "Authorizing to: {0}", url);
|
||||
|
||||
if (string.IsNullOrEmpty(Config.ServerUrl))
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Config URL address is not set. Check portal configuration");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
req.Url.Parse(url);
|
||||
new HttpClient().DispatchAsync(req, (r, e) =>
|
||||
{
|
||||
CheckHttpDebug(r, e);
|
||||
if (e == HTTP_CALLBACK_ERROR.COMPLETED)
|
||||
{
|
||||
if (r.Code == 200)
|
||||
{
|
||||
Debug.Console(0, "System authorized, sending config.");
|
||||
RegisterSystemToServer();
|
||||
}
|
||||
else if (r.Code == 404)
|
||||
{
|
||||
if (r.ContentString.Contains("codeNotFound"))
|
||||
{
|
||||
Debug.Console(0, "Authorization failed, code not found for system UUID {0}", SystemUuid);
|
||||
}
|
||||
else if (r.ContentString.Contains("uuidNotFound"))
|
||||
{
|
||||
Debug.Console(0, "Authorization failed, uuid {0} not found. Check Essentials configuration is correct",
|
||||
SystemUuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
Debug.Console(0, this, "Error {0} in authorizing system", e);
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, this, "Error in authorizing: {0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dumps info in response to console command.
|
||||
/// </summary>
|
||||
void ShowInfo()
|
||||
{
|
||||
var url = Config != null ? Config.ServerUrl : "No config";
|
||||
string name;
|
||||
string code;
|
||||
if (RoomBridges != null && RoomBridges.Count > 0)
|
||||
{
|
||||
name = RoomBridges[0].RoomName;
|
||||
code = RoomBridges[0].UserCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = "No config";
|
||||
code = "Not available";
|
||||
}
|
||||
var conn = WSClient == null ? "No client" : (WSClient.Connected ? "Yes" : "No");
|
||||
|
||||
CrestronConsole.ConsoleCommandResponse(@"Mobile Control Information:
|
||||
Server address: {0}
|
||||
System Name: {1}
|
||||
System UUID: {2}
|
||||
System User code: {3}
|
||||
Connected?: {4}", url, name, SystemUuid,
|
||||
code, conn);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers the room with the server
|
||||
/// </summary>
|
||||
/// <param name="url">URL of the server, including the port number, if not 80. Format: "serverUrlOrIp:port"</param>
|
||||
void RegisterSystemToServer(string command)
|
||||
void RegisterSystemToServer()
|
||||
{
|
||||
try
|
||||
var ready = RegisterLockEvent.Wait(20000);
|
||||
if (!ready)
|
||||
{
|
||||
Debug.Console(1, this, "RegisterSystemToServer failed to enter after 20 seconds. Ignoring");
|
||||
return;
|
||||
}
|
||||
RegisterLockEvent.Reset();
|
||||
|
||||
try
|
||||
{
|
||||
string filePath = string.Format(@"\NVRAM\Program{0}\configurationFile.json", Global.ControlSystem.ProgramNumber);
|
||||
string postBody = null;
|
||||
var confObject = ConfigReader.ConfigObject;
|
||||
confObject.Info.RuntimeInfo.AppName = Assembly.GetExecutingAssembly().GetName().Name;
|
||||
var version = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
confObject.Info.RuntimeInfo.AssemblyVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
|
||||
confObject.Info.RuntimeInfo.OsVersion = Crestron.SimplSharp.CrestronEnvironment.OSVersion.Firmware;
|
||||
|
||||
if (string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
Debug.Console(0, this, "Error reading file. No path specified.");
|
||||
return;
|
||||
}
|
||||
|
||||
FileLock = new CCriticalSection();
|
||||
|
||||
if (FileLock.TryEnter())
|
||||
{
|
||||
Debug.Console(1, this, "Reading configuration file to extract system UUID...");
|
||||
|
||||
postBody = File.ReadToEnd(filePath, Encoding.ASCII);
|
||||
|
||||
Debug.Console(2, this, "{0}", postBody);
|
||||
|
||||
FileLock.Leave();
|
||||
}
|
||||
string postBody = JsonConvert.SerializeObject(confObject);
|
||||
SystemUuid = confObject.SystemUuid;
|
||||
|
||||
if (string.IsNullOrEmpty(postBody))
|
||||
{
|
||||
Debug.Console(1, "Post Body is null or empty");
|
||||
Debug.Console(1, this, "ERROR: Config body is empty. Cannot register with server.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Client = new HttpClient();
|
||||
var regClient = new HttpClient();
|
||||
regClient.Verbose = true;
|
||||
regClient.KeepAlive = true;
|
||||
|
||||
string url = string.Format("http://{0}/api/system/join/{1}", Config.ServerUrl, SystemUuid);
|
||||
Debug.Console(1, this, "Joining server at {0}", url);
|
||||
|
||||
HttpClientRequest request = new HttpClientRequest();
|
||||
|
||||
Client.Verbose = true;
|
||||
Client.KeepAlive = true;
|
||||
|
||||
SystemUuid = Essentials.ConfigReader.ConfigObject.SystemUuid;
|
||||
|
||||
string url = string.Format("http://{0}/api/system/join/{1}", Config.serverUrl, SystemUuid);
|
||||
|
||||
request.Url.Parse(url);
|
||||
request.RequestType = RequestType.Post;
|
||||
request.Header.SetHeaderValue("Content-Type", "application/json");
|
||||
request.ContentString = postBody;
|
||||
|
||||
Client.DispatchAsync(request, PostConnectionCallback);
|
||||
var err = regClient.DispatchAsync(request, RegistrationConnectionCallback);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, this, "Error Initilizing Room: {0}", e);
|
||||
Debug.Console(0, this, "ERROR: Initilizing Room: {0}", e);
|
||||
RegisterLockEvent.Set();
|
||||
StartReconnectTimer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Posts a message to the server from a room
|
||||
/// Sends a message to the server from a room
|
||||
/// </summary>
|
||||
/// <param name="room">room from which the message originates</param>
|
||||
/// <param name="o">object to be serialized and sent in post body</param>
|
||||
public void PostToServer(EssentialsRoomBase room, JObject o)
|
||||
public void SendMessageToServer(JObject o)
|
||||
{
|
||||
try
|
||||
|
||||
if (WSClient != null && WSClient.Connected)
|
||||
{
|
||||
if (Client == null)
|
||||
Client = new HttpClient();
|
||||
|
||||
//HttpClient client = new HttpClient();
|
||||
|
||||
HttpClientRequest request = new HttpClientRequest();
|
||||
|
||||
Client.Verbose = true;
|
||||
Client.KeepAlive = true;
|
||||
|
||||
string url = string.Format("http://{0}/api/room/{1}/status", Config.serverUrl, string.Format("{0}--{1}", SystemUuid, room.Key));
|
||||
|
||||
request.Url.Parse(url);
|
||||
request.RequestType = RequestType.Post;
|
||||
request.Header.SetHeaderValue("Content-Type", "application/json");
|
||||
request.KeepAlive = true;
|
||||
|
||||
// Ignore any null objects when serializing and remove formatting
|
||||
string ignored = JsonConvert.SerializeObject(o, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
|
||||
request.ContentString = ignored;
|
||||
|
||||
Debug.Console(1, this, "Posting to '{0}':\n{1}", url, request.ContentString);
|
||||
|
||||
Client.DispatchAsync(request, (r, err) => { if (r != null) { Debug.Console(1, this, "Status Response Code: {0}", r.Code); } });
|
||||
|
||||
StartReconnectTimer(ServerReconnectInterval, ServerReconnectInterval);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Debug.Console(1, this, "Error Posting to Server: {0}", e);
|
||||
string message = JsonConvert.SerializeObject(o, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
|
||||
Debug.Console(1, this, "Message TX: {0}", message);
|
||||
var messageBytes = System.Text.Encoding.UTF8.GetBytes(message);
|
||||
WSClient.Send(messageBytes, (uint)messageBytes.Length, WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME);
|
||||
//WSClient.SendAsync(messageBytes, (uint)messageBytes.Length, WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnects the SSE Client and stops the heartbeat timer
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
void DisconnectSseClient(string command)
|
||||
void DisconnectStreamClient(string command)
|
||||
{
|
||||
if(SseClient != null)
|
||||
SseClient.Disconnect();
|
||||
//if(SseClient != null)
|
||||
// SseClient.Disconnect();
|
||||
|
||||
if (ServerHeartbeat != null)
|
||||
if (WSClient != null && WSClient.Connected)
|
||||
WSClient.Disconnect();
|
||||
|
||||
if (ServerHeartbeatCheckTimer != null)
|
||||
{
|
||||
ServerHeartbeat.Stop();
|
||||
ServerHeartbeatCheckTimer.Stop();
|
||||
|
||||
ServerHeartbeat = null;
|
||||
ServerHeartbeatCheckTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,76 +339,88 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
/// <param name="resp"></param>
|
||||
/// <param name="err"></param>
|
||||
void PostConnectionCallback(HttpClientResponse resp, HTTP_CALLBACK_ERROR err)
|
||||
void RegistrationConnectionCallback(HttpClientResponse resp, HTTP_CALLBACK_ERROR err)
|
||||
{
|
||||
CheckHttpDebug(resp, err);
|
||||
Debug.Console(1, this, "RegistrationConnectionCallback: {0}", err);
|
||||
try
|
||||
{
|
||||
if (resp != null && resp.Code == 200)
|
||||
{
|
||||
if(ServerReconnect != null)
|
||||
if(ServerReconnectTimer != null)
|
||||
{
|
||||
ServerReconnect.Stop();
|
||||
|
||||
ServerReconnect = null;
|
||||
ServerReconnectTimer.Stop();
|
||||
ServerReconnectTimer = null;
|
||||
}
|
||||
|
||||
if (SseClient == null)
|
||||
{
|
||||
ConnectSseClient(null);
|
||||
}
|
||||
// Success here!
|
||||
ConnectStreamClient();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (resp != null)
|
||||
Debug.Console(1, this, "Response from server: {0}\n{1}", resp.Code, err);
|
||||
else
|
||||
Debug.Console(1, this, "Null response received from server.");
|
||||
if (resp != null)
|
||||
Debug.Console(1, this, "Response from server: {0}\n{1}", resp.Code, err);
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "Null response received from server.");
|
||||
}
|
||||
StartReconnectTimer();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(1, this, "Error Initializing SSE Client: {0}", e);
|
||||
Debug.Console(1, this, "Error Initializing Stream Client: {0}", e);
|
||||
StartReconnectTimer();
|
||||
}
|
||||
RegisterLockEvent.Set();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes when we don't get a heartbeat message in time. Triggers reconnect.
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
void HeartbeatExpired(object o)
|
||||
/// <param name="o">For CTimer callback. Not used</param>
|
||||
void HeartbeatExpiredTimerCallback(object o)
|
||||
{
|
||||
if (ServerHeartbeat != null)
|
||||
Debug.Console(1, this, "Heartbeat Timer Expired.");
|
||||
if (ServerHeartbeatCheckTimer != null)
|
||||
{
|
||||
Debug.Console(1, this, "Heartbeat Timer Expired.");
|
||||
|
||||
ServerHeartbeat.Stop();
|
||||
|
||||
ServerHeartbeat = null;
|
||||
ServerHeartbeatCheckTimer.Stop();
|
||||
ServerHeartbeatCheckTimer = null;
|
||||
}
|
||||
|
||||
StartReconnectTimer(ServerReconnectInterval, ServerReconnectInterval);
|
||||
StartReconnectTimer();
|
||||
}
|
||||
|
||||
void StartReconnectTimer(long dueTime, long repeatTime)
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dueTime"></param>
|
||||
/// <param name="repeatTime"></param>
|
||||
void StartReconnectTimer()
|
||||
{
|
||||
// Start the reconnect timer
|
||||
ServerReconnect = new CTimer(ReconnectToServer, null, dueTime, repeatTime);
|
||||
|
||||
ServerReconnect.Reset(dueTime, repeatTime);
|
||||
if (ServerReconnectTimer == null)
|
||||
{
|
||||
ServerReconnectTimer = new CTimer(ReconnectToServerTimerCallback, null, ServerReconnectInterval, ServerReconnectInterval);
|
||||
Debug.Console(1, this, "Reconnect Timer Started.");
|
||||
}
|
||||
ServerReconnectTimer.Reset(ServerReconnectInterval, ServerReconnectInterval);
|
||||
}
|
||||
|
||||
void StartHearbeatTimer(long dueTime, long repeatTime)
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dueTime"></param>
|
||||
/// <param name="repeatTime"></param>
|
||||
void ResetOrStartHearbeatTimer()
|
||||
{
|
||||
if (ServerHeartbeat == null)
|
||||
if (ServerHeartbeatCheckTimer == null)
|
||||
{
|
||||
ServerHeartbeat = new CTimer(HeartbeatExpired, null, dueTime, repeatTime);
|
||||
ServerHeartbeatCheckTimer = new CTimer(HeartbeatExpiredTimerCallback, null, ServerHeartbeatInterval, ServerHeartbeatInterval);
|
||||
|
||||
Debug.Console(2, this, "Heartbeat Timer Started.");
|
||||
Debug.Console(1, this, "Heartbeat Timer Started.");
|
||||
}
|
||||
|
||||
ServerHeartbeat.Reset(dueTime, repeatTime);
|
||||
|
||||
Debug.Console(2, this, "Heartbeat Timer Reset.");
|
||||
ServerHeartbeatCheckTimer.Reset(ServerHeartbeatInterval, ServerHeartbeatInterval);
|
||||
}
|
||||
|
||||
|
||||
@@ -290,156 +428,263 @@ namespace PepperDash.Essentials
|
||||
/// Connects the SSE Client
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
void ConnectSseClient(object o)
|
||||
void ConnectStreamClient()
|
||||
{
|
||||
Debug.Console(0, this, "Initializing SSE Client.");
|
||||
Debug.Console(0, this, "Initializing Stream client to server.");
|
||||
|
||||
if (SseClient == null)
|
||||
{
|
||||
SseClient = new GenericHttpSseClient(string.Format("{0}-SseClient", Key), Name);
|
||||
|
||||
CommunicationGather LineGathered = new CommunicationGather(SseClient, "\x0d\x0a");
|
||||
|
||||
LineGathered.LineReceived += new EventHandler<GenericCommMethodReceiveTextArgs>(LineGathered_LineReceived);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SseClient.IsConnected)
|
||||
{
|
||||
SseClient.Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
string uuid = Essentials.ConfigReader.ConfigObject.SystemUuid;
|
||||
|
||||
SseClient.Url = string.Format("http://{0}/api/system/stream/{1}", Config.serverUrl, uuid);
|
||||
|
||||
SseClient.Connect();
|
||||
if (WSClient == null)
|
||||
{
|
||||
WSClient = new WebSocketClient();
|
||||
}
|
||||
WSClient.URL = string.Format("wss://{0}/system/join/{1}", Config.ServerUrl, this.SystemUuid);
|
||||
WSClient.Connect();
|
||||
Debug.Console(0, this, "Websocket connected");
|
||||
WSClient.ReceiveCallBack = WebsocketReceiveCallback;
|
||||
//WSClient.SendCallBack = WebsocketSendCallback;
|
||||
WSClient.ReceiveAsync();
|
||||
}
|
||||
|
||||
|
||||
void LineGathered_LineReceived(object sender, GenericCommMethodReceiveTextArgs e)
|
||||
/// <summary>
|
||||
/// Resets reconnect timer and updates usercode
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
void HandleHeartBeat(JToken content)
|
||||
{
|
||||
var code = content["userCode"];
|
||||
if(code != null)
|
||||
{
|
||||
foreach (var b in RoomBridges)
|
||||
{
|
||||
b.SetUserCode(code.Value<string>());
|
||||
}
|
||||
}
|
||||
ResetOrStartHearbeatTimer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs debug info when enabled
|
||||
/// </summary>
|
||||
/// <param name="req"></param>
|
||||
/// <param name="r"></param>
|
||||
/// <param name="e"></param>
|
||||
void CheckHttpDebug(HttpClientResponse r, HTTP_CALLBACK_ERROR e)
|
||||
{
|
||||
if (HttpDebugEnabled)
|
||||
{
|
||||
Debug.Console(0, this, "------ Begin HTTP Debug ---------------------------------------");
|
||||
Debug.Console(0, this, "HTTP Response URL: {0}", r.ResponseUrl.ToString());
|
||||
Debug.Console(0, this, "HTTP Response 'error' {0}", e);
|
||||
Debug.Console(0, this, "HTTP Response code: {0}", r.Code);
|
||||
Debug.Console(0, this, "HTTP Response content: \r{0}", r.ContentString);
|
||||
Debug.Console(0, this, "------ End HTTP Debug -----------------------------------------");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <param name="opcode"></param>
|
||||
/// <param name="err"></param>
|
||||
int WebsocketReceiveCallback(byte[] data, uint length, WebSocketClient.WEBSOCKET_PACKET_TYPES opcode,
|
||||
WebSocketClient.WEBSOCKET_RESULT_CODES err)
|
||||
{
|
||||
var rx = System.Text.Encoding.UTF8.GetString(data, 0, (int)length);
|
||||
if(rx.Length > 0)
|
||||
ParseStreamRx(rx);
|
||||
WSClient.ReceiveAsync();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback to catch possible errors in sending via the websocket
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
int WebsocketSendCallback(Crestron.SimplSharp.CrestronWebSocketClient.WebSocketClient.WEBSOCKET_RESULT_CODES result)
|
||||
{
|
||||
//Debug.Console(1, this, "Received from Server: '{0}'", e.Text);
|
||||
Debug.Console(1, this, "SendCallback result: {0}", result);
|
||||
|
||||
if(e.Text.IndexOf("data:") > -1)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void ParseStreamRx(string message)
|
||||
{
|
||||
if(string.IsNullOrEmpty(message))
|
||||
return;
|
||||
|
||||
Debug.Console(1, this, "Message RX: '{0}'", message);
|
||||
try
|
||||
{
|
||||
var message = e.Text.Substring(6);
|
||||
var messageObj = JObject.Parse(message);
|
||||
|
||||
Debug.Console(1, this, "Message: '{0}'", message);
|
||||
var type = messageObj["type"].Value<string>();
|
||||
|
||||
try
|
||||
if (type == "hello")
|
||||
{
|
||||
var messageObj = JObject.Parse(message);
|
||||
|
||||
var type = messageObj["type"].Value<string>();
|
||||
|
||||
if (type == "hello")
|
||||
{
|
||||
StartHearbeatTimer(ServerHeartbeatInterval, ServerHeartbeatInterval);
|
||||
}
|
||||
else if (type == "/system/heartbeat")
|
||||
{
|
||||
StartHearbeatTimer(ServerHeartbeatInterval, ServerHeartbeatInterval);
|
||||
}
|
||||
else if (type == "close")
|
||||
{
|
||||
SseClient.Disconnect();
|
||||
|
||||
// Start the reconnect timer
|
||||
ServerReconnect = new CTimer(ConnectSseClient, null, ServerReconnectInterval, ServerReconnectInterval);
|
||||
|
||||
ServerReconnect.Reset(ServerReconnectInterval, ServerReconnectInterval);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check path against Action dictionary
|
||||
if (ActionDictionary.ContainsKey(type))
|
||||
{
|
||||
var action = ActionDictionary[type];
|
||||
|
||||
if (action is Action)
|
||||
{
|
||||
(action as Action)();
|
||||
}
|
||||
else if (action is PressAndHoldAction)
|
||||
{
|
||||
var stateString = messageObj["content"]["state"].Value<string>();
|
||||
|
||||
// Look for a button press event
|
||||
if (!string.IsNullOrEmpty(stateString))
|
||||
{
|
||||
switch (stateString)
|
||||
{
|
||||
case "true":
|
||||
{
|
||||
if (!PushedActions.ContainsKey(type))
|
||||
{
|
||||
PushedActions.Add(type, new CTimer(o =>
|
||||
{
|
||||
(action as PressAndHoldAction)(false);
|
||||
PushedActions.Remove(type);
|
||||
}, null, ButtonHeartbeatInterval, ButtonHeartbeatInterval));
|
||||
}
|
||||
// Maybe add an else to reset the timer
|
||||
break;
|
||||
}
|
||||
case "held":
|
||||
{
|
||||
if (!PushedActions.ContainsKey(type))
|
||||
{
|
||||
PushedActions[type].Reset(ButtonHeartbeatInterval, ButtonHeartbeatInterval);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case "false":
|
||||
{
|
||||
if (PushedActions.ContainsKey(type))
|
||||
{
|
||||
PushedActions[type].Stop();
|
||||
PushedActions.Remove(type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
(action as PressAndHoldAction)(stateString == "true");
|
||||
}
|
||||
}
|
||||
else if (action is Action<bool>)
|
||||
{
|
||||
var stateString = messageObj["content"]["state"].Value<string>();
|
||||
|
||||
if (!string.IsNullOrEmpty(stateString))
|
||||
{
|
||||
(action as Action<bool>)(stateString == "true");
|
||||
}
|
||||
}
|
||||
else if (action is Action<ushort>)
|
||||
{
|
||||
(action as Action<ushort>)(messageObj["content"]["value"].Value<ushort>());
|
||||
}
|
||||
else if (action is Action<string>)
|
||||
{
|
||||
(action as Action<string>)(messageObj["content"]["value"].Value<string>());
|
||||
}
|
||||
else if (action is Action<SourceSelectMessageContent>)
|
||||
{
|
||||
(action as Action<SourceSelectMessageContent>)(messageObj["content"]
|
||||
.ToObject<SourceSelectMessageContent>());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
Debug.Console(1, this, "Unable to parse message: {0}", err);
|
||||
ResetOrStartHearbeatTimer();
|
||||
}
|
||||
else if (type == "/system/heartbeat")
|
||||
{
|
||||
HandleHeartBeat(messageObj["content"]);
|
||||
}
|
||||
else if (type == "close")
|
||||
{
|
||||
WSClient.Disconnect();
|
||||
|
||||
ServerHeartbeatCheckTimer.Stop();
|
||||
// Start the reconnect timer
|
||||
StartReconnectTimer();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check path against Action dictionary
|
||||
if (ActionDictionary.ContainsKey(type))
|
||||
{
|
||||
var action = ActionDictionary[type];
|
||||
|
||||
if (action is Action)
|
||||
{
|
||||
(action as Action)();
|
||||
}
|
||||
else if (action is PressAndHoldAction)
|
||||
{
|
||||
var stateString = messageObj["content"]["state"].Value<string>();
|
||||
|
||||
// Look for a button press event
|
||||
if (!string.IsNullOrEmpty(stateString))
|
||||
{
|
||||
switch (stateString)
|
||||
{
|
||||
case "true":
|
||||
{
|
||||
if (!PushedActions.ContainsKey(type))
|
||||
{
|
||||
PushedActions.Add(type, new CTimer(o =>
|
||||
{
|
||||
(action as PressAndHoldAction)(false);
|
||||
PushedActions.Remove(type);
|
||||
}, null, ButtonHeartbeatInterval, ButtonHeartbeatInterval));
|
||||
}
|
||||
// Maybe add an else to reset the timer
|
||||
break;
|
||||
}
|
||||
case "held":
|
||||
{
|
||||
if (!PushedActions.ContainsKey(type))
|
||||
{
|
||||
PushedActions[type].Reset(ButtonHeartbeatInterval, ButtonHeartbeatInterval);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case "false":
|
||||
{
|
||||
if (PushedActions.ContainsKey(type))
|
||||
{
|
||||
PushedActions[type].Stop();
|
||||
PushedActions.Remove(type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
(action as PressAndHoldAction)(stateString == "true");
|
||||
}
|
||||
}
|
||||
else if (action is Action<bool>)
|
||||
{
|
||||
var stateString = messageObj["content"]["state"].Value<string>();
|
||||
|
||||
if (!string.IsNullOrEmpty(stateString))
|
||||
{
|
||||
(action as Action<bool>)(stateString == "true");
|
||||
}
|
||||
}
|
||||
else if (action is Action<ushort>)
|
||||
{
|
||||
(action as Action<ushort>)(messageObj["content"]["value"].Value<ushort>());
|
||||
}
|
||||
else if (action is Action<string>)
|
||||
{
|
||||
(action as Action<string>)(messageObj["content"]["value"].Value<string>());
|
||||
}
|
||||
else if (action is Action<SourceSelectMessageContent>)
|
||||
{
|
||||
(action as Action<SourceSelectMessageContent>)(messageObj["content"]
|
||||
.ToObject<SourceSelectMessageContent>());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "-- Warning: Incoming message has no registered handler");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
//Debug.Console(1, "SseMessageLengthBeforeFailureCount: {0}", SseMessageLengthBeforeFailureCount);
|
||||
//SseMessageLengthBeforeFailureCount = 0;
|
||||
Debug.Console(1, this, "Unable to parse message: {0}", err);
|
||||
}
|
||||
}
|
||||
|
||||
void TestHttpRequest(string s)
|
||||
{
|
||||
{
|
||||
s = s.Trim();
|
||||
if (string.IsNullOrEmpty(s))
|
||||
{
|
||||
PrintTestHttpRequestUsage();
|
||||
return;
|
||||
}
|
||||
var tokens = s.Split(' ');
|
||||
if (tokens.Length < 2)
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Too few paramaters\r");
|
||||
PrintTestHttpRequestUsage();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var url = tokens[1];
|
||||
if (tokens[0].ToLower() == "get")
|
||||
{
|
||||
var resp = new HttpClient().Get(url);
|
||||
CrestronConsole.ConsoleCommandResponse("RESPONSE:\r{0}\r\r", resp);
|
||||
}
|
||||
else if (tokens[0].ToLower() == "post")
|
||||
{
|
||||
var resp = new HttpClient().Post(url, new byte[] { });
|
||||
CrestronConsole.ConsoleCommandResponse("RESPONSE:\r{0}\r\r", resp);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Only get or post supported\r");
|
||||
PrintTestHttpRequestUsage();
|
||||
}
|
||||
}
|
||||
catch (HttpException e)
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Exception in request:\r");
|
||||
CrestronConsole.ConsoleCommandResponse("Response URL: {0}\r", e.Response.ResponseUrl);
|
||||
CrestronConsole.ConsoleCommandResponse("Response Error Code: {0}\r", e.Response.Code);
|
||||
CrestronConsole.ConsoleCommandResponse("Response body: {0}\r", e.Response.ContentString);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void PrintTestHttpRequestUsage()
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Usage: mobilehttprequest:N get/post url\r");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,694 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
using Crestron.SimplSharpPro.CrestronThread;
|
||||
using Crestron.SimplSharp.CrestronWebSocketClient;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharp.Net.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Room.Cotija;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class CotijaSystemController : Device
|
||||
{
|
||||
WebSocketClient WSClient;
|
||||
|
||||
/// <summary>
|
||||
/// Prevents post operations from stomping on each other and getting lost
|
||||
/// </summary>
|
||||
CEvent PostLockEvent = new CEvent(true, true);
|
||||
|
||||
CEvent RegisterLockEvent = new CEvent(true, true);
|
||||
|
||||
public CotijaConfig Config { get; private set; }
|
||||
|
||||
Dictionary<string, Object> ActionDictionary = new Dictionary<string, Object>(StringComparer.InvariantCultureIgnoreCase);
|
||||
|
||||
Dictionary<string, CTimer> PushedActions = new Dictionary<string, CTimer>();
|
||||
|
||||
CTimer ServerHeartbeatCheckTimer;
|
||||
|
||||
long ServerHeartbeatInterval = 20000;
|
||||
|
||||
CTimer ServerReconnectTimer;
|
||||
|
||||
long ServerReconnectInterval = 5000;
|
||||
|
||||
string SystemUuid;
|
||||
|
||||
List<CotijaBridgeBase> RoomBridges = new List<CotijaBridgeBase>();
|
||||
|
||||
long ButtonHeartbeatInterval = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// Used for tracking HTTP debugging
|
||||
/// </summary>
|
||||
bool HttpDebugEnabled;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="config"></param>
|
||||
public CotijaSystemController(string key, string name, CotijaConfig config) : base(key, name)
|
||||
{
|
||||
Config = config;
|
||||
Debug.Console(0, this, "Mobile UI controller initializing for server:{0}", config.ServerUrl);
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(AuthorizeSystem,
|
||||
"mobileauth", "Authorizes system to talk to cotija server", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => ShowInfo(),
|
||||
"mobileinfo", "Shows information for current mobile control session", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => {
|
||||
s = s.Trim();
|
||||
if(!string.IsNullOrEmpty(s))
|
||||
{
|
||||
HttpDebugEnabled = (s.Trim() != "0");
|
||||
}
|
||||
CrestronConsole.ConsoleCommandResponse("HTTP Debug {0}", HttpDebugEnabled ? "Enabled" : "Disabled");
|
||||
},
|
||||
"mobilehttpdebug", "1 enables more verbose HTTP response debugging", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(TestHttpRequest,
|
||||
"mobilehttprequest", "Tests an HTTP get to URL given", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an action to the dictionary
|
||||
/// </summary>
|
||||
/// <param name="key">The path of the API command</param>
|
||||
/// <param name="action">The action to be triggered by the commmand</param>
|
||||
public void AddAction(string key, object action)
|
||||
{
|
||||
if (!ActionDictionary.ContainsKey(key))
|
||||
{
|
||||
ActionDictionary.Add(key, action);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "Cannot add action with key '{0}' because key already exists in ActionDictionary.", key);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an action from the dictionary
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
public void RemoveAction(string key)
|
||||
{
|
||||
if (ActionDictionary.ContainsKey(key))
|
||||
ActionDictionary.Remove(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="bridge"></param>
|
||||
public void AddBridge(CotijaBridgeBase bridge)
|
||||
{
|
||||
RoomBridges.Add(bridge);
|
||||
var b = bridge as IDelayedConfiguration;
|
||||
if (b != null)
|
||||
{
|
||||
Debug.Console(0, this, "Adding room bridge with delayed configuration");
|
||||
b.ConfigurationIsReady += new EventHandler<EventArgs>(bridge_ConfigurationIsReady);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(0, this, "Adding room bridge and sending configuration");
|
||||
RegisterSystemToServer();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void bridge_ConfigurationIsReady(object sender, EventArgs e)
|
||||
{
|
||||
Debug.Console(1, this, "Bridge ready. Registering");
|
||||
// send the configuration object to the server
|
||||
RegisterSystemToServer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
void ReconnectToServerTimerCallback(object o)
|
||||
{
|
||||
RegisterSystemToServer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies system connection with servers
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
void AuthorizeSystem(string code)
|
||||
{
|
||||
if (string.IsNullOrEmpty(code))
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Please enter a user code to authorize a system");
|
||||
return;
|
||||
}
|
||||
|
||||
var req = new HttpClientRequest();
|
||||
string url = string.Format("http://{0}/api/system/grantcode/{1}/{2}", Config.ServerUrl, code, SystemUuid);
|
||||
Debug.Console(0, this, "Authorizing to: {0}", url);
|
||||
|
||||
if (string.IsNullOrEmpty(Config.ServerUrl))
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Config URL address is not set. Check portal configuration");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
req.Url.Parse(url);
|
||||
new HttpClient().DispatchAsync(req, (r, e) =>
|
||||
{
|
||||
CheckHttpDebug(r, e);
|
||||
if (e == HTTP_CALLBACK_ERROR.COMPLETED)
|
||||
{
|
||||
if (r.Code == 200)
|
||||
{
|
||||
Debug.Console(0, "System authorized, sending config.");
|
||||
RegisterSystemToServer();
|
||||
}
|
||||
else if (r.Code == 404)
|
||||
{
|
||||
if (r.ContentString.Contains("codeNotFound"))
|
||||
{
|
||||
Debug.Console(0, "Authorization failed, code not found for system UUID {0}", SystemUuid);
|
||||
}
|
||||
else if (r.ContentString.Contains("uuidNotFound"))
|
||||
{
|
||||
Debug.Console(0, "Authorization failed, uuid {0} not found. Check Essentials configuration is correct",
|
||||
SystemUuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
Debug.Console(0, this, "Error {0} in authorizing system", e);
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, this, "Error in authorizing: {0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dumps info in response to console command.
|
||||
/// </summary>
|
||||
void ShowInfo()
|
||||
{
|
||||
var url = Config != null ? Config.ServerUrl : "No config";
|
||||
string name;
|
||||
string code;
|
||||
if (RoomBridges != null && RoomBridges.Count > 0)
|
||||
{
|
||||
name = RoomBridges[0].RoomName;
|
||||
code = RoomBridges[0].UserCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = "No config";
|
||||
code = "Not available";
|
||||
}
|
||||
var conn = WSClient == null ? "No client" : (WSClient.Connected ? "Yes" : "No");
|
||||
|
||||
CrestronConsole.ConsoleCommandResponse(@"Mobile Control Information:
|
||||
Server address: {0}
|
||||
System Name: {1}
|
||||
System UUID: {2}
|
||||
System User code: {3}
|
||||
Connected?: {4}", url, name, SystemUuid,
|
||||
code, conn);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers the room with the server
|
||||
/// </summary>
|
||||
/// <param name="url">URL of the server, including the port number, if not 80. Format: "serverUrlOrIp:port"</param>
|
||||
void RegisterSystemToServer()
|
||||
{
|
||||
var ready = RegisterLockEvent.Wait(20000);
|
||||
if (!ready)
|
||||
{
|
||||
Debug.Console(1, this, "RegisterSystemToServer failed to enter after 20 seconds. Ignoring");
|
||||
return;
|
||||
}
|
||||
RegisterLockEvent.Reset();
|
||||
|
||||
try
|
||||
{
|
||||
var confObject = ConfigReader.ConfigObject;
|
||||
confObject.Info.RuntimeInfo.AppName = Assembly.GetExecutingAssembly().GetName().Name;
|
||||
var version = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
confObject.Info.RuntimeInfo.AssemblyVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
|
||||
confObject.Info.RuntimeInfo.OsVersion = Crestron.SimplSharp.CrestronEnvironment.OSVersion.Firmware;
|
||||
|
||||
string postBody = JsonConvert.SerializeObject(confObject);
|
||||
SystemUuid = confObject.SystemUuid;
|
||||
|
||||
if (string.IsNullOrEmpty(postBody))
|
||||
{
|
||||
Debug.Console(1, this, "ERROR: Config body is empty. Cannot register with server.");
|
||||
}
|
||||
else
|
||||
{
|
||||
var regClient = new HttpClient();
|
||||
regClient.Verbose = true;
|
||||
regClient.KeepAlive = true;
|
||||
|
||||
string url = string.Format("http://{0}/api/system/join/{1}", Config.ServerUrl, SystemUuid);
|
||||
Debug.Console(1, this, "Joining server at {0}", url);
|
||||
|
||||
HttpClientRequest request = new HttpClientRequest();
|
||||
request.Url.Parse(url);
|
||||
request.RequestType = RequestType.Post;
|
||||
request.Header.SetHeaderValue("Content-Type", "application/json");
|
||||
request.ContentString = postBody;
|
||||
|
||||
var err = regClient.DispatchAsync(request, RegistrationConnectionCallback);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, this, "ERROR: Initilizing Room: {0}", e);
|
||||
RegisterLockEvent.Set();
|
||||
StartReconnectTimer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a message to the server from a room
|
||||
/// </summary>
|
||||
/// <param name="room">room from which the message originates</param>
|
||||
/// <param name="o">object to be serialized and sent in post body</param>
|
||||
public void SendMessageToServer(JObject o)
|
||||
{
|
||||
|
||||
if (WSClient != null && WSClient.Connected)
|
||||
{
|
||||
string message = JsonConvert.SerializeObject(o, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
|
||||
Debug.Console(1, this, "Message TX: {0}", message);
|
||||
var messageBytes = System.Text.Encoding.UTF8.GetBytes(message);
|
||||
WSClient.Send(messageBytes, (uint)messageBytes.Length, WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME);
|
||||
//WSClient.SendAsync(messageBytes, (uint)messageBytes.Length, WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME);
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
|
||||
=======
|
||||
|
||||
>>>>>>> feature/ecs-684
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnects the SSE Client and stops the heartbeat timer
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
void DisconnectStreamClient(string command)
|
||||
{
|
||||
//if(SseClient != null)
|
||||
// SseClient.Disconnect();
|
||||
|
||||
if (WSClient != null && WSClient.Connected)
|
||||
WSClient.Disconnect();
|
||||
|
||||
if (ServerHeartbeatCheckTimer != null)
|
||||
{
|
||||
ServerHeartbeatCheckTimer.Stop();
|
||||
|
||||
ServerHeartbeatCheckTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The callback that fires when we get a response from our registration attempt
|
||||
/// </summary>
|
||||
/// <param name="resp"></param>
|
||||
/// <param name="err"></param>
|
||||
void RegistrationConnectionCallback(HttpClientResponse resp, HTTP_CALLBACK_ERROR err)
|
||||
{
|
||||
CheckHttpDebug(resp, err);
|
||||
Debug.Console(1, this, "RegistrationConnectionCallback: {0}", err);
|
||||
try
|
||||
{
|
||||
if (resp != null && resp.Code == 200)
|
||||
{
|
||||
if(ServerReconnectTimer != null)
|
||||
{
|
||||
ServerReconnectTimer.Stop();
|
||||
ServerReconnectTimer = null;
|
||||
}
|
||||
|
||||
// Success here!
|
||||
ConnectStreamClient();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (resp != null)
|
||||
Debug.Console(1, this, "Response from server: {0}\n{1}", resp.Code, err);
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "Null response received from server.");
|
||||
}
|
||||
StartReconnectTimer();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(1, this, "Error Initializing Stream Client: {0}", e);
|
||||
StartReconnectTimer();
|
||||
}
|
||||
RegisterLockEvent.Set();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes when we don't get a heartbeat message in time. Triggers reconnect.
|
||||
/// </summary>
|
||||
/// <param name="o">For CTimer callback. Not used</param>
|
||||
void HeartbeatExpiredTimerCallback(object o)
|
||||
{
|
||||
Debug.Console(1, this, "Heartbeat Timer Expired.");
|
||||
if (ServerHeartbeatCheckTimer != null)
|
||||
{
|
||||
ServerHeartbeatCheckTimer.Stop();
|
||||
ServerHeartbeatCheckTimer = null;
|
||||
}
|
||||
StartReconnectTimer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dueTime"></param>
|
||||
/// <param name="repeatTime"></param>
|
||||
void StartReconnectTimer()
|
||||
{
|
||||
// Start the reconnect timer
|
||||
if (ServerReconnectTimer == null)
|
||||
{
|
||||
ServerReconnectTimer = new CTimer(ReconnectToServerTimerCallback, null, ServerReconnectInterval, ServerReconnectInterval);
|
||||
Debug.Console(1, this, "Reconnect Timer Started.");
|
||||
}
|
||||
ServerReconnectTimer.Reset(ServerReconnectInterval, ServerReconnectInterval);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dueTime"></param>
|
||||
/// <param name="repeatTime"></param>
|
||||
void ResetOrStartHearbeatTimer()
|
||||
{
|
||||
if (ServerHeartbeatCheckTimer == null)
|
||||
{
|
||||
ServerHeartbeatCheckTimer = new CTimer(HeartbeatExpiredTimerCallback, null, ServerHeartbeatInterval, ServerHeartbeatInterval);
|
||||
|
||||
Debug.Console(1, this, "Heartbeat Timer Started.");
|
||||
}
|
||||
|
||||
ServerHeartbeatCheckTimer.Reset(ServerHeartbeatInterval, ServerHeartbeatInterval);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Connects the SSE Client
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
void ConnectStreamClient()
|
||||
{
|
||||
Debug.Console(0, this, "Initializing Stream client to server.");
|
||||
|
||||
if (WSClient == null)
|
||||
{
|
||||
WSClient = new WebSocketClient();
|
||||
}
|
||||
WSClient.URL = string.Format("wss://{0}/system/join/{1}", Config.ServerUrl, this.SystemUuid);
|
||||
WSClient.Connect();
|
||||
Debug.Console(0, this, "Websocket connected");
|
||||
WSClient.ReceiveCallBack = WebsocketReceiveCallback;
|
||||
//WSClient.SendCallBack = WebsocketSendCallback;
|
||||
WSClient.ReceiveAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets reconnect timer and updates usercode
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
void HandleHeartBeat(JToken content)
|
||||
{
|
||||
var code = content["userCode"];
|
||||
if(code != null)
|
||||
{
|
||||
foreach (var b in RoomBridges)
|
||||
{
|
||||
b.SetUserCode(code.Value<string>());
|
||||
}
|
||||
}
|
||||
ResetOrStartHearbeatTimer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs debug info when enabled
|
||||
/// </summary>
|
||||
/// <param name="req"></param>
|
||||
/// <param name="r"></param>
|
||||
/// <param name="e"></param>
|
||||
void CheckHttpDebug(HttpClientResponse r, HTTP_CALLBACK_ERROR e)
|
||||
{
|
||||
if (HttpDebugEnabled)
|
||||
{
|
||||
Debug.Console(0, this, "------ Begin HTTP Debug ---------------------------------------");
|
||||
Debug.Console(0, this, "HTTP Response URL: {0}", r.ResponseUrl.ToString());
|
||||
Debug.Console(0, this, "HTTP Response 'error' {0}", e);
|
||||
Debug.Console(0, this, "HTTP Response code: {0}", r.Code);
|
||||
Debug.Console(0, this, "HTTP Response content: \r{0}", r.ContentString);
|
||||
Debug.Console(0, this, "------ End HTTP Debug -----------------------------------------");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <param name="opcode"></param>
|
||||
/// <param name="err"></param>
|
||||
int WebsocketReceiveCallback(byte[] data, uint length, WebSocketClient.WEBSOCKET_PACKET_TYPES opcode,
|
||||
WebSocketClient.WEBSOCKET_RESULT_CODES err)
|
||||
{
|
||||
var rx = System.Text.Encoding.UTF8.GetString(data, 0, (int)length);
|
||||
if(rx.Length > 0)
|
||||
ParseStreamRx(rx);
|
||||
WSClient.ReceiveAsync();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback to catch possible errors in sending via the websocket
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
int WebsocketSendCallback(Crestron.SimplSharp.CrestronWebSocketClient.WebSocketClient.WEBSOCKET_RESULT_CODES result)
|
||||
{
|
||||
Debug.Console(1, this, "SendCallback result: {0}", result);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void ParseStreamRx(string message)
|
||||
{
|
||||
if(string.IsNullOrEmpty(message))
|
||||
return;
|
||||
|
||||
Debug.Console(1, this, "Message RX: '{0}'", message);
|
||||
try
|
||||
{
|
||||
var messageObj = JObject.Parse(message);
|
||||
|
||||
var type = messageObj["type"].Value<string>();
|
||||
|
||||
if (type == "hello")
|
||||
{
|
||||
ResetOrStartHearbeatTimer();
|
||||
}
|
||||
else if (type == "/system/heartbeat")
|
||||
{
|
||||
HandleHeartBeat(messageObj["content"]);
|
||||
}
|
||||
else if (type == "close")
|
||||
{
|
||||
WSClient.Disconnect();
|
||||
|
||||
ServerHeartbeatCheckTimer.Stop();
|
||||
// Start the reconnect timer
|
||||
StartReconnectTimer();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check path against Action dictionary
|
||||
if (ActionDictionary.ContainsKey(type))
|
||||
{
|
||||
var action = ActionDictionary[type];
|
||||
|
||||
if (action is Action)
|
||||
{
|
||||
(action as Action)();
|
||||
}
|
||||
else if (action is PressAndHoldAction)
|
||||
{
|
||||
var stateString = messageObj["content"]["state"].Value<string>();
|
||||
|
||||
// Look for a button press event
|
||||
if (!string.IsNullOrEmpty(stateString))
|
||||
{
|
||||
switch (stateString)
|
||||
{
|
||||
case "true":
|
||||
{
|
||||
if (!PushedActions.ContainsKey(type))
|
||||
{
|
||||
PushedActions.Add(type, new CTimer(o =>
|
||||
{
|
||||
(action as PressAndHoldAction)(false);
|
||||
PushedActions.Remove(type);
|
||||
}, null, ButtonHeartbeatInterval, ButtonHeartbeatInterval));
|
||||
}
|
||||
// Maybe add an else to reset the timer
|
||||
break;
|
||||
}
|
||||
case "held":
|
||||
{
|
||||
if (!PushedActions.ContainsKey(type))
|
||||
{
|
||||
PushedActions[type].Reset(ButtonHeartbeatInterval, ButtonHeartbeatInterval);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case "false":
|
||||
{
|
||||
if (PushedActions.ContainsKey(type))
|
||||
{
|
||||
PushedActions[type].Stop();
|
||||
PushedActions.Remove(type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
(action as PressAndHoldAction)(stateString == "true");
|
||||
}
|
||||
}
|
||||
else if (action is Action<bool>)
|
||||
{
|
||||
var stateString = messageObj["content"]["state"].Value<string>();
|
||||
|
||||
if (!string.IsNullOrEmpty(stateString))
|
||||
{
|
||||
(action as Action<bool>)(stateString == "true");
|
||||
}
|
||||
}
|
||||
else if (action is Action<ushort>)
|
||||
{
|
||||
(action as Action<ushort>)(messageObj["content"]["value"].Value<ushort>());
|
||||
}
|
||||
else if (action is Action<string>)
|
||||
{
|
||||
(action as Action<string>)(messageObj["content"]["value"].Value<string>());
|
||||
}
|
||||
else if (action is Action<SourceSelectMessageContent>)
|
||||
{
|
||||
(action as Action<SourceSelectMessageContent>)(messageObj["content"]
|
||||
.ToObject<SourceSelectMessageContent>());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "-- Warning: Incoming message has no registered handler");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
//Debug.Console(1, "SseMessageLengthBeforeFailureCount: {0}", SseMessageLengthBeforeFailureCount);
|
||||
//SseMessageLengthBeforeFailureCount = 0;
|
||||
Debug.Console(1, this, "Unable to parse message: {0}", err);
|
||||
}
|
||||
}
|
||||
|
||||
void TestHttpRequest(string s)
|
||||
{
|
||||
{
|
||||
s = s.Trim();
|
||||
if (string.IsNullOrEmpty(s))
|
||||
{
|
||||
PrintTestHttpRequestUsage();
|
||||
return;
|
||||
}
|
||||
var tokens = s.Split(' ');
|
||||
if (tokens.Length < 2)
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Too few paramaters\r");
|
||||
PrintTestHttpRequestUsage();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var url = tokens[1];
|
||||
if (tokens[0].ToLower() == "get")
|
||||
{
|
||||
var resp = new HttpClient().Get(url);
|
||||
CrestronConsole.ConsoleCommandResponse("RESPONSE:\r{0}\r\r", resp);
|
||||
}
|
||||
else if (tokens[0].ToLower() == "post")
|
||||
{
|
||||
var resp = new HttpClient().Post(url, new byte[] { });
|
||||
CrestronConsole.ConsoleCommandResponse("RESPONSE:\r{0}\r\r", resp);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Only get or post supported\r");
|
||||
PrintTestHttpRequestUsage();
|
||||
}
|
||||
}
|
||||
catch (HttpException e)
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Exception in request:\r");
|
||||
CrestronConsole.ConsoleCommandResponse("Response URL: {0}\r", e.Response.ResponseUrl);
|
||||
CrestronConsole.ConsoleCommandResponse("Response Error Code: {0}\r", e.Response.Code);
|
||||
CrestronConsole.ConsoleCommandResponse("Response body: {0}\r", e.Response.ContentString);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void PrintTestHttpRequestUsage()
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Usage: mobilehttprequest:N get/post url\r");
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Essentials/PepperDashEssentials/Room/Cotija/Interfaces.cs
Normal file
13
Essentials/PepperDashEssentials/Room/Cotija/Interfaces.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Cotija
|
||||
{
|
||||
public interface IDelayedConfiguration
|
||||
{
|
||||
event EventHandler<EventArgs> ConfigurationIsReady;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public abstract class CotijaBridgeBase: Device
|
||||
{
|
||||
public CotijaSystemController Parent { get; private set; }
|
||||
|
||||
public string UserCode { get; private set; }
|
||||
|
||||
public abstract string RoomName { get; }
|
||||
|
||||
public CotijaBridgeBase(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the parent. Does nothing else. Override to add functionality such
|
||||
/// as adding actions to parent
|
||||
/// </summary>
|
||||
/// <param name="parent"></param>
|
||||
public virtual void AddParent(CotijaSystemController parent)
|
||||
{
|
||||
Parent = parent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the UserCode on the bridge object. Called from controller. A changed code will
|
||||
/// fire method UserCodeChange. Override that to handle changes
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
public void SetUserCode(string code)
|
||||
{
|
||||
var changed = UserCode != code;
|
||||
UserCode = code;
|
||||
if (changed)
|
||||
{
|
||||
UserCodeChange();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Empty method in base class. Override this to add functionality
|
||||
/// when code changes
|
||||
/// </summary>
|
||||
protected virtual void UserCodeChange()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,607 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro.EthernetCommunication;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
using PepperDash.Essentials.Room.Config;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Room.Cotija
|
||||
{
|
||||
public class CotijaDdvc01RoomBridge : CotijaBridgeBase, IDelayedConfiguration
|
||||
{
|
||||
public class BoolJoin
|
||||
{
|
||||
/// <summary>
|
||||
/// 301
|
||||
/// </summary>
|
||||
public const uint RoomIsOn = 301;
|
||||
|
||||
/// <summary>
|
||||
/// 51
|
||||
/// </summary>
|
||||
public const uint ActivitySharePress = 51;
|
||||
/// <summary>
|
||||
/// 52
|
||||
/// </summary>
|
||||
public const uint ActivityPhoneCallPress = 52;
|
||||
/// <summary>
|
||||
/// 53
|
||||
/// </summary>
|
||||
public const uint ActivityVideoCallPress = 53;
|
||||
|
||||
/// <summary>
|
||||
/// 1
|
||||
/// </summary>
|
||||
public const uint MasterVolumeIsMuted = 1;
|
||||
/// <summary>
|
||||
/// 1
|
||||
/// </summary>
|
||||
public const uint MasterVolumeMuteToggle = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 61
|
||||
/// </summary>
|
||||
public const uint ShutdownCancel = 61;
|
||||
/// <summary>
|
||||
/// 62
|
||||
/// </summary>
|
||||
public const uint ShutdownEnd = 62;
|
||||
/// <summary>
|
||||
/// 63
|
||||
/// </summary>
|
||||
public const uint ShutdownStart = 63;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 72
|
||||
/// </summary>
|
||||
public const uint SourceHasChanged = 72;
|
||||
/// <summary>
|
||||
/// 501
|
||||
/// </summary>
|
||||
public const uint ConfigIsReady = 501;
|
||||
}
|
||||
|
||||
public class UshortJoin
|
||||
{
|
||||
/// <summary>
|
||||
/// 1
|
||||
/// </summary>
|
||||
public const uint MasterVolumeLevel = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 61
|
||||
/// </summary>
|
||||
public const uint ShutdownPromptDuration = 61;
|
||||
}
|
||||
|
||||
public class StringJoin
|
||||
{
|
||||
/// <summary>
|
||||
/// 71
|
||||
/// </summary>
|
||||
public const uint SelectedSourceKey = 71;
|
||||
|
||||
/// <summary>
|
||||
/// 501
|
||||
/// </summary>
|
||||
public const uint ConfigRoomName = 501;
|
||||
/// <summary>
|
||||
/// 502
|
||||
/// </summary>
|
||||
public const uint ConfigHelpMessage = 502;
|
||||
/// <summary>
|
||||
/// 503
|
||||
/// </summary>
|
||||
public const uint ConfigHelpNumber = 503;
|
||||
/// <summary>
|
||||
/// 504
|
||||
/// </summary>
|
||||
public const uint ConfigRoomPhoneNumber = 504;
|
||||
/// <summary>
|
||||
/// 505
|
||||
/// </summary>
|
||||
public const uint ConfigRoomURI = 505;
|
||||
/// <summary>
|
||||
/// 401
|
||||
/// </summary>
|
||||
public const uint UserCodeToSystem = 401;
|
||||
/// <summary>
|
||||
/// 402
|
||||
/// </summary>
|
||||
public const uint ServerUrl = 402;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires when config is ready to go
|
||||
/// </summary>
|
||||
public event EventHandler<EventArgs> ConfigurationIsReady;
|
||||
|
||||
public ThreeSeriesTcpIpEthernetIntersystemCommunications EISC { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool ConfigIsLoaded { get; private set; }
|
||||
|
||||
public override string RoomName
|
||||
{
|
||||
get {
|
||||
var name = EISC.StringOutput[StringJoin.ConfigRoomName].StringValue;
|
||||
return string.IsNullOrEmpty(name) ? "Not Loaded" : name;
|
||||
}
|
||||
}
|
||||
|
||||
CotijaDdvc01DeviceBridge SourceBridge;
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="ipId"></param>
|
||||
public CotijaDdvc01RoomBridge(string key, string name, uint ipId)
|
||||
: base(key, name)
|
||||
{
|
||||
try
|
||||
{
|
||||
EISC = new ThreeSeriesTcpIpEthernetIntersystemCommunications(ipId, "127.0.0.2", Global.ControlSystem);
|
||||
var reg = EISC.Register();
|
||||
if (reg != Crestron.SimplSharpPro.eDeviceRegistrationUnRegistrationResponse.Success)
|
||||
Debug.Console(0, this, "Cannot connect EISC at IPID {0}: \r{1}", ipId, reg);
|
||||
|
||||
SourceBridge = new CotijaDdvc01DeviceBridge(key + "-sourceBridge", "DDVC01 source bridge", EISC);
|
||||
DeviceManager.AddDevice(SourceBridge);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finish wiring up everything after all devices are created. The base class will hunt down the related
|
||||
/// parent controller and link them up.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
Debug.Console(0, this, "Final activation. Setting up actions and feedbacks");
|
||||
SetupFunctions();
|
||||
SetupFeedbacks();
|
||||
|
||||
EISC.SigChange += EISC_SigChange;
|
||||
EISC.OnlineStatusChange += (o, a) =>
|
||||
{
|
||||
Debug.Console(1, this, "DDVC EISC online={0}. Config is ready={1}", a.DeviceOnLine, EISC.BooleanOutput[BoolJoin.ConfigIsReady].BoolValue);
|
||||
if (a.DeviceOnLine && EISC.BooleanOutput[BoolJoin.ConfigIsReady].BoolValue)
|
||||
LoadConfigValues();
|
||||
};
|
||||
// load config if it's already there
|
||||
if (EISC.IsOnline && EISC.BooleanOutput[BoolJoin.ConfigIsReady].BoolValue) // || EISC.BooleanInput[BoolJoin.ConfigIsReady].BoolValue)
|
||||
LoadConfigValues();
|
||||
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(s =>
|
||||
{
|
||||
for (uint i = 1; i < 1000; i++)
|
||||
{
|
||||
if (s.ToLower().Equals("b"))
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("D{0,6} {1} - ", i, EISC.BooleanOutput[i].BoolValue);
|
||||
}
|
||||
else if (s.ToLower().Equals("u"))
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("U{0,6} {1,8} - ", i, EISC.UShortOutput[i].UShortValue);
|
||||
}
|
||||
else if (s.ToLower().Equals("s"))
|
||||
{
|
||||
var val = EISC.StringOutput[i].StringValue;
|
||||
if(!string.IsNullOrEmpty(val))
|
||||
CrestronConsole.ConsoleCommandResponse("S{0,6} {1}\r", i, EISC.StringOutput[i].StringValue);
|
||||
}
|
||||
|
||||
}
|
||||
}, "mobilebridgedump", "Dumps DDVC01 bridge EISC data b,u,s", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(s => LoadConfigValues(), "loadddvc", "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
return base.CustomActivate();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Setup the actions to take place on various incoming API calls
|
||||
/// </summary>
|
||||
void SetupFunctions()
|
||||
{
|
||||
|
||||
Parent.AddAction(@"/room/room1/status", new Action(SendFullStatus));
|
||||
|
||||
Parent.AddAction(@"/room/room1/source", new Action<SourceSelectMessageContent>(c =>
|
||||
{
|
||||
EISC.SetString(StringJoin.SelectedSourceKey, c.SourceListItem);
|
||||
EISC.PulseBool(BoolJoin.SourceHasChanged);
|
||||
}));
|
||||
|
||||
#warning CHANGE to activityshare. Perhaps
|
||||
Parent.AddAction(@"/room/room1/defaultsource", new Action(() =>
|
||||
EISC.PulseBool(BoolJoin.ActivitySharePress)));
|
||||
|
||||
Parent.AddAction(@"/room/room1/masterVolumeLevel", new Action<ushort>(u =>
|
||||
EISC.SetUshort(UshortJoin.MasterVolumeLevel, u)));
|
||||
Parent.AddAction(@"/room/room1/masterVolumeMuteToggle", new Action(() =>
|
||||
EISC.PulseBool(BoolJoin.MasterVolumeIsMuted)));
|
||||
|
||||
Parent.AddAction(@"/room/room1/shutdownStart", new Action(() =>
|
||||
EISC.PulseBool(BoolJoin.ShutdownStart)));
|
||||
Parent.AddAction(@"/room/room1/shutdownEnd", new Action(() =>
|
||||
EISC.PulseBool(BoolJoin.ShutdownEnd)));
|
||||
Parent.AddAction(@"/room/room1/shutdownCancel", new Action(() =>
|
||||
EISC.PulseBool(BoolJoin.ShutdownCancel)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Links feedbacks to whatever is gonna happen!
|
||||
/// </summary>
|
||||
void SetupFeedbacks()
|
||||
{
|
||||
// Power
|
||||
EISC.SetBoolSigAction(BoolJoin.RoomIsOn, b =>
|
||||
PostStatusMessage(new
|
||||
{
|
||||
isOn = b
|
||||
}));
|
||||
|
||||
// Source change things
|
||||
EISC.SetSigTrueAction(BoolJoin.SourceHasChanged, () =>
|
||||
PostStatusMessage(new
|
||||
{
|
||||
selectedSourceKey = EISC.StringOutput[StringJoin.SelectedSourceKey].StringValue
|
||||
}));
|
||||
|
||||
// Volume things
|
||||
EISC.SetUShortSigAction(UshortJoin.MasterVolumeLevel, u =>
|
||||
PostStatusMessage(new
|
||||
{
|
||||
masterVolumeLevel = u
|
||||
}));
|
||||
|
||||
EISC.SetBoolSigAction(BoolJoin.MasterVolumeIsMuted, b =>
|
||||
PostStatusMessage(new
|
||||
{
|
||||
masterVolumeMuteState = b
|
||||
}));
|
||||
|
||||
// shutdown things
|
||||
EISC.SetSigTrueAction(BoolJoin.ShutdownCancel, new Action(() =>
|
||||
PostMessage("/room/shutdown/", new
|
||||
{
|
||||
state = "wasCancelled"
|
||||
})));
|
||||
EISC.SetSigTrueAction(BoolJoin.ShutdownEnd, new Action(() =>
|
||||
PostMessage("/room/shutdown/", new
|
||||
{
|
||||
state = "hasFinished"
|
||||
})));
|
||||
EISC.SetSigTrueAction(BoolJoin.ShutdownStart, new Action(() =>
|
||||
PostMessage("/room/shutdown/", new
|
||||
{
|
||||
state = "hasStarted",
|
||||
duration = EISC.UShortOutput[UshortJoin.ShutdownPromptDuration].UShortValue
|
||||
})));
|
||||
|
||||
// Config things
|
||||
EISC.SetSigTrueAction(BoolJoin.ConfigIsReady, LoadConfigValues);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads in config values when the Simpl program is ready
|
||||
/// </summary>
|
||||
void LoadConfigValues()
|
||||
{
|
||||
Debug.Console(1, this, "Loading configuration from DDVC01 EISC bridge");
|
||||
ConfigIsLoaded = false;
|
||||
|
||||
var co = ConfigReader.ConfigObject;
|
||||
|
||||
//Room
|
||||
if (co.Rooms == null)
|
||||
co.Rooms = new List<EssentialsRoomConfig>();
|
||||
var rm = new EssentialsRoomConfig();
|
||||
if (co.Rooms.Count == 0)
|
||||
{
|
||||
Debug.Console(0, this, "Adding room to config");
|
||||
co.Rooms.Add(rm);
|
||||
}
|
||||
rm.Name = EISC.StringOutput[501].StringValue;
|
||||
rm.Key = "room1";
|
||||
rm.Type = "ddvc01";
|
||||
|
||||
DDVC01RoomPropertiesConfig rmProps;
|
||||
if (rm.Properties == null)
|
||||
rmProps = new DDVC01RoomPropertiesConfig();
|
||||
else
|
||||
rmProps = JsonConvert.DeserializeObject<DDVC01RoomPropertiesConfig>(rm.Properties.ToString());
|
||||
|
||||
rmProps.Help = new EssentialsHelpPropertiesConfig();
|
||||
rmProps.Help.CallButtonText = EISC.StringOutput[503].StringValue;
|
||||
rmProps.Help.Message = EISC.StringOutput[502].StringValue;
|
||||
|
||||
rmProps.Environment = new EssentialsEnvironmentPropertiesConfig(); // enabled defaults to false
|
||||
|
||||
rmProps.RoomPhoneNumber = EISC.StringOutput[504].StringValue;
|
||||
rmProps.RoomURI = EISC.StringOutput[505].StringValue;
|
||||
rmProps.SpeedDials = new List<DDVC01SpeedDial>();
|
||||
// add speed dials as long as there are more - up to 4
|
||||
for (uint i = 512; i <= 519; i = i + 2)
|
||||
{
|
||||
var num = EISC.StringOutput[i].StringValue;
|
||||
if (string.IsNullOrEmpty(num))
|
||||
break;
|
||||
var name = EISC.StringOutput[i + 1].StringValue;
|
||||
rmProps.SpeedDials.Add(new DDVC01SpeedDial { Number = num, Name = name});
|
||||
}
|
||||
// volume control names
|
||||
var volCount = EISC.UShortOutput[701].UShortValue;
|
||||
|
||||
// use Volumes object or?
|
||||
rmProps.VolumeSliderNames = new List<string>();
|
||||
for(uint i = 701; i <= 700 + volCount; i++)
|
||||
{
|
||||
rmProps.VolumeSliderNames.Add(EISC.StringInput[i].StringValue);
|
||||
}
|
||||
|
||||
// There should be cotija devices in here, I think...
|
||||
if(co.Devices == null)
|
||||
co.Devices = new List<DeviceConfig>();
|
||||
|
||||
// clear out previous DDVC devices
|
||||
co.Devices.RemoveAll(d => d.Key.StartsWith("source-", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
rmProps.SourceListKey = "default";
|
||||
rm.Properties = JToken.FromObject(rmProps);
|
||||
|
||||
// Source list! This might be brutal!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
var groupMap = GetSourceGroupDictionary();
|
||||
|
||||
co.SourceLists = new Dictionary<string,Dictionary<string,SourceListItem>>();
|
||||
var newSl = new Dictionary<string, SourceListItem>();
|
||||
// add sources...
|
||||
for (uint i = 0; i<= 19; i++)
|
||||
{
|
||||
var name = EISC.StringOutput[601 + i].StringValue;
|
||||
if(string.IsNullOrEmpty(name))
|
||||
break;
|
||||
var icon = EISC.StringOutput[651 + i].StringValue;
|
||||
var key = EISC.StringOutput[671 + i].StringValue;
|
||||
var type = EISC.StringOutput[701 + i].StringValue;
|
||||
|
||||
Debug.Console(0, this, "Adding source {0} '{1}'", key, name);
|
||||
var newSLI = new SourceListItem{
|
||||
Icon = icon,
|
||||
Name = name,
|
||||
Order = (int)i + 1,
|
||||
SourceKey = key,
|
||||
};
|
||||
newSl.Add(key, newSLI);
|
||||
|
||||
string group = "genericsource";
|
||||
if (groupMap.ContainsKey(type))
|
||||
{
|
||||
group = groupMap[type];
|
||||
}
|
||||
|
||||
// add dev to devices list
|
||||
var devConf = new DeviceConfig {
|
||||
Group = group,
|
||||
Key = key,
|
||||
Name = name,
|
||||
Type = type
|
||||
};
|
||||
co.Devices.Add(devConf);
|
||||
}
|
||||
|
||||
co.SourceLists.Add("default", newSl);
|
||||
|
||||
Debug.Console(0, this, "******* CONFIG FROM DDVC: \r{0}", JsonConvert.SerializeObject(ConfigReader.ConfigObject, Formatting.Indented));
|
||||
|
||||
var handler = ConfigurationIsReady;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, new EventArgs());
|
||||
}
|
||||
|
||||
ConfigIsLoaded = true;
|
||||
}
|
||||
|
||||
void SendFullStatus()
|
||||
{
|
||||
if (ConfigIsLoaded)
|
||||
{
|
||||
PostStatusMessage(new
|
||||
{
|
||||
isOn = EISC.BooleanOutput[BoolJoin.RoomIsOn].BoolValue,
|
||||
selectedSourceKey = EISC.StringOutput[StringJoin.SelectedSourceKey].StringValue,
|
||||
masterVolumeLevel = EISC.UShortOutput[UshortJoin.MasterVolumeLevel].UShortValue,
|
||||
masterVolumeMuteState = EISC.BooleanOutput[BoolJoin.MasterVolumeIsMuted].BoolValue
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
PostStatusMessage(new
|
||||
{
|
||||
error = "systemNotReady"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Helper for posting status message
|
||||
/// </summary>
|
||||
/// <param name="contentObject">The contents of the content object</param>
|
||||
void PostStatusMessage(object contentObject)
|
||||
{
|
||||
Parent.SendMessageToServer(JObject.FromObject(new
|
||||
{
|
||||
type = "/room/status/",
|
||||
content = contentObject
|
||||
}));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="messageType"></param>
|
||||
/// <param name="contentObject"></param>
|
||||
void PostMessage(string messageType, object contentObject)
|
||||
{
|
||||
Parent.SendMessageToServer(JObject.FromObject(new
|
||||
{
|
||||
type = messageType,
|
||||
content = contentObject
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="currentDevice"></param>
|
||||
/// <param name="args"></param>
|
||||
void EISC_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args)
|
||||
{
|
||||
if (Debug.Level >= 1)
|
||||
Debug.Console(1, this, "DDVC EISC change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
|
||||
var uo = args.Sig.UserObject;
|
||||
if (uo is Action<bool>)
|
||||
(uo as Action<bool>)(args.Sig.BoolValue);
|
||||
else if (uo is Action<ushort>)
|
||||
(uo as Action<ushort>)(args.Sig.UShortValue);
|
||||
else if (uo is Action<string>)
|
||||
(uo as Action<string>)(args.Sig.StringValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the mapping of types to groups, for setting up devices.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Dictionary<string, string> GetSourceGroupDictionary()
|
||||
{
|
||||
//type, group
|
||||
var d = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{ "laptop", "pc" },
|
||||
{ "wireless", "genericsource" },
|
||||
{ "iptv", "settopbox" }
|
||||
|
||||
};
|
||||
return d;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// updates the usercode from server
|
||||
/// </summary>
|
||||
protected override void UserCodeChange()
|
||||
{
|
||||
Debug.Console(1, this, "Server user code changed: {0}", UserCode);
|
||||
EISC.StringInput[StringJoin.UserCodeToSystem].StringValue = UserCode;
|
||||
EISC.StringInput[StringJoin.ServerUrl].StringValue = Parent.Config.ClientAppUrl;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="oldKey"></param>
|
||||
/// <param name="newKey"></param>
|
||||
void SourceChange(string oldKey, string newKey)
|
||||
{
|
||||
/* Example message
|
||||
* {
|
||||
"type":"/room/status",
|
||||
"content": {
|
||||
"selectedSourceKey": "off",
|
||||
}
|
||||
}
|
||||
*/
|
||||
//if (type == ChangeType.WillChange)
|
||||
//{
|
||||
// // Disconnect from previous source
|
||||
|
||||
// if (info != null)
|
||||
// {
|
||||
// var previousDev = info.SourceDevice;
|
||||
|
||||
// // device type interfaces
|
||||
// if (previousDev is ISetTopBoxControls)
|
||||
// (previousDev as ISetTopBoxControls).UnlinkActions(Parent);
|
||||
// // common interfaces
|
||||
// if (previousDev is IChannel)
|
||||
// (previousDev as IChannel).UnlinkActions(Parent);
|
||||
// if (previousDev is IColor)
|
||||
// (previousDev as IColor).UnlinkActions(Parent);
|
||||
// if (previousDev is IDPad)
|
||||
// (previousDev as IDPad).UnlinkActions(Parent);
|
||||
// if (previousDev is IDvr)
|
||||
// (previousDev as IDvr).UnlinkActions(Parent);
|
||||
// if (previousDev is INumericKeypad)
|
||||
// (previousDev as INumericKeypad).UnlinkActions(Parent);
|
||||
// if (previousDev is IPower)
|
||||
// (previousDev as IPower).UnlinkActions(Parent);
|
||||
// if (previousDev is ITransport)
|
||||
// (previousDev as ITransport).UnlinkActions(Parent);
|
||||
// }
|
||||
|
||||
|
||||
// var huddleRoom = room as EssentialsHuddleSpaceRoom;
|
||||
// JObject roomStatus = new JObject();
|
||||
// roomStatus.Add("selectedSourceKey", huddleRoom.CurrentSourceInfoKey);
|
||||
|
||||
// JObject message = new JObject();
|
||||
|
||||
// message.Add("type", "/room/status/");
|
||||
// message.Add("content", roomStatus);
|
||||
|
||||
// Parent.PostToServer(message);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// if (info != null)
|
||||
// {
|
||||
// var dev = info.SourceDevice;
|
||||
|
||||
// if (dev is ISetTopBoxControls)
|
||||
// (dev as ISetTopBoxControls).LinkActions(Parent);
|
||||
// if (dev is IChannel)
|
||||
// (dev as IChannel).LinkActions(Parent);
|
||||
// if (dev is IColor)
|
||||
// (dev as IColor).LinkActions(Parent);
|
||||
// if (dev is IDPad)
|
||||
// (dev as IDPad).LinkActions(Parent);
|
||||
// if (dev is IDvr)
|
||||
// (dev as IDvr).LinkActions(Parent);
|
||||
// if (dev is INumericKeypad)
|
||||
// (dev as INumericKeypad).LinkActions(Parent);
|
||||
// if (dev is IPower)
|
||||
// (dev as IPower).LinkActions(Parent);
|
||||
// if (dev is ITransport)
|
||||
// (dev as ITransport).LinkActions(Parent);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,256 +1,379 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Room.Cotija;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class CotijaEssentialsHuddleSpaceRoomBridge
|
||||
{
|
||||
CotijaSystemController Parent;
|
||||
|
||||
public EssentialsHuddleSpaceRoom Room { get; private set; }
|
||||
|
||||
public CotijaEssentialsHuddleSpaceRoomBridge(CotijaSystemController parent, EssentialsHuddleSpaceRoom room)
|
||||
{
|
||||
Parent = parent;
|
||||
Room = room;
|
||||
|
||||
// Source Changes and room off
|
||||
Parent.AddAction(string.Format(@"/room/{0}/status",Room.Key), new Action(() => Room_RoomFullStatus(Room)));
|
||||
Parent.AddAction(string.Format(@"/room/{0}/source", Room.Key), new Action<SourceSelectMessageContent>(c => room.RunRouteAction(c.SourceSelect)));
|
||||
Parent.AddAction(string.Format(@"/room/{0}/event/masterVolumeUpBtn", Room.Key), new PressAndHoldAction(b => room.CurrentVolumeControls.VolumeUp(b)));
|
||||
Parent.AddAction(string.Format(@"/room/{0}/event/masterVolumeDownBtn", Room.Key), new PressAndHoldAction(b => room.CurrentVolumeControls.VolumeDown(b)));
|
||||
Parent.AddAction(string.Format(@"/room/{0}/event/muteToggle", Room.Key), new Action(() => room.CurrentVolumeControls.MuteToggle()));
|
||||
|
||||
Room.CurrentSingleSourceChange += new SourceInfoChangeHandler(Room_CurrentSingleSourceChange);
|
||||
|
||||
Room.CurrentVolumeDeviceChange += new EventHandler<VolumeDeviceChangeEventArgs>(Room_CurrentVolumeDeviceChange);
|
||||
|
||||
Room.OnFeedback.OutputChange += new EventHandler<EventArgs>(OnFeedback_OutputChange);
|
||||
|
||||
// Registers for initial volume events, if possible
|
||||
var currentVolumeDevice = Room.CurrentVolumeControls;
|
||||
|
||||
if (currentVolumeDevice != null)
|
||||
{
|
||||
if (currentVolumeDevice is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var newDev = currentVolumeDevice as IBasicVolumeWithFeedback;
|
||||
|
||||
newDev.MuteFeedback.OutputChange += new EventHandler<EventArgs>(VolumeLevelFeedback_OutputChange);
|
||||
newDev.VolumeLevelFeedback.OutputChange += new EventHandler<EventArgs>(VolumeLevelFeedback_OutputChange);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void OnFeedback_OutputChange(object sender, EventArgs e)
|
||||
{
|
||||
/* Example message
|
||||
* {
|
||||
"type":"/room/status",
|
||||
"content": {
|
||||
"isOn": false
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
JObject roomStatus = new JObject();
|
||||
|
||||
roomStatus.Add("isOn", (sender as BoolFeedback).BoolValue);
|
||||
|
||||
JObject message = new JObject();
|
||||
|
||||
message.Add("type", "/room/status/");
|
||||
message.Add("content", roomStatus);
|
||||
|
||||
Parent.PostToServer(Room, message);
|
||||
}
|
||||
|
||||
void Room_CurrentVolumeDeviceChange(object sender, VolumeDeviceChangeEventArgs e)
|
||||
{
|
||||
if (e.OldDev is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var oldDev = e.OldDev as IBasicVolumeWithFeedback;
|
||||
|
||||
oldDev.MuteFeedback.OutputChange -= VolumeLevelFeedback_OutputChange;
|
||||
oldDev.VolumeLevelFeedback.OutputChange -= VolumeLevelFeedback_OutputChange;
|
||||
}
|
||||
|
||||
if (e.NewDev is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var newDev = e.NewDev as IBasicVolumeWithFeedback;
|
||||
|
||||
newDev.MuteFeedback.OutputChange += new EventHandler<EventArgs>(VolumeLevelFeedback_OutputChange);
|
||||
newDev.VolumeLevelFeedback.OutputChange += new EventHandler<EventArgs>(VolumeLevelFeedback_OutputChange);
|
||||
}
|
||||
}
|
||||
|
||||
void VolumeLevelFeedback_OutputChange(object sender, EventArgs e)
|
||||
{
|
||||
/* Example message
|
||||
* {
|
||||
"type":"/room/status",
|
||||
"content": {
|
||||
"masterVolumeLevel": 12345,
|
||||
"masterVolumeMuteState": false
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
var huddleRoom = Room as EssentialsHuddleSpaceRoom;
|
||||
|
||||
if(huddleRoom.CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
JObject roomStatus = new JObject();
|
||||
|
||||
if (huddleRoom.CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var currentVolumeConstrols = huddleRoom.CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
roomStatus.Add("masterVolumeLevel", currentVolumeConstrols.VolumeLevelFeedback.IntValue);
|
||||
roomStatus.Add("masterVolumeMuteState", currentVolumeConstrols.MuteFeedback.BoolValue);
|
||||
}
|
||||
|
||||
JObject message = new JObject();
|
||||
|
||||
message.Add("type", "/room/status/");
|
||||
message.Add("content", roomStatus);
|
||||
|
||||
Parent.PostToServer(Room, message);
|
||||
}
|
||||
}
|
||||
|
||||
void Room_CurrentSingleSourceChange(EssentialsRoomBase room, PepperDash.Essentials.Core.SourceListItem info, ChangeType type)
|
||||
{
|
||||
/* Example message
|
||||
* {
|
||||
"type":"/room/status",
|
||||
"content": {
|
||||
"selectedSourceKey": "off",
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (type == ChangeType.WillChange)
|
||||
{
|
||||
// Disconnect from previous source
|
||||
|
||||
if (info != null)
|
||||
{
|
||||
var previousDev = info.SourceDevice;
|
||||
|
||||
// device type interfaces
|
||||
if (previousDev is ISetTopBoxControls)
|
||||
(previousDev as ISetTopBoxControls).UnlinkActions(Parent);
|
||||
// common interfaces
|
||||
if (previousDev is IChannel)
|
||||
(previousDev as IChannel).UnlinkActions(Parent);
|
||||
if (previousDev is IColor)
|
||||
(previousDev as IColor).UnlinkActions(Parent);
|
||||
if (previousDev is IDPad)
|
||||
(previousDev as IDPad).UnlinkActions(Parent);
|
||||
if (previousDev is IDvr)
|
||||
(previousDev as IDvr).UnlinkActions(Parent);
|
||||
if (previousDev is INumericKeypad)
|
||||
(previousDev as INumericKeypad).UnlinkActions(Parent);
|
||||
if (previousDev is IPower)
|
||||
(previousDev as IPower).UnlinkActions(Parent);
|
||||
if (previousDev is ITransport)
|
||||
(previousDev as ITransport).UnlinkActions(Parent);
|
||||
}
|
||||
|
||||
JObject roomStatus = new JObject();
|
||||
|
||||
var huddleRoom = room as EssentialsHuddleSpaceRoom;
|
||||
roomStatus.Add("selectedSourceKey", huddleRoom.CurrentSourceInfoKey);
|
||||
|
||||
JObject message = new JObject();
|
||||
|
||||
message.Add("type", "/room/status/");
|
||||
message.Add("content", roomStatus);
|
||||
|
||||
Parent.PostToServer(Room, message);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (info != null)
|
||||
{
|
||||
var dev = info.SourceDevice;
|
||||
|
||||
if (dev is ISetTopBoxControls)
|
||||
(dev as ISetTopBoxControls).LinkActions(Parent);
|
||||
if (dev is IChannel)
|
||||
(dev as IChannel).LinkActions(Parent);
|
||||
if (dev is IColor)
|
||||
(dev as IColor).LinkActions(Parent);
|
||||
if (dev is IDPad)
|
||||
(dev as IDPad).LinkActions(Parent);
|
||||
if (dev is IDvr)
|
||||
(dev as IDvr).LinkActions(Parent);
|
||||
if (dev is INumericKeypad)
|
||||
(dev as INumericKeypad).LinkActions(Parent);
|
||||
if (dev is IPower)
|
||||
(dev as IPower).LinkActions(Parent);
|
||||
if (dev is ITransport)
|
||||
(dev as ITransport).LinkActions(Parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Posts the full status of the room to the server
|
||||
/// </summary>
|
||||
/// <param name="room"></param>
|
||||
void Room_RoomFullStatus(EssentialsRoomBase room)
|
||||
{
|
||||
/* Example message
|
||||
* {
|
||||
"type":"/room/status",
|
||||
"content": {
|
||||
"selectedSourceKey": "off",
|
||||
"isOn": false,
|
||||
"masterVolumeLevel": 50,
|
||||
"masterVolumeMuteState": false
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
JObject roomStatus = new JObject();
|
||||
|
||||
var huddleRoom = room as EssentialsHuddleSpaceRoom;
|
||||
roomStatus.Add("isOn", huddleRoom.OnFeedback.BoolValue);
|
||||
roomStatus.Add("selectedSourceKey", huddleRoom.CurrentSourceInfoKey);
|
||||
|
||||
|
||||
if(huddleRoom.CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var currentVolumeConstrols = huddleRoom.CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
roomStatus.Add("masterVolumeLevel", currentVolumeConstrols.VolumeLevelFeedback.IntValue);
|
||||
roomStatus.Add("masterVolumeMuteState", currentVolumeConstrols.MuteFeedback.BoolValue);
|
||||
}
|
||||
|
||||
JObject message = new JObject();
|
||||
|
||||
message.Add("type", "/room/status/");
|
||||
message.Add("content", roomStatus);
|
||||
|
||||
Parent.PostToServer(Room, message);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class SourceSelectMessageContent
|
||||
{
|
||||
public string Destination { get; set; }
|
||||
public string SourceSelect { get; set; }
|
||||
}
|
||||
|
||||
public delegate void PressAndHoldAction(bool b);
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Room.Cotija;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class CotijaEssentialsHuddleSpaceRoomBridge : CotijaBridgeBase
|
||||
{
|
||||
|
||||
public EssentialsHuddleSpaceRoom Room { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public override string RoomName
|
||||
{
|
||||
get
|
||||
{
|
||||
return Room.Name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="parent"></param>
|
||||
/// <param name="room"></param>
|
||||
public CotijaEssentialsHuddleSpaceRoomBridge(EssentialsHuddleSpaceRoom room):
|
||||
base("mobileControlBridge-essentialsHuddle", "Essentials Mobile Control Bridge-Huddle")
|
||||
{
|
||||
Room = room;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override of base: calls base to add parent and then registers actions and events.
|
||||
/// </summary>
|
||||
/// <param name="parent"></param>
|
||||
public override void AddParent(CotijaSystemController parent)
|
||||
{
|
||||
base.AddParent(parent);
|
||||
|
||||
// we add actions to the messaging system with a path, and a related action. Custom action
|
||||
// content objects can be handled in the controller's LineReceived method - and perhaps other
|
||||
// sub-controller parsing could be attached to these classes, so that the systemController
|
||||
// doesn't need to know about everything.
|
||||
|
||||
// Source Changes and room off
|
||||
Parent.AddAction(string.Format(@"/room/{0}/status", Room.Key), new Action(() => Room_RoomFullStatus(Room)));
|
||||
Parent.AddAction(string.Format(@"/room/{0}/source", Room.Key), new Action<SourceSelectMessageContent>(c => Room.RunRouteAction(c.SourceListItem)));
|
||||
Parent.AddAction(string.Format(@"/room/{0}/defaultsource", Room.Key), new Action(Room.RunDefaultRoute));
|
||||
|
||||
Parent.AddAction(string.Format(@"/room/{0}/masterVolumeLevel", Room.Key), new Action<ushort>(u =>
|
||||
(Room.CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(u)));
|
||||
Parent.AddAction(string.Format(@"/room/{0}/masterVolumeMuteToggle", Room.Key), new Action(() => Room.CurrentVolumeControls.MuteToggle()));
|
||||
|
||||
Parent.AddAction(string.Format(@"/room/{0}/shutdownStart", Room.Key), new Action(() => Room.StartShutdown(eShutdownType.Manual)));
|
||||
Parent.AddAction(string.Format(@"/room/{0}/shutdownEnd", Room.Key), new Action(() => Room.ShutdownPromptTimer.Finish()));
|
||||
Parent.AddAction(string.Format(@"/room/{0}/shutdownCancel", Room.Key), new Action(() => Room.ShutdownPromptTimer.Cancel()));
|
||||
|
||||
Room.CurrentSingleSourceChange += new SourceInfoChangeHandler(Room_CurrentSingleSourceChange);
|
||||
|
||||
Room.CurrentVolumeDeviceChange += new EventHandler<VolumeDeviceChangeEventArgs>(Room_CurrentVolumeDeviceChange);
|
||||
|
||||
Room.OnFeedback.OutputChange += new EventHandler<EventArgs>(OnFeedback_OutputChange);
|
||||
Room.IsCoolingDownFeedback.OutputChange += new EventHandler<EventArgs>(IsCoolingDownFeedback_OutputChange);
|
||||
Room.IsWarmingUpFeedback.OutputChange += new EventHandler<EventArgs>(IsWarmingUpFeedback_OutputChange);
|
||||
|
||||
Room.ShutdownPromptTimer.HasStarted += new EventHandler<EventArgs>(ShutdownPromptTimer_HasStarted);
|
||||
Room.ShutdownPromptTimer.HasFinished += new EventHandler<EventArgs>(ShutdownPromptTimer_HasFinished);
|
||||
Room.ShutdownPromptTimer.WasCancelled += new EventHandler<EventArgs>(ShutdownPromptTimer_WasCancelled);
|
||||
|
||||
// Registers for initial volume events, if possible
|
||||
var currentVolumeDevice = Room.CurrentVolumeControls;
|
||||
|
||||
if (currentVolumeDevice != null)
|
||||
{
|
||||
if (currentVolumeDevice is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var newDev = currentVolumeDevice as IBasicVolumeWithFeedback;
|
||||
|
||||
newDev.MuteFeedback.OutputChange += new EventHandler<EventArgs>(VolumeLevelFeedback_OutputChange);
|
||||
newDev.VolumeLevelFeedback.OutputChange += new EventHandler<EventArgs>(VolumeLevelFeedback_OutputChange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for cancelled shutdown
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void ShutdownPromptTimer_WasCancelled(object sender, EventArgs e)
|
||||
{
|
||||
JObject roomStatus = new JObject();
|
||||
roomStatus.Add("state", "wasCancelled");
|
||||
JObject message = new JObject();
|
||||
message.Add("type", "/room/shutdown/");
|
||||
message.Add("content", roomStatus);
|
||||
Parent.SendMessageToServer(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for when shutdown finishes
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void ShutdownPromptTimer_HasFinished(object sender, EventArgs e)
|
||||
{
|
||||
JObject roomStatus = new JObject();
|
||||
roomStatus.Add("state", "hasFinished");
|
||||
JObject message = new JObject();
|
||||
message.Add("type", "/room/shutdown/");
|
||||
message.Add("content", roomStatus);
|
||||
Parent.SendMessageToServer(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for when shutdown starts
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void ShutdownPromptTimer_HasStarted(object sender, EventArgs e)
|
||||
{
|
||||
JObject roomStatus = new JObject();
|
||||
roomStatus.Add("state", "hasStarted");
|
||||
roomStatus.Add("duration", Room.ShutdownPromptTimer.SecondsToCount);
|
||||
JObject message = new JObject();
|
||||
message.Add("type", "/room/shutdown/");
|
||||
message.Add("content", roomStatus);
|
||||
Parent.SendMessageToServer(message);
|
||||
// equivalent JS message:
|
||||
// Post( { type: '/room/status/', content: { shutdown: 'hasStarted', duration: Room.ShutdownPromptTimer.SecondsToCount })
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void IsWarmingUpFeedback_OutputChange(object sender, EventArgs e)
|
||||
{
|
||||
JObject roomStatus = new JObject();
|
||||
roomStatus.Add("isWarmingUp", (sender as BoolFeedback).BoolValue);
|
||||
JObject message = new JObject();
|
||||
message.Add("type", "/room/status/");
|
||||
message.Add("content", roomStatus);
|
||||
Parent.SendMessageToServer(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void IsCoolingDownFeedback_OutputChange(object sender, EventArgs e)
|
||||
{
|
||||
JObject roomStatus = new JObject();
|
||||
roomStatus.Add("isCoolingDown", (sender as BoolFeedback).BoolValue);
|
||||
JObject message = new JObject();
|
||||
message.Add("type", "/room/status/");
|
||||
message.Add("content", roomStatus);
|
||||
Parent.SendMessageToServer(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void OnFeedback_OutputChange(object sender, EventArgs e)
|
||||
{
|
||||
/* Example message
|
||||
* {
|
||||
"type":"/room/status",
|
||||
"content": {
|
||||
"isOn": false
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
JObject roomStatus = new JObject();
|
||||
|
||||
roomStatus.Add("isOn", (sender as BoolFeedback).BoolValue);
|
||||
|
||||
JObject message = new JObject();
|
||||
|
||||
message.Add("type", "/room/status/");
|
||||
message.Add("content", roomStatus);
|
||||
|
||||
Parent.SendMessageToServer(message);
|
||||
}
|
||||
|
||||
void Room_CurrentVolumeDeviceChange(object sender, VolumeDeviceChangeEventArgs e)
|
||||
{
|
||||
if (e.OldDev is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var oldDev = e.OldDev as IBasicVolumeWithFeedback;
|
||||
|
||||
oldDev.MuteFeedback.OutputChange -= VolumeLevelFeedback_OutputChange;
|
||||
oldDev.VolumeLevelFeedback.OutputChange -= VolumeLevelFeedback_OutputChange;
|
||||
}
|
||||
|
||||
if (e.NewDev is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var newDev = e.NewDev as IBasicVolumeWithFeedback;
|
||||
|
||||
newDev.MuteFeedback.OutputChange += new EventHandler<EventArgs>(VolumeLevelFeedback_OutputChange);
|
||||
newDev.VolumeLevelFeedback.OutputChange += new EventHandler<EventArgs>(VolumeLevelFeedback_OutputChange);
|
||||
}
|
||||
}
|
||||
|
||||
void VolumeLevelFeedback_OutputChange(object sender, EventArgs e)
|
||||
{
|
||||
/* Example message
|
||||
* {
|
||||
"type":"/room/status",
|
||||
"content": {
|
||||
"masterVolumeLevel": 12345,
|
||||
"masterVolumeMuteState": false
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
var huddleRoom = Room as EssentialsHuddleSpaceRoom;
|
||||
|
||||
if(huddleRoom.CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
JObject roomStatus = new JObject();
|
||||
|
||||
if (huddleRoom.CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var currentVolumeConstrols = huddleRoom.CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
roomStatus.Add("masterVolumeLevel", currentVolumeConstrols.VolumeLevelFeedback.IntValue);
|
||||
roomStatus.Add("masterVolumeMuteState", currentVolumeConstrols.MuteFeedback.BoolValue);
|
||||
}
|
||||
|
||||
JObject message = new JObject();
|
||||
|
||||
message.Add("type", "/room/status/");
|
||||
message.Add("content", roomStatus);
|
||||
|
||||
Parent.SendMessageToServer(message);
|
||||
}
|
||||
}
|
||||
|
||||
void Room_CurrentSingleSourceChange(EssentialsRoomBase room, PepperDash.Essentials.Core.SourceListItem info, ChangeType type)
|
||||
{
|
||||
/* Example message
|
||||
* {
|
||||
"type":"/room/status",
|
||||
"content": {
|
||||
"selectedSourceKey": "off",
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (type == ChangeType.WillChange)
|
||||
{
|
||||
// Disconnect from previous source
|
||||
|
||||
if (info != null)
|
||||
{
|
||||
var previousDev = info.SourceDevice;
|
||||
|
||||
// device type interfaces
|
||||
if (previousDev is ISetTopBoxControls)
|
||||
(previousDev as ISetTopBoxControls).UnlinkActions(Parent);
|
||||
// common interfaces
|
||||
if (previousDev is IChannel)
|
||||
(previousDev as IChannel).UnlinkActions(Parent);
|
||||
if (previousDev is IColor)
|
||||
(previousDev as IColor).UnlinkActions(Parent);
|
||||
if (previousDev is IDPad)
|
||||
(previousDev as IDPad).UnlinkActions(Parent);
|
||||
if (previousDev is IDvr)
|
||||
(previousDev as IDvr).UnlinkActions(Parent);
|
||||
if (previousDev is INumericKeypad)
|
||||
(previousDev as INumericKeypad).UnlinkActions(Parent);
|
||||
if (previousDev is IPower)
|
||||
(previousDev as IPower).UnlinkActions(Parent);
|
||||
if (previousDev is ITransport)
|
||||
(previousDev as ITransport).UnlinkActions(Parent);
|
||||
}
|
||||
}
|
||||
else // did change
|
||||
{
|
||||
if (info != null)
|
||||
{
|
||||
var dev = info.SourceDevice;
|
||||
|
||||
if (dev is ISetTopBoxControls)
|
||||
(dev as ISetTopBoxControls).LinkActions(Parent);
|
||||
if (dev is IChannel)
|
||||
(dev as IChannel).LinkActions(Parent);
|
||||
if (dev is IColor)
|
||||
(dev as IColor).LinkActions(Parent);
|
||||
if (dev is IDPad)
|
||||
(dev as IDPad).LinkActions(Parent);
|
||||
if (dev is IDvr)
|
||||
(dev as IDvr).LinkActions(Parent);
|
||||
if (dev is INumericKeypad)
|
||||
(dev as INumericKeypad).LinkActions(Parent);
|
||||
if (dev is IPower)
|
||||
(dev as IPower).LinkActions(Parent);
|
||||
if (dev is ITransport)
|
||||
(dev as ITransport).LinkActions(Parent);
|
||||
|
||||
var huddleRoom = room as EssentialsHuddleSpaceRoom;
|
||||
JObject roomStatus = new JObject();
|
||||
roomStatus.Add("selectedSourceKey", huddleRoom.CurrentSourceInfoKey);
|
||||
|
||||
JObject message = new JObject();
|
||||
|
||||
message.Add("type", "/room/status/");
|
||||
message.Add("content", roomStatus);
|
||||
|
||||
Parent.SendMessageToServer(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Posts the full status of the room to the server
|
||||
/// </summary>
|
||||
/// <param name="room"></param>
|
||||
void Room_RoomFullStatus(EssentialsRoomBase room)
|
||||
{
|
||||
/* Example message
|
||||
* {
|
||||
"type":"/room/status",
|
||||
"content": {
|
||||
"selectedSourceKey": "off",
|
||||
"isOn": false,
|
||||
"masterVolumeLevel": 50,
|
||||
"masterVolumeMuteState": false
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
JObject roomStatus = new JObject();
|
||||
|
||||
var huddleRoom = room as EssentialsHuddleSpaceRoom;
|
||||
roomStatus.Add("isOn", huddleRoom.OnFeedback.BoolValue);
|
||||
roomStatus.Add("selectedSourceKey", huddleRoom.CurrentSourceInfoKey);
|
||||
|
||||
|
||||
if(huddleRoom.CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var currentVolumeConstrols = huddleRoom.CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
roomStatus.Add("masterVolumeLevel", currentVolumeConstrols.VolumeLevelFeedback.IntValue);
|
||||
roomStatus.Add("masterVolumeMuteState", currentVolumeConstrols.MuteFeedback.BoolValue);
|
||||
}
|
||||
|
||||
JObject message = new JObject();
|
||||
|
||||
message.Add("type", "/room/status/");
|
||||
message.Add("content", roomStatus);
|
||||
|
||||
Parent.SendMessageToServer(message);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class SourceSelectMessageContent
|
||||
{
|
||||
public string SourceListItem { get; set; }
|
||||
//public string Destination { get; set; }
|
||||
//public string SourceSelect { get; set; }
|
||||
}
|
||||
|
||||
public delegate void PressAndHoldAction(bool b);
|
||||
|
||||
}
|
||||
@@ -187,8 +187,6 @@ namespace PepperDash.Essentials
|
||||
disp.IsCoolingDownFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
if (IsCoolingDownFeedback.BoolValue)
|
||||
(DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -202,6 +200,12 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
protected override void EndShutdown()
|
||||
{
|
||||
SetDefaultLevels();
|
||||
|
||||
RunDefaultRoute();
|
||||
|
||||
CrestronEnvironment.Sleep(1000);
|
||||
|
||||
RunRouteAction("roomOff");
|
||||
}
|
||||
|
||||
@@ -210,8 +214,8 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
public void RunDefaultRoute()
|
||||
{
|
||||
if (DefaultSourceItem != null)
|
||||
RunRouteAction(DefaultSourceItem);
|
||||
//if (DefaultSourceItem != null && !OnFeedback.BoolValue)
|
||||
RunRouteAction(DefaultSourceItem);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -313,7 +317,9 @@ namespace PepperDash.Essentials
|
||||
}
|
||||
|
||||
|
||||
// Set volume control on room, using default if non provided
|
||||
|
||||
|
||||
// Set volume control, using default if non provided
|
||||
IBasicVolumeControls volDev = null;
|
||||
// Handle special cases for volume control
|
||||
if (string.IsNullOrEmpty(item.VolumeControlKey)
|
||||
@@ -330,7 +336,27 @@ namespace PepperDash.Essentials
|
||||
else if (dev is IHasVolumeDevice)
|
||||
volDev = (dev as IHasVolumeDevice).VolumeDevice;
|
||||
}
|
||||
CurrentVolumeControls = volDev;
|
||||
|
||||
if (volDev != CurrentVolumeControls)
|
||||
{
|
||||
// zero the volume on the device we are leaving.
|
||||
// Set the volume to default on device we are entering
|
||||
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
SavedVolumeLevels[vd] = (uint)vd.VolumeLevelFeedback.IntValue;
|
||||
vd.SetVolume(0);
|
||||
}
|
||||
CurrentVolumeControls = volDev;
|
||||
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
ushort vol = (SavedVolumeLevels.ContainsKey(vd) ? (ushort)SavedVolumeLevels[vd] : DefaultVolume);
|
||||
vd.SetVolume(vol);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// store the name and UI info for routes
|
||||
if (item.SourceKey == "$off")
|
||||
@@ -370,7 +396,10 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
public override void SetDefaultLevels()
|
||||
{
|
||||
Debug.Console(0, this, "SetDefaultLevels not implemented");
|
||||
Debug.Console(1, this, "Restoring default levels");
|
||||
var vc = CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
if (vc != null)
|
||||
vc.SetVolume(DefaultVolume);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -12,7 +12,7 @@ using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IHasCurrentSourceInfoChange, IPrivacy
|
||||
public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IHasCurrentSourceInfoChange, IPrivacy, IHasCurrentVolumeControls
|
||||
{
|
||||
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
|
||||
public event SourceInfoChangeHandler CurrentSingleSourceChange;
|
||||
@@ -122,7 +122,8 @@ namespace PepperDash.Essentials
|
||||
string LastSourceKey;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// Sets the volume control device, and attaches/removes InUseTrackers with "audio"
|
||||
/// tag to device.
|
||||
/// </summary>
|
||||
public IBasicVolumeControls CurrentVolumeControls
|
||||
{
|
||||
@@ -190,6 +191,8 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
public IHasScheduleAwareness ScheduleSource { get { return VideoCodec as IHasScheduleAwareness; } }
|
||||
|
||||
CCriticalSection SourceSelectLock = new CCriticalSection();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
@@ -211,6 +214,7 @@ namespace PepperDash.Essentials
|
||||
else if (defaultAudio is IHasVolumeDevice)
|
||||
DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
|
||||
CurrentVolumeControls = DefaultVolumeControls;
|
||||
|
||||
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
@@ -243,7 +247,10 @@ namespace PepperDash.Essentials
|
||||
}
|
||||
|
||||
InCallFeedback = new BoolFeedback(() => VideoCodec.IsInCall);
|
||||
IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingSourceFeedback.StringValue != null);
|
||||
VideoCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate();
|
||||
|
||||
IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue);
|
||||
VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => this.IsSharingFeedback.FireUpdate();
|
||||
|
||||
// link privacy to VC (for now?)
|
||||
PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue);
|
||||
@@ -262,6 +269,13 @@ namespace PepperDash.Essentials
|
||||
protected override void EndShutdown()
|
||||
{
|
||||
VideoCodec.EndAllCalls();
|
||||
|
||||
SetDefaultLevels();
|
||||
|
||||
RunDefaultPresentRoute();
|
||||
|
||||
CrestronEnvironment.Sleep(1000);
|
||||
|
||||
RunRouteAction("roomOff");
|
||||
}
|
||||
|
||||
@@ -270,7 +284,7 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
public bool RunDefaultPresentRoute()
|
||||
{
|
||||
if (DefaultSourceItem != null)
|
||||
//if (DefaultSourceItem != null)
|
||||
RunRouteAction(DefaultSourceItem);
|
||||
return DefaultSourceItem != null;
|
||||
}
|
||||
@@ -304,6 +318,9 @@ namespace PepperDash.Essentials
|
||||
// Run this on a separate thread
|
||||
new CTimer(o =>
|
||||
{
|
||||
// try to prevent multiple simultaneous selections
|
||||
SourceSelectLock.TryEnter();
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -362,6 +379,50 @@ namespace PepperDash.Essentials
|
||||
(item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
|
||||
}
|
||||
|
||||
// See if this can be moved into common, base-class method -------------
|
||||
|
||||
|
||||
// Set volume control, using default if non provided
|
||||
IBasicVolumeControls volDev = null;
|
||||
// Handle special cases for volume control
|
||||
if (string.IsNullOrEmpty(item.VolumeControlKey)
|
||||
|| item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
|
||||
volDev = DefaultVolumeControls;
|
||||
else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
||||
volDev = DefaultDisplay as IBasicVolumeControls;
|
||||
// Or a specific device, probably rarely used.
|
||||
else
|
||||
{
|
||||
var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
|
||||
if (dev is IBasicVolumeControls)
|
||||
volDev = dev as IBasicVolumeControls;
|
||||
else if (dev is IHasVolumeDevice)
|
||||
volDev = (dev as IHasVolumeDevice).VolumeDevice;
|
||||
}
|
||||
|
||||
if (volDev != CurrentVolumeControls)
|
||||
{
|
||||
// zero the volume on the device we are leaving.
|
||||
// Set the volume to default on device we are entering
|
||||
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
SavedVolumeLevels[vd] = (uint)vd.VolumeLevelFeedback.IntValue;
|
||||
vd.SetVolume(0);
|
||||
}
|
||||
|
||||
CurrentVolumeControls = volDev;
|
||||
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
ushort vol = (SavedVolumeLevels.ContainsKey(vd) ? (ushort)SavedVolumeLevels[vd] : DefaultVolume);
|
||||
vd.SetVolume(vol);
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// store the name and UI info for routes
|
||||
if (item.SourceKey == "$off")
|
||||
{
|
||||
@@ -385,6 +446,7 @@ namespace PepperDash.Essentials
|
||||
Debug.Console(1, this, "ERROR in routing: {0}", e);
|
||||
}
|
||||
|
||||
SourceSelectLock.Leave();
|
||||
}, 0); // end of CTimer
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,8 @@ namespace PepperDash.Essentials
|
||||
|
||||
public PepperDash.Essentials.Room.EssentialsRoomEmergencyBase Emergency { get; set; }
|
||||
|
||||
public PepperDash.Essentials.Devices.Common.Microphones.MicrophonePrivacyController MicrophonePrivacy { get; set; }
|
||||
|
||||
public string LogoUrl { get; set; }
|
||||
|
||||
protected SecondsCountdownTimer RoomVacancyShutdownTimer { get; private set; }
|
||||
@@ -72,6 +74,13 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
protected abstract Func<bool> OnFeedbackFunc { get; }
|
||||
|
||||
protected Dictionary<IBasicVolumeWithFeedback, uint> SavedVolumeLevels = new Dictionary<IBasicVolumeWithFeedback, uint>();
|
||||
|
||||
/// <summary>
|
||||
/// When volume control devices change, should we zero the one that we are leaving?
|
||||
/// </summary>
|
||||
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
@@ -121,8 +130,11 @@ namespace PepperDash.Essentials
|
||||
StartRoomVacancyTimer(eVacancyMode.InShutdownWarning);
|
||||
break;
|
||||
case eVacancyMode.InShutdownWarning:
|
||||
StartShutdown(eShutdownType.Vacancy);
|
||||
break;
|
||||
{
|
||||
StartShutdown(eShutdownType.Vacancy);
|
||||
Debug.Console(0, this, "Shutting Down due to vacancy.");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -152,6 +164,8 @@ namespace PepperDash.Essentials
|
||||
RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownSeconds;
|
||||
VacancyMode = mode;
|
||||
RoomVacancyShutdownTimer.Start();
|
||||
|
||||
Debug.Console(0, this, "Vacancy Timer Started.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -179,12 +193,21 @@ namespace PepperDash.Essentials
|
||||
/// Sets the object to be used as the IOccupancyStatusProvider for the room. Can be an Occupancy Aggregator or a specific device
|
||||
/// </summary>
|
||||
/// <param name="statusProvider"></param>
|
||||
public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider)
|
||||
public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes)
|
||||
{
|
||||
if (statusProvider == null)
|
||||
{
|
||||
Debug.Console(0, this, "ERROR: Occupancy sensor device is null");
|
||||
return;
|
||||
}
|
||||
|
||||
// If status provider is fusion, set flag to remote
|
||||
if (statusProvider is PepperDash.Essentials.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase)
|
||||
OccupancyStatusProviderIsRemote = true;
|
||||
|
||||
if(timeoutMinutes > 0)
|
||||
RoomVacancyShutdownSeconds = timeoutMinutes * 60;
|
||||
|
||||
RoomOccupancy = statusProvider;
|
||||
|
||||
RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += new EventHandler<EventArgs>(RoomIsOccupiedFeedback_OutputChange);
|
||||
@@ -192,19 +215,26 @@ namespace PepperDash.Essentials
|
||||
|
||||
void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e)
|
||||
{
|
||||
if ((sender as IOccupancyStatusProvider).RoomIsOccupiedFeedback.BoolValue == false)
|
||||
if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false)
|
||||
{
|
||||
Debug.Console(1, this, "Notice: Vacancy Detected");
|
||||
// Trigger the timer when the room is vacant
|
||||
StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "Notice: Occupancy Detected");
|
||||
// Reset the timer when the room is occupied
|
||||
if(RoomVacancyShutdownTimer.IsRunningFeedback.BoolValue)
|
||||
|
||||
RoomVacancyShutdownTimer.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
//void SwapVolumeDevices(IBasicVolumeControls currentDevice, IBasicVolumeControls newDevice)
|
||||
//{
|
||||
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed
|
||||
/// </summary>
|
||||
|
||||
19813
Essentials/PepperDashEssentials/SGD/PepperDash Essentials TSW-560.sgd
Normal file
19813
Essentials/PepperDashEssentials/SGD/PepperDash Essentials TSW-560.sgd
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
20901
Essentials/PepperDashEssentials/SGD/PepperDash Essentials iPad.sgd
Normal file
20901
Essentials/PepperDashEssentials/SGD/PepperDash Essentials iPad.sgd
Normal file
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,9 @@
|
||||
public bool ShowDate { get; set; }
|
||||
public bool ShowTime { get; set; }
|
||||
public UiSetupPropertiesConfig Setup { get; set; }
|
||||
public string HeaderStyle { get; set; }
|
||||
public string HeaderStyle { get; set; }
|
||||
public bool IncludeInFusionRoomHealth { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The count of sources that will trigger the "additional" arrows to show on the SRL.
|
||||
|
||||
@@ -36,149 +36,74 @@ namespace PepperDash.Essentials
|
||||
public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id)
|
||||
: base(key, name)
|
||||
{
|
||||
AddPostActivationAction(() =>
|
||||
{
|
||||
Debug.Console(0, this, "Creating hardware...");
|
||||
type = type.ToLower();
|
||||
try
|
||||
{
|
||||
if (type == "crestronapp")
|
||||
{
|
||||
var app = new CrestronApp(id, Global.ControlSystem);
|
||||
app.ParameterProjectName.Value = props.ProjectName;
|
||||
Panel = app;
|
||||
}
|
||||
else if (type == "tsw550")
|
||||
Panel = new Tsw550(id, Global.ControlSystem);
|
||||
else if (type == "tsw552")
|
||||
Panel = new Tsw552(id, Global.ControlSystem);
|
||||
else if (type == "tsw560")
|
||||
Panel = new Tsw560(id, Global.ControlSystem);
|
||||
else if (type == "tsw750")
|
||||
Panel = new Tsw750(id, Global.ControlSystem);
|
||||
else if (type == "tsw752")
|
||||
Panel = new Tsw752(id, Global.ControlSystem);
|
||||
else if (type == "tsw760")
|
||||
Panel = new Tsw760(id, Global.ControlSystem);
|
||||
else if (type == "tsw1050")
|
||||
Panel = new Tsw1050(id, Global.ControlSystem);
|
||||
else if (type == "tsw1052")
|
||||
Panel = new Tsw1052(id, Global.ControlSystem);
|
||||
else if (type == "tsw1060")
|
||||
Panel = new Tsw1060(id, Global.ControlSystem);
|
||||
else
|
||||
{
|
||||
Debug.Console(0, this, "WARNING: Cannot create TSW controller with type '{0}'", type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, this, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Reserved sigs
|
||||
if (Panel is TswFt5ButtonSystem)
|
||||
{
|
||||
var tsw = Panel as TswFt5ButtonSystem;
|
||||
tsw.ExtenderSystemReservedSigs.Use();
|
||||
tsw.ExtenderSystemReservedSigs.DeviceExtenderSigChange
|
||||
+= ExtenderSystemReservedSigs_DeviceExtenderSigChange;
|
||||
}
|
||||
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating touchpanel hardware...");
|
||||
type = type.ToLower();
|
||||
try
|
||||
{
|
||||
if (type == "crestronapp")
|
||||
{
|
||||
var app = new CrestronApp(id, Global.ControlSystem);
|
||||
app.ParameterProjectName.Value = props.ProjectName;
|
||||
Panel = app;
|
||||
}
|
||||
else if (type == "tsw550")
|
||||
Panel = new Tsw550(id, Global.ControlSystem);
|
||||
else if (type == "tsw552")
|
||||
Panel = new Tsw552(id, Global.ControlSystem);
|
||||
else if (type == "tsw560")
|
||||
Panel = new Tsw560(id, Global.ControlSystem);
|
||||
else if (type == "tsw750")
|
||||
Panel = new Tsw750(id, Global.ControlSystem);
|
||||
else if (type == "tsw752")
|
||||
Panel = new Tsw752(id, Global.ControlSystem);
|
||||
else if (type == "tsw760")
|
||||
Panel = new Tsw760(id, Global.ControlSystem);
|
||||
else if (type == "tsw1050")
|
||||
Panel = new Tsw1050(id, Global.ControlSystem);
|
||||
else if (type == "tsw1052")
|
||||
Panel = new Tsw1052(id, Global.ControlSystem);
|
||||
else if (type == "tsw1060")
|
||||
Panel = new Tsw1060(id, Global.ControlSystem);
|
||||
else
|
||||
{
|
||||
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW controller with type '{0}'", type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
new CTimer(o =>
|
||||
{
|
||||
var regSuccess = Panel.Register();
|
||||
if (regSuccess != eDeviceRegistrationUnRegistrationResponse.Success)
|
||||
Debug.Console(0, this, "WARNING: Registration failed. Continuing, but panel may not function: {0}", regSuccess);
|
||||
// Reserved sigs
|
||||
if (Panel is TswFt5ButtonSystem)
|
||||
{
|
||||
var tsw = Panel as TswFt5ButtonSystem;
|
||||
tsw.ExtenderSystemReservedSigs.Use();
|
||||
tsw.ExtenderSystemReservedSigs.DeviceExtenderSigChange
|
||||
+= ExtenderSystemReservedSigs_DeviceExtenderSigChange;
|
||||
|
||||
// Give up cleanly if SGD is not present.
|
||||
var sgdName = @"\NVRAM\Program" + InitialParametersClass.ApplicationNumber
|
||||
+ @"\sgd\" + props.SgdFile;
|
||||
if (!File.Exists(sgdName))
|
||||
{
|
||||
Debug.Console(0, this, "WARNING: Smart object file '{0}' not present. Exiting TSW load", sgdName);
|
||||
return;
|
||||
}
|
||||
tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange);
|
||||
|
||||
Panel.LoadSmartObjects(sgdName);
|
||||
Panel.SigChange += Tsw_SigChange;
|
||||
}
|
||||
|
||||
var mainDriver = new EssentialsPanelMainInterfaceDriver(Panel, props);
|
||||
// Then the AV driver
|
||||
if (Panel.Register() != eDeviceRegistrationUnRegistrationResponse.Success)
|
||||
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Registration failed. Continuing, but panel may not function: {0}", Panel.RegistrationFailureReason);
|
||||
|
||||
// spin up different room drivers depending on room type
|
||||
var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey);
|
||||
if (room is EssentialsHuddleSpaceRoom)
|
||||
{
|
||||
Debug.Console(0, this, "Adding huddle space driver");
|
||||
var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, props);
|
||||
avDriver.CurrentRoom = room as EssentialsHuddleSpaceRoom;
|
||||
avDriver.DefaultRoomKey = props.DefaultRoomKey;
|
||||
mainDriver.AvDriver = avDriver;
|
||||
LoadAndShowDriver(mainDriver); // This is a little convoluted.
|
||||
// Give up cleanly if SGD is not present.
|
||||
var sgdName = Global.FilePathPrefix
|
||||
+ Global.DirectorySeparator + "sgd" + Global.DirectorySeparator + props.SgdFile;
|
||||
if (!File.Exists(sgdName))
|
||||
{
|
||||
Debug.Console(0, this, "ERROR: Smart object file '{0}' not present. Exiting TSW load", sgdName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Panel is TswFt5ButtonSystem)
|
||||
{
|
||||
var tsw = Panel as TswFt5ButtonSystem;
|
||||
// Wire up hard keys
|
||||
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
|
||||
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
|
||||
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
|
||||
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
|
||||
tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange);
|
||||
}
|
||||
}
|
||||
else if (room is EssentialsPresentationRoom)
|
||||
{
|
||||
Debug.Console(0, this, "Adding presentation room driver");
|
||||
var avDriver = new EssentialsPresentationPanelAvFunctionsDriver(mainDriver, props);
|
||||
avDriver.CurrentRoom = room as EssentialsPresentationRoom;
|
||||
avDriver.DefaultRoomKey = props.DefaultRoomKey;
|
||||
mainDriver.AvDriver = avDriver;
|
||||
LoadAndShowDriver(mainDriver);
|
||||
|
||||
if (Panel is TswFt5ButtonSystem)
|
||||
{
|
||||
var tsw = Panel as TswFt5ButtonSystem;
|
||||
// Wire up hard keys
|
||||
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
|
||||
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
|
||||
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
|
||||
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
|
||||
tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange);
|
||||
}
|
||||
}
|
||||
else if (room is EssentialsHuddleVtc1Room)
|
||||
{
|
||||
Debug.Console(0, this, "Adding huddle space driver");
|
||||
var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, props);
|
||||
var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(Panel, avDriver,
|
||||
(room as EssentialsHuddleVtc1Room).VideoCodec);
|
||||
avDriver.SetVideoCodecDriver(codecDriver);
|
||||
avDriver.CurrentRoom = room as EssentialsHuddleVtc1Room;
|
||||
avDriver.DefaultRoomKey = props.DefaultRoomKey;
|
||||
mainDriver.AvDriver = avDriver;
|
||||
LoadAndShowDriver(mainDriver); // This is a little convoluted.
|
||||
Panel.LoadSmartObjects(sgdName);
|
||||
Panel.SigChange += Tsw_SigChange;
|
||||
|
||||
if (Panel is TswFt5ButtonSystem)
|
||||
{
|
||||
var tsw = Panel as TswFt5ButtonSystem;
|
||||
// Wire up hard keys
|
||||
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.EndMeetingPress(); });
|
||||
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
|
||||
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
|
||||
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
|
||||
tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(0, this, "ERROR: Cannot load AvFunctionsDriver for room '{0}'", props.DefaultRoomKey);
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
|
||||
public void LoadAndShowDriver(PanelDriverBase driver)
|
||||
|
||||
@@ -207,16 +207,132 @@ namespace PepperDash.Essentials
|
||||
/// <summary>
|
||||
/// 1252
|
||||
/// </summary>
|
||||
public const uint VCRemoteViewTogglePress = 1252;
|
||||
public const uint VCLayoutTogglePress = 1252;
|
||||
/// <summary>
|
||||
/// 1253
|
||||
/// </summary>
|
||||
public const uint VCSelfViewPipTogglePress = 1253;
|
||||
/// <summary>
|
||||
/// 1254
|
||||
/// </summary>
|
||||
public const uint VCLayoutToggleEnable = 1254;
|
||||
/// <summary>
|
||||
/// 1255
|
||||
/// </summary>
|
||||
public const uint VCMinMaxPress = 1255;
|
||||
/// <summary>
|
||||
/// 1256
|
||||
/// </summary>
|
||||
public const uint VCMinMaxEnable = 1256;
|
||||
|
||||
// Letter joins start at 2921;
|
||||
|
||||
//******************************************************
|
||||
|
||||
// Letter joins start at 2921;
|
||||
// Environment Joins
|
||||
|
||||
// Popup Container
|
||||
|
||||
/// <summary>
|
||||
/// 2001 - 2004
|
||||
/// </summary>
|
||||
public const uint EnvironmentBackgroundSubpageVisibleBase = 2000;
|
||||
|
||||
|
||||
// ColumnOne
|
||||
|
||||
/// <summary>
|
||||
/// 2011 - 2015
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnOneLightingTypeVisibleBase = 2010;
|
||||
|
||||
/// <summary>
|
||||
/// 2016 - 2020
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnOneShadingTypeVisibleBase = 2015;
|
||||
|
||||
// ColumnTwo
|
||||
|
||||
/// <summary>
|
||||
/// 2021 - 2025
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnTwoLightingTypeVisibleBase = 2020;
|
||||
|
||||
/// <summary>
|
||||
/// 2026 - 2030
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnTwoShadingTypeVisibleBase = 2025;
|
||||
|
||||
// ColumnThree
|
||||
|
||||
/// <summary>
|
||||
/// 2031 - 2035
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnThreeLightingTypeVisibleBase = 2030;
|
||||
|
||||
/// <summary>
|
||||
/// 2036 - 2040
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnThreeShadingTypeVisibleBase = 2035;
|
||||
|
||||
// ColumnFour
|
||||
|
||||
/// <summary>
|
||||
/// 2041 - 2045
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnFourLightingTypeVisibleBase = 2040;
|
||||
|
||||
/// <summary>
|
||||
/// 2046 - 2050
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnFourShadingTypeVisibleBase = 2045;
|
||||
|
||||
// Button press
|
||||
|
||||
/// <summary>
|
||||
/// 2051 - 2060
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnOneButtonPressBase = 2050;
|
||||
|
||||
/// <summary>
|
||||
/// 2061 - 2070
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnTwoButtonPressBase = 2060;
|
||||
|
||||
/// <summary>
|
||||
/// 2071 - 2080
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnThreeButtonPressBase = 2070;
|
||||
|
||||
/// <summary>
|
||||
/// 2081 - 2090
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnFourButtonPressBase = 2080;
|
||||
|
||||
// Button visibility
|
||||
|
||||
/// <summary>
|
||||
/// 2151 - 2160
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnOneButtonVisibleBase = 2150;
|
||||
|
||||
/// <summary>
|
||||
/// 2161 - 2170
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnTwoButtonVisibleBase = 2160;
|
||||
|
||||
/// <summary>
|
||||
/// 2171 - 2180
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnThreeButtonVisibleBase = 2170;
|
||||
|
||||
/// <summary>
|
||||
/// 2181 - 2190
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnFourButtonVisibleBase = 2180;
|
||||
|
||||
|
||||
//******************************************************
|
||||
|
||||
/// <summary>
|
||||
/// 3101
|
||||
@@ -251,7 +367,7 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
public const uint TechSchedulerVisible = 3112;
|
||||
|
||||
//******************************************************
|
||||
//*****************************************************
|
||||
/// <summary>
|
||||
/// 3811
|
||||
/// </summary>
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
/// 1204
|
||||
/// </summary>
|
||||
public const uint VCFavoritesList = 1204;
|
||||
/// <summary>
|
||||
/// 1205 Layout buttons dynamic list
|
||||
/// </summary>
|
||||
public const uint VCLayoutsList = 1205;
|
||||
|
||||
|
||||
//******************************************************
|
||||
|
||||
@@ -68,6 +68,34 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
//public const uint KeypadText = 2901;
|
||||
|
||||
//******************************************************
|
||||
|
||||
// Environment Joins
|
||||
|
||||
/// <summary>
|
||||
/// 2001 - 2010
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnOneLabelBase = 2000;
|
||||
|
||||
/// <summary>
|
||||
/// 2011 - 2020
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnTwoLabelBase = 2010;
|
||||
|
||||
/// <summary>
|
||||
/// 2021 - 2030
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnThreeLabelBase = 2020;
|
||||
|
||||
/// <summary>
|
||||
/// 2031 - 2040
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnFourLabelBase = 2030;
|
||||
|
||||
// 2050, 2060, 2070 and 2080 reserved for column device name labels
|
||||
|
||||
//******************************************************
|
||||
|
||||
/// <summary>
|
||||
/// 3101 - This is the start of the range 3101 - 3120
|
||||
/// </summary>
|
||||
@@ -121,6 +149,10 @@ namespace PepperDash.Essentials
|
||||
/// 3906 - The separator for verbose-header text on addresses
|
||||
/// </summary>
|
||||
public const uint RoomAddressPipeText = 3906;
|
||||
/// <summary>
|
||||
/// 3907 - The user code for mobile control
|
||||
/// </summary>
|
||||
public const uint RoomUserCode = 3907;
|
||||
/// <summary>
|
||||
/// 3911
|
||||
/// </summary>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user