mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-15 20:54:55 +00:00
Compare commits
5 Commits
v2.15.4-mc
...
v2.16.1-ho
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
258699fbcd | ||
|
|
738504e9fc | ||
|
|
cae1bbd6e6 | ||
|
|
dea4407e3e | ||
|
|
ab08a546f7 |
@@ -466,14 +466,14 @@ namespace PepperDash.Core
|
||||
/// </summary>
|
||||
public static void SetFileMinimumDebugLevel(LogEventLevel level)
|
||||
{
|
||||
_fileLevelSwitch.MinimumLevel = level;
|
||||
_errorLogLevelSwitch.MinimumLevel = level;
|
||||
|
||||
var err = CrestronDataStoreStatic.SetLocalUintValue(FileLevelStoreKey, (uint)level);
|
||||
var err = CrestronDataStoreStatic.SetLocalUintValue(ErrorLogLevelStoreKey, (uint)level);
|
||||
|
||||
if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
|
||||
LogMessage(LogEventLevel.Information, "Error saving File debug level setting: {error}", err);
|
||||
|
||||
LogMessage(LogEventLevel.Information, "File debug level set to {0}", _fileLevelSwitch.MinimumLevel);
|
||||
LogMessage(LogEventLevel.Information, "File debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -103,6 +103,12 @@ namespace PepperDash.Essentials.Core
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to hide this scenario in the UI.
|
||||
/// </summary>
|
||||
[JsonProperty("hideInUi", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool HideInUi { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the collection of partition states.
|
||||
/// </summary>
|
||||
|
||||
@@ -109,6 +109,12 @@ namespace PepperDash.Essentials.Core
|
||||
[JsonProperty("isActive")]
|
||||
bool IsActive { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this scenario should be hidden in the UI.
|
||||
/// </summary>
|
||||
[JsonProperty("hideInUi")]
|
||||
bool HideInUi { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Activates this room combination scenario
|
||||
/// </summary>
|
||||
|
||||
@@ -14,18 +14,40 @@ namespace PepperDash.Essentials.Core
|
||||
{
|
||||
private RoomCombinationScenarioConfig _config;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the key associated with the object.
|
||||
/// </summary>
|
||||
[JsonProperty("key")]
|
||||
public string Key { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name associated with the object.
|
||||
/// </summary>
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("partitionStates")]
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether to hide this scenario in the UI.
|
||||
/// </summary>
|
||||
///
|
||||
[JsonProperty("hideInUi")]
|
||||
|
||||
public bool HideInUi
|
||||
{
|
||||
get { return _config.HideInUi; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the PartitionStates
|
||||
/// </summary>
|
||||
///
|
||||
[JsonProperty("partitionStates")]
|
||||
|
||||
public List<PartitionState> PartitionStates { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines which UI devices get mapped to which room in this scenario. The Key should be the key of the UI device and the Value should be the key of the room to map to
|
||||
/// </summary>
|
||||
[JsonProperty("uiMap")]
|
||||
public Dictionary<string, string> UiMap { get; set; }
|
||||
|
||||
|
||||
@@ -244,15 +244,13 @@ namespace PepperDash.Essentials
|
||||
CrestronEnvironment.ProgramStatusEventHandler +=
|
||||
CrestronEnvironment_ProgramStatusEventHandler;
|
||||
|
||||
ApiOnlineAndAuthorized = new BoolFeedback("apiOnlineAndAuthorized", () =>
|
||||
ApiOnlineAndAuthorized = new BoolFeedback(() =>
|
||||
{
|
||||
if (_wsClient2 == null)
|
||||
return false;
|
||||
|
||||
return _wsClient2.IsAlive && IsAuthorized;
|
||||
});
|
||||
|
||||
Debug.SetFileMinimumDebugLevel(Serilog.Events.LogEventLevel.Debug);
|
||||
}
|
||||
|
||||
private void SetupDefaultRoomMessengers()
|
||||
@@ -1919,8 +1917,7 @@ namespace PepperDash.Essentials
|
||||
/// <param name="e"></param>
|
||||
private void HandleError(object sender, ErrorEventArgs e)
|
||||
{
|
||||
this.LogError("Websocket error {message}", e.Message);
|
||||
this.LogError(e.Exception, "Websocket error");
|
||||
this.LogError("Websocket error {0}", e.Message);
|
||||
|
||||
IsAuthorized = false;
|
||||
StartServerReconnectTimer();
|
||||
@@ -1933,7 +1930,7 @@ namespace PepperDash.Essentials
|
||||
/// <param name="e"></param>
|
||||
private void HandleClose(object sender, CloseEventArgs e)
|
||||
{
|
||||
this.LogInformation(
|
||||
this.LogDebug(
|
||||
"Websocket close {code} {reason}, clean={wasClean}",
|
||||
e.Code,
|
||||
e.Reason,
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
using Crestron.SimplSharpPro.UI;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Core.Logging;
|
||||
|
||||
namespace PepperDash.Essentials.Touchpanel
|
||||
{
|
||||
/// <summary>
|
||||
/// Partial class containing app control functionality for managing applications on the touchpanel.
|
||||
/// </summary>
|
||||
public partial class MobileControlTouchpanelController
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the application URL for mobile control access.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to set for the mobile control application.</param>
|
||||
public void SetAppUrl(string url)
|
||||
{
|
||||
_appUrl = GetUrlWithCorrectIp(url);
|
||||
AppUrlFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hides the currently open application on the touchpanel.
|
||||
/// </summary>
|
||||
public void HideOpenApp()
|
||||
{
|
||||
if (Panel is TswX70Base x70Panel)
|
||||
{
|
||||
x70Panel.ExtenderApplicationControlReservedSigs.HideOpenedApplication();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Panel is TswX60BaseClass x60Panel)
|
||||
{
|
||||
x60Panel.ExtenderApplicationControlReservedSigs.HideOpenApplication();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens an application on the touchpanel.
|
||||
/// </summary>
|
||||
public void OpenApp()
|
||||
{
|
||||
if (Panel is TswX70Base x70Panel)
|
||||
{
|
||||
x70Panel.ExtenderApplicationControlReservedSigs.OpenApplication();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Panel is TswX60WithZoomRoomAppReservedSigs)
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"X60 panel does not support zoom app");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the currently open application on the touchpanel.
|
||||
/// </summary>
|
||||
public void CloseOpenApp()
|
||||
{
|
||||
if (Panel is TswX70Base x70Panel)
|
||||
{
|
||||
x70Panel.ExtenderApplicationControlReservedSigs.CloseOpenedApplication();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Panel is TswX60WithZoomRoomAppReservedSigs x60Panel)
|
||||
{
|
||||
x60Panel.ExtenderApplicationControlReservedSigs.CloseOpenedApplication();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.UI;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Core.Logging;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.DeviceInfo;
|
||||
|
||||
namespace PepperDash.Essentials.Touchpanel
|
||||
{
|
||||
/// <summary>
|
||||
/// Partial class containing device information, IP address handling, and network configuration functionality.
|
||||
/// </summary>
|
||||
public partial class MobileControlTouchpanelController
|
||||
{
|
||||
/// <summary>
|
||||
/// Updates device information including MAC address and IP address from panel extenders.
|
||||
/// </summary>
|
||||
public void UpdateDeviceInfo()
|
||||
{
|
||||
if (Panel is TswXX70Base x70Panel)
|
||||
{
|
||||
DeviceInfo.MacAddress = x70Panel.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue;
|
||||
DeviceInfo.IpAddress = x70Panel.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue;
|
||||
|
||||
var handler = DeviceInfoChanged;
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
handler(this, new DeviceInfoEventArgs(DeviceInfo));
|
||||
}
|
||||
|
||||
if (Panel is TswX60WithZoomRoomAppReservedSigs x60Panel)
|
||||
{
|
||||
DeviceInfo.MacAddress = x60Panel.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue;
|
||||
DeviceInfo.IpAddress = x60Panel.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue;
|
||||
|
||||
var handler = DeviceInfoChanged;
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
handler(this, new DeviceInfoEventArgs(DeviceInfo));
|
||||
}
|
||||
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"MAC: {DeviceInfo.MacAddress} IP: {DeviceInfo.IpAddress}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the URL with the correct IP address based on the connected devices and the Crestron processor's IP address.
|
||||
/// </summary>
|
||||
/// <param name="url">The original URL to process.</param>
|
||||
/// <returns>The URL with the correct IP address for the panel's network connection.</returns>
|
||||
private string GetUrlWithCorrectIp(string url)
|
||||
{
|
||||
var lanAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetLANAdapter);
|
||||
|
||||
var processorIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, lanAdapterId);
|
||||
|
||||
if (csIpAddress == null || csSubnetMask == null || url == null)
|
||||
{
|
||||
this.LogWarning("CS IP Address Subnet Mask or url is null, cannot determine correct IP for URL");
|
||||
return url;
|
||||
}
|
||||
|
||||
this.LogVerbose("Processor IP: {processorIp}, CS IP: {csIpAddress}, CS Subnet Mask: {csSubnetMask}", processorIp, csIpAddress, csSubnetMask);
|
||||
this.LogVerbose("Connected IP Count: {connectedIps}", ConnectedIps.Count);
|
||||
|
||||
var ip = ConnectedIps.Any(ipInfo =>
|
||||
{
|
||||
if (System.Net.IPAddress.TryParse(ipInfo.DeviceIpAddress, out var parsedIp))
|
||||
{
|
||||
return parsedIp.IsInSameSubnet(csIpAddress, csSubnetMask);
|
||||
}
|
||||
this.LogWarning("Invalid IP address: {deviceIpAddress}", ipInfo.DeviceIpAddress);
|
||||
return false;
|
||||
}) ? csIpAddress.ToString() : processorIp;
|
||||
|
||||
var match = Regex.Match(url, @"^http://([^:/]+):\d+/mc/app\?token=.+$");
|
||||
if (match.Success)
|
||||
{
|
||||
string ipa = match.Groups[1].Value;
|
||||
// ip will be "192.168.1.100"
|
||||
}
|
||||
|
||||
// replace ipa with ip but leave the rest of the string intact
|
||||
var updatedUrl = Regex.Replace(url, @"^http://[^:/]+", $"http://{ip}");
|
||||
|
||||
this.LogVerbose("Updated URL: {updatedUrl}", updatedUrl);
|
||||
|
||||
return updatedUrl;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes to mobile control updates and bridge events for feedback updates.
|
||||
/// </summary>
|
||||
private void SubscribeForMobileControlUpdates()
|
||||
{
|
||||
foreach (var dev in DeviceManager.AllDevices)
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"{dev.Key}:{dev.GetType().Name}");
|
||||
}
|
||||
|
||||
var mcList = DeviceManager.AllDevices.OfType<MobileControlSystemController>().ToList();
|
||||
|
||||
if (mcList.Count == 0)
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"No Mobile Control controller found");
|
||||
return;
|
||||
}
|
||||
|
||||
// use first in list, since there should only be one.
|
||||
var mc = mcList[0];
|
||||
|
||||
var bridge = mc.GetRoomBridge(_config.DefaultRoomKey);
|
||||
|
||||
if (bridge == null)
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"No Mobile Control bridge for {_config.DefaultRoomKey} found ");
|
||||
return;
|
||||
}
|
||||
|
||||
_bridge = bridge;
|
||||
|
||||
_bridge.UserCodeChanged += UpdateFeedbacks;
|
||||
_bridge.AppUrlChanged += (s, a) =>
|
||||
{
|
||||
SetAppUrl(_bridge.AppUrl);
|
||||
};
|
||||
|
||||
UpdateFeedbacks();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
using System;
|
||||
using Crestron.SimplSharpPro.UI;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Core.Logging;
|
||||
using PepperDash.Essentials.Core.DeviceInfo;
|
||||
|
||||
namespace PepperDash.Essentials.Touchpanel
|
||||
{
|
||||
/// <summary>
|
||||
/// Partial class containing panel extender registration and event handling functionality.
|
||||
/// </summary>
|
||||
public partial class MobileControlTouchpanelController
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers for extender signals based on the panel type and sets up event handlers
|
||||
/// for app control, Zoom room, and Ethernet functionality.
|
||||
/// </summary>
|
||||
private void RegisterForExtenders()
|
||||
{
|
||||
if (Panel is TswXX70Base x70Panel)
|
||||
{
|
||||
RegisterX70PanelExtenders(x70Panel);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Panel is TswX60WithZoomRoomAppReservedSigs x60withZoomApp)
|
||||
{
|
||||
RegisterX60PanelExtenders(x60withZoomApp);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers extender signals and event handlers for TSW X70 series panels.
|
||||
/// </summary>
|
||||
/// <param name="x70Panel">The X70 panel to register extenders for.</param>
|
||||
private void RegisterX70PanelExtenders(TswXX70Base x70Panel)
|
||||
{
|
||||
// App Control Extender
|
||||
x70Panel.ExtenderApplicationControlReservedSigs.DeviceExtenderSigChange += (e, a) =>
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X70 App Control Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}");
|
||||
|
||||
UpdateZoomFeedbacks();
|
||||
|
||||
if (!x70Panel.ExtenderApplicationControlReservedSigs.HideOpenedApplicationFeedback.BoolValue)
|
||||
{
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.ShowButtonToolbar();
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.Button2On();
|
||||
}
|
||||
else
|
||||
{
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.HideButtonToolbar();
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.Button2Off();
|
||||
}
|
||||
};
|
||||
|
||||
// Zoom Room App Extender
|
||||
x70Panel.ExtenderZoomRoomAppReservedSigs.DeviceExtenderSigChange += (e, a) =>
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X70 Zoom Room App Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}");
|
||||
|
||||
if (a.Sig.Number == x70Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomIncomingCallFeedback.Number)
|
||||
{
|
||||
ZoomIncomingCallFeedback.FireUpdate();
|
||||
}
|
||||
else if (a.Sig.Number == x70Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomActiveFeedback.Number)
|
||||
{
|
||||
ZoomInCallFeedback.FireUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
// Ethernet Extender
|
||||
x70Panel.ExtenderEthernetReservedSigs.DeviceExtenderSigChange += (e, a) =>
|
||||
{
|
||||
DeviceInfo.MacAddress = x70Panel.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue;
|
||||
DeviceInfo.IpAddress = x70Panel.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue;
|
||||
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"MAC: {DeviceInfo.MacAddress} IP: {DeviceInfo.IpAddress}");
|
||||
|
||||
var handler = DeviceInfoChanged;
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
handler(this, new DeviceInfoEventArgs(DeviceInfo));
|
||||
};
|
||||
|
||||
// Initialize extenders
|
||||
x70Panel.ExtenderApplicationControlReservedSigs.Use();
|
||||
x70Panel.ExtenderZoomRoomAppReservedSigs.Use();
|
||||
x70Panel.ExtenderEthernetReservedSigs.Use();
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.Use();
|
||||
|
||||
// Initialize button toolbar
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.Button1Off();
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.Button3Off();
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.Button4Off();
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.Button5Off();
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.Button6Off();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers extender signals and event handlers for TSW X60 series panels with Zoom room app support.
|
||||
/// </summary>
|
||||
/// <param name="x60withZoomApp">The X60 panel with Zoom room app to register extenders for.</param>
|
||||
private void RegisterX60PanelExtenders(TswX60WithZoomRoomAppReservedSigs x60withZoomApp)
|
||||
{
|
||||
// App Control Extender
|
||||
x60withZoomApp.ExtenderApplicationControlReservedSigs.DeviceExtenderSigChange += (e, a) =>
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X60 App Control Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}");
|
||||
|
||||
if (a.Sig.Number == x60withZoomApp.ExtenderApplicationControlReservedSigs.HideOpenApplicationFeedback.Number)
|
||||
{
|
||||
AppOpenFeedback.FireUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
// Zoom Room App Extender
|
||||
x60withZoomApp.ExtenderZoomRoomAppReservedSigs.DeviceExtenderSigChange += (e, a) =>
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X60 Zoom Room App Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}");
|
||||
|
||||
if (a.Sig.Number == x60withZoomApp.ExtenderZoomRoomAppReservedSigs.ZoomRoomIncomingCallFeedback.Number)
|
||||
{
|
||||
ZoomIncomingCallFeedback.FireUpdate();
|
||||
}
|
||||
else if (a.Sig.Number == x60withZoomApp.ExtenderZoomRoomAppReservedSigs.ZoomRoomActiveFeedback.Number)
|
||||
{
|
||||
ZoomInCallFeedback.FireUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
// Ethernet Extender
|
||||
x60withZoomApp.ExtenderEthernetReservedSigs.DeviceExtenderSigChange += (e, a) =>
|
||||
{
|
||||
DeviceInfo.MacAddress = x60withZoomApp.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue;
|
||||
DeviceInfo.IpAddress = x60withZoomApp.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue;
|
||||
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"MAC: {DeviceInfo.MacAddress} IP: {DeviceInfo.IpAddress}");
|
||||
|
||||
var handler = DeviceInfoChanged;
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
handler(this, new DeviceInfoEventArgs(DeviceInfo));
|
||||
};
|
||||
|
||||
// Initialize extenders
|
||||
x60withZoomApp.ExtenderZoomRoomAppReservedSigs.Use();
|
||||
x60withZoomApp.ExtenderApplicationControlReservedSigs.Use();
|
||||
x60withZoomApp.ExtenderEthernetReservedSigs.Use();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using Crestron.SimplSharpPro.UI;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Core.Logging;
|
||||
|
||||
namespace PepperDash.Essentials.Touchpanel
|
||||
{
|
||||
/// <summary>
|
||||
/// Partial class containing Zoom integration functionality for managing Zoom calls and room control.
|
||||
/// </summary>
|
||||
public partial class MobileControlTouchpanelController
|
||||
{
|
||||
/// <summary>
|
||||
/// Updates all Zoom-related feedback values to reflect current state.
|
||||
/// </summary>
|
||||
private void UpdateZoomFeedbacks()
|
||||
{
|
||||
foreach (var feedback in ZoomFeedbacks)
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"Updating {feedback.Key}");
|
||||
feedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ends the current Zoom call on the touchpanel.
|
||||
/// </summary>
|
||||
public void EndZoomCall()
|
||||
{
|
||||
if (Panel is TswX70Base x70Panel)
|
||||
{
|
||||
x70Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomEndCall();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Panel is TswX60WithZoomRoomAppReservedSigs x60Panel)
|
||||
{
|
||||
x60Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomEndCall();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ using PepperDash.Essentials.Core.Config;
|
||||
using PepperDash.Essentials.Core.DeviceInfo;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
using PepperDash.Essentials.Core.UI;
|
||||
using Serilog.Events;
|
||||
using Feedback = PepperDash.Essentials.Core.Feedback;
|
||||
|
||||
namespace PepperDash.Essentials.Touchpanel
|
||||
@@ -23,9 +24,8 @@ namespace PepperDash.Essentials.Touchpanel
|
||||
/// <summary>
|
||||
/// Mobile Control touchpanel controller that provides app control, Zoom integration,
|
||||
/// and mobile control functionality for Crestron touchpanels.
|
||||
/// This is the main partial class containing core properties, constructor, and basic functionality.
|
||||
/// </summary>
|
||||
public partial class MobileControlTouchpanelController : TouchpanelBase, IHasFeedback, ITswAppControl, ITswZoomControl, IDeviceInfoProvider, IMobileControlCrestronTouchpanelController, ITheme
|
||||
public class MobileControlTouchpanelController : TouchpanelBase, IHasFeedback, ITswAppControl, ITswZoomControl, IDeviceInfoProvider, IMobileControlCrestronTouchpanelController, ITheme
|
||||
{
|
||||
private readonly MobileControlTouchpanelProperties localConfig;
|
||||
private IMobileControlRoomMessenger _bridge;
|
||||
@@ -191,12 +191,6 @@ namespace PepperDash.Essentials.Touchpanel
|
||||
|
||||
RegisterForExtenders();
|
||||
|
||||
if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Appliance)
|
||||
{
|
||||
this.LogInformation("Not running on processor. Skipping CS LAN Configuration");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var csAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetCSAdapter);
|
||||
@@ -206,9 +200,9 @@ namespace PepperDash.Essentials.Touchpanel
|
||||
this.csSubnetMask = System.Net.IPAddress.Parse(csSubnetMask);
|
||||
this.csIpAddress = System.Net.IPAddress.Parse(csIpAddress);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
catch
|
||||
{
|
||||
this.LogInformation("This processor does not have a CS LAN");
|
||||
Debug.LogInformation("This processor does not have a CS LAN", this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,6 +228,123 @@ namespace PepperDash.Essentials.Touchpanel
|
||||
ConfigWriter.UpdateDeviceConfig(deviceConfig);
|
||||
}
|
||||
|
||||
private void RegisterForExtenders()
|
||||
{
|
||||
if (Panel is TswXX70Base x70Panel)
|
||||
{
|
||||
x70Panel.ExtenderApplicationControlReservedSigs.DeviceExtenderSigChange += (e, a) =>
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X70 App Control Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}");
|
||||
|
||||
UpdateZoomFeedbacks();
|
||||
|
||||
if (!x70Panel.ExtenderApplicationControlReservedSigs.HideOpenedApplicationFeedback.BoolValue)
|
||||
{
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.ShowButtonToolbar();
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.Button2On();
|
||||
}
|
||||
else
|
||||
{
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.HideButtonToolbar();
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.Button2Off();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
x70Panel.ExtenderZoomRoomAppReservedSigs.DeviceExtenderSigChange += (e, a) =>
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X70 Zoom Room Ap Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}");
|
||||
|
||||
if (a.Sig.Number == x70Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomIncomingCallFeedback.Number)
|
||||
{
|
||||
ZoomIncomingCallFeedback.FireUpdate();
|
||||
}
|
||||
else if (a.Sig.Number == x70Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomActiveFeedback.Number)
|
||||
{
|
||||
ZoomInCallFeedback.FireUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
x70Panel.ExtenderEthernetReservedSigs.DeviceExtenderSigChange += (e, a) =>
|
||||
{
|
||||
DeviceInfo.MacAddress = x70Panel.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue;
|
||||
DeviceInfo.IpAddress = x70Panel.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue;
|
||||
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"MAC: {DeviceInfo.MacAddress} IP: {DeviceInfo.IpAddress}");
|
||||
|
||||
var handler = DeviceInfoChanged;
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
handler(this, new DeviceInfoEventArgs(DeviceInfo));
|
||||
};
|
||||
|
||||
x70Panel.ExtenderApplicationControlReservedSigs.Use();
|
||||
x70Panel.ExtenderZoomRoomAppReservedSigs.Use();
|
||||
x70Panel.ExtenderEthernetReservedSigs.Use();
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.Use();
|
||||
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.Button1Off();
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.Button3Off();
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.Button4Off();
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.Button5Off();
|
||||
x70Panel.ExtenderButtonToolbarReservedSigs.Button6Off();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Panel is TswX60WithZoomRoomAppReservedSigs x60withZoomApp)
|
||||
{
|
||||
x60withZoomApp.ExtenderApplicationControlReservedSigs.DeviceExtenderSigChange += (e, a) =>
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X60 App Control Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}");
|
||||
|
||||
if (a.Sig.Number == x60withZoomApp.ExtenderApplicationControlReservedSigs.HideOpenApplicationFeedback.Number)
|
||||
{
|
||||
AppOpenFeedback.FireUpdate();
|
||||
}
|
||||
};
|
||||
x60withZoomApp.ExtenderZoomRoomAppReservedSigs.DeviceExtenderSigChange += (e, a) =>
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X60 Zoom Room App Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}");
|
||||
|
||||
if (a.Sig.Number == x60withZoomApp.ExtenderZoomRoomAppReservedSigs.ZoomRoomIncomingCallFeedback.Number)
|
||||
{
|
||||
ZoomIncomingCallFeedback.FireUpdate();
|
||||
}
|
||||
else if (a.Sig.Number == x60withZoomApp.ExtenderZoomRoomAppReservedSigs.ZoomRoomActiveFeedback.Number)
|
||||
{
|
||||
ZoomInCallFeedback.FireUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
x60withZoomApp.ExtenderEthernetReservedSigs.DeviceExtenderSigChange += (e, a) =>
|
||||
{
|
||||
DeviceInfo.MacAddress = x60withZoomApp.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue;
|
||||
DeviceInfo.IpAddress = x60withZoomApp.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue;
|
||||
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"MAC: {DeviceInfo.MacAddress} IP: {DeviceInfo.IpAddress}");
|
||||
|
||||
var handler = DeviceInfoChanged;
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
handler(this, new DeviceInfoEventArgs(DeviceInfo));
|
||||
};
|
||||
|
||||
x60withZoomApp.ExtenderZoomRoomAppReservedSigs.Use();
|
||||
x60withZoomApp.ExtenderApplicationControlReservedSigs.Use();
|
||||
x60withZoomApp.ExtenderEthernetReservedSigs.Use();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs custom activation setup for the touchpanel controller, including
|
||||
/// registering messengers and linking to mobile control.
|
||||
@@ -323,26 +434,232 @@ namespace PepperDash.Essentials.Touchpanel
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates feedbacks in response to state changes.
|
||||
/// Gets the URL with the correct IP address based on the connected devices and the Crestron processor's IP address.
|
||||
/// </summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="args">The event arguments.</param>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
private string GetUrlWithCorrectIp(string url)
|
||||
{
|
||||
var lanAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetLANAdapter);
|
||||
|
||||
var processorIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, lanAdapterId);
|
||||
|
||||
if(csIpAddress == null || csSubnetMask == null || url == null)
|
||||
{
|
||||
this.LogWarning("CS IP Address Subnet Mask or url is null, cannot determine correct IP for URL");
|
||||
return url;
|
||||
}
|
||||
|
||||
this.LogVerbose("Processor IP: {processorIp}, CS IP: {csIpAddress}, CS Subnet Mask: {csSubnetMask}", processorIp, csIpAddress, csSubnetMask);
|
||||
this.LogVerbose("Connected IP Count: {connectedIps}", ConnectedIps.Count);
|
||||
|
||||
var ip = ConnectedIps.Any(ipInfo =>
|
||||
{
|
||||
if (System.Net.IPAddress.TryParse(ipInfo.DeviceIpAddress, out var parsedIp))
|
||||
{
|
||||
return csIpAddress.IsInSameSubnet(parsedIp, csSubnetMask);
|
||||
}
|
||||
this.LogWarning("Invalid IP address: {deviceIpAddress}", ipInfo.DeviceIpAddress);
|
||||
return false;
|
||||
}) ? csIpAddress.ToString() : processorIp;
|
||||
|
||||
var match = Regex.Match(url, @"^http://([^:/]+):\d+/mc/app\?token=.+$");
|
||||
if (match.Success)
|
||||
{
|
||||
string ipa = match.Groups[1].Value;
|
||||
// ip will be "192.168.1.100"
|
||||
}
|
||||
|
||||
// replace ipa with ip but leave the rest of the string intact
|
||||
var updatedUrl = Regex.Replace(url, @"^http://[^:/]+", $"http://{ip}");
|
||||
|
||||
this.LogVerbose("Updated URL: {updatedUrl}", updatedUrl);
|
||||
|
||||
return updatedUrl;
|
||||
}
|
||||
|
||||
private void SubscribeForMobileControlUpdates()
|
||||
{
|
||||
foreach (var dev in DeviceManager.AllDevices)
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"{dev.Key}:{dev.GetType().Name}");
|
||||
}
|
||||
|
||||
var mcList = DeviceManager.AllDevices.OfType<MobileControlSystemController>().ToList();
|
||||
|
||||
if (mcList.Count == 0)
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"No Mobile Control controller found");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// use first in list, since there should only be one.
|
||||
var mc = mcList[0];
|
||||
|
||||
var bridge = mc.GetRoomBridge(_config.DefaultRoomKey);
|
||||
|
||||
if (bridge == null)
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"No Mobile Control bridge for {_config.DefaultRoomKey} found ");
|
||||
return;
|
||||
}
|
||||
|
||||
_bridge = bridge;
|
||||
|
||||
_bridge.UserCodeChanged += UpdateFeedbacks;
|
||||
_bridge.AppUrlChanged += (s, a) =>
|
||||
{
|
||||
this.LogInformation("AppURL changed: {appURL}", _bridge.AppUrl);
|
||||
SetAppUrl(_bridge.AppUrl);
|
||||
UpdateFeedbacks(s, a);
|
||||
};
|
||||
|
||||
SetAppUrl(_bridge.AppUrl);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the application URL and updates the corresponding feedback.
|
||||
/// </summary>
|
||||
/// <param name="url">The new application URL to set.</param>
|
||||
/// <summary>
|
||||
/// SetAppUrl method
|
||||
/// </summary>
|
||||
public void SetAppUrl(string url)
|
||||
{
|
||||
_appUrl = GetUrlWithCorrectIp(url);
|
||||
|
||||
AppUrlFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
private void UpdateFeedbacks(object sender, EventArgs args)
|
||||
{
|
||||
UpdateFeedbacks();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates all feedback values to reflect current state.
|
||||
/// </summary>
|
||||
private void UpdateFeedbacks()
|
||||
{
|
||||
foreach (var feedback in Feedbacks)
|
||||
foreach (var feedback in Feedbacks) { this.LogDebug("Updating {feedbackKey}", feedback.Key); feedback.FireUpdate(); }
|
||||
}
|
||||
|
||||
private void UpdateZoomFeedbacks()
|
||||
{
|
||||
foreach (var feedback in ZoomFeedbacks)
|
||||
{
|
||||
this.LogDebug("Updating {feedbackKey}", feedback.Key);
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"Updating {feedback.Key}");
|
||||
feedback.FireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// HideOpenApp method
|
||||
/// </summary>
|
||||
public void HideOpenApp()
|
||||
{
|
||||
if (Panel is TswX70Base x70Panel)
|
||||
{
|
||||
x70Panel.ExtenderApplicationControlReservedSigs.HideOpenedApplication();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Panel is TswX60BaseClass x60Panel)
|
||||
{
|
||||
x60Panel.ExtenderApplicationControlReservedSigs.HideOpenApplication();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OpenApp method
|
||||
/// </summary>
|
||||
public void OpenApp()
|
||||
{
|
||||
if (Panel is TswX70Base x70Panel)
|
||||
{
|
||||
x70Panel.ExtenderApplicationControlReservedSigs.OpenApplication();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Panel is TswX60WithZoomRoomAppReservedSigs)
|
||||
{
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"X60 panel does not support zoom app");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CloseOpenApp method
|
||||
/// </summary>
|
||||
public void CloseOpenApp()
|
||||
{
|
||||
if (Panel is TswX70Base x70Panel)
|
||||
{
|
||||
x70Panel.ExtenderApplicationControlReservedSigs.CloseOpenedApplication();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Panel is TswX60WithZoomRoomAppReservedSigs x60Panel)
|
||||
{
|
||||
x60Panel.ExtenderApplicationControlReservedSigs.CloseOpenedApplication();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// EndZoomCall method
|
||||
/// </summary>
|
||||
public void EndZoomCall()
|
||||
{
|
||||
if (Panel is TswX70Base x70Panel)
|
||||
{
|
||||
x70Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomEndCall();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Panel is TswX60WithZoomRoomAppReservedSigs x60Panel)
|
||||
{
|
||||
x60Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomEndCall();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UpdateDeviceInfo method
|
||||
/// </summary>
|
||||
public void UpdateDeviceInfo()
|
||||
{
|
||||
if (Panel is TswXX70Base x70Panel)
|
||||
{
|
||||
DeviceInfo.MacAddress = x70Panel.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue;
|
||||
DeviceInfo.IpAddress = x70Panel.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue;
|
||||
|
||||
var handler = DeviceInfoChanged;
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
handler(this, new DeviceInfoEventArgs(DeviceInfo));
|
||||
}
|
||||
|
||||
if (Panel is TswX60WithZoomRoomAppReservedSigs x60Panel)
|
||||
{
|
||||
DeviceInfo.MacAddress = x60Panel.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue;
|
||||
DeviceInfo.IpAddress = x60Panel.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue;
|
||||
|
||||
var handler = DeviceInfoChanged;
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
handler(this, new DeviceInfoEventArgs(DeviceInfo));
|
||||
}
|
||||
|
||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"MAC: {DeviceInfo.MacAddress} IP: {DeviceInfo.IpAddress}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user