diff --git a/PepperDashEssentials/AppServer/CotijaSystemController.cs b/PepperDashEssentials/AppServer/CotijaSystemController.cs
index 70beec0e..00f3ef5b 100644
--- a/PepperDashEssentials/AppServer/CotijaSystemController.cs
+++ b/PepperDashEssentials/AppServer/CotijaSystemController.cs
@@ -15,7 +15,6 @@ using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Essentials.Core;
-using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Room.Cotija;
namespace PepperDash.Essentials
@@ -24,6 +23,8 @@ namespace PepperDash.Essentials
{
WebSocketClient WSClient;
+ //bool LinkUp;
+
///
/// Prevents post operations from stomping on each other and getting lost
///
@@ -83,12 +84,33 @@ namespace PepperDash.Essentials
CrestronConsole.AddNewConsoleCommand(TestHttpRequest,
"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.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler);
+
}
+ ///
+ ///
+ ///
+ ///
+ 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();
+ }
+ }
+
///
/// Sends message to server to indicate the system is shutting down
///
@@ -97,11 +119,7 @@ namespace PepperDash.Essentials
{
if (programEventType == eProgramStatusEventType.Stopping && WSClient.Connected)
{
- SendMessageToServer(JObject.FromObject( new
- {
- type = "/system/close"
- }));
-
+ CleanUpWebsocketClient();
}
}
@@ -158,6 +176,7 @@ namespace PepperDash.Essentials
else
{
Debug.Console(0, this, "Adding room bridge and sending configuration");
+ SystemUuid = ConfigReader.ConfigObject.SystemUuid;
RegisterSystemToServer();
}
}
@@ -170,6 +189,7 @@ namespace PepperDash.Essentials
void bridge_ConfigurationIsReady(object sender, EventArgs e)
{
Debug.Console(1, this, "Bridge ready. Registering");
+ SystemUuid = ConfigReader.ConfigObject.SystemUuid;
// send the configuration object to the server
RegisterSystemToServer();
}
@@ -189,6 +209,8 @@ namespace PepperDash.Essentials
///
void AuthorizeSystem(string code)
{
+ SystemUuid = ConfigReader.ConfigObject.SystemUuid;
+
if (string.IsNullOrEmpty(SystemUuid))
{
CrestronConsole.ConsoleCommandResponse("System does not have a UUID. Please ensure proper portal-format configuration is loaded and restart.");
@@ -221,6 +243,7 @@ namespace PepperDash.Essentials
if (r.Code == 200)
{
Debug.Console(0, "System authorized, sending config.");
+#warning This registration may need to wait for config ready. Maybe.
RegisterSystemToServer();
}
else if (r.Code == 404)
@@ -281,58 +304,104 @@ namespace PepperDash.Essentials
/// URL of the server, including the port number, if not 80. Format: "serverUrlOrIp:port"
void RegisterSystemToServer()
{
-
-
- var ready = RegisterLockEvent.Wait(20000);
- if (!ready)
- {
- Debug.Console(1, this, "RegisterSystemToServer failed to enter after 20 seconds. Ignoring");
- return;
- }
- RegisterLockEvent.Reset();
-
- try
- {
- var confObject = ConfigReader.ConfigObject;
- confObject.Info.RuntimeInfo.AppName = Assembly.GetExecutingAssembly().GetName().Name;
- var version = Assembly.GetExecutingAssembly().GetName().Version;
- confObject.Info.RuntimeInfo.AssemblyVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
-
- 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();
- }
-
+ ConnectWebsocketClient();
}
+ ///
+ /// Connects the Websocket Client
+ ///
+ ///
+ 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();
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ 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;
+ }
+
+ ///
+ /// After a "hello" from the server, sends config and stuff
+ ///
+ 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);
+ }
+
+ ///
+ /// Sends any object type to server
+ ///
+ ///
+ public void SendMessageObjectToServer(object o)
+ {
+ SendMessageToServer(JObject.FromObject(o));
+ }
+
///
/// Sends a message to the server from a room
///
@@ -340,78 +409,67 @@ namespace PepperDash.Essentials
/// object to be serialized and sent in post body
public void SendMessageToServer(JObject o)
{
-
if (WSClient != null && WSClient.Connected)
{
string message = JsonConvert.SerializeObject(o, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
Debug.Console(1, this, "Message TX: {0}", message);
var messageBytes = System.Text.Encoding.UTF8.GetBytes(message);
- WSClient.Send(messageBytes, (uint)messageBytes.Length, WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME);
- //WSClient.SendAsync(messageBytes, (uint)messageBytes.Length, WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME);
+ var result = WSClient.Send(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}");
+ }
}
///
/// Disconnects the SSE Client and stops the heartbeat timer
///
///
- void DisconnectStreamClient(string command)
+ void CleanUpWebsocketClient()
{
- //if(SseClient != null)
- // SseClient.Disconnect();
-
- if (WSClient != null && WSClient.Connected)
- WSClient.Disconnect();
-
- if (ServerHeartbeatCheckTimer != null)
- {
- ServerHeartbeatCheckTimer.Stop();
-
- ServerHeartbeatCheckTimer = null;
- }
+ Debug.Console(1, this, "Disconnecting websocket");
+ if (WSClient != null)
+ {
+ WSClient.SendCallBack = null;
+ WSClient.ReceiveCallBack = null;
+ WSClient.ConnectionCallBack = null;
+ WSClient.DisconnectCallBack = null;
+ if (WSClient.Connected)
+ {
+ WSClient.Disconnect();
+ }
+ WSClient = null;
+ }
}
-
- ///
- /// The callback that fires when we get a response from our registration attempt
- ///
- ///
- ///
- void RegistrationConnectionCallback(HttpClientResponse resp, HTTP_CALLBACK_ERROR err)
- {
- CheckHttpDebug(resp, err);
- Debug.Console(1, this, "RegistrationConnectionCallback: {0}", err);
- try
- {
- if (resp != null && resp.Code == 200)
- {
- if(ServerReconnectTimer != null)
- {
- ServerReconnectTimer.Stop();
- ServerReconnectTimer = null;
- }
- // Success here!
- ConnectStreamClient();
- }
- else
- {
- if (resp != null)
- Debug.Console(1, this, "Response from server: {0}\n{1}", resp.Code, err);
- else
- {
- Debug.Console(1, this, "Null response received from server.");
- }
- StartReconnectTimer();
- }
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "Error Initializing Stream Client: {0}", e);
- StartReconnectTimer();
- }
- RegisterLockEvent.Set();
- }
+ ///
+ ///
+ ///
+ ///
+ ///
+ void StartServerReconnectTimer()
+ {
+ StopServerReconnectTimer();
+ ServerReconnectTimer = new CTimer(ReconnectToServerTimerCallback, ServerReconnectInterval);
+ Debug.Console(1, this, "Reconnect Timer Started.");
+ }
+
+ ///
+ /// Does what it says
+ ///
+ void StopServerReconnectTimer()
+ {
+ if (ServerReconnectTimer != null)
+ {
+ ServerReconnectTimer.Stop();
+ ServerReconnectTimer = null;
+ }
+ }
///
/// Executes when we don't get a heartbeat message in time. Triggers reconnect.
@@ -425,23 +483,8 @@ namespace PepperDash.Essentials
ServerHeartbeatCheckTimer.Stop();
ServerHeartbeatCheckTimer = null;
}
- StartReconnectTimer();
- }
-
- ///
- ///
- ///
- ///
- ///
- 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);
+ CleanUpWebsocketClient();
+ StartServerReconnectTimer();
}
///
@@ -451,37 +494,42 @@ namespace PepperDash.Essentials
///
void ResetOrStartHearbeatTimer()
{
- if (ServerHeartbeatCheckTimer == null)
- {
- ServerHeartbeatCheckTimer = new CTimer(HeartbeatExpiredTimerCallback, null, ServerHeartbeatInterval, ServerHeartbeatInterval);
-
- Debug.Console(1, this, "Heartbeat Timer Started.");
- }
-
- ServerHeartbeatCheckTimer.Reset(ServerHeartbeatInterval, ServerHeartbeatInterval);
- }
-
-
- ///
- /// Connects the SSE Client
- ///
- ///
- void ConnectStreamClient()
- {
- Debug.Console(0, this, "Initializing Stream client to server.");
-
- if (WSClient == null)
+ if (ServerHeartbeatCheckTimer == 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();
}
+ ///
+ /// Waits two and goes again
+ ///
+ void ReconnectStreamClient()
+ {
+ new CTimer(o => ConnectWebsocketClient(), 2000);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ 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;
+ }
+
+
///
/// Resets reconnect timer and updates usercode
///
@@ -514,12 +562,26 @@ namespace PepperDash.Essentials
{
if (HttpDebugEnabled)
{
- Debug.Console(0, this, "------ Begin HTTP Debug ---------------------------------------");
- Debug.Console(0, this, "HTTP Response URL: {0}", r.ResponseUrl.ToString());
- Debug.Console(0, this, "HTTP Response 'error' {0}", e);
- Debug.Console(0, this, "HTTP Response code: {0}", r.Code);
- Debug.Console(0, this, "HTTP Response content: \r{0}", r.ContentString);
- Debug.Console(0, this, "------ End HTTP Debug -----------------------------------------");
+ try
+ {
+ Debug.Console(0, this, "------ Begin HTTP Debug ---------------------------------------");
+ if (r != null)
+ {
+ 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
///
///
///
- 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)
{
- var rx = System.Text.Encoding.UTF8.GetString(data, 0, (int)length);
- if(rx.Length > 0)
- ParseStreamRx(rx);
- WSClient.ReceiveAsync();
- return 1;
+ if (opcode == WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME)
+ {
+ var rx = System.Text.Encoding.UTF8.GetString(data, 0, (int)length);
+ if (rx.Length > 0)
+ 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;
}
///
@@ -545,11 +621,11 @@ namespace PepperDash.Essentials
///
///
///
- 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);
-
- return 1;
+ if(result != WebSocketClient.WEBSOCKET_RESULT_CODES.WEBSOCKET_CLIENT_SUCCESS)
+ Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "SendCallback questionable result: {0}", result);
+ return 1;
}
///
@@ -562,7 +638,7 @@ namespace PepperDash.Essentials
if(string.IsNullOrEmpty(message))
return;
- Debug.Console(1, this, "Message RX: '{0}'", message);
+ Debug.Console(1, this, "Message RX: {0}", message);
try
{
var messageObj = JObject.Parse(message);
@@ -571,6 +647,7 @@ namespace PepperDash.Essentials
if (type == "hello")
{
+ SendInitialMessage();
ResetOrStartHearbeatTimer();
}
else if (type == "/system/heartbeat")
@@ -579,11 +656,11 @@ namespace PepperDash.Essentials
}
else if (type == "close")
{
- WSClient.Disconnect();
+ Debug.Console(1, this, "Received close message from server.");
+ // DisconnectWebsocketClient();
- ServerHeartbeatCheckTimer.Stop();
- // Start the reconnect timer
- StartReconnectTimer();
+ if (ServerHeartbeatCheckTimer != null)
+ ServerHeartbeatCheckTimer.Stop();
}
else
{
@@ -620,7 +697,7 @@ namespace PepperDash.Essentials
}
case "held":
{
- if (!PushedActions.ContainsKey(type))
+ if (PushedActions.ContainsKey(type))
{
PushedActions[type].Reset(ButtonHeartbeatInterval, ButtonHeartbeatInterval);
}
diff --git a/PepperDashEssentials/AppServer/Messengers/AtcDdvc01Messenger.cs b/PepperDashEssentials/AppServer/Messengers/AtcDdvc01Messenger.cs
new file mode 100644
index 00000000..882ad317
--- /dev/null
+++ b/PepperDashEssentials/AppServer/Messengers/AtcDdvc01Messenger.cs
@@ -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;
+
+ ///
+ /// 201
+ ///
+ const uint SCurrentDialString = 201;
+ ///
+ /// 211
+ ///
+ const uint SCurrentCallString = 211;
+ ///
+ /// 221
+ ///
+ const uint SHookState = 221;
+
+ ///
+ ///
+ ///
+ Dictionary DTMFMap = new Dictionary
+ {
+ { "1", 201 },
+ { "2", 202 },
+ { "3", 203 },
+ { "4", 204 },
+ { "5", 205 },
+ { "6", 206 },
+ { "7", 207 },
+ { "8", 208 },
+ { "9", 209 },
+ { "0", 210 },
+ { "*", 211 },
+ { "#", 212 },
+ };
+
+ CodecActiveCallItem CurrentCallItem;
+
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Ddvc01AtcMessenger(BasicTriList eisc, string messagePath)
+ : base(messagePath)
+ {
+ EISC = eisc;
+
+ CurrentCallItem = new CodecActiveCallItem();
+ CurrentCallItem.Type = eCodecCallType.Audio;
+ CurrentCallItem.Id = "-audio-";
+ }
+
+ ///
+ ///
+ ///
+ void SendFullStatus()
+ {
+ this.PostStatusMessage(new
+ {
+ calls = GetCurrentCallList(),
+ callStatus = EISC.GetString(SHookState),
+ currentCallString = EISC.GetString(SCurrentCallString),
+ currentDialString = EISC.GetString(SCurrentDialString),
+ });
+ }
+
+ ///
+ ///
+ ///
+ ///
+ protected override void CustomRegisterWithAppServer(CotijaSystemController appServerController)
+ {
+ Action
public const uint RoomIsOn = 301;
+ ///
+ /// 41
+ ///
+ public const uint PromptForCode = 41;
+ ///
+ /// 42
+ ///
+ public const uint ClientJoined = 42;
///
/// 51
///
@@ -60,14 +69,15 @@ namespace PepperDash.Essentials.Room.Cotija
/// 63
///
public const uint ShutdownStart = 63;
-
-
-
///
/// 72
///
public const uint SourceHasChanged = 72;
///
+ /// 261 - The start of the range of speed dial visibles
+ ///
+ public const uint SpeedDialVisibleStartJoin = 261;
+ ///
/// 501
///
public const uint ConfigIsReady = 501;
@@ -92,6 +102,16 @@ namespace PepperDash.Essentials.Room.Cotija
/// 71
///
public const uint SelectedSourceKey = 71;
+
+ ///
+ /// 241
+ ///
+ public const uint SpeedDialNameStartJoin = 241;
+
+ ///
+ /// 251
+ ///
+ public const uint SpeedDialNumberStartJoin = 251;
///
/// 501
@@ -145,6 +165,8 @@ namespace PepperDash.Essentials.Room.Cotija
CotijaDdvc01DeviceBridge SourceBridge;
+ Ddvc01AtcMessenger AtcMessenger;
+
///
///
@@ -182,6 +204,9 @@ namespace PepperDash.Essentials.Room.Cotija
SetupFunctions();
SetupFeedbacks();
+ AtcMessenger = new Ddvc01AtcMessenger(EISC, "/device/audioCodec");
+ AtcMessenger.RegisterWithAppServer(Parent);
+
EISC.SigChange += EISC_SigChange;
EISC.OnlineStatusChange += (o, a) =>
{
@@ -216,8 +241,6 @@ namespace PepperDash.Essentials.Room.Cotija
}
}, "mobilebridgedump", "Dumps DDVC01 bridge EISC data b,u,s", ConsoleAccessLevelEnum.AccessOperator);
- CrestronConsole.AddNewConsoleCommand(s => LoadConfigValues(), "loadddvc", "", ConsoleAccessLevelEnum.AccessOperator);
-
return base.CustomActivate();
}
@@ -227,6 +250,9 @@ namespace PepperDash.Essentials.Room.Cotija
///
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));
@@ -238,6 +264,10 @@ namespace PepperDash.Essentials.Room.Cotija
Parent.AddAction(@"/room/room1/defaultsource", new Action(() =>
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(u =>
EISC.SetUshort(UshortJoin.MasterVolumeLevel, u)));
@@ -250,20 +280,26 @@ namespace PepperDash.Essentials.Room.Cotija
EISC.PulseBool(BoolJoin.ShutdownEnd)));
Parent.AddAction(@"/room/room1/shutdownCancel", new Action(() =>
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)));
- }
}
+ ///
+ ///
+ ///
+ ///
+ 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)));
+ }
+ }
+
+
///
/// Links feedbacks to whatever is gonna happen!
///
@@ -345,11 +381,11 @@ namespace PepperDash.Essentials.Room.Cotija
var version = Assembly.GetExecutingAssembly().GetName().Version;
co.Info.RuntimeInfo.AssemblyVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
-
//Room
- if (co.Rooms == null)
- co.Rooms = new List();
- var rm = new DeviceConfig();
+ //if (co.Rooms == null)
+ // always start fresh in case simpl changed
+ co.Rooms = new List();
+ var rm = new EssentialsRoomConfig();
if (co.Rooms.Count == 0)
{
Debug.Console(0, this, "Adding room to config");
@@ -388,6 +424,11 @@ namespace PepperDash.Essentials.Room.Cotija
var name = EISC.StringOutput[i + 1].StringValue;
rmProps.SpeedDials.Add(new DDVC01SpeedDial { Number = num, Name = name});
}
+
+ // This MAY need a check
+ rmProps.AudioCodecKey = "audioCodec";
+ rmProps.VideoCodecKey = null; // "videoCodec";
+
// volume control names
var volCount = EISC.UShortOutput[701].UShortValue;
@@ -403,7 +444,10 @@ namespace PepperDash.Essentials.Room.Cotija
co.Devices = new List();
// 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";
rm.Properties = JToken.FromObject(rmProps);
@@ -422,6 +466,7 @@ namespace PepperDash.Essentials.Room.Cotija
break;
var icon = EISC.StringOutput[651 + i].StringValue;
var key = EISC.StringOutput[671 + i].StringValue;
+
var type = EISC.StringOutput[701 + i].StringValue;
Debug.Console(0, this, "Adding source {0} '{1}'", key, name);
@@ -430,6 +475,7 @@ namespace PepperDash.Essentials.Room.Cotija
Name = name,
Order = (int)i + 1,
SourceKey = key,
+ Type = eSourceListItemType.Route
};
newSl.Add(key, newSLI);
@@ -447,10 +493,50 @@ namespace PepperDash.Essentials.Room.Cotija
Type = type
};
co.Devices.Add(devConf);
+
+ if (group.ToLower().StartsWith("settopbox")) // Add others here as needed
+ {
+ SetupSourceFunctions(key);
+ }
}
co.SourceLists.Add("default", newSl);
+ // build "audioCodec" config if we need
+ if (!string.IsNullOrEmpty(rmProps.AudioCodecKey))
+ {
+ var acFavs = new List();
+ 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));
var handler = ConfigurationIsReady;
@@ -462,6 +548,9 @@ namespace PepperDash.Essentials.Room.Cotija
ConfigIsLoaded = true;
}
+ ///
+ ///
+ ///
void SendFullStatus()
{
if (ConfigIsLoaded)
@@ -585,86 +674,5 @@ namespace PepperDash.Essentials.Room.Cotija
EISC.StringInput[StringJoin.UserCodeToSystem].StringValue = UserCode;
EISC.StringInput[StringJoin.ServerUrl].StringValue = Parent.Config.ClientAppUrl;
}
-
- ///
- ///
- ///
- ///
- ///
- 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);
- // }
- //}
- }
}
}
\ No newline at end of file
diff --git a/PepperDashEssentials/AppServer/RoomBridges/CotijaEssentialsHuddleSpaceRoomBridge.cs b/PepperDashEssentials/AppServer/RoomBridges/CotijaEssentialsHuddleSpaceRoomBridge.cs
index 24f2340a..35acefc6 100644
--- a/PepperDashEssentials/AppServer/RoomBridges/CotijaEssentialsHuddleSpaceRoomBridge.cs
+++ b/PepperDashEssentials/AppServer/RoomBridges/CotijaEssentialsHuddleSpaceRoomBridge.cs
@@ -74,7 +74,7 @@ namespace PepperDash.Essentials
{
Parent.AddAction(string.Format(@"/room/{0}/volumes/master/level", Room.Key), new Action(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.CurrentVolumeDeviceChange += new EventHandler(Room_CurrentVolumeDeviceChange);
@@ -82,7 +82,7 @@ namespace PepperDash.Essentials
var currentVolumeDevice = volumeRoom.CurrentVolumeControls as IBasicVolumeWithFeedback;
if (currentVolumeDevice != null)
{
- currentVolumeDevice.MuteFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
+ currentVolumeDevice.MuteFeedback.OutputChange += MuteFeedback_OutputChange;
currentVolumeDevice.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
}
}
@@ -470,8 +470,7 @@ namespace PepperDash.Essentials
};
}
return vtc;
- }
-
+ }
}
///
diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs
index 8c28a48c..660d8311 100644
--- a/PepperDashEssentials/ControlSystem.cs
+++ b/PepperDashEssentials/ControlSystem.cs
@@ -42,6 +42,10 @@ namespace PepperDash.Essentials
// 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 =>
{
diff --git a/PepperDashEssentials/ControlSystem.cs.orig b/PepperDashEssentials/ControlSystem.cs.orig
deleted file mode 100644
index bd9590c4..00000000
--- a/PepperDashEssentials/ControlSystem.cs.orig
+++ /dev/null
@@ -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);
- }
-
- ///
- /// Git 'er goin'
- ///
- 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();
- }
-
- ///
- /// Determines if the program is running on a processor (appliance) or server (XiO Edge).
- ///
- /// Sets Global.FilePathPrefix based on platform
- ///
- 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);
- }
-
- ///
- /// Do it, yo
- ///
- 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);
- }
-
- }
-
- ///
- /// Verifies filesystem is set up. IR, SGD, and program1 folders
- ///
- 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");
- }
-
- ///
- ///
- ///
- void Load()
- {
- LoadDevices();
- LoadTieLines();
- LoadRooms();
- LoadLogoServer();
-
- DeviceManager.ActivateAll();
- }
-
-
- ///
- /// Reads all devices from config and adds them to DeviceManager
- ///
- 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.");
-
- }
-
- ///
- /// Helper method to load tie lines. This should run after devices have loaded
- ///
- 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.");
-
- }
-
- ///
- /// Reads all rooms from config and adds them to DeviceManager
- ///
- 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.");
-
- }
-
- ///
- /// Helps add the post activation steps that link bridges to main controller
- ///
- ///
- 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);
- });
- }
-
- ///
- /// Fires up a logo server if not already running
- ///
- 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");
- }
- }
- }
-}
diff --git a/PepperDashEssentials/OTHER/Fusion/EssentialsHuddleVtc1FusionController.cs b/PepperDashEssentials/OTHER/Fusion/EssentialsHuddleVtc1FusionController.cs
index 14148a12..c79d49d7 100644
--- a/PepperDashEssentials/OTHER/Fusion/EssentialsHuddleVtc1FusionController.cs
+++ b/PepperDashEssentials/OTHER/Fusion/EssentialsHuddleVtc1FusionController.cs
@@ -1,348 +1,348 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using Crestron.SimplSharp;
-using Crestron.SimplSharp.CrestronIO;
-using Crestron.SimplSharpPro;
-using Crestron.SimplSharpPro.DeviceSupport;
-using Crestron.SimplSharpPro.Fusion;
-
-
-using PepperDash.Core;
-using PepperDash.Essentials;
-using PepperDash.Essentials.Core;
-using PepperDash.Essentials.Core.Config;
-using PepperDash.Essentials.Devices.Common;
-using PepperDash.Essentials.Devices.Common.Occupancy;
-
-namespace PepperDash.Essentials.Fusion
-{
- public class EssentialsHuddleVtc1FusionController : EssentialsHuddleSpaceFusionSystemControllerBase
- {
- BooleanSigData CodecIsInCall;
-
- public EssentialsHuddleVtc1FusionController(EssentialsHuddleVtc1Room room, uint ipId)
- : base(room, ipId)
- {
-
- }
-
- ///
- /// Called in base class constructor before RVI and GUID files are built
- ///
- protected override void ExecuteCustomSteps()
- {
- SetUpCodec();
- }
-
- ///
- /// Creates a static asset for the codec and maps the joins to the main room symbol
- ///
- void SetUpCodec()
- {
- try
- {
- var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec;
-
- if (codec == null)
- {
- Debug.Console(1, this, "Cannot link codec to Fusion because codec is null");
- return;
- }
-
- codec.UsageTracker = new UsageTracking(codec);
- codec.UsageTracker.UsageIsTracked = true;
- codec.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
-
- var codecPowerOnAction = new Action(b => { if (!b) codec.StandbyDeactivate(); });
- var codecPowerOffAction = new Action(b => { if (!b) codec.StandbyActivate(); });
-
- // Map FusionRoom Attributes:
-
- // Codec volume
- var codecVolume = FusionRoom.CreateOffsetUshortSig(50, "Volume - Fader01", eSigIoMask.InputOutputSig);
- codecVolume.OutputSig.UserObject = new Action(b => (codec as IBasicVolumeWithFeedback).SetVolume(b));
- (codec as IBasicVolumeWithFeedback).VolumeLevelFeedback.LinkInputSig(codecVolume.InputSig);
-
- // In Call Status
- CodecIsInCall = FusionRoom.CreateOffsetBoolSig(69, "Conf - VC 1 In Call", eSigIoMask.InputSigOnly);
- codec.CallStatusChange += new EventHandler(codec_CallStatusChange);
-
- // Online status
- if (codec is ICommunicationMonitor)
- {
- var c = codec as ICommunicationMonitor;
- var codecOnline = FusionRoom.CreateOffsetBoolSig(122, "Online - VC 1", eSigIoMask.InputSigOnly);
- codecOnline.InputSig.BoolValue = c.CommunicationMonitor.Status == MonitorStatus.IsOk;
- c.CommunicationMonitor.StatusChange += (o, a) =>
- {
- codecOnline.InputSig.BoolValue = a.Status == MonitorStatus.IsOk;
- };
- Debug.Console(0, this, "Linking '{0}' communication monitor to Fusion '{1}'", codec.Key, "Online - VC 1");
- }
-
- // Codec IP Address
- bool codecHasIpInfo = false;
- var codecComm = codec.Communication;
-
- string codecIpAddress = string.Empty;
- int codecIpPort = 0;
-
- StringSigData codecIpAddressSig;
- StringSigData codecIpPortSig;
-
- if(codecComm is GenericSshClient)
- {
- codecIpAddress = (codecComm as GenericSshClient).Hostname;
- codecIpPort = (codecComm as GenericSshClient).Port;
- codecHasIpInfo = true;
- }
- else if (codecComm is GenericTcpIpClient)
- {
- codecIpAddress = (codecComm as GenericTcpIpClient).Hostname;
- codecIpPort = (codecComm as GenericTcpIpClient).Port;
- codecHasIpInfo = true;
- }
-
- if (codecHasIpInfo)
- {
- codecIpAddressSig = FusionRoom.CreateOffsetStringSig(121, "IP Address - VC", eSigIoMask.InputSigOnly);
- codecIpAddressSig.InputSig.StringValue = codecIpAddress;
-
- codecIpPortSig = FusionRoom.CreateOffsetStringSig(150, "IP Port - VC", eSigIoMask.InputSigOnly);
- codecIpPortSig.InputSig.StringValue = codecIpPort.ToString();
- }
-
- var tempAsset = new FusionAsset();
-
- var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(c => c.Key.Equals(codec.Key));
-
- if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
- {
- tempAsset = FusionStaticAssets[deviceConfig.Uid];
- }
- else
- {
- // Create a new asset
- tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), codec.Name, "Codec", "");
- FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
- }
-
- var codecAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
- codecAsset.PowerOn.OutputSig.UserObject = codecPowerOnAction;
- codecAsset.PowerOff.OutputSig.UserObject = codecPowerOffAction;
- codec.StandbyIsOnFeedback.LinkComplementInputSig(codecAsset.PowerOn.InputSig);
-
- // TODO: Map relevant attributes on asset symbol
-
- codecAsset.TrySetMakeModel(codec);
- codecAsset.TryLinkAssetErrorToCommunication(codec);
- }
- catch (Exception 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)
- {
- var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec;
-
- CodecIsInCall.InputSig.BoolValue = codec.IsInCall;
- }
-
- // These methods are overridden because they access the room class which is of a different type
-
- protected override void CreateSymbolAndBasicSigs(uint ipId)
- {
- Debug.Console(1, this, "Creating Fusion Room symbol with GUID: {0}", RoomGuid);
-
- FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
- FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();
- FusionRoom.ExtenderFusionRoomDataReservedSigs.Use();
-
- FusionRoom.Register();
-
- FusionRoom.FusionStateChange += FusionRoom_FusionStateChange;
-
- FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.DeviceExtenderSigChange += FusionRoomSchedule_DeviceExtenderSigChange;
- FusionRoom.ExtenderFusionRoomDataReservedSigs.DeviceExtenderSigChange += ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange;
- FusionRoom.OnlineStatusChange += FusionRoom_OnlineStatusChange;
-
- 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(CreateAsHocMeeting, "FusCreateMeeting", "Creates and Ad Hoc meeting for on hour or until the next meeting", ConsoleAccessLevelEnum.AccessOperator);
-
- // Room to fusion room
- Room.OnFeedback.LinkInputSig(FusionRoom.SystemPowerOn.InputSig);
-
- // Moved to
- 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.
- (Room as EssentialsHuddleVtc1Room).CurrentSingleSourceChange += Room_CurrentSourceInfoChange;
-
-
- FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction((Room as EssentialsHuddleVtc1Room).PowerOnToDefaultOrLastSource);
- FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff"));
- // NO!! room.RoomIsOn.LinkComplementInputSig(FusionRoom.SystemPowerOff.InputSig);
-
-
- CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
- }
-
- protected override void SetUpSources()
- {
- // Sources
- var dict = ConfigReader.ConfigObject.GetSourceListForKey((Room as EssentialsHuddleVtc1Room).SourceListKey);
- if (dict != null)
- {
- // NEW PROCESS:
- // Make these lists and insert the fusion attributes by iterating these
- var setTopBoxes = dict.Where(d => d.Value.SourceDevice is ISetTopBoxControls);
- uint i = 1;
- foreach (var kvp in setTopBoxes)
- {
- TryAddRouteActionSigs("Display 1 - Source TV " + i, 188 + i, kvp.Key, kvp.Value.SourceDevice);
- i++;
- if (i > 5) // We only have five spots
- break;
- }
-
- var discPlayers = dict.Where(d => d.Value.SourceDevice is IDiscPlayerControls);
- i = 1;
- foreach (var kvp in discPlayers)
- {
- TryAddRouteActionSigs("Display 1 - Source DVD " + i, 181 + i, kvp.Key, kvp.Value.SourceDevice);
- i++;
- if (i > 5) // We only have five spots
- break;
- }
-
- var laptops = dict.Where(d => d.Value.SourceDevice is Laptop);
- i = 1;
- foreach (var kvp in laptops)
- {
- TryAddRouteActionSigs("Display 1 - Source Laptop " + i, 166 + i, kvp.Key, kvp.Value.SourceDevice);
- i++;
- if (i > 10) // We only have ten spots???
- break;
- }
-
- foreach (var kvp in dict)
- {
- var usageDevice = kvp.Value.SourceDevice as IUsageTracking;
-
- if (usageDevice != null)
- {
- usageDevice.UsageTracker = new UsageTracking(usageDevice as Device);
- usageDevice.UsageTracker.UsageIsTracked = true;
- usageDevice.UsageTracker.DeviceUsageEnded += new EventHandler(UsageTracker_DeviceUsageEnded);
- }
- }
-
- }
- else
- {
- Debug.Console(1, this, "WARNING: Config source list '{0}' not found for room '{1}'",
- (Room as EssentialsHuddleVtc1Room).SourceListKey, Room.Key);
- }
- }
-
- protected override void SetUpDisplay()
- {
- try
- {
- //Setup Display Usage Monitoring
-
- var displays = DeviceManager.AllDevices.Where(d => d is DisplayBase);
-
- // Consider updating this in multiple display systems
-
- foreach (DisplayBase display in displays)
- {
- display.UsageTracker = new UsageTracking(display);
- display.UsageTracker.UsageIsTracked = true;
- display.UsageTracker.DeviceUsageEnded += new EventHandler(UsageTracker_DeviceUsageEnded);
- }
-
- var defaultDisplay = (Room as EssentialsHuddleVtc1Room).DefaultDisplay as DisplayBase;
- if (defaultDisplay == null)
- {
- Debug.Console(1, this, "Cannot link null display to Fusion because default display is null");
- return;
- }
-
- var dispPowerOnAction = new Action(b => { if (!b) defaultDisplay.PowerOn(); });
- var dispPowerOffAction = new Action(b => { if (!b) defaultDisplay.PowerOff(); });
-
- // Display to fusion room sigs
- FusionRoom.DisplayPowerOn.OutputSig.UserObject = dispPowerOnAction;
- FusionRoom.DisplayPowerOff.OutputSig.UserObject = dispPowerOffAction;
- defaultDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
- if (defaultDisplay is IDisplayUsage)
- (defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
-
-
-
- MapDisplayToRoomJoins(1, 158, defaultDisplay);
-
-
- var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key));
-
- //Check for existing asset in GUIDs collection
-
- var tempAsset = new FusionAsset();
-
- if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
- {
- tempAsset = FusionStaticAssets[deviceConfig.Uid];
- }
- else
- {
- // Create a new asset
- tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), defaultDisplay.Name, "Display", "");
- FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
- }
-
- var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
- dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
- dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
- defaultDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
- // NO!! display.PowerIsOn.LinkComplementInputSig(dispAsset.PowerOff.InputSig);
- // Use extension methods
- dispAsset.TrySetMakeModel(defaultDisplay);
- dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay);
- }
- catch (Exception e)
- {
- Debug.Console(1, this, "Error setting up display in Fusion: {0}", e);
- }
-
- }
-
- protected override void MapDisplayToRoomJoins(int displayIndex, int joinOffset, DisplayBase display)
- {
- string displayName = string.Format("Display {0} - ", displayIndex);
-
-
- if (display == (Room as EssentialsHuddleVtc1Room).DefaultDisplay)
- {
- // Power on
- var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig);
- defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => { if (!b) display.PowerOn(); });
- display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
-
- // Power Off
- var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off", eSigIoMask.InputOutputSig);
- defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => { if (!b) display.PowerOff(); }); ;
- display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
-
- // Current Source
- var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig);
- defaultDisplaySourceNone.OutputSig.UserObject = new Action(b => { if (!b) (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff"); }); ;
- }
- }
- }
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Crestron.SimplSharp;
+using Crestron.SimplSharp.CrestronIO;
+using Crestron.SimplSharpPro;
+using Crestron.SimplSharpPro.DeviceSupport;
+using Crestron.SimplSharpPro.Fusion;
+
+
+using PepperDash.Core;
+using PepperDash.Essentials;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Core.Config;
+using PepperDash.Essentials.Devices.Common;
+using PepperDash.Essentials.Devices.Common.Occupancy;
+
+namespace PepperDash.Essentials.Fusion
+{
+ public class EssentialsHuddleVtc1FusionController : EssentialsHuddleSpaceFusionSystemControllerBase
+ {
+ BooleanSigData CodecIsInCall;
+
+ public EssentialsHuddleVtc1FusionController(EssentialsHuddleVtc1Room room, uint ipId)
+ : base(room, ipId)
+ {
+
+ }
+
+ ///
+ /// Called in base class constructor before RVI and GUID files are built
+ ///
+ protected override void ExecuteCustomSteps()
+ {
+ SetUpCodec();
+ }
+
+ ///
+ /// Creates a static asset for the codec and maps the joins to the main room symbol
+ ///
+ void SetUpCodec()
+ {
+ try
+ {
+ var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec;
+
+ if (codec == null)
+ {
+ Debug.Console(1, this, "Cannot link codec to Fusion because codec is null");
+ return;
+ }
+
+ codec.UsageTracker = new UsageTracking(codec);
+ codec.UsageTracker.UsageIsTracked = true;
+ codec.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
+
+ var codecPowerOnAction = new Action(b => { if (!b) codec.StandbyDeactivate(); });
+ var codecPowerOffAction = new Action(b => { if (!b) codec.StandbyActivate(); });
+
+ // Map FusionRoom Attributes:
+
+ // Codec volume
+ var codecVolume = FusionRoom.CreateOffsetUshortSig(50, "Volume - Fader01", eSigIoMask.InputOutputSig);
+ codecVolume.OutputSig.UserObject = new Action(b => (codec as IBasicVolumeWithFeedback).SetVolume(b));
+ (codec as IBasicVolumeWithFeedback).VolumeLevelFeedback.LinkInputSig(codecVolume.InputSig);
+
+ // In Call Status
+ CodecIsInCall = FusionRoom.CreateOffsetBoolSig(69, "Conf - VC 1 In Call", eSigIoMask.InputSigOnly);
+ codec.CallStatusChange += new EventHandler(codec_CallStatusChange);
+
+ // Online status
+ if (codec is ICommunicationMonitor)
+ {
+ var c = codec as ICommunicationMonitor;
+ var codecOnline = FusionRoom.CreateOffsetBoolSig(122, "Online - VC 1", eSigIoMask.InputSigOnly);
+ codecOnline.InputSig.BoolValue = c.CommunicationMonitor.Status == MonitorStatus.IsOk;
+ c.CommunicationMonitor.StatusChange += (o, a) =>
+ {
+ codecOnline.InputSig.BoolValue = a.Status == MonitorStatus.IsOk;
+ };
+ Debug.Console(0, this, "Linking '{0}' communication monitor to Fusion '{1}'", codec.Key, "Online - VC 1");
+ }
+
+ // Codec IP Address
+ bool codecHasIpInfo = false;
+ var codecComm = codec.Communication;
+
+ string codecIpAddress = string.Empty;
+ int codecIpPort = 0;
+
+ StringSigData codecIpAddressSig;
+ StringSigData codecIpPortSig;
+
+ if(codecComm is GenericSshClient)
+ {
+ codecIpAddress = (codecComm as GenericSshClient).Hostname;
+ codecIpPort = (codecComm as GenericSshClient).Port;
+ codecHasIpInfo = true;
+ }
+ else if (codecComm is GenericTcpIpClient)
+ {
+ codecIpAddress = (codecComm as GenericTcpIpClient).Hostname;
+ codecIpPort = (codecComm as GenericTcpIpClient).Port;
+ codecHasIpInfo = true;
+ }
+
+ if (codecHasIpInfo)
+ {
+ codecIpAddressSig = FusionRoom.CreateOffsetStringSig(121, "IP Address - VC", eSigIoMask.InputSigOnly);
+ codecIpAddressSig.InputSig.StringValue = codecIpAddress;
+
+ codecIpPortSig = FusionRoom.CreateOffsetStringSig(150, "IP Port - VC", eSigIoMask.InputSigOnly);
+ codecIpPortSig.InputSig.StringValue = codecIpPort.ToString();
+ }
+
+ var tempAsset = new FusionAsset();
+
+ var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(c => c.Key.Equals(codec.Key));
+
+ if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
+ {
+ tempAsset = FusionStaticAssets[deviceConfig.Uid];
+ }
+ else
+ {
+ // Create a new asset
+ tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), codec.Name, "Codec", "");
+ FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
+ }
+
+ var codecAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
+ codecAsset.PowerOn.OutputSig.UserObject = codecPowerOnAction;
+ codecAsset.PowerOff.OutputSig.UserObject = codecPowerOffAction;
+ codec.StandbyIsOnFeedback.LinkComplementInputSig(codecAsset.PowerOn.InputSig);
+
+ // TODO: Map relevant attributes on asset symbol
+
+ codecAsset.TrySetMakeModel(codec);
+ codecAsset.TryLinkAssetErrorToCommunication(codec);
+ }
+ catch (Exception 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)
+ {
+ var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec;
+
+ CodecIsInCall.InputSig.BoolValue = codec.IsInCall;
+ }
+
+ // These methods are overridden because they access the room class which is of a different type
+
+ protected override void CreateSymbolAndBasicSigs(uint ipId)
+ {
+ Debug.Console(1, this, "Creating Fusion Room symbol with GUID: {0}", RoomGuid);
+
+ FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
+ FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();
+ FusionRoom.ExtenderFusionRoomDataReservedSigs.Use();
+
+ FusionRoom.Register();
+
+ FusionRoom.FusionStateChange += FusionRoom_FusionStateChange;
+
+ FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.DeviceExtenderSigChange += FusionRoomSchedule_DeviceExtenderSigChange;
+ FusionRoom.ExtenderFusionRoomDataReservedSigs.DeviceExtenderSigChange += ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange;
+ FusionRoom.OnlineStatusChange += FusionRoom_OnlineStatusChange;
+
+ 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(CreateAsHocMeeting, "FusCreateMeeting", "Creates and Ad Hoc meeting for on hour or until the next meeting", ConsoleAccessLevelEnum.AccessOperator);
+
+ // Room to fusion room
+ Room.OnFeedback.LinkInputSig(FusionRoom.SystemPowerOn.InputSig);
+
+ // Moved to
+ 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.
+ (Room as EssentialsHuddleVtc1Room).CurrentSingleSourceChange += Room_CurrentSourceInfoChange;
+
+
+ FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction((Room as EssentialsHuddleVtc1Room).PowerOnToDefaultOrLastSource);
+ FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff"));
+ // NO!! room.RoomIsOn.LinkComplementInputSig(FusionRoom.SystemPowerOff.InputSig);
+
+
+ CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
+ }
+
+ protected override void SetUpSources()
+ {
+ // Sources
+ var dict = ConfigReader.ConfigObject.GetSourceListForKey((Room as EssentialsHuddleVtc1Room).SourceListKey);
+ if (dict != null)
+ {
+ // NEW PROCESS:
+ // Make these lists and insert the fusion attributes by iterating these
+ var setTopBoxes = dict.Where(d => d.Value.SourceDevice is ISetTopBoxControls);
+ uint i = 1;
+ foreach (var kvp in setTopBoxes)
+ {
+ TryAddRouteActionSigs("Display 1 - Source TV " + i, 188 + i, kvp.Key, kvp.Value.SourceDevice);
+ i++;
+ if (i > 5) // We only have five spots
+ break;
+ }
+
+ var discPlayers = dict.Where(d => d.Value.SourceDevice is IDiscPlayerControls);
+ i = 1;
+ foreach (var kvp in discPlayers)
+ {
+ TryAddRouteActionSigs("Display 1 - Source DVD " + i, 181 + i, kvp.Key, kvp.Value.SourceDevice);
+ i++;
+ if (i > 5) // We only have five spots
+ break;
+ }
+
+ var laptops = dict.Where(d => d.Value.SourceDevice is Laptop);
+ i = 1;
+ foreach (var kvp in laptops)
+ {
+ TryAddRouteActionSigs("Display 1 - Source Laptop " + i, 166 + i, kvp.Key, kvp.Value.SourceDevice);
+ i++;
+ if (i > 10) // We only have ten spots???
+ break;
+ }
+
+ foreach (var kvp in dict)
+ {
+ var usageDevice = kvp.Value.SourceDevice as IUsageTracking;
+
+ if (usageDevice != null)
+ {
+ usageDevice.UsageTracker = new UsageTracking(usageDevice as Device);
+ usageDevice.UsageTracker.UsageIsTracked = true;
+ usageDevice.UsageTracker.DeviceUsageEnded += new EventHandler(UsageTracker_DeviceUsageEnded);
+ }
+ }
+
+ }
+ else
+ {
+ Debug.Console(1, this, "WARNING: Config source list '{0}' not found for room '{1}'",
+ (Room as EssentialsHuddleVtc1Room).SourceListKey, Room.Key);
+ }
+ }
+
+ protected override void SetUpDisplay()
+ {
+ try
+ {
+ //Setup Display Usage Monitoring
+
+ var displays = DeviceManager.AllDevices.Where(d => d is DisplayBase);
+
+ // Consider updating this in multiple display systems
+
+ foreach (DisplayBase display in displays)
+ {
+ display.UsageTracker = new UsageTracking(display);
+ display.UsageTracker.UsageIsTracked = true;
+ display.UsageTracker.DeviceUsageEnded += new EventHandler(UsageTracker_DeviceUsageEnded);
+ }
+
+ var defaultDisplay = (Room as EssentialsHuddleVtc1Room).DefaultDisplay as DisplayBase;
+ if (defaultDisplay == null)
+ {
+ Debug.Console(1, this, "Cannot link null display to Fusion because default display is null");
+ return;
+ }
+
+ var dispPowerOnAction = new Action(b => { if (!b) defaultDisplay.PowerOn(); });
+ var dispPowerOffAction = new Action(b => { if (!b) defaultDisplay.PowerOff(); });
+
+ // Display to fusion room sigs
+ FusionRoom.DisplayPowerOn.OutputSig.UserObject = dispPowerOnAction;
+ FusionRoom.DisplayPowerOff.OutputSig.UserObject = dispPowerOffAction;
+ defaultDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
+ if (defaultDisplay is IDisplayUsage)
+ (defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
+
+
+
+ MapDisplayToRoomJoins(1, 158, defaultDisplay);
+
+
+ var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key));
+
+ //Check for existing asset in GUIDs collection
+
+ var tempAsset = new FusionAsset();
+
+ if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
+ {
+ tempAsset = FusionStaticAssets[deviceConfig.Uid];
+ }
+ else
+ {
+ // Create a new asset
+ tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), defaultDisplay.Name, "Display", "");
+ FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
+ }
+
+ var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
+ dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
+ dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
+ defaultDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
+ // NO!! display.PowerIsOn.LinkComplementInputSig(dispAsset.PowerOff.InputSig);
+ // Use extension methods
+ dispAsset.TrySetMakeModel(defaultDisplay);
+ dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay);
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "Error setting up display in Fusion: {0}", e);
+ }
+
+ }
+
+ protected override void MapDisplayToRoomJoins(int displayIndex, int joinOffset, DisplayBase display)
+ {
+ string displayName = string.Format("Display {0} - ", displayIndex);
+
+
+ if (display == (Room as EssentialsHuddleVtc1Room).DefaultDisplay)
+ {
+ // Power on
+ var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig);
+ defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => { if (!b) display.PowerOn(); });
+ display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
+
+ // Power Off
+ var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off", eSigIoMask.InputOutputSig);
+ defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => { if (!b) display.PowerOff(); }); ;
+ display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
+
+ // Current Source
+ var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig);
+ defaultDisplaySourceNone.OutputSig.UserObject = new Action(b => { if (!b) (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff"); }); ;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/PepperDashEssentials/PepperDashEssentials.csproj b/PepperDashEssentials/PepperDashEssentials.csproj
index e38f2f70..26305d2f 100644
--- a/PepperDashEssentials/PepperDashEssentials.csproj
+++ b/PepperDashEssentials/PepperDashEssentials.csproj
@@ -108,6 +108,8 @@
+
+
diff --git a/PepperDashEssentials/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs b/PepperDashEssentials/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs
index 83303582..16e49933 100644
--- a/PepperDashEssentials/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs
+++ b/PepperDashEssentials/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs
@@ -20,5 +20,7 @@ namespace PepperDash.Essentials.Room.Config
public string DefaultSourceItem { get; set; }
[JsonProperty("videoCodecKey")]
public string VideoCodecKey { get; set; }
+ [JsonProperty("audioCodecKey")]
+ public string AudioCodecKey { get; set; }
}
}
\ No newline at end of file
diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs
index f1b86477..9a2b7a31 100644
--- a/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs
+++ b/PepperDashEssentials/UIDrivers/EssentialsHuddle/EssentialsHuddlePanelAvFunctionsDriver.cs
@@ -1,1076 +1,1076 @@
-using System;
-using System.Collections.Generic;
-using Crestron.SimplSharp;
-using Crestron.SimplSharpPro;
-using Crestron.SimplSharpPro.UI;
-
-using PepperDash.Core;
-using PepperDash.Essentials.Core;
-using PepperDash.Essentials.Core.Config;
-using PepperDash.Essentials.Core.SmartObjects;
-using PepperDash.Essentials.Core.PageManagers;
-
-namespace PepperDash.Essentials
-{
- ///
- ///
- ///
- public class EssentialsHuddlePanelAvFunctionsDriver : PanelDriverBase, IAVDriver
- {
- CrestronTouchpanelPropertiesConfig Config;
-
- public enum UiDisplayMode
- {
- PresentationMode, AudioSetup
- }
-
- ///
- /// Whether volume ramping from this panel will show the volume
- /// gauge popup.
- ///
- public bool ShowVolumeGauge { get; set; }
-
- ///
- /// The amount of time that the volume buttons stays on screen, in ms
- ///
- public uint VolumeButtonPopupTimeout
- {
- get { return VolumeButtonsPopupFeedback.TimeoutMs; }
- set { VolumeButtonsPopupFeedback.TimeoutMs = value; }
- }
-
- ///
- /// The amount of time that the volume gauge stays on screen, in ms
- ///
- public uint VolumeGaugePopupTimeout
- {
- get { return VolumeGaugeFeedback.TimeoutMs; }
- set { VolumeGaugeFeedback.TimeoutMs = value; }
- }
-
- ///
- ///
- ///
- public uint PowerOffTimeout { get; set; }
-
- ///
- ///
- ///
- public string DefaultRoomKey
- {
- get { return _DefaultRoomKey; }
- set
- {
- _DefaultRoomKey = value;
- //CurrentRoom = DeviceManager.GetDeviceForKey(value) as EssentialsHuddleSpaceRoom;
- }
- }
- string _DefaultRoomKey;
-
- ///
- /// Indicates that the SetHeaderButtons method has completed successfully
- ///
- public bool HeaderButtonsAreSetUp { get; private set; }
-
- ///
- ///
- ///
- public EssentialsHuddleSpaceRoom CurrentRoom
- {
- get { return _CurrentRoom; }
- set
- {
- SetCurrentRoom(value);
- }
- }
- EssentialsHuddleSpaceRoom _CurrentRoom;
-
- ///
- ///
- ///
- //uint CurrentInterlockedModalJoin;
-
- ///
- /// For hitting feedback
- ///
- BoolInputSig ShareButtonSig;
- BoolInputSig EndMeetingButtonSig;
-
- ///
- /// Controls the extended period that the volume gauge shows on-screen,
- /// as triggered by Volume up/down operations
- ///
- BoolFeedbackPulseExtender VolumeGaugeFeedback;
-
- ///
- /// Controls the period that the volume buttons show on non-hard-button
- /// interfaces
- ///
- BoolFeedbackPulseExtender VolumeButtonsPopupFeedback;
-
- ///
- /// The parent driver for this
- ///
- PanelDriverBase Parent;
-
- ///
- /// All children attached to this driver. For hiding and showing as a group.
- ///
- List ChildDrivers = new List();
-
- List CurrentDisplayModeSigsInUse = new List();
-
- //// Important smart objects
-
- ///
- /// Smart Object 3200
- ///
- SubpageReferenceList SourcesSrl;
-
- ///
- /// Smart Object 15022
- ///
- SubpageReferenceList ActivityFooterSrl;
-
- ///
- /// Tracks which audio page group the UI is in
- ///
- UiDisplayMode CurrentDisplayMode;
-
- ///
- /// The AV page mangagers that have been used, to keep them alive for later
- ///
- Dictionary