mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-15 12:44:58 +00:00
Merge remote-tracking branch 'origin/bugfix/mob-470' into feature/ecs-967
# Conflicts: # PepperDashEssentials/AppServer/CotijaSystemController.cs # PepperDashEssentials/AppServer/RoomBridges/CotijaDdvc01RoomBridge.cs # PepperDashEssentials/ControlSystem.cs # PepperDashEssentials/OTHER/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs # PepperDashEssentials/OTHER/Fusion/EssentialsHuddleVtc1FusionController.cs # PepperDashEssentials/Properties/AssemblyInfo.cs # PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs # devjson commands.json
This commit is contained in:
@@ -15,7 +15,6 @@ 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
|
||||||
@@ -24,6 +23,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>
|
||||||
@@ -83,12 +84,33 @@ 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, "showactionpaths", "Prints the paths in teh Action Dictionary", 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.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
|
||||||
|
CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <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>
|
/// <summary>
|
||||||
/// Sends message to server to indicate the system is shutting down
|
/// Sends message to server to indicate the system is shutting down
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -97,11 +119,7 @@ namespace PepperDash.Essentials
|
|||||||
{
|
{
|
||||||
if (programEventType == eProgramStatusEventType.Stopping && WSClient.Connected)
|
if (programEventType == eProgramStatusEventType.Stopping && WSClient.Connected)
|
||||||
{
|
{
|
||||||
SendMessageToServer(JObject.FromObject( new
|
CleanUpWebsocketClient();
|
||||||
{
|
|
||||||
type = "/system/close"
|
|
||||||
}));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,6 +176,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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,6 +189,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();
|
||||||
}
|
}
|
||||||
@@ -189,6 +209,8 @@ 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))
|
if (string.IsNullOrEmpty(SystemUuid))
|
||||||
{
|
{
|
||||||
CrestronConsole.ConsoleCommandResponse("System does not have a UUID. Please ensure proper portal-format configuration is loaded and restart.");
|
CrestronConsole.ConsoleCommandResponse("System does not have a UUID. Please ensure proper portal-format configuration is loaded and restart.");
|
||||||
@@ -221,6 +243,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)
|
||||||
@@ -281,58 +304,104 @@ 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()
|
||||||
{
|
{
|
||||||
|
ConnectWebsocketClient();
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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>
|
||||||
|
/// 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;
|
||||||
|
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);
|
||||||
|
|
||||||
|
var msg = new
|
||||||
|
{
|
||||||
|
type = "join",
|
||||||
|
content = new
|
||||||
|
{
|
||||||
|
config = confObject
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SendMessageObjectToServer(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends any object type to server
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="o"></param>
|
||||||
|
public void SendMessageObjectToServer(object o)
|
||||||
|
{
|
||||||
|
SendMessageToServer(JObject.FromObject(o));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends a message to the server from a room
|
/// Sends a message to the server from a room
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -340,78 +409,67 @@ 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()
|
||||||
{
|
{
|
||||||
//if(SseClient != null)
|
Debug.Console(1, this, "Disconnecting websocket");
|
||||||
// SseClient.Disconnect();
|
if (WSClient != null)
|
||||||
|
{
|
||||||
if (WSClient != null && WSClient.Connected)
|
WSClient.SendCallBack = null;
|
||||||
WSClient.Disconnect();
|
WSClient.ReceiveCallBack = null;
|
||||||
|
WSClient.ConnectionCallBack = null;
|
||||||
if (ServerHeartbeatCheckTimer != null)
|
WSClient.DisconnectCallBack = null;
|
||||||
{
|
if (WSClient.Connected)
|
||||||
ServerHeartbeatCheckTimer.Stop();
|
{
|
||||||
|
WSClient.Disconnect();
|
||||||
ServerHeartbeatCheckTimer = null;
|
}
|
||||||
}
|
WSClient = 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!
|
/// <summary>
|
||||||
ConnectStreamClient();
|
///
|
||||||
}
|
/// </summary>
|
||||||
else
|
/// <param name="dueTime"></param>
|
||||||
{
|
/// <param name="repeatTime"></param>
|
||||||
if (resp != null)
|
void StartServerReconnectTimer()
|
||||||
Debug.Console(1, this, "Response from server: {0}\n{1}", resp.Code, err);
|
{
|
||||||
else
|
StopServerReconnectTimer();
|
||||||
{
|
ServerReconnectTimer = new CTimer(ReconnectToServerTimerCallback, ServerReconnectInterval);
|
||||||
Debug.Console(1, this, "Null response received from server.");
|
Debug.Console(1, this, "Reconnect Timer Started.");
|
||||||
}
|
}
|
||||||
StartReconnectTimer();
|
|
||||||
}
|
/// <summary>
|
||||||
}
|
/// Does what it says
|
||||||
catch (Exception e)
|
/// </summary>
|
||||||
{
|
void StopServerReconnectTimer()
|
||||||
Debug.Console(1, this, "Error Initializing Stream Client: {0}", e);
|
{
|
||||||
StartReconnectTimer();
|
if (ServerReconnectTimer != null)
|
||||||
}
|
{
|
||||||
RegisterLockEvent.Set();
|
ServerReconnectTimer.Stop();
|
||||||
}
|
ServerReconnectTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executes when we don't get a heartbeat message in time. Triggers reconnect.
|
/// Executes when we don't get a heartbeat message in time. Triggers reconnect.
|
||||||
@@ -425,23 +483,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>
|
||||||
@@ -451,37 +494,42 @@ namespace PepperDash.Essentials
|
|||||||
/// <param name="repeatTime"></param>
|
/// <param name="repeatTime"></param>
|
||||||
void ResetOrStartHearbeatTimer()
|
void ResetOrStartHearbeatTimer()
|
||||||
{
|
{
|
||||||
if (ServerHeartbeatCheckTimer == null)
|
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();
|
ServerHeartbeatCheckTimer = new CTimer(HeartbeatExpiredTimerCallback, null, ServerHeartbeatInterval, ServerHeartbeatInterval);
|
||||||
|
Debug.Console(1, this, "Heartbeat Timer Started.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ServerHeartbeatCheckTimer.Reset(ServerHeartbeatInterval, ServerHeartbeatInterval);
|
||||||
}
|
}
|
||||||
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>
|
||||||
|
/// Waits two and goes again
|
||||||
|
/// </summary>
|
||||||
|
void ReconnectStreamClient()
|
||||||
|
{
|
||||||
|
new CTimer(o => ConnectWebsocketClient(), 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="code"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
int Websocket_DisconnectCallback(WebSocketClient.WEBSOCKET_RESULT_CODES code, object o)
|
||||||
|
{
|
||||||
|
Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Websocket disconnected with code: {0}", code);
|
||||||
|
|
||||||
|
if (ServerHeartbeatCheckTimer != null)
|
||||||
|
ServerHeartbeatCheckTimer.Stop();
|
||||||
|
// Start the reconnect timer
|
||||||
|
StartServerReconnectTimer();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resets reconnect timer and updates usercode
|
/// Resets reconnect timer and updates usercode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -514,12 +562,26 @@ namespace PepperDash.Essentials
|
|||||||
{
|
{
|
||||||
if (HttpDebugEnabled)
|
if (HttpDebugEnabled)
|
||||||
{
|
{
|
||||||
Debug.Console(0, this, "------ Begin HTTP Debug ---------------------------------------");
|
try
|
||||||
Debug.Console(0, this, "HTTP Response URL: {0}", r.ResponseUrl.ToString());
|
{
|
||||||
Debug.Console(0, this, "HTTP Response 'error' {0}", e);
|
Debug.Console(0, this, "------ Begin HTTP Debug ---------------------------------------");
|
||||||
Debug.Console(0, this, "HTTP Response code: {0}", r.Code);
|
if (r != null)
|
||||||
Debug.Console(0, this, "HTTP Response content: \r{0}", r.ContentString);
|
{
|
||||||
Debug.Console(0, this, "------ End HTTP Debug -----------------------------------------");
|
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 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 -----------------------------------------");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.Console(0, this, "HttpDebugError: {0}", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,14 +592,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)
|
||||||
{
|
{
|
||||||
var rx = System.Text.Encoding.UTF8.GetString(data, 0, (int)length);
|
if (opcode == WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME)
|
||||||
if(rx.Length > 0)
|
{
|
||||||
ParseStreamRx(rx);
|
var rx = System.Text.Encoding.UTF8.GetString(data, 0, (int)length);
|
||||||
WSClient.ReceiveAsync();
|
if (rx.Length > 0)
|
||||||
return 1;
|
ParseStreamRx(rx);
|
||||||
|
WSClient.ReceiveAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
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>
|
||||||
@@ -545,11 +621,11 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -562,7 +638,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);
|
||||||
@@ -571,6 +647,7 @@ namespace PepperDash.Essentials
|
|||||||
|
|
||||||
if (type == "hello")
|
if (type == "hello")
|
||||||
{
|
{
|
||||||
|
SendInitialMessage();
|
||||||
ResetOrStartHearbeatTimer();
|
ResetOrStartHearbeatTimer();
|
||||||
}
|
}
|
||||||
else if (type == "/system/heartbeat")
|
else if (type == "/system/heartbeat")
|
||||||
@@ -579,11 +656,11 @@ namespace PepperDash.Essentials
|
|||||||
}
|
}
|
||||||
else if (type == "close")
|
else if (type == "close")
|
||||||
{
|
{
|
||||||
WSClient.Disconnect();
|
Debug.Console(1, this, "Received close message from server.");
|
||||||
|
// DisconnectWebsocketClient();
|
||||||
|
|
||||||
ServerHeartbeatCheckTimer.Stop();
|
if (ServerHeartbeatCheckTimer != null)
|
||||||
// Start the reconnect timer
|
ServerHeartbeatCheckTimer.Stop();
|
||||||
StartReconnectTimer();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -620,7 +697,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);
|
||||||
}
|
}
|
||||||
|
|||||||
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(BasicTriList eisc, string messagePath)
|
||||||
|
: base(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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
72
PepperDashEssentials/AppServer/Messengers/MessengerBase.cs
Normal file
72
PepperDashEssentials/AppServer/Messengers/MessengerBase.cs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
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 abstract class MessengerBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public CotijaSystemController AppServerController { get; private set; }
|
||||||
|
|
||||||
|
public string MessagePath { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codec"></param>
|
||||||
|
public MessengerBase(string messagePath)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
AppServerController.SendMessageToServer(JObject.FromObject(new
|
||||||
|
{
|
||||||
|
type = MessagePath,
|
||||||
|
content = contentObject
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,29 +15,22 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides a messaging bridge for a VideoCodecBase
|
/// Provides a messaging bridge for a VideoCodecBase
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class VideoCodecBaseMessenger
|
public class VideoCodecBaseMessenger : MessengerBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public VideoCodecBase Codec { get; private set; }
|
public VideoCodecBase Codec { get; private set; }
|
||||||
|
|
||||||
public CotijaSystemController AppServerController { get; private set; }
|
|
||||||
|
|
||||||
public string MessagePath { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="codec"></param>
|
/// <param name="codec"></param>
|
||||||
public VideoCodecBaseMessenger(VideoCodecBase codec, string messagePath)
|
public VideoCodecBaseMessenger(VideoCodecBase codec, string messagePath) : base(messagePath)
|
||||||
{
|
{
|
||||||
if (codec == null)
|
if (codec == null)
|
||||||
throw new ArgumentNullException("codec");
|
throw new ArgumentNullException("codec");
|
||||||
if (string.IsNullOrEmpty(messagePath))
|
|
||||||
throw new ArgumentException("messagePath must not be empty or null");
|
|
||||||
|
|
||||||
MessagePath = messagePath;
|
|
||||||
Codec = codec;
|
Codec = codec;
|
||||||
codec.CallStatusChange += new EventHandler<CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
|
codec.CallStatusChange += new EventHandler<CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
|
||||||
codec.IsReadyChange += new EventHandler<EventArgs>(codec_IsReadyChange);
|
codec.IsReadyChange += new EventHandler<EventArgs>(codec_IsReadyChange);
|
||||||
@@ -77,16 +70,11 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registers this codec's messaging with an app server controller
|
/// Called from base's RegisterWithAppServer method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="appServerController"></param>
|
/// <param name="appServerController"></param>
|
||||||
public void RegisterWithAppServer(CotijaSystemController appServerController)
|
protected override void CustomRegisterWithAppServer(CotijaSystemController appServerController)
|
||||||
{
|
{
|
||||||
if (appServerController == null)
|
|
||||||
throw new ArgumentNullException("appServerController");
|
|
||||||
|
|
||||||
AppServerController = appServerController;
|
|
||||||
|
|
||||||
appServerController.AddAction("/device/videoCodec/isReady", new Action(SendIsReady));
|
appServerController.AddAction("/device/videoCodec/isReady", new Action(SendIsReady));
|
||||||
appServerController.AddAction("/device/videoCodec/fullStatus", new Action(SendVtcFullMessageObject));
|
appServerController.AddAction("/device/videoCodec/fullStatus", new Action(SendVtcFullMessageObject));
|
||||||
appServerController.AddAction("/device/videoCodec/dial", new Action<string>(s => Codec.Dial(s)));
|
appServerController.AddAction("/device/videoCodec/dial", new Action<string>(s => Codec.Dial(s)));
|
||||||
@@ -242,18 +230,5 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||||||
hasDirectory = Codec is IHasDirectory
|
hasDirectory = Codec is IHasDirectory
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Helper for posting status message
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="contentObject">The contents of the content object</param>
|
|
||||||
void PostStatusMessage(object contentObject)
|
|
||||||
{
|
|
||||||
AppServerController.SendMessageToServer(JObject.FromObject(new
|
|
||||||
{
|
|
||||||
type = MessagePath,
|
|
||||||
content = contentObject
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@ 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;
|
||||||
@@ -26,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>
|
||||||
@@ -60,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 +102,16 @@ namespace PepperDash.Essentials.Room.Cotija
|
|||||||
/// 71
|
/// 71
|
||||||
/// </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
|
||||||
@@ -145,6 +165,8 @@ namespace PepperDash.Essentials.Room.Cotija
|
|||||||
|
|
||||||
CotijaDdvc01DeviceBridge SourceBridge;
|
CotijaDdvc01DeviceBridge SourceBridge;
|
||||||
|
|
||||||
|
Ddvc01AtcMessenger AtcMessenger;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
@@ -182,6 +204,9 @@ namespace PepperDash.Essentials.Room.Cotija
|
|||||||
SetupFunctions();
|
SetupFunctions();
|
||||||
SetupFeedbacks();
|
SetupFeedbacks();
|
||||||
|
|
||||||
|
AtcMessenger = new Ddvc01AtcMessenger(EISC, "/device/audioCodec");
|
||||||
|
AtcMessenger.RegisterWithAppServer(Parent);
|
||||||
|
|
||||||
EISC.SigChange += EISC_SigChange;
|
EISC.SigChange += EISC_SigChange;
|
||||||
EISC.OnlineStatusChange += (o, a) =>
|
EISC.OnlineStatusChange += (o, a) =>
|
||||||
{
|
{
|
||||||
@@ -216,8 +241,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,6 +250,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));
|
||||||
|
|
||||||
@@ -238,6 +264,10 @@ namespace PepperDash.Essentials.Room.Cotija
|
|||||||
|
|
||||||
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/volumes/master/level", 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)));
|
||||||
@@ -250,20 +280,26 @@ namespace PepperDash.Essentials.Room.Cotija
|
|||||||
EISC.PulseBool(BoolJoin.ShutdownEnd)));
|
EISC.PulseBool(BoolJoin.ShutdownEnd)));
|
||||||
Parent.AddAction(@"/room/room1/shutdownCancel", new Action(() =>
|
Parent.AddAction(@"/room/room1/shutdownCancel", new Action(() =>
|
||||||
EISC.PulseBool(BoolJoin.ShutdownCancel)));
|
EISC.PulseBool(BoolJoin.ShutdownCancel)));
|
||||||
|
|
||||||
|
|
||||||
// Source Device (Current Source)'
|
|
||||||
|
|
||||||
SourceDeviceMapDictionary sourceJoinMap = new SourceDeviceMapDictionary();
|
|
||||||
|
|
||||||
var prefix = @"/device/currentSource/";
|
|
||||||
|
|
||||||
foreach (var item in sourceJoinMap)
|
|
||||||
{
|
|
||||||
Parent.AddAction(string.Format("{0}{1}", prefix, item.Key), new PressAndHoldAction(b => EISC.SetBool(item.Value, b)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <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>
|
||||||
@@ -345,11 +381,11 @@ namespace PepperDash.Essentials.Room.Cotija
|
|||||||
var version = Assembly.GetExecutingAssembly().GetName().Version;
|
var version = Assembly.GetExecutingAssembly().GetName().Version;
|
||||||
co.Info.RuntimeInfo.AssemblyVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
|
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<DeviceConfig>();
|
// always start fresh in case simpl changed
|
||||||
var rm = new DeviceConfig();
|
co.Rooms = new List<EssentialsRoomConfig>();
|
||||||
|
var rm = new EssentialsRoomConfig();
|
||||||
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");
|
||||||
@@ -388,6 +424,11 @@ 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;
|
||||||
|
|
||||||
@@ -403,7 +444,10 @@ namespace PepperDash.Essentials.Room.Cotija
|
|||||||
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);
|
||||||
@@ -422,6 +466,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);
|
||||||
@@ -430,6 +475,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);
|
||||||
|
|
||||||
@@ -447,10 +493,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;
|
||||||
@@ -462,6 +548,9 @@ namespace PepperDash.Essentials.Room.Cotija
|
|||||||
ConfigIsLoaded = true;
|
ConfigIsLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
void SendFullStatus()
|
void SendFullStatus()
|
||||||
{
|
{
|
||||||
if (ConfigIsLoaded)
|
if (ConfigIsLoaded)
|
||||||
@@ -585,86 +674,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);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,7 @@ namespace PepperDash.Essentials
|
|||||||
{
|
{
|
||||||
Parent.AddAction(string.Format(@"/room/{0}/volumes/master/level", Room.Key), new Action<ushort>(u =>
|
Parent.AddAction(string.Format(@"/room/{0}/volumes/master/level", Room.Key), new Action<ushort>(u =>
|
||||||
(volumeRoom.CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(u)));
|
(volumeRoom.CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(u)));
|
||||||
Parent.AddAction(string.Format(@"/room/{0}/volumes/master/mute", Room.Key), new Action(() =>
|
Parent.AddAction(string.Format(@"/room/{0}/volumes/master/muteToggle", Room.Key), new Action(() =>
|
||||||
volumeRoom.CurrentVolumeControls.MuteToggle()));
|
volumeRoom.CurrentVolumeControls.MuteToggle()));
|
||||||
volumeRoom.CurrentVolumeDeviceChange += new EventHandler<VolumeDeviceChangeEventArgs>(Room_CurrentVolumeDeviceChange);
|
volumeRoom.CurrentVolumeDeviceChange += new EventHandler<VolumeDeviceChangeEventArgs>(Room_CurrentVolumeDeviceChange);
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ namespace PepperDash.Essentials
|
|||||||
var currentVolumeDevice = volumeRoom.CurrentVolumeControls as IBasicVolumeWithFeedback;
|
var currentVolumeDevice = volumeRoom.CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||||
if (currentVolumeDevice != null)
|
if (currentVolumeDevice != null)
|
||||||
{
|
{
|
||||||
currentVolumeDevice.MuteFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
|
currentVolumeDevice.MuteFeedback.OutputChange += MuteFeedback_OutputChange;
|
||||||
currentVolumeDevice.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
|
currentVolumeDevice.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -470,8 +470,7 @@ namespace PepperDash.Essentials
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
return vtc;
|
return vtc;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ namespace PepperDash.Essentials
|
|||||||
// ConsoleAccessLevelEnum.AccessOperator);
|
// ConsoleAccessLevelEnum.AccessOperator);
|
||||||
|
|
||||||
// CrestronConsole.AddNewConsoleCommand(S => { ConfigWriter.WriteConfigFile(null); }, "writeconfig", "writes the current config to a file", 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 =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,348 +1,348 @@
|
|||||||
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 Crestron.SimplSharp.CrestronIO;
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
using Crestron.SimplSharpPro;
|
using Crestron.SimplSharpPro;
|
||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
using Crestron.SimplSharpPro.Fusion;
|
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.Core.Config;
|
||||||
using PepperDash.Essentials.Devices.Common;
|
using PepperDash.Essentials.Devices.Common;
|
||||||
using PepperDash.Essentials.Devices.Common.Occupancy;
|
using PepperDash.Essentials.Devices.Common.Occupancy;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Fusion
|
namespace PepperDash.Essentials.Fusion
|
||||||
{
|
{
|
||||||
public class EssentialsHuddleVtc1FusionController : EssentialsHuddleSpaceFusionSystemControllerBase
|
public class EssentialsHuddleVtc1FusionController : EssentialsHuddleSpaceFusionSystemControllerBase
|
||||||
{
|
{
|
||||||
BooleanSigData CodecIsInCall;
|
BooleanSigData CodecIsInCall;
|
||||||
|
|
||||||
public EssentialsHuddleVtc1FusionController(EssentialsHuddleVtc1Room room, uint ipId)
|
public EssentialsHuddleVtc1FusionController(EssentialsHuddleVtc1Room room, uint ipId)
|
||||||
: base(room, ipId)
|
: base(room, ipId)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called in base class constructor before RVI and GUID files are built
|
/// Called in base class constructor before RVI and GUID files are built
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void ExecuteCustomSteps()
|
protected override void ExecuteCustomSteps()
|
||||||
{
|
{
|
||||||
SetUpCodec();
|
SetUpCodec();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a static asset for the codec and maps the joins to the main room symbol
|
/// Creates a static asset for the codec and maps the joins to the main room symbol
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void SetUpCodec()
|
void SetUpCodec()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec;
|
var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec;
|
||||||
|
|
||||||
if (codec == null)
|
if (codec == null)
|
||||||
{
|
{
|
||||||
Debug.Console(1, this, "Cannot link codec to Fusion because codec is null");
|
Debug.Console(1, this, "Cannot link codec to Fusion because codec is null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
codec.UsageTracker = new UsageTracking(codec);
|
codec.UsageTracker = new UsageTracking(codec);
|
||||||
codec.UsageTracker.UsageIsTracked = true;
|
codec.UsageTracker.UsageIsTracked = true;
|
||||||
codec.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
|
codec.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
|
||||||
|
|
||||||
var codecPowerOnAction = new Action<bool>(b => { if (!b) codec.StandbyDeactivate(); });
|
var codecPowerOnAction = new Action<bool>(b => { if (!b) codec.StandbyDeactivate(); });
|
||||||
var codecPowerOffAction = new Action<bool>(b => { if (!b) codec.StandbyActivate(); });
|
var codecPowerOffAction = new Action<bool>(b => { if (!b) codec.StandbyActivate(); });
|
||||||
|
|
||||||
// Map FusionRoom Attributes:
|
// Map FusionRoom Attributes:
|
||||||
|
|
||||||
// Codec volume
|
// Codec volume
|
||||||
var codecVolume = FusionRoom.CreateOffsetUshortSig(50, "Volume - Fader01", eSigIoMask.InputOutputSig);
|
var codecVolume = FusionRoom.CreateOffsetUshortSig(50, "Volume - Fader01", eSigIoMask.InputOutputSig);
|
||||||
codecVolume.OutputSig.UserObject = new Action<ushort>(b => (codec as IBasicVolumeWithFeedback).SetVolume(b));
|
codecVolume.OutputSig.UserObject = new Action<ushort>(b => (codec as IBasicVolumeWithFeedback).SetVolume(b));
|
||||||
(codec as IBasicVolumeWithFeedback).VolumeLevelFeedback.LinkInputSig(codecVolume.InputSig);
|
(codec as IBasicVolumeWithFeedback).VolumeLevelFeedback.LinkInputSig(codecVolume.InputSig);
|
||||||
|
|
||||||
// In Call Status
|
// In Call Status
|
||||||
CodecIsInCall = FusionRoom.CreateOffsetBoolSig(69, "Conf - VC 1 In Call", eSigIoMask.InputSigOnly);
|
CodecIsInCall = FusionRoom.CreateOffsetBoolSig(69, "Conf - VC 1 In Call", eSigIoMask.InputSigOnly);
|
||||||
codec.CallStatusChange += new EventHandler<PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
|
codec.CallStatusChange += new EventHandler<PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
|
||||||
|
|
||||||
// Online status
|
// Online status
|
||||||
if (codec is ICommunicationMonitor)
|
if (codec is ICommunicationMonitor)
|
||||||
{
|
{
|
||||||
var c = codec as ICommunicationMonitor;
|
var c = codec as ICommunicationMonitor;
|
||||||
var codecOnline = FusionRoom.CreateOffsetBoolSig(122, "Online - VC 1", eSigIoMask.InputSigOnly);
|
var codecOnline = FusionRoom.CreateOffsetBoolSig(122, "Online - VC 1", eSigIoMask.InputSigOnly);
|
||||||
codecOnline.InputSig.BoolValue = c.CommunicationMonitor.Status == MonitorStatus.IsOk;
|
codecOnline.InputSig.BoolValue = c.CommunicationMonitor.Status == MonitorStatus.IsOk;
|
||||||
c.CommunicationMonitor.StatusChange += (o, a) =>
|
c.CommunicationMonitor.StatusChange += (o, a) =>
|
||||||
{
|
{
|
||||||
codecOnline.InputSig.BoolValue = a.Status == MonitorStatus.IsOk;
|
codecOnline.InputSig.BoolValue = a.Status == MonitorStatus.IsOk;
|
||||||
};
|
};
|
||||||
Debug.Console(0, this, "Linking '{0}' communication monitor to Fusion '{1}'", codec.Key, "Online - VC 1");
|
Debug.Console(0, this, "Linking '{0}' communication monitor to Fusion '{1}'", codec.Key, "Online - VC 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Codec IP Address
|
// Codec IP Address
|
||||||
bool codecHasIpInfo = false;
|
bool codecHasIpInfo = false;
|
||||||
var codecComm = codec.Communication;
|
var codecComm = codec.Communication;
|
||||||
|
|
||||||
string codecIpAddress = string.Empty;
|
string codecIpAddress = string.Empty;
|
||||||
int codecIpPort = 0;
|
int codecIpPort = 0;
|
||||||
|
|
||||||
StringSigData codecIpAddressSig;
|
StringSigData codecIpAddressSig;
|
||||||
StringSigData codecIpPortSig;
|
StringSigData codecIpPortSig;
|
||||||
|
|
||||||
if(codecComm is GenericSshClient)
|
if(codecComm is GenericSshClient)
|
||||||
{
|
{
|
||||||
codecIpAddress = (codecComm as GenericSshClient).Hostname;
|
codecIpAddress = (codecComm as GenericSshClient).Hostname;
|
||||||
codecIpPort = (codecComm as GenericSshClient).Port;
|
codecIpPort = (codecComm as GenericSshClient).Port;
|
||||||
codecHasIpInfo = true;
|
codecHasIpInfo = true;
|
||||||
}
|
}
|
||||||
else if (codecComm is GenericTcpIpClient)
|
else if (codecComm is GenericTcpIpClient)
|
||||||
{
|
{
|
||||||
codecIpAddress = (codecComm as GenericTcpIpClient).Hostname;
|
codecIpAddress = (codecComm as GenericTcpIpClient).Hostname;
|
||||||
codecIpPort = (codecComm as GenericTcpIpClient).Port;
|
codecIpPort = (codecComm as GenericTcpIpClient).Port;
|
||||||
codecHasIpInfo = true;
|
codecHasIpInfo = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (codecHasIpInfo)
|
if (codecHasIpInfo)
|
||||||
{
|
{
|
||||||
codecIpAddressSig = FusionRoom.CreateOffsetStringSig(121, "IP Address - VC", eSigIoMask.InputSigOnly);
|
codecIpAddressSig = FusionRoom.CreateOffsetStringSig(121, "IP Address - VC", eSigIoMask.InputSigOnly);
|
||||||
codecIpAddressSig.InputSig.StringValue = codecIpAddress;
|
codecIpAddressSig.InputSig.StringValue = codecIpAddress;
|
||||||
|
|
||||||
codecIpPortSig = FusionRoom.CreateOffsetStringSig(150, "IP Port - VC", eSigIoMask.InputSigOnly);
|
codecIpPortSig = FusionRoom.CreateOffsetStringSig(150, "IP Port - VC", eSigIoMask.InputSigOnly);
|
||||||
codecIpPortSig.InputSig.StringValue = codecIpPort.ToString();
|
codecIpPortSig.InputSig.StringValue = codecIpPort.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
var tempAsset = new FusionAsset();
|
var tempAsset = new FusionAsset();
|
||||||
|
|
||||||
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(c => c.Key.Equals(codec.Key));
|
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(c => c.Key.Equals(codec.Key));
|
||||||
|
|
||||||
if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
|
if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
|
||||||
{
|
{
|
||||||
tempAsset = FusionStaticAssets[deviceConfig.Uid];
|
tempAsset = FusionStaticAssets[deviceConfig.Uid];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Create a new asset
|
// Create a new asset
|
||||||
tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), codec.Name, "Codec", "");
|
tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), codec.Name, "Codec", "");
|
||||||
FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
|
FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
|
||||||
}
|
}
|
||||||
|
|
||||||
var codecAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
|
var codecAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
|
||||||
codecAsset.PowerOn.OutputSig.UserObject = codecPowerOnAction;
|
codecAsset.PowerOn.OutputSig.UserObject = codecPowerOnAction;
|
||||||
codecAsset.PowerOff.OutputSig.UserObject = codecPowerOffAction;
|
codecAsset.PowerOff.OutputSig.UserObject = codecPowerOffAction;
|
||||||
codec.StandbyIsOnFeedback.LinkComplementInputSig(codecAsset.PowerOn.InputSig);
|
codec.StandbyIsOnFeedback.LinkComplementInputSig(codecAsset.PowerOn.InputSig);
|
||||||
|
|
||||||
// TODO: Map relevant attributes on asset symbol
|
// TODO: Map relevant attributes on asset symbol
|
||||||
|
|
||||||
codecAsset.TrySetMakeModel(codec);
|
codecAsset.TrySetMakeModel(codec);
|
||||||
codecAsset.TryLinkAssetErrorToCommunication(codec);
|
codecAsset.TryLinkAssetErrorToCommunication(codec);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.Console(1, this, "Error setting up codec in Fusion: {0}", e);
|
Debug.Console(1, this, "Error setting up codec in Fusion: {0}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void codec_CallStatusChange(object sender, PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs e)
|
void codec_CallStatusChange(object sender, PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs e)
|
||||||
{
|
{
|
||||||
var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec;
|
var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec;
|
||||||
|
|
||||||
CodecIsInCall.InputSig.BoolValue = codec.IsInCall;
|
CodecIsInCall.InputSig.BoolValue = codec.IsInCall;
|
||||||
}
|
}
|
||||||
|
|
||||||
// These methods are overridden because they access the room class which is of a different type
|
// These methods are overridden because they access the room class which is of a different type
|
||||||
|
|
||||||
protected override void CreateSymbolAndBasicSigs(uint ipId)
|
protected override void CreateSymbolAndBasicSigs(uint ipId)
|
||||||
{
|
{
|
||||||
Debug.Console(1, this, "Creating Fusion Room symbol with GUID: {0}", RoomGuid);
|
Debug.Console(1, this, "Creating Fusion Room symbol with GUID: {0}", RoomGuid);
|
||||||
|
|
||||||
FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
|
FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
|
||||||
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();
|
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();
|
||||||
FusionRoom.ExtenderFusionRoomDataReservedSigs.Use();
|
FusionRoom.ExtenderFusionRoomDataReservedSigs.Use();
|
||||||
|
|
||||||
FusionRoom.Register();
|
FusionRoom.Register();
|
||||||
|
|
||||||
FusionRoom.FusionStateChange += FusionRoom_FusionStateChange;
|
FusionRoom.FusionStateChange += FusionRoom_FusionStateChange;
|
||||||
|
|
||||||
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.DeviceExtenderSigChange += FusionRoomSchedule_DeviceExtenderSigChange;
|
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.DeviceExtenderSigChange += FusionRoomSchedule_DeviceExtenderSigChange;
|
||||||
FusionRoom.ExtenderFusionRoomDataReservedSigs.DeviceExtenderSigChange += ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange;
|
FusionRoom.ExtenderFusionRoomDataReservedSigs.DeviceExtenderSigChange += ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange;
|
||||||
FusionRoom.OnlineStatusChange += FusionRoom_OnlineStatusChange;
|
FusionRoom.OnlineStatusChange += FusionRoom_OnlineStatusChange;
|
||||||
|
|
||||||
CrestronConsole.AddNewConsoleCommand(RequestFullRoomSchedule, "FusReqRoomSchedule", "Requests schedule of the room for the next 24 hours", ConsoleAccessLevelEnum.AccessOperator);
|
CrestronConsole.AddNewConsoleCommand(RequestFullRoomSchedule, "FusReqRoomSchedule", "Requests schedule of the room for the next 24 hours", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
CrestronConsole.AddNewConsoleCommand(ModifyMeetingEndTimeConsoleHelper, "FusReqRoomSchMod", "Ends or extends a meeting by the specified time", ConsoleAccessLevelEnum.AccessOperator);
|
CrestronConsole.AddNewConsoleCommand(ModifyMeetingEndTimeConsoleHelper, "FusReqRoomSchMod", "Ends or extends a meeting by the specified time", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
CrestronConsole.AddNewConsoleCommand(CreateAsHocMeeting, "FusCreateMeeting", "Creates and Ad Hoc meeting for on hour or until the next meeting", ConsoleAccessLevelEnum.AccessOperator);
|
CrestronConsole.AddNewConsoleCommand(CreateAsHocMeeting, "FusCreateMeeting", "Creates and Ad Hoc meeting for on hour or until the next meeting", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
|
|
||||||
// Room to fusion room
|
// Room to fusion room
|
||||||
Room.OnFeedback.LinkInputSig(FusionRoom.SystemPowerOn.InputSig);
|
Room.OnFeedback.LinkInputSig(FusionRoom.SystemPowerOn.InputSig);
|
||||||
|
|
||||||
// Moved to
|
// Moved to
|
||||||
CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(84, "Display 1 - Current Source", eSigIoMask.InputSigOnly);
|
CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(84, "Display 1 - Current Source", eSigIoMask.InputSigOnly);
|
||||||
// Don't think we need to get current status of this as nothing should be alive yet.
|
// Don't think we need to get current status of this as nothing should be alive yet.
|
||||||
(Room as EssentialsHuddleVtc1Room).CurrentSingleSourceChange += Room_CurrentSourceInfoChange;
|
(Room as EssentialsHuddleVtc1Room).CurrentSingleSourceChange += Room_CurrentSourceInfoChange;
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
|
||||||
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
|
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void SetUpSources()
|
protected override void SetUpSources()
|
||||||
{
|
{
|
||||||
// Sources
|
// Sources
|
||||||
var dict = ConfigReader.ConfigObject.GetSourceListForKey((Room as EssentialsHuddleVtc1Room).SourceListKey);
|
var dict = ConfigReader.ConfigObject.GetSourceListForKey((Room as EssentialsHuddleVtc1Room).SourceListKey);
|
||||||
if (dict != null)
|
if (dict != null)
|
||||||
{
|
{
|
||||||
// NEW PROCESS:
|
// NEW PROCESS:
|
||||||
// Make these lists and insert the fusion attributes by iterating these
|
// Make these lists and insert the fusion attributes by iterating these
|
||||||
var setTopBoxes = dict.Where(d => d.Value.SourceDevice is ISetTopBoxControls);
|
var setTopBoxes = dict.Where(d => d.Value.SourceDevice is ISetTopBoxControls);
|
||||||
uint i = 1;
|
uint i = 1;
|
||||||
foreach (var kvp in setTopBoxes)
|
foreach (var kvp in setTopBoxes)
|
||||||
{
|
{
|
||||||
TryAddRouteActionSigs("Display 1 - Source TV " + i, 188 + i, kvp.Key, kvp.Value.SourceDevice);
|
TryAddRouteActionSigs("Display 1 - Source TV " + i, 188 + i, kvp.Key, kvp.Value.SourceDevice);
|
||||||
i++;
|
i++;
|
||||||
if (i > 5) // We only have five spots
|
if (i > 5) // We only have five spots
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var discPlayers = dict.Where(d => d.Value.SourceDevice is IDiscPlayerControls);
|
var discPlayers = dict.Where(d => d.Value.SourceDevice is IDiscPlayerControls);
|
||||||
i = 1;
|
i = 1;
|
||||||
foreach (var kvp in discPlayers)
|
foreach (var kvp in discPlayers)
|
||||||
{
|
{
|
||||||
TryAddRouteActionSigs("Display 1 - Source DVD " + i, 181 + i, kvp.Key, kvp.Value.SourceDevice);
|
TryAddRouteActionSigs("Display 1 - Source DVD " + i, 181 + i, kvp.Key, kvp.Value.SourceDevice);
|
||||||
i++;
|
i++;
|
||||||
if (i > 5) // We only have five spots
|
if (i > 5) // We only have five spots
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var laptops = dict.Where(d => d.Value.SourceDevice is Laptop);
|
var laptops = dict.Where(d => d.Value.SourceDevice is Laptop);
|
||||||
i = 1;
|
i = 1;
|
||||||
foreach (var kvp in laptops)
|
foreach (var kvp in laptops)
|
||||||
{
|
{
|
||||||
TryAddRouteActionSigs("Display 1 - Source Laptop " + i, 166 + i, kvp.Key, kvp.Value.SourceDevice);
|
TryAddRouteActionSigs("Display 1 - Source Laptop " + i, 166 + i, kvp.Key, kvp.Value.SourceDevice);
|
||||||
i++;
|
i++;
|
||||||
if (i > 10) // We only have ten spots???
|
if (i > 10) // We only have ten spots???
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var kvp in dict)
|
foreach (var kvp in dict)
|
||||||
{
|
{
|
||||||
var usageDevice = kvp.Value.SourceDevice as IUsageTracking;
|
var usageDevice = kvp.Value.SourceDevice as IUsageTracking;
|
||||||
|
|
||||||
if (usageDevice != null)
|
if (usageDevice != null)
|
||||||
{
|
{
|
||||||
usageDevice.UsageTracker = new UsageTracking(usageDevice as Device);
|
usageDevice.UsageTracker = new UsageTracking(usageDevice as Device);
|
||||||
usageDevice.UsageTracker.UsageIsTracked = true;
|
usageDevice.UsageTracker.UsageIsTracked = true;
|
||||||
usageDevice.UsageTracker.DeviceUsageEnded += new EventHandler<DeviceUsageEventArgs>(UsageTracker_DeviceUsageEnded);
|
usageDevice.UsageTracker.DeviceUsageEnded += new EventHandler<DeviceUsageEventArgs>(UsageTracker_DeviceUsageEnded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Console(1, this, "WARNING: Config source list '{0}' not found for room '{1}'",
|
Debug.Console(1, this, "WARNING: Config source list '{0}' not found for room '{1}'",
|
||||||
(Room as EssentialsHuddleVtc1Room).SourceListKey, Room.Key);
|
(Room as EssentialsHuddleVtc1Room).SourceListKey, Room.Key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void SetUpDisplay()
|
protected override void SetUpDisplay()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//Setup Display Usage Monitoring
|
//Setup Display Usage Monitoring
|
||||||
|
|
||||||
var displays = DeviceManager.AllDevices.Where(d => d is DisplayBase);
|
var displays = DeviceManager.AllDevices.Where(d => d is DisplayBase);
|
||||||
|
|
||||||
// Consider updating this in multiple display systems
|
// Consider updating this in multiple display systems
|
||||||
|
|
||||||
foreach (DisplayBase display in displays)
|
foreach (DisplayBase display in displays)
|
||||||
{
|
{
|
||||||
display.UsageTracker = new UsageTracking(display);
|
display.UsageTracker = new UsageTracking(display);
|
||||||
display.UsageTracker.UsageIsTracked = true;
|
display.UsageTracker.UsageIsTracked = true;
|
||||||
display.UsageTracker.DeviceUsageEnded += new EventHandler<DeviceUsageEventArgs>(UsageTracker_DeviceUsageEnded);
|
display.UsageTracker.DeviceUsageEnded += new EventHandler<DeviceUsageEventArgs>(UsageTracker_DeviceUsageEnded);
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultDisplay = (Room as EssentialsHuddleVtc1Room).DefaultDisplay as DisplayBase;
|
var defaultDisplay = (Room as EssentialsHuddleVtc1Room).DefaultDisplay as DisplayBase;
|
||||||
if (defaultDisplay == null)
|
if (defaultDisplay == null)
|
||||||
{
|
{
|
||||||
Debug.Console(1, this, "Cannot link null display to Fusion because default display is null");
|
Debug.Console(1, this, "Cannot link null display to Fusion because default display is null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var dispPowerOnAction = new Action<bool>(b => { if (!b) defaultDisplay.PowerOn(); });
|
var dispPowerOnAction = new Action<bool>(b => { if (!b) defaultDisplay.PowerOn(); });
|
||||||
var dispPowerOffAction = new Action<bool>(b => { if (!b) defaultDisplay.PowerOff(); });
|
var dispPowerOffAction = new Action<bool>(b => { if (!b) defaultDisplay.PowerOff(); });
|
||||||
|
|
||||||
// Display to fusion room sigs
|
// Display to fusion room sigs
|
||||||
FusionRoom.DisplayPowerOn.OutputSig.UserObject = dispPowerOnAction;
|
FusionRoom.DisplayPowerOn.OutputSig.UserObject = dispPowerOnAction;
|
||||||
FusionRoom.DisplayPowerOff.OutputSig.UserObject = dispPowerOffAction;
|
FusionRoom.DisplayPowerOff.OutputSig.UserObject = dispPowerOffAction;
|
||||||
defaultDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
|
defaultDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
|
||||||
if (defaultDisplay is IDisplayUsage)
|
if (defaultDisplay is IDisplayUsage)
|
||||||
(defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
|
(defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MapDisplayToRoomJoins(1, 158, defaultDisplay);
|
MapDisplayToRoomJoins(1, 158, defaultDisplay);
|
||||||
|
|
||||||
|
|
||||||
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key));
|
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key));
|
||||||
|
|
||||||
//Check for existing asset in GUIDs collection
|
//Check for existing asset in GUIDs collection
|
||||||
|
|
||||||
var tempAsset = new FusionAsset();
|
var tempAsset = new FusionAsset();
|
||||||
|
|
||||||
if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
|
if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
|
||||||
{
|
{
|
||||||
tempAsset = FusionStaticAssets[deviceConfig.Uid];
|
tempAsset = FusionStaticAssets[deviceConfig.Uid];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Create a new asset
|
// Create a new asset
|
||||||
tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), defaultDisplay.Name, "Display", "");
|
tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), defaultDisplay.Name, "Display", "");
|
||||||
FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
|
FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
|
var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
|
||||||
dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
|
dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
|
||||||
dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
|
dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
|
||||||
defaultDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
|
defaultDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
|
||||||
// NO!! display.PowerIsOn.LinkComplementInputSig(dispAsset.PowerOff.InputSig);
|
// NO!! display.PowerIsOn.LinkComplementInputSig(dispAsset.PowerOff.InputSig);
|
||||||
// Use extension methods
|
// Use extension methods
|
||||||
dispAsset.TrySetMakeModel(defaultDisplay);
|
dispAsset.TrySetMakeModel(defaultDisplay);
|
||||||
dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay);
|
dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.Console(1, this, "Error setting up display in Fusion: {0}", e);
|
Debug.Console(1, this, "Error setting up display in Fusion: {0}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void MapDisplayToRoomJoins(int displayIndex, int joinOffset, DisplayBase display)
|
protected override void MapDisplayToRoomJoins(int displayIndex, int joinOffset, DisplayBase display)
|
||||||
{
|
{
|
||||||
string displayName = string.Format("Display {0} - ", displayIndex);
|
string displayName = string.Format("Display {0} - ", displayIndex);
|
||||||
|
|
||||||
|
|
||||||
if (display == (Room as EssentialsHuddleVtc1Room).DefaultDisplay)
|
if (display == (Room as EssentialsHuddleVtc1Room).DefaultDisplay)
|
||||||
{
|
{
|
||||||
// Power on
|
// Power on
|
||||||
var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig);
|
var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig);
|
||||||
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b => { if (!b) display.PowerOn(); });
|
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b => { if (!b) display.PowerOn(); });
|
||||||
display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
|
display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
|
||||||
|
|
||||||
// Power Off
|
// Power Off
|
||||||
var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off", eSigIoMask.InputOutputSig);
|
var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off", eSigIoMask.InputOutputSig);
|
||||||
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b => { if (!b) display.PowerOff(); }); ;
|
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b => { if (!b) display.PowerOff(); }); ;
|
||||||
display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
|
display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
|
||||||
|
|
||||||
// Current Source
|
// Current Source
|
||||||
var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig);
|
var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig);
|
||||||
defaultDisplaySourceNone.OutputSig.UserObject = new Action<bool>(b => { if (!b) (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff"); }); ;
|
defaultDisplaySourceNone.OutputSig.UserObject = new Action<bool>(b => { if (!b) (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff"); }); ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,6 +108,8 @@
|
|||||||
<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\VideoCodecBaseMessenger.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" />
|
||||||
|
|||||||
@@ -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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user