Refactor: Removing unused classes that reference Crestron HTTP classes

- Removed the HttpLogoServer class and its related functionality from ControlSystem.
- Updated ControlSystem to eliminate references to the logo server, including initialization and device checks.
- Cleaned up unused variables and methods related to logo server handling.
This commit is contained in:
Neil Dorin 2026-03-23 11:20:44 -06:00
parent 7137945c94
commit 43a9661e08
7 changed files with 7 additions and 1793 deletions

View file

@ -1,86 +0,0 @@
using System;
namespace PepperDash.Core.WebApi.Presets;
/// <summary>
/// Represents a preset
/// </summary>
public class Preset
{
/// <summary>
/// ID of preset
/// </summary>
public int Id { get; set; }
/// <summary>
/// User ID
/// </summary>
public int UserId { get; set; }
/// <summary>
/// Room Type ID
/// </summary>
public int RoomTypeId { get; set; }
/// <summary>
/// Preset Name
/// </summary>
public string PresetName { get; set; }
/// <summary>
/// Preset Number
/// </summary>
public int PresetNumber { get; set; }
/// <summary>
/// Preset Data
/// </summary>
public string Data { get; set; }
/// <summary>
/// Constructor
/// </summary>
public Preset()
{
PresetName = "";
PresetNumber = 1;
Data = "{}";
}
}
/// <summary>
/// Represents a PresetReceivedEventArgs
/// </summary>
public class PresetReceivedEventArgs : EventArgs
{
/// <summary>
/// True when the preset is found
/// </summary>
public bool LookupSuccess { get; private set; }
/// <summary>
/// S+ helper
/// </summary>
public ushort ULookupSuccess { get { return (ushort)(LookupSuccess ? 1 : 0); } }
/// <summary>
/// The preset
/// </summary>
public Preset Preset { get; private set; }
/// <summary>
/// For Simpl+
/// </summary>
public PresetReceivedEventArgs() { }
/// <summary>
/// Constructor
/// </summary>
/// <param name="preset"></param>
/// <param name="success"></param>
public PresetReceivedEventArgs(Preset preset, bool success)
{
LookupSuccess = success;
Preset = preset;
}
}

View file

@ -1,92 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Core.WebApi.Presets;
/// <summary>
///
/// </summary>
public class User
{
/// <summary>
///
/// </summary>
public int Id { get; set; }
/// <summary>
///
/// </summary>
public string ExternalId { get; set; }
/// <summary>
///
/// </summary>
public string FirstName { get; set; }
/// <summary>
///
/// </summary>
public string LastName { get; set; }
}
/// <summary>
///
/// </summary>
public class UserReceivedEventArgs : EventArgs
{
/// <summary>
/// True when user is found
/// </summary>
public bool LookupSuccess { get; private set; }
/// <summary>
/// For stupid S+
/// </summary>
public ushort ULookupSuccess { get { return (ushort)(LookupSuccess ? 1 : 0); } }
/// <summary>
///
/// </summary>
public User User { get; private set; }
/// <summary>
/// For Simpl+
/// </summary>
public UserReceivedEventArgs() { }
/// <summary>
/// Constructor
/// </summary>
/// <param name="user"></param>
/// <param name="success"></param>
public UserReceivedEventArgs(User user, bool success)
{
LookupSuccess = success;
User = user;
}
}
/// <summary>
/// Represents a UserAndRoomMessage
/// </summary>
public class UserAndRoomMessage
{
/// <summary>
///
/// </summary>
public int UserId { get; set; }
/// <summary>
///
/// </summary>
public int RoomTypeId { get; set; }
/// <summary>
///
/// </summary>
public int PresetNumber { get; set; }
}

View file

@ -1,280 +0,0 @@
extern alias NewtonsoftJson;
using System;
using Crestron.SimplSharp; // For Basic SIMPL# Classes
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Net.Http;
using Crestron.SimplSharp.Net.Https;
using JsonConvert = NewtonsoftJson::Newtonsoft.Json.JsonConvert;
using JObject = NewtonsoftJson::Newtonsoft.Json.Linq.JObject;
using PepperDash.Core.JsonToSimpl;
namespace PepperDash.Core.WebApi.Presets;
/// <summary>
/// Passcode client for the WebApi
/// </summary>
public class WebApiPasscodeClient : IKeyed
{
/// <summary>
/// Notifies when user received
/// </summary>
public event EventHandler<UserReceivedEventArgs> UserReceived;
/// <summary>
/// Notifies when Preset received
/// </summary>
public event EventHandler<PresetReceivedEventArgs> PresetReceived;
/// <summary>
/// Unique identifier for this instance
/// </summary>
public string Key { get; private set; }
//string JsonMasterKey;
/// <summary>
/// An embedded JsonToSimpl master object.
/// </summary>
JsonToSimplGenericMaster J2SMaster;
string UrlBase;
string DefaultPresetJsonFilePath;
User CurrentUser;
Preset CurrentPreset;
/// <summary>
/// SIMPL+ can only execute the default constructor. If you have variables that require initialization, please
/// use an Initialize method
/// </summary>
public WebApiPasscodeClient()
{
}
/// <summary>
/// Initializes the instance
/// </summary>
/// <param name="key"></param>
/// <param name="jsonMasterKey"></param>
/// <param name="urlBase"></param>
/// <param name="defaultPresetJsonFilePath"></param>
public void Initialize(string key, string jsonMasterKey, string urlBase, string defaultPresetJsonFilePath)
{
Key = key;
//JsonMasterKey = jsonMasterKey;
UrlBase = urlBase;
DefaultPresetJsonFilePath = defaultPresetJsonFilePath;
J2SMaster = new JsonToSimplGenericMaster();
J2SMaster.SaveCallback = this.SaveCallback;
J2SMaster.Initialize(jsonMasterKey);
}
/// <summary>
/// Gets the user for a passcode
/// </summary>
/// <param name="passcode"></param>
public void GetUserForPasscode(string passcode)
{
// Bullshit duplicate code here... These two cases should be the same
// except for https/http and the certificate ignores
if (!UrlBase.StartsWith("https"))
return;
var req = new HttpsClientRequest();
req.Url = new UrlParser(UrlBase + "/api/users/dopin");
req.RequestType = Crestron.SimplSharp.Net.Https.RequestType.Post;
req.Header.AddHeader(new HttpsHeader("Content-Type", "application/json"));
req.Header.AddHeader(new HttpsHeader("Accept", "application/json"));
var jo = new JObject();
jo.Add("pin", passcode);
req.ContentString = jo.ToString();
var client = new HttpsClient();
client.HostVerification = false;
client.PeerVerification = false;
var resp = client.Dispatch(req);
var handler = UserReceived;
if (resp.Code == 200)
{
//CrestronConsole.PrintLine("Received: {0}", resp.ContentString);
var user = JsonConvert.DeserializeObject<User>(resp.ContentString);
CurrentUser = user;
if (handler != null)
UserReceived(this, new UserReceivedEventArgs(user, true));
}
else
if (handler != null)
UserReceived(this, new UserReceivedEventArgs(null, false));
}
/// <summary>
///
/// </summary>
/// <param name="roomTypeId"></param>
/// <param name="presetNumber"></param>
/// <summary>
/// GetPresetForThisUser method
/// </summary>
public void GetPresetForThisUser(int roomTypeId, int presetNumber)
{
if (CurrentUser == null)
{
CrestronConsole.PrintLine("GetPresetForThisUser no user loaded");
return;
}
var msg = new UserAndRoomMessage
{
UserId = CurrentUser.Id,
RoomTypeId = roomTypeId,
PresetNumber = presetNumber
};
var handler = PresetReceived;
try
{
if (!UrlBase.StartsWith("https"))
return;
var req = new HttpsClientRequest();
req.Url = new UrlParser(UrlBase + "/api/presets/userandroom");
req.RequestType = Crestron.SimplSharp.Net.Https.RequestType.Post;
req.Header.AddHeader(new HttpsHeader("Content-Type", "application/json"));
req.Header.AddHeader(new HttpsHeader("Accept", "application/json"));
req.ContentString = JsonConvert.SerializeObject(msg);
var client = new HttpsClient();
client.HostVerification = false;
client.PeerVerification = false;
// ask for the preset
var resp = client.Dispatch(req);
if (resp.Code == 200) // got it
{
//Debug.Console(1, this, "Received: {0}", resp.ContentString);
var preset = JsonConvert.DeserializeObject<Preset>(resp.ContentString);
CurrentPreset = preset;
//if there's no preset data, load the template
if (preset.Data == null || preset.Data.Trim() == string.Empty || JObject.Parse(preset.Data).Count == 0)
{
//Debug.Console(1, this, "Loaded preset has no data. Loading default template.");
LoadDefaultPresetData();
return;
}
J2SMaster.LoadWithJson(preset.Data);
if (handler != null)
PresetReceived(this, new PresetReceivedEventArgs(preset, true));
}
else // no existing preset
{
CurrentPreset = new Preset();
LoadDefaultPresetData();
if (handler != null)
PresetReceived(this, new PresetReceivedEventArgs(null, false));
}
}
catch (HttpException e)
{
var resp = e.Response;
Debug.Console(1, this, "No preset received (code {0}). Loading default template", resp.Code);
LoadDefaultPresetData();
if (handler != null)
PresetReceived(this, new PresetReceivedEventArgs(null, false));
}
}
void LoadDefaultPresetData()
{
CurrentPreset = null;
if (!File.Exists(DefaultPresetJsonFilePath))
{
Debug.Console(0, this, "Cannot load default preset file. Saving will not work");
return;
}
using (StreamReader sr = new StreamReader(DefaultPresetJsonFilePath))
{
try
{
var data = sr.ReadToEnd();
J2SMaster.SetJsonWithoutEvaluating(data);
CurrentPreset = new Preset() { Data = data, UserId = CurrentUser.Id };
}
catch (Exception e)
{
Debug.Console(0, this, "Error reading default preset JSON: \r{0}", e);
}
}
}
/// <summary>
///
/// </summary>
/// <param name="roomTypeId"></param>
/// <param name="presetNumber"></param>
/// <summary>
/// SavePresetForThisUser method
/// </summary>
public void SavePresetForThisUser(int roomTypeId, int presetNumber)
{
if (CurrentPreset == null)
LoadDefaultPresetData();
//return;
//// A new preset needs to have its numbers set
//if (CurrentPreset.IsNewPreset)
//{
CurrentPreset.UserId = CurrentUser.Id;
CurrentPreset.RoomTypeId = roomTypeId;
CurrentPreset.PresetNumber = presetNumber;
//}
J2SMaster.Save(); // Will trigger callback when ready
}
/// <summary>
/// After save operation on JSON master happens, send it to server
/// </summary>
/// <param name="json"></param>
void SaveCallback(string json)
{
CurrentPreset.Data = json;
if (!UrlBase.StartsWith("https"))
return;
var req = new HttpsClientRequest();
req.RequestType = Crestron.SimplSharp.Net.Https.RequestType.Post;
req.Url = new UrlParser(string.Format("{0}/api/presets/addorchange", UrlBase));
req.Header.AddHeader(new HttpsHeader("Content-Type", "application/json"));
req.Header.AddHeader(new HttpsHeader("Accept", "application/json"));
req.ContentString = JsonConvert.SerializeObject(CurrentPreset);
var client = new HttpsClient();
client.HostVerification = false;
client.PeerVerification = false;
try
{
var resp = client.Dispatch(req);
// 201=created
// 204=empty content
if (resp.Code == 201)
CrestronConsole.PrintLine("Preset added");
else if (resp.Code == 204)
CrestronConsole.PrintLine("Preset updated");
else if (resp.Code == 209)
CrestronConsole.PrintLine("Preset already exists. Cannot save as new.");
else
CrestronConsole.PrintLine("Preset save failed: {0}\r", resp.Code, resp.ContentString);
}
catch (HttpException e)
{
CrestronConsole.PrintLine("Preset save exception {0}", e.Response.Code);
}
}
}

View file

@ -1,259 +0,0 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Crestron.SimplSharp.Net.Http;
using Crestron.SimplSharpPro.Diagnostics;
using PepperDash.Core;
using Serilog.Events;
namespace PepperDash.Essentials.Core.Config;
public static class ConfigUpdater
{
public static event EventHandler<ConfigStatusEventArgs> ConfigStatusChanged;
public static void GetConfigFromServer(string url)
{
Debug.LogMessage(LogEventLevel.Information, "Attempting to get new config from '{0}'", url);
// HTTP GET
var req = new HttpClientRequest();
try
{
req.RequestType = RequestType.Get;
req.Url.Parse(url);
new HttpClient().DispatchAsync(req, (r, e) =>
{
if (e == HTTP_CALLBACK_ERROR.COMPLETED)
{
if (r.Code == 200)
{
var newConfig = r.ContentString;
OnStatusUpdate(eUpdateStatus.ConfigFileReceived);
ArchiveExistingPortalConfigs();
CheckForLocalConfigAndDelete();
WriteConfigToFile(newConfig);
RestartProgram();
}
else
{
Debug.LogMessage(LogEventLevel.Information, "Config Update Process Stopped. Failed to get config file from server: {0}", r.Code);
OnStatusUpdate(eUpdateStatus.UpdateFailed);
}
}
else
Debug.LogMessage(LogEventLevel.Information, "Request for config from Server Failed: {0}", e);
});
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Debug, "Error Getting Config from Server: {0}", e);
}
}
static void OnStatusUpdate(eUpdateStatus status)
{
var handler = ConfigStatusChanged;
if(handler != null)
{
handler(typeof(ConfigUpdater), new ConfigStatusEventArgs(status));
}
}
static void WriteConfigToFile(string configData)
{
var filePath = Global.FilePathPrefix+ "configurationFile-updated.json";
try
{
var config = JObject.Parse(configData).ToObject<EssentialsConfig>();
ConfigWriter.WriteFile(filePath, configData);
OnStatusUpdate(eUpdateStatus.WritingConfigFile);
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Debug, "Error parsing new config: {0}", e);
OnStatusUpdate(eUpdateStatus.UpdateFailed);
}
}
/// <summary>
/// Checks for any existing portal config files and archives them
/// </summary>
static void ArchiveExistingPortalConfigs()
{
var filePath = Global.FilePathPrefix + Global.ConfigFileName;
var configFiles = ConfigReader.GetConfigFiles(filePath);
if (configFiles != null)
{
Debug.LogMessage(LogEventLevel.Information, "Existing config files found. Moving to Archive folder.");
OnStatusUpdate(eUpdateStatus.ArchivingConfigs);
MoveFilesToArchiveFolder(configFiles);
}
else
{
Debug.LogMessage(LogEventLevel.Information, "No Existing config files found in '{0}'. Nothing to archive", filePath);
}
}
/// <summary>
/// Checks for presence of archive folder and if found deletes contents.
/// Moves any config files to the archive folder and adds a .bak suffix
/// </summary>
/// <param name="files"></param>
static void MoveFilesToArchiveFolder(FileInfo[] files)
{
string archiveDirectoryPath = Global.FilePathPrefix + "archive";
if (!Directory.Exists(archiveDirectoryPath))
{
// Directory does not exist, create it
Directory.Create(archiveDirectoryPath);
}
else
{
// Directory exists, first clear any contents
var archivedConfigFiles = ConfigReader.GetConfigFiles(archiveDirectoryPath + Global.DirectorySeparator + Global.ConfigFileName + ".bak");
if(archivedConfigFiles != null || archivedConfigFiles.Length > 0)
{
Debug.LogMessage(LogEventLevel.Information, "{0} Existing files found in archive folder. Deleting.", archivedConfigFiles.Length);
for (int i = 0; i < archivedConfigFiles.Length; i++ )
{
var file = archivedConfigFiles[i];
Debug.LogMessage(LogEventLevel.Information, "Deleting archived file: '{0}'", file.FullName);
file.Delete();
}
}
}
// Move any files from the program folder to the archive folder
foreach (var file in files)
{
Debug.LogMessage(LogEventLevel.Information, "Moving config file '{0}' to archive folder", file.FullName);
// Moves the file and appends the .bak extension
var fileDest = archiveDirectoryPath + "/" + file.Name + ".bak";
if(!File.Exists(fileDest))
{
file.MoveTo(fileDest);
}
else
Debug.LogMessage(LogEventLevel.Information, "Cannot move file to archive folder. Existing file already exists with same name: '{0}'", fileDest);
}
}
/// <summary>
/// Checks for LocalConfig folder in file system and deletes if found
/// </summary>
static void CheckForLocalConfigAndDelete()
{
var folderPath = Global.FilePathPrefix + ConfigWriter.LocalConfigFolder;
if (Directory.Exists(folderPath))
{
OnStatusUpdate(eUpdateStatus.DeletingLocalConfig);
Directory.Delete(folderPath);
Debug.LogMessage(LogEventLevel.Information, "Local Config Found in '{0}'. Deleting.", folderPath);
}
}
/// <summary>
/// Connects to the processor via SSH and restarts the program
/// </summary>
static void RestartProgram()
{
Debug.LogMessage(LogEventLevel.Information, "Attempting to Reset Program");
OnStatusUpdate(eUpdateStatus.RestartingProgram);
string response = string.Empty;
CrestronConsole.SendControlSystemCommand(string.Format("progreset -p:{0}", InitialParametersClass.ApplicationNumber), ref response);
Debug.LogMessage(LogEventLevel.Debug, "Console Response: {0}", response);
}
}
/// <summary>
/// Enumeration of eUpdateStatus values
/// </summary>
public enum eUpdateStatus
{
/// <summary>
/// UpdateStarted status
/// </summary>
UpdateStarted,
/// <summary>
/// ConfigFileReceived status
/// </summary>
ConfigFileReceived,
/// <summary>
/// ArchivingConfigs status
/// </summary>
ArchivingConfigs,
/// <summary>
/// DeletingLocalConfig status
/// </summary>
DeletingLocalConfig,
/// <summary>
/// WritingConfigFile status
/// </summary>
WritingConfigFile,
/// <summary>
/// RestartingProgram status
/// </summary>
RestartingProgram,
/// <summary>
/// UpdateSucceeded status
/// </summary>
UpdateSucceeded,
/// <summary>
/// UpdateFailed status
/// </summary>
UpdateFailed
}
public class ConfigStatusEventArgs : EventArgs
{
public eUpdateStatus UpdateStatus { get; private set; }
public ConfigStatusEventArgs(eUpdateStatus status)
{
UpdateStatus = status;
}
}

View file

@ -1,881 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="PepperDash.Essentials.EssentialsRoomVolumesConfig" Collapsed="true">
<Position X="19.25" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAQAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAIAgA=</HashCode>
<FileName>Audio\EssentialsVolumeLevelConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.EssentialsVolumeLevelConfig" Collapsed="true">
<Position X="22.75" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAEAAAAAAAAAAAAAAAAIAAAAgBAAAAAAAAAAA=</HashCode>
<FileName>Audio\EssentialsVolumeLevelConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.ConfigReader" Collapsed="true">
<Position X="26.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAIAAAAAAAABAAAACAAIAAAAQAAAAAAAAAAEAA=</HashCode>
<FileName>Config\ConfigReader.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.DeviceFactory" Collapsed="true">
<Position X="29.75" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAA=</HashCode>
<FileName>Config\DeviceFactory.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.EssentialsConfig" Collapsed="true">
<Position X="33.25" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAEAAAAAQAIAAAAAAAACAAAAAAAAAAAAAAEAAAA=</HashCode>
<FileName>Config\EssentialsConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.SystemTemplateConfigs" Collapsed="true">
<Position X="33.25" Y="7.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Config\EssentialsConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.ConfigTieLine" Collapsed="true">
<Position X="31.5" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAgEAAAAAAEAAAAAAAAAAAAAAAAAAAAAEAIAIA=</HashCode>
<FileName>Configuration ORIGINAL\ConfigTieLine.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Configuration" Collapsed="true">
<Position X="33.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AEAAAAAAAAAAgQAAAAAAgAAAAAAAAAAAAAAgEDAADAQ=</HashCode>
<FileName>Configuration ORIGINAL\Configuration.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.ConfigSourceList" Collapsed="true">
<Position X="29.75" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAQAAAAAAAQAAACAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Configuration ORIGINAL\Configuration.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.ConfigSourceItem" Collapsed="true">
<Position X="28" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAgAAAAAAAEAAAAAAAAAAAAAAAAAgAAAAAAA=</HashCode>
<FileName>Configuration ORIGINAL\Configuration.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.ConfigInfo" Collapsed="true">
<Position X="24.5" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>IQAAAAAEAAAAAAADAAACABQAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Configuration ORIGINAL\Configuration.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.SourceListConfigProperties" Collapsed="true">
<Position X="24.5" Y="7.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAEAAAAAAAAAAAIAAAAAgAAAIAAA=</HashCode>
<FileName>Configuration ORIGINAL\ConfigurationHelpers.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.DmFactory" Collapsed="true">
<Position X="31.5" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAQAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAA=</HashCode>
<FileName>Configuration ORIGINAL\Factories\DmFactory.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.FactoryHelper" Collapsed="true">
<Position X="26.25" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAEDAAKAA=</HashCode>
<FileName>Configuration ORIGINAL\Factories\FactoryHelper.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.IrOutPortConfig" Collapsed="true">
<Position X="31.5" Y="4.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAABAAAA=</HashCode>
<FileName>Configuration ORIGINAL\Factories\FactoryHelper.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.ControlSystem" Collapsed="true">
<Position X="35" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAoAgAAIAEAACAAEAIEIBICAAAAAAABAAAAAAAAAAAA=</HashCode>
<FileName>ControlSystem.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Amplifier" Collapsed="true" BaseTypeListCollapsed="true">
<Position X="21" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAA=</HashCode>
<FileName>Devices\Amplifier.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" Collapsed="true" />
</Class>
<Class Name="PepperDash.Essentials.CotijaConfig" Collapsed="true">
<Position X="19.25" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAA=</HashCode>
<FileName>Room\Cotija\CotijaConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.CotijaDdvc01RoomBridgePropertiesConfig" Collapsed="true">
<Position X="22.75" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Cotija\CotijaConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.CotijaSystemController" Collapsed="true">
<Position X="24.5" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>CAAABAABAgACCAKGBIAAEyBAFAAACYSAgIAAAAJkAAA=</HashCode>
<FileName>Room\Cotija\CotijaSystemController.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.CotijaBridgeBase" Collapsed="true">
<Position X="9.5" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAQIQAAAAAAAAgAAAAAAQAAAAAAAAAAAAAAAABAAAAA=</HashCode>
<FileName>Room\Cotija\RoomBridges\CotijaBridgeBase.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.CotijaEssentialsHuddleSpaceRoomBridge" Collapsed="true">
<Position X="8.25" Y="5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAIAAAAIABAAkgAABgIAAAAAAAAAEAAAAAAgBAAACA=</HashCode>
<FileName>Room\Cotija\RoomBridges\CotijaEssentialsHuddleSpaceRoomBridge.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.SourceSelectMessageContent" Collapsed="true">
<Position X="26.25" Y="7.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAA=</HashCode>
<FileName>Room\Cotija\RoomBridges\CotijaEssentialsHuddleSpaceRoomBridge.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.EssentialsHuddleSpaceRoom" Collapsed="true">
<Position X="0.5" Y="9" Width="1.5" />
<TypeIdentifier>
<HashCode>iQFBQAIAAgAAgQAEQACAMABAAABAACAQUAAQAAgCgBA=</HashCode>
<FileName>Room\Types\EssentialsHuddleSpaceRoom.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" />
</Class>
<Class Name="PepperDash.Essentials.EssentialsHuddleVtc1Room" Collapsed="true">
<Position X="2.75" Y="9" Width="1.5" />
<TypeIdentifier>
<HashCode>iQFBQAIAIgQMgQAEQAigMABAAABAADIwUACQAAgCgTE=</HashCode>
<FileName>Room\Types\EssentialsHuddleVtc1Room.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" />
</Class>
<Class Name="PepperDash.Essentials.EssentialsPresentationRoom" Collapsed="true">
<Position X="5" Y="9" Width="1.5" />
<TypeIdentifier>
<HashCode>iQAEAAIACkAAAQAOQASgMAAJAABgAAAQQAAQAAgCgBA=</HashCode>
<FileName>Room\Types\EssentialsPresentationRoom.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" />
</Class>
<Class Name="PepperDash.Essentials.EssentialsRoomBase" Collapsed="true">
<Position X="2.75" Y="7.5" Width="1.5" />
<TypeIdentifier>
<HashCode>gQAAEAICECgCAQAEAAAUIwIyAAAAgACiAgAAAQECAgA=</HashCode>
<FileName>Room\Types\EssentialsRoomBase.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.CrestronTouchpanelPropertiesConfig" Collapsed="true">
<Position X="26.25" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AICCIAAIGIAAAAAgCAAIAEAAAAAAAAAAAAEAIAAAAAA=</HashCode>
<FileName>UI\CrestronTouchpanelPropertiesConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.UiSetupPropertiesConfig" Collapsed="true">
<Position X="19.25" Y="8.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>UI\CrestronTouchpanelPropertiesConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.EssentialsTouchpanelController" Collapsed="true">
<Position X="21" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAIAEAAAAAAAAAAAAAAAAEAAAAACKIBAAgACAAAAAA=</HashCode>
<FileName>UI\EssentialsTouchpanelController.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.HttpLogoServer" Collapsed="true">
<Position X="19.25" Y="4.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAQAAAACAAAAABAAAAAAAAAABAAAAAAAAAAkAAAAA=</HashCode>
<FileName>UI\HttpLogoServer.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.UIBoolJoin" Collapsed="true">
<Position X="35" Y="7.5" Width="1.5" />
<TypeIdentifier>
<HashCode>j+jWCNqEIGzi4UTaTgyn37kpncQJK7L42VMLmMgTE5A=</HashCode>
<FileName>UI\JoinConstants\UIBoolJoin.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.UISmartObjectJoin" Collapsed="true">
<Position X="21" Y="8.5" Width="1.5" />
<TypeIdentifier>
<HashCode>BAggBIABCQAAGAAQAAAACAACAAAAAAAAAAIAAAAAAAA=</HashCode>
<FileName>UI\JoinConstants\UISmartObjectJoin.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.UIStringJoin" Collapsed="true">
<Position X="22.75" Y="8.5" Width="1.5" />
<TypeIdentifier>
<HashCode>BkBgIAgAAggOQAFGAYQIABACgCEBjkSQAUEAASIABCE=</HashCode>
<FileName>UI\JoinConstants\UIStringlJoin.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.UIUshortJoin" Collapsed="true">
<Position X="24.5" Y="8.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAQAAAACAAAACAEAAIAAAAAAIABAIAAAABAAAEAAAAA=</HashCode>
<FileName>UI\JoinConstants\UIUshortJoin.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.SubpageReferenceListActivityItem" Collapsed="true">
<Position X="28" Y="7.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA=</HashCode>
<FileName>UI\SubpageReferenceListActivityItem.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.SubpageReferenceListButtonAndModeItem" Collapsed="true">
<Position X="29.75" Y="7.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA=</HashCode>
<FileName>UI\SubpageReferenceListCallStagingItem.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.SubpageReferenceListSourceItem" Collapsed="true">
<Position X="31.5" Y="7.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAABAAAAAAAAAAAAAAAAAAAAgAAAAACAAAAAABgAAA=</HashCode>
<FileName>UI\SubpageReferenceListSourceItem.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.PanelDriverBase" Collapsed="true">
<Position X="8.75" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>CAAIkAAAAAAQEAAAEAACAAAAAIAEABAAAgAACAAAAAA=</HashCode>
<FileName>UIDrivers\enums and base.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.EssentialsPanelMainInterfaceDriver" Collapsed="true">
<Position X="1" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>ABAAAAAAAhgAAAAAEAAAAAAAAIAEAAAAAAAAAAAAAAA=</HashCode>
<FileName>UIDrivers\Essentials\EssentialsPanelMainInterfaceDriver.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.EssentialsPresentationPanelAvFunctionsDriver" Collapsed="true">
<Position X="3.25" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>gTEAIIAiCggFNCQ4EA4AWBkAKJCEqAAOS4CKMAQQJQA=</HashCode>
<FileName>UIDrivers\Essentials\EssentialsPresentationPanelAvFunctionsDriver.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.EssentialsHuddlePanelAvFunctionsDriver" Collapsed="true">
<Position X="7.75" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>gRQAIICuAghENHQpEA4IWCkBMJDEsEAEC4CAMARQIBA=</HashCode>
<FileName>UIDrivers\EssentialsHuddle\EssentialsHuddlePanelAvFunctionsDriver.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.EssentialsHuddleVtc1PanelAvFunctionsDriver" Collapsed="true">
<Position X="12.25" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>GRwAIYC+oghAeHStEDAIWCdBMADEsBAcDwCAMARYIBg=</HashCode>
<FileName>UIDrivers\EssentialsHuddleVTC\EssentialsHuddleVtc1PanelAvFunctionsDriver.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" />
</Class>
<Class Name="PepperDash.Essentials.JoinedSigInterlock" Collapsed="true">
<Position X="19.25" Y="5.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAQgAIAAAAAAAAAEAAAAAQAAAAEAAAAAAAAEAAAgAA=</HashCode>
<FileName>UIDrivers\JoinedSigInterlock.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.SingleSubpageModalAndBackDriver" Collapsed="true">
<Position X="14.5" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAEAAAQAAABIAEAAAAAAAAAAAAAAA=</HashCode>
<FileName>UIDrivers\Page Drivers\SingleSubpageModalAndBackDriver.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.SingleSubpageModalDriver" Collapsed="true">
<Position X="16.75" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAEAAAAAAABAAEAAAAAAAAAAAAAAA=</HashCode>
<FileName>UIDrivers\Page Drivers\SingleSubpageModalDriver.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.SigInterlock" Collapsed="true">
<Position X="19.25" Y="7.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAQAAIAAAAAAAAIEAAAAAAAAAAEAAAAAAAAEAAAgAA=</HashCode>
<FileName>UIDrivers\SigInterlock.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.SmartObjectRoomsList" Collapsed="true">
<Position X="21" Y="7.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAACAAACBAAAAAAAAAAAAAAAAAAAAIAAAAAAQA=</HashCode>
<FileName>UIDrivers\SmartObjectRoomsList.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.SmartObjectRoomsListItem" Collapsed="true">
<Position X="22.75" Y="7.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAQAAAAAAAAAAAABAAQAAAAAAAAAACAAEAAAAAAAA=</HashCode>
<FileName>UIDrivers\SmartObjectRoomsList.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.VolumeDeviceChangeEventArgs" Collapsed="true">
<Position X="26.25" Y="8.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAABAAAAAEAAAAAAAAAAAAAAAAAAAQAAAAAAAAA=</HashCode>
<FileName>UIDrivers\VolumeAndSourceChangeArgs.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase" Collapsed="true">
<Position X="8.25" Y="9.5" Width="1.5" />
<TypeIdentifier>
<HashCode>IAGigRBpCgZwAIMSBBIbIgAAImAPtEBiAAgECpJgKQo=</HashCode>
<FileName>OTHER\Fusion\EssentialsHuddleSpaceFusionSystemControllerBase.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" />
</Class>
<Class Name="PepperDash.Essentials.Fusion.FusionRoomExtensions" Collapsed="true">
<Position X="31.5" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAACgAIQAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\EssentialsHuddleSpaceFusionSystemControllerBase.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.FusionStaticAssetExtensions" Collapsed="true">
<Position X="35" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAQAAACAAAAAAAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\EssentialsHuddleSpaceFusionSystemControllerBase.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.EssentialsHuddleVtc1FusionController" Collapsed="true">
<Position X="8.25" Y="11" Width="1.5" />
<TypeIdentifier>
<HashCode>AACAAAAAAgAAAIAAAAAAAAAgIBAQAAAAAAAAAAAAAQA=</HashCode>
<FileName>OTHER\Fusion\EssentialsHuddleVtc1FusionController.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.ScheduleChangeEventArgs" Collapsed="true">
<Position X="33.25" Y="6.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionEventHandlers.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.MeetingChangeEventArgs" Collapsed="true">
<Position X="26.25" Y="5.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionEventHandlers.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.ProcessorProgReg" Collapsed="true">
<Position X="19.25" Y="6.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionProcessorQueries.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.ProcessorProgramItem" Collapsed="true">
<Position X="35" Y="5.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAEAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionProcessorQueries.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.FusionRoomGuids" Collapsed="true">
<Position X="33.25" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAICAAAAAAAAAAAAAAAAAACAAAATQAAAAAAAABAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.FusionOccupancySensorAsset" Collapsed="true">
<Position X="29.75" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAQAQAAAAAAAAQAAAAAAQAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.FusionAsset" Collapsed="true">
<Position X="28" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAQAQAAAAAAAAQAAAAAAQAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.RoomSchedule" Collapsed="true">
<Position X="31.5" Y="6.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.LocalTimeRequest" Collapsed="true">
<Position X="24.5" Y="5.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.RequestSchedule" Collapsed="true">
<Position X="22.75" Y="6.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAACACAAAAQAAAAAAAAAAAAAAAAAAAACAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.RequestAction" Collapsed="true">
<Position X="21" Y="6.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAACAAAgAAQAAAAAAAAAAAAAAAAAAIAAAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.ActionResponse" Collapsed="true">
<Position X="19.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAgAAQAAAAAAAAAAAAAAAAAAIAAAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.Parameter" Collapsed="true">
<Position X="33.25" Y="5.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAgAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.ScheduleResponse" Collapsed="true">
<Position X="35" Y="6.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAACAAAAAAQAAAAAAAAAAgAAAAAAAAAAABAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.Event" Collapsed="true">
<Position X="24.5" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AABCAAAAYEAAEBIBAIAAJAQAQKAYAAAIEAAAEAACCgg=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.Resources" Collapsed="true">
<Position X="26.25" Y="6.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.Rooms" Collapsed="true">
<Position X="29.75" Y="6.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.Room" Collapsed="true">
<Position X="28" Y="6.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAgAAAAAAAAAQAAAAAAAAAAAAAAAAEAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.Attendees" Collapsed="true">
<Position X="22.75" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAABAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.Required" Collapsed="true">
<Position X="24.5" Y="6.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.Optional" Collapsed="true">
<Position X="31.5" Y="5.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.MeetingType" Collapsed="true">
<Position X="28" Y="5.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAgAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.MeetingTypes" Collapsed="true">
<Position X="29.75" Y="5.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.LiveMeeting" Collapsed="true">
<Position X="21" Y="5.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAgAQAAIAAAAAAACAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Fusion.LiveMeetingURL" Collapsed="true">
<Position X="22.75" Y="5.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.DDVC01RoomPropertiesConfig" Collapsed="true">
<Position X="5" Y="6.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAIAgAAQAAAAAAAAEAAAAAAA=</HashCode>
<FileName>Room\Config\DDVC01RoomPropertiesConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.DDVC01SpeedDial" Collapsed="true">
<Position X="28" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAEAAAAQAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Config\DDVC01RoomPropertiesConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.EssentialsHuddleRoomPropertiesConfig" Collapsed="true">
<Position X="2.75" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAgAAAAAAAAAAACAAAAAABAAAAAAAAABA=</HashCode>
<FileName>Room\Config\EssentialsHuddleRoomPropertiesConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.EssentialsHuddleVtc1PropertiesConfig" Collapsed="true">
<Position X="5" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAgAAAAAAAAAAACIAAAAABAAAAAAAAABA=</HashCode>
<FileName>Room\Config\EssentialsHuddleVtc1PropertiesConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.EssentialsPresentationRoomPropertiesConfig" Collapsed="true">
<Position X="0.5" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAACAIAAAAAAAAAAABAACAAAAAABAAAAAAAAABA=</HashCode>
<FileName>Room\Config\EssentialsPresentationPropertiesConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomConfig" Collapsed="true">
<Position X="26.25" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAEAAAAAA=</HashCode>
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomPropertiesConfig" Collapsed="true">
<Position X="2.75" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AABAEQAAAAEoAAEEAAQAAAACAAAAAAgggAAAAQAAAgA=</HashCode>
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.EssentialsLightingPropertiesConfig" Collapsed="true">
<Position X="19.25" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomMicrophonePrivacyConfig" Collapsed="true">
<Position X="31.5" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAEAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.EssentialsHelpPropertiesConfig" Collapsed="true">
<Position X="35" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAgABAAAAAIAAAAAA=</HashCode>
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.EssentialsOneButtonMeetingPropertiesConfig" Collapsed="true">
<Position X="22.75" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomAddressPropertiesConfig" Collapsed="true">
<Position X="24.5" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAQAAAgAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.EssentialsLogoPropertiesConfig" Collapsed="true">
<Position X="21" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIACQAAAAAAAAA=</HashCode>
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomOccSensorConfig" Collapsed="true">
<Position X="33.25" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AACAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomTechConfig" Collapsed="true">
<Position X="35" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAA=</HashCode>
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomEmergencyConfig" Collapsed="true">
<Position X="28" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAABAACAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Config\EssentialsRoomEmergencyConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomEmergencyTriggerConfig" Collapsed="true">
<Position X="29.75" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAABQAAAAAAAAA=</HashCode>
<FileName>Room\Config\EssentialsRoomEmergencyConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Cotija.CotijaDdvc01DeviceBridge" Collapsed="true" BaseTypeListCollapsed="true">
<Position X="21" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AUAAAAgAAAACwAYAAAAAAAEAAAAAAAAAIcAAAEAAAAA=</HashCode>
<FileName>Room\Cotija\CotijaDdvc01DeviceBridge.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" Collapsed="true" />
</Class>
<Class Name="PepperDash.Essentials.Room.Cotija.IChannelExtensions" Collapsed="true">
<Position X="21" Y="4.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Cotija\DeviceTypeInterfaces\IChannelExtensions.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Cotija.IColorExtensions" Collapsed="true">
<Position X="22.75" Y="4.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Cotija\DeviceTypeInterfaces\IColorExtensions.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Cotija.IDPadExtensions" Collapsed="true">
<Position X="24.5" Y="4.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Cotija\DeviceTypeInterfaces\IDPadExtensions.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Cotija.IDvrExtensions" Collapsed="true">
<Position X="26.25" Y="4.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Cotija\DeviceTypeInterfaces\IDvrExtensions.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Cotija.INumericExtensions" Collapsed="true">
<Position X="28" Y="4.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Cotija\DeviceTypeInterfaces\INumericExtensions.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Cotija.IPowerExtensions" Collapsed="true">
<Position X="29.75" Y="4.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Cotija\DeviceTypeInterfaces\IPowerExtensions.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Cotija.ISetTopBoxControlsExtensions" Collapsed="true">
<Position X="33.25" Y="4.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Cotija\DeviceTypeInterfaces\ISetTopBoxControlsExtensions.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Cotija.ITransportExtensions" Collapsed="true">
<Position X="35" Y="4.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Cotija\DeviceTypeInterfaces\ITransportExtensions.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.Room.Cotija.CotijaDdvc01RoomBridge" Collapsed="true">
<Position X="10.5" Y="5" Width="1.5" />
<TypeIdentifier>
<HashCode>gACIAAAAAAICAFAAAACAAAEIIAAAAAQAQAAAABAAAAA=</HashCode>
<FileName>Room\Cotija\RoomBridges\CotijaDdvc01RoomBridge.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" />
</Class>
<Class Name="PepperDash.Essentials.Room.EssentialsRoomEmergencyBase" Collapsed="true">
<Position X="8.25" Y="6.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Emergency\EsentialsRoomEmergencyContactClosure.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" />
</Class>
<Class Name="PepperDash.Essentials.Room.EssentialsRoomEmergencyContactClosure" Collapsed="true">
<Position X="8.25" Y="7.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAASBAAAAAAAAAAAAAABAAAAAAAEAA=</HashCode>
<FileName>Room\Emergency\EsentialsRoomEmergencyContactClosure.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.UIDrivers.EssentialsHuddleTechPageDriver" Collapsed="true">
<Position X="5.5" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAQAAAAAiACDAAAGCAACgAIAABECBAgQAAAAQAAAAA=</HashCode>
<FileName>UIDrivers\EssentialsHuddle\EssentialsHuddleTechPageDriver.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver" Collapsed="true">
<Position X="10" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>XAASAoAiAagwAcBAGAUURWQEOHQFAKCmAABCNSSEDPA=</HashCode>
<FileName>UIDrivers\VC\EssentialsVideoCodecUiDriver.cs</FileName>
</TypeIdentifier>
</Class>
<Interface Name="PepperDash.Essentials.IHasCurrentSourceInfoChange" Collapsed="true">
<Position X="22.75" Y="9.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Types\EssentialsRoomBase.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="PepperDash.Essentials.IAVDriver" Collapsed="true">
<Position X="19.25" Y="9.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAgAAAAAAAAACBAAACAAAAIBAAAEAAAEAgAAAAAAIAA=</HashCode>
<FileName>UIDrivers\EssentialsHuddleVTC\EssentialsHuddleVtc1PanelAvFunctionsDriver.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="PepperDash.Essentials.Room.Cotija.IDelayedConfiguration" Collapsed="true">
<Position X="21" Y="9.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA=</HashCode>
<FileName>Room\Cotija\Interfaces.cs</FileName>
</TypeIdentifier>
</Interface>
<Enum Name="PepperDash.Essentials.eShutdownType" Collapsed="true">
<Position X="29.75" Y="10.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAQAAAAAAACAAAAAAAAAAAAAAAAAAAAAEACAA=</HashCode>
<FileName>Room\Types\EssentialsRoomBase.cs</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="PepperDash.Essentials.eVacancyMode" Collapsed="true">
<Position X="31.5" Y="10.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAACAAAAAAAAAAAAAAAAACAAAAAAAAAAEAAAA=</HashCode>
<FileName>Room\Types\EssentialsRoomBase.cs</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="PepperDash.Essentials.eWarmingCoolingMode" Collapsed="true">
<Position X="33.25" Y="10.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAIEAAAA=</HashCode>
<FileName>Room\Types\EssentialsRoomBase.cs</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="PepperDash.Essentials.eAvSubpageType" Collapsed="true">
<Position X="24.5" Y="10.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AIAAAAAAAAAAAAAAAhBAAAAAAAAAAACYAAAAAAAAAAA=</HashCode>
<FileName>UIDrivers\enums and base.cs</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="PepperDash.Essentials.eAvSourceSubpageType" Collapsed="true">
<Position X="22.75" Y="10.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAABAAAAAAAAAAAAAAACAAAEAAAAAAAAA=</HashCode>
<FileName>UIDrivers\enums and base.cs</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="PepperDash.Essentials.eCommonSubpageType" Collapsed="true">
<Position X="28" Y="10.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAEAAAAAAAAAIAAAAAAAAQAAAAQAAAAAAAAAAA=</HashCode>
<FileName>UIDrivers\enums and base.cs</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="PepperDash.Essentials.eAvSmartObjects" Collapsed="true">
<Position X="21" Y="10.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAABAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>UIDrivers\enums and base.cs</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="PepperDash.Essentials.eCommonSmartObjects" Collapsed="true">
<Position X="26.25" Y="10.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>UIDrivers\enums and base.cs</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="PepperDash.Essentials.ChangeType" Collapsed="true">
<Position X="19.25" Y="10.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>UIDrivers\VolumeAndSourceChangeArgs.cs</FileName>
</TypeIdentifier>
</Enum>
<Delegate Name="PepperDash.Essentials.PressAndHoldAction" Collapsed="true">
<Position X="19.25" Y="11.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Room\Cotija\RoomBridges\CotijaEssentialsHuddleSpaceRoomBridge.cs</FileName>
</TypeIdentifier>
</Delegate>
<Delegate Name="PepperDash.Essentials.SourceInfoChangeHandler" Collapsed="true">
<Position X="21" Y="11.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAACAAACAAAAAAAAAAAAAAAAAAACAAAAA=</HashCode>
<FileName>UIDrivers\VolumeAndSourceChangeArgs.cs</FileName>
</TypeIdentifier>
</Delegate>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

View file

@ -5,7 +5,6 @@ using System.Reflection;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO; using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro; using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.CrestronThread;
using Crestron.SimplSharpPro.Diagnostics; using Crestron.SimplSharpPro.Diagnostics;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
@ -28,10 +27,8 @@ namespace PepperDash.Essentials;
/// provides methods for platform determination, configuration loading, and system teardown.</remarks> /// provides methods for platform determination, configuration loading, and system teardown.</remarks>
public class ControlSystem : CrestronControlSystem, ILoadConfig public class ControlSystem : CrestronControlSystem, ILoadConfig
{ {
private HttpLogoServer LogoServer; private Timer startTimer;
private ManualResetEventSlim initializeEvent;
private Timer _startTimer;
private ManualResetEventSlim _initializeEvent;
private const long StartupTime = 500; private const long StartupTime = 500;
/// <summary> /// <summary>
@ -79,16 +76,16 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
{ {
Debug.LogMessage(LogEventLevel.Debug, "******************* Initializing System **********************"); Debug.LogMessage(LogEventLevel.Debug, "******************* Initializing System **********************");
_startTimer = new Timer(StartSystem, preventInitializationComplete, StartupTime, Timeout.Infinite); startTimer = new Timer(StartSystem, preventInitializationComplete, StartupTime, Timeout.Infinite);
_initializeEvent = new ManualResetEventSlim(false); initializeEvent = new ManualResetEventSlim(false);
DeviceManager.AllDevicesRegistered += (o, a) => DeviceManager.AllDevicesRegistered += (o, a) =>
{ {
_initializeEvent.Set(); initializeEvent.Set();
}; };
_initializeEvent.Wait(30000); initializeEvent.Wait(30000);
Debug.LogMessage(LogEventLevel.Debug, "******************* System Initialization Complete **********************"); Debug.LogMessage(LogEventLevel.Debug, "******************* System Initialization Complete **********************");
@ -96,7 +93,7 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
} }
else else
{ {
_startTimer = new Timer(StartSystem, preventInitializationComplete, StartupTime, Timeout.Infinite); startTimer = new Timer(StartSystem, preventInitializationComplete, StartupTime, Timeout.Infinite);
} }
} }
@ -357,7 +354,6 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
{ {
LoadDevices(); LoadDevices();
LoadRooms(); LoadRooms();
LoadLogoServer();
DeviceManager.ActivateAll(); DeviceManager.ActivateAll();
@ -495,67 +491,6 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
} }
/// <summary>
/// Fires up a logo server if not already running
/// </summary>
void LoadLogoServer()
{
if (ConfigReader.ConfigObject.Rooms == null)
{
Debug.LogMessage(LogEventLevel.Information, "No rooms configured. Bypassing Logo server startup.");
return;
}
if (
!ConfigReader.ConfigObject.Rooms.Any(
CheckRoomConfig))
{
Debug.LogMessage(LogEventLevel.Information, "No rooms configured to use system Logo server. Bypassing Logo server startup");
return;
}
try
{
LogoServer = new HttpLogoServer(8080, Global.DirectorySeparator + "html" + Global.DirectorySeparator + "logo");
}
catch (Exception)
{
Debug.LogMessage(LogEventLevel.Information, "NOTICE: Logo server cannot be started. Likely already running in another program");
}
}
private bool CheckRoomConfig(DeviceConfig c)
{
string logoDark = null;
string logoLight = null;
string logo = null;
try
{
if (c.Properties["logoDark"] != null)
{
logoDark = c.Properties["logoDark"].Value<string>("type");
}
if (c.Properties["logoLight"] != null)
{
logoLight = c.Properties["logoLight"].Value<string>("type");
}
if (c.Properties["logo"] != null)
{
logo = c.Properties["logo"].Value<string>("type");
}
return ((logoDark != null && logoDark == "system") ||
(logoLight != null && logoLight == "system") || (logo != null && logo == "system"));
}
catch
{
Debug.LogMessage(LogEventLevel.Information, "Unable to find logo information in any room config");
return false;
}
}
private static void LoadAssets() private static void LoadAssets()
{ {

View file

@ -1,123 +0,0 @@
using System;
using System.Collections.Generic;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Net.Http;
using PepperDash.Core;
using Serilog.Events;
namespace PepperDash.Essentials;
public class HttpLogoServer
{
/// <summary>
///
/// </summary>
readonly HttpServer _server;
/// <summary>
///
/// </summary>
readonly string _fileDirectory;
/// <summary>
///
/// </summary>
public static Dictionary<string, string> ExtensionContentTypes;
/// <summary>
///
/// </summary>
/// <param name="port"></param>
/// <param name="directory"></param>
public HttpLogoServer(int port, string directory)
{
ExtensionContentTypes = new Dictionary<string, string>
{
//{ ".css", "text/css" },
//{ ".htm", "text/html" },
//{ ".html", "text/html" },
{ ".jpg", "image/jpeg" },
{ ".jpeg", "image/jpeg" },
//{ ".js", "application/javascript" },
//{ ".json", "application/json" },
//{ ".map", "application/x-navimap" },
{ ".pdf", "application/pdf" },
{ ".png", "image/png" },
//{ ".txt", "text/plain" },
};
_server = new HttpServer {Port = port};
_fileDirectory = directory;
_server.OnHttpRequest += Server_OnHttpRequest;
_server.Open();
CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler;
}
/// <summary>
///
/// </summary>
void Server_OnHttpRequest(object sender, OnHttpRequestArgs args)
{
var path = args.Request.Path;
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "HTTP Request with path: '{requestPath:l}'", args.Request.Path);
try
{
if (File.Exists(_fileDirectory + path))
{
var filePath = path.Replace('/', '\\');
var localPath = string.Format(@"{0}{1}", _fileDirectory, filePath);
Debug.LogMessage(LogEventLevel.Verbose, "HTTP Logo Server attempting to find file: '{localPath:l}'", localPath);
if (File.Exists(localPath))
{
args.Response.Header.ContentType = GetContentType(new FileInfo(localPath).Extension);
args.Response.ContentStream = new FileStream(localPath, FileMode.Open, FileAccess.Read);
}
else
{
Debug.LogMessage(LogEventLevel.Verbose, "HTTP Logo Server Cannot find file '{localPath:l}'", localPath);
args.Response.ContentString = string.Format("Not found: '{0}'", filePath);
args.Response.Code = 404;
}
}
else
{
Debug.LogMessage(LogEventLevel.Verbose, "HTTP Logo Server: '{file:l}' does not exist", _fileDirectory + path);
args.Response.ContentString = string.Format("Not found: '{0}'", _fileDirectory + path);
args.Response.Code = 404;
}
}
catch (Exception ex)
{
Debug.LogMessage(LogEventLevel.Error, "Exception getting file: {exception}", ex.Message, ex.StackTrace);
Debug.LogMessage(LogEventLevel.Verbose, "Stack Trace: {stackTrace}", ex.StackTrace);
args.Response.Code = 400;
args.Response.ContentString = string.Format("invalid request");
}
}
/// <summary>
///
/// </summary>
void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
{
if (programEventType == eProgramStatusEventType.Stopping)
_server.Close();
}
/// <summary>
///
/// </summary>
/// <param name="extension"></param>
/// <returns></returns>
public static string GetContentType(string extension)
{
var type = ExtensionContentTypes.ContainsKey(extension) ? ExtensionContentTypes[extension] : "text/plain";
return type;
}
}