mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-04-14 13:07:18 +00:00
Merge remote-tracking branch 'origin/feature/ecs-967' into JTA
# Conflicts: # PepperDashEssentials/AppServer/CotijaSystemController.cs # PepperDashEssentials/Bridges/BridgeBase.cs # PepperDashEssentials/Bridges/IBasicCommunicationBridge.cs # PepperDashEssentials/PepperDashEssentials.csproj # Release Package/PepperDashEssentials.cpz # Release Package/PepperDashEssentials.dll # essentials-framework
This commit is contained in:
commit
6bbad2e0f9
65 changed files with 8550 additions and 7381 deletions
|
|
@ -15,6 +15,7 @@ using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
using PepperDash.Essentials.Room.Cotija;
|
using PepperDash.Essentials.Room.Cotija;
|
||||||
|
|
||||||
namespace PepperDash.Essentials
|
namespace PepperDash.Essentials
|
||||||
|
|
@ -23,6 +24,8 @@ namespace PepperDash.Essentials
|
||||||
{
|
{
|
||||||
WebSocketClient WSClient;
|
WebSocketClient WSClient;
|
||||||
|
|
||||||
|
//bool LinkUp;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prevents post operations from stomping on each other and getting lost
|
/// Prevents post operations from stomping on each other and getting lost
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -64,6 +67,9 @@ namespace PepperDash.Essentials
|
||||||
public CotijaSystemController(string key, string name, CotijaConfig config) : base(key, name)
|
public CotijaSystemController(string key, string name, CotijaConfig config) : base(key, name)
|
||||||
{
|
{
|
||||||
Config = config;
|
Config = config;
|
||||||
|
|
||||||
|
SystemUuid = ConfigReader.ConfigObject.SystemUuid;
|
||||||
|
|
||||||
Debug.Console(0, this, "Mobile UI controller initializing for server:{0}", config.ServerUrl);
|
Debug.Console(0, this, "Mobile UI controller initializing for server:{0}", config.ServerUrl);
|
||||||
|
|
||||||
CrestronConsole.AddNewConsoleCommand(AuthorizeSystem,
|
CrestronConsole.AddNewConsoleCommand(AuthorizeSystem,
|
||||||
|
|
@ -82,6 +88,68 @@ namespace PepperDash.Essentials
|
||||||
CrestronConsole.AddNewConsoleCommand(TestHttpRequest,
|
CrestronConsole.AddNewConsoleCommand(TestHttpRequest,
|
||||||
"mobilehttprequest", "Tests an HTTP get to URL given", ConsoleAccessLevelEnum.AccessOperator);
|
"mobilehttprequest", "Tests an HTTP get to URL given", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
|
|
||||||
|
CrestronConsole.AddNewConsoleCommand(PrintActionDictionaryPaths, "mobileshowactionpaths",
|
||||||
|
"Prints the paths in the Action Dictionary", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
|
CrestronConsole.AddNewConsoleCommand(s => ConnectWebsocketClient(), "mobileconnect",
|
||||||
|
"Forces connect of websocket", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
|
CrestronConsole.AddNewConsoleCommand(s => CleanUpWebsocketClient(), "mobiledisco",
|
||||||
|
"Disconnects websocket", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
|
|
||||||
|
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
|
||||||
|
CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If config rooms is empty or null then go
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override bool CustomActivate()
|
||||||
|
{
|
||||||
|
if (ConfigReader.ConfigObject.Rooms == null || ConfigReader.ConfigObject.Rooms.Count == 0)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Config contains no rooms. Registering with Server.");
|
||||||
|
RegisterSystemToServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.CustomActivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ethernetEventArgs"></param>
|
||||||
|
void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs args)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Ethernet status change, port {0}: {1}",
|
||||||
|
args.EthernetAdapter, args.EthernetEventType);
|
||||||
|
|
||||||
|
if (args.EthernetEventType == eEthernetEventType.LinkDown && WSClient != null && args.EthernetAdapter == WSClient.EthernetAdapter)
|
||||||
|
{
|
||||||
|
CleanUpWebsocketClient();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends message to server to indicate the system is shutting down
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="programEventType"></param>
|
||||||
|
void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
|
||||||
|
{
|
||||||
|
if (programEventType == eProgramStatusEventType.Stopping && WSClient.Connected)
|
||||||
|
{
|
||||||
|
CleanUpWebsocketClient();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PrintActionDictionaryPaths(object o)
|
||||||
|
{
|
||||||
|
Debug.Console(0, this, "ActionDictionary Contents:");
|
||||||
|
|
||||||
|
foreach (var item in ActionDictionary)
|
||||||
|
{
|
||||||
|
Debug.Console(0, this, "{0}", item.Key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -127,6 +195,7 @@ namespace PepperDash.Essentials
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Console(0, this, "Adding room bridge and sending configuration");
|
Debug.Console(0, this, "Adding room bridge and sending configuration");
|
||||||
|
//SystemUuid = ConfigReader.ConfigObject.SystemUuid;
|
||||||
RegisterSystemToServer();
|
RegisterSystemToServer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -139,6 +208,7 @@ namespace PepperDash.Essentials
|
||||||
void bridge_ConfigurationIsReady(object sender, EventArgs e)
|
void bridge_ConfigurationIsReady(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Debug.Console(1, this, "Bridge ready. Registering");
|
Debug.Console(1, this, "Bridge ready. Registering");
|
||||||
|
//SystemUuid = ConfigReader.ConfigObject.SystemUuid;
|
||||||
// send the configuration object to the server
|
// send the configuration object to the server
|
||||||
RegisterSystemToServer();
|
RegisterSystemToServer();
|
||||||
}
|
}
|
||||||
|
|
@ -158,6 +228,14 @@ namespace PepperDash.Essentials
|
||||||
/// <param name="command"></param>
|
/// <param name="command"></param>
|
||||||
void AuthorizeSystem(string code)
|
void AuthorizeSystem(string code)
|
||||||
{
|
{
|
||||||
|
//SystemUuid = ConfigReader.ConfigObject.SystemUuid;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(SystemUuid))
|
||||||
|
{
|
||||||
|
CrestronConsole.ConsoleCommandResponse("System does not have a UUID. Please ensure proper portal-format configuration is loaded and restart.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(code))
|
if (string.IsNullOrEmpty(code))
|
||||||
{
|
{
|
||||||
CrestronConsole.ConsoleCommandResponse("Please enter a user code to authorize a system");
|
CrestronConsole.ConsoleCommandResponse("Please enter a user code to authorize a system");
|
||||||
|
|
@ -184,6 +262,7 @@ namespace PepperDash.Essentials
|
||||||
if (r.Code == 200)
|
if (r.Code == 200)
|
||||||
{
|
{
|
||||||
Debug.Console(0, "System authorized, sending config.");
|
Debug.Console(0, "System authorized, sending config.");
|
||||||
|
#warning This registration may need to wait for config ready. Maybe.
|
||||||
RegisterSystemToServer();
|
RegisterSystemToServer();
|
||||||
}
|
}
|
||||||
else if (r.Code == 404)
|
else if (r.Code == 404)
|
||||||
|
|
@ -244,58 +323,101 @@ namespace PepperDash.Essentials
|
||||||
/// <param name="url">URL of the server, including the port number, if not 80. Format: "serverUrlOrIp:port"</param>
|
/// <param name="url">URL of the server, including the port number, if not 80. Format: "serverUrlOrIp:port"</param>
|
||||||
void RegisterSystemToServer()
|
void RegisterSystemToServer()
|
||||||
{
|
{
|
||||||
var ready = RegisterLockEvent.Wait(20000);
|
ConnectWebsocketClient();
|
||||||
if (!ready)
|
|
||||||
{
|
|
||||||
Debug.Console(1, this, "RegisterSystemToServer failed to enter after 20 seconds. Ignoring");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
RegisterLockEvent.Reset();
|
|
||||||
|
|
||||||
try
|
/// <summary>
|
||||||
|
/// Connects the Websocket Client
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="o"></param>
|
||||||
|
void ConnectWebsocketClient()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Debug.Console(1, this, "Initializing Stream client to server.");
|
||||||
|
|
||||||
|
if (WSClient != null)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Cleaning up previous socket");
|
||||||
|
CleanUpWebsocketClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
WSClient = new WebSocketClient();
|
||||||
|
WSClient.URL = string.Format("wss://{0}/system/join/{1}", Config.ServerUrl, this.SystemUuid);
|
||||||
|
WSClient.ConnectionCallBack = Websocket_ConnectCallback;
|
||||||
|
WSClient.ConnectAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="code"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
int Websocket_ConnectCallback(WebSocketClient.WEBSOCKET_RESULT_CODES code)
|
||||||
|
{
|
||||||
|
if (code == WebSocketClient.WEBSOCKET_RESULT_CODES.WEBSOCKET_CLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
StopServerReconnectTimer();
|
||||||
|
Debug.Console(1, this, "Websocket connected");
|
||||||
|
WSClient.DisconnectCallBack = Websocket_DisconnectCallback;
|
||||||
|
WSClient.SendCallBack = Websocket_SendCallback;
|
||||||
|
WSClient.ReceiveCallBack = Websocket_ReceiveCallback;
|
||||||
|
WSClient.ReceiveAsync();
|
||||||
|
SendMessageObjectToServer(new
|
||||||
|
{
|
||||||
|
type = "hello"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (code == WebSocketClient.WEBSOCKET_RESULT_CODES.WEBSOCKET_CLIENT_HTTP_HANDSHAKE_TOKEN_ERROR)
|
||||||
|
{
|
||||||
|
// This is the case when app server is running behind a websever and app server is down
|
||||||
|
Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Web socket connection failed. Check that app server is running behind web server");
|
||||||
|
}
|
||||||
|
else if (code == WebSocketClient.WEBSOCKET_RESULT_CODES.WEBSOCKET_CLIENT_SOCKET_CONNECTION_FAILED)
|
||||||
|
{
|
||||||
|
// this will be the case when webserver is unreachable
|
||||||
|
Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Web socket connection failed");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Web socket connection failure: {0}", code);
|
||||||
|
}
|
||||||
|
StartServerReconnectTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// After a "hello" from the server, sends config and stuff
|
||||||
|
/// </summary>
|
||||||
|
void SendInitialMessage()
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Sending initial join message");
|
||||||
var confObject = ConfigReader.ConfigObject;
|
var confObject = ConfigReader.ConfigObject;
|
||||||
confObject.Info.RuntimeInfo.AppName = Assembly.GetExecutingAssembly().GetName().Name;
|
confObject.Info.RuntimeInfo.AppName = Assembly.GetExecutingAssembly().GetName().Name;
|
||||||
var version = Assembly.GetExecutingAssembly().GetName().Version;
|
var version = Assembly.GetExecutingAssembly().GetName().Version;
|
||||||
confObject.Info.RuntimeInfo.AssemblyVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
|
confObject.Info.RuntimeInfo.AssemblyVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
|
||||||
|
|
||||||
|
var msg = new
|
||||||
# warning I commented this out...read only property...Bad merge? JTA 2018-08-13 ;
|
|
||||||
//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.");
|
type = "join",
|
||||||
}
|
content = new
|
||||||
else
|
|
||||||
{
|
{
|
||||||
var regClient = new HttpClient();
|
config = confObject
|
||||||
regClient.Verbose = true;
|
}
|
||||||
regClient.KeepAlive = true;
|
};
|
||||||
|
SendMessageObjectToServer(msg);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
/// <summary>
|
||||||
catch (Exception e)
|
/// Sends any object type to server
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="o"></param>
|
||||||
|
public void SendMessageObjectToServer(object o)
|
||||||
{
|
{
|
||||||
Debug.Console(0, this, "ERROR: Initilizing Room: {0}", e);
|
SendMessageToServer(JObject.FromObject(o));
|
||||||
RegisterLockEvent.Set();
|
|
||||||
StartReconnectTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -305,77 +427,66 @@ namespace PepperDash.Essentials
|
||||||
/// <param name="o">object to be serialized and sent in post body</param>
|
/// <param name="o">object to be serialized and sent in post body</param>
|
||||||
public void SendMessageToServer(JObject o)
|
public void SendMessageToServer(JObject o)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (WSClient != null && WSClient.Connected)
|
if (WSClient != null && WSClient.Connected)
|
||||||
{
|
{
|
||||||
string message = JsonConvert.SerializeObject(o, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
|
string message = JsonConvert.SerializeObject(o, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
|
||||||
Debug.Console(1, this, "Message TX: {0}", message);
|
Debug.Console(1, this, "Message TX: {0}", message);
|
||||||
var messageBytes = System.Text.Encoding.UTF8.GetBytes(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);
|
var result = 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);
|
if (result != WebSocketClient.WEBSOCKET_RESULT_CODES.WEBSOCKET_CLIENT_SUCCESS)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Socket send result error: {0}", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!WSClient.Connected)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Cannot send. Not connected {0}");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disconnects the SSE Client and stops the heartbeat timer
|
/// Disconnects the SSE Client and stops the heartbeat timer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="command"></param>
|
/// <param name="command"></param>
|
||||||
void DisconnectStreamClient(string command)
|
void CleanUpWebsocketClient()
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Disconnecting websocket");
|
||||||
|
if (WSClient != null)
|
||||||
|
{
|
||||||
|
WSClient.SendCallBack = null;
|
||||||
|
WSClient.ReceiveCallBack = null;
|
||||||
|
WSClient.ConnectionCallBack = null;
|
||||||
|
WSClient.DisconnectCallBack = null;
|
||||||
|
if (WSClient.Connected)
|
||||||
{
|
{
|
||||||
//if(SseClient != null)
|
|
||||||
// SseClient.Disconnect();
|
|
||||||
|
|
||||||
if (WSClient != null && WSClient.Connected)
|
|
||||||
WSClient.Disconnect();
|
WSClient.Disconnect();
|
||||||
|
}
|
||||||
if (ServerHeartbeatCheckTimer != null)
|
WSClient = null;
|
||||||
{
|
|
||||||
ServerHeartbeatCheckTimer.Stop();
|
|
||||||
|
|
||||||
ServerHeartbeatCheckTimer = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The callback that fires when we get a response from our registration attempt
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="resp"></param>
|
/// <param name="dueTime"></param>
|
||||||
/// <param name="err"></param>
|
/// <param name="repeatTime"></param>
|
||||||
void RegistrationConnectionCallback(HttpClientResponse resp, HTTP_CALLBACK_ERROR err)
|
void StartServerReconnectTimer()
|
||||||
{
|
{
|
||||||
CheckHttpDebug(resp, err);
|
StopServerReconnectTimer();
|
||||||
Debug.Console(1, this, "RegistrationConnectionCallback: {0}", err);
|
ServerReconnectTimer = new CTimer(ReconnectToServerTimerCallback, ServerReconnectInterval);
|
||||||
try
|
Debug.Console(1, this, "Reconnect Timer Started.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Does what it says
|
||||||
|
/// </summary>
|
||||||
|
void StopServerReconnectTimer()
|
||||||
{
|
{
|
||||||
if (resp != null && resp.Code == 200)
|
if (ServerReconnectTimer != null)
|
||||||
{
|
|
||||||
if(ServerReconnectTimer != null)
|
|
||||||
{
|
{
|
||||||
ServerReconnectTimer.Stop();
|
ServerReconnectTimer.Stop();
|
||||||
ServerReconnectTimer = null;
|
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>
|
/// <summary>
|
||||||
|
|
@ -390,23 +501,8 @@ namespace PepperDash.Essentials
|
||||||
ServerHeartbeatCheckTimer.Stop();
|
ServerHeartbeatCheckTimer.Stop();
|
||||||
ServerHeartbeatCheckTimer = null;
|
ServerHeartbeatCheckTimer = null;
|
||||||
}
|
}
|
||||||
StartReconnectTimer();
|
CleanUpWebsocketClient();
|
||||||
}
|
StartServerReconnectTimer();
|
||||||
|
|
||||||
/// <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>
|
||||||
|
|
@ -419,34 +515,39 @@ namespace PepperDash.Essentials
|
||||||
if (ServerHeartbeatCheckTimer == null)
|
if (ServerHeartbeatCheckTimer == null)
|
||||||
{
|
{
|
||||||
ServerHeartbeatCheckTimer = new CTimer(HeartbeatExpiredTimerCallback, null, ServerHeartbeatInterval, ServerHeartbeatInterval);
|
ServerHeartbeatCheckTimer = new CTimer(HeartbeatExpiredTimerCallback, null, ServerHeartbeatInterval, ServerHeartbeatInterval);
|
||||||
|
|
||||||
Debug.Console(1, this, "Heartbeat Timer Started.");
|
Debug.Console(1, this, "Heartbeat Timer Started.");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
ServerHeartbeatCheckTimer.Reset(ServerHeartbeatInterval, ServerHeartbeatInterval);
|
ServerHeartbeatCheckTimer.Reset(ServerHeartbeatInterval, ServerHeartbeatInterval);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Connects the SSE Client
|
/// Waits two and goes again
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="o"></param>
|
void ReconnectStreamClient()
|
||||||
void ConnectStreamClient()
|
|
||||||
{
|
{
|
||||||
Debug.Console(0, this, "Initializing Stream client to server.");
|
new CTimer(o => ConnectWebsocketClient(), 2000);
|
||||||
|
}
|
||||||
|
|
||||||
if (WSClient == null)
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="code"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
int Websocket_DisconnectCallback(WebSocketClient.WEBSOCKET_RESULT_CODES code, object o)
|
||||||
{
|
{
|
||||||
WSClient = new WebSocketClient();
|
Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Websocket disconnected with code: {0}", code);
|
||||||
}
|
|
||||||
WSClient.URL = string.Format("wss://{0}/system/join/{1}", Config.ServerUrl, this.SystemUuid);
|
if (ServerHeartbeatCheckTimer != null)
|
||||||
WSClient.Connect();
|
ServerHeartbeatCheckTimer.Stop();
|
||||||
Debug.Console(0, this, "Websocket connected");
|
// Start the reconnect timer
|
||||||
WSClient.ReceiveCallBack = WebsocketReceiveCallback;
|
StartServerReconnectTimer();
|
||||||
//WSClient.SendCallBack = WebsocketSendCallback;
|
return 0;
|
||||||
WSClient.ReceiveAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resets reconnect timer and updates usercode
|
/// Resets reconnect timer and updates usercode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -455,7 +556,7 @@ namespace PepperDash.Essentials
|
||||||
{
|
{
|
||||||
SendMessageToServer(JObject.FromObject(new
|
SendMessageToServer(JObject.FromObject(new
|
||||||
{
|
{
|
||||||
type = "/heartbeat-ack"
|
type = "/system/heartbeatAck"
|
||||||
}));
|
}));
|
||||||
|
|
||||||
var code = content["userCode"];
|
var code = content["userCode"];
|
||||||
|
|
@ -478,14 +579,28 @@ namespace PepperDash.Essentials
|
||||||
void CheckHttpDebug(HttpClientResponse r, HTTP_CALLBACK_ERROR e)
|
void CheckHttpDebug(HttpClientResponse r, HTTP_CALLBACK_ERROR e)
|
||||||
{
|
{
|
||||||
if (HttpDebugEnabled)
|
if (HttpDebugEnabled)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
Debug.Console(0, this, "------ Begin HTTP Debug ---------------------------------------");
|
Debug.Console(0, this, "------ Begin HTTP Debug ---------------------------------------");
|
||||||
Debug.Console(0, this, "HTTP Response URL: {0}", r.ResponseUrl.ToString());
|
if (r != null)
|
||||||
Debug.Console(0, this, "HTTP Response 'error' {0}", e);
|
{
|
||||||
|
Debug.Console(0, this, "HTTP Response URL: {0}", r.ResponseUrl != null ? r.ResponseUrl.ToString() : "NONE");
|
||||||
Debug.Console(0, this, "HTTP Response code: {0}", r.Code);
|
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, "HTTP Response content: \r{0}", r.ContentString);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Console(0, this, "No HTTP response");
|
||||||
|
}
|
||||||
|
Debug.Console(0, this, "HTTP Response 'error' {0}", e);
|
||||||
Debug.Console(0, this, "------ End HTTP Debug -----------------------------------------");
|
Debug.Console(0, this, "------ End HTTP Debug -----------------------------------------");
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.Console(0, this, "HttpDebugError: {0}", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -495,14 +610,28 @@ namespace PepperDash.Essentials
|
||||||
/// <param name="length"></param>
|
/// <param name="length"></param>
|
||||||
/// <param name="opcode"></param>
|
/// <param name="opcode"></param>
|
||||||
/// <param name="err"></param>
|
/// <param name="err"></param>
|
||||||
int WebsocketReceiveCallback(byte[] data, uint length, WebSocketClient.WEBSOCKET_PACKET_TYPES opcode,
|
int Websocket_ReceiveCallback(byte[] data, uint length, WebSocketClient.WEBSOCKET_PACKET_TYPES opcode,
|
||||||
WebSocketClient.WEBSOCKET_RESULT_CODES err)
|
WebSocketClient.WEBSOCKET_RESULT_CODES err)
|
||||||
|
{
|
||||||
|
if (opcode == WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME)
|
||||||
{
|
{
|
||||||
var rx = System.Text.Encoding.UTF8.GetString(data, 0, (int)length);
|
var rx = System.Text.Encoding.UTF8.GetString(data, 0, (int)length);
|
||||||
if(rx.Length > 0)
|
if (rx.Length > 0)
|
||||||
ParseStreamRx(rx);
|
ParseStreamRx(rx);
|
||||||
WSClient.ReceiveAsync();
|
WSClient.ReceiveAsync();
|
||||||
return 1;
|
}
|
||||||
|
|
||||||
|
else if (opcode == WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__CLOSE)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Websocket disconnect received from remote");
|
||||||
|
CleanUpWebsocketClient();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "websocket rx opcode/err {0}/{1}", opcode, err);
|
||||||
|
WSClient.ReceiveAsync();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -510,10 +639,10 @@ namespace PepperDash.Essentials
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="result"></param>
|
/// <param name="result"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
int WebsocketSendCallback(Crestron.SimplSharp.CrestronWebSocketClient.WebSocketClient.WEBSOCKET_RESULT_CODES result)
|
int Websocket_SendCallback(Crestron.SimplSharp.CrestronWebSocketClient.WebSocketClient.WEBSOCKET_RESULT_CODES result)
|
||||||
{
|
{
|
||||||
Debug.Console(1, this, "SendCallback result: {0}", result);
|
if(result != WebSocketClient.WEBSOCKET_RESULT_CODES.WEBSOCKET_CLIENT_SUCCESS)
|
||||||
|
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "SendCallback questionable result: {0}", result);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -527,7 +656,7 @@ namespace PepperDash.Essentials
|
||||||
if(string.IsNullOrEmpty(message))
|
if(string.IsNullOrEmpty(message))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Debug.Console(1, this, "Message RX: '{0}'", message);
|
Debug.Console(1, this, "Message RX: {0}", message);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var messageObj = JObject.Parse(message);
|
var messageObj = JObject.Parse(message);
|
||||||
|
|
@ -536,6 +665,7 @@ namespace PepperDash.Essentials
|
||||||
|
|
||||||
if (type == "hello")
|
if (type == "hello")
|
||||||
{
|
{
|
||||||
|
SendInitialMessage();
|
||||||
ResetOrStartHearbeatTimer();
|
ResetOrStartHearbeatTimer();
|
||||||
}
|
}
|
||||||
else if (type == "/system/heartbeat")
|
else if (type == "/system/heartbeat")
|
||||||
|
|
@ -544,11 +674,11 @@ namespace PepperDash.Essentials
|
||||||
}
|
}
|
||||||
else if (type == "close")
|
else if (type == "close")
|
||||||
{
|
{
|
||||||
WSClient.Disconnect();
|
Debug.Console(1, this, "Received close message from server.");
|
||||||
|
// DisconnectWebsocketClient();
|
||||||
|
|
||||||
|
if (ServerHeartbeatCheckTimer != null)
|
||||||
ServerHeartbeatCheckTimer.Stop();
|
ServerHeartbeatCheckTimer.Stop();
|
||||||
// Start the reconnect timer
|
|
||||||
StartReconnectTimer();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -585,7 +715,7 @@ namespace PepperDash.Essentials
|
||||||
}
|
}
|
||||||
case "held":
|
case "held":
|
||||||
{
|
{
|
||||||
if (!PushedActions.ContainsKey(type))
|
if (PushedActions.ContainsKey(type))
|
||||||
{
|
{
|
||||||
PushedActions[type].Reset(ButtonHeartbeatInterval, ButtonHeartbeatInterval);
|
PushedActions[type].Reset(ButtonHeartbeatInterval, ButtonHeartbeatInterval);
|
||||||
}
|
}
|
||||||
|
|
@ -14,9 +14,9 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
{
|
{
|
||||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||||
|
|
||||||
controller.AddAction(prefix + "chanup", new PressAndHoldAction(dev.ChannelUp));
|
controller.AddAction(prefix + "chanUp", new PressAndHoldAction(dev.ChannelUp));
|
||||||
controller.AddAction(prefix + "chandown", new PressAndHoldAction(dev.ChannelDown));
|
controller.AddAction(prefix + "chanDown", new PressAndHoldAction(dev.ChannelDown));
|
||||||
controller.AddAction(prefix + "lastchan", new PressAndHoldAction(dev.LastChannel));
|
controller.AddAction(prefix + "lastChan", new PressAndHoldAction(dev.LastChannel));
|
||||||
controller.AddAction(prefix + "guide", new PressAndHoldAction(dev.Guide));
|
controller.AddAction(prefix + "guide", new PressAndHoldAction(dev.Guide));
|
||||||
controller.AddAction(prefix + "info", new PressAndHoldAction(dev.Info));
|
controller.AddAction(prefix + "info", new PressAndHoldAction(dev.Info));
|
||||||
controller.AddAction(prefix + "exit", new PressAndHoldAction(dev.Exit));
|
controller.AddAction(prefix + "exit", new PressAndHoldAction(dev.Exit));
|
||||||
|
|
@ -26,9 +26,9 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
{
|
{
|
||||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||||
|
|
||||||
controller.RemoveAction(prefix + "chanup");
|
controller.RemoveAction(prefix + "chanUp");
|
||||||
controller.RemoveAction(prefix + "chandown");
|
controller.RemoveAction(prefix + "chanDown");
|
||||||
controller.RemoveAction(prefix + "lastchan");
|
controller.RemoveAction(prefix + "lastChan");
|
||||||
controller.RemoveAction(prefix + "guide");
|
controller.RemoveAction(prefix + "guide");
|
||||||
controller.RemoveAction(prefix + "info");
|
controller.RemoveAction(prefix + "info");
|
||||||
controller.RemoveAction(prefix + "exit");
|
controller.RemoveAction(prefix + "exit");
|
||||||
|
|
@ -24,8 +24,8 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
controller.AddAction(prefix + "num7", new PressAndHoldAction(dev.Digit0));
|
controller.AddAction(prefix + "num7", new PressAndHoldAction(dev.Digit0));
|
||||||
controller.AddAction(prefix + "num8", new PressAndHoldAction(dev.Digit0));
|
controller.AddAction(prefix + "num8", new PressAndHoldAction(dev.Digit0));
|
||||||
controller.AddAction(prefix + "num9", new PressAndHoldAction(dev.Digit0));
|
controller.AddAction(prefix + "num9", new PressAndHoldAction(dev.Digit0));
|
||||||
controller.AddAction(prefix + "dash", new PressAndHoldAction(dev.KeypadAccessoryButton1));
|
controller.AddAction(prefix + "numDash", new PressAndHoldAction(dev.KeypadAccessoryButton1));
|
||||||
controller.AddAction(prefix + "enter", new PressAndHoldAction(dev.KeypadAccessoryButton2));
|
controller.AddAction(prefix + "numEnter", new PressAndHoldAction(dev.KeypadAccessoryButton2));
|
||||||
// Deal with the Accessory functions on the numpad later
|
// Deal with the Accessory functions on the numpad later
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,8 +43,8 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
controller.RemoveAction(prefix + "num7");
|
controller.RemoveAction(prefix + "num7");
|
||||||
controller.RemoveAction(prefix + "num8");
|
controller.RemoveAction(prefix + "num8");
|
||||||
controller.RemoveAction(prefix + "num9");
|
controller.RemoveAction(prefix + "num9");
|
||||||
controller.RemoveAction(prefix + "dash");
|
controller.RemoveAction(prefix + "numDash");
|
||||||
controller.RemoveAction(prefix + "enter");
|
controller.RemoveAction(prefix + "numEnter");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -14,18 +14,18 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
{
|
{
|
||||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||||
|
|
||||||
controller.AddAction(prefix + "poweron", new Action(dev.PowerOn));
|
controller.AddAction(prefix + "powerOn", new Action(dev.PowerOn));
|
||||||
controller.AddAction(prefix + "poweroff", new Action(dev.PowerOff));
|
controller.AddAction(prefix + "powerOff", new Action(dev.PowerOff));
|
||||||
controller.AddAction(prefix + "powertoggle", new Action(dev.PowerToggle));
|
controller.AddAction(prefix + "powerToggle", new Action(dev.PowerToggle));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UnlinkActions(this IPower dev, CotijaSystemController controller)
|
public static void UnlinkActions(this IPower dev, CotijaSystemController controller)
|
||||||
{
|
{
|
||||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||||
|
|
||||||
controller.RemoveAction(prefix + "poweron");
|
controller.RemoveAction(prefix + "powerOn");
|
||||||
controller.RemoveAction(prefix + "poweroff");
|
controller.RemoveAction(prefix + "powerOff");
|
||||||
controller.RemoveAction(prefix + "powertoggle");
|
controller.RemoveAction(prefix + "powerToggle");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
{
|
{
|
||||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||||
|
|
||||||
controller.AddAction(prefix + "dvrlist", new PressAndHoldAction(dev.DvrList));
|
controller.AddAction(prefix + "dvrList", new PressAndHoldAction(dev.DvrList));
|
||||||
controller.AddAction(prefix + "replay", new PressAndHoldAction(dev.Replay));
|
controller.AddAction(prefix + "replay", new PressAndHoldAction(dev.Replay));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
{
|
{
|
||||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||||
|
|
||||||
controller.RemoveAction(prefix + "dvrlist");
|
controller.RemoveAction(prefix + "dvrList");
|
||||||
controller.RemoveAction(prefix + "replay");
|
controller.RemoveAction(prefix + "replay");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -17,8 +17,8 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
controller.AddAction(prefix + "play", new PressAndHoldAction(dev.Play));
|
controller.AddAction(prefix + "play", new PressAndHoldAction(dev.Play));
|
||||||
controller.AddAction(prefix + "pause", new PressAndHoldAction(dev.Pause));
|
controller.AddAction(prefix + "pause", new PressAndHoldAction(dev.Pause));
|
||||||
controller.AddAction(prefix + "stop", new PressAndHoldAction(dev.Stop));
|
controller.AddAction(prefix + "stop", new PressAndHoldAction(dev.Stop));
|
||||||
controller.AddAction(prefix + "prevtrack", new PressAndHoldAction(dev.ChapPlus));
|
controller.AddAction(prefix + "prevTrack", new PressAndHoldAction(dev.ChapPlus));
|
||||||
controller.AddAction(prefix + "nexttrack", new PressAndHoldAction(dev.ChapMinus));
|
controller.AddAction(prefix + "nextTrack", new PressAndHoldAction(dev.ChapMinus));
|
||||||
controller.AddAction(prefix + "rewind", new PressAndHoldAction(dev.Rewind));
|
controller.AddAction(prefix + "rewind", new PressAndHoldAction(dev.Rewind));
|
||||||
controller.AddAction(prefix + "ffwd", new PressAndHoldAction(dev.FFwd));
|
controller.AddAction(prefix + "ffwd", new PressAndHoldAction(dev.FFwd));
|
||||||
controller.AddAction(prefix + "record", new PressAndHoldAction(dev.Record));
|
controller.AddAction(prefix + "record", new PressAndHoldAction(dev.Record));
|
||||||
|
|
@ -31,8 +31,8 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
controller.RemoveAction(prefix + "play");
|
controller.RemoveAction(prefix + "play");
|
||||||
controller.RemoveAction(prefix + "pause");
|
controller.RemoveAction(prefix + "pause");
|
||||||
controller.RemoveAction(prefix + "stop");
|
controller.RemoveAction(prefix + "stop");
|
||||||
controller.RemoveAction(prefix + "prevtrack");
|
controller.RemoveAction(prefix + "prevTrack");
|
||||||
controller.RemoveAction(prefix + "nexttrack");
|
controller.RemoveAction(prefix + "nextTrack");
|
||||||
controller.RemoveAction(prefix + "rewind");
|
controller.RemoveAction(prefix + "rewind");
|
||||||
controller.RemoveAction(prefix + "ffwd");
|
controller.RemoveAction(prefix + "ffwd");
|
||||||
controller.RemoveAction(prefix + "record");
|
controller.RemoveAction(prefix + "record");
|
||||||
60
PepperDashEssentials/AppServer/Interfaces.cs
Normal file
60
PepperDashEssentials/AppServer/Interfaces.cs
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
|
||||||
|
using PepperDash.Essentials.Core;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Room.Cotija
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a room whose configuration is derived from runtime data,
|
||||||
|
/// perhaps from another program, and that the data may not be fully
|
||||||
|
/// available at startup.
|
||||||
|
/// </summary>
|
||||||
|
public interface IDelayedConfiguration
|
||||||
|
{
|
||||||
|
event EventHandler<EventArgs> ConfigurationIsReady;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// For rooms with a single presentation source, change event
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasCurrentSourceInfoChange
|
||||||
|
{
|
||||||
|
string CurrentSourceInfoKey { get; }
|
||||||
|
SourceListItem CurrentSourceInfo { get; }
|
||||||
|
event SourceInfoChangeHandler CurrentSingleSourceChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For rooms with routing
|
||||||
|
/// </summary>
|
||||||
|
public interface IRunRouteAction
|
||||||
|
{
|
||||||
|
void RunRouteAction(string routeKey);
|
||||||
|
|
||||||
|
void RunRouteAction(string routeKey, Action successCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For rooms that default presentation only routing
|
||||||
|
/// </summary>
|
||||||
|
public interface IRunDefaultPresentRoute
|
||||||
|
{
|
||||||
|
bool RunDefaultPresentRoute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For rooms that have default presentation and calling routes
|
||||||
|
/// </summary>
|
||||||
|
public interface IRunDefaultCallRoute : IRunDefaultPresentRoute
|
||||||
|
{
|
||||||
|
bool RunDefaultCallRoute();
|
||||||
|
}
|
||||||
|
}
|
||||||
167
PepperDashEssentials/AppServer/Messengers/AtcDdvc01Messenger.cs
Normal file
167
PepperDashEssentials/AppServer/Messengers/AtcDdvc01Messenger.cs
Normal file
|
|
@ -0,0 +1,167 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
|
using Crestron.SimplSharpPro.EthernetCommunication;
|
||||||
|
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.Devices.Common.Codec;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
|
{
|
||||||
|
public class Ddvc01AtcMessenger : MessengerBase
|
||||||
|
{
|
||||||
|
BasicTriList EISC;
|
||||||
|
|
||||||
|
const uint BDialHangup = 221;
|
||||||
|
const uint BIncomingAnswer = 251;
|
||||||
|
const uint BIncomingReject = 252;
|
||||||
|
const uint BSpeedDial1 = 241;
|
||||||
|
const uint BSpeedDial2 = 242;
|
||||||
|
const uint BSpeedDial3 = 243;
|
||||||
|
const uint BSpeedDial4 = 244;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 201
|
||||||
|
/// </summary>
|
||||||
|
const uint SCurrentDialString = 201;
|
||||||
|
/// <summary>
|
||||||
|
/// 211
|
||||||
|
/// </summary>
|
||||||
|
const uint SCurrentCallString = 211;
|
||||||
|
/// <summary>
|
||||||
|
/// 221
|
||||||
|
/// </summary>
|
||||||
|
const uint SHookState = 221;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
Dictionary<string, uint> DTMFMap = new Dictionary<string, uint>
|
||||||
|
{
|
||||||
|
{ "1", 201 },
|
||||||
|
{ "2", 202 },
|
||||||
|
{ "3", 203 },
|
||||||
|
{ "4", 204 },
|
||||||
|
{ "5", 205 },
|
||||||
|
{ "6", 206 },
|
||||||
|
{ "7", 207 },
|
||||||
|
{ "8", 208 },
|
||||||
|
{ "9", 209 },
|
||||||
|
{ "0", 210 },
|
||||||
|
{ "*", 211 },
|
||||||
|
{ "#", 212 },
|
||||||
|
};
|
||||||
|
|
||||||
|
CodecActiveCallItem CurrentCallItem;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eisc"></param>
|
||||||
|
/// <param name="messagePath"></param>
|
||||||
|
public Ddvc01AtcMessenger(string key, BasicTriList eisc, string messagePath)
|
||||||
|
: base(key, messagePath)
|
||||||
|
{
|
||||||
|
EISC = eisc;
|
||||||
|
|
||||||
|
CurrentCallItem = new CodecActiveCallItem();
|
||||||
|
CurrentCallItem.Type = eCodecCallType.Audio;
|
||||||
|
CurrentCallItem.Id = "-audio-";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
void SendFullStatus()
|
||||||
|
{
|
||||||
|
this.PostStatusMessage(new
|
||||||
|
{
|
||||||
|
calls = GetCurrentCallList(),
|
||||||
|
callStatus = EISC.GetString(SHookState),
|
||||||
|
currentCallString = EISC.GetString(SCurrentCallString),
|
||||||
|
currentDialString = EISC.GetString(SCurrentDialString),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="appServerController"></param>
|
||||||
|
protected override void CustomRegisterWithAppServer(CotijaSystemController appServerController)
|
||||||
|
{
|
||||||
|
Action<object> send = this.PostStatusMessage;
|
||||||
|
EISC.SetStringSigAction(SCurrentDialString, s => send(new { currentDialString = s }));
|
||||||
|
|
||||||
|
EISC.SetStringSigAction(SHookState, s =>
|
||||||
|
{
|
||||||
|
CurrentCallItem.Status = (eCodecCallStatus)Enum.Parse(typeof(eCodecCallStatus), s, true);
|
||||||
|
GetCurrentCallList();
|
||||||
|
send(new
|
||||||
|
{
|
||||||
|
calls = GetCurrentCallList(),
|
||||||
|
callStatus = s
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
EISC.SetStringSigAction(SCurrentCallString, s =>
|
||||||
|
{
|
||||||
|
CurrentCallItem.Name = s;
|
||||||
|
CurrentCallItem.Number = s;
|
||||||
|
send(new
|
||||||
|
{
|
||||||
|
calls = GetCurrentCallList(),
|
||||||
|
currentCallString = s
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add press and holds using helper
|
||||||
|
Action<string, uint> addPHAction = (s, u) =>
|
||||||
|
AppServerController.AddAction(MessagePath + s, new PressAndHoldAction(b => EISC.SetBool(u, b)));
|
||||||
|
|
||||||
|
// Add straight pulse calls
|
||||||
|
Action<string, uint> addAction = (s, u) =>
|
||||||
|
AppServerController.AddAction(MessagePath + s, new Action(() => EISC.PulseBool(u, 100)));
|
||||||
|
addAction("/endCall", BDialHangup);
|
||||||
|
addAction("/incomingAnswer", BIncomingAnswer);
|
||||||
|
addAction("/incomingReject", BIncomingReject);
|
||||||
|
addAction("/speedDial1", BSpeedDial1);
|
||||||
|
addAction("/speedDial2", BSpeedDial2);
|
||||||
|
addAction("/speedDial3", BSpeedDial3);
|
||||||
|
addAction("/speedDial4", BSpeedDial4);
|
||||||
|
|
||||||
|
// Get status
|
||||||
|
AppServerController.AddAction(MessagePath + "/fullStatus", new Action(SendFullStatus));
|
||||||
|
// Dial on string
|
||||||
|
AppServerController.AddAction(MessagePath + "/dial", new Action<string>(s => EISC.SetString(SCurrentDialString, s)));
|
||||||
|
// Pulse DTMF
|
||||||
|
AppServerController.AddAction(MessagePath + "/dtmf", new Action<string>(s =>
|
||||||
|
{
|
||||||
|
if (DTMFMap.ContainsKey(s))
|
||||||
|
{
|
||||||
|
EISC.PulseBool(DTMFMap[s], 100);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Turns the
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<CodecActiveCallItem> GetCurrentCallList()
|
||||||
|
{
|
||||||
|
if (CurrentCallItem.Status == eCodecCallStatus.Disconnected)
|
||||||
|
{
|
||||||
|
return new List<CodecActiveCallItem>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new List<CodecActiveCallItem>() { CurrentCallItem };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
81
PepperDashEssentials/AppServer/Messengers/MessengerBase.cs
Normal file
81
PepperDashEssentials/AppServer/Messengers/MessengerBase.cs
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
using PepperDash.Core;
|
||||||
|
|
||||||
|
using PepperDash.Essentials.Devices.Common.Codec;
|
||||||
|
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides a messaging bridge for a VideoCodecBase
|
||||||
|
/// </summary>
|
||||||
|
public abstract class MessengerBase : IKeyed
|
||||||
|
{
|
||||||
|
public string Key { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public CotijaSystemController AppServerController { get; private set; }
|
||||||
|
|
||||||
|
public string MessagePath { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codec"></param>
|
||||||
|
public MessengerBase(string key, string messagePath)
|
||||||
|
{
|
||||||
|
Key = key;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(messagePath))
|
||||||
|
throw new ArgumentException("messagePath must not be empty or null");
|
||||||
|
|
||||||
|
MessagePath = messagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers this messenger with appserver controller
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="appServerController"></param>
|
||||||
|
public void RegisterWithAppServer(CotijaSystemController appServerController)
|
||||||
|
{
|
||||||
|
if (appServerController == null)
|
||||||
|
throw new ArgumentNullException("appServerController");
|
||||||
|
|
||||||
|
AppServerController = appServerController;
|
||||||
|
CustomRegisterWithAppServer(AppServerController);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implemented in extending classes. Wire up API calls and feedback here
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="appServerController"></param>
|
||||||
|
abstract protected void CustomRegisterWithAppServer(CotijaSystemController appServerController);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper for posting status message
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="contentObject">The contents of the content object</param>
|
||||||
|
protected void PostStatusMessage(object contentObject)
|
||||||
|
{
|
||||||
|
if (AppServerController != null)
|
||||||
|
{
|
||||||
|
AppServerController.SendMessageToServer(JObject.FromObject(new
|
||||||
|
{
|
||||||
|
type = MessagePath,
|
||||||
|
content = contentObject
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core.Monitoring;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
|
{
|
||||||
|
public class SystemMonitorMessenger : MessengerBase
|
||||||
|
{
|
||||||
|
public SystemMonitorController SysMon { get; private set; }
|
||||||
|
|
||||||
|
public SystemMonitorMessenger(string key, SystemMonitorController sysMon, string messagePath)
|
||||||
|
: base(key, messagePath)
|
||||||
|
{
|
||||||
|
if (sysMon == null)
|
||||||
|
throw new ArgumentNullException("sysMon");
|
||||||
|
|
||||||
|
SysMon = sysMon;
|
||||||
|
|
||||||
|
SysMon.SystemMonitorPropertiesChanged += new EventHandler<EventArgs>(SysMon_SystemMonitorPropertiesChanged);
|
||||||
|
|
||||||
|
foreach (var p in SysMon.ProgramStatusFeedbackCollection)
|
||||||
|
{
|
||||||
|
p.Value.AggregatedProgramInfoFeedback.OutputChange += new EventHandler<PepperDash.Essentials.Core.FeedbackEventArgs>(AggregatedProgramInfoFeedback_OutputChange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Posts the program information message
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
void AggregatedProgramInfoFeedback_OutputChange(object sender, PepperDash.Essentials.Core.FeedbackEventArgs e)
|
||||||
|
{
|
||||||
|
SendProgramInfoStatusMessage(e.StringValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deserializes the program info into an object that can be setn in a status message
|
||||||
|
void SendProgramInfoStatusMessage(string serializedProgramInfo)
|
||||||
|
{
|
||||||
|
var programInfo = JsonConvert.DeserializeObject<ProgramInfo>(serializedProgramInfo);
|
||||||
|
|
||||||
|
Debug.Console(2, "Posting Status Message: {0}", programInfo.ToString());
|
||||||
|
|
||||||
|
PostStatusMessage(programInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Posts the system monitor properties
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
void SysMon_SystemMonitorPropertiesChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
SendSystemMonitorStatusMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendFullStatusMessage()
|
||||||
|
{
|
||||||
|
SendSystemMonitorStatusMessage();
|
||||||
|
|
||||||
|
foreach (var p in SysMon.ProgramStatusFeedbackCollection)
|
||||||
|
{
|
||||||
|
SendProgramInfoStatusMessage(p.Value.AggregatedProgramInfoFeedback.StringValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendSystemMonitorStatusMessage()
|
||||||
|
{
|
||||||
|
Debug.Console(2, "Posting System Monitor Status Message.");
|
||||||
|
|
||||||
|
// This takes a while, launch a new thread
|
||||||
|
CrestronInvoke.BeginInvoke((o) =>
|
||||||
|
{
|
||||||
|
PostStatusMessage(new
|
||||||
|
{
|
||||||
|
timeZone = SysMon.TimeZoneFeedback.IntValue,
|
||||||
|
timeZoneName = SysMon.TimeZoneTextFeedback.StringValue,
|
||||||
|
ioControllerVersion = SysMon.IOControllerVersionFeedback.StringValue,
|
||||||
|
snmpVersion = SysMon.SnmpVersionFeedback.StringValue,
|
||||||
|
bacnetVersion = SysMon.BACnetAppVersionFeedback.StringValue,
|
||||||
|
controllerVersion = SysMon.ControllerVersionFeedback.StringValue
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void CustomRegisterWithAppServer(CotijaSystemController appServerController)
|
||||||
|
{
|
||||||
|
AppServerController.AddAction(MessagePath + "/fullStatus", new Action(SendFullStatusMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,235 @@
|
||||||
|
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.Devices.Common.Codec;
|
||||||
|
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides a messaging bridge for a VideoCodecBase
|
||||||
|
/// </summary>
|
||||||
|
public class VideoCodecBaseMessenger : MessengerBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public VideoCodecBase Codec { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codec"></param>
|
||||||
|
public VideoCodecBaseMessenger(string key, VideoCodecBase codec, string messagePath)
|
||||||
|
: base(key, messagePath)
|
||||||
|
{
|
||||||
|
if (codec == null)
|
||||||
|
throw new ArgumentNullException("codec");
|
||||||
|
|
||||||
|
Codec = codec;
|
||||||
|
codec.CallStatusChange += new EventHandler<CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
|
||||||
|
codec.IsReadyChange += new EventHandler<EventArgs>(codec_IsReadyChange);
|
||||||
|
|
||||||
|
var dirCodec = codec as IHasDirectory;
|
||||||
|
if (dirCodec != null)
|
||||||
|
{
|
||||||
|
dirCodec.DirectoryResultReturned += new EventHandler<DirectoryEventArgs>(dirCodec_DirectoryResultReturned);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
void dirCodec_DirectoryResultReturned(object sender, DirectoryEventArgs e)
|
||||||
|
{
|
||||||
|
var dir = e.Directory;
|
||||||
|
PostStatusMessage(new
|
||||||
|
{
|
||||||
|
currentDirectory = e.Directory
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
void codec_IsReadyChange(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
PostStatusMessage(new
|
||||||
|
{
|
||||||
|
isReady = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called from base's RegisterWithAppServer method
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="appServerController"></param>
|
||||||
|
protected override void CustomRegisterWithAppServer(CotijaSystemController appServerController)
|
||||||
|
{
|
||||||
|
appServerController.AddAction("/device/videoCodec/isReady", new Action(SendIsReady));
|
||||||
|
appServerController.AddAction("/device/videoCodec/fullStatus", new Action(SendVtcFullMessageObject));
|
||||||
|
appServerController.AddAction("/device/videoCodec/dial", new Action<string>(s => Codec.Dial(s)));
|
||||||
|
appServerController.AddAction("/device/videoCodec/endCallById", new Action<string>(s =>
|
||||||
|
{
|
||||||
|
var call = GetCallWithId(s);
|
||||||
|
if (call != null)
|
||||||
|
Codec.EndCall(call);
|
||||||
|
}));
|
||||||
|
appServerController.AddAction(MessagePath + "/endAllCalls", new Action(Codec.EndAllCalls));
|
||||||
|
appServerController.AddAction(MessagePath + "/dtmf", new Action<string>(s => Codec.SendDtmf(s)));
|
||||||
|
appServerController.AddAction(MessagePath + "/rejectById", new Action<string>(s =>
|
||||||
|
{
|
||||||
|
var call = GetCallWithId(s);
|
||||||
|
if (call != null)
|
||||||
|
Codec.RejectCall(call);
|
||||||
|
}));
|
||||||
|
appServerController.AddAction(MessagePath + "/acceptById", new Action<string>(s =>
|
||||||
|
{
|
||||||
|
var call = GetCallWithId(s);
|
||||||
|
if (call != null)
|
||||||
|
Codec.AcceptCall(call);
|
||||||
|
}));
|
||||||
|
appServerController.AddAction(MessagePath + "/directoryRoot", new Action(GetDirectoryRoot));
|
||||||
|
appServerController.AddAction(MessagePath + "/directoryById", new Action<string>(s => GetDirectory(s)));
|
||||||
|
appServerController.AddAction(MessagePath + "/directorySearch", new Action<string>(s => DirectorySearch(s)));
|
||||||
|
appServerController.AddAction(MessagePath + "/privacyModeOn", new Action(Codec.PrivacyModeOn));
|
||||||
|
appServerController.AddAction(MessagePath + "/privacyModeOff", new Action(Codec.PrivacyModeOff));
|
||||||
|
appServerController.AddAction(MessagePath + "/privacyModeToggle", new Action(Codec.PrivacyModeToggle));
|
||||||
|
appServerController.AddAction(MessagePath + "/sharingStart", new Action(Codec.StartSharing));
|
||||||
|
appServerController.AddAction(MessagePath + "/sharingStop", new Action(Codec.StopSharing));
|
||||||
|
appServerController.AddAction(MessagePath + "/standbyOn", new Action(Codec.StandbyActivate));
|
||||||
|
appServerController.AddAction(MessagePath + "/standbyOff", new Action(Codec.StandbyDeactivate));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetFullStatusMessage()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper to grab a call with string ID
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
CodecActiveCallItem GetCallWithId(string id)
|
||||||
|
{
|
||||||
|
return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="s"></param>
|
||||||
|
void DirectorySearch(string s)
|
||||||
|
{
|
||||||
|
var dirCodec = Codec as IHasDirectory;
|
||||||
|
if (dirCodec != null)
|
||||||
|
{
|
||||||
|
dirCodec.SearchDirectory(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
void GetDirectory(string id)
|
||||||
|
{
|
||||||
|
var dirCodec = Codec as IHasDirectory;
|
||||||
|
if(dirCodec == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dirCodec.GetDirectoryFolderContents(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
void GetDirectoryRoot()
|
||||||
|
{
|
||||||
|
var dirCodec = Codec as IHasDirectory;
|
||||||
|
if (dirCodec == null)
|
||||||
|
{
|
||||||
|
// do something else?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!dirCodec.PhonebookSyncState.InitialSyncComplete)
|
||||||
|
{
|
||||||
|
PostStatusMessage(new
|
||||||
|
{
|
||||||
|
initialSyncComplete = false
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PostStatusMessage(new
|
||||||
|
{
|
||||||
|
currentDirectory = dirCodec.DirectoryRoot
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handler for codec changes
|
||||||
|
/// </summary>
|
||||||
|
void codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
|
||||||
|
{
|
||||||
|
SendVtcFullMessageObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
void SendIsReady()
|
||||||
|
{
|
||||||
|
PostStatusMessage(new
|
||||||
|
{
|
||||||
|
isReady = Codec.IsReady
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper method to build call status for vtc
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
void SendVtcFullMessageObject()
|
||||||
|
{
|
||||||
|
if (!Codec.IsReady)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var info = Codec.CodecInfo;
|
||||||
|
PostStatusMessage(new
|
||||||
|
{
|
||||||
|
isInCall = Codec.IsInCall,
|
||||||
|
privacyModeIsOn = Codec.PrivacyModeIsOnFeedback.BoolValue,
|
||||||
|
sharingContentIsOn = Codec.SharingContentIsOnFeedback.BoolValue,
|
||||||
|
sharingSource = Codec.SharingSourceFeedback.StringValue,
|
||||||
|
standbyIsOn = Codec.StandbyIsOnFeedback.StringValue,
|
||||||
|
calls = Codec.ActiveCalls,
|
||||||
|
info = new
|
||||||
|
{
|
||||||
|
autoAnswerEnabled = info.AutoAnswerEnabled,
|
||||||
|
e164Alias = info.E164Alias,
|
||||||
|
h323Id = info.H323Id,
|
||||||
|
ipAddress = info.IpAddress,
|
||||||
|
sipPhoneNumber = info.SipPhoneNumber,
|
||||||
|
sipURI = info.SipUri
|
||||||
|
},
|
||||||
|
showSelfViewByDefault = Codec.ShowSelfViewByDefault,
|
||||||
|
hasDirectory = Codec is IHasDirectory
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,12 +3,14 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
|
using Crestron.SimplSharp.Reflection;
|
||||||
using Crestron.SimplSharpPro.EthernetCommunication;
|
using Crestron.SimplSharpPro.EthernetCommunication;
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.AppServer.Messengers;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using PepperDash.Essentials.Core.Config;
|
using PepperDash.Essentials.Core.Config;
|
||||||
using PepperDash.Essentials.Room.Config;
|
using PepperDash.Essentials.Room.Config;
|
||||||
|
|
@ -25,6 +27,14 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const uint RoomIsOn = 301;
|
public const uint RoomIsOn = 301;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 41
|
||||||
|
/// </summary>
|
||||||
|
public const uint PromptForCode = 41;
|
||||||
|
/// <summary>
|
||||||
|
/// 42
|
||||||
|
/// </summary>
|
||||||
|
public const uint ClientJoined = 42;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 51
|
/// 51
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -59,14 +69,15 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
/// 63
|
/// 63
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const uint ShutdownStart = 63;
|
public const uint ShutdownStart = 63;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 72
|
/// 72
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const uint SourceHasChanged = 72;
|
public const uint SourceHasChanged = 72;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// 261 - The start of the range of speed dial visibles
|
||||||
|
/// </summary>
|
||||||
|
public const uint SpeedDialVisibleStartJoin = 261;
|
||||||
|
/// <summary>
|
||||||
/// 501
|
/// 501
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const uint ConfigIsReady = 501;
|
public const uint ConfigIsReady = 501;
|
||||||
|
|
@ -92,6 +103,16 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const uint SelectedSourceKey = 71;
|
public const uint SelectedSourceKey = 71;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 241
|
||||||
|
/// </summary>
|
||||||
|
public const uint SpeedDialNameStartJoin = 241;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 251
|
||||||
|
/// </summary>
|
||||||
|
public const uint SpeedDialNumberStartJoin = 251;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 501
|
/// 501
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -144,6 +165,8 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
|
|
||||||
CotijaDdvc01DeviceBridge SourceBridge;
|
CotijaDdvc01DeviceBridge SourceBridge;
|
||||||
|
|
||||||
|
Ddvc01AtcMessenger AtcMessenger;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
|
@ -181,6 +204,10 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
SetupFunctions();
|
SetupFunctions();
|
||||||
SetupFeedbacks();
|
SetupFeedbacks();
|
||||||
|
|
||||||
|
var key = this.Key + "-" + Parent.Key;
|
||||||
|
AtcMessenger = new Ddvc01AtcMessenger(key, EISC, "/device/audioCodec");
|
||||||
|
AtcMessenger.RegisterWithAppServer(Parent);
|
||||||
|
|
||||||
EISC.SigChange += EISC_SigChange;
|
EISC.SigChange += EISC_SigChange;
|
||||||
EISC.OnlineStatusChange += (o, a) =>
|
EISC.OnlineStatusChange += (o, a) =>
|
||||||
{
|
{
|
||||||
|
|
@ -215,8 +242,6 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
}
|
}
|
||||||
}, "mobilebridgedump", "Dumps DDVC01 bridge EISC data b,u,s", ConsoleAccessLevelEnum.AccessOperator);
|
}, "mobilebridgedump", "Dumps DDVC01 bridge EISC data b,u,s", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
|
|
||||||
CrestronConsole.AddNewConsoleCommand(s => LoadConfigValues(), "loadddvc", "", ConsoleAccessLevelEnum.AccessOperator);
|
|
||||||
|
|
||||||
return base.CustomActivate();
|
return base.CustomActivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -226,6 +251,9 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void SetupFunctions()
|
void SetupFunctions()
|
||||||
{
|
{
|
||||||
|
#warning need join numbers for these
|
||||||
|
Parent.AddAction(@"/room/room1/promptForCode", new Action(() => EISC.PulseBool(BoolJoin.PromptForCode)));
|
||||||
|
Parent.AddAction(@"/room/room1/clientJoined", new Action(() => EISC.PulseBool(BoolJoin.ClientJoined)));
|
||||||
|
|
||||||
Parent.AddAction(@"/room/room1/status", new Action(SendFullStatus));
|
Parent.AddAction(@"/room/room1/status", new Action(SendFullStatus));
|
||||||
|
|
||||||
|
|
@ -235,13 +263,16 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
EISC.PulseBool(BoolJoin.SourceHasChanged);
|
EISC.PulseBool(BoolJoin.SourceHasChanged);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
#warning CHANGE to activityshare. Perhaps
|
|
||||||
Parent.AddAction(@"/room/room1/defaultsource", new Action(() =>
|
Parent.AddAction(@"/room/room1/defaultsource", new Action(() =>
|
||||||
EISC.PulseBool(BoolJoin.ActivitySharePress)));
|
EISC.PulseBool(BoolJoin.ActivitySharePress)));
|
||||||
|
Parent.AddAction(@"/room/room1/activityVideo", new Action(() =>
|
||||||
|
EISC.PulseBool(BoolJoin.ActivityVideoCallPress)));
|
||||||
|
Parent.AddAction(@"/room/room1/activityPhone", new Action(() =>
|
||||||
|
EISC.PulseBool(BoolJoin.ActivityPhoneCallPress)));
|
||||||
|
|
||||||
Parent.AddAction(@"/room/room1/masterVolumeLevel", new Action<ushort>(u =>
|
Parent.AddAction(@"/room/room1/volumes/master/level", new Action<ushort>(u =>
|
||||||
EISC.SetUshort(UshortJoin.MasterVolumeLevel, u)));
|
EISC.SetUshort(UshortJoin.MasterVolumeLevel, u)));
|
||||||
Parent.AddAction(@"/room/room1/masterVolumeMuteToggle", new Action(() =>
|
Parent.AddAction(@"/room/room1/volumes/master/muteToggle", new Action(() =>
|
||||||
EISC.PulseBool(BoolJoin.MasterVolumeIsMuted)));
|
EISC.PulseBool(BoolJoin.MasterVolumeIsMuted)));
|
||||||
|
|
||||||
Parent.AddAction(@"/room/room1/shutdownStart", new Action(() =>
|
Parent.AddAction(@"/room/room1/shutdownStart", new Action(() =>
|
||||||
|
|
@ -252,6 +283,24 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
EISC.PulseBool(BoolJoin.ShutdownCancel)));
|
EISC.PulseBool(BoolJoin.ShutdownCancel)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="devKey"></param>
|
||||||
|
void SetupSourceFunctions(string devKey)
|
||||||
|
{
|
||||||
|
SourceDeviceMapDictionary sourceJoinMap = new SourceDeviceMapDictionary();
|
||||||
|
|
||||||
|
var prefix = string.Format("/device/{0}/", devKey);
|
||||||
|
|
||||||
|
foreach (var item in sourceJoinMap)
|
||||||
|
{
|
||||||
|
var join = item.Value;
|
||||||
|
Parent.AddAction(string.Format("{0}{1}", prefix, item.Key), new PressAndHoldAction(b => EISC.SetBool(join, b)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Links feedbacks to whatever is gonna happen!
|
/// Links feedbacks to whatever is gonna happen!
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -275,15 +324,28 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
EISC.SetUShortSigAction(UshortJoin.MasterVolumeLevel, u =>
|
EISC.SetUShortSigAction(UshortJoin.MasterVolumeLevel, u =>
|
||||||
PostStatusMessage(new
|
PostStatusMessage(new
|
||||||
{
|
{
|
||||||
masterVolumeLevel = u
|
volumes = new
|
||||||
|
{
|
||||||
|
master = new
|
||||||
|
{
|
||||||
|
level = u
|
||||||
|
}
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
EISC.SetBoolSigAction(BoolJoin.MasterVolumeIsMuted, b =>
|
EISC.SetBoolSigAction(BoolJoin.MasterVolumeIsMuted, b =>
|
||||||
PostStatusMessage(new
|
PostStatusMessage(new
|
||||||
{
|
{
|
||||||
masterVolumeMuteState = b
|
volumes = new
|
||||||
|
{
|
||||||
|
master = new
|
||||||
|
{
|
||||||
|
muted = b
|
||||||
|
}
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
// shutdown things
|
// shutdown things
|
||||||
EISC.SetSigTrueAction(BoolJoin.ShutdownCancel, new Action(() =>
|
EISC.SetSigTrueAction(BoolJoin.ShutdownCancel, new Action(() =>
|
||||||
PostMessage("/room/shutdown/", new
|
PostMessage("/room/shutdown/", new
|
||||||
|
|
@ -316,14 +378,24 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
|
|
||||||
var co = ConfigReader.ConfigObject;
|
var co = ConfigReader.ConfigObject;
|
||||||
|
|
||||||
|
co.Info.RuntimeInfo.AppName = Assembly.GetExecutingAssembly().GetName().Name;
|
||||||
|
var version = Assembly.GetExecutingAssembly().GetName().Version;
|
||||||
|
co.Info.RuntimeInfo.AssemblyVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
|
||||||
|
|
||||||
//Room
|
//Room
|
||||||
if (co.Rooms == null)
|
//if (co.Rooms == null)
|
||||||
co.Rooms = new List<EssentialsRoomConfig>();
|
// always start fresh in case simpl changed
|
||||||
var rm = new EssentialsRoomConfig();
|
co.Rooms = new List<DeviceConfig>();
|
||||||
|
var rm = new DeviceConfig();
|
||||||
if (co.Rooms.Count == 0)
|
if (co.Rooms.Count == 0)
|
||||||
{
|
{
|
||||||
Debug.Console(0, this, "Adding room to config");
|
Debug.Console(0, this, "Adding room to config");
|
||||||
co.Rooms.Add(rm);
|
co.Rooms.Add(rm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Console(0, this, "Replacing Room[0] in config");
|
||||||
|
co.Rooms[0] = rm;
|
||||||
}
|
}
|
||||||
rm.Name = EISC.StringOutput[501].StringValue;
|
rm.Name = EISC.StringOutput[501].StringValue;
|
||||||
rm.Key = "room1";
|
rm.Key = "room1";
|
||||||
|
|
@ -353,22 +425,30 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
var name = EISC.StringOutput[i + 1].StringValue;
|
var name = EISC.StringOutput[i + 1].StringValue;
|
||||||
rmProps.SpeedDials.Add(new DDVC01SpeedDial { Number = num, Name = name});
|
rmProps.SpeedDials.Add(new DDVC01SpeedDial { Number = num, Name = name});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This MAY need a check
|
||||||
|
rmProps.AudioCodecKey = "audioCodec";
|
||||||
|
rmProps.VideoCodecKey = null; // "videoCodec";
|
||||||
|
|
||||||
// volume control names
|
// volume control names
|
||||||
var volCount = EISC.UShortOutput[701].UShortValue;
|
var volCount = EISC.UShortOutput[701].UShortValue;
|
||||||
|
|
||||||
// use Volumes object or?
|
//// use Volumes object or?
|
||||||
rmProps.VolumeSliderNames = new List<string>();
|
//rmProps.VolumeSliderNames = new List<string>();
|
||||||
for(uint i = 701; i <= 700 + volCount; i++)
|
//for(uint i = 701; i <= 700 + volCount; i++)
|
||||||
{
|
//{
|
||||||
rmProps.VolumeSliderNames.Add(EISC.StringInput[i].StringValue);
|
// rmProps.VolumeSliderNames.Add(EISC.StringInput[i].StringValue);
|
||||||
}
|
//}
|
||||||
|
|
||||||
// There should be cotija devices in here, I think...
|
// There should be cotija devices in here, I think...
|
||||||
if(co.Devices == null)
|
if(co.Devices == null)
|
||||||
co.Devices = new List<DeviceConfig>();
|
co.Devices = new List<DeviceConfig>();
|
||||||
|
|
||||||
// clear out previous DDVC devices
|
// clear out previous DDVC devices
|
||||||
co.Devices.RemoveAll(d => d.Key.StartsWith("source-", StringComparison.OrdinalIgnoreCase));
|
co.Devices.RemoveAll(d =>
|
||||||
|
d.Key.StartsWith("source-", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| d.Key.Equals("audioCodec", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| d.Key.Equals("videoCodec", StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
rmProps.SourceListKey = "default";
|
rmProps.SourceListKey = "default";
|
||||||
rm.Properties = JToken.FromObject(rmProps);
|
rm.Properties = JToken.FromObject(rmProps);
|
||||||
|
|
@ -387,6 +467,7 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
break;
|
break;
|
||||||
var icon = EISC.StringOutput[651 + i].StringValue;
|
var icon = EISC.StringOutput[651 + i].StringValue;
|
||||||
var key = EISC.StringOutput[671 + i].StringValue;
|
var key = EISC.StringOutput[671 + i].StringValue;
|
||||||
|
|
||||||
var type = EISC.StringOutput[701 + i].StringValue;
|
var type = EISC.StringOutput[701 + i].StringValue;
|
||||||
|
|
||||||
Debug.Console(0, this, "Adding source {0} '{1}'", key, name);
|
Debug.Console(0, this, "Adding source {0} '{1}'", key, name);
|
||||||
|
|
@ -395,6 +476,7 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
Name = name,
|
Name = name,
|
||||||
Order = (int)i + 1,
|
Order = (int)i + 1,
|
||||||
SourceKey = key,
|
SourceKey = key,
|
||||||
|
Type = eSourceListItemType.Route
|
||||||
};
|
};
|
||||||
newSl.Add(key, newSLI);
|
newSl.Add(key, newSLI);
|
||||||
|
|
||||||
|
|
@ -412,10 +494,50 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
Type = type
|
Type = type
|
||||||
};
|
};
|
||||||
co.Devices.Add(devConf);
|
co.Devices.Add(devConf);
|
||||||
|
|
||||||
|
if (group.ToLower().StartsWith("settopbox")) // Add others here as needed
|
||||||
|
{
|
||||||
|
SetupSourceFunctions(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
co.SourceLists.Add("default", newSl);
|
co.SourceLists.Add("default", newSl);
|
||||||
|
|
||||||
|
// build "audioCodec" config if we need
|
||||||
|
if (!string.IsNullOrEmpty(rmProps.AudioCodecKey))
|
||||||
|
{
|
||||||
|
var acFavs = new List<PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem>();
|
||||||
|
for (uint i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (!EISC.GetBool(BoolJoin.SpeedDialVisibleStartJoin + i))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
acFavs.Add(new PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem()
|
||||||
|
{
|
||||||
|
Name = EISC.GetString(StringJoin.SpeedDialNameStartJoin + i),
|
||||||
|
Number = EISC.GetString(StringJoin.SpeedDialNumberStartJoin + i),
|
||||||
|
Type = PepperDash.Essentials.Devices.Common.Codec.eCodecCallType.Audio
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var acProps = new
|
||||||
|
{
|
||||||
|
favorites = acFavs
|
||||||
|
};
|
||||||
|
|
||||||
|
var acStr = "audioCodec";
|
||||||
|
var acConf = new DeviceConfig()
|
||||||
|
{
|
||||||
|
Group = acStr,
|
||||||
|
Key = acStr,
|
||||||
|
Name = acStr,
|
||||||
|
Type = acStr,
|
||||||
|
Properties = JToken.FromObject(acProps)
|
||||||
|
};
|
||||||
|
co.Devices.Add(acConf);
|
||||||
|
}
|
||||||
|
|
||||||
Debug.Console(0, this, "******* CONFIG FROM DDVC: \r{0}", JsonConvert.SerializeObject(ConfigReader.ConfigObject, Formatting.Indented));
|
Debug.Console(0, this, "******* CONFIG FROM DDVC: \r{0}", JsonConvert.SerializeObject(ConfigReader.ConfigObject, Formatting.Indented));
|
||||||
|
|
||||||
var handler = ConfigurationIsReady;
|
var handler = ConfigurationIsReady;
|
||||||
|
|
@ -427,16 +549,49 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
ConfigIsLoaded = true;
|
ConfigIsLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
void SendFullStatus()
|
void SendFullStatus()
|
||||||
{
|
{
|
||||||
if (ConfigIsLoaded)
|
if (ConfigIsLoaded)
|
||||||
{
|
{
|
||||||
|
var count = EISC.UShortOutput[801].UShortValue;
|
||||||
|
|
||||||
|
Debug.Console(1, this, "The Fader Count is : {0}", count);
|
||||||
|
|
||||||
|
// build volumes object, serialize and put in content of method below
|
||||||
|
|
||||||
|
var auxFaders = new List<Volume>();
|
||||||
|
|
||||||
|
// Create auxFaders
|
||||||
|
for (uint i = 2; i <= count; i++)
|
||||||
|
{
|
||||||
|
auxFaders.Add(
|
||||||
|
new Volume(string.Format("level-{0}", i),
|
||||||
|
EISC.UShortOutput[i].UShortValue,
|
||||||
|
EISC.BooleanOutput[i].BoolValue,
|
||||||
|
EISC.StringOutput[800 + i].StringValue,
|
||||||
|
true,
|
||||||
|
"someting.png"));
|
||||||
|
}
|
||||||
|
|
||||||
|
var volumes = new Volumes();
|
||||||
|
|
||||||
|
volumes.Master = new Volume("master",
|
||||||
|
EISC.UShortOutput[UshortJoin.MasterVolumeLevel].UShortValue,
|
||||||
|
EISC.BooleanOutput[BoolJoin.MasterVolumeIsMuted].BoolValue,
|
||||||
|
EISC.StringOutput[801].StringValue,
|
||||||
|
true,
|
||||||
|
"something.png");
|
||||||
|
|
||||||
|
volumes.AuxFaders = auxFaders;
|
||||||
|
|
||||||
PostStatusMessage(new
|
PostStatusMessage(new
|
||||||
{
|
{
|
||||||
isOn = EISC.BooleanOutput[BoolJoin.RoomIsOn].BoolValue,
|
isOn = EISC.BooleanOutput[BoolJoin.RoomIsOn].BoolValue,
|
||||||
selectedSourceKey = EISC.StringOutput[StringJoin.SelectedSourceKey].StringValue,
|
selectedSourceKey = EISC.StringOutput[StringJoin.SelectedSourceKey].StringValue,
|
||||||
masterVolumeLevel = EISC.UShortOutput[UshortJoin.MasterVolumeLevel].UShortValue,
|
volumes = volumes
|
||||||
masterVolumeMuteState = EISC.BooleanOutput[BoolJoin.MasterVolumeIsMuted].BoolValue
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -448,8 +603,6 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper for posting status message
|
/// Helper for posting status message
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -522,86 +675,5 @@ namespace PepperDash.Essentials.Room.Cotija
|
||||||
EISC.StringInput[StringJoin.UserCodeToSystem].StringValue = UserCode;
|
EISC.StringInput[StringJoin.UserCodeToSystem].StringValue = UserCode;
|
||||||
EISC.StringInput[StringJoin.ServerUrl].StringValue = Parent.Config.ClientAppUrl;
|
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);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,15 +5,22 @@ using System.Text;
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.AppServer.Messengers;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using PepperDash.Essentials.Room.Cotija;
|
using PepperDash.Essentials.Room.Cotija;
|
||||||
|
using PepperDash.Essentials.Devices.Common.Codec;
|
||||||
|
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||||
|
|
||||||
namespace PepperDash.Essentials
|
namespace PepperDash.Essentials
|
||||||
{
|
{
|
||||||
public class CotijaEssentialsHuddleSpaceRoomBridge : CotijaBridgeBase
|
public class CotijaEssentialsHuddleSpaceRoomBridge : CotijaBridgeBase
|
||||||
{
|
{
|
||||||
|
|
||||||
public EssentialsHuddleSpaceRoom Room { get; private set; }
|
public EssentialsRoomBase Room { get; private set; }
|
||||||
|
|
||||||
|
public VideoCodecBaseMessenger VCMessenger { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
|
@ -31,7 +38,7 @@ namespace PepperDash.Essentials
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="parent"></param>
|
/// <param name="parent"></param>
|
||||||
/// <param name="room"></param>
|
/// <param name="room"></param>
|
||||||
public CotijaEssentialsHuddleSpaceRoomBridge(EssentialsHuddleSpaceRoom room):
|
public CotijaEssentialsHuddleSpaceRoomBridge(EssentialsRoomBase room):
|
||||||
base("mobileControlBridge-essentialsHuddle", "Essentials Mobile Control Bridge-Huddle")
|
base("mobileControlBridge-essentialsHuddle", "Essentials Mobile Control Bridge-Huddle")
|
||||||
{
|
{
|
||||||
Room = room;
|
Room = room;
|
||||||
|
|
@ -51,22 +58,74 @@ namespace PepperDash.Essentials
|
||||||
// doesn't need to know about everything.
|
// doesn't need to know about everything.
|
||||||
|
|
||||||
// Source Changes and room off
|
// 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}/status", Room.Key), new Action(() => SendFullStatus(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 =>
|
var routeRoom = Room as IRunRouteAction;
|
||||||
(Room.CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(u)));
|
if(routeRoom != null)
|
||||||
Parent.AddAction(string.Format(@"/room/{0}/masterVolumeMuteToggle", Room.Key), new Action(() => Room.CurrentVolumeControls.MuteToggle()));
|
Parent.AddAction(string.Format(@"/room/{0}/source", Room.Key), new Action<SourceSelectMessageContent>(c =>
|
||||||
|
routeRoom.RunRouteAction(c.SourceListItem)));
|
||||||
|
|
||||||
|
var defaultRoom = Room as IRunDefaultPresentRoute;
|
||||||
|
if(defaultRoom != null)
|
||||||
|
Parent.AddAction(string.Format(@"/room/{0}/defaultsource", Room.Key), new Action(() => defaultRoom.RunDefaultPresentRoute()));
|
||||||
|
|
||||||
|
var volumeRoom = Room as IHasCurrentVolumeControls;
|
||||||
|
if (volumeRoom != null)
|
||||||
|
{
|
||||||
|
Parent.AddAction(string.Format(@"/room/{0}/volumes/master/level", Room.Key), new Action<ushort>(u =>
|
||||||
|
(volumeRoom.CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(u)));
|
||||||
|
Parent.AddAction(string.Format(@"/room/{0}/volumes/master/muteToggle", Room.Key), new Action(() =>
|
||||||
|
volumeRoom.CurrentVolumeControls.MuteToggle()));
|
||||||
|
volumeRoom.CurrentVolumeDeviceChange += new EventHandler<VolumeDeviceChangeEventArgs>(Room_CurrentVolumeDeviceChange);
|
||||||
|
|
||||||
|
// Registers for initial volume events, if possible
|
||||||
|
var currentVolumeDevice = volumeRoom.CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||||
|
if (currentVolumeDevice != null)
|
||||||
|
{
|
||||||
|
currentVolumeDevice.MuteFeedback.OutputChange += MuteFeedback_OutputChange;
|
||||||
|
currentVolumeDevice.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sscRoom = Room as IHasCurrentSourceInfoChange;
|
||||||
|
if(sscRoom != null)
|
||||||
|
sscRoom.CurrentSingleSourceChange += new SourceInfoChangeHandler(Room_CurrentSingleSourceChange);
|
||||||
|
|
||||||
|
var vcRoom = Room as IHasVideoCodec;
|
||||||
|
if (vcRoom != null)
|
||||||
|
{
|
||||||
|
var codec = vcRoom.VideoCodec;
|
||||||
|
var key = vcRoom.VideoCodec.Key + "-" + parent.Key;
|
||||||
|
VCMessenger = new VideoCodecBaseMessenger(key, vcRoom.VideoCodec, "/device/videoCodec");
|
||||||
|
VCMessenger.RegisterWithAppServer(Parent);
|
||||||
|
|
||||||
|
// May need to move this or remove this
|
||||||
|
codec.CallStatusChange += new EventHandler<CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
|
||||||
|
|
||||||
|
vcRoom.IsSharingFeedback.OutputChange += new EventHandler<FeedbackEventArgs>(IsSharingFeedback_OutputChange);
|
||||||
|
|
||||||
|
//Parent.AddAction("/device/videoCodec/dial", new Action<string>(s => codec.Dial(s)));
|
||||||
|
//Parent.AddAction("/device/videoCodec/endCall", new Action<string>(s =>
|
||||||
|
//{
|
||||||
|
// var call = codec.ActiveCalls.FirstOrDefault(c => c.Id == s);
|
||||||
|
// if (call != null)
|
||||||
|
// {
|
||||||
|
// codec.EndCall(call);
|
||||||
|
// }
|
||||||
|
//}));
|
||||||
|
//Parent.AddAction("/device/videoCodec/endAllCalls", new Action(() => codec.EndAllCalls()));
|
||||||
|
}
|
||||||
|
|
||||||
|
var defCallRm = Room as IRunDefaultCallRoute;
|
||||||
|
if (defCallRm != null)
|
||||||
|
{
|
||||||
|
Parent.AddAction(string.Format(@"/room/{0}/activityVideo", Room.Key), new Action(()=>defCallRm.RunDefaultCallRoute()));
|
||||||
|
}
|
||||||
|
|
||||||
Parent.AddAction(string.Format(@"/room/{0}/shutdownStart", Room.Key), new Action(() => Room.StartShutdown(eShutdownType.Manual)));
|
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}/shutdownEnd", Room.Key), new Action(() => Room.ShutdownPromptTimer.Finish()));
|
||||||
Parent.AddAction(string.Format(@"/room/{0}/shutdownCancel", Room.Key), new Action(() => Room.ShutdownPromptTimer.Cancel()));
|
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 += OnFeedback_OutputChange;
|
Room.OnFeedback.OutputChange += OnFeedback_OutputChange;
|
||||||
Room.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange;
|
Room.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange;
|
||||||
Room.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange;
|
Room.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange;
|
||||||
|
|
@ -74,20 +133,67 @@ namespace PepperDash.Essentials
|
||||||
Room.ShutdownPromptTimer.HasStarted += ShutdownPromptTimer_HasStarted;
|
Room.ShutdownPromptTimer.HasStarted += ShutdownPromptTimer_HasStarted;
|
||||||
Room.ShutdownPromptTimer.HasFinished += ShutdownPromptTimer_HasFinished;
|
Room.ShutdownPromptTimer.HasFinished += ShutdownPromptTimer_HasFinished;
|
||||||
Room.ShutdownPromptTimer.WasCancelled += ShutdownPromptTimer_WasCancelled;
|
Room.ShutdownPromptTimer.WasCancelled += 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 += VolumeLevelFeedback_OutputChange;
|
|
||||||
newDev.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
void IsSharingFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
||||||
|
{
|
||||||
|
// sharing source
|
||||||
|
string shareText;
|
||||||
|
bool isSharing;
|
||||||
|
#warning This share update needs to happen on source change as well!
|
||||||
|
var vcRoom = Room as IHasVideoCodec;
|
||||||
|
var srcInfoRoom = Room as IHasCurrentSourceInfoChange;
|
||||||
|
if (vcRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue && srcInfoRoom.CurrentSourceInfo != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
shareText = srcInfoRoom.CurrentSourceInfo.PreferredName;
|
||||||
|
isSharing = true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shareText = "None";
|
||||||
|
isSharing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PostStatusMessage(new
|
||||||
|
{
|
||||||
|
share = new
|
||||||
|
{
|
||||||
|
currentShareText = shareText,
|
||||||
|
isSharing = isSharing
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handler for codec changes
|
||||||
|
/// </summary>
|
||||||
|
void codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
|
||||||
|
{
|
||||||
|
PostStatusMessage(new
|
||||||
|
{
|
||||||
|
calls = GetCallsMessageObject(),
|
||||||
|
//vtc = GetVtcCallsMessageObject()
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
|
@ -143,14 +249,12 @@ namespace PepperDash.Essentials
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender"></param>
|
/// <param name="sender"></param>
|
||||||
/// <param name="e"></param>
|
/// <param name="e"></param>
|
||||||
void IsWarmingUpFeedback_OutputChange(object sender, EventArgs e)
|
void IsWarmingUpFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
||||||
{
|
{
|
||||||
JObject roomStatus = new JObject();
|
PostStatusMessage(new
|
||||||
roomStatus.Add("isWarmingUp", (sender as BoolFeedback).BoolValue);
|
{
|
||||||
JObject message = new JObject();
|
isWarmingUp = e.BoolValue
|
||||||
message.Add("type", "/room/status/");
|
});
|
||||||
message.Add("content", roomStatus);
|
|
||||||
Parent.SendMessageToServer(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -158,14 +262,12 @@ namespace PepperDash.Essentials
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender"></param>
|
/// <param name="sender"></param>
|
||||||
/// <param name="e"></param>
|
/// <param name="e"></param>
|
||||||
void IsCoolingDownFeedback_OutputChange(object sender, EventArgs e)
|
void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
||||||
{
|
{
|
||||||
JObject roomStatus = new JObject();
|
PostStatusMessage(new
|
||||||
roomStatus.Add("isCoolingDown", (sender as BoolFeedback).BoolValue);
|
{
|
||||||
JObject message = new JObject();
|
isCoolingDown = e.BoolValue
|
||||||
message.Add("type", "/room/status/");
|
});
|
||||||
message.Add("content", roomStatus);
|
|
||||||
Parent.SendMessageToServer(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -173,27 +275,12 @@ namespace PepperDash.Essentials
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender"></param>
|
/// <param name="sender"></param>
|
||||||
/// <param name="e"></param>
|
/// <param name="e"></param>
|
||||||
void OnFeedback_OutputChange(object sender, EventArgs e)
|
void OnFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
||||||
{
|
{
|
||||||
/* Example message
|
PostStatusMessage(new
|
||||||
* {
|
{
|
||||||
"type":"/room/status",
|
isOn = e.BoolValue
|
||||||
"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)
|
void Room_CurrentVolumeDeviceChange(object sender, VolumeDeviceChangeEventArgs e)
|
||||||
|
|
@ -201,53 +288,52 @@ namespace PepperDash.Essentials
|
||||||
if (e.OldDev is IBasicVolumeWithFeedback)
|
if (e.OldDev is IBasicVolumeWithFeedback)
|
||||||
{
|
{
|
||||||
var oldDev = e.OldDev as IBasicVolumeWithFeedback;
|
var oldDev = e.OldDev as IBasicVolumeWithFeedback;
|
||||||
|
oldDev.MuteFeedback.OutputChange -= MuteFeedback_OutputChange;
|
||||||
oldDev.MuteFeedback.OutputChange -= VolumeLevelFeedback_OutputChange;
|
|
||||||
oldDev.VolumeLevelFeedback.OutputChange -= VolumeLevelFeedback_OutputChange;
|
oldDev.VolumeLevelFeedback.OutputChange -= VolumeLevelFeedback_OutputChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.NewDev is IBasicVolumeWithFeedback)
|
if (e.NewDev is IBasicVolumeWithFeedback)
|
||||||
{
|
{
|
||||||
var newDev = e.NewDev as IBasicVolumeWithFeedback;
|
var newDev = e.NewDev as IBasicVolumeWithFeedback;
|
||||||
|
newDev.MuteFeedback.OutputChange += MuteFeedback_OutputChange;
|
||||||
newDev.MuteFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
|
|
||||||
newDev.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
|
newDev.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VolumeLevelFeedback_OutputChange(object sender, EventArgs e)
|
/// <summary>
|
||||||
|
/// Event handler for mute changes
|
||||||
|
/// </summary>
|
||||||
|
void MuteFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
||||||
{
|
{
|
||||||
/* Example message
|
PostStatusMessage(new
|
||||||
* {
|
|
||||||
"type":"/room/status",
|
|
||||||
"content": {
|
|
||||||
"masterVolumeLevel": 12345,
|
|
||||||
"masterVolumeMuteState": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
var huddleRoom = Room as EssentialsHuddleSpaceRoom;
|
|
||||||
|
|
||||||
if(huddleRoom.CurrentVolumeControls is IBasicVolumeWithFeedback)
|
|
||||||
{
|
{
|
||||||
JObject roomStatus = new JObject();
|
volumes = new
|
||||||
|
|
||||||
if (huddleRoom.CurrentVolumeControls is IBasicVolumeWithFeedback)
|
|
||||||
{
|
{
|
||||||
var currentVolumeConstrols = huddleRoom.CurrentVolumeControls as IBasicVolumeWithFeedback;
|
master = new
|
||||||
roomStatus.Add("masterVolumeLevel", currentVolumeConstrols.VolumeLevelFeedback.IntValue);
|
{
|
||||||
roomStatus.Add("masterVolumeMuteState", currentVolumeConstrols.MuteFeedback.BoolValue);
|
muted = e.BoolValue
|
||||||
}
|
|
||||||
|
|
||||||
JObject message = new JObject();
|
|
||||||
|
|
||||||
message.Add("type", "/room/status/");
|
|
||||||
message.Add("content", roomStatus);
|
|
||||||
|
|
||||||
Parent.SendMessageToServer(message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles Volume changes on room
|
||||||
|
/// </summary>
|
||||||
|
void VolumeLevelFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
||||||
|
{
|
||||||
|
PostStatusMessage(new
|
||||||
|
{
|
||||||
|
volumes = new
|
||||||
|
{
|
||||||
|
master = new
|
||||||
|
{
|
||||||
|
level = e.IntValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Room_CurrentSingleSourceChange(EssentialsRoomBase room, PepperDash.Essentials.Core.SourceListItem info, ChangeType type)
|
void Room_CurrentSingleSourceChange(EssentialsRoomBase room, PepperDash.Essentials.Core.SourceListItem info, ChangeType type)
|
||||||
{
|
{
|
||||||
|
|
@ -310,16 +396,11 @@ namespace PepperDash.Essentials
|
||||||
if (dev is ITransport)
|
if (dev is ITransport)
|
||||||
(dev as ITransport).LinkActions(Parent);
|
(dev as ITransport).LinkActions(Parent);
|
||||||
|
|
||||||
var huddleRoom = room as EssentialsHuddleSpaceRoom;
|
var srcRm = room as IHasCurrentSourceInfoChange;
|
||||||
JObject roomStatus = new JObject();
|
PostStatusMessage(new
|
||||||
roomStatus.Add("selectedSourceKey", huddleRoom.CurrentSourceInfoKey);
|
{
|
||||||
|
selectedSourceKey = srcRm.CurrentSourceInfoKey
|
||||||
JObject message = new JObject();
|
});
|
||||||
|
|
||||||
message.Add("type", "/room/status/");
|
|
||||||
message.Add("content", roomStatus);
|
|
||||||
|
|
||||||
Parent.SendMessageToServer(message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -328,52 +409,83 @@ namespace PepperDash.Essentials
|
||||||
/// Posts the full status of the room to the server
|
/// Posts the full status of the room to the server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="room"></param>
|
/// <param name="room"></param>
|
||||||
void Room_RoomFullStatus(EssentialsRoomBase room)
|
void SendFullStatus(EssentialsRoomBase room)
|
||||||
{
|
{
|
||||||
/* Example message
|
var sourceKey = room is IHasCurrentSourceInfoChange ? (room as IHasCurrentSourceInfoChange).CurrentSourceInfoKey : null;
|
||||||
* {
|
|
||||||
"type":"/room/status",
|
|
||||||
"content": {
|
|
||||||
"selectedSourceKey": "off",
|
|
||||||
"isOn": false,
|
|
||||||
"masterVolumeLevel": 50,
|
|
||||||
"masterVolumeMuteState": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
JObject roomStatus = new JObject();
|
var rmVc = room as IHasCurrentVolumeControls;
|
||||||
|
var volumes = new Volumes();
|
||||||
var huddleRoom = room as EssentialsHuddleSpaceRoom;
|
if (rmVc != null)
|
||||||
roomStatus.Add("isOn", huddleRoom.OnFeedback.BoolValue);
|
|
||||||
roomStatus.Add("selectedSourceKey", huddleRoom.CurrentSourceInfoKey);
|
|
||||||
|
|
||||||
|
|
||||||
if(huddleRoom.CurrentVolumeControls is IBasicVolumeWithFeedback)
|
|
||||||
{
|
{
|
||||||
var currentVolumeConstrols = huddleRoom.CurrentVolumeControls as IBasicVolumeWithFeedback;
|
var vc = rmVc.CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||||
roomStatus.Add("masterVolumeLevel", currentVolumeConstrols.VolumeLevelFeedback.IntValue);
|
if (rmVc != null)
|
||||||
roomStatus.Add("masterVolumeMuteState", currentVolumeConstrols.MuteFeedback.BoolValue);
|
{
|
||||||
|
volumes.Master = new Volume("master", vc.VolumeLevelFeedback.UShortValue, vc.MuteFeedback.BoolValue, "Volume", true, "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JObject message = new JObject();
|
PostStatusMessage(new
|
||||||
|
{
|
||||||
message.Add("type", "/room/status/");
|
calls = GetCallsMessageObject(),
|
||||||
message.Add("content", roomStatus);
|
isOn = room.OnFeedback.BoolValue,
|
||||||
|
selectedSourceKey = sourceKey,
|
||||||
Parent.SendMessageToServer(message);
|
vtc = GetVtcCallsMessageObject(),
|
||||||
|
volumes = volumes
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper to return a anonymous object with the call data for JSON message
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
object GetCallsMessageObject()
|
||||||
|
{
|
||||||
|
var callRm = Room as IHasVideoCodec;
|
||||||
|
if (callRm == null)
|
||||||
|
return null;
|
||||||
|
return new
|
||||||
|
{
|
||||||
|
activeCalls = callRm.VideoCodec.ActiveCalls,
|
||||||
|
callType = callRm.CallTypeFeedback.IntValue,
|
||||||
|
inCall = callRm.InCallFeedback.BoolValue,
|
||||||
|
isSharing = callRm.IsSharingFeedback.BoolValue,
|
||||||
|
privacyModeIsOn = callRm.PrivacyModeIsOnFeedback.BoolValue
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper method to build call status for vtc
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
object GetVtcCallsMessageObject()
|
||||||
|
{
|
||||||
|
var callRm = Room as IHasVideoCodec;
|
||||||
|
object vtc = null;
|
||||||
|
if (callRm != null)
|
||||||
|
{
|
||||||
|
var codec = callRm.VideoCodec;
|
||||||
|
vtc = new
|
||||||
|
{
|
||||||
|
isInCall = codec.IsInCall,
|
||||||
|
calls = codec.ActiveCalls
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return vtc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
public class SourceSelectMessageContent
|
public class SourceSelectMessageContent
|
||||||
{
|
{
|
||||||
public string SourceListItem { get; set; }
|
public string SourceListItem { get; set; }
|
||||||
//public string Destination { get; set; }
|
|
||||||
//public string SourceSelect { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="b"></param>
|
||||||
public delegate void PressAndHoldAction(bool b);
|
public delegate void PressAndHoldAction(bool b);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Room.Cotija
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains all of the default joins that map to API funtions
|
||||||
|
/// </summary>
|
||||||
|
public class SourceDeviceMapDictionary : Dictionary<string, uint>
|
||||||
|
{
|
||||||
|
|
||||||
|
public SourceDeviceMapDictionary(): base()
|
||||||
|
{
|
||||||
|
var dictionary = new Dictionary<string, uint>
|
||||||
|
{
|
||||||
|
{"preset01", 101},
|
||||||
|
{"preset02", 102},
|
||||||
|
{"preset03", 103},
|
||||||
|
{"preset04", 104},
|
||||||
|
{"preset05", 105},
|
||||||
|
{"preset06", 106},
|
||||||
|
{"preset07", 107},
|
||||||
|
{"preset08", 108},
|
||||||
|
{"preset09", 109},
|
||||||
|
{"preset10", 110},
|
||||||
|
{"preset11", 111},
|
||||||
|
{"preset12", 112},
|
||||||
|
{"preset13", 113},
|
||||||
|
{"preset14", 114},
|
||||||
|
{"preset15", 115},
|
||||||
|
{"preset16", 116},
|
||||||
|
{"preset17", 117},
|
||||||
|
{"preset18", 118},
|
||||||
|
{"preset19", 119},
|
||||||
|
{"preset20", 120},
|
||||||
|
{"preset21", 121},
|
||||||
|
{"preset22", 122},
|
||||||
|
{"preset23", 123},
|
||||||
|
{"preset24", 124},
|
||||||
|
|
||||||
|
{"num0", 130},
|
||||||
|
{"num1", 131},
|
||||||
|
{"num2", 132},
|
||||||
|
{"num3", 133},
|
||||||
|
{"num4", 134},
|
||||||
|
{"num5", 135},
|
||||||
|
{"num6", 136},
|
||||||
|
{"num7", 137},
|
||||||
|
{"num8", 138},
|
||||||
|
{"num9", 139},
|
||||||
|
{"numDash", 140},
|
||||||
|
{"numEnter", 141},
|
||||||
|
{"chanUp", 142},
|
||||||
|
{"chanDown", 143},
|
||||||
|
{"lastChan", 144},
|
||||||
|
{"exit", 145},
|
||||||
|
{"powerToggle", 146},
|
||||||
|
{"red", 147},
|
||||||
|
{"green", 148},
|
||||||
|
{"yellow", 149},
|
||||||
|
{"blue", 150},
|
||||||
|
{"video", 151},
|
||||||
|
{"previous", 152},
|
||||||
|
{"next", 153},
|
||||||
|
{"rewind", 154},
|
||||||
|
{"ffwd", 155},
|
||||||
|
{"closedCaption", 156},
|
||||||
|
{"stop", 157},
|
||||||
|
{"pause", 158},
|
||||||
|
{"up", 159},
|
||||||
|
{"down", 160},
|
||||||
|
{"left", 161},
|
||||||
|
{"right", 162},
|
||||||
|
{"settings", 163},
|
||||||
|
{"info", 164},
|
||||||
|
{"return", 165},
|
||||||
|
{"guide", 166},
|
||||||
|
{"reboot", 167},
|
||||||
|
{"dvrList", 168},
|
||||||
|
{"replay", 169},
|
||||||
|
{"play", 170},
|
||||||
|
{"select", 171},
|
||||||
|
{"record", 172},
|
||||||
|
{"menu", 173},
|
||||||
|
{"topMenu", 174},
|
||||||
|
{"prevTrack", 175},
|
||||||
|
{"nextTrack", 176},
|
||||||
|
{"powerOn", 177},
|
||||||
|
{"powerOff", 178},
|
||||||
|
{"dot", 179}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var item in dictionary)
|
||||||
|
{
|
||||||
|
this.Add(item.Key, item.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
55
PepperDashEssentials/AppServer/Volumes.cs
Normal file
55
PepperDashEssentials/AppServer/Volumes.cs
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Room.Cotija
|
||||||
|
{
|
||||||
|
public class Volumes
|
||||||
|
{
|
||||||
|
[JsonProperty("master")]
|
||||||
|
public Volume Master { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("auxFaders")]
|
||||||
|
public List<Volume> AuxFaders { get; set; }
|
||||||
|
|
||||||
|
public Volumes()
|
||||||
|
{
|
||||||
|
AuxFaders = new List<Volume>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Volume
|
||||||
|
{
|
||||||
|
[JsonProperty("key")]
|
||||||
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("level")]
|
||||||
|
public ushort Level { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("muted")]
|
||||||
|
public bool Muted { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("label")]
|
||||||
|
public string Label { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("hasMute")]
|
||||||
|
public bool HasMute { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("muteIcon")]
|
||||||
|
public string MuteIcon { get; set; }
|
||||||
|
|
||||||
|
public Volume(string key, ushort level, bool muted, string label, bool hasMute, string muteIcon)
|
||||||
|
{
|
||||||
|
Key = key;
|
||||||
|
Level = level;
|
||||||
|
Muted = muted;
|
||||||
|
Label = label;
|
||||||
|
HasMute = hasMute;
|
||||||
|
MuteIcon = muteIcon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,8 +10,8 @@ using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using PepperDash.Essentials.Core.Devices;
|
using PepperDash.Essentials.Core.Devices;
|
||||||
using PepperDash.Essentials.Devices.Common;
|
|
||||||
using PepperDash.Essentials.Core.Config;
|
using PepperDash.Essentials.Core.Config;
|
||||||
|
using PepperDash.Essentials.Core.CrestronIO;
|
||||||
using PepperDash.Essentials.DM;
|
using PepperDash.Essentials.DM;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Bridges
|
namespace PepperDash.Essentials.Bridges
|
||||||
|
|
@ -75,29 +75,39 @@ namespace PepperDash.Essentials.Bridges
|
||||||
|
|
||||||
if (device != null)
|
if (device != null)
|
||||||
{
|
{
|
||||||
if (device is GenericComm)
|
if (device is PepperDash.Essentials.Core.Monitoring.SystemMonitorController)
|
||||||
|
{
|
||||||
|
(device as PepperDash.Essentials.Core.Monitoring.SystemMonitorController).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (device is GenericComm)
|
||||||
{
|
{
|
||||||
(device as GenericComm).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
|
(device as GenericComm).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
else if (device is DigitalLogger)
|
|
||||||
{
|
|
||||||
(device as DigitalLogger).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
else if (device is DmChassisController)
|
else if (device is DmChassisController)
|
||||||
{
|
{
|
||||||
// (device as DmChassisController).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
|
(device as DmChassisController).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (device is DmTxControllerBase)
|
else if (device is DmTxControllerBase)
|
||||||
{
|
{
|
||||||
// (device as DmTxControllerBase).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
|
(device as DmTxControllerBase).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (device is DmRmcControllerBase)
|
else if (device is DmRmcControllerBase)
|
||||||
{
|
{
|
||||||
// (device as DmRmcControllerBase).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
|
(device as DmRmcControllerBase).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (device is GenericRelayDevice)
|
||||||
|
{
|
||||||
|
(device as GenericRelayDevice).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (device is IDigitalInput)
|
||||||
|
{
|
||||||
|
(device as IDigitalInput).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -134,6 +144,7 @@ namespace PepperDash.Essentials.Bridges
|
||||||
[JsonProperty("devices")]
|
[JsonProperty("devices")]
|
||||||
public List<ApiDevice> Devices { get; set; }
|
public List<ApiDevice> Devices { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public class ApiDevice
|
public class ApiDevice
|
||||||
{
|
{
|
||||||
[JsonProperty("deviceKey")]
|
[JsonProperty("deviceKey")]
|
||||||
|
|
@ -149,108 +160,4 @@ namespace PepperDash.Essentials.Bridges
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///// <summary>
|
|
||||||
///// API class for IBasicCommunication devices
|
|
||||||
///// </summary>
|
|
||||||
//public class IBasicCommunicationApi : DeviceApiBase
|
|
||||||
//{
|
|
||||||
// public IBasicCommunication Device { get; set; }
|
|
||||||
|
|
||||||
// SerialFeedback TextReceivedFeedback;
|
|
||||||
|
|
||||||
// public IBasicCommunicationApi(IBasicCommunication dev)
|
|
||||||
// {
|
|
||||||
// TextReceivedFeedback = new SerialFeedback();
|
|
||||||
|
|
||||||
// Device = dev;
|
|
||||||
|
|
||||||
// SetupFeedbacks();
|
|
||||||
|
|
||||||
// ActionApi = new Dictionary<string, Object>
|
|
||||||
// {
|
|
||||||
// { "connect", new Action(Device.Connect) },
|
|
||||||
// { "disconnect", new Action(Device.Disconnect) },
|
|
||||||
// { "connectstate", new Action<bool>( b => ConnectByState(b) ) },
|
|
||||||
// { "sendtext", new Action<string>( s => Device.SendText(s) ) }
|
|
||||||
|
|
||||||
// };
|
|
||||||
|
|
||||||
// FeedbackApi = new Dictionary<string, Feedback>
|
|
||||||
// {
|
|
||||||
// { "isconnected", new BoolFeedback( () => Device.IsConnected ) },
|
|
||||||
// { "textrecieved", TextReceivedFeedback }
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// Controls connection based on state of input
|
|
||||||
// /// </summary>
|
|
||||||
// /// <param name="state"></param>
|
|
||||||
// void ConnectByState(bool state)
|
|
||||||
// {
|
|
||||||
// if (state)
|
|
||||||
// Device.Connect();
|
|
||||||
// else
|
|
||||||
// Device.Disconnect();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void SetupFeedbacks()
|
|
||||||
// {
|
|
||||||
// Device.TextReceived += new EventHandler<GenericCommMethodReceiveTextArgs>(Device_TextReceived);
|
|
||||||
|
|
||||||
// if(Device is ISocketStatus)
|
|
||||||
// (Device as ISocketStatus).ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(IBasicCommunicationApi_ConnectionChange);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void IBasicCommunicationApi_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
|
||||||
// {
|
|
||||||
// FeedbackApi["isconnected"].FireUpdate();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void Device_TextReceived(object sender, GenericCommMethodReceiveTextArgs e)
|
|
||||||
// {
|
|
||||||
// TextReceivedFeedback.FireUpdate(e.Text);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///// <summary>
|
|
||||||
///// Each flavor of API is a static class with static properties and a static constructor that
|
|
||||||
///// links up the things to do.
|
|
||||||
///// </summary>
|
|
||||||
//public class DmChassisControllerApi : DeviceApiBase
|
|
||||||
//{
|
|
||||||
// IntFeedback Output1Feedback;
|
|
||||||
// IntFeedback Output2Feedback;
|
|
||||||
|
|
||||||
// public DmChassisControllerApi(DmChassisController dev)
|
|
||||||
// {
|
|
||||||
// Output1Feedback = new IntFeedback( new Func<int>(() => 1));
|
|
||||||
// Output2Feedback = new IntFeedback( new Func<int>(() => 2));
|
|
||||||
|
|
||||||
// ActionApi = new Dictionary<string, Object>
|
|
||||||
// {
|
|
||||||
|
|
||||||
// };
|
|
||||||
|
|
||||||
// FeedbackApi = new Dictionary<string, Feedback>
|
|
||||||
// {
|
|
||||||
// { "Output-1/fb", Output1Feedback },
|
|
||||||
// { "Output-2/fb", Output2Feedback }
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// Factory method
|
|
||||||
// /// </summary>
|
|
||||||
// /// <param name="dev"></param>
|
|
||||||
// /// <returns></returns>
|
|
||||||
// public static DmChassisControllerApi GetActionApiForDevice(DmChassisController dev)
|
|
||||||
// {
|
|
||||||
// return new DmChassisControllerApi(dev);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
181
PepperDashEssentials/Bridges/BridgeFactory.cs
Normal file
181
PepperDashEssentials/Bridges/BridgeFactory.cs
Normal file
|
|
@ -0,0 +1,181 @@
|
||||||
|
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.Core.Config;
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core.Routing;
|
||||||
|
using PepperDash.Essentials.Bridges;
|
||||||
|
using Crestron.SimplSharpPro;
|
||||||
|
using Crestron.SimplSharpPro.EthernetCommunication;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials
|
||||||
|
{
|
||||||
|
public class BridgeFactory
|
||||||
|
{
|
||||||
|
public static IKeyed GetDevice(DeviceConfig dc)
|
||||||
|
{
|
||||||
|
// ? why is this static JTA 2018-06-13?
|
||||||
|
|
||||||
|
var key = dc.Key;
|
||||||
|
var name = dc.Name;
|
||||||
|
var type = dc.Type;
|
||||||
|
var properties = dc.Properties;
|
||||||
|
var propAnon = new { };
|
||||||
|
|
||||||
|
var typeName = dc.Type.ToLower();
|
||||||
|
var groupName = dc.Group.ToLower();
|
||||||
|
|
||||||
|
//Debug.Console(2, "Name {0}, Key {1}, Type {2}, Properties {3}", name, key, type, properties.ToString());
|
||||||
|
|
||||||
|
if (typeName == "eiscapi")
|
||||||
|
{
|
||||||
|
return new EiscApi(dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DmBridge : Device
|
||||||
|
{
|
||||||
|
public EiscBridgeProperties Properties { get; private set; }
|
||||||
|
|
||||||
|
public PepperDash.Essentials.DM.DmChassisController DmSwitch { get; private set; }
|
||||||
|
|
||||||
|
public DmBridge(string key, string name, JToken properties) : base(key, name)
|
||||||
|
{
|
||||||
|
Properties = JsonConvert.DeserializeObject<EiscBridgeProperties>(properties.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CustomActivate()
|
||||||
|
{
|
||||||
|
// Create EiscApis
|
||||||
|
if (Properties.Eiscs != null)
|
||||||
|
{
|
||||||
|
foreach (var eisc in Properties.Eiscs)
|
||||||
|
{
|
||||||
|
var ApiEisc = new BridgeApiEisc(eisc.IpId, eisc.Hostname);
|
||||||
|
|
||||||
|
ApiEisc.Eisc.SetUShortSigAction(101, u => DmSwitch.ExecuteSwitch(u,1, eRoutingSignalType.Video));
|
||||||
|
ApiEisc.Eisc.SetUShortSigAction(102, u => DmSwitch.ExecuteSwitch(u,2, eRoutingSignalType.Video));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var device in DeviceManager.AllDevices)
|
||||||
|
{
|
||||||
|
if (device.Key == this.Properties.ParentDeviceKey)
|
||||||
|
{
|
||||||
|
Debug.Console(0, "deviceKey {0} Matches", device.Key);
|
||||||
|
DmSwitch = DeviceManager.GetDeviceForKey(device.Key) as PepperDash.Essentials.DM.DmChassisController;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Console(0, "deviceKey {0} doesn't match", device.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Console(0, "Bridge {0} Activated", this.Name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommBridge : Device
|
||||||
|
{
|
||||||
|
public CommBridgeProperties Properties { get; private set; }
|
||||||
|
|
||||||
|
public List<IBasicCommunication> CommDevices { get; private set; }
|
||||||
|
|
||||||
|
public CommBridge(string key, string name, JToken properties)
|
||||||
|
: base(key, name)
|
||||||
|
{
|
||||||
|
Properties = JsonConvert.DeserializeObject<CommBridgeProperties>(properties.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CustomActivate()
|
||||||
|
{
|
||||||
|
// Create EiscApis
|
||||||
|
if (Properties.Eiscs != null)
|
||||||
|
{
|
||||||
|
foreach (var eisc in Properties.Eiscs)
|
||||||
|
{
|
||||||
|
var ApiEisc = new BridgeApiEisc(eisc.IpId, eisc.Hostname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var deviceKey in Properties.CommDevices)
|
||||||
|
{
|
||||||
|
var device = DeviceManager.GetDeviceForKey(deviceKey);
|
||||||
|
|
||||||
|
if (device != null)
|
||||||
|
{
|
||||||
|
Debug.Console(0, "deviceKey {0} Found in Device Manager", device.Key);
|
||||||
|
CommDevices.Add(device as IBasicCommunication);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Console(0, "deviceKey {0} Not Found in Device Manager", deviceKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate through all the CommDevices and link up their Actions and Feedbacks
|
||||||
|
|
||||||
|
Debug.Console(0, "Bridge {0} Activated", this.Name);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class EiscBridgeProperties
|
||||||
|
{
|
||||||
|
public string ParentDeviceKey { get; set; }
|
||||||
|
public eApiType ApiType { get; set; }
|
||||||
|
public List<EiscProperties> Eiscs { get; set; }
|
||||||
|
public string ApiOverrideFilePath { get; set; }
|
||||||
|
|
||||||
|
public class EiscProperties
|
||||||
|
{
|
||||||
|
public string IpId { get; set; }
|
||||||
|
public string Hostname { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommBridgeProperties : EiscBridgeProperties
|
||||||
|
{
|
||||||
|
public List<string> CommDevices { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum eApiType { Eisc = 0 }
|
||||||
|
|
||||||
|
public class BridgeApiEisc
|
||||||
|
{
|
||||||
|
public uint Ipid { get; private set; }
|
||||||
|
public ThreeSeriesTcpIpEthernetIntersystemCommunications Eisc { get; private set; }
|
||||||
|
|
||||||
|
public BridgeApiEisc(string ipid, string hostname)
|
||||||
|
{
|
||||||
|
Ipid = (UInt32)int.Parse(ipid, System.Globalization.NumberStyles.HexNumber);
|
||||||
|
Eisc = new ThreeSeriesTcpIpEthernetIntersystemCommunications(Ipid, hostname, Global.ControlSystem);
|
||||||
|
Eisc.Register();
|
||||||
|
Eisc.SigChange += Eisc_SigChange;
|
||||||
|
Debug.Console(0, "BridgeApiEisc Created at Ipid {0}", ipid);
|
||||||
|
}
|
||||||
|
void Eisc_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args)
|
||||||
|
{
|
||||||
|
if (Debug.Level >= 1)
|
||||||
|
Debug.Console(1, "BridgeApiEisc 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
109
PepperDashEssentials/Bridges/DmChassisControllerBridge.cs
Normal file
109
PepperDashEssentials/Bridges/DmChassisControllerBridge.cs
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
|
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.DM;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Bridges
|
||||||
|
{
|
||||||
|
public static class DmChassisControllerApiExtentions
|
||||||
|
{
|
||||||
|
public static void LinkToApi(this DmChassisController dmChassis, BasicTriList trilist, uint joinStart, string joinMapKey)
|
||||||
|
{
|
||||||
|
var joinMap = JoinMapHelper.GetJoinMapForDevice(joinMapKey) as DmChassisControllerJoinMap;
|
||||||
|
|
||||||
|
if (joinMap == null)
|
||||||
|
joinMap = new DmChassisControllerJoinMap();
|
||||||
|
|
||||||
|
joinMap.OffsetJoinNumbers(joinStart);
|
||||||
|
|
||||||
|
Debug.Console(1, dmChassis, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
|
||||||
|
|
||||||
|
dmChassis.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline]);
|
||||||
|
|
||||||
|
// Link up outputs
|
||||||
|
for (uint i = 1; i <= dmChassis.Chassis.NumberOfOutputs - 1; i++)
|
||||||
|
{
|
||||||
|
var ioSlot = i;
|
||||||
|
|
||||||
|
// Control
|
||||||
|
trilist.SetUShortSigAction(joinMap.OutputVideo + ioSlot, new Action<ushort>(o => dmChassis.ExecuteSwitch(o, ioSlot, eRoutingSignalType.Video)));
|
||||||
|
trilist.SetUShortSigAction(joinMap.OutputAudio + ioSlot, new Action<ushort>(o => dmChassis.ExecuteSwitch(o, ioSlot, eRoutingSignalType.Audio)));
|
||||||
|
|
||||||
|
// Feedback
|
||||||
|
dmChassis.VideoOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputVideo + ioSlot]);
|
||||||
|
dmChassis.AudioOutputFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[joinMap.OutputAudio + ioSlot]);
|
||||||
|
|
||||||
|
dmChassis.VideoInputSyncFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus + ioSlot]);
|
||||||
|
|
||||||
|
dmChassis.OutputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputNames + ioSlot]);
|
||||||
|
dmChassis.InputNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.InputNames + ioSlot]);
|
||||||
|
dmChassis.OutputVideoRouteNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputCurrentVideoInputNames + ioSlot]);
|
||||||
|
dmChassis.OutputAudioRouteNameFeedbacks[ioSlot].LinkInputSig(trilist.StringInput[joinMap.OutputCurrentAudioInputNames + ioSlot]);
|
||||||
|
dmChassis.InputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.InputEndpointOnline + ioSlot]);
|
||||||
|
dmChassis.OutputEndpointOnlineFeedbacks[ioSlot].LinkInputSig(trilist.BooleanInput[joinMap.OutputEndpointOnline + ioSlot]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class DmChassisControllerJoinMap : JoinMapBase
|
||||||
|
{
|
||||||
|
public uint IsOnline { get; set; }
|
||||||
|
public uint OutputVideo { get; set; }
|
||||||
|
public uint OutputAudio { get; set; }
|
||||||
|
public uint VideoSyncStatus { get; set; }
|
||||||
|
public uint InputNames { get; set; }
|
||||||
|
public uint OutputNames { get; set; }
|
||||||
|
public uint OutputCurrentVideoInputNames { get; set; }
|
||||||
|
public uint OutputCurrentAudioInputNames { get; set; }
|
||||||
|
public uint InputCurrentResolution { get; set; }
|
||||||
|
public uint InputEndpointOnline { get; set; }
|
||||||
|
public uint OutputEndpointOnline { get; set; }
|
||||||
|
//public uint HdcpSupport { get; set; }
|
||||||
|
//public uint HdcpSupportCapability { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public DmChassisControllerJoinMap()
|
||||||
|
{
|
||||||
|
IsOnline = 11;
|
||||||
|
OutputVideo = 100; //101-299
|
||||||
|
OutputAudio = 300; //301-499
|
||||||
|
VideoSyncStatus = 100; //101-299
|
||||||
|
InputNames = 100; //101-299
|
||||||
|
OutputNames = 300; //301-499
|
||||||
|
OutputCurrentVideoInputNames = 2000; //2001-2199
|
||||||
|
OutputCurrentAudioInputNames = 2200; //2201-2399
|
||||||
|
InputCurrentResolution = 2400; // 2401-2599
|
||||||
|
InputEndpointOnline = 500;
|
||||||
|
OutputEndpointOnline = 700;
|
||||||
|
//HdcpSupport = 1000; //1001-1199
|
||||||
|
//HdcpSupportCapability = 1200; //1201-1399
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OffsetJoinNumbers(uint joinStart)
|
||||||
|
{
|
||||||
|
var joinOffset = joinStart - 1;
|
||||||
|
|
||||||
|
IsOnline = IsOnline + joinOffset;
|
||||||
|
OutputVideo = OutputVideo + joinOffset;
|
||||||
|
OutputAudio = OutputAudio + joinOffset;
|
||||||
|
VideoSyncStatus = VideoSyncStatus + joinOffset;
|
||||||
|
InputNames = InputNames + joinOffset;
|
||||||
|
OutputNames = OutputNames + joinOffset;
|
||||||
|
OutputCurrentVideoInputNames = OutputCurrentVideoInputNames + joinOffset;
|
||||||
|
OutputCurrentAudioInputNames = OutputCurrentAudioInputNames + joinOffset;
|
||||||
|
InputCurrentResolution = InputCurrentResolution + joinOffset;
|
||||||
|
InputEndpointOnline = InputEndpointOnline + joinOffset;
|
||||||
|
OutputEndpointOnline = OutputEndpointOnline + joinOffset;
|
||||||
|
//HdcpSupport = HdcpSupport + joinOffset;
|
||||||
|
//HdcpSupportCapability = HdcpSupportCapability + joinOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
75
PepperDashEssentials/Bridges/DmRmcControllerBridge.cs
Normal file
75
PepperDashEssentials/Bridges/DmRmcControllerBridge.cs
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
|
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.DM;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Bridges
|
||||||
|
{
|
||||||
|
public static class DmRmcControllerApiExtensions
|
||||||
|
{
|
||||||
|
public static void LinkToApi(this DmRmcControllerBase rmc, BasicTriList trilist, uint joinStart, string joinMapKey)
|
||||||
|
{
|
||||||
|
var joinMap = JoinMapHelper.GetJoinMapForDevice(joinMapKey) as DmRmcControllerJoinMap;
|
||||||
|
|
||||||
|
if (joinMap == null)
|
||||||
|
joinMap = new DmRmcControllerJoinMap();
|
||||||
|
|
||||||
|
joinMap.OffsetJoinNumbers(joinStart);
|
||||||
|
|
||||||
|
Debug.Console(1, rmc, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
|
||||||
|
|
||||||
|
rmc.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline]);
|
||||||
|
if(rmc.VideoOutputResolutionFeedback != null)
|
||||||
|
rmc.VideoOutputResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentOutputResolution]);
|
||||||
|
if(rmc.EdidManufacturerFeedback != null)
|
||||||
|
rmc.EdidManufacturerFeedback.LinkInputSig(trilist.StringInput[joinMap.EdidManufacturer]);
|
||||||
|
if(rmc.EdidNameFeedback != null)
|
||||||
|
rmc.EdidNameFeedback.LinkInputSig(trilist.StringInput[joinMap.EdidName]);
|
||||||
|
if(rmc.EdidPreferredTimingFeedback != null)
|
||||||
|
rmc.EdidPreferredTimingFeedback.LinkInputSig(trilist.StringInput[joinMap.EdidPrefferedTiming]);
|
||||||
|
if(rmc.EdidSerialNumberFeedback != null)
|
||||||
|
rmc.EdidSerialNumberFeedback.LinkInputSig(trilist.StringInput[joinMap.EdidSerialNumber]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DmRmcControllerJoinMap : JoinMapBase
|
||||||
|
{
|
||||||
|
public uint IsOnline { get; set; }
|
||||||
|
public uint CurrentOutputResolution { get; set; }
|
||||||
|
public uint EdidManufacturer { get; set; }
|
||||||
|
public uint EdidName { get; set; }
|
||||||
|
public uint EdidPrefferedTiming { get; set; }
|
||||||
|
public uint EdidSerialNumber { get; set; }
|
||||||
|
|
||||||
|
public DmRmcControllerJoinMap()
|
||||||
|
{
|
||||||
|
// Digital
|
||||||
|
IsOnline = 1;
|
||||||
|
|
||||||
|
// Serial
|
||||||
|
CurrentOutputResolution = 1;
|
||||||
|
EdidManufacturer = 2;
|
||||||
|
EdidName = 3;
|
||||||
|
EdidPrefferedTiming = 4;
|
||||||
|
EdidSerialNumber = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OffsetJoinNumbers(uint joinStart)
|
||||||
|
{
|
||||||
|
var joinOffset = joinStart - 1;
|
||||||
|
|
||||||
|
IsOnline = IsOnline + joinOffset;
|
||||||
|
CurrentOutputResolution = CurrentOutputResolution + joinOffset;
|
||||||
|
EdidManufacturer = EdidManufacturer + joinOffset;
|
||||||
|
EdidName = EdidName + joinOffset;
|
||||||
|
EdidPrefferedTiming = EdidPrefferedTiming + joinOffset;
|
||||||
|
EdidSerialNumber = EdidSerialNumber + joinOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
173
PepperDashEssentials/Bridges/DmTxControllerBridge.cs
Normal file
173
PepperDashEssentials/Bridges/DmTxControllerBridge.cs
Normal file
|
|
@ -0,0 +1,173 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
using Crestron.SimplSharpPro.DM;
|
||||||
|
using Crestron.SimplSharpPro.DM.Endpoints;
|
||||||
|
using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
|
||||||
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
|
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.DM;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Bridges
|
||||||
|
{
|
||||||
|
public static class DmTxControllerApiExtensions
|
||||||
|
{
|
||||||
|
public static void LinkToApi(this DmTxControllerBase tx, BasicTriList trilist, uint joinStart, string joinMapKey)
|
||||||
|
{
|
||||||
|
var joinMap = JoinMapHelper.GetJoinMapForDevice(joinMapKey) as DmTxControllerJoinMap;
|
||||||
|
|
||||||
|
if (joinMap == null)
|
||||||
|
joinMap = new DmTxControllerJoinMap();
|
||||||
|
|
||||||
|
joinMap.OffsetJoinNumbers(joinStart);
|
||||||
|
|
||||||
|
Debug.Console(1, tx, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
|
||||||
|
|
||||||
|
tx.IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline]);
|
||||||
|
tx.AnyVideoInput.VideoStatus.VideoSyncFeedback.LinkInputSig(trilist.BooleanInput[joinMap.VideoSyncStatus]);
|
||||||
|
tx.AnyVideoInput.VideoStatus.VideoResolutionFeedback.LinkInputSig(trilist.StringInput[joinMap.CurrentInputResolution]);
|
||||||
|
//tx.HdcpSupportAllFeedback.LinkInputSig(trilist.UShortInput[joinMap.HdcpSupportCapability]);
|
||||||
|
|
||||||
|
bool hdcpTypeSimple;
|
||||||
|
|
||||||
|
if (tx.Hardware is DmTx4kX02CBase || tx.Hardware is DmTx4kzX02CBase)
|
||||||
|
hdcpTypeSimple = false;
|
||||||
|
else
|
||||||
|
hdcpTypeSimple = true;
|
||||||
|
|
||||||
|
if (tx is ITxRouting)
|
||||||
|
{
|
||||||
|
var txR = tx as ITxRouting;
|
||||||
|
|
||||||
|
trilist.SetUShortSigAction(joinMap.VideoInput,
|
||||||
|
new Action<ushort>(i => txR.ExecuteNumericSwitch(i, 0, eRoutingSignalType.Video)));
|
||||||
|
trilist.SetUShortSigAction(joinMap.AudioInput,
|
||||||
|
new Action<ushort>(i => txR.ExecuteNumericSwitch(i, 0, eRoutingSignalType.Audio)));
|
||||||
|
|
||||||
|
txR.VideoSourceNumericFeedback.LinkInputSig(trilist.UShortInput[joinMap.VideoInput]);
|
||||||
|
txR.AudioSourceNumericFeedback.LinkInputSig(trilist.UShortInput[joinMap.AudioInput]);
|
||||||
|
|
||||||
|
trilist.UShortInput[joinMap.HdcpSupportCapability].UShortValue = (ushort)tx.HdcpSupportCapability;
|
||||||
|
|
||||||
|
if(txR.InputPorts[DmPortName.HdmiIn] != null)
|
||||||
|
{
|
||||||
|
var inputPort = txR.InputPorts[DmPortName.HdmiIn];
|
||||||
|
|
||||||
|
if (tx.Feedbacks["HdmiInHdcpCapability"] != null)
|
||||||
|
(tx.Feedbacks["HdmiInHdcpCapability"] as IntFeedback).LinkInputSig(trilist.UShortInput[joinMap.Port1HdcpState]);
|
||||||
|
|
||||||
|
if (inputPort.ConnectionType == eRoutingPortConnectionType.Hdmi && inputPort.Port != null)
|
||||||
|
{
|
||||||
|
var port = inputPort.Port as EndpointHdmiInput;
|
||||||
|
|
||||||
|
SetHdcpCapabilityAction(hdcpTypeSimple, port, joinMap.Port1HdcpState, trilist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (txR.InputPorts[DmPortName.HdmiIn1] != null)
|
||||||
|
{
|
||||||
|
var inputPort = txR.InputPorts[DmPortName.HdmiIn1];
|
||||||
|
|
||||||
|
if (tx.Feedbacks["HdmiIn1HdcpCapability"] != null)
|
||||||
|
(tx.Feedbacks["HdmiIn1HdcpCapability"] as IntFeedback).LinkInputSig(trilist.UShortInput[joinMap.Port1HdcpState]);
|
||||||
|
|
||||||
|
if (inputPort.ConnectionType == eRoutingPortConnectionType.Hdmi && inputPort.Port != null)
|
||||||
|
{
|
||||||
|
var port = inputPort.Port as EndpointHdmiInput;
|
||||||
|
|
||||||
|
SetHdcpCapabilityAction(hdcpTypeSimple, port, joinMap.Port1HdcpState, trilist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (txR.InputPorts[DmPortName.HdmiIn2] != null)
|
||||||
|
{
|
||||||
|
var inputPort = txR.InputPorts[DmPortName.HdmiIn2];
|
||||||
|
|
||||||
|
if (tx.Feedbacks["HdmiIn2HdcpCapability"] != null)
|
||||||
|
(tx.Feedbacks["HdmiIn2HdcpCapability"] as IntFeedback).LinkInputSig(trilist.UShortInput[joinMap.Port1HdcpState]);
|
||||||
|
|
||||||
|
if (inputPort.ConnectionType == eRoutingPortConnectionType.Hdmi && inputPort.Port != null)
|
||||||
|
{
|
||||||
|
var port = inputPort.Port as EndpointHdmiInput;
|
||||||
|
|
||||||
|
SetHdcpCapabilityAction(hdcpTypeSimple, port, joinMap.Port2HdcpState, trilist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetHdcpCapabilityAction(bool hdcpTypeSimple, EndpointHdmiInput port, uint join, BasicTriList trilist)
|
||||||
|
{
|
||||||
|
if (hdcpTypeSimple)
|
||||||
|
{
|
||||||
|
trilist.SetUShortSigAction(join,
|
||||||
|
new Action<ushort>(s =>
|
||||||
|
{
|
||||||
|
if (s == 0)
|
||||||
|
{
|
||||||
|
port.HdcpSupportOff();
|
||||||
|
}
|
||||||
|
else if (s > 0)
|
||||||
|
{
|
||||||
|
port.HdcpSupportOn();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
trilist.SetUShortSigAction(join,
|
||||||
|
new Action<ushort>(s =>
|
||||||
|
{
|
||||||
|
port.HdcpCapability = (eHdcpCapabilityType)s;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DmTxControllerJoinMap : JoinMapBase
|
||||||
|
{
|
||||||
|
public uint IsOnline { get; set; }
|
||||||
|
public uint VideoSyncStatus { get; set; }
|
||||||
|
public uint CurrentInputResolution { get; set; }
|
||||||
|
public uint HdcpSupportCapability { get; set; }
|
||||||
|
public uint VideoInput { get; set; }
|
||||||
|
public uint AudioInput { get; set; }
|
||||||
|
public uint Port1HdcpState { get; set; }
|
||||||
|
public uint Port2HdcpState { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public DmTxControllerJoinMap()
|
||||||
|
{
|
||||||
|
// Digital
|
||||||
|
IsOnline = 1;
|
||||||
|
VideoSyncStatus = 2;
|
||||||
|
// Serial
|
||||||
|
CurrentInputResolution = 1;
|
||||||
|
// Analog
|
||||||
|
VideoInput = 1;
|
||||||
|
AudioInput = 2;
|
||||||
|
HdcpSupportCapability = 3;
|
||||||
|
Port1HdcpState = 4;
|
||||||
|
Port2HdcpState = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OffsetJoinNumbers(uint joinStart)
|
||||||
|
{
|
||||||
|
var joinOffset = joinStart - 1;
|
||||||
|
|
||||||
|
IsOnline = IsOnline + joinOffset;
|
||||||
|
VideoSyncStatus = VideoSyncStatus + joinOffset;
|
||||||
|
CurrentInputResolution = CurrentInputResolution + joinOffset;
|
||||||
|
VideoInput = VideoInput + joinOffset;
|
||||||
|
AudioInput = AudioInput + joinOffset;
|
||||||
|
HdcpSupportCapability = HdcpSupportCapability + joinOffset;
|
||||||
|
Port1HdcpState = Port1HdcpState + joinOffset;
|
||||||
|
Port2HdcpState = Port2HdcpState + joinOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
66
PepperDashEssentials/Bridges/GenericRelayDeviceBridge.cs
Normal file
66
PepperDashEssentials/Bridges/GenericRelayDeviceBridge.cs
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
|
|
||||||
|
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.Core.CrestronIO;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Bridges
|
||||||
|
{
|
||||||
|
public static class GenericRelayDeviceApiExtensions
|
||||||
|
{
|
||||||
|
public static void LinkToApi(this GenericRelayDevice relay, BasicTriList trilist, uint joinStart, string joinMapKey)
|
||||||
|
{
|
||||||
|
var joinMap = JoinMapHelper.GetJoinMapForDevice(joinMapKey) as GenericRelayControllerJoinMap;
|
||||||
|
|
||||||
|
if (joinMap == null)
|
||||||
|
joinMap = new GenericRelayControllerJoinMap();
|
||||||
|
|
||||||
|
joinMap.OffsetJoinNumbers(joinStart);
|
||||||
|
|
||||||
|
if (relay.RelayOutput == null)
|
||||||
|
{
|
||||||
|
Debug.Console(1, relay, "Unable to link device '{0}'. Relay is null", relay.Key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Console(1, relay, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
|
||||||
|
|
||||||
|
trilist.SetBoolSigAction(joinMap.Relay, new Action<bool>(b =>
|
||||||
|
{
|
||||||
|
if (b)
|
||||||
|
relay.CloseRelay();
|
||||||
|
else
|
||||||
|
relay.OpenRelay();
|
||||||
|
}));
|
||||||
|
|
||||||
|
// feedback for relay state
|
||||||
|
|
||||||
|
relay.OutputIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Relay]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GenericRelayControllerJoinMap : JoinMapBase
|
||||||
|
{
|
||||||
|
//Digital
|
||||||
|
public uint Relay { get; set; }
|
||||||
|
|
||||||
|
public GenericRelayControllerJoinMap()
|
||||||
|
{
|
||||||
|
Relay = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OffsetJoinNumbers(uint joinStart)
|
||||||
|
{
|
||||||
|
var joinOffset = joinStart - 1;
|
||||||
|
|
||||||
|
Relay = Relay + joinOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -63,13 +63,18 @@ namespace PepperDash.Essentials.Bridges
|
||||||
|
|
||||||
public class IBasicCommunicationJoinMap : JoinMapBase
|
public class IBasicCommunicationJoinMap : JoinMapBase
|
||||||
{
|
{
|
||||||
// Default joins
|
//Digital
|
||||||
|
public uint Connect { get; set; }
|
||||||
|
public uint Connected { get; set; }
|
||||||
|
|
||||||
|
//Analog
|
||||||
|
public uint Status { get; set; }
|
||||||
|
|
||||||
|
// Serial
|
||||||
public uint TextReceived { get; set; }
|
public uint TextReceived { get; set; }
|
||||||
public uint SendText { get; set; }
|
public uint SendText { get; set; }
|
||||||
public uint SetPortConfig { get; set; }
|
public uint SetPortConfig { get; set; }
|
||||||
public uint Connect { get; set; }
|
|
||||||
public uint Connected { get; set; }
|
|
||||||
public uint Status { get; set; }
|
|
||||||
|
|
||||||
public IBasicCommunicationJoinMap()
|
public IBasicCommunicationJoinMap()
|
||||||
{
|
{
|
||||||
|
|
@ -94,38 +99,5 @@ namespace PepperDash.Essentials.Bridges
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
///// <summary>
|
|
||||||
/////
|
|
||||||
///// </summary>
|
|
||||||
//public static class DmChassisControllerApiExtensions
|
|
||||||
//{
|
|
||||||
// public static void LinkToApi(this PepperDash.Essentials.DM.DmChassisController chassis,
|
|
||||||
// BasicTriList trilist, Dictionary<string,uint> map, uint joinstart)
|
|
||||||
// {
|
|
||||||
// uint joinOffset = joinstart - 1;
|
|
||||||
|
|
||||||
// uint videoSelectOffset = 0 + joinOffset;
|
|
||||||
// uint audioSelectOffset = 40 + joinOffset;
|
|
||||||
|
|
||||||
|
|
||||||
// // loop chassis number of inupts
|
|
||||||
// for (uint i = 1; i <= chassis.Chassis.NumberOfOutputs; i++)
|
|
||||||
// {
|
|
||||||
// trilist.SetUShortSigAction(videoSelectOffset + i, new Action<ushort>(u => chassis.ExecuteSwitch(u, i, eRoutingSignalType.Video)));
|
|
||||||
// trilist.SetUShortSigAction(audioSelectOffset + i, new Action<ushort>(u => chassis.ExecuteSwitch(u, i, eRoutingSignalType.Audio)));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // wire up output change detection (try to add feedbacks or something to DMChassisController??
|
|
||||||
|
|
||||||
// // names?
|
|
||||||
|
|
||||||
// // HDCP?
|
|
||||||
|
|
||||||
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
59
PepperDashEssentials/Bridges/IDigitalInputBridge.cs
Normal file
59
PepperDashEssentials/Bridges/IDigitalInputBridge.cs
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
|
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core.CrestronIO;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Bridges
|
||||||
|
{
|
||||||
|
public static class IDigitalInputApiExtenstions
|
||||||
|
{
|
||||||
|
public static void LinkToApi(this IDigitalInput input, BasicTriList trilist, uint joinStart, string joinMapKey)
|
||||||
|
{
|
||||||
|
var joinMap = JoinMapHelper.GetJoinMapForDevice(joinMapKey) as IDigitalInputApiJoinMap;
|
||||||
|
|
||||||
|
if (joinMap == null)
|
||||||
|
joinMap = new IDigitalInputApiJoinMap();
|
||||||
|
|
||||||
|
joinMap.OffsetJoinNumbers(joinStart);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Debug.Console(1, input as Device, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
|
||||||
|
|
||||||
|
// Link feedback for input state
|
||||||
|
input.InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState]);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.Console(1, input as Device, "Unable to link device '{0}'. Input is null", (input as Device).Key);
|
||||||
|
Debug.Console(1, input as Device, "Error: {0}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IDigitalInputApiJoinMap : JoinMapBase
|
||||||
|
{
|
||||||
|
//Digital
|
||||||
|
public uint InputState { get; set; }
|
||||||
|
|
||||||
|
public IDigitalInputApiJoinMap()
|
||||||
|
{
|
||||||
|
InputState = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OffsetJoinNumbers(uint joinStart)
|
||||||
|
{
|
||||||
|
var joinOffset = joinStart - 1;
|
||||||
|
|
||||||
|
InputState = InputState + joinOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
151
PepperDashEssentials/Bridges/SystemMonitorBridge.cs
Normal file
151
PepperDashEssentials/Bridges/SystemMonitorBridge.cs
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
|
using Crestron.SimplSharpPro.Diagnostics;
|
||||||
|
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.Core.Monitoring;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Bridges
|
||||||
|
{
|
||||||
|
public static class SystemMonitorBridge
|
||||||
|
{
|
||||||
|
public static void LinkToApi(this SystemMonitorController systemMonitorController, BasicTriList trilist, uint joinStart, string joinMapKey)
|
||||||
|
{
|
||||||
|
var joinMap = JoinMapHelper.GetJoinMapForDevice(joinMapKey) as SystemMonitorJoinMap;
|
||||||
|
|
||||||
|
if (joinMap == null)
|
||||||
|
joinMap = new SystemMonitorJoinMap();
|
||||||
|
|
||||||
|
joinMap.OffsetJoinNumbers(joinStart);
|
||||||
|
|
||||||
|
//Debug.Console(1, systemMonitorController, "Linking API starting at join: {0}", joinStart);
|
||||||
|
|
||||||
|
systemMonitorController.TimeZoneFeedback.LinkInputSig(trilist.UShortInput[joinMap.TimeZone]);
|
||||||
|
//trilist.SetUShortSigAction(joinMap.TimeZone, new Action<ushort>(u => systemMonitorController.SetTimeZone(u)));
|
||||||
|
systemMonitorController.TimeZoneTextFeedback.LinkInputSig(trilist.StringInput[joinMap.TimeZoneName]);
|
||||||
|
|
||||||
|
systemMonitorController.IOControllerVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.IOControllerVersion]);
|
||||||
|
systemMonitorController.SnmpVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.SnmpAppVersion]);
|
||||||
|
systemMonitorController.BACnetAppVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.BACnetAppVersion]);
|
||||||
|
systemMonitorController.ControllerVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.ControllerVersion]);
|
||||||
|
|
||||||
|
|
||||||
|
// iterate the program status feedback collection and map all the joins
|
||||||
|
var programSlotJoinStart = joinMap.ProgramStartJoin;
|
||||||
|
|
||||||
|
foreach (var p in systemMonitorController.ProgramStatusFeedbackCollection)
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: link feedbacks for each program slot
|
||||||
|
var programNumber = p.Value.Program.Number;
|
||||||
|
|
||||||
|
//Debug.Console(1, systemMonitorController, "Linking API for Program Slot: {0} starting at join: {1}", programNumber, programSlotJoinStart);
|
||||||
|
|
||||||
|
trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramStart, new Action<bool>
|
||||||
|
(b => SystemMonitor.ProgramCollection[programNumber].OperatingState = eProgramOperatingState.Start));
|
||||||
|
p.Value.ProgramStartedFeedback.LinkInputSig(trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramStart]);
|
||||||
|
|
||||||
|
trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramStop, new Action<bool>
|
||||||
|
(b => SystemMonitor.ProgramCollection[programNumber].OperatingState = eProgramOperatingState.Stop));
|
||||||
|
p.Value.ProgramStoppedFeedback.LinkInputSig(trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramStop]);
|
||||||
|
|
||||||
|
trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramRegister, new Action<bool>
|
||||||
|
(b => SystemMonitor.ProgramCollection[programNumber].RegistrationState = eProgramRegistrationState.Register));
|
||||||
|
p.Value.ProgramRegisteredFeedback.LinkInputSig(trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramRegister]);
|
||||||
|
|
||||||
|
trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramUnregister, new Action<bool>
|
||||||
|
(b => SystemMonitor.ProgramCollection[programNumber].RegistrationState = eProgramRegistrationState.Unregister));
|
||||||
|
p.Value.ProgramUnregisteredFeedback.LinkInputSig(trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramUnregister]);
|
||||||
|
|
||||||
|
programSlotJoinStart = programSlotJoinStart + joinMap.ProgramOffsetJoin;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SystemMonitorJoinMap : JoinMapBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Offset to indicate where the range of iterated program joins will start
|
||||||
|
/// </summary>
|
||||||
|
public uint ProgramStartJoin { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Offset between each program join set
|
||||||
|
/// </summary>
|
||||||
|
public uint ProgramOffsetJoin { get; set; }
|
||||||
|
|
||||||
|
//Digital
|
||||||
|
public uint ProgramStart { get; set; }
|
||||||
|
public uint ProgramStop { get; set; }
|
||||||
|
public uint ProgramRegister { get; set; }
|
||||||
|
public uint ProgramUnregister { get; set; }
|
||||||
|
|
||||||
|
//Analog
|
||||||
|
public uint TimeZone { get; set; }
|
||||||
|
|
||||||
|
//Serial
|
||||||
|
public uint TimeZoneName { get; set; }
|
||||||
|
public uint IOControllerVersion { get; set; }
|
||||||
|
public uint SnmpAppVersion { get; set; }
|
||||||
|
public uint BACnetAppVersion { get; set; }
|
||||||
|
public uint ControllerVersion { get; set; }
|
||||||
|
|
||||||
|
public uint ProgramName { get; set; }
|
||||||
|
public uint ProgramCompiledTime { get; set; }
|
||||||
|
public uint ProgramCrestronDatabaseVersion { get; set; }
|
||||||
|
public uint ProgramEnvironmentVersion { get; set; }
|
||||||
|
public uint AggregatedProgramInfo { get; set; }
|
||||||
|
|
||||||
|
public SystemMonitorJoinMap()
|
||||||
|
{
|
||||||
|
TimeZone = 1;
|
||||||
|
|
||||||
|
TimeZoneName = 1;
|
||||||
|
IOControllerVersion = 2;
|
||||||
|
SnmpAppVersion = 3;
|
||||||
|
BACnetAppVersion = 4;
|
||||||
|
ControllerVersion = 5;
|
||||||
|
|
||||||
|
|
||||||
|
ProgramStartJoin = 10;
|
||||||
|
|
||||||
|
ProgramOffsetJoin = 5;
|
||||||
|
|
||||||
|
// Offset in groups of 5 joins
|
||||||
|
ProgramStart = 1;
|
||||||
|
ProgramStop = 2;
|
||||||
|
ProgramRegister = 3;
|
||||||
|
ProgramUnregister = 4;
|
||||||
|
|
||||||
|
ProgramName = 1;
|
||||||
|
ProgramCompiledTime = 2;
|
||||||
|
ProgramCrestronDatabaseVersion = 3;
|
||||||
|
ProgramEnvironmentVersion = 4;
|
||||||
|
AggregatedProgramInfo = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OffsetJoinNumbers(uint joinStart)
|
||||||
|
{
|
||||||
|
var joinOffset = joinStart - 1;
|
||||||
|
|
||||||
|
TimeZone = TimeZone + joinOffset;
|
||||||
|
|
||||||
|
TimeZoneName = TimeZoneName + joinOffset;
|
||||||
|
IOControllerVersion = IOControllerVersion + joinOffset;
|
||||||
|
SnmpAppVersion = SnmpAppVersion + joinOffset;
|
||||||
|
BACnetAppVersion = BACnetAppVersion + joinOffset;
|
||||||
|
ControllerVersion = ControllerVersion + joinOffset;
|
||||||
|
|
||||||
|
// Sets the initial join value where the iterated program joins will begin
|
||||||
|
ProgramStartJoin = ProgramStartJoin + joinOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,188 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
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
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Loads the ConfigObject from the file
|
|
||||||
/// </summary>
|
|
||||||
public class ConfigReader
|
|
||||||
{
|
|
||||||
public static EssentialsConfig ConfigObject { get; private set; }
|
|
||||||
|
|
||||||
public static bool LoadConfig2()
|
|
||||||
{
|
|
||||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading unmerged system/template portal configuration file.");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
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 into final config output
|
|
||||||
|
|
||||||
if (doubleObj["system_url"] != null)
|
|
||||||
{
|
|
||||||
ConfigObject.SystemUrl = doubleObj["system_url"].Value<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doubleObj["template_url"] != null)
|
|
||||||
{
|
|
||||||
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, Debug.ErrorLogLevel.Error, "ERROR: Config load failed: \r{0}", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static JObject MergeConfigs(JObject doubleConfig)
|
|
||||||
{
|
|
||||||
var system = JObject.FromObject(doubleConfig["system"]);
|
|
||||||
var template = JObject.FromObject(doubleConfig["template"]);
|
|
||||||
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
|
|
||||||
merged.Add("info", template["info"]);
|
|
||||||
|
|
||||||
merged.Add("devices", MergeArraysOnTopLevelProperty(template["devices"] as JArray,
|
|
||||||
system["devices"] as JArray, "uid"));
|
|
||||||
|
|
||||||
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 (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 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());
|
|
||||||
|
|
||||||
Debug.Console(2, "MERGED CONFIG RESULT: \x0d\x0a{0}", merged);
|
|
||||||
return merged;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Merges the contents of a base and a delta array, matching the entries on a top-level property
|
|
||||||
/// given by propertyName. Returns a merge of them. Items in the delta array that do not have
|
|
||||||
/// a matched item in base array will not be merged.
|
|
||||||
/// </summary>
|
|
||||||
static JArray MergeArraysOnTopLevelProperty(JArray a1, JArray a2, string propertyName)
|
|
||||||
{
|
|
||||||
var result = new JArray();
|
|
||||||
if (a2 == null)
|
|
||||||
result = a1;
|
|
||||||
else if (a1 != null)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < a1.Count(); i++)
|
|
||||||
{
|
|
||||||
var a1Dev = a1[i];
|
|
||||||
// Try to get a system device and if found, merge it onto template
|
|
||||||
var a2Match = a2.FirstOrDefault(t => t[propertyName].Equals(a1Dev[propertyName]));// t.Value<int>("uid") == tmplDev.Value<int>("uid"));
|
|
||||||
if (a2Match != null)
|
|
||||||
{
|
|
||||||
var mergedItem = Merge(a1Dev, a2Match);// Merge(JObject.FromObject(a1Dev), JObject.FromObject(a2Match));
|
|
||||||
result.Add(mergedItem);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
result.Add(a1Dev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Helper for using with JTokens. Converts to JObject
|
|
||||||
/// </summary>
|
|
||||||
static JObject Merge(JToken t1, JToken t2)
|
|
||||||
{
|
|
||||||
return Merge(JObject.FromObject(t1), JObject.FromObject(t2));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Merge b ONTO a
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="a"></param>
|
|
||||||
/// <param name="b"></param>
|
|
||||||
static JObject Merge(JObject o1, JObject o2)
|
|
||||||
{
|
|
||||||
foreach (var o2Prop in o2)
|
|
||||||
{
|
|
||||||
var o1Value = o1[o2Prop.Key];
|
|
||||||
if (o1Value == null)
|
|
||||||
o1.Add(o2Prop.Key, o2Prop.Value);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
JToken replacement = null;
|
|
||||||
if (o2Prop.Value.HasValues && o1Value.HasValues) // Drill down
|
|
||||||
replacement = Merge(JObject.FromObject(o1Value), JObject.FromObject(o2Prop.Value));
|
|
||||||
else
|
|
||||||
replacement = o2Prop.Value;
|
|
||||||
o1[o2Prop.Key].Replace(replacement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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));
|
|
||||||
return dev == null ? null : dev.Group;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
using Crestron.SimplSharp.CrestronIO;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
using PepperDash.Core;
|
|
||||||
using PepperDash.Essentials.Core.Config;
|
|
||||||
using PepperDash.Essentials.Room.Config;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Loads the ConfigObject from the file
|
|
||||||
/// </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; }
|
|
||||||
|
|
||||||
[JsonProperty("systemUuid")]
|
|
||||||
public string SystemUuid
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/#.*");
|
|
||||||
|
|
||||||
string uuid = result.Groups[1].Value;
|
|
||||||
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonProperty("templateUuid")]
|
|
||||||
public string TemplateUuid
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/templates\/(.*)\/#.*");
|
|
||||||
|
|
||||||
string uuid = result.Groups[1].Value;
|
|
||||||
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonProperty("rooms")]
|
|
||||||
public List<EssentialsRoomConfig> Rooms { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class SystemTemplateConfigs
|
|
||||||
{
|
|
||||||
public EssentialsConfig System { get; set; }
|
|
||||||
|
|
||||||
public EssentialsConfig Template { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -4,11 +4,15 @@ using Crestron.SimplSharp;
|
||||||
using Crestron.SimplSharp.CrestronIO;
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
using Crestron.SimplSharpPro;
|
using Crestron.SimplSharpPro;
|
||||||
using Crestron.SimplSharpPro.CrestronThread;
|
using Crestron.SimplSharpPro.CrestronThread;
|
||||||
|
using Crestron.SimplSharpPro.Diagnostics;
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
using PepperDash.Essentials.Devices.Common;
|
using PepperDash.Essentials.Devices.Common;
|
||||||
using PepperDash.Essentials.DM;
|
using PepperDash.Essentials.DM;
|
||||||
using PepperDash.Essentials.Fusion;
|
using PepperDash.Essentials.Fusion;
|
||||||
|
using PepperDash.Essentials.Room.Config;
|
||||||
using PepperDash.Essentials.Room.Cotija;
|
using PepperDash.Essentials.Room.Cotija;
|
||||||
|
|
||||||
namespace PepperDash.Essentials
|
namespace PepperDash.Essentials
|
||||||
|
|
@ -30,11 +34,19 @@ namespace PepperDash.Essentials
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public override void InitializeSystem()
|
public override void InitializeSystem()
|
||||||
{
|
{
|
||||||
|
SystemMonitor.ProgramInitialization.ProgramInitializationUnderUserControl = true;
|
||||||
|
|
||||||
DeterminePlatform();
|
DeterminePlatform();
|
||||||
|
|
||||||
//CrestronConsole.AddNewConsoleCommand(s => GoWithLoad(), "go", "Loads configuration file",
|
//CrestronConsole.AddNewConsoleCommand(s => GoWithLoad(), "go", "Loads configuration file",
|
||||||
// ConsoleAccessLevelEnum.AccessOperator);
|
// ConsoleAccessLevelEnum.AccessOperator);
|
||||||
|
|
||||||
|
// CrestronConsole.AddNewConsoleCommand(S => { ConfigWriter.WriteConfigFile(null); }, "writeconfig", "writes the current config to a file", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
|
CrestronConsole.AddNewConsoleCommand(s =>
|
||||||
|
{
|
||||||
|
Debug.Console(0, Debug.ErrorLogLevel.Notice, "CONSOLE MESSAGE: {0}", s);
|
||||||
|
}, "appdebugmessage", "Writes message to log", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
|
|
||||||
CrestronConsole.AddNewConsoleCommand(s =>
|
CrestronConsole.AddNewConsoleCommand(s =>
|
||||||
{
|
{
|
||||||
foreach (var tl in TieLineCollection.Default)
|
foreach (var tl in TieLineCollection.Default)
|
||||||
|
|
@ -94,7 +106,7 @@ namespace PepperDash.Essentials
|
||||||
{
|
{
|
||||||
filePathPrefix = directoryPrefix + dirSeparator + "User" + dirSeparator;
|
filePathPrefix = directoryPrefix + dirSeparator + "User" + dirSeparator;
|
||||||
|
|
||||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on XiO Edge Server", versionString);
|
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on Virtual Control Server", versionString);
|
||||||
}
|
}
|
||||||
|
|
||||||
Global.SetFilePathPrefix(filePathPrefix);
|
Global.SetFilePathPrefix(filePathPrefix);
|
||||||
|
|
@ -137,12 +149,18 @@ namespace PepperDash.Essentials
|
||||||
"------------------------------------------------\r" +
|
"------------------------------------------------\r" +
|
||||||
"------------------------------------------------");
|
"------------------------------------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.Console(0, "FATAL INITIALIZE ERROR. System is in an inconsistent state:\r{0}", e);
|
Debug.Console(0, "FATAL INITIALIZE ERROR. System is in an inconsistent state:\r{0}", e);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notify the
|
||||||
|
SystemMonitor.ProgramInitialization.ProgramInitializationComplete = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -194,6 +212,7 @@ namespace PepperDash.Essentials
|
||||||
void Load()
|
void Load()
|
||||||
{
|
{
|
||||||
LoadDevices();
|
LoadDevices();
|
||||||
|
LinkSystemMonitorToAppServer();
|
||||||
LoadTieLines();
|
LoadTieLines();
|
||||||
LoadRooms();
|
LoadRooms();
|
||||||
LoadLogoServer();
|
LoadLogoServer();
|
||||||
|
|
@ -201,6 +220,26 @@ namespace PepperDash.Essentials
|
||||||
DeviceManager.ActivateAll();
|
DeviceManager.ActivateAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LinkSystemMonitorToAppServer()
|
||||||
|
{
|
||||||
|
var sysMon = DeviceManager.GetDeviceForKey("systemMonitor") as PepperDash.Essentials.Core.Monitoring.SystemMonitorController;
|
||||||
|
|
||||||
|
var appServer = DeviceManager.GetDeviceForKey("appServer") as CotijaSystemController;
|
||||||
|
|
||||||
|
|
||||||
|
if (sysMon != null && appServer != null)
|
||||||
|
{
|
||||||
|
var key = sysMon.Key + "-" + appServer.Key;
|
||||||
|
var messenger = new PepperDash.Essentials.AppServer.Messengers.SystemMonitorMessenger
|
||||||
|
(key, sysMon, "/device/systemMonitor");
|
||||||
|
|
||||||
|
messenger.RegisterWithAppServer(appServer);
|
||||||
|
|
||||||
|
DeviceManager.AddDevice(messenger);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads all devices from config and adds them to DeviceManager
|
/// Reads all devices from config and adds them to DeviceManager
|
||||||
|
|
@ -211,6 +250,9 @@ namespace PepperDash.Essentials
|
||||||
// Build the processor wrapper class
|
// Build the processor wrapper class
|
||||||
// DeviceManager.AddDevice(new PepperDash.Essentials.Core.Devices.CrestronProcessor("processor"));
|
// DeviceManager.AddDevice(new PepperDash.Essentials.Core.Devices.CrestronProcessor("processor"));
|
||||||
|
|
||||||
|
// Add global System Monitor device
|
||||||
|
DeviceManager.AddDevice(new PepperDash.Essentials.Core.Monitoring.SystemMonitorController("systemMonitor"));
|
||||||
|
|
||||||
foreach (var devConf in ConfigReader.ConfigObject.Devices)
|
foreach (var devConf in ConfigReader.ConfigObject.Devices)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -228,10 +270,15 @@ namespace PepperDash.Essentials
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try local factory first
|
// Try local factories first
|
||||||
var newDev = DeviceFactory.GetDevice(devConf);
|
var newDev = DeviceFactory.GetDevice(devConf);
|
||||||
|
|
||||||
|
if (newDev == null)
|
||||||
|
newDev = BridgeFactory.GetDevice(devConf);
|
||||||
|
|
||||||
// Then associated library factories
|
// Then associated library factories
|
||||||
|
if (newDev == null)
|
||||||
|
newDev = PepperDash.Essentials.Core.DeviceFactory.GetDevice(devConf);
|
||||||
if (newDev == null)
|
if (newDev == null)
|
||||||
newDev = PepperDash.Essentials.Devices.Common.DeviceFactory.GetDevice(devConf);
|
newDev = PepperDash.Essentials.Devices.Common.DeviceFactory.GetDevice(devConf);
|
||||||
if (newDev == null)
|
if (newDev == null)
|
||||||
|
|
@ -254,6 +301,7 @@ namespace PepperDash.Essentials
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper method to load tie lines. This should run after devices have loaded
|
/// Helper method to load tie lines. This should run after devices have loaded
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -293,7 +341,7 @@ namespace PepperDash.Essentials
|
||||||
|
|
||||||
foreach (var roomConfig in ConfigReader.ConfigObject.Rooms)
|
foreach (var roomConfig in ConfigReader.ConfigObject.Rooms)
|
||||||
{
|
{
|
||||||
var room = roomConfig.GetRoomObject();
|
var room = EssentialsRoomConfigHelper.GetRoomObject(roomConfig) as EssentialsRoomBase;
|
||||||
if (room != null)
|
if (room != null)
|
||||||
{
|
{
|
||||||
if (room is EssentialsHuddleSpaceRoom)
|
if (room is EssentialsHuddleSpaceRoom)
|
||||||
|
|
@ -318,10 +366,16 @@ namespace PepperDash.Essentials
|
||||||
|
|
||||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "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));
|
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, 0xf1));
|
||||||
|
|
||||||
|
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Cotija Bridge...");
|
||||||
|
// Cotija bridge
|
||||||
|
var bridge = new CotijaEssentialsHuddleSpaceRoomBridge(room);
|
||||||
|
AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present
|
||||||
|
DeviceManager.AddDevice(bridge);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is NOT EssentialsHuddleSpaceRoom, attempting to add to DeviceManager w/o Fusion");
|
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is NOT EssentialsRoom, attempting to add to DeviceManager w/o Fusion");
|
||||||
DeviceManager.AddDevice(room);
|
DeviceManager.AddDevice(room);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -345,7 +399,8 @@ namespace PepperDash.Essentials
|
||||||
var parent = DeviceManager.AllDevices.FirstOrDefault(d => d.Key == "appServer") as CotijaSystemController;
|
var parent = DeviceManager.AllDevices.FirstOrDefault(d => d.Key == "appServer") as CotijaSystemController;
|
||||||
if (parent == null)
|
if (parent == null)
|
||||||
{
|
{
|
||||||
Debug.Console(0, bridge, "ERROR: Cannot connect bridge. System controller not present");
|
Debug.Console(0, bridge, "ERROR: Cannot connect app server room bridge. System controller not present");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
Debug.Console(0, bridge, "Linking to parent controller");
|
Debug.Console(0, bridge, "Linking to parent controller");
|
||||||
bridge.AddParent(parent);
|
bridge.AddParent(parent);
|
||||||
|
|
|
||||||
|
|
@ -1,367 +0,0 @@
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -17,6 +17,7 @@ using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials;
|
using PepperDash.Essentials;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
using PepperDash.Essentials.Devices.Common;
|
using PepperDash.Essentials.Devices.Common;
|
||||||
using PepperDash.Essentials.Devices.Common.Occupancy;
|
using PepperDash.Essentials.Devices.Common.Occupancy;
|
||||||
|
|
||||||
|
|
@ -30,6 +31,10 @@ namespace PepperDash.Essentials.Fusion
|
||||||
//public event EventHandler<MeetingChangeEventArgs> MeetingEndWarning;
|
//public event EventHandler<MeetingChangeEventArgs> MeetingEndWarning;
|
||||||
//public event EventHandler<MeetingChangeEventArgs> NextMeetingBeginWarning;
|
//public event EventHandler<MeetingChangeEventArgs> NextMeetingBeginWarning;
|
||||||
|
|
||||||
|
public event EventHandler<EventArgs> RoomInfoChange;
|
||||||
|
|
||||||
|
public FusionCustomPropertiesBridge CustomPropertiesBridge = new FusionCustomPropertiesBridge();
|
||||||
|
|
||||||
protected FusionRoom FusionRoom;
|
protected FusionRoom FusionRoom;
|
||||||
protected EssentialsRoomBase Room;
|
protected EssentialsRoomBase Room;
|
||||||
Dictionary<Device, BoolInputSig> SourceToFeedbackSigs =
|
Dictionary<Device, BoolInputSig> SourceToFeedbackSigs =
|
||||||
|
|
@ -334,6 +339,8 @@ namespace PepperDash.Essentials.Fusion
|
||||||
FusionRoom.ErrorMessage.InputSig.StringValue =
|
FusionRoom.ErrorMessage.InputSig.StringValue =
|
||||||
"3: 7 Errors: This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;";
|
"3: 7 Errors: This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;";
|
||||||
|
|
||||||
|
SetUpEthernetValues();
|
||||||
|
|
||||||
GetProcessorEthernetValues();
|
GetProcessorEthernetValues();
|
||||||
|
|
||||||
GetSystemInfo();
|
GetSystemInfo();
|
||||||
|
|
@ -363,7 +370,7 @@ namespace PepperDash.Essentials.Fusion
|
||||||
systemReboot.OutputSig.SetSigFalseAction(() => CrestronConsole.SendControlSystemCommand("reboot", ref response));
|
systemReboot.OutputSig.SetSigFalseAction(() => CrestronConsole.SendControlSystemCommand("reboot", ref response));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void GetProcessorEthernetValues()
|
protected void SetUpEthernetValues()
|
||||||
{
|
{
|
||||||
Ip1 = FusionRoom.CreateOffsetStringSig(50, "Info - Processor - IP 1", eSigIoMask.InputSigOnly);
|
Ip1 = FusionRoom.CreateOffsetStringSig(50, "Info - Processor - IP 1", eSigIoMask.InputSigOnly);
|
||||||
Ip2 = FusionRoom.CreateOffsetStringSig(51, "Info - Processor - IP 2", eSigIoMask.InputSigOnly);
|
Ip2 = FusionRoom.CreateOffsetStringSig(51, "Info - Processor - IP 2", eSigIoMask.InputSigOnly);
|
||||||
|
|
@ -376,8 +383,10 @@ namespace PepperDash.Essentials.Fusion
|
||||||
Mac2 = FusionRoom.CreateOffsetStringSig(58, "Info - Processor - MAC 2", eSigIoMask.InputSigOnly);
|
Mac2 = FusionRoom.CreateOffsetStringSig(58, "Info - Processor - MAC 2", eSigIoMask.InputSigOnly);
|
||||||
NetMask1 = FusionRoom.CreateOffsetStringSig(59, "Info - Processor - Net Mask 1", eSigIoMask.InputSigOnly);
|
NetMask1 = FusionRoom.CreateOffsetStringSig(59, "Info - Processor - Net Mask 1", eSigIoMask.InputSigOnly);
|
||||||
NetMask2 = FusionRoom.CreateOffsetStringSig(60, "Info - Processor - Net Mask 2", eSigIoMask.InputSigOnly);
|
NetMask2 = FusionRoom.CreateOffsetStringSig(60, "Info - Processor - Net Mask 2", eSigIoMask.InputSigOnly);
|
||||||
|
}
|
||||||
|
|
||||||
// Interface =0
|
protected void GetProcessorEthernetValues()
|
||||||
|
{
|
||||||
Ip1.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0);
|
Ip1.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0);
|
||||||
Gateway.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, 0);
|
Gateway.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, 0);
|
||||||
Hostname.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0);
|
Hostname.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0);
|
||||||
|
|
@ -420,6 +429,16 @@ namespace PepperDash.Essentials.Fusion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void GetCustomProperties()
|
||||||
|
{
|
||||||
|
if (FusionRoom.IsOnline)
|
||||||
|
{
|
||||||
|
string fusionRoomCustomPropertiesRequest = @"<RequestRoomConfiguration><RequestID>RoomConfigurationRequest</RequestID><CustomProperties><Property></Property></CustomProperties></RequestRoomConfiguration>";
|
||||||
|
|
||||||
|
FusionRoom.ExtenderFusionRoomDataReservedSigs.RoomConfigQuery.StringValue = fusionRoomCustomPropertiesRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GetTouchpanelInfo()
|
void GetTouchpanelInfo()
|
||||||
{
|
{
|
||||||
// TODO Get IP and Project Name from TP
|
// TODO Get IP and Project Name from TP
|
||||||
|
|
@ -465,6 +484,7 @@ namespace PepperDash.Essentials.Fusion
|
||||||
|
|
||||||
FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = actionRequest;
|
FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = actionRequest;
|
||||||
|
|
||||||
|
GetCustomProperties();
|
||||||
|
|
||||||
// Request current Fusion Server Time
|
// Request current Fusion Server Time
|
||||||
RequestLocalDateTime(null);
|
RequestLocalDateTime(null);
|
||||||
|
|
@ -748,6 +768,82 @@ namespace PepperDash.Essentials.Fusion
|
||||||
Debug.Console(1, this, "Error parsing LocalDateTimeQueryResponse: {0}", e);
|
Debug.Console(1, this, "Error parsing LocalDateTimeQueryResponse: {0}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.RoomConfigResponse)
|
||||||
|
{
|
||||||
|
// Room info response with custom properties
|
||||||
|
|
||||||
|
string roomConfigResponseArgs = args.Sig.StringValue.Replace("&", "and");
|
||||||
|
|
||||||
|
Debug.Console(2, this, "Fusion Response: \n {0}", roomConfigResponseArgs);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
XmlDocument roomConfigResponse = new XmlDocument();
|
||||||
|
|
||||||
|
roomConfigResponse.LoadXml(roomConfigResponseArgs);
|
||||||
|
|
||||||
|
var requestRoomConfiguration = roomConfigResponse["RoomConfigurationResponse"];
|
||||||
|
|
||||||
|
if (requestRoomConfiguration != null)
|
||||||
|
{
|
||||||
|
RoomInformation roomInformation = new RoomInformation();
|
||||||
|
|
||||||
|
foreach (XmlElement e in roomConfigResponse.FirstChild.ChildNodes)
|
||||||
|
{
|
||||||
|
if (e.Name == "RoomInformation")
|
||||||
|
{
|
||||||
|
XmlReader roomInfo = new XmlReader(e.OuterXml);
|
||||||
|
|
||||||
|
roomInformation = CrestronXMLSerialization.DeSerializeObject<RoomInformation>(roomInfo);
|
||||||
|
}
|
||||||
|
else if (e.Name == "CustomFields")
|
||||||
|
{
|
||||||
|
foreach (XmlElement el in e)
|
||||||
|
{
|
||||||
|
FusionCustomProperty customProperty = new FusionCustomProperty();
|
||||||
|
|
||||||
|
if (el.Name == "CustomField")
|
||||||
|
{
|
||||||
|
customProperty.ID = el.Attributes["ID"].Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (XmlElement elm in el)
|
||||||
|
{
|
||||||
|
if (elm.Name == "CustomFieldName")
|
||||||
|
{
|
||||||
|
customProperty.CustomFieldName = elm.InnerText;
|
||||||
|
}
|
||||||
|
if (elm.Name == "CustomFieldType")
|
||||||
|
{
|
||||||
|
customProperty.CustomFieldType = elm.InnerText;
|
||||||
|
}
|
||||||
|
if (elm.Name == "CustomFieldValue")
|
||||||
|
{
|
||||||
|
customProperty.CustomFieldValue = elm.InnerText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
roomInformation.FusionCustomProperties.Add(customProperty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var handler = RoomInfoChange;
|
||||||
|
if (handler != null)
|
||||||
|
handler(this, new EventArgs());
|
||||||
|
|
||||||
|
CustomPropertiesBridge.EvaluateRoomInfo(Room.Key, roomInformation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Error parsing Custom Properties response: {0}", e);
|
||||||
|
}
|
||||||
|
//PrintRoomInfo();
|
||||||
|
//getRoomInfoBusy = false;
|
||||||
|
//_DynFusion.API.EISC.BooleanInput[Constants.GetRoomInfo].BoolValue = getRoomInfoBusy;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -1461,5 +1557,39 @@ namespace PepperDash.Essentials.Fusion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class RoomInformation
|
||||||
|
{
|
||||||
|
public string ID { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Location { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public string TimeZone { get; set; }
|
||||||
|
public string WebcamURL { get; set; }
|
||||||
|
public string BacklogMsg { get; set; }
|
||||||
|
public string SubErrorMsg { get; set; }
|
||||||
|
public string EmailInfo { get; set; }
|
||||||
|
public List<FusionCustomProperty> FusionCustomProperties { get; set; }
|
||||||
|
|
||||||
|
public RoomInformation()
|
||||||
|
{
|
||||||
|
FusionCustomProperties = new List<FusionCustomProperty>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class FusionCustomProperty
|
||||||
|
{
|
||||||
|
public string ID { get; set; }
|
||||||
|
public string CustomFieldName { get; set; }
|
||||||
|
public string CustomFieldType { get; set; }
|
||||||
|
public string CustomFieldValue { get; set; }
|
||||||
|
|
||||||
|
public FusionCustomProperty()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public FusionCustomProperty(string id)
|
||||||
|
{
|
||||||
|
ID = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13,6 +13,7 @@ using Crestron.SimplSharpPro.Fusion;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials;
|
using PepperDash.Essentials;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
using PepperDash.Essentials.Devices.Common;
|
using PepperDash.Essentials.Devices.Common;
|
||||||
using PepperDash.Essentials.Devices.Common.Occupancy;
|
using PepperDash.Essentials.Devices.Common.Occupancy;
|
||||||
|
|
||||||
|
|
@ -186,14 +187,7 @@ namespace PepperDash.Essentials.Fusion
|
||||||
FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction((Room as EssentialsHuddleVtc1Room).PowerOnToDefaultOrLastSource);
|
FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction((Room as EssentialsHuddleVtc1Room).PowerOnToDefaultOrLastSource);
|
||||||
FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff"));
|
FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff"));
|
||||||
// NO!! room.RoomIsOn.LinkComplementInputSig(FusionRoom.SystemPowerOff.InputSig);
|
// NO!! room.RoomIsOn.LinkComplementInputSig(FusionRoom.SystemPowerOff.InputSig);
|
||||||
FusionRoom.ErrorMessage.InputSig.StringValue =
|
|
||||||
"3: 7 Errors: This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;";
|
|
||||||
|
|
||||||
GetProcessorEthernetValues();
|
|
||||||
|
|
||||||
GetSystemInfo();
|
|
||||||
|
|
||||||
GetProcessorInfo();
|
|
||||||
|
|
||||||
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
|
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
|
using PepperDash.Essentials.Core.Devices;
|
||||||
|
using PepperDash.Essentials.Room.Behaviours;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Fusion
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Handles mapping Fusion Custom Property values to system properties
|
||||||
|
/// </summary>
|
||||||
|
public class FusionCustomPropertiesBridge
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Evaluates the room info and custom properties from Fusion and updates the system properties aa needed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="roomInfo"></param>
|
||||||
|
public void EvaluateRoomInfo(string roomKey, RoomInformation roomInfo)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var reconfigurableDevices = DeviceManager.AllDevices.Where(d => d is ReconfigurableDevice);
|
||||||
|
|
||||||
|
foreach (var device in reconfigurableDevices)
|
||||||
|
{
|
||||||
|
// Get the current device config so new values can be overwritten over existing
|
||||||
|
var deviceConfig = (device as ReconfigurableDevice).Config;
|
||||||
|
|
||||||
|
if (device is RoomOnToDefaultSourceWhenOccupied)
|
||||||
|
{
|
||||||
|
Debug.Console(1, "Mapping Room on via Occupancy values from Fusion");
|
||||||
|
|
||||||
|
var devProps = JsonConvert.DeserializeObject<RoomOnToDefaultSourceWhenOccupiedConfig>(deviceConfig.Properties.ToString());
|
||||||
|
|
||||||
|
var enableFeature = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupied"));
|
||||||
|
if (enableFeature != null)
|
||||||
|
devProps.EnableRoomOnWhenOccupied = bool.Parse(enableFeature.CustomFieldValue);
|
||||||
|
|
||||||
|
var enableTime = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("RoomOnWhenOccupiedStartTime"));
|
||||||
|
if (enableTime != null)
|
||||||
|
devProps.OccupancyStartTime = enableTime.CustomFieldValue;
|
||||||
|
|
||||||
|
var disableTime = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("RoomOnWhenOccupiedEndTime"));
|
||||||
|
if (disableTime != null)
|
||||||
|
devProps.OccupancyEndTime = disableTime.CustomFieldValue;
|
||||||
|
|
||||||
|
var enableSunday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedSun"));
|
||||||
|
if (enableSunday != null)
|
||||||
|
devProps.EnableSunday = bool.Parse(enableSunday.CustomFieldValue);
|
||||||
|
|
||||||
|
var enableMonday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedMon"));
|
||||||
|
if (enableMonday != null)
|
||||||
|
devProps.EnableMonday = bool.Parse(enableMonday.CustomFieldValue);
|
||||||
|
|
||||||
|
var enableTuesday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedTue"));
|
||||||
|
if (enableTuesday != null)
|
||||||
|
devProps.EnableTuesday = bool.Parse(enableTuesday.CustomFieldValue);
|
||||||
|
|
||||||
|
var enableWednesday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedWed"));
|
||||||
|
if (enableWednesday != null)
|
||||||
|
devProps.EnableWednesday = bool.Parse(enableWednesday.CustomFieldValue);
|
||||||
|
|
||||||
|
var enableThursday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedThu"));
|
||||||
|
if (enableThursday != null)
|
||||||
|
devProps.EnableThursday = bool.Parse(enableThursday.CustomFieldValue);
|
||||||
|
|
||||||
|
var enableFriday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedFri"));
|
||||||
|
if (enableFriday != null)
|
||||||
|
devProps.EnableFriday = bool.Parse(enableFriday.CustomFieldValue);
|
||||||
|
|
||||||
|
var enableSaturday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedSat"));
|
||||||
|
if (enableSaturday != null)
|
||||||
|
devProps.EnableSaturday = bool.Parse(enableSaturday.CustomFieldValue);
|
||||||
|
|
||||||
|
deviceConfig.Properties = JToken.FromObject(devProps);
|
||||||
|
}
|
||||||
|
else if (device is EssentialsRoomBase)
|
||||||
|
{
|
||||||
|
// Set the room name
|
||||||
|
if (!string.IsNullOrEmpty(roomInfo.Name))
|
||||||
|
{
|
||||||
|
Debug.Console(1, "Current Room Name: {0}. New Room Name: {1}", deviceConfig.Name, roomInfo.Name);
|
||||||
|
// Set the name in config
|
||||||
|
deviceConfig.Name = roomInfo.Name;
|
||||||
|
|
||||||
|
Debug.Console(1, "Room Name Successfully Changed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the help message
|
||||||
|
var helpMessage = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("RoomHelpMessage"));
|
||||||
|
if (helpMessage != null)
|
||||||
|
{
|
||||||
|
//Debug.Console(1, "Current Help Message: {0}. New Help Message: {1}", deviceConfig.Properties["help"]["message"].Value<string>(ToString()), helpMessage.CustomFieldValue);
|
||||||
|
deviceConfig.Properties["helpMessage"] = (string)helpMessage.CustomFieldValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the config on the device
|
||||||
|
(device as ReconfigurableDevice).SetConfig(deviceConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.Console(1, "FusionCustomPropetiesBridge: Error mapping properties: {0}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -85,6 +85,11 @@ namespace PepperDash.Essentials
|
||||||
return bridge;
|
return bridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (typeName == "roomonwhenoccupancydetectedfeature")
|
||||||
|
{
|
||||||
|
return new Room.Behaviours.RoomOnToDefaultSourceWhenOccupied(dc);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,12 +49,12 @@ namespace PepperDash.Essentials
|
||||||
avDriver.CurrentRoom = room as EssentialsHuddleSpaceRoom;
|
avDriver.CurrentRoom = room as EssentialsHuddleSpaceRoom;
|
||||||
|
|
||||||
// Environment Driver
|
// Environment Driver
|
||||||
if (avDriver.CurrentRoom.Config.Environment != null && avDriver.CurrentRoom.Config.Environment.DeviceKeys.Count > 0)
|
if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0)
|
||||||
{
|
{
|
||||||
Debug.Console(0, panelController, "Adding environment driver");
|
Debug.Console(0, panelController, "Adding environment driver");
|
||||||
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, props);
|
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, props);
|
||||||
|
|
||||||
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.Config.Environment);
|
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
|
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
|
||||||
|
|
@ -118,12 +118,12 @@ namespace PepperDash.Essentials
|
||||||
avDriver.CurrentRoom = room as EssentialsHuddleVtc1Room;
|
avDriver.CurrentRoom = room as EssentialsHuddleVtc1Room;
|
||||||
|
|
||||||
// Environment Driver
|
// Environment Driver
|
||||||
if (avDriver.CurrentRoom.Config.Environment != null && avDriver.CurrentRoom.Config.Environment.DeviceKeys.Count > 0)
|
if (avDriver.CurrentRoom.PropertiesConfig.Environment != null && avDriver.CurrentRoom.PropertiesConfig.Environment.DeviceKeys.Count > 0)
|
||||||
{
|
{
|
||||||
Debug.Console(0, panelController, "Adding environment driver");
|
Debug.Console(0, panelController, "Adding environment driver");
|
||||||
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, props);
|
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, props);
|
||||||
|
|
||||||
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.Config.Environment);
|
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.PropertiesConfig.Environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
|
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
|
||||||
|
|
|
||||||
|
|
@ -99,20 +99,30 @@
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath>
|
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="SimplSharpTimerEventInterface, Version=1.0.6197.20052, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpTimerEventInterface.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="AppServer\Messengers\AtcDdvc01Messenger.cs" />
|
||||||
|
<Compile Include="AppServer\Messengers\MessengerBase.cs" />
|
||||||
|
<Compile Include="AppServer\Messengers\SystemMonitorMessenger.cs" />
|
||||||
|
<Compile Include="AppServer\Messengers\VideoCodecBaseMessenger.cs" />
|
||||||
<Compile Include="Audio\EssentialsVolumeLevelConfig.cs" />
|
<Compile Include="Audio\EssentialsVolumeLevelConfig.cs" />
|
||||||
<Compile Include="Bridges\BridgeBase.cs" />
|
<Compile Include="Bridges\BridgeBase.cs" />
|
||||||
<Compile Include="Bridges\Bridges.BridgeFactory.cs" />
|
<Compile Include="Bridges\BridgeFactory.cs" />
|
||||||
<Compile Include="Bridges\DigitalLoggerBridge.cs" />
|
<Compile Include="Bridges\DmChassisControllerBridge.cs" />
|
||||||
<Compile Include="Bridges\EssentialsLightsBridge.cs" />
|
<Compile Include="Bridges\DmTxControllerBridge.cs" />
|
||||||
<Compile Include="Bridges\EssentialTVOne.cs" />
|
<Compile Include="Bridges\GenericRelayDeviceBridge.cs" />
|
||||||
<Compile Include="Bridges\EssentialDsp.cs" />
|
|
||||||
<Compile Include="Bridges\IBasicCommunicationBridge.cs" />
|
<Compile Include="Bridges\IBasicCommunicationBridge.cs" />
|
||||||
|
<Compile Include="Bridges\DmRmcControllerBridge.cs" />
|
||||||
|
<Compile Include="Bridges\IDigitalInputBridge.cs" />
|
||||||
<Compile Include="Bridges\JoinMapBase.cs" />
|
<Compile Include="Bridges\JoinMapBase.cs" />
|
||||||
|
<Compile Include="Bridges\SystemMonitorBridge.cs" />
|
||||||
<Compile Include="Configuration ORIGINAL\Builders\TPConfig.cs" />
|
<Compile Include="Configuration ORIGINAL\Builders\TPConfig.cs" />
|
||||||
<Compile Include="Configuration ORIGINAL\Configuration.cs" />
|
<Compile Include="Configuration ORIGINAL\Configuration.cs" />
|
||||||
<Compile Include="Configuration ORIGINAL\ConfigurationHelpers.cs" />
|
<Compile Include="Configuration ORIGINAL\ConfigurationHelpers.cs" />
|
||||||
|
|
@ -127,43 +137,43 @@
|
||||||
<Compile Include="Configuration ORIGINAL\Factories\MAYBE SetTopBoxFactory.cs" />
|
<Compile Include="Configuration ORIGINAL\Factories\MAYBE SetTopBoxFactory.cs" />
|
||||||
<Compile Include="Configuration ORIGINAL\Factories\DisplayFactory.cs" />
|
<Compile Include="Configuration ORIGINAL\Factories\DisplayFactory.cs" />
|
||||||
<Compile Include="Configuration ORIGINAL\Factories\FactoryHelper.cs" />
|
<Compile Include="Configuration ORIGINAL\Factories\FactoryHelper.cs" />
|
||||||
<Compile Include="Config\ConfigReader.cs" />
|
|
||||||
<Compile Include="Config\EssentialsConfig.cs" />
|
|
||||||
<Compile Include="Bridges\EssentialComms.cs" />
|
|
||||||
<Compile Include="Bridges\EssentialDM.cs" />
|
|
||||||
<Compile Include="Factory\DeviceFactory.cs" />
|
<Compile Include="Factory\DeviceFactory.cs" />
|
||||||
<Compile Include="Devices\Amplifier.cs" />
|
<Compile Include="Devices\Amplifier.cs" />
|
||||||
<Compile Include="Devices\DiscPlayer\OppoExtendedBdp.cs" />
|
<Compile Include="Devices\DiscPlayer\OppoExtendedBdp.cs" />
|
||||||
<Compile Include="Devices\NUMERIC AppleTV.cs" />
|
<Compile Include="Devices\NUMERIC AppleTV.cs" />
|
||||||
<Compile Include="ControlSystem.cs" />
|
<Compile Include="ControlSystem.cs" />
|
||||||
<Compile Include="Factory\UiDeviceFactory.cs" />
|
<Compile Include="Factory\UiDeviceFactory.cs" />
|
||||||
<Compile Include="OTHER\Fusion\EssentialsHuddleVtc1FusionController.cs" />
|
<Compile Include="FOR REFERENCE UI\OTHER\Fusion\EssentialsHuddleVtc1FusionController.cs" />
|
||||||
<Compile Include="OTHER\Fusion\FusionEventHandlers.cs" />
|
<Compile Include="FOR REFERENCE UI\OTHER\Fusion\FusionCustomPropertiesBridge.cs" />
|
||||||
<Compile Include="OTHER\Fusion\FusionProcessorQueries.cs" />
|
<Compile Include="FOR REFERENCE UI\OTHER\Fusion\FusionEventHandlers.cs" />
|
||||||
<Compile Include="OTHER\Fusion\FusionRviDataClasses.cs" />
|
<Compile Include="FOR REFERENCE UI\OTHER\Fusion\FusionProcessorQueries.cs" />
|
||||||
|
<Compile Include="FOR REFERENCE UI\OTHER\Fusion\FusionRviDataClasses.cs" />
|
||||||
<Compile Include="REMOVE EssentialsApp.cs" />
|
<Compile Include="REMOVE EssentialsApp.cs" />
|
||||||
<Compile Include="OTHER\Fusion\EssentialsHuddleSpaceFusionSystemControllerBase.cs" />
|
<Compile Include="FOR REFERENCE UI\OTHER\Fusion\EssentialsHuddleSpaceFusionSystemControllerBase.cs" />
|
||||||
<Compile Include="HttpApiHandler.cs" />
|
<Compile Include="HttpApiHandler.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Room\Behaviours\RoomOnToDefaultSourceWhenOccupied.cs" />
|
||||||
<Compile Include="Room\Config\DDVC01RoomPropertiesConfig.cs" />
|
<Compile Include="Room\Config\DDVC01RoomPropertiesConfig.cs" />
|
||||||
<Compile Include="Room\Config\EssentialsPresentationPropertiesConfig.cs" />
|
<Compile Include="Room\Config\EssentialsPresentationPropertiesConfig.cs" />
|
||||||
<Compile Include="Room\Config\EssentialsHuddleRoomPropertiesConfig.cs" />
|
<Compile Include="Room\Config\EssentialsHuddleRoomPropertiesConfig.cs" />
|
||||||
<Compile Include="Room\Config\EssentialsHuddleVtc1PropertiesConfig.cs" />
|
<Compile Include="Room\Config\EssentialsHuddleVtc1PropertiesConfig.cs" />
|
||||||
<Compile Include="Room\Config\EssentialsRoomEmergencyConfig.cs" />
|
<Compile Include="Room\Config\EssentialsRoomEmergencyConfig.cs" />
|
||||||
<Compile Include="Room\Cotija\CotijaConfig.cs" />
|
<Compile Include="AppServer\CotijaConfig.cs" />
|
||||||
<Compile Include="Room\Cotija\CotijaDdvc01DeviceBridge.cs" />
|
<Compile Include="AppServer\CotijaDdvc01DeviceBridge.cs" />
|
||||||
<Compile Include="Room\Cotija\Interfaces.cs" />
|
<Compile Include="AppServer\Interfaces.cs" />
|
||||||
<Compile Include="Room\Cotija\RoomBridges\CotijaBridgeBase.cs" />
|
<Compile Include="AppServer\RoomBridges\CotijaBridgeBase.cs" />
|
||||||
<Compile Include="Room\Cotija\RoomBridges\CotijaDdvc01RoomBridge.cs" />
|
<Compile Include="AppServer\RoomBridges\CotijaDdvc01RoomBridge.cs" />
|
||||||
<Compile Include="Room\Cotija\RoomBridges\CotijaEssentialsHuddleSpaceRoomBridge.cs" />
|
<Compile Include="AppServer\RoomBridges\CotijaEssentialsHuddleSpaceRoomBridge.cs" />
|
||||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IChannelExtensions.cs" />
|
<Compile Include="AppServer\DeviceTypeInterfaces\IChannelExtensions.cs" />
|
||||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IColorExtensions.cs" />
|
<Compile Include="AppServer\DeviceTypeInterfaces\IColorExtensions.cs" />
|
||||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IDPadExtensions.cs" />
|
<Compile Include="AppServer\DeviceTypeInterfaces\IDPadExtensions.cs" />
|
||||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IDvrExtensions.cs" />
|
<Compile Include="AppServer\DeviceTypeInterfaces\IDvrExtensions.cs" />
|
||||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\INumericExtensions.cs" />
|
<Compile Include="AppServer\DeviceTypeInterfaces\INumericExtensions.cs" />
|
||||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IPowerExtensions.cs" />
|
<Compile Include="AppServer\DeviceTypeInterfaces\IPowerExtensions.cs" />
|
||||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\ISetTopBoxControlsExtensions.cs" />
|
<Compile Include="AppServer\DeviceTypeInterfaces\ISetTopBoxControlsExtensions.cs" />
|
||||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\ITransportExtensions.cs" />
|
<Compile Include="AppServer\DeviceTypeInterfaces\ITransportExtensions.cs" />
|
||||||
|
<Compile Include="AppServer\RoomBridges\SourceDeviceMapDictionary.cs" />
|
||||||
|
<Compile Include="AppServer\Volumes.cs" />
|
||||||
<Compile Include="Room\Emergency\EsentialsRoomEmergencyContactClosure.cs" />
|
<Compile Include="Room\Emergency\EsentialsRoomEmergencyContactClosure.cs" />
|
||||||
<Compile Include="Room\Types\EssentialsHuddleVtc1Room.cs" />
|
<Compile Include="Room\Types\EssentialsHuddleVtc1Room.cs" />
|
||||||
<Compile Include="Room\Types\EssentialsPresentationRoom.cs" />
|
<Compile Include="Room\Types\EssentialsPresentationRoom.cs" />
|
||||||
|
|
@ -188,7 +198,7 @@
|
||||||
<Compile Include="UI\SubpageReferenceListCallStagingItem.cs" />
|
<Compile Include="UI\SubpageReferenceListCallStagingItem.cs" />
|
||||||
<Compile Include="UIDrivers\VC\EssentialsVideoCodecUiDriver.cs" />
|
<Compile Include="UIDrivers\VC\EssentialsVideoCodecUiDriver.cs" />
|
||||||
<Compile Include="UIDrivers\EssentialsHuddleVTC\EssentialsHuddleVtc1PanelAvFunctionsDriver.cs" />
|
<Compile Include="UIDrivers\EssentialsHuddleVTC\EssentialsHuddleVtc1PanelAvFunctionsDriver.cs" />
|
||||||
<Compile Include="UIDrivers\VolumeAndSourceChangeArgs.cs" />
|
<Compile Include="UIDrivers\SourceChangeArgs.cs" />
|
||||||
<Compile Include="UI\JoinConstants\UISmartObjectJoin.cs" />
|
<Compile Include="UI\JoinConstants\UISmartObjectJoin.cs" />
|
||||||
<Compile Include="UI\JoinConstants\UIStringlJoin.cs" />
|
<Compile Include="UI\JoinConstants\UIStringlJoin.cs" />
|
||||||
<Compile Include="UI\JoinConstants\UIUshortJoin.cs" />
|
<Compile Include="UI\JoinConstants\UIUshortJoin.cs" />
|
||||||
|
|
@ -201,7 +211,7 @@
|
||||||
<Compile Include="UIDrivers\Page Drivers\SingleSubpageModalAndBackDriver.cs" />
|
<Compile Include="UIDrivers\Page Drivers\SingleSubpageModalAndBackDriver.cs" />
|
||||||
<Compile Include="UIDrivers\SmartObjectRoomsList.cs" />
|
<Compile Include="UIDrivers\SmartObjectRoomsList.cs" />
|
||||||
<Compile Include="UI\JoinConstants\UIBoolJoin.cs" />
|
<Compile Include="UI\JoinConstants\UIBoolJoin.cs" />
|
||||||
<Compile Include="Room\Cotija\CotijaSystemController.cs" />
|
<Compile Include="AppServer\CotijaSystemController.cs" />
|
||||||
<Compile Include="UI\DualDisplaySourceSRLController.cs" />
|
<Compile Include="UI\DualDisplaySourceSRLController.cs" />
|
||||||
<Compile Include="UI\SubpageReferenceListActivityItem.cs" />
|
<Compile Include="UI\SubpageReferenceListActivityItem.cs" />
|
||||||
<Compile Include="UI\CrestronTouchpanelPropertiesConfig.cs" />
|
<Compile Include="UI\CrestronTouchpanelPropertiesConfig.cs" />
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,6 @@
|
||||||
[assembly: AssemblyTitle("PepperDashEssentials")]
|
[assembly: AssemblyTitle("PepperDashEssentials")]
|
||||||
[assembly: AssemblyCompany("PepperDash Technology Corp")]
|
[assembly: AssemblyCompany("PepperDash Technology Corp")]
|
||||||
[assembly: AssemblyProduct("PepperDashEssentials")]
|
[assembly: AssemblyProduct("PepperDashEssentials")]
|
||||||
[assembly: AssemblyCopyright("Copyright © PepperDash Technology Corp 2017")]
|
[assembly: AssemblyCopyright("Copyright © PepperDash Technology Corp 2018")]
|
||||||
[assembly: AssemblyVersion("1.2.4.*")]
|
[assembly: AssemblyVersion("1.3.1.*")]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,526 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
using Crestron.SimplSharp.Scheduler;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
|
using PepperDash.Essentials.Core.Devices;
|
||||||
|
using PepperDash.Essentials.Devices.Common.Occupancy;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Room.Behaviours
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A device that when linked to a room can power the room on when enabled during scheduled hours.
|
||||||
|
/// </summary>
|
||||||
|
public class RoomOnToDefaultSourceWhenOccupied : ReconfigurableDevice
|
||||||
|
{
|
||||||
|
RoomOnToDefaultSourceWhenOccupiedConfig PropertiesConfig;
|
||||||
|
|
||||||
|
public bool FeatureEnabled { get; private set; }
|
||||||
|
|
||||||
|
public DateTime FeatureEnabledTime { get; private set; }
|
||||||
|
|
||||||
|
ScheduledEvent FeatureEnableEvent;
|
||||||
|
|
||||||
|
const string FeatureEnableEventName = "EnableRoomOnToDefaultSourceWhenOccupied";
|
||||||
|
|
||||||
|
public DateTime FeatureDisabledTime { get; private set; }
|
||||||
|
|
||||||
|
ScheduledEvent FeatureDisableEvent;
|
||||||
|
|
||||||
|
const string FeatureDisableEventName = "DisableRoomOnToDefaultSourceWhenOccupied";
|
||||||
|
|
||||||
|
ScheduledEventGroup FeatureEventGroup;
|
||||||
|
|
||||||
|
public EssentialsRoomBase Room { get; private set; }
|
||||||
|
|
||||||
|
private Fusion.EssentialsHuddleSpaceFusionSystemControllerBase FusionRoom;
|
||||||
|
|
||||||
|
public RoomOnToDefaultSourceWhenOccupied(DeviceConfig config) :
|
||||||
|
base (config)
|
||||||
|
{
|
||||||
|
PropertiesConfig = JsonConvert.DeserializeObject<RoomOnToDefaultSourceWhenOccupiedConfig>(config.Properties.ToString());
|
||||||
|
|
||||||
|
FeatureEventGroup = new ScheduledEventGroup(this.Key);
|
||||||
|
|
||||||
|
FeatureEventGroup.RetrieveAllEvents();
|
||||||
|
|
||||||
|
// Add to the global class for tracking
|
||||||
|
Scheduler.AddEventGroup(FeatureEventGroup);
|
||||||
|
|
||||||
|
AddPostActivationAction(() =>
|
||||||
|
{
|
||||||
|
// Subscribe to room event to know when RoomOccupancy is set and ready to be subscribed to
|
||||||
|
if (Room != null)
|
||||||
|
Room.RoomOccupancyIsSet += new EventHandler<EventArgs>(RoomOccupancyIsSet);
|
||||||
|
|
||||||
|
else
|
||||||
|
Debug.Console(1, this, "Room has no RoomOccupancy object set");
|
||||||
|
|
||||||
|
var fusionRoomKey = PropertiesConfig.RoomKey + "-fusion";
|
||||||
|
|
||||||
|
FusionRoom = DeviceManager.GetDeviceForKey(fusionRoomKey) as Fusion.EssentialsHuddleSpaceFusionSystemControllerBase;
|
||||||
|
|
||||||
|
if (FusionRoom == null)
|
||||||
|
Debug.Console(1, this, "Unable to get Fusion Room from Device Manager with key: {0}", fusionRoomKey);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CustomActivate()
|
||||||
|
{
|
||||||
|
SetUpDevice();
|
||||||
|
|
||||||
|
return base.CustomActivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets up device based on config values
|
||||||
|
/// </summary>
|
||||||
|
void SetUpDevice()
|
||||||
|
{
|
||||||
|
Room = DeviceManager.GetDeviceForKey(PropertiesConfig.RoomKey) as EssentialsRoomBase;
|
||||||
|
|
||||||
|
if (Room != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FeatureEnabledTime = DateTime.Parse(PropertiesConfig.OccupancyStartTime);
|
||||||
|
|
||||||
|
if (FeatureEnabledTime != null)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Enabled Time: {0}", FeatureEnabledTime.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Debug.Console(1, this, "Unable to parse {0} to DateTime", PropertiesConfig.OccupancyStartTime);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Unable to parse OccupancyStartTime property: {0} \n Error: {1}", PropertiesConfig.OccupancyStartTime, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FeatureDisabledTime = DateTime.Parse(PropertiesConfig.OccupancyEndTime);
|
||||||
|
|
||||||
|
if (FeatureDisabledTime != null)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Disabled Time: {0}", FeatureDisabledTime.ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Debug.Console(1, this, "Unable to parse {0} to DateTime", PropertiesConfig.OccupancyEndTime);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Unable to parse a DateTime config value \n Error: {1}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PropertiesConfig.EnableRoomOnWhenOccupied)
|
||||||
|
FeatureEventGroup.ClearAllEvents();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddEnableEventToGroup();
|
||||||
|
|
||||||
|
AddDisableEventToGroup();
|
||||||
|
|
||||||
|
FeatureEventGroup.UserGroupCallBack += new ScheduledEventGroup.UserEventGroupCallBack(FeatureEventGroup_UserGroupCallBack);
|
||||||
|
|
||||||
|
FeatureEventGroup.EnableAllEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
FeatureEnabled = CheckIfFeatureShouldBeEnabled();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Debug.Console(1, this, "Unable to get room from Device Manager with key: {0}", PropertiesConfig.RoomKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected override void CustomSetConfig(DeviceConfig config)
|
||||||
|
{
|
||||||
|
var newPropertiesConfig = JsonConvert.DeserializeObject<RoomOnToDefaultSourceWhenOccupiedConfig>(config.Properties.ToString());
|
||||||
|
|
||||||
|
if(newPropertiesConfig != null)
|
||||||
|
PropertiesConfig = newPropertiesConfig;
|
||||||
|
|
||||||
|
ConfigWriter.UpdateDeviceConfig(config);
|
||||||
|
|
||||||
|
SetUpDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Subscribe to feedback from RoomIsOccupiedFeedback on Room
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
void RoomOccupancyIsSet(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (Room.RoomOccupancy != null)
|
||||||
|
{
|
||||||
|
Room.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange -= RoomIsOccupiedFeedback_OutputChange;
|
||||||
|
Room.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += new EventHandler<FeedbackEventArgs>(RoomIsOccupiedFeedback_OutputChange);
|
||||||
|
Debug.Console(1, this, "Subscribed to RoomOccupancy status from: '{0}'", Room.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeatureEventGroup_UserGroupCallBack(ScheduledEvent SchEvent, ScheduledEventCommon.eCallbackReason type)
|
||||||
|
{
|
||||||
|
if (type == ScheduledEventCommon.eCallbackReason.NormalExpiration)
|
||||||
|
{
|
||||||
|
if (SchEvent.Name == FeatureEnableEventName)
|
||||||
|
{
|
||||||
|
if (PropertiesConfig.EnableRoomOnWhenOccupied)
|
||||||
|
FeatureEnabled = true;
|
||||||
|
|
||||||
|
Debug.Console(1, this, "*****Feature Enabled by event.*****");
|
||||||
|
}
|
||||||
|
else if (SchEvent.Name == FeatureDisableEventName)
|
||||||
|
{
|
||||||
|
FeatureEnabled = false;
|
||||||
|
|
||||||
|
Debug.Console(1, this, "*****Feature Disabled by event.*****");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the feature should be currently enabled. Used on startup if processor starts after start time but before end time
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool CheckIfFeatureShouldBeEnabled()
|
||||||
|
{
|
||||||
|
bool enabled = false;
|
||||||
|
|
||||||
|
if(PropertiesConfig.EnableRoomOnWhenOccupied)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Current Time: {0} \n FeatureEnabledTime: {1} \n FeatureDisabledTime: {2}", DateTime.Now, FeatureEnabledTime, FeatureDisabledTime);
|
||||||
|
|
||||||
|
if (DateTime.Now.TimeOfDay.CompareTo(FeatureEnabledTime.TimeOfDay) >= 0 && FeatureDisabledTime.TimeOfDay.CompareTo(DateTime.Now.TimeOfDay) > 0)
|
||||||
|
{
|
||||||
|
if (SchedulerUtilities.CheckIfDayOfWeekMatchesRecurrenceDays(DateTime.Now, CalculateDaysOfWeekRecurrence()))
|
||||||
|
{
|
||||||
|
enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(enabled)
|
||||||
|
Debug.Console(1, this, "*****Feature Enabled*****");
|
||||||
|
else
|
||||||
|
Debug.Console(1, this, "*****Feature Disabled*****");
|
||||||
|
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Respond to Occupancy status event
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
void RoomIsOccupiedFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "RoomIsOccupiedFeeback.OutputChange event fired. e.BoolValue: {0}", e.BoolValue);
|
||||||
|
if(e.BoolValue)
|
||||||
|
{
|
||||||
|
// Occupancy detected
|
||||||
|
|
||||||
|
if (FeatureEnabled)
|
||||||
|
{
|
||||||
|
// Check room power state first
|
||||||
|
if (!Room.OnFeedback.BoolValue)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Powering Room on to default source");
|
||||||
|
Room.RunDefaultPresentRoute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateEvent(ScheduledEvent schEvent, string name)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Adding Event: '{0}'", name);
|
||||||
|
// Create the event
|
||||||
|
if (schEvent == null)
|
||||||
|
schEvent = new ScheduledEvent(name, FeatureEventGroup);
|
||||||
|
|
||||||
|
// Set up its initial properties
|
||||||
|
|
||||||
|
if(!schEvent.Acknowledgeable)
|
||||||
|
schEvent.Acknowledgeable = true;
|
||||||
|
|
||||||
|
if(!schEvent.Persistent)
|
||||||
|
schEvent.Persistent = true;
|
||||||
|
|
||||||
|
schEvent.DateAndTime.SetFirstDayOfWeek(ScheduledEventCommon.eFirstDayOfWeek.Sunday);
|
||||||
|
|
||||||
|
// Set config driven properties
|
||||||
|
|
||||||
|
if (schEvent.Name == FeatureEnableEventName)
|
||||||
|
{
|
||||||
|
schEvent.Description = "Enables the RoomOnToDefaultSourceWhenOccupiedFeature";
|
||||||
|
|
||||||
|
var eventRecurrennce = CalculateDaysOfWeekRecurrence();
|
||||||
|
|
||||||
|
var eventTime = new DateTime();
|
||||||
|
|
||||||
|
// Check to make sure the date for this event is in the future
|
||||||
|
if (DateTime.Now.CompareTo(FeatureEnabledTime) > 0)
|
||||||
|
eventTime = FeatureEnabledTime.AddDays(1);
|
||||||
|
else
|
||||||
|
eventTime = FeatureEnabledTime;
|
||||||
|
|
||||||
|
Debug.Console(1, this, "eventTime (before recurrence check): {0}", eventTime);
|
||||||
|
|
||||||
|
// Check day of week against recurrence days and move date ahead as necessary to avoid throwing an exception by trying to set the event
|
||||||
|
// start date on a day of the week that doesn't match teh recurrence values
|
||||||
|
while(!SchedulerUtilities.CheckIfDayOfWeekMatchesRecurrenceDays(eventTime, eventRecurrennce))
|
||||||
|
{
|
||||||
|
eventTime = eventTime.AddDays(1);
|
||||||
|
Debug.Console(1, this, "eventTime does not fall on a recurrence weekday. eventTime: {0}", eventTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
schEvent.DateAndTime.SetAbsoluteEventTime(eventTime);
|
||||||
|
|
||||||
|
Debug.Console(1, this, "Event '{0}' Absolute time set to {1}", schEvent.Name, schEvent.DateAndTime.ToString());
|
||||||
|
|
||||||
|
CalculateAndSetAcknowledgeExpirationTimeout(schEvent, FeatureEnabledTime, FeatureDisabledTime);
|
||||||
|
|
||||||
|
schEvent.Recurrence.Weekly(eventRecurrennce);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (schEvent.Name == FeatureDisableEventName)
|
||||||
|
{
|
||||||
|
schEvent.Description = "Disables the RoomOnToDefaultSourceWhenOccupiedFeature";
|
||||||
|
|
||||||
|
// Check to make sure the date for this event is in the future
|
||||||
|
if (DateTime.Now.CompareTo(FeatureDisabledTime) > 0)
|
||||||
|
schEvent.DateAndTime.SetAbsoluteEventTime(FeatureDisabledTime.AddDays(1));
|
||||||
|
else
|
||||||
|
schEvent.DateAndTime.SetAbsoluteEventTime(FeatureDisabledTime);
|
||||||
|
|
||||||
|
Debug.Console(1, this, "Event '{0}' Absolute time set to {1}", schEvent.Name, schEvent.DateAndTime.ToString());
|
||||||
|
|
||||||
|
CalculateAndSetAcknowledgeExpirationTimeout(schEvent, FeatureDisabledTime, FeatureEnabledTime);
|
||||||
|
|
||||||
|
schEvent.Recurrence.Daily();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CalculateAndSetAcknowledgeExpirationTimeout(ScheduledEvent schEvent, DateTime time1, DateTime time2)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "time1.Hour = {0}", time1.Hour);
|
||||||
|
Debug.Console(1, this, "time2.Hour = {0}", time2.Hour);
|
||||||
|
Debug.Console(1, this, "time1.Minute = {0}", time1.Minute);
|
||||||
|
Debug.Console(1, this, "time2.Minute = {0}", time2.Minute);
|
||||||
|
|
||||||
|
// Calculate the Acknowledge Expiration timer to be the time between the enable and dispable events, less one minute
|
||||||
|
var ackHours = time2.Hour - time1.Hour;
|
||||||
|
if(ackHours < 0)
|
||||||
|
ackHours = ackHours + 24;
|
||||||
|
var ackMinutes = time2.Minute - time1.Minute;
|
||||||
|
|
||||||
|
Debug.Console(1, this, "ackHours = {0}, ackMinutes = {1}", ackHours, ackMinutes);
|
||||||
|
|
||||||
|
var ackTotalMinutes = ((ackHours * 60) + ackMinutes) - 1;
|
||||||
|
|
||||||
|
var ackExpHour = ackTotalMinutes / 60;
|
||||||
|
var ackExpMinutes = ackTotalMinutes % 60;
|
||||||
|
|
||||||
|
Debug.Console(1, this, "Acknowledge Expiration Timeout: {0} hours, {1} minutes", ackExpHour, ackExpMinutes);
|
||||||
|
|
||||||
|
schEvent.AcknowledgeExpirationTimeout.Hour = (ushort)(ackHours);
|
||||||
|
schEvent.AcknowledgeExpirationTimeout.Minute = (ushort)(ackExpMinutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks existing event to see if it matches the execution time
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="existingEvent"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool CheckExistingEventTimeForMatch(ScheduledEvent existingEvent, DateTime newTime)
|
||||||
|
{
|
||||||
|
bool isMatch = true;
|
||||||
|
|
||||||
|
// Check to see if hour and minute match
|
||||||
|
if (existingEvent.DateAndTime.Hour != newTime.Hour || existingEvent.DateAndTime.Minute != newTime.Minute)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
|
||||||
|
return isMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks existing event to see if it matches the recurrence days
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="existingEvent"></param>
|
||||||
|
/// <param name="eWeekdays"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool CheckExistingEventRecurrenceForMatch(ScheduledEvent existingEvent, ScheduledEventCommon.eWeekDays eWeekdays)
|
||||||
|
{
|
||||||
|
bool isMatch = true;
|
||||||
|
|
||||||
|
// Check to see if recurrence matches
|
||||||
|
if (eWeekdays != existingEvent.Recurrence.RecurrenceDays)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return isMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the Enable event to the local event group and sets its properties based on config
|
||||||
|
/// </summary>
|
||||||
|
void AddEnableEventToGroup()
|
||||||
|
{
|
||||||
|
if (!FeatureEventGroup.ScheduledEvents.ContainsKey(FeatureEnableEventName))
|
||||||
|
{
|
||||||
|
CreateEvent(FeatureEnableEvent, FeatureEnableEventName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Check if existing event has same time and recurrence as config values
|
||||||
|
|
||||||
|
FeatureEnableEvent = FeatureEventGroup.ScheduledEvents[FeatureEnableEventName];
|
||||||
|
Debug.Console(1, this, "Enable event already found in group");
|
||||||
|
|
||||||
|
// Check config times and days against DateAndTime of existing event. If different, delete existing event and create new event
|
||||||
|
if(!CheckExistingEventTimeForMatch(FeatureEnableEvent, FeatureEnabledTime) || !CheckExistingEventRecurrenceForMatch(FeatureEnableEvent, CalculateDaysOfWeekRecurrence()))
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Existing event does not match new config properties. Deleting exisiting event: '{0}'", FeatureEnableEvent.Name);
|
||||||
|
FeatureEventGroup.DeleteEvent(FeatureEnableEvent);
|
||||||
|
|
||||||
|
FeatureEnableEvent = null;
|
||||||
|
|
||||||
|
CreateEvent(FeatureEnableEvent, FeatureEnableEventName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the Enable event to the local event group and sets its properties based on config
|
||||||
|
/// </summary>
|
||||||
|
void AddDisableEventToGroup()
|
||||||
|
{
|
||||||
|
if (!FeatureEventGroup.ScheduledEvents.ContainsKey(FeatureDisableEventName))
|
||||||
|
{
|
||||||
|
CreateEvent(FeatureDisableEvent, FeatureDisableEventName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FeatureDisableEvent = FeatureEventGroup.ScheduledEvents[FeatureDisableEventName];
|
||||||
|
Debug.Console(1, this, "Disable event already found in group");
|
||||||
|
|
||||||
|
// Check config times against DateAndTime of existing event. If different, delete existing event and create new event
|
||||||
|
if(!CheckExistingEventTimeForMatch(FeatureDisableEvent, FeatureDisabledTime))
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Existing event does not match new config properties. Deleting exisiting event: '{0}'", FeatureDisableEvent.Name);
|
||||||
|
|
||||||
|
FeatureEventGroup.DeleteEvent(FeatureDisableEvent);
|
||||||
|
|
||||||
|
FeatureDisableEvent = null;
|
||||||
|
|
||||||
|
CreateEvent(FeatureDisableEvent, FeatureDisableEventName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the correct bitfield enum value for the event recurrence based on the config values
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
ScheduledEventCommon.eWeekDays CalculateDaysOfWeekRecurrence()
|
||||||
|
{
|
||||||
|
ScheduledEventCommon.eWeekDays value = new ScheduledEventCommon.eWeekDays();
|
||||||
|
|
||||||
|
if (PropertiesConfig.EnableSunday)
|
||||||
|
value = value | ScheduledEventCommon.eWeekDays.Sunday;
|
||||||
|
if (PropertiesConfig.EnableMonday)
|
||||||
|
value = value | ScheduledEventCommon.eWeekDays.Monday;
|
||||||
|
if (PropertiesConfig.EnableTuesday)
|
||||||
|
value = value | ScheduledEventCommon.eWeekDays.Tuesday;
|
||||||
|
if (PropertiesConfig.EnableWednesday)
|
||||||
|
value = value | ScheduledEventCommon.eWeekDays.Wednesday;
|
||||||
|
if (PropertiesConfig.EnableThursday)
|
||||||
|
value = value | ScheduledEventCommon.eWeekDays.Thursday;
|
||||||
|
if (PropertiesConfig.EnableFriday)
|
||||||
|
value = value | ScheduledEventCommon.eWeekDays.Friday;
|
||||||
|
if (PropertiesConfig.EnableSaturday)
|
||||||
|
value = value | ScheduledEventCommon.eWeekDays.Saturday;
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback for event that enables feature. Enables feature if config property is true
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="SchEvent"></param>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
void FeatureEnableEvent_UserCallBack(ScheduledEvent SchEvent, ScheduledEventCommon.eCallbackReason type)
|
||||||
|
{
|
||||||
|
if (type == ScheduledEventCommon.eCallbackReason.NormalExpiration)
|
||||||
|
{
|
||||||
|
if(PropertiesConfig.EnableRoomOnWhenOccupied)
|
||||||
|
FeatureEnabled = true;
|
||||||
|
|
||||||
|
Debug.Console(1, this, "RoomOnToDefaultSourceWhenOccupied Feature Enabled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback for event that enables feature. Disables feature
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="SchEvent"></param>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
void FeatureDisableEvent_UserCallBack(ScheduledEvent SchEvent, ScheduledEventCommon.eCallbackReason type)
|
||||||
|
{
|
||||||
|
if (type == ScheduledEventCommon.eCallbackReason.NormalExpiration)
|
||||||
|
{
|
||||||
|
FeatureEnabled = false;
|
||||||
|
|
||||||
|
Debug.Console(1, this, "RoomOnToDefaultSourceWhenOccupied Feature Disabled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RoomOnToDefaultSourceWhenOccupiedConfig
|
||||||
|
{
|
||||||
|
[JsonProperty("roomKey")]
|
||||||
|
public string RoomKey { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("enableRoomOnWhenOccupied")]
|
||||||
|
public bool EnableRoomOnWhenOccupied { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("occupancyStartTime")]
|
||||||
|
public string OccupancyStartTime { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("occupancyEndTime")]
|
||||||
|
public string OccupancyEndTime { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("enableSunday")]
|
||||||
|
public bool EnableSunday { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("enableMonday")]
|
||||||
|
public bool EnableMonday { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("enableTuesday")]
|
||||||
|
public bool EnableTuesday { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("enableWednesday")]
|
||||||
|
public bool EnableWednesday { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("enableThursday")]
|
||||||
|
public bool EnableThursday { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("enableFriday")]
|
||||||
|
public bool EnableFriday { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("enableSaturday")]
|
||||||
|
public bool EnableSaturday { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,5 +20,7 @@ namespace PepperDash.Essentials.Room.Config
|
||||||
public string DefaultSourceItem { get; set; }
|
public string DefaultSourceItem { get; set; }
|
||||||
[JsonProperty("videoCodecKey")]
|
[JsonProperty("videoCodecKey")]
|
||||||
public string VideoCodecKey { get; set; }
|
public string VideoCodecKey { get; set; }
|
||||||
|
[JsonProperty("audioCodecKey")]
|
||||||
|
public string AudioCodecKey { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13,80 +13,30 @@ using PepperDash.Essentials.Core.Config;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Room.Config
|
namespace PepperDash.Essentials.Room.Config
|
||||||
{
|
{
|
||||||
public class EssentialsRoomConfig : DeviceConfig
|
public class EssentialsRoomConfigHelper
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a room object from this config data
|
/// Returns a room object from this config data
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Device GetRoomObject()
|
public static Device GetRoomObject(DeviceConfig roomConfig)
|
||||||
{
|
{
|
||||||
var typeName = Type.ToLower();
|
var typeName = roomConfig.Type.ToLower();
|
||||||
if (typeName == "huddle")
|
if (typeName == "huddle")
|
||||||
{
|
{
|
||||||
var props = JsonConvert.DeserializeObject<EssentialsHuddleRoomPropertiesConfig>
|
var huddle = new EssentialsHuddleSpaceRoom(roomConfig);
|
||||||
(this.Properties.ToString());
|
|
||||||
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;
|
|
||||||
huddle.DefaultVolume = (ushort)(props.Volumes.Master.Level * 65535 / 100);
|
|
||||||
return huddle;
|
return huddle;
|
||||||
}
|
}
|
||||||
else if (typeName == "presentation")
|
|
||||||
{
|
|
||||||
var props = JsonConvert.DeserializeObject<EssentialsPresentationRoomPropertiesConfig>
|
|
||||||
(this.Properties.ToString());
|
|
||||||
var displaysDict = new Dictionary<uint, IRoutingSinkNoSwitching>();
|
|
||||||
uint i = 1;
|
|
||||||
foreach (var dispKey in props.DisplayKeys) // read in the ordered displays list
|
|
||||||
{
|
|
||||||
var disp = DeviceManager.GetDeviceForKey(dispKey) as IRoutingSinkWithSwitching;
|
|
||||||
displaysDict.Add(i++, disp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the master volume control
|
|
||||||
IBasicVolumeWithFeedback masterVolumeControlDev = props.Volumes.Master.GetDevice();
|
|
||||||
|
|
||||||
|
|
||||||
var presRoom = new EssentialsPresentationRoom(Key, Name, displaysDict, masterVolumeControlDev, props);
|
|
||||||
return presRoom;
|
|
||||||
}
|
|
||||||
else if (typeName == "huddlevtc1")
|
else if (typeName == "huddlevtc1")
|
||||||
{
|
{
|
||||||
var props = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>
|
var rm = new EssentialsHuddleVtc1Room(roomConfig);
|
||||||
(this.Properties.ToString());
|
|
||||||
var disp = DeviceManager.GetDeviceForKey(props.DefaultDisplayKey) as IRoutingSinkWithSwitching;
|
|
||||||
|
|
||||||
var codec = DeviceManager.GetDeviceForKey(props.VideoCodecKey) as
|
|
||||||
PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;
|
|
||||||
|
|
||||||
var rm = new EssentialsHuddleVtc1Room(Key, Name, disp, codec, codec, props);
|
|
||||||
// Add Occupancy object from config
|
|
||||||
|
|
||||||
if (props.Occupancy != null)
|
|
||||||
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;
|
return rm;
|
||||||
}
|
}
|
||||||
else if (typeName == "ddvc01Bridge")
|
else if (typeName == "ddvc01Bridge")
|
||||||
{
|
{
|
||||||
return new Device(Key, Name); // placeholder device that does nothing.
|
return new Device(roomConfig.Key, roomConfig.Name); // placeholder device that does nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -96,7 +46,7 @@ namespace PepperDash.Essentials.Room.Config
|
||||||
/// Gets and operating, standalone emergegncy object that can be plugged into a room.
|
/// Gets and operating, standalone emergegncy object that can be plugged into a room.
|
||||||
/// Returns null if there is no emergency defined
|
/// Returns null if there is no emergency defined
|
||||||
/// </summary>
|
/// </summary>
|
||||||
EssentialsRoomEmergencyBase GetEmergency(EssentialsRoomPropertiesConfig props, EssentialsRoomBase room)
|
public static EssentialsRoomEmergencyBase GetEmergency(EssentialsRoomPropertiesConfig props, EssentialsRoomBase room)
|
||||||
{
|
{
|
||||||
// This emergency
|
// This emergency
|
||||||
var emergency = props.Emergency;
|
var emergency = props.Emergency;
|
||||||
|
|
@ -115,7 +65,7 @@ namespace PepperDash.Essentials.Room.Config
|
||||||
/// <param name="props"></param>
|
/// <param name="props"></param>
|
||||||
/// <param name="room"></param>
|
/// <param name="room"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
PepperDash.Essentials.Devices.Common.Microphones.MicrophonePrivacyController GetMicrophonePrivacy(
|
public static PepperDash.Essentials.Devices.Common.Microphones.MicrophonePrivacyController GetMicrophonePrivacy(
|
||||||
EssentialsRoomPropertiesConfig props, EssentialsHuddleVtc1Room room)
|
EssentialsRoomPropertiesConfig props, EssentialsHuddleVtc1Room room)
|
||||||
{
|
{
|
||||||
var microphonePrivacy = props.MicrophonePrivacy;
|
var microphonePrivacy = props.MicrophonePrivacy;
|
||||||
|
|
@ -322,8 +272,8 @@ namespace PepperDash.Essentials.Room.Config
|
||||||
[JsonProperty("deviceKey")]
|
[JsonProperty("deviceKey")]
|
||||||
public string DeviceKey { get; set; }
|
public string DeviceKey { get; set; }
|
||||||
|
|
||||||
[JsonProperty("timoutMinutes")]
|
[JsonProperty("timeoutMinutes")]
|
||||||
public int TimoutMinutes { get; set; }
|
public int TimeoutMinutes { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class EssentialsRoomTechConfig
|
public class EssentialsRoomTechConfig
|
||||||
|
|
|
||||||
|
|
@ -1,694 +0,0 @@
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -4,13 +4,16 @@ using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
|
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
using PepperDash.Essentials.Room.Config;
|
using PepperDash.Essentials.Room.Config;
|
||||||
|
|
||||||
namespace PepperDash.Essentials
|
namespace PepperDash.Essentials
|
||||||
{
|
{
|
||||||
public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange
|
public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute
|
||||||
{
|
{
|
||||||
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
|
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
|
||||||
public event SourceInfoChangeHandler CurrentSingleSourceChange;
|
public event SourceInfoChangeHandler CurrentSingleSourceChange;
|
||||||
|
|
@ -65,7 +68,7 @@ namespace PepperDash.Essentials
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public EssentialsRoomPropertiesConfig Config { get; private set; }
|
public EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; private set; }
|
||||||
|
|
||||||
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
|
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
|
||||||
public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; }
|
public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; }
|
||||||
|
|
@ -146,22 +149,32 @@ namespace PepperDash.Essentials
|
||||||
|
|
||||||
public string CurrentSourceInfoKey { get; private set; }
|
public string CurrentSourceInfoKey { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
public EssentialsHuddleSpaceRoom(DeviceConfig config)
|
||||||
///
|
: base(config)
|
||||||
/// </summary>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="name"></param>
|
|
||||||
public EssentialsHuddleSpaceRoom(string key, string name, IRoutingSinkWithSwitching defaultDisplay,
|
|
||||||
IRoutingSinkNoSwitching defaultAudio, EssentialsRoomPropertiesConfig config)
|
|
||||||
: base(key, name)
|
|
||||||
{
|
{
|
||||||
Config = config;
|
try
|
||||||
DefaultDisplay = defaultDisplay;
|
{
|
||||||
DefaultAudioDevice = defaultAudio;
|
PropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleRoomPropertiesConfig>
|
||||||
if (defaultAudio is IBasicVolumeControls)
|
(config.Properties.ToString());
|
||||||
DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
|
DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching;
|
||||||
else if (defaultAudio is IHasVolumeDevice)
|
|
||||||
DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
|
|
||||||
|
DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IRoutingSinkWithSwitching;
|
||||||
|
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Error building room: \n{0}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Initialize()
|
||||||
|
{
|
||||||
|
if (DefaultAudioDevice is IBasicVolumeControls)
|
||||||
|
DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls;
|
||||||
|
else if (DefaultAudioDevice is IHasVolumeDevice)
|
||||||
|
DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice;
|
||||||
CurrentVolumeControls = DefaultVolumeControls;
|
CurrentVolumeControls = DefaultVolumeControls;
|
||||||
|
|
||||||
var disp = DefaultDisplay as DisplayBase;
|
var disp = DefaultDisplay as DisplayBase;
|
||||||
|
|
@ -194,6 +207,15 @@ namespace PepperDash.Essentials
|
||||||
EnablePowerOnToLastSource = true;
|
EnablePowerOnToLastSource = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void CustomSetConfig(DeviceConfig config)
|
||||||
|
{
|
||||||
|
var newPropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleRoomPropertiesConfig>(config.Properties.ToString());
|
||||||
|
|
||||||
|
if (newPropertiesConfig != null)
|
||||||
|
PropertiesConfig = newPropertiesConfig;
|
||||||
|
|
||||||
|
ConfigWriter.UpdateRoomConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
|
@ -202,7 +224,7 @@ namespace PepperDash.Essentials
|
||||||
{
|
{
|
||||||
SetDefaultLevels();
|
SetDefaultLevels();
|
||||||
|
|
||||||
RunDefaultRoute();
|
RunDefaultPresentRoute();
|
||||||
|
|
||||||
CrestronEnvironment.Sleep(1000);
|
CrestronEnvironment.Sleep(1000);
|
||||||
|
|
||||||
|
|
@ -212,10 +234,31 @@ namespace PepperDash.Essentials
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Routes the default source item, if any
|
/// Routes the default source item, if any
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void RunDefaultRoute()
|
public override bool RunDefaultPresentRoute()
|
||||||
{
|
{
|
||||||
//if (DefaultSourceItem != null && !OnFeedback.BoolValue)
|
if (DefaultSourceItem == null)
|
||||||
|
{
|
||||||
|
Debug.Console(0, this, "Unable to run default present route, DefaultSourceItem is null.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
RunRouteAction(DefaultSourceItem);
|
RunRouteAction(DefaultSourceItem);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CustomActivate()
|
||||||
|
{
|
||||||
|
// Add Occupancy object from config
|
||||||
|
if (PropertiesConfig.Occupancy != null)
|
||||||
|
this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
|
||||||
|
PepperDash.Essentials.Devices.Common.Occupancy.IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes);
|
||||||
|
|
||||||
|
this.LogoUrl = PropertiesConfig.Logo.GetUrl();
|
||||||
|
this.SourceListKey = PropertiesConfig.SourceListKey;
|
||||||
|
this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
|
||||||
|
this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);
|
||||||
|
|
||||||
|
return base.CustomActivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -384,7 +427,7 @@ namespace PepperDash.Essentials
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Will power the room on with the last-used source
|
/// Will power the room on with the last-used source
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void PowerOnToDefaultOrLastSource()
|
public override void PowerOnToDefaultOrLastSource()
|
||||||
{
|
{
|
||||||
if (!EnablePowerOnToLastSource || LastSourceKey == null)
|
if (!EnablePowerOnToLastSource || LastSourceKey == null)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,19 @@ using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
|
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
using PepperDash.Essentials.Room.Config;
|
using PepperDash.Essentials.Room.Config;
|
||||||
using PepperDash.Essentials.Devices.Common.Codec;
|
using PepperDash.Essentials.Devices.Common.Codec;
|
||||||
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||||
|
|
||||||
namespace PepperDash.Essentials
|
namespace PepperDash.Essentials
|
||||||
{
|
{
|
||||||
public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IHasCurrentSourceInfoChange, IPrivacy, IHasCurrentVolumeControls
|
public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IHasCurrentSourceInfoChange,
|
||||||
|
IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec
|
||||||
{
|
{
|
||||||
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
|
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
|
||||||
public event SourceInfoChangeHandler CurrentSingleSourceChange;
|
public event SourceInfoChangeHandler CurrentSingleSourceChange;
|
||||||
|
|
@ -96,7 +100,7 @@ namespace PepperDash.Essentials
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public EssentialsHuddleVtc1PropertiesConfig Config { get; private set; }
|
public EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; private set; }
|
||||||
|
|
||||||
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
|
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
|
||||||
public IBasicVolumeControls DefaultAudioDevice { get; private set; }
|
public IBasicVolumeControls DefaultAudioDevice { get; private set; }
|
||||||
|
|
@ -193,26 +197,37 @@ namespace PepperDash.Essentials
|
||||||
|
|
||||||
CCriticalSection SourceSelectLock = new CCriticalSection();
|
CCriticalSection SourceSelectLock = new CCriticalSection();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="name"></param>
|
|
||||||
public EssentialsHuddleVtc1Room(string key, string name, IRoutingSinkWithSwitching defaultDisplay,
|
|
||||||
IBasicVolumeControls defaultAudio, VideoCodecBase codec, EssentialsHuddleVtc1PropertiesConfig config)
|
|
||||||
: base(key, name)
|
|
||||||
{
|
|
||||||
if (codec == null)
|
|
||||||
throw new ArgumentNullException("codec cannot be null");
|
|
||||||
Config = config;
|
|
||||||
DefaultDisplay = defaultDisplay;
|
|
||||||
VideoCodec = codec;
|
|
||||||
DefaultAudioDevice = defaultAudio;
|
|
||||||
|
|
||||||
if (defaultAudio is IBasicVolumeControls)
|
public EssentialsHuddleVtc1Room(DeviceConfig config)
|
||||||
DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
|
: base(config)
|
||||||
else if (defaultAudio is IHasVolumeDevice)
|
{
|
||||||
DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
|
try
|
||||||
|
{
|
||||||
|
PropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>
|
||||||
|
(config.Properties.ToString());
|
||||||
|
DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching;
|
||||||
|
|
||||||
|
VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as
|
||||||
|
PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;
|
||||||
|
if (VideoCodec == null)
|
||||||
|
throw new ArgumentNullException("codec cannot be null");
|
||||||
|
|
||||||
|
DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IBasicVolumeControls;
|
||||||
|
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, "Error building room: \n{0}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Initialize()
|
||||||
|
{
|
||||||
|
if (DefaultAudioDevice is IBasicVolumeControls)
|
||||||
|
DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls;
|
||||||
|
else if (DefaultAudioDevice is IHasVolumeDevice)
|
||||||
|
DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice;
|
||||||
CurrentVolumeControls = DefaultVolumeControls;
|
CurrentVolumeControls = DefaultVolumeControls;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -262,6 +277,37 @@ namespace PepperDash.Essentials
|
||||||
EnablePowerOnToLastSource = true;
|
EnablePowerOnToLastSource = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void CustomSetConfig(DeviceConfig config)
|
||||||
|
{
|
||||||
|
var newPropertiesConfig = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>(config.Properties.ToString());
|
||||||
|
|
||||||
|
if (newPropertiesConfig != null)
|
||||||
|
PropertiesConfig = newPropertiesConfig;
|
||||||
|
|
||||||
|
ConfigWriter.UpdateRoomConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CustomActivate()
|
||||||
|
{
|
||||||
|
// Add Occupancy object from config
|
||||||
|
if (PropertiesConfig.Occupancy != null)
|
||||||
|
this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as
|
||||||
|
PepperDash.Essentials.Devices.Common.Occupancy.IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes);
|
||||||
|
|
||||||
|
this.LogoUrl = PropertiesConfig.Logo.GetUrl();
|
||||||
|
this.SourceListKey = PropertiesConfig.SourceListKey;
|
||||||
|
this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem;
|
||||||
|
this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100);
|
||||||
|
|
||||||
|
// Get Microphone Privacy object, if any
|
||||||
|
this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this);
|
||||||
|
|
||||||
|
// Get emergency object, if any
|
||||||
|
this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this);
|
||||||
|
|
||||||
|
return base.CustomActivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
|
@ -282,10 +328,11 @@ namespace PepperDash.Essentials
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Routes the default source item, if any. Returns true when default route exists
|
/// Routes the default source item, if any. Returns true when default route exists
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool RunDefaultPresentRoute()
|
public override bool RunDefaultPresentRoute()
|
||||||
{
|
{
|
||||||
//if (DefaultSourceItem != null)
|
if (DefaultSourceItem != null)
|
||||||
RunRouteAction(DefaultSourceItem);
|
RunRouteAction(DefaultSourceItem);
|
||||||
|
|
||||||
return DefaultSourceItem != null;
|
return DefaultSourceItem != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -531,7 +578,7 @@ namespace PepperDash.Essentials
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Will power the room on with the last-used source
|
/// Will power the room on with the last-used source
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void PowerOnToDefaultOrLastSource()
|
public override void PowerOnToDefaultOrLastSource()
|
||||||
{
|
{
|
||||||
if (!EnablePowerOnToLastSource || LastSourceKey == null)
|
if (!EnablePowerOnToLastSource || LastSourceKey == null)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -1,437 +1,437 @@
|
||||||
using System;
|
//using System;
|
||||||
using System.Collections.Generic;
|
//using System.Collections.Generic;
|
||||||
using System.Linq;
|
//using System.Linq;
|
||||||
using System.Text;
|
//using System.Text;
|
||||||
using Crestron.SimplSharp;
|
//using Crestron.SimplSharp;
|
||||||
|
|
||||||
using PepperDash.Core;
|
//using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
//using PepperDash.Essentials.Core;
|
||||||
using PepperDash.Essentials.Room.Config;
|
//using PepperDash.Essentials.Room.Config;
|
||||||
|
|
||||||
namespace PepperDash.Essentials
|
//namespace PepperDash.Essentials
|
||||||
{
|
//{
|
||||||
public class EssentialsPresentationRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange
|
// public class EssentialsPresentationRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange
|
||||||
{
|
// {
|
||||||
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
|
// public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
|
||||||
public event SourceInfoChangeHandler CurrentSingleSourceChange;
|
// public event SourceInfoChangeHandler CurrentSingleSourceChange;
|
||||||
public event SourceInfoChangeHandler CurrentDisplay1SourceChange;
|
// public event SourceInfoChangeHandler CurrentDisplay1SourceChange;
|
||||||
public event SourceInfoChangeHandler CurrentDisplay2SourceChange;
|
// public event SourceInfoChangeHandler CurrentDisplay2SourceChange;
|
||||||
|
|
||||||
protected override Func<bool> OnFeedbackFunc { get {
|
// protected override Func<bool> OnFeedbackFunc { get {
|
||||||
return () => (CurrentSingleSourceInfo != null
|
// return () => (CurrentSingleSourceInfo != null
|
||||||
&& CurrentSingleSourceInfo.Type != eSourceListItemType.Off)
|
// && CurrentSingleSourceInfo.Type != eSourceListItemType.Off)
|
||||||
|| (Display1SourceInfo != null
|
// || (Display1SourceInfo != null
|
||||||
&& Display1SourceInfo.Type != eSourceListItemType.Off)
|
// && Display1SourceInfo.Type != eSourceListItemType.Off)
|
||||||
|| (Display2SourceInfo != null
|
// || (Display2SourceInfo != null
|
||||||
&& Display2SourceInfo.Type != eSourceListItemType.Off); } }
|
// && Display2SourceInfo.Type != eSourceListItemType.Off); } }
|
||||||
|
|
||||||
protected override Func<bool> IsWarmingFeedbackFunc { get { return () =>false;; } }
|
// protected override Func<bool> IsWarmingFeedbackFunc { get { return () =>false;; } }
|
||||||
protected override Func<bool> IsCoolingFeedbackFunc { get { return () => false; } }
|
// protected override Func<bool> IsCoolingFeedbackFunc { get { return () => false; } }
|
||||||
|
|
||||||
public EssentialsPresentationRoomPropertiesConfig Config { get; private set; }
|
// public EssentialsPresentationRoomPropertiesConfig Config { get; private set; }
|
||||||
|
|
||||||
public Dictionary<uint, IRoutingSinkNoSwitching> Displays { get; private set; }
|
// public Dictionary<uint, IRoutingSinkNoSwitching> Displays { get; private set; }
|
||||||
|
|
||||||
public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; }
|
// public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; }
|
||||||
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
|
// public IBasicVolumeControls DefaultVolumeControls { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
/// The config name of the source list
|
// /// The config name of the source list
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
public string SourceListKey { get; set; }
|
// public string SourceListKey { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
/// If room is off, enables power on to last source. Default true
|
// /// If room is off, enables power on to last source. Default true
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
public bool EnablePowerOnToLastSource { get; set; }
|
// public bool EnablePowerOnToLastSource { get; set; }
|
||||||
string LastSourceKey;
|
// string LastSourceKey;
|
||||||
|
|
||||||
public enum eVideoRoutingMode
|
// public enum eVideoRoutingMode
|
||||||
{
|
// {
|
||||||
SelectSourceSelectDisplay, SourceToAllDisplays
|
// SelectSourceSelectDisplay, SourceToAllDisplays
|
||||||
}
|
// }
|
||||||
|
|
||||||
public eVideoRoutingMode VideoRoutingMode { get; set; }
|
// public eVideoRoutingMode VideoRoutingMode { get; set; }
|
||||||
|
|
||||||
public enum eAudioRoutingMode
|
// public enum eAudioRoutingMode
|
||||||
{
|
// {
|
||||||
AudioFollowsLastVideo, SelectAudioFromDisplay
|
// AudioFollowsLastVideo, SelectAudioFromDisplay
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
///
|
// ///
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
public IBasicVolumeControls CurrentVolumeControls
|
// public IBasicVolumeControls CurrentVolumeControls
|
||||||
{
|
// {
|
||||||
get { return _CurrentAudioDevice; }
|
// get { return _CurrentAudioDevice; }
|
||||||
set
|
// set
|
||||||
{
|
// {
|
||||||
if (value == _CurrentAudioDevice) return;
|
// if (value == _CurrentAudioDevice) return;
|
||||||
|
|
||||||
var oldDev = _CurrentAudioDevice;
|
// var oldDev = _CurrentAudioDevice;
|
||||||
// derigister this room from the device, if it can
|
// // derigister this room from the device, if it can
|
||||||
if (oldDev is IInUseTracking)
|
// if (oldDev is IInUseTracking)
|
||||||
(oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
|
// (oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
|
||||||
var handler = CurrentVolumeDeviceChange;
|
// var handler = CurrentVolumeDeviceChange;
|
||||||
if (handler != null)
|
// if (handler != null)
|
||||||
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
|
// CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
|
||||||
_CurrentAudioDevice = value;
|
// _CurrentAudioDevice = value;
|
||||||
if (handler != null)
|
// if (handler != null)
|
||||||
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
|
// CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
|
||||||
// register this room with new device, if it can
|
// // register this room with new device, if it can
|
||||||
if (_CurrentAudioDevice is IInUseTracking)
|
// if (_CurrentAudioDevice is IInUseTracking)
|
||||||
(_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
|
// (_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
IBasicVolumeControls _CurrentAudioDevice;
|
// IBasicVolumeControls _CurrentAudioDevice;
|
||||||
|
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
/// The SourceListItem last run - containing names and icons. The complex setter is
|
// /// The SourceListItem last run - containing names and icons. The complex setter is
|
||||||
/// to add/remove this room to the source's InUseTracking, if it is capable
|
// /// to add/remove this room to the source's InUseTracking, if it is capable
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
public SourceListItem CurrentSingleSourceInfo
|
// public SourceListItem CurrentSingleSourceInfo
|
||||||
{
|
// {
|
||||||
get { return _CurrentSingleSourceInfo; }
|
// get { return _CurrentSingleSourceInfo; }
|
||||||
private set
|
// private set
|
||||||
{
|
// {
|
||||||
if (value == _CurrentSingleSourceInfo) return;
|
// if (value == _CurrentSingleSourceInfo) return;
|
||||||
|
|
||||||
var handler = CurrentSingleSourceChange;
|
// var handler = CurrentSingleSourceChange;
|
||||||
// remove from in-use tracker, if so equipped
|
// // remove from in-use tracker, if so equipped
|
||||||
if(_CurrentSingleSourceInfo != null && _CurrentSingleSourceInfo.SourceDevice is IInUseTracking)
|
// if(_CurrentSingleSourceInfo != null && _CurrentSingleSourceInfo.SourceDevice is IInUseTracking)
|
||||||
(_CurrentSingleSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
|
// (_CurrentSingleSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
|
||||||
|
|
||||||
if (handler != null)
|
// if (handler != null)
|
||||||
handler(this, _CurrentSingleSourceInfo, ChangeType.WillChange);
|
// handler(this, _CurrentSingleSourceInfo, ChangeType.WillChange);
|
||||||
|
|
||||||
_CurrentSingleSourceInfo = value;
|
// _CurrentSingleSourceInfo = value;
|
||||||
|
|
||||||
// add to in-use tracking
|
// // add to in-use tracking
|
||||||
if (_CurrentSingleSourceInfo != null && _CurrentSingleSourceInfo.SourceDevice is IInUseTracking)
|
// if (_CurrentSingleSourceInfo != null && _CurrentSingleSourceInfo.SourceDevice is IInUseTracking)
|
||||||
(_CurrentSingleSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
|
// (_CurrentSingleSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
|
||||||
if (handler != null)
|
// if (handler != null)
|
||||||
handler(this, _CurrentSingleSourceInfo, ChangeType.DidChange);
|
// handler(this, _CurrentSingleSourceInfo, ChangeType.DidChange);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
SourceListItem _CurrentSingleSourceInfo;
|
// SourceListItem _CurrentSingleSourceInfo;
|
||||||
|
|
||||||
public SourceListItem Display1SourceInfo
|
// public SourceListItem Display1SourceInfo
|
||||||
{
|
// {
|
||||||
get { return _Display1SourceInfo; }
|
// get { return _Display1SourceInfo; }
|
||||||
set
|
// set
|
||||||
{
|
// {
|
||||||
if (value == _Display1SourceInfo) return;
|
// if (value == _Display1SourceInfo) return;
|
||||||
|
|
||||||
var handler = CurrentDisplay1SourceChange;
|
// var handler = CurrentDisplay1SourceChange;
|
||||||
if (handler != null)
|
// if (handler != null)
|
||||||
handler(this, _Display1SourceInfo, ChangeType.WillChange);
|
// handler(this, _Display1SourceInfo, ChangeType.WillChange);
|
||||||
|
|
||||||
_Display1SourceInfo = value;
|
// _Display1SourceInfo = value;
|
||||||
|
|
||||||
if (handler != null)
|
// if (handler != null)
|
||||||
handler(this, _Display1SourceInfo, ChangeType.DidChange);
|
// handler(this, _Display1SourceInfo, ChangeType.DidChange);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
SourceListItem _Display1SourceInfo;
|
// SourceListItem _Display1SourceInfo;
|
||||||
|
|
||||||
public SourceListItem Display2SourceInfo
|
// public SourceListItem Display2SourceInfo
|
||||||
{
|
// {
|
||||||
get { return _Display2SourceInfo; }
|
// get { return _Display2SourceInfo; }
|
||||||
set
|
// set
|
||||||
{
|
// {
|
||||||
if (value == _Display2SourceInfo) return;
|
// if (value == _Display2SourceInfo) return;
|
||||||
|
|
||||||
var handler = CurrentDisplay2SourceChange;
|
// var handler = CurrentDisplay2SourceChange;
|
||||||
if (handler != null)
|
// if (handler != null)
|
||||||
handler(this, _Display2SourceInfo, ChangeType.WillChange);
|
// handler(this, _Display2SourceInfo, ChangeType.WillChange);
|
||||||
|
|
||||||
_Display2SourceInfo = value;
|
// _Display2SourceInfo = value;
|
||||||
|
|
||||||
if (handler != null)
|
// if (handler != null)
|
||||||
handler(this, _Display2SourceInfo, ChangeType.DidChange);
|
// handler(this, _Display2SourceInfo, ChangeType.DidChange);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
SourceListItem _Display2SourceInfo;
|
// SourceListItem _Display2SourceInfo;
|
||||||
|
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
/// If an audio dialer is available for this room
|
// /// If an audio dialer is available for this room
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
public bool HasAudioDialer { get { return false; } }
|
// public bool HasAudioDialer { get { return false; } }
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
///
|
// ///
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
/// <param name="key"></param>
|
// /// <param name="key"></param>
|
||||||
/// <param name="name"></param>
|
// /// <param name="name"></param>
|
||||||
public EssentialsPresentationRoom(string key, string name,
|
// public EssentialsPresentationRoom(string key, string name,
|
||||||
Dictionary<uint, IRoutingSinkNoSwitching> displays,
|
// Dictionary<uint, IRoutingSinkNoSwitching> displays,
|
||||||
IBasicVolumeWithFeedback defaultVolume, EssentialsPresentationRoomPropertiesConfig config)
|
// IBasicVolumeWithFeedback defaultVolume, EssentialsPresentationRoomPropertiesConfig config)
|
||||||
: base(key, name)
|
// : base(key, name)
|
||||||
{
|
// {
|
||||||
Config = config;
|
// Config = config;
|
||||||
Displays = displays;
|
// Displays = displays;
|
||||||
|
|
||||||
DefaultVolumeControls = defaultVolume;
|
// DefaultVolumeControls = defaultVolume;
|
||||||
CurrentVolumeControls = defaultVolume;
|
// CurrentVolumeControls = defaultVolume;
|
||||||
|
|
||||||
//DefaultAudioDevice = defaultAudio;
|
// //DefaultAudioDevice = defaultAudio;
|
||||||
//if (defaultAudio is IBasicVolumeControls)
|
// //if (defaultAudio is IBasicVolumeControls)
|
||||||
// DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
|
// // DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
|
||||||
//else if (defaultAudio is IHasVolumeDevice)
|
// //else if (defaultAudio is IHasVolumeDevice)
|
||||||
// DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
|
// // DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
|
||||||
|
|
||||||
|
|
||||||
SourceListKey = "default";
|
// SourceListKey = "default";
|
||||||
EnablePowerOnToLastSource = true;
|
// EnablePowerOnToLastSource = true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
/// Run the same source to all destinations
|
// /// Run the same source to all destinations
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
/// <param name="sourceItem"></param>
|
// /// <param name="sourceItem"></param>
|
||||||
public void RouteSourceToAllDestinations(SourceListItem sourceItem)
|
// public void RouteSourceToAllDestinations(SourceListItem sourceItem)
|
||||||
{
|
// {
|
||||||
if (Config.Volumes.Master != null)
|
// if (Config.Volumes.Master != null)
|
||||||
{
|
// {
|
||||||
var audioDev = DeviceManager.GetDeviceForKey(Config.Volumes.Master.DeviceKey);
|
// var audioDev = DeviceManager.GetDeviceForKey(Config.Volumes.Master.DeviceKey);
|
||||||
if (audioDev is IBasicVolumeWithFeedback)
|
// if (audioDev is IBasicVolumeWithFeedback)
|
||||||
{
|
// {
|
||||||
|
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
foreach (var display in Displays.Values)
|
// foreach (var display in Displays.Values)
|
||||||
{
|
// {
|
||||||
if (sourceItem != null)
|
// if (sourceItem != null)
|
||||||
DoVideoRoute(sourceItem.SourceKey, display.Key);
|
// DoVideoRoute(sourceItem.SourceKey, display.Key);
|
||||||
else
|
// else
|
||||||
DoVideoRoute("$off", display.Key);
|
// DoVideoRoute("$off", display.Key);
|
||||||
}
|
// }
|
||||||
Display1SourceInfo = sourceItem;
|
// Display1SourceInfo = sourceItem;
|
||||||
Display2SourceInfo = sourceItem;
|
// Display2SourceInfo = sourceItem;
|
||||||
CurrentSingleSourceInfo = sourceItem;
|
// CurrentSingleSourceInfo = sourceItem;
|
||||||
OnFeedback.FireUpdate();
|
// OnFeedback.FireUpdate();
|
||||||
}
|
// }
|
||||||
|
|
||||||
public void SourceToDisplay1(SourceListItem sourceItem)
|
// public void SourceToDisplay1(SourceListItem sourceItem)
|
||||||
{
|
// {
|
||||||
DoVideoRoute(sourceItem.SourceKey, Displays[1].Key);
|
// DoVideoRoute(sourceItem.SourceKey, Displays[1].Key);
|
||||||
Display1SourceInfo = sourceItem;
|
// Display1SourceInfo = sourceItem;
|
||||||
OnFeedback.FireUpdate();
|
// OnFeedback.FireUpdate();
|
||||||
}
|
// }
|
||||||
|
|
||||||
public void SourceToDisplay2(SourceListItem sourceItem)
|
// public void SourceToDisplay2(SourceListItem sourceItem)
|
||||||
{
|
// {
|
||||||
DoVideoRoute(sourceItem.SourceKey, Displays[2].Key);
|
// DoVideoRoute(sourceItem.SourceKey, Displays[2].Key);
|
||||||
Display2SourceInfo = sourceItem;
|
// Display2SourceInfo = sourceItem;
|
||||||
OnFeedback.FireUpdate();
|
// OnFeedback.FireUpdate();
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
/// Basic source -> destination routing
|
// /// Basic source -> destination routing
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
void DoVideoRoute(string sourceKey, string destinationKey)
|
// void DoVideoRoute(string sourceKey, string destinationKey)
|
||||||
{
|
// {
|
||||||
new CTimer(o =>
|
// new CTimer(o =>
|
||||||
{
|
// {
|
||||||
var dest = DeviceManager.GetDeviceForKey(destinationKey) as IRoutingSinkNoSwitching;
|
// var dest = DeviceManager.GetDeviceForKey(destinationKey) as IRoutingSinkNoSwitching;
|
||||||
if (dest == null)
|
// if (dest == null)
|
||||||
{
|
// {
|
||||||
Debug.Console(1, this, "Cannot route. Destination '{0}' not found", destinationKey);
|
// Debug.Console(1, this, "Cannot route. Destination '{0}' not found", destinationKey);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
// off is special case
|
// // off is special case
|
||||||
if (sourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
|
// if (sourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
// {
|
||||||
dest.ReleaseRoute();
|
// dest.ReleaseRoute();
|
||||||
if (dest is IPower)
|
// if (dest is IPower)
|
||||||
(dest as IPower).PowerOff();
|
// (dest as IPower).PowerOff();
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
var source = DeviceManager.GetDeviceForKey(sourceKey) as IRoutingOutputs;
|
// var source = DeviceManager.GetDeviceForKey(sourceKey) as IRoutingOutputs;
|
||||||
if (source == null)
|
// if (source == null)
|
||||||
{
|
// {
|
||||||
Debug.Console(1, this, "Cannot route. Source '{0}' not found", sourceKey);
|
// Debug.Console(1, this, "Cannot route. Source '{0}' not found", sourceKey);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
dest.ReleaseAndMakeRoute(source, eRoutingSignalType.Video);
|
// dest.ReleaseAndMakeRoute(source, eRoutingSignalType.Video);
|
||||||
}, 0);
|
// }, 0);
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
///
|
// ///
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
protected override void EndShutdown()
|
// protected override void EndShutdown()
|
||||||
{
|
// {
|
||||||
RunRouteAction("roomoff");
|
// RunRouteAction("roomoff");
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
///
|
// ///
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
/// <param name="routeKey"></param>
|
// /// <param name="routeKey"></param>
|
||||||
public void RunRouteAction(string routeKey)
|
// public void RunRouteAction(string routeKey)
|
||||||
{
|
// {
|
||||||
RunRouteAction(routeKey, null);
|
// RunRouteAction(routeKey, null);
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
/// Gets a source from config list SourceListKey and dynamically build and executes the
|
// /// Gets a source from config list SourceListKey and dynamically build and executes the
|
||||||
/// route or commands
|
// /// route or commands
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
/// <param name="name"></param>
|
// /// <param name="name"></param>
|
||||||
public void RunRouteAction(string routeKey, Action successCallback)
|
// public void RunRouteAction(string routeKey, Action successCallback)
|
||||||
{
|
// {
|
||||||
// Run this on a separate thread
|
// // Run this on a separate thread
|
||||||
new CTimer(o =>
|
// new CTimer(o =>
|
||||||
{
|
// {
|
||||||
Debug.Console(1, this, "Run room action '{0}'", routeKey);
|
// Debug.Console(1, this, "Run room action '{0}'", routeKey);
|
||||||
var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
|
// var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
|
||||||
if(dict == null)
|
// if(dict == null)
|
||||||
{
|
// {
|
||||||
Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
|
// Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Try to get the list item by it's string key
|
// // Try to get the list item by it's string key
|
||||||
if (!dict.ContainsKey(routeKey))
|
// if (!dict.ContainsKey(routeKey))
|
||||||
{
|
// {
|
||||||
Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
|
// Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
|
||||||
routeKey, SourceListKey);
|
// routeKey, SourceListKey);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
var item = dict[routeKey];
|
// var item = dict[routeKey];
|
||||||
//Debug.Console(2, this, "Action {0} has {1} steps",
|
// //Debug.Console(2, this, "Action {0} has {1} steps",
|
||||||
// item.SourceKey, item.RouteList.Count);
|
// // item.SourceKey, item.RouteList.Count);
|
||||||
|
|
||||||
// Let's run it
|
// // Let's run it
|
||||||
if (routeKey.ToLower() != "roomoff")
|
// if (routeKey.ToLower() != "roomoff")
|
||||||
LastSourceKey = routeKey;
|
// LastSourceKey = routeKey;
|
||||||
|
|
||||||
foreach (var route in item.RouteList)
|
// foreach (var route in item.RouteList)
|
||||||
{
|
// {
|
||||||
// if there is a $defaultAll on route, run two separate
|
// // if there is a $defaultAll on route, run two separate
|
||||||
if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
|
// if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
// {
|
||||||
var tempAudio = new SourceRouteListItem
|
// var tempAudio = new SourceRouteListItem
|
||||||
{
|
// {
|
||||||
DestinationKey = "$defaultDisplay",
|
// DestinationKey = "$defaultDisplay",
|
||||||
SourceKey = route.SourceKey,
|
// SourceKey = route.SourceKey,
|
||||||
Type = eRoutingSignalType.Video
|
// Type = eRoutingSignalType.Video
|
||||||
};
|
// };
|
||||||
DoRoute(tempAudio);
|
// DoRoute(tempAudio);
|
||||||
|
|
||||||
var tempVideo = new SourceRouteListItem
|
// var tempVideo = new SourceRouteListItem
|
||||||
{
|
// {
|
||||||
DestinationKey = "$defaultAudio",
|
// DestinationKey = "$defaultAudio",
|
||||||
SourceKey = route.SourceKey,
|
// SourceKey = route.SourceKey,
|
||||||
Type = eRoutingSignalType.Audio
|
// Type = eRoutingSignalType.Audio
|
||||||
};
|
// };
|
||||||
DoRoute(tempVideo);
|
// DoRoute(tempVideo);
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
DoRoute(route);
|
// DoRoute(route);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Set volume control on room, using default if non provided
|
// // Set volume control on room, using default if non provided
|
||||||
IBasicVolumeControls volDev = null;
|
// IBasicVolumeControls volDev = null;
|
||||||
// Handle special cases for volume control
|
// // Handle special cases for volume control
|
||||||
if (string.IsNullOrEmpty(item.VolumeControlKey)
|
// if (string.IsNullOrEmpty(item.VolumeControlKey)
|
||||||
|| item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
|
// || item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
|
||||||
volDev = DefaultVolumeControls;
|
// volDev = DefaultVolumeControls;
|
||||||
//else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
// //else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
||||||
// volDev = DefaultDisplay as IBasicVolumeControls;
|
// // volDev = DefaultDisplay as IBasicVolumeControls;
|
||||||
// Or a specific device, probably rarely used.
|
// // Or a specific device, probably rarely used.
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
|
// var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
|
||||||
if (dev is IBasicVolumeControls)
|
// if (dev is IBasicVolumeControls)
|
||||||
volDev = dev as IBasicVolumeControls;
|
// volDev = dev as IBasicVolumeControls;
|
||||||
else if (dev is IHasVolumeDevice)
|
// else if (dev is IHasVolumeDevice)
|
||||||
volDev = (dev as IHasVolumeDevice).VolumeDevice;
|
// volDev = (dev as IHasVolumeDevice).VolumeDevice;
|
||||||
}
|
// }
|
||||||
CurrentVolumeControls = volDev;
|
// CurrentVolumeControls = volDev;
|
||||||
|
|
||||||
// store the name and UI info for routes
|
// // store the name and UI info for routes
|
||||||
if (item.SourceKey != null)
|
// if (item.SourceKey != null)
|
||||||
CurrentSingleSourceInfo = item;
|
// CurrentSingleSourceInfo = item;
|
||||||
// And finally, set the "control". This will trigger event
|
// // And finally, set the "control". This will trigger event
|
||||||
//CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device;
|
// //CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device;
|
||||||
|
|
||||||
OnFeedback.FireUpdate();
|
// OnFeedback.FireUpdate();
|
||||||
|
|
||||||
// report back when done
|
// // report back when done
|
||||||
if (successCallback != null)
|
// if (successCallback != null)
|
||||||
successCallback();
|
// successCallback();
|
||||||
}, 0); // end of CTimer
|
// }, 0); // end of CTimer
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
/// Will power the room on with the last-used source
|
// /// Will power the room on with the last-used source
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
public void PowerOnToDefaultOrLastSource()
|
// public void PowerOnToDefaultOrLastSource()
|
||||||
{
|
// {
|
||||||
if (!EnablePowerOnToLastSource || LastSourceKey == null)
|
// if (!EnablePowerOnToLastSource || LastSourceKey == null)
|
||||||
return;
|
// return;
|
||||||
RunRouteAction(LastSourceKey);
|
// RunRouteAction(LastSourceKey);
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
/// Does what it says
|
// /// Does what it says
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
public override void SetDefaultLevels()
|
// public override void SetDefaultLevels()
|
||||||
{
|
// {
|
||||||
Debug.Console(0, this, "SetDefaultLevels not implemented");
|
// Debug.Console(0, this, "SetDefaultLevels not implemented");
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
///
|
// ///
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
/// <param name="route"></param>
|
// /// <param name="route"></param>
|
||||||
/// <returns></returns>
|
// /// <returns></returns>
|
||||||
bool DoRoute(SourceRouteListItem route)
|
// bool DoRoute(SourceRouteListItem route)
|
||||||
{
|
// {
|
||||||
IRoutingSinkNoSwitching dest = null;
|
// IRoutingSinkNoSwitching dest = null;
|
||||||
|
|
||||||
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
|
// if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
|
||||||
dest = DefaultAudioDevice;
|
// dest = DefaultAudioDevice;
|
||||||
//else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
// //else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
||||||
// dest = DefaultDisplay;
|
// // dest = DefaultDisplay;
|
||||||
else
|
// else
|
||||||
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
|
// dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
|
||||||
|
|
||||||
if (dest == null)
|
// if (dest == null)
|
||||||
{
|
// {
|
||||||
Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
|
// Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
|
// if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
// {
|
||||||
dest.ReleaseRoute();
|
// dest.ReleaseRoute();
|
||||||
if (dest is IPower)
|
// if (dest is IPower)
|
||||||
(dest as IPower).PowerOff();
|
// (dest as IPower).PowerOff();
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
|
// var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
|
||||||
if (source == null)
|
// if (source == null)
|
||||||
{
|
// {
|
||||||
Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
|
// Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
dest.ReleaseAndMakeRoute(source, route.Type);
|
// dest.ReleaseAndMakeRoute(source, route.Type);
|
||||||
}
|
// }
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public override void RoomVacatedForTimeoutPeriod(object o)
|
// public override void RoomVacatedForTimeoutPeriod(object o)
|
||||||
{
|
// {
|
||||||
//Implement this
|
// //Implement this
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
@ -3,8 +3,12 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
|
using Crestron.SimplSharp.Scheduler;
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
|
using PepperDash.Essentials.Core.Devices;
|
||||||
using PepperDash.Essentials.Devices.Common.Occupancy;
|
using PepperDash.Essentials.Devices.Common.Occupancy;
|
||||||
|
|
||||||
namespace PepperDash.Essentials
|
namespace PepperDash.Essentials
|
||||||
|
|
@ -12,21 +16,18 @@ namespace PepperDash.Essentials
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IHasCurrentSourceInfoChange
|
public abstract class EssentialsRoomBase : ReconfigurableDevice
|
||||||
{
|
|
||||||
event SourceInfoChangeHandler CurrentSingleSourceChange;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public abstract class EssentialsRoomBase : Device
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BoolFeedback OnFeedback { get; private set; }
|
public BoolFeedback OnFeedback { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fires when the RoomOccupancy object is set
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<EventArgs> RoomOccupancyIsSet;
|
||||||
|
|
||||||
public BoolFeedback IsWarmingUpFeedback { get; private set; }
|
public BoolFeedback IsWarmingUpFeedback { get; private set; }
|
||||||
public BoolFeedback IsCoolingDownFeedback { get; private set; }
|
public BoolFeedback IsCoolingDownFeedback { get; private set; }
|
||||||
|
|
||||||
|
|
@ -81,12 +82,9 @@ namespace PepperDash.Essentials
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; }
|
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
public EssentialsRoomBase(DeviceConfig config)
|
||||||
/// </summary>
|
: base(config)
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="name"></param>
|
|
||||||
public EssentialsRoomBase(string key, string name) : base(key, name)
|
|
||||||
{
|
{
|
||||||
// Setup the ShutdownPromptTimer
|
// Setup the ShutdownPromptTimer
|
||||||
ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer");
|
ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer");
|
||||||
|
|
@ -117,6 +115,12 @@ namespace PepperDash.Essentials
|
||||||
|
|
||||||
IsWarmingUpFeedback = new BoolFeedback(IsWarmingFeedbackFunc);
|
IsWarmingUpFeedback = new BoolFeedback(IsWarmingFeedbackFunc);
|
||||||
IsCoolingDownFeedback = new BoolFeedback(IsCoolingFeedbackFunc);
|
IsCoolingDownFeedback = new BoolFeedback(IsCoolingFeedbackFunc);
|
||||||
|
|
||||||
|
AddPostActivationAction(() =>
|
||||||
|
{
|
||||||
|
if (RoomOccupancy != null)
|
||||||
|
OnRoomOccupancyIsSet();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomVacancyShutdownPromptTimer_HasFinished(object sender, EventArgs e)
|
void RoomVacancyShutdownPromptTimer_HasFinished(object sender, EventArgs e)
|
||||||
|
|
@ -154,6 +158,8 @@ namespace PepperDash.Essentials
|
||||||
ShutdownPromptTimer.SecondsToCount = ShutdownVacancySeconds;
|
ShutdownPromptTimer.SecondsToCount = ShutdownVacancySeconds;
|
||||||
ShutdownType = type;
|
ShutdownType = type;
|
||||||
ShutdownPromptTimer.Start();
|
ShutdownPromptTimer.Start();
|
||||||
|
|
||||||
|
Debug.Console(0, this, "ShutdwonPromptTimer Started. Type: {0}. Seconds: {1}", ShutdownType, ShutdownPromptTimer.SecondsToCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartRoomVacancyTimer(eVacancyMode mode)
|
public void StartRoomVacancyTimer(eVacancyMode mode)
|
||||||
|
|
@ -165,7 +171,7 @@ namespace PepperDash.Essentials
|
||||||
VacancyMode = mode;
|
VacancyMode = mode;
|
||||||
RoomVacancyShutdownTimer.Start();
|
RoomVacancyShutdownTimer.Start();
|
||||||
|
|
||||||
Debug.Console(0, this, "Vacancy Timer Started.");
|
Debug.Console(0, this, "Vacancy Timer Started. Mode: {0}. Seconds: {1}", VacancyMode, RoomVacancyShutdownTimer.SecondsToCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -208,11 +214,36 @@ namespace PepperDash.Essentials
|
||||||
if(timeoutMinutes > 0)
|
if(timeoutMinutes > 0)
|
||||||
RoomVacancyShutdownSeconds = timeoutMinutes * 60;
|
RoomVacancyShutdownSeconds = timeoutMinutes * 60;
|
||||||
|
|
||||||
|
Debug.Console(1, this, "RoomVacancyShutdownSeconds set to {0}", RoomVacancyShutdownSeconds);
|
||||||
|
|
||||||
RoomOccupancy = statusProvider;
|
RoomOccupancy = statusProvider;
|
||||||
|
|
||||||
|
OnRoomOccupancyIsSet();
|
||||||
|
|
||||||
|
RoomOccupancy.RoomIsOccupiedFeedback.OutputChange -= RoomIsOccupiedFeedback_OutputChange;
|
||||||
RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
|
RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
|
||||||
|
|
||||||
|
Debug.Console(0, this, "Room Occupancy set to device: '{0}'", (statusProvider as Device).Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnRoomOccupancyIsSet()
|
||||||
|
{
|
||||||
|
var handler = RoomOccupancyIsSet;
|
||||||
|
if (handler != null)
|
||||||
|
handler(this, new EventArgs());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// To allow base class to power room on to last source
|
||||||
|
/// </summary>
|
||||||
|
public abstract void PowerOnToDefaultOrLastSource();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// To allow base class to power room on to default source
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public abstract bool RunDefaultPresentRoute();
|
||||||
|
|
||||||
void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e)
|
void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false)
|
if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false)
|
||||||
|
|
@ -225,16 +256,10 @@ namespace PepperDash.Essentials
|
||||||
{
|
{
|
||||||
Debug.Console(1, this, "Notice: Occupancy Detected");
|
Debug.Console(1, this, "Notice: Occupancy Detected");
|
||||||
// Reset the timer when the room is occupied
|
// Reset the timer when the room is occupied
|
||||||
|
|
||||||
RoomVacancyShutdownTimer.Cancel();
|
RoomVacancyShutdownTimer.Cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//void SwapVolumeDevices(IBasicVolumeControls currentDevice, IBasicVolumeControls newDevice)
|
|
||||||
//{
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed
|
/// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ namespace PepperDash.Essentials
|
||||||
avDriver.PopupInterlock.HideAndClear());
|
avDriver.PopupInterlock.HideAndClear());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetUpHelpButton(EssentialsRoomPropertiesConfig roomConf)
|
public void SetUpHelpButton(EssentialsRoomPropertiesConfig roomConf)
|
||||||
{
|
{
|
||||||
// Help roomConf and popup
|
// Help roomConf and popup
|
||||||
if (roomConf.Help != null)
|
if (roomConf.Help != null)
|
||||||
|
|
@ -107,7 +107,7 @@ namespace PepperDash.Essentials
|
||||||
var room = DeviceManager.GetDeviceForKey(Config.DefaultRoomKey)
|
var room = DeviceManager.GetDeviceForKey(Config.DefaultRoomKey)
|
||||||
as EssentialsHuddleSpaceRoom;
|
as EssentialsHuddleSpaceRoom;
|
||||||
if (room != null)
|
if (room != null)
|
||||||
message = room.Config.HelpMessage;
|
message = room.PropertiesConfig.HelpMessage;
|
||||||
else
|
else
|
||||||
message = "Sorry, no help message available. No room connected.";
|
message = "Sorry, no help message available. No room connected.";
|
||||||
//TriList.StringInput[UIStringJoin.HelpMessage].StringValue = message;
|
//TriList.StringInput[UIStringJoin.HelpMessage].StringValue = message;
|
||||||
|
|
@ -227,7 +227,7 @@ namespace PepperDash.Essentials
|
||||||
|
|
||||||
TriList.SetBool(UIBoolJoin.TopBarHabaneroDynamicVisible, true);
|
TriList.SetBool(UIBoolJoin.TopBarHabaneroDynamicVisible, true);
|
||||||
|
|
||||||
var roomConf = currentRoom.Config;
|
var roomConf = currentRoom.PropertiesConfig;
|
||||||
|
|
||||||
// Register for the PopupInterlock IsShowsFeedback event to tie the header carets subpage visiblity to it
|
// Register for the PopupInterlock IsShowsFeedback event to tie the header carets subpage visiblity to it
|
||||||
Parent.AvDriver.PopupInterlock.StatusChanged -= PopupInterlock_StatusChanged;
|
Parent.AvDriver.PopupInterlock.StatusChanged -= PopupInterlock_StatusChanged;
|
||||||
|
|
@ -289,7 +289,7 @@ namespace PepperDash.Essentials
|
||||||
|
|
||||||
TriList.SetBool(UIBoolJoin.TopBarHabaneroDynamicVisible, true);
|
TriList.SetBool(UIBoolJoin.TopBarHabaneroDynamicVisible, true);
|
||||||
|
|
||||||
var roomConf = currentRoom.Config;
|
var roomConf = currentRoom.PropertiesConfig;
|
||||||
|
|
||||||
// Register for the PopupInterlock IsShowsFeedback event to tie the header carets subpage visiblity to it
|
// Register for the PopupInterlock IsShowsFeedback event to tie the header carets subpage visiblity to it
|
||||||
Parent.AvDriver.PopupInterlock.StatusChanged -= PopupInterlock_StatusChanged;
|
Parent.AvDriver.PopupInterlock.StatusChanged -= PopupInterlock_StatusChanged;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -6,6 +6,7 @@ using Crestron.SimplSharpPro.UI;
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
using PepperDash.Essentials.Core.SmartObjects;
|
using PepperDash.Essentials.Core.SmartObjects;
|
||||||
using PepperDash.Essentials.Core.PageManagers;
|
using PepperDash.Essentials.Core.PageManagers;
|
||||||
|
|
||||||
|
|
@ -163,7 +164,7 @@ namespace PepperDash.Essentials
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_TechDriver == null)
|
if (_TechDriver == null)
|
||||||
_TechDriver = new PepperDash.Essentials.UIDrivers.EssentialsHuddleTechPageDriver(TriList, CurrentRoom.Config.Tech);
|
_TechDriver = new PepperDash.Essentials.UIDrivers.EssentialsHuddleTechPageDriver(TriList, CurrentRoom.PropertiesConfig.Tech);
|
||||||
return _TechDriver;
|
return _TechDriver;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -219,9 +220,7 @@ namespace PepperDash.Essentials
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var roomConf = CurrentRoom.Config;
|
var roomConf = CurrentRoom.PropertiesConfig;
|
||||||
|
|
||||||
TriList.SetString(UIStringJoin.CurrentRoomName, CurrentRoom.Name);
|
|
||||||
|
|
||||||
if (Config.HeaderStyle.ToLower() == CrestronTouchpanelPropertiesConfig.Habanero)
|
if (Config.HeaderStyle.ToLower() == CrestronTouchpanelPropertiesConfig.Habanero)
|
||||||
{
|
{
|
||||||
|
|
@ -480,7 +479,7 @@ namespace PepperDash.Essentials
|
||||||
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = true;
|
TriList.BooleanInput[UIBoolJoin.SelectASourceVisible].BoolValue = true;
|
||||||
// Run default source when room is off and share is pressed
|
// Run default source when room is off and share is pressed
|
||||||
if (!CurrentRoom.OnFeedback.BoolValue)
|
if (!CurrentRoom.OnFeedback.BoolValue)
|
||||||
CurrentRoom.RunDefaultRoute();
|
CurrentRoom.RunDefaultPresentRoute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -592,7 +591,7 @@ namespace PepperDash.Essentials
|
||||||
EndMeetingButtonSig.BoolValue = true;
|
EndMeetingButtonSig.BoolValue = true;
|
||||||
ShareButtonSig.BoolValue = false;
|
ShareButtonSig.BoolValue = false;
|
||||||
|
|
||||||
if (CurrentRoom.ShutdownType == eShutdownType.Manual)
|
if (CurrentRoom.ShutdownType == eShutdownType.Manual || CurrentRoom.ShutdownType == eShutdownType.Vacancy)
|
||||||
{
|
{
|
||||||
PowerDownModal = new ModalDialog(TriList);
|
PowerDownModal = new ModalDialog(TriList);
|
||||||
var message = string.Format("Meeting will end in {0} seconds", CurrentRoom.ShutdownPromptSeconds);
|
var message = string.Format("Meeting will end in {0} seconds", CurrentRoom.ShutdownPromptSeconds);
|
||||||
|
|
@ -723,13 +722,12 @@ namespace PepperDash.Essentials
|
||||||
CurrentRoom.CurrentVolumeControls.VolumeDown(state);
|
CurrentRoom.CurrentVolumeControls.VolumeDown(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper for property setter. Sets the panel to the given room, latching up all functionality
|
/// Helper for property setter. Sets the panel to the given room, latching up all functionality
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void SetCurrentRoom(EssentialsHuddleSpaceRoom room)
|
public void RefreshCurrentRoom(EssentialsHuddleSpaceRoom room)
|
||||||
{
|
{
|
||||||
if (_CurrentRoom == room) return;
|
|
||||||
// Disconnect current (probably never called)
|
|
||||||
if (_CurrentRoom != null)
|
if (_CurrentRoom != null)
|
||||||
{
|
{
|
||||||
// Disconnect current room
|
// Disconnect current room
|
||||||
|
|
@ -741,7 +739,7 @@ namespace PepperDash.Essentials
|
||||||
_CurrentRoom.ShutdownPromptTimer.HasFinished -= ShutdownPromptTimer_HasFinished;
|
_CurrentRoom.ShutdownPromptTimer.HasFinished -= ShutdownPromptTimer_HasFinished;
|
||||||
_CurrentRoom.ShutdownPromptTimer.WasCancelled -= ShutdownPromptTimer_WasCancelled;
|
_CurrentRoom.ShutdownPromptTimer.WasCancelled -= ShutdownPromptTimer_WasCancelled;
|
||||||
|
|
||||||
_CurrentRoom.OnFeedback.OutputChange += CurrentRoom_OnFeedback_OutputChange;
|
_CurrentRoom.OnFeedback.OutputChange -= CurrentRoom_OnFeedback_OutputChange;
|
||||||
_CurrentRoom.IsWarmingUpFeedback.OutputChange -= CurrentRoom_IsWarmingFeedback_OutputChange;
|
_CurrentRoom.IsWarmingUpFeedback.OutputChange -= CurrentRoom_IsWarmingFeedback_OutputChange;
|
||||||
_CurrentRoom.IsCoolingDownFeedback.OutputChange -= IsCoolingDownFeedback_OutputChange;
|
_CurrentRoom.IsCoolingDownFeedback.OutputChange -= IsCoolingDownFeedback_OutputChange;
|
||||||
}
|
}
|
||||||
|
|
@ -817,83 +815,26 @@ namespace PepperDash.Essentials
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//void SetupHeaderButtons()
|
void SetCurrentRoom(EssentialsHuddleSpaceRoom room)
|
||||||
//{
|
{
|
||||||
// HeaderButtonsAreSetUp = false;
|
if (_CurrentRoom == room) return;
|
||||||
|
// Disconnect current (probably never called)
|
||||||
|
|
||||||
// TriList.SetBool(UIBoolJoin.TopBarHabaneroDynamicVisible, true);
|
room.ConfigChanged -= room_ConfigChanged;
|
||||||
|
room.ConfigChanged += room_ConfigChanged;
|
||||||
|
|
||||||
// var roomConf = CurrentRoom.Config;
|
RefreshCurrentRoom(room);
|
||||||
|
}
|
||||||
// // Gear
|
|
||||||
// TriList.SetString(UIStringJoin.HeaderButtonIcon5, "Gear");
|
|
||||||
// TriList.SetSigHeldAction(UIBoolJoin.HeaderIcon5Press, 2000,
|
|
||||||
// ShowTech,
|
|
||||||
// null,
|
|
||||||
// () =>
|
|
||||||
// {
|
|
||||||
// if (CurrentRoom.OnFeedback.BoolValue)
|
|
||||||
// PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.VolumesPageVisible);
|
|
||||||
// else
|
|
||||||
// PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.VolumesPagePowerOffVisible);
|
|
||||||
// });
|
|
||||||
// TriList.SetSigFalseAction(UIBoolJoin.TechExitButton, () =>
|
|
||||||
// PopupInterlock.HideAndClear());
|
|
||||||
|
|
||||||
// // Help button and popup
|
|
||||||
// if (CurrentRoom.Config.Help != null)
|
|
||||||
// {
|
|
||||||
// TriList.SetString(UIStringJoin.HelpMessage, roomConf.Help.Message);
|
|
||||||
// TriList.SetBool(UIBoolJoin.HelpPageShowCallButtonVisible, roomConf.Help.ShowCallButton);
|
|
||||||
// TriList.SetString(UIStringJoin.HelpPageCallButtonText, roomConf.Help.CallButtonText);
|
|
||||||
// if (roomConf.Help.ShowCallButton)
|
|
||||||
// TriList.SetSigFalseAction(UIBoolJoin.HelpPageShowCallButtonPress, () => { }); // ************ FILL IN
|
|
||||||
// else
|
|
||||||
// TriList.ClearBoolSigAction(UIBoolJoin.HelpPageShowCallButtonPress);
|
|
||||||
// }
|
|
||||||
// else // older config
|
|
||||||
// {
|
|
||||||
// TriList.SetString(UIStringJoin.HelpMessage, CurrentRoom.Config.HelpMessage);
|
|
||||||
// TriList.SetBool(UIBoolJoin.HelpPageShowCallButtonVisible, false);
|
|
||||||
// TriList.SetString(UIStringJoin.HelpPageCallButtonText, null);
|
|
||||||
// TriList.ClearBoolSigAction(UIBoolJoin.HelpPageShowCallButtonPress);
|
|
||||||
// }
|
|
||||||
// TriList.SetString(UIStringJoin.HeaderButtonIcon4, "Help");
|
|
||||||
// TriList.SetSigFalseAction(UIBoolJoin.HeaderIcon4Press, () =>
|
|
||||||
// {
|
|
||||||
// string message = null;
|
|
||||||
// var room = DeviceManager.GetDeviceForKey(Config.DefaultRoomKey)
|
|
||||||
// as EssentialsHuddleSpaceRoom;
|
|
||||||
// if (room != null)
|
|
||||||
// message = room.Config.HelpMessage;
|
|
||||||
// else
|
|
||||||
// message = "Sorry, no help message available. No room connected.";
|
|
||||||
// //TriList.StringInput[UIStringJoin.HelpMessage].StringValue = message;
|
|
||||||
// PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.HelpPageVisible);
|
|
||||||
// });
|
|
||||||
// uint nextJoin = 3953;
|
|
||||||
|
|
||||||
// //// Calendar button
|
|
||||||
// //if (_CurrentRoom.ScheduleSource != null)
|
|
||||||
// //{
|
|
||||||
// // TriList.SetString(nextJoin, "Calendar");
|
|
||||||
// // TriList.SetSigFalseAction(nextJoin, CalendarPress);
|
|
||||||
|
|
||||||
// // nextJoin--;
|
|
||||||
// //}
|
|
||||||
|
|
||||||
// //nextJoin--;
|
|
||||||
|
|
||||||
// // blank any that remain
|
|
||||||
// for (var i = nextJoin; i > 3950; i--)
|
|
||||||
// {
|
|
||||||
// TriList.SetString(i, "Blank");
|
|
||||||
// TriList.SetSigFalseAction(i, () => { });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// HeaderButtonsAreSetUp = true;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fires when room config of current room has changed. Meant to refresh room values to propegate any updates to UI
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
void room_ConfigChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
RefreshCurrentRoom(_CurrentRoom);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For room on/off changes
|
/// For room on/off changes
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials;
|
using PepperDash.Essentials;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
using PepperDash.Essentials.Core.SmartObjects;
|
using PepperDash.Essentials.Core.SmartObjects;
|
||||||
using PepperDash.Essentials.Core.Touchpanels.Keyboards;
|
using PepperDash.Essentials.Core.Touchpanels.Keyboards;
|
||||||
using PepperDash.Essentials.Devices.Displays;
|
using PepperDash.Essentials.Devices.Displays;
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using Crestron.SimplSharpPro.UI;
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
using PepperDash.Essentials.Core.SmartObjects;
|
using PepperDash.Essentials.Core.SmartObjects;
|
||||||
using PepperDash.Essentials.Core.PageManagers;
|
using PepperDash.Essentials.Core.PageManagers;
|
||||||
using PepperDash.Essentials.Room.Config;
|
using PepperDash.Essentials.Room.Config;
|
||||||
|
|
@ -154,7 +155,7 @@ namespace PepperDash.Essentials
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_TechDriver == null)
|
if (_TechDriver == null)
|
||||||
_TechDriver = new PepperDash.Essentials.UIDrivers.EssentialsHuddleTechPageDriver(TriList, CurrentRoom.Config.Tech);
|
_TechDriver = new PepperDash.Essentials.UIDrivers.EssentialsHuddleTechPageDriver(TriList, CurrentRoom.PropertiesConfig.Tech);
|
||||||
return _TechDriver;
|
return _TechDriver;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -234,9 +235,7 @@ namespace PepperDash.Essentials
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var roomConf = CurrentRoom.Config;
|
var roomConf = CurrentRoom.PropertiesConfig;
|
||||||
|
|
||||||
TriList.SetString(UIStringJoin.CurrentRoomName, CurrentRoom.Name);
|
|
||||||
|
|
||||||
if (Config.HeaderStyle.ToLower() == CrestronTouchpanelPropertiesConfig.Habanero)
|
if (Config.HeaderStyle.ToLower() == CrestronTouchpanelPropertiesConfig.Habanero)
|
||||||
{
|
{
|
||||||
|
|
@ -763,7 +762,7 @@ namespace PepperDash.Essentials
|
||||||
var timer = CurrentRoom.ShutdownPromptTimer;
|
var timer = CurrentRoom.ShutdownPromptTimer;
|
||||||
SetActivityFooterFeedbacks();
|
SetActivityFooterFeedbacks();
|
||||||
|
|
||||||
if (CurrentRoom.ShutdownType == eShutdownType.Manual)
|
if (CurrentRoom.ShutdownType == eShutdownType.Manual || CurrentRoom.ShutdownType == eShutdownType.Vacancy)
|
||||||
{
|
{
|
||||||
PowerDownModal = new ModalDialog(TriList);
|
PowerDownModal = new ModalDialog(TriList);
|
||||||
var message = string.Format("Meeting will end in {0} seconds", CurrentRoom.ShutdownPromptSeconds);
|
var message = string.Format("Meeting will end in {0} seconds", CurrentRoom.ShutdownPromptSeconds);
|
||||||
|
|
@ -878,10 +877,9 @@ namespace PepperDash.Essentials
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper for property setter. Sets the panel to the given room, latching up all functionality
|
/// Helper for property setter. Sets the panel to the given room, latching up all functionality
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void SetCurrentRoom(EssentialsHuddleVtc1Room room)
|
void RefreshCurrentRoom(EssentialsHuddleVtc1Room room)
|
||||||
{
|
{
|
||||||
if (_CurrentRoom == room) return;
|
|
||||||
// Disconnect current (probably never called)
|
|
||||||
if (_CurrentRoom != null)
|
if (_CurrentRoom != null)
|
||||||
{
|
{
|
||||||
// Disconnect current room
|
// Disconnect current room
|
||||||
|
|
@ -893,7 +891,7 @@ namespace PepperDash.Essentials
|
||||||
_CurrentRoom.ShutdownPromptTimer.HasFinished -= ShutdownPromptTimer_HasFinished;
|
_CurrentRoom.ShutdownPromptTimer.HasFinished -= ShutdownPromptTimer_HasFinished;
|
||||||
_CurrentRoom.ShutdownPromptTimer.WasCancelled -= ShutdownPromptTimer_WasCancelled;
|
_CurrentRoom.ShutdownPromptTimer.WasCancelled -= ShutdownPromptTimer_WasCancelled;
|
||||||
|
|
||||||
_CurrentRoom.OnFeedback.OutputChange += CurrentRoom_OnFeedback_OutputChange;
|
_CurrentRoom.OnFeedback.OutputChange -= CurrentRoom_OnFeedback_OutputChange;
|
||||||
_CurrentRoom.IsWarmingUpFeedback.OutputChange -= CurrentRoom_IsWarmingFeedback_OutputChange;
|
_CurrentRoom.IsWarmingUpFeedback.OutputChange -= CurrentRoom_IsWarmingFeedback_OutputChange;
|
||||||
_CurrentRoom.IsCoolingDownFeedback.OutputChange -= CurrentRoom_IsCoolingDownFeedback_OutputChange;
|
_CurrentRoom.IsCoolingDownFeedback.OutputChange -= CurrentRoom_IsCoolingDownFeedback_OutputChange;
|
||||||
_CurrentRoom.InCallFeedback.OutputChange -= CurrentRoom_InCallFeedback_OutputChange;
|
_CurrentRoom.InCallFeedback.OutputChange -= CurrentRoom_InCallFeedback_OutputChange;
|
||||||
|
|
@ -951,6 +949,27 @@ namespace PepperDash.Essentials
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetCurrentRoom(EssentialsHuddleVtc1Room room)
|
||||||
|
{
|
||||||
|
if (_CurrentRoom == room) return;
|
||||||
|
// Disconnect current (probably never called)
|
||||||
|
|
||||||
|
room.ConfigChanged -= room_ConfigChanged;
|
||||||
|
room.ConfigChanged += room_ConfigChanged;
|
||||||
|
|
||||||
|
RefreshCurrentRoom(room);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fires when room config of current room has changed. Meant to refresh room values to propegate any updates to UI
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
void room_ConfigChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
RefreshCurrentRoom(_CurrentRoom);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -1065,155 +1084,6 @@ namespace PepperDash.Essentials
|
||||||
TriList.StringInput[UIStringJoin.CallSharedSourceNameText].StringValue = callListSharedSourceLabel;
|
TriList.StringInput[UIStringJoin.CallSharedSourceNameText].StringValue = callListSharedSourceLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///// <summary>
|
|
||||||
/////
|
|
||||||
///// </summary>
|
|
||||||
//void SetupHeaderButtons()
|
|
||||||
//{
|
|
||||||
// HeaderButtonsAreSetUp = false;
|
|
||||||
|
|
||||||
// TriList.SetBool(UIBoolJoin.TopBarHabaneroDynamicVisible, true);
|
|
||||||
|
|
||||||
// var roomConf = CurrentRoom.Config;
|
|
||||||
|
|
||||||
// // Gear
|
|
||||||
// TriList.SetString(UIStringJoin.HeaderButtonIcon5, "Gear");
|
|
||||||
// TriList.SetSigHeldAction(UIBoolJoin.HeaderIcon5Press, 2000,
|
|
||||||
// ShowTech,
|
|
||||||
// null,
|
|
||||||
// () =>
|
|
||||||
// {
|
|
||||||
// if (CurrentRoom.OnFeedback.BoolValue)
|
|
||||||
// PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.VolumesPageVisible);
|
|
||||||
// else
|
|
||||||
// PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.VolumesPagePowerOffVisible);
|
|
||||||
// });
|
|
||||||
// TriList.SetSigFalseAction(UIBoolJoin.TechExitButton, () =>
|
|
||||||
// PopupInterlock.HideAndClear());
|
|
||||||
|
|
||||||
// // Help button and popup
|
|
||||||
// if (CurrentRoom.Config.Help != null)
|
|
||||||
// {
|
|
||||||
// TriList.SetString(UIStringJoin.HelpMessage, roomConf.Help.Message);
|
|
||||||
// TriList.SetBool(UIBoolJoin.HelpPageShowCallButtonVisible, roomConf.Help.ShowCallButton);
|
|
||||||
// TriList.SetString(UIStringJoin.HelpPageCallButtonText, roomConf.Help.CallButtonText);
|
|
||||||
// if (roomConf.Help.ShowCallButton)
|
|
||||||
// TriList.SetSigFalseAction(UIBoolJoin.HelpPageShowCallButtonPress, () => { }); // ************ FILL IN
|
|
||||||
// else
|
|
||||||
// TriList.ClearBoolSigAction(UIBoolJoin.HelpPageShowCallButtonPress);
|
|
||||||
// }
|
|
||||||
// else // older config
|
|
||||||
// {
|
|
||||||
// TriList.SetString(UIStringJoin.HelpMessage, CurrentRoom.Config.HelpMessage);
|
|
||||||
// TriList.SetBool(UIBoolJoin.HelpPageShowCallButtonVisible, false);
|
|
||||||
// TriList.SetString(UIStringJoin.HelpPageCallButtonText, null);
|
|
||||||
// TriList.ClearBoolSigAction(UIBoolJoin.HelpPageShowCallButtonPress);
|
|
||||||
// }
|
|
||||||
// TriList.SetString(UIStringJoin.HeaderButtonIcon4, "Help");
|
|
||||||
// TriList.SetSigFalseAction(UIBoolJoin.HeaderIcon4Press, () =>
|
|
||||||
// {
|
|
||||||
// string message = null;
|
|
||||||
// var room = DeviceManager.GetDeviceForKey(Config.DefaultRoomKey)
|
|
||||||
// as EssentialsHuddleSpaceRoom;
|
|
||||||
// if (room != null)
|
|
||||||
// message = room.Config.HelpMessage;
|
|
||||||
// else
|
|
||||||
// message = "Sorry, no help message available. No room connected.";
|
|
||||||
// //TriList.StringInput[UIStringJoin.HelpMessage].StringValue = message;
|
|
||||||
// PopupInterlock.ShowInterlockedWithToggle(UIBoolJoin.HelpPageVisible);
|
|
||||||
// });
|
|
||||||
// uint nextJoin = 3953;
|
|
||||||
|
|
||||||
// // Calendar button
|
|
||||||
// if (_CurrentRoom.ScheduleSource != null)
|
|
||||||
// {
|
|
||||||
// TriList.SetString(nextJoin, "Calendar");
|
|
||||||
// TriList.SetSigFalseAction(nextJoin, CalendarPress);
|
|
||||||
|
|
||||||
// nextJoin--;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Call button
|
|
||||||
// TriList.SetString(nextJoin, "DND");
|
|
||||||
// TriList.SetSigFalseAction(nextJoin, ShowActiveCallsList);
|
|
||||||
// HeaderCallButtonIconSig = TriList.StringInput[nextJoin];
|
|
||||||
|
|
||||||
// nextJoin--;
|
|
||||||
|
|
||||||
// // blank any that remain
|
|
||||||
// for (var i = nextJoin; i > 3950; i--)
|
|
||||||
// {
|
|
||||||
// TriList.SetString(i, "Blank");
|
|
||||||
// TriList.SetSigFalseAction(i, () => { });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// TriList.SetSigFalseAction(UIBoolJoin.HeaderCallStatusLabelPress, ShowActiveCallsList);
|
|
||||||
|
|
||||||
// // Set Call Status Subpage Position
|
|
||||||
|
|
||||||
// if (nextJoin == 3951)
|
|
||||||
// {
|
|
||||||
// // Set to right position
|
|
||||||
// TriList.SetBool(UIBoolJoin.HeaderCallStatusLeftPositionVisible, false);
|
|
||||||
// TriList.SetBool(UIBoolJoin.HeaderCallStatusRightPositionVisible, true);
|
|
||||||
// }
|
|
||||||
// else if (nextJoin == 3950)
|
|
||||||
// {
|
|
||||||
// // Set to left position
|
|
||||||
// TriList.SetBool(UIBoolJoin.HeaderCallStatusLeftPositionVisible, true);
|
|
||||||
// TriList.SetBool(UIBoolJoin.HeaderCallStatusRightPositionVisible, false);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// HeaderButtonsAreSetUp = true;
|
|
||||||
|
|
||||||
// ComputeHeaderCallStatus(CurrentRoom.VideoCodec);
|
|
||||||
//}
|
|
||||||
|
|
||||||
///// <summary>
|
|
||||||
///// Evaluates the call status and sets the icon mode and text label
|
|
||||||
///// </summary>
|
|
||||||
//public void ComputeHeaderCallStatus(VideoCodecBase codec)
|
|
||||||
//{
|
|
||||||
// if (codec == null)
|
|
||||||
// {
|
|
||||||
// Debug.Console(1, "ComputeHeaderCallStatus() cannot execute. codec is null");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (HeaderCallButtonIconSig == null)
|
|
||||||
// {
|
|
||||||
// Debug.Console(1, "ComputeHeaderCallStatus() cannot execute. HeaderCallButtonIconSig is null");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Set mode of header button
|
|
||||||
// if (!codec.IsInCall)
|
|
||||||
// {
|
|
||||||
// HeaderCallButtonIconSig.StringValue = "DND";
|
|
||||||
// //HeaderCallButton.SetIcon(HeaderListButton.OnHook);
|
|
||||||
// }
|
|
||||||
// else if (codec.ActiveCalls.Any(c => c.Type == eCodecCallType.Video))
|
|
||||||
// HeaderCallButtonIconSig.StringValue = "Misc-06_Dark";
|
|
||||||
// //HeaderCallButton.SetIcon(HeaderListButton.Camera);
|
|
||||||
// //TriList.SetUshort(UIUshortJoin.CallHeaderButtonMode, 2);
|
|
||||||
// else
|
|
||||||
// HeaderCallButtonIconSig.StringValue = "Misc-09_Dark";
|
|
||||||
// //HeaderCallButton.SetIcon(HeaderListButton.Phone);
|
|
||||||
// //TriList.SetUshort(UIUshortJoin.CallHeaderButtonMode, 1);
|
|
||||||
|
|
||||||
// // Set the call status text
|
|
||||||
// if (codec.ActiveCalls.Count > 0)
|
|
||||||
// {
|
|
||||||
// if (codec.ActiveCalls.Count == 1)
|
|
||||||
// TriList.SetString(UIStringJoin.HeaderCallStatusLabel, "1 Active Call");
|
|
||||||
// else if (codec.ActiveCalls.Count > 1)
|
|
||||||
// TriList.SetString(UIStringJoin.HeaderCallStatusLabel, string.Format("{0} Active Calls", codec.ActiveCalls.Count));
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// TriList.SetString(UIStringJoin.HeaderCallStatusLabel, "No Active Calls");
|
|
||||||
//}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
16
PepperDashEssentials/UIDrivers/SourceChangeArgs.cs
Normal file
16
PepperDashEssentials/UIDrivers/SourceChangeArgs.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
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>
|
||||||
|
/// The handler type for a Room's SourceInfoChange
|
||||||
|
/// </summary>
|
||||||
|
public delegate void SourceInfoChangeHandler(EssentialsRoomBase room, SourceListItem info, ChangeType type);
|
||||||
|
}
|
||||||
|
|
@ -202,8 +202,6 @@ namespace PepperDash.Essentials.UIDrivers.VC
|
||||||
{
|
{
|
||||||
string roomNumberSipUri = "";
|
string roomNumberSipUri = "";
|
||||||
|
|
||||||
#warning FIX PHONE FORMATTING TO ONLY SHOW WHEN APPROPRIATE - TALK TO NEIL
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Codec.CodecInfo.SipUri)) // If both values are present, format the string with a pipe divider
|
if (!string.IsNullOrEmpty(Codec.CodecInfo.SipUri)) // If both values are present, format the string with a pipe divider
|
||||||
roomNumberSipUri = string.Format("{0} | {1}", GetFormattedPhoneNumber(Codec.CodecInfo.SipPhoneNumber), Codec.CodecInfo.SipUri);
|
roomNumberSipUri = string.Format("{0} | {1}", GetFormattedPhoneNumber(Codec.CodecInfo.SipPhoneNumber), Codec.CodecInfo.SipUri);
|
||||||
else // If only one value present, just show the phone number
|
else // If only one value present, just show the phone number
|
||||||
|
|
@ -537,8 +535,6 @@ namespace PepperDash.Essentials.UIDrivers.VC
|
||||||
DirectoryBrowseHistory = new List<CodecDirectory>();
|
DirectoryBrowseHistory = new List<CodecDirectory>();
|
||||||
|
|
||||||
var codec = Codec as IHasDirectory;
|
var codec = Codec as IHasDirectory;
|
||||||
if (codec != null)
|
|
||||||
{
|
|
||||||
if (codec != null)
|
if (codec != null)
|
||||||
{
|
{
|
||||||
DirectoryList = new SmartObjectDynamicList(TriList.SmartObjects[UISmartObjectJoin.VCDirectoryList],
|
DirectoryList = new SmartObjectDynamicList(TriList.SmartObjects[UISmartObjectJoin.VCDirectoryList],
|
||||||
|
|
@ -560,7 +556,6 @@ namespace PepperDash.Essentials.UIDrivers.VC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the current directory resutls to the DirectorRoot and updates Back Button visibiltiy
|
/// Sets the current directory resutls to the DirectorRoot and updates Back Button visibiltiy
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
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 class VolumeDeviceChangeEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
public IBasicVolumeControls OldDev { get; private set; }
|
|
||||||
public IBasicVolumeControls NewDev { get; private set; }
|
|
||||||
public ChangeType Type { get; private set; }
|
|
||||||
|
|
||||||
public VolumeDeviceChangeEventArgs(IBasicVolumeControls oldDev, IBasicVolumeControls newDev, ChangeType type)
|
|
||||||
{
|
|
||||||
OldDev = oldDev;
|
|
||||||
NewDev = newDev;
|
|
||||||
Type = type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The handler type for a Room's SourceInfoChange
|
|
||||||
/// </summary>
|
|
||||||
public delegate void SourceInfoChangeHandler(EssentialsRoomBase room, SourceListItem info, ChangeType type);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public enum ChangeType
|
|
||||||
{
|
|
||||||
WillChange, DidChange
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BIN
Release Package/PepperDashEssentials.cpz
Normal file
BIN
Release Package/PepperDashEssentials.cpz
Normal file
Binary file not shown.
BIN
Release Package/PepperDashEssentials.dll
Normal file
BIN
Release Package/PepperDashEssentials.dll
Normal file
Binary file not shown.
|
|
@ -29,3 +29,5 @@ devjson:1 {"deviceKey":"microphonePrivacyController-1", "methodName":"TogglePriv
|
||||||
devjson:1 {"deviceKey":"room1.InCallFeedback","methodName":"SetTestValue", "params": [ true ]}
|
devjson:1 {"deviceKey":"room1.InCallFeedback","methodName":"SetTestValue", "params": [ true ]}
|
||||||
|
|
||||||
devjson:1 {"deviceKey":"room1.InCallFeedback","methodName":"ClearTestValue", "params": []}
|
devjson:1 {"deviceKey":"room1.InCallFeedback","methodName":"ClearTestValue", "params": []}
|
||||||
|
|
||||||
|
devjson:3 {"deviceKey":"room1.RoomOccupancy.RoomIsOccupiedFeedback","methodName":"SetTestValue", "params": [ true ]}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue