fix: remove references to Crestron.SimplSharp.CrestronIO

Replaced with System.IO. Also modified calls as necessary due to differences in API
This commit is contained in:
Andrew Welker
2025-08-13 22:11:37 -05:00
parent 9c81546a07
commit 083c270cf3
32 changed files with 3504 additions and 3509 deletions

View File

@@ -1,7 +1,7 @@
using System;
using System.IO;
using System.Linq;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
@@ -12,223 +12,223 @@ namespace PepperDash.Core.Config;
/// <summary>
/// Reads a Portal formatted config file
/// </summary>
public class PortalConfigReader
public class PortalConfigReader
{
/// <summary>
/// Reads the config file, checks if it needs a merge, merges and saves, then returns the merged Object.
/// </summary>
/// <returns>JObject of config file</returns>
public static void ReadAndMergeFileIfNecessary(string filePath, string savePath)
{
/// <summary>
/// Reads the config file, checks if it needs a merge, merges and saves, then returns the merged Object.
/// </summary>
/// <returns>JObject of config file</returns>
public static void ReadAndMergeFileIfNecessary(string filePath, string savePath)
try
{
try
if (!File.Exists(filePath))
{
if (!File.Exists(filePath))
Debug.Console(1, Debug.ErrorLogLevel.Error,
"ERROR: Configuration file not present. Please load file to {0} and reset program", filePath);
}
using (StreamReader fs = new StreamReader(filePath))
{
var jsonObj = JObject.Parse(fs.ReadToEnd());
if (jsonObj["template"] != null && jsonObj["system"] != null)
{
Debug.Console(1, Debug.ErrorLogLevel.Error,
"ERROR: Configuration file not present. Please load file to {0} and reset program", filePath);
// it's a double-config, merge it.
var merged = MergeConfigs(jsonObj);
if (jsonObj["system_url"] != null)
{
merged["systemUrl"] = jsonObj["system_url"].Value<string>();
}
if (jsonObj["template_url"] != null)
{
merged["templateUrl"] = jsonObj["template_url"].Value<string>();
}
jsonObj = merged;
}
using (StreamReader fs = new StreamReader(filePath))
using (StreamWriter fw = new StreamWriter(savePath))
{
var jsonObj = JObject.Parse(fs.ReadToEnd());
if(jsonObj["template"] != null && jsonObj["system"] != null)
{
// it's a double-config, merge it.
var merged = MergeConfigs(jsonObj);
if (jsonObj["system_url"] != null)
{
merged["systemUrl"] = jsonObj["system_url"].Value<string>();
}
if (jsonObj["template_url"] != null)
{
merged["templateUrl"] = jsonObj["template_url"].Value<string>();
}
jsonObj = merged;
}
using (StreamWriter fw = new StreamWriter(savePath))
{
fw.Write(jsonObj.ToString(Formatting.Indented));
Debug.LogMessage(LogEventLevel.Debug, "JSON config merged and saved to {0}", savePath);
}
fw.Write(jsonObj.ToString(Formatting.Indented));
Debug.LogMessage(LogEventLevel.Debug, "JSON config merged and saved to {0}", savePath);
}
}
catch (Exception e)
{
Debug.LogMessage(e, "ERROR: Config load failed");
}
}
/// <summary>
///
/// </summary>
/// <param name="doubleConfig"></param>
/// <returns></returns>
public static JObject MergeConfigs(JObject doubleConfig)
catch (Exception e)
{
var system = JObject.FromObject(doubleConfig["system"]);
var template = JObject.FromObject(doubleConfig["template"]);
var merged = new JObject();
// Put together top-level objects
if (system["info"] != null)
merged.Add("info", Merge(template["info"], system["info"], "infO"));
else
merged.Add("info", template["info"]);
merged.Add("devices", MergeArraysOnTopLevelProperty(template["devices"] as JArray,
system["devices"] as JArray, "key", "devices"));
if (system["rooms"] == null)
merged.Add("rooms", template["rooms"]);
else
merged.Add("rooms", MergeArraysOnTopLevelProperty(template["rooms"] as JArray,
system["rooms"] as JArray, "key", "rooms"));
if (system["sourceLists"] == null)
merged.Add("sourceLists", template["sourceLists"]);
else
merged.Add("sourceLists", Merge(template["sourceLists"], system["sourceLists"], "sourceLists"));
if (system["destinationLists"] == null)
merged.Add("destinationLists", template["destinationLists"]);
else
merged.Add("destinationLists",
Merge(template["destinationLists"], system["destinationLists"], "destinationLists"));
if (system["cameraLists"] == null)
merged.Add("cameraLists", template["cameraLists"]);
else
merged.Add("cameraLists", Merge(template["cameraLists"], system["cameraLists"], "cameraLists"));
if (system["audioControlPointLists"] == null)
merged.Add("audioControlPointLists", template["audioControlPointLists"]);
else
merged.Add("audioControlPointLists",
Merge(template["audioControlPointLists"], system["audioControlPointLists"], "audioControlPointLists"));
// Template tie lines take precedence. Config tool doesn't do them at system
// level anyway...
if (template["tieLines"] != null)
merged.Add("tieLines", template["tieLines"]);
else if (system["tieLines"] != null)
merged.Add("tieLines", system["tieLines"]);
else
merged.Add("tieLines", new JArray());
if (template["joinMaps"] != null)
merged.Add("joinMaps", template["joinMaps"]);
else
merged.Add("joinMaps", new JObject());
if (system["global"] != null)
merged.Add("global", Merge(template["global"], system["global"], "global"));
else
merged.Add("global", template["global"]);
//Debug.Console(2, "MERGED CONFIG RESULT: \x0d\x0a{0}", merged);
return merged;
Debug.LogMessage(e, "ERROR: Config load failed");
}
}
/// <summary>
/// Merges the contents of a base and a delta array, matching the entries on a top-level property
/// given by propertyName. Returns a merge of them. Items in the delta array that do not have
/// a matched item in base array will not be merged. Non keyed system items will replace the template items.
/// </summary>
static JArray MergeArraysOnTopLevelProperty(JArray a1, JArray a2, string propertyName, string path)
/// <summary>
///
/// </summary>
/// <param name="doubleConfig"></param>
/// <returns></returns>
public static JObject MergeConfigs(JObject doubleConfig)
{
var system = JObject.FromObject(doubleConfig["system"]);
var template = JObject.FromObject(doubleConfig["template"]);
var merged = new JObject();
// Put together top-level objects
if (system["info"] != null)
merged.Add("info", Merge(template["info"], system["info"], "infO"));
else
merged.Add("info", template["info"]);
merged.Add("devices", MergeArraysOnTopLevelProperty(template["devices"] as JArray,
system["devices"] as JArray, "key", "devices"));
if (system["rooms"] == null)
merged.Add("rooms", template["rooms"]);
else
merged.Add("rooms", MergeArraysOnTopLevelProperty(template["rooms"] as JArray,
system["rooms"] as JArray, "key", "rooms"));
if (system["sourceLists"] == null)
merged.Add("sourceLists", template["sourceLists"]);
else
merged.Add("sourceLists", Merge(template["sourceLists"], system["sourceLists"], "sourceLists"));
if (system["destinationLists"] == null)
merged.Add("destinationLists", template["destinationLists"]);
else
merged.Add("destinationLists",
Merge(template["destinationLists"], system["destinationLists"], "destinationLists"));
if (system["cameraLists"] == null)
merged.Add("cameraLists", template["cameraLists"]);
else
merged.Add("cameraLists", Merge(template["cameraLists"], system["cameraLists"], "cameraLists"));
if (system["audioControlPointLists"] == null)
merged.Add("audioControlPointLists", template["audioControlPointLists"]);
else
merged.Add("audioControlPointLists",
Merge(template["audioControlPointLists"], system["audioControlPointLists"], "audioControlPointLists"));
// Template tie lines take precedence. Config tool doesn't do them at system
// level anyway...
if (template["tieLines"] != null)
merged.Add("tieLines", template["tieLines"]);
else if (system["tieLines"] != null)
merged.Add("tieLines", system["tieLines"]);
else
merged.Add("tieLines", new JArray());
if (template["joinMaps"] != null)
merged.Add("joinMaps", template["joinMaps"]);
else
merged.Add("joinMaps", new JObject());
if (system["global"] != null)
merged.Add("global", Merge(template["global"], system["global"], "global"));
else
merged.Add("global", template["global"]);
//Debug.Console(2, "MERGED CONFIG RESULT: \x0d\x0a{0}", merged);
return merged;
}
/// <summary>
/// Merges the contents of a base and a delta array, matching the entries on a top-level property
/// given by propertyName. Returns a merge of them. Items in the delta array that do not have
/// a matched item in base array will not be merged. Non keyed system items will replace the template items.
/// </summary>
static JArray MergeArraysOnTopLevelProperty(JArray a1, JArray a2, string propertyName, string path)
{
var result = new JArray();
if (a2 == null || a2.Count == 0) // If the system array is null or empty, return the template array
return a1;
else if (a1 != null)
{
var result = new JArray();
if (a2 == null || a2.Count == 0) // If the system array is null or empty, return the template array
return a1;
else if (a1 != null)
{
if (a2[0]["key"] == null) // If the first item in the system array has no key, overwrite the template array
{ // with the system array
return a2;
}
else // The arrays are keyed, merge them by key
{
for (int i = 0; i < a1.Count(); i++)
{
var a1Dev = a1[i];
// Try to get a system device and if found, merge it onto template
var a2Match = a2.FirstOrDefault(t => t[propertyName].Equals(a1Dev[propertyName]));// t.Value<int>("uid") == tmplDev.Value<int>("uid"));
if (a2Match != null)
{
var mergedItem = Merge(a1Dev, a2Match, string.Format("{0}[{1}].", path, i));// Merge(JObject.FromObject(a1Dev), JObject.FromObject(a2Match));
result.Add(mergedItem);
}
else
result.Add(a1Dev);
}
}
if (a2[0]["key"] == null) // If the first item in the system array has no key, overwrite the template array
{ // with the system array
return a2;
}
return result;
}
/// <summary>
/// Helper for using with JTokens. Converts to JObject
/// </summary>
static JObject Merge(JToken t1, JToken t2, string path)
{
return Merge(JObject.FromObject(t1), JObject.FromObject(t2), path);
}
/// <summary>
/// Merge o2 onto o1
/// </summary>
/// <param name="o1"></param>
/// <param name="o2"></param>
/// <param name="path"></param>
static JObject Merge(JObject o1, JObject o2, string path)
{
foreach (var o2Prop in o2)
else // The arrays are keyed, merge them by key
{
var propKey = o2Prop.Key;
var o1Value = o1[propKey];
var o2Value = o2[propKey];
// if the property doesn't exist on o1, then add it.
if (o1Value == null)
for (int i = 0; i < a1.Count(); i++)
{
o1.Add(propKey, o2Value);
}
// otherwise merge them
else
{
// Drill down
var propPath = String.Format("{0}.{1}", path, propKey);
try
var a1Dev = a1[i];
// Try to get a system device and if found, merge it onto template
var a2Match = a2.FirstOrDefault(t => t[propertyName].Equals(a1Dev[propertyName]));// t.Value<int>("uid") == tmplDev.Value<int>("uid"));
if (a2Match != null)
{
if (o1Value is JArray)
{
if (o2Value is JArray)
{
o1Value.Replace(MergeArraysOnTopLevelProperty(o1Value as JArray, o2Value as JArray, "key", propPath));
}
}
else if (o2Prop.Value.HasValues && o1Value.HasValues)
{
o1Value.Replace(Merge(JObject.FromObject(o1Value), JObject.FromObject(o2Value), propPath));
}
else
{
o1Value.Replace(o2Prop.Value);
}
}
catch (Exception e)
{
Debug.Console(1, Debug.ErrorLogLevel.Warning, "Cannot merge items at path {0}: \r{1}", propPath, e);
var mergedItem = Merge(a1Dev, a2Match, string.Format("{0}[{1}].", path, i));// Merge(JObject.FromObject(a1Dev), JObject.FromObject(a2Match));
result.Add(mergedItem);
}
else
result.Add(a1Dev);
}
}
return o1;
}
}
return result;
}
/// <summary>
/// Helper for using with JTokens. Converts to JObject
/// </summary>
static JObject Merge(JToken t1, JToken t2, string path)
{
return Merge(JObject.FromObject(t1), JObject.FromObject(t2), path);
}
/// <summary>
/// Merge o2 onto o1
/// </summary>
/// <param name="o1"></param>
/// <param name="o2"></param>
/// <param name="path"></param>
static JObject Merge(JObject o1, JObject o2, string path)
{
foreach (var o2Prop in o2)
{
var propKey = o2Prop.Key;
var o1Value = o1[propKey];
var o2Value = o2[propKey];
// if the property doesn't exist on o1, then add it.
if (o1Value == null)
{
o1.Add(propKey, o2Value);
}
// otherwise merge them
else
{
// Drill down
var propPath = String.Format("{0}.{1}", path, propKey);
try
{
if (o1Value is JArray)
{
if (o2Value is JArray)
{
o1Value.Replace(MergeArraysOnTopLevelProperty(o1Value as JArray, o2Value as JArray, "key", propPath));
}
}
else if (o2Prop.Value.HasValues && o1Value.HasValues)
{
o1Value.Replace(Merge(JObject.FromObject(o1Value), JObject.FromObject(o2Value), propPath));
}
else
{
o1Value.Replace(o2Prop.Value);
}
}
catch (Exception e)
{
Debug.Console(1, Debug.ErrorLogLevel.Warning, "Cannot merge items at path {0}: \r{1}", propPath, e);
}
}
}
return o1;
}
}

View File

@@ -3,8 +3,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using static Crestron.SimplSharp.Net.Http;
using static Crestron.SimplSharp.Net.Https;
using Crestron.SimplSharp.Net.Http;
using Crestron.SimplSharp.Net.Https;
namespace PepperDash.Core.GenericRESTfulCommunications;

View File

@@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json.Linq;
namespace PepperDash.Core.JsonToSimpl;
@@ -79,7 +79,7 @@ public class JsonToSimplFileMaster : JsonToSimplMaster
JsonToSimplConstants.DevicePlatformValueChange);
// get the roomID
var roomId = Crestron.SimplSharp.InitialParametersClass.RoomId;
var roomId = Crestron.SimplSharp.InitialParametersClass.RoomId;
if (!string.IsNullOrEmpty(roomId))
{
OnStringChange(roomId, 0, JsonToSimplConstants.RoomIdChange);
@@ -92,13 +92,13 @@ public class JsonToSimplFileMaster : JsonToSimplMaster
OnStringChange(roomName, 0, JsonToSimplConstants.RoomNameChange);
}
var rootDirectory = Directory.GetApplicationRootDirectory();
OnStringChange(rootDirectory, 0, JsonToSimplConstants.RootDirectoryChange);
var rootDirectory = Directory.GetCurrentDirectory();
OnStringChange(rootDirectory, 0, JsonToSimplConstants.RootDirectoryChange);
var splusPath = string.Empty;
if (Regex.IsMatch(filepath, @"user", RegexOptions.IgnoreCase))
{
if (is4Series)
if (is4Series)
splusPath = Regex.Replace(filepath, "user", "user", RegexOptions.IgnoreCase);
else if (isServer)
splusPath = Regex.Replace(filepath, "user", "User", RegexOptions.IgnoreCase);
@@ -107,10 +107,10 @@ public class JsonToSimplFileMaster : JsonToSimplMaster
}
filepath = splusPath.Replace(dirSeparatorAlt, dirSeparator);
Filepath = string.Format("{1}{0}{2}", dirSeparator, rootDirectory,
filepath.TrimStart(dirSeparator, dirSeparatorAlt));
OnStringChange(string.Format("Attempting to evaluate {0}", Filepath), 0, JsonToSimplConstants.StringValueChange);
if (string.IsNullOrEmpty(Filepath))
@@ -130,10 +130,10 @@ public class JsonToSimplFileMaster : JsonToSimplMaster
if (Directory.Exists(fileDirectory))
{
// get the directory info
var directoryInfo = new DirectoryInfo(fileDirectory);
var directoryInfo = new DirectoryInfo(fileDirectory);
// get the file to be read
var actualFile = directoryInfo.GetFiles(fileName).FirstOrDefault();
var actualFile = directoryInfo.GetFiles(fileName).FirstOrDefault();
if (actualFile == null)
{
var msg = string.Format("JSON file not found: {0}", Filepath);
@@ -145,7 +145,7 @@ public class JsonToSimplFileMaster : JsonToSimplMaster
// \xSE\xR\PDT000-Template_Main_Config-Combined_DSP_v00.02.json
// \USER\PDT000-Template_Main_Config-Combined_DSP_v00.02.json
ActualFilePath = actualFile.FullName;
ActualFilePath = actualFile.FullName;
OnStringChange(ActualFilePath, 0, JsonToSimplConstants.ActualFilePathChange);
OnStringChange(string.Format("Actual JSON file is {0}", ActualFilePath), 0, JsonToSimplConstants.StringValueChange);
Debug.Console(1, "Actual JSON file is {0}", ActualFilePath);
@@ -159,9 +159,9 @@ public class JsonToSimplFileMaster : JsonToSimplMaster
FilePathName = string.Format(@"{0}{1}", actualFile.DirectoryName, dirSeparator);
OnStringChange(string.Format(@"{0}", actualFile.DirectoryName), 0, JsonToSimplConstants.FilePathResolvedChange);
OnStringChange(string.Format(@"JSON File Path is {0}", actualFile.DirectoryName), 0, JsonToSimplConstants.StringValueChange);
Debug.Console(1, "JSON File Path is {0}", FilePathName);
Debug.Console(1, "JSON File Path is {0}", FilePathName);
var json = File.ReadToEnd(ActualFilePath, System.Text.Encoding.ASCII);
var json = File.ReadAllText(ActualFilePath, System.Text.Encoding.ASCII);
JsonObject = JObject.Parse(json);
foreach (var child in Children)

View File

@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json.Linq;
using PepperDash.Core.Config;
@@ -13,178 +13,178 @@ namespace PepperDash.Core.JsonToSimpl;
/// </summary>
public class JsonToSimplPortalFileMaster : JsonToSimplMaster
{
/// <summary>
/// Sets the filepath as well as registers this with the Global.Masters list
/// </summary>
public string PortalFilepath { get; private set; }
/// <summary>
/// Sets the filepath as well as registers this with the Global.Masters list
/// </summary>
public string PortalFilepath { get; private set; }
/// <summary>
/// File path of the actual file being read (Portal or local)
/// </summary>
public string ActualFilePath { get; private set; }
/// <summary>
/// File path of the actual file being read (Portal or local)
/// </summary>
public string ActualFilePath { get; private set; }
/*****************************************************************************************/
/** Privates **/
/*****************************************************************************************/
/** Privates **/
// To prevent multiple same-file access
object StringBuilderLock = new object();
static object FileLock = new object();
// To prevent multiple same-file access
object StringBuilderLock = new object();
static object FileLock = new object();
/*****************************************************************************************/
/*****************************************************************************************/
/// <summary>
/// SIMPL+ default constructor.
/// </summary>
public JsonToSimplPortalFileMaster()
{
/// <summary>
/// SIMPL+ default constructor.
/// </summary>
public JsonToSimplPortalFileMaster()
{
}
/// <summary>
/// Read, evaluate and udpate status
/// </summary>
public void EvaluateFile(string portalFilepath)
{
PortalFilepath = portalFilepath;
OnBoolChange(false, 0, JsonToSimplConstants.JsonIsValidBoolChange);
if (string.IsNullOrEmpty(PortalFilepath))
{
CrestronConsole.PrintLine("Cannot evaluate file. JSON file path not set");
return;
}
/// <summary>
/// Read, evaluate and udpate status
/// </summary>
public void EvaluateFile(string portalFilepath)
// Resolve possible wildcarded filename
// If the portal file is xyz.json, then
// the file we want to check for first will be called xyz.local.json
var localFilepath = Path.ChangeExtension(PortalFilepath, "local.json");
Debug.Console(0, this, "Checking for local file {0}", localFilepath);
var actualLocalFile = GetActualFileInfoFromPath(localFilepath);
if (actualLocalFile != null)
{
PortalFilepath = portalFilepath;
OnBoolChange(false, 0, JsonToSimplConstants.JsonIsValidBoolChange);
if (string.IsNullOrEmpty(PortalFilepath))
ActualFilePath = actualLocalFile.FullName;
OnStringChange(ActualFilePath, 0, JsonToSimplConstants.ActualFilePathChange);
}
// If the local file does not exist, then read the portal file xyz.json
// and create the local.
else
{
Debug.Console(1, this, "Local JSON file not found {0}\rLoading portal JSON file", localFilepath);
var actualPortalFile = GetActualFileInfoFromPath(portalFilepath);
if (actualPortalFile != null)
{
CrestronConsole.PrintLine("Cannot evaluate file. JSON file path not set");
return;
var newLocalPath = Path.ChangeExtension(actualPortalFile.FullName, "local.json");
// got the portal file, hand off to the merge / save method
PortalConfigReader.ReadAndMergeFileIfNecessary(actualPortalFile.FullName, newLocalPath);
ActualFilePath = newLocalPath;
OnStringChange(ActualFilePath, 0, JsonToSimplConstants.ActualFilePathChange);
}
// Resolve possible wildcarded filename
// If the portal file is xyz.json, then
// the file we want to check for first will be called xyz.local.json
var localFilepath = Path.ChangeExtension(PortalFilepath, "local.json");
Debug.Console(0, this, "Checking for local file {0}", localFilepath);
var actualLocalFile = GetActualFileInfoFromPath(localFilepath);
if (actualLocalFile != null)
{
ActualFilePath = actualLocalFile.FullName;
OnStringChange(ActualFilePath, 0, JsonToSimplConstants.ActualFilePathChange);
}
// If the local file does not exist, then read the portal file xyz.json
// and create the local.
else
{
Debug.Console(1, this, "Local JSON file not found {0}\rLoading portal JSON file", localFilepath);
var actualPortalFile = GetActualFileInfoFromPath(portalFilepath);
if (actualPortalFile != null)
{
var newLocalPath = Path.ChangeExtension(actualPortalFile.FullName, "local.json");
// got the portal file, hand off to the merge / save method
PortalConfigReader.ReadAndMergeFileIfNecessary(actualPortalFile.FullName, newLocalPath);
ActualFilePath = newLocalPath;
OnStringChange(ActualFilePath, 0, JsonToSimplConstants.ActualFilePathChange);
}
else
{
var msg = string.Format("Portal JSON file not found: {0}", PortalFilepath);
Debug.Console(1, this, msg);
ErrorLog.Error(msg);
return;
}
}
// At this point we should have a local file. Do it.
Debug.Console(1, "Reading local JSON file {0}", ActualFilePath);
string json = File.ReadToEnd(ActualFilePath, System.Text.Encoding.ASCII);
try
{
JsonObject = JObject.Parse(json);
foreach (var child in Children)
child.ProcessAll();
OnBoolChange(true, 0, JsonToSimplConstants.JsonIsValidBoolChange);
}
catch (Exception e)
{
var msg = string.Format("JSON parsing failed:\r{0}", e);
CrestronConsole.PrintLine(msg);
var msg = string.Format("Portal JSON file not found: {0}", PortalFilepath);
Debug.Console(1, this, msg);
ErrorLog.Error(msg);
return;
}
}
/// <summary>
/// Returns the FileInfo object for a given path, with possible wildcards
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
FileInfo GetActualFileInfoFromPath(string path)
{
var dir = Path.GetDirectoryName(path);
var localFilename = Path.GetFileName(path);
var directory = new DirectoryInfo(dir);
// search the directory for the file w/ wildcards
return directory.GetFiles(localFilename).FirstOrDefault();
}
// At this point we should have a local file. Do it.
Debug.Console(1, "Reading local JSON file {0}", ActualFilePath);
/// <summary>
///
/// </summary>
/// <param name="level"></param>
public void setDebugLevel(uint level)
{
Debug.SetDebugLevel(level);
}
string json = File.ReadAllText(ActualFilePath, System.Text.Encoding.ASCII);
/// <summary>
///
/// </summary>
public override void Save()
try
{
// this code is duplicated in the other masters!!!!!!!!!!!!!
UnsavedValues = new Dictionary<string, JValue>();
// Make each child update their values into master object
JsonObject = JObject.Parse(json);
foreach (var child in Children)
{
Debug.Console(1, "Master [{0}] checking child [{1}] for updates to save", UniqueID, child.Key);
child.UpdateInputsForMaster();
}
child.ProcessAll();
OnBoolChange(true, 0, JsonToSimplConstants.JsonIsValidBoolChange);
}
catch (Exception e)
{
var msg = string.Format("JSON parsing failed:\r{0}", e);
CrestronConsole.PrintLine(msg);
ErrorLog.Error(msg);
return;
}
}
if (UnsavedValues == null || UnsavedValues.Count == 0)
/// <summary>
/// Returns the FileInfo object for a given path, with possible wildcards
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
FileInfo GetActualFileInfoFromPath(string path)
{
var dir = Path.GetDirectoryName(path);
var localFilename = Path.GetFileName(path);
var directory = new DirectoryInfo(dir);
// search the directory for the file w/ wildcards
return directory.GetFiles(localFilename).FirstOrDefault();
}
/// <summary>
///
/// </summary>
/// <param name="level"></param>
public void setDebugLevel(uint level)
{
Debug.SetDebugLevel(level);
}
/// <summary>
///
/// </summary>
public override void Save()
{
// this code is duplicated in the other masters!!!!!!!!!!!!!
UnsavedValues = new Dictionary<string, JValue>();
// Make each child update their values into master object
foreach (var child in Children)
{
Debug.Console(1, "Master [{0}] checking child [{1}] for updates to save", UniqueID, child.Key);
child.UpdateInputsForMaster();
}
if (UnsavedValues == null || UnsavedValues.Count == 0)
{
Debug.Console(1, "Master [{0}] No updated values to save. Skipping", UniqueID);
return;
}
lock (FileLock)
{
Debug.Console(1, "Saving");
foreach (var path in UnsavedValues.Keys)
{
Debug.Console(1, "Master [{0}] No updated values to save. Skipping", UniqueID);
return;
}
lock (FileLock)
{
Debug.Console(1, "Saving");
foreach (var path in UnsavedValues.Keys)
{
var tokenToReplace = JsonObject.SelectToken(path);
if (tokenToReplace != null)
{// It's found
tokenToReplace.Replace(UnsavedValues[path]);
Debug.Console(1, "JSON Master[{0}] Updating '{1}'", UniqueID, path);
}
else // No token. Let's make one
{
//http://stackoverflow.com/questions/17455052/how-to-set-the-value-of-a-json-path-using-json-net
Debug.Console(1, "JSON Master[{0}] Cannot write value onto missing property: '{1}'", UniqueID, path);
}
var tokenToReplace = JsonObject.SelectToken(path);
if (tokenToReplace != null)
{// It's found
tokenToReplace.Replace(UnsavedValues[path]);
Debug.Console(1, "JSON Master[{0}] Updating '{1}'", UniqueID, path);
}
using (StreamWriter sw = new StreamWriter(ActualFilePath))
else // No token. Let's make one
{
try
{
sw.Write(JsonObject.ToString());
sw.Flush();
}
catch (Exception e)
{
string err = string.Format("Error writing JSON file:\r{0}", e);
Debug.Console(0, err);
ErrorLog.Warn(err);
return;
}
//http://stackoverflow.com/questions/17455052/how-to-set-the-value-of-a-json-path-using-json-net
Debug.Console(1, "JSON Master[{0}] Cannot write value onto missing property: '{1}'", UniqueID, path);
}
}
using (StreamWriter sw = new StreamWriter(ActualFilePath))
{
try
{
sw.Write(JsonObject.ToString());
sw.Flush();
}
catch (Exception e)
{
string err = string.Format("Error writing JSON file:\r{0}", e);
Debug.Console(0, err);
ErrorLog.Warn(err);
return;
}
}
}
}
}

View File

@@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronDataStore;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.CrestronLogger;
using Newtonsoft.Json;
using PepperDash.Core.Logging;
@@ -142,8 +142,8 @@ public static class Debug
_websocketSink = new DebugWebsocketSink(new JsonFormatter(renderMessage: true));
var logFilePath = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ?
$@"{Directory.GetApplicationRootDirectory()}{Path.DirectorySeparatorChar}user{Path.DirectorySeparatorChar}debug{Path.DirectorySeparatorChar}app{InitialParametersClass.ApplicationNumber}{Path.DirectorySeparatorChar}global-log.log" :
$@"{Directory.GetApplicationRootDirectory()}{Path.DirectorySeparatorChar}user{Path.DirectorySeparatorChar}debug{Path.DirectorySeparatorChar}room{InitialParametersClass.RoomId}{Path.DirectorySeparatorChar}global-log.log";
$@"{Directory.GetCurrentDirectory()}{Path.DirectorySeparatorChar}user{Path.DirectorySeparatorChar}debug{Path.DirectorySeparatorChar}app{InitialParametersClass.ApplicationNumber}{Path.DirectorySeparatorChar}global-log.log" :
$@"{Directory.GetCurrentDirectory()}{Path.DirectorySeparatorChar}user{Path.DirectorySeparatorChar}debug{Path.DirectorySeparatorChar}room{InitialParametersClass.RoomId}{Path.DirectorySeparatorChar}global-log.log";
CrestronConsole.PrintLine($"Saving log files to {logFilePath}");
@@ -1004,7 +1004,7 @@ public static class Debug
return string.Format(@"\user\debugSettings\program{0}", InitialParametersClass.ApplicationNumber);
}
return string.Format("{0}{1}user{1}debugSettings{1}{2}.json", Directory.GetApplicationRootDirectory(), Path.DirectorySeparatorChar, InitialParametersClass.RoomId);
return string.Format("{0}{1}user{1}debugSettings{1}{2}.json", Directory.GetCurrentDirectory(), Path.DirectorySeparatorChar, InitialParametersClass.RoomId);
}
/// <summary>

View File

@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json;

View File

@@ -2,15 +2,15 @@
namespace PepperDash.Core.Web.RequestHandlers;
/// <summary>
/// Web API default request handler
/// </summary>
public class DefaultRequestHandler : WebApiBaseRequestHandler
{
/// <summary>
/// Web API default request handler
/// Constructor
/// </summary>
public class DefaultRequestHandler : WebApiBaseRequestHandler
{
/// <summary>
/// Constructor
/// </summary>
public DefaultRequestHandler()
: base(true)
{ }
}
public DefaultRequestHandler()
: base(true)
{ }
}

View File

@@ -1,11 +1,11 @@
using Crestron.SimplSharp.WebScripting;
using System;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Crestron.SimplSharp.WebScripting;
namespace PepperDash.Core.Web.RequestHandlers;
public abstract class WebApiBaseRequestAsyncHandler:IHttpCwsHandler
public abstract class WebApiBaseRequestAsyncHandler : IHttpCwsHandler
{
private readonly Dictionary<string, Func<HttpCwsContext, Task>> _handlers;
protected readonly bool EnableCors;
@@ -47,7 +47,7 @@ public abstract class WebApiBaseRequestAsyncHandler:IHttpCwsHandler
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
context.Response.End();
}
/// <summary>

View File

@@ -4,22 +4,22 @@ using Crestron.SimplSharp.WebScripting;
namespace PepperDash.Core.Web.RequestHandlers;
/// <summary>
/// CWS Base Handler, implements IHttpCwsHandler
/// </summary>
public abstract class WebApiBaseRequestHandler : IHttpCwsHandler
{
private readonly Dictionary<string, Action<HttpCwsContext>> _handlers;
protected readonly bool EnableCors;
/// <summary>
/// CWS Base Handler, implements IHttpCwsHandler
/// Constructor
/// </summary>
public abstract class WebApiBaseRequestHandler : IHttpCwsHandler
protected WebApiBaseRequestHandler(bool enableCors)
{
private readonly Dictionary<string, Action<HttpCwsContext>> _handlers;
protected readonly bool EnableCors;
EnableCors = enableCors;
/// <summary>
/// Constructor
/// </summary>
protected WebApiBaseRequestHandler(bool enableCors)
{
EnableCors = enableCors;
_handlers = new Dictionary<string, Action<HttpCwsContext>>
_handlers = new Dictionary<string, Action<HttpCwsContext>>
{
{"CONNECT", HandleConnect},
{"DELETE", HandleDelete},
@@ -31,134 +31,134 @@ namespace PepperDash.Core.Web.RequestHandlers;
{"PUT", HandlePut},
{"TRACE", HandleTrace}
};
}
/// <summary>
/// Constructor
/// </summary>
protected WebApiBaseRequestHandler()
: this(false)
{
}
/// <summary>
/// Handles CONNECT method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandleConnect(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Handles DELETE method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandleDelete(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Handles GET method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandleGet(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Handles HEAD method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandleHead(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Handles OPTIONS method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandleOptions(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Handles PATCH method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandlePatch(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Handles POST method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandlePost(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Handles PUT method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandlePut(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Handles TRACE method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandleTrace(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Process request
/// </summary>
/// <param name="context"></param>
public void ProcessRequest(HttpCwsContext context)
{
Action<HttpCwsContext> handler;
if (!_handlers.TryGetValue(context.Request.HttpMethod, out handler))
{
return;
}
/// <summary>
/// Constructor
/// </summary>
protected WebApiBaseRequestHandler()
: this(false)
if (EnableCors)
{
}
/// <summary>
/// Handles CONNECT method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandleConnect(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
context.Response.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
}
/// <summary>
/// Handles DELETE method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandleDelete(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Handles GET method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandleGet(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Handles HEAD method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandleHead(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Handles OPTIONS method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandleOptions(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Handles PATCH method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandlePatch(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Handles POST method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandlePost(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Handles PUT method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandlePut(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Handles TRACE method requests
/// </summary>
/// <param name="context"></param>
protected virtual void HandleTrace(HttpCwsContext context)
{
context.Response.StatusCode = 501;
context.Response.StatusDescription = "Not Implemented";
context.Response.End();
}
/// <summary>
/// Process request
/// </summary>
/// <param name="context"></param>
public void ProcessRequest(HttpCwsContext context)
{
Action<HttpCwsContext> handler;
if (!_handlers.TryGetValue(context.Request.HttpMethod, out handler))
{
return;
}
if (EnableCors)
{
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
context.Response.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
}
handler(context);
}
}
handler(context);
}
}

View File

@@ -9,275 +9,275 @@ using PepperDash.Core.Web.RequestHandlers;
namespace PepperDash.Core.Web;
/// <summary>
/// Web API server
/// </summary>
public class WebApiServer : IKeyName
{
private const string SplusKey = "Uninitialized Web API Server";
private const string DefaultName = "Web API Server";
private const string DefaultBasePath = "/api";
private const uint DebugTrace = 0;
private const uint DebugInfo = 1;
private const uint DebugVerbose = 2;
private readonly CCriticalSection _serverLock = new CCriticalSection();
private HttpCwsServer _server;
/// <summary>
/// Web API server
/// Web API server key
/// </summary>
public class WebApiServer : IKeyName
public string Key { get; private set; }
/// <summary>
/// Web API server name
/// </summary>
public string Name { get; private set; }
/// <summary>
/// CWS base path, will default to "/api" if not set via initialize method
/// </summary>
public string BasePath { get; private set; }
/// <summary>
/// Indicates CWS is registered with base path
/// </summary>
public bool IsRegistered { get; private set; }
/// <summary>
/// Http request handler
/// </summary>
//public IHttpCwsHandler HttpRequestHandler
//{
// get { return _server.HttpRequestHandler; }
// set
// {
// if (_server == null) return;
// _server.HttpRequestHandler = value;
// }
//}
/// <summary>
/// Received request event handler
/// </summary>
//public event EventHandler<HttpCwsRequestEventArgs> ReceivedRequestEvent
//{
// add { _server.ReceivedRequestEvent += new HttpCwsRequestEventHandler(value); }
// remove { _server.ReceivedRequestEvent -= new HttpCwsRequestEventHandler(value); }
//}
/// <summary>
/// Constructor for S+. Make sure to set necessary properties using init method
/// </summary>
public WebApiServer()
: this(SplusKey, DefaultName, null)
{
private const string SplusKey = "Uninitialized Web API Server";
private const string DefaultName = "Web API Server";
private const string DefaultBasePath = "/api";
}
private const uint DebugTrace = 0;
private const uint DebugInfo = 1;
private const uint DebugVerbose = 2;
/// <summary>
/// Constructor
/// </summary>
/// <param name="key"></param>
/// <param name="basePath"></param>
public WebApiServer(string key, string basePath)
: this(key, DefaultName, basePath)
{
}
private readonly CCriticalSection _serverLock = new CCriticalSection();
private HttpCwsServer _server;
/// <summary>
/// Constructor
/// </summary>
/// <param name="key"></param>
/// <param name="name"></param>
/// <param name="basePath"></param>
public WebApiServer(string key, string name, string basePath)
{
Key = key;
Name = string.IsNullOrEmpty(name) ? DefaultName : name;
BasePath = string.IsNullOrEmpty(basePath) ? DefaultBasePath : basePath;
/// <summary>
/// Web API server key
/// </summary>
public string Key { get; private set; }
if (_server == null) _server = new HttpCwsServer(BasePath);
/// <summary>
/// Web API server name
/// </summary>
public string Name { get; private set; }
_server.setProcessName(Key);
_server.HttpRequestHandler = new DefaultRequestHandler();
/// <summary>
/// CWS base path, will default to "/api" if not set via initialize method
/// </summary>
public string BasePath { get; private set; }
CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler;
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
}
/// <summary>
/// Indicates CWS is registered with base path
/// </summary>
public bool IsRegistered { get; private set; }
/// <summary>
/// Program status event handler
/// </summary>
/// <param name="programEventType"></param>
void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
{
if (programEventType != eProgramStatusEventType.Stopping) return;
/// <summary>
/// Http request handler
/// </summary>
//public IHttpCwsHandler HttpRequestHandler
//{
// get { return _server.HttpRequestHandler; }
// set
// {
// if (_server == null) return;
// _server.HttpRequestHandler = value;
// }
//}
Debug.Console(DebugInfo, this, "Program stopping. stopping server");
/// <summary>
/// Received request event handler
/// </summary>
//public event EventHandler<HttpCwsRequestEventArgs> ReceivedRequestEvent
//{
// add { _server.ReceivedRequestEvent += new HttpCwsRequestEventHandler(value); }
// remove { _server.ReceivedRequestEvent -= new HttpCwsRequestEventHandler(value); }
//}
Stop();
}
/// <summary>
/// Constructor for S+. Make sure to set necessary properties using init method
/// </summary>
public WebApiServer()
: this(SplusKey, DefaultName, null)
/// <summary>
/// Ethernet event handler
/// </summary>
/// <param name="ethernetEventArgs"></param>
void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs ethernetEventArgs)
{
// Re-enable the server if the link comes back up and the status should be connected
if (ethernetEventArgs.EthernetEventType == eEthernetEventType.LinkUp && IsRegistered)
{
Debug.Console(DebugInfo, this, "Ethernet link up. Server is alreedy registered.");
return;
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="key"></param>
/// <param name="basePath"></param>
public WebApiServer(string key, string basePath)
: this(key, DefaultName, basePath)
Debug.Console(DebugInfo, this, "Ethernet link up. Starting server");
Start();
}
/// <summary>
/// Initializes CWS class
/// </summary>
public void Initialize(string key, string basePath)
{
Key = key;
BasePath = string.IsNullOrEmpty(basePath) ? DefaultBasePath : basePath;
}
/// <summary>
/// Adds a route to CWS
/// </summary>
public void AddRoute(HttpCwsRoute route)
{
if (route == null)
{
Debug.Console(DebugInfo, this, "Failed to add route, route parameter is null");
return;
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="key"></param>
/// <param name="name"></param>
/// <param name="basePath"></param>
public WebApiServer(string key, string name, string basePath)
_server.Routes.Add(route);
}
/// <summary>
/// Removes a route from CWS
/// </summary>
/// <param name="route"></param>
public void RemoveRoute(HttpCwsRoute route)
{
if (route == null)
{
Key = key;
Name = string.IsNullOrEmpty(name) ? DefaultName : name;
BasePath = string.IsNullOrEmpty(basePath) ? DefaultBasePath : basePath;
if (_server == null) _server = new HttpCwsServer(BasePath);
_server.setProcessName(Key);
_server.HttpRequestHandler = new DefaultRequestHandler();
CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler;
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
Debug.Console(DebugInfo, this, "Failed to remote route, orute parameter is null");
return;
}
/// <summary>
/// Program status event handler
/// </summary>
/// <param name="programEventType"></param>
void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
_server.Routes.Remove(route);
}
/// <summary>
/// Returns a list of the current routes
/// </summary>
public HttpCwsRouteCollection GetRouteCollection()
{
return _server.Routes;
}
/// <summary>
/// Starts CWS instance
/// </summary>
public void Start()
{
try
{
if (programEventType != eProgramStatusEventType.Stopping) return;
_serverLock.Enter();
Debug.Console(DebugInfo, this, "Program stopping. stopping server");
Stop();
}
/// <summary>
/// Ethernet event handler
/// </summary>
/// <param name="ethernetEventArgs"></param>
void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs ethernetEventArgs)
{
// Re-enable the server if the link comes back up and the status should be connected
if (ethernetEventArgs.EthernetEventType == eEthernetEventType.LinkUp && IsRegistered)
if (_server == null)
{
Debug.Console(DebugInfo, this, "Ethernet link up. Server is alreedy registered.");
Debug.Console(DebugInfo, this, "Server is null, unable to start");
return;
}
Debug.Console(DebugInfo, this, "Ethernet link up. Starting server");
Start();
}
/// <summary>
/// Initializes CWS class
/// </summary>
public void Initialize(string key, string basePath)
{
Key = key;
BasePath = string.IsNullOrEmpty(basePath) ? DefaultBasePath : basePath;
}
/// <summary>
/// Adds a route to CWS
/// </summary>
public void AddRoute(HttpCwsRoute route)
{
if (route == null)
if (IsRegistered)
{
Debug.Console(DebugInfo, this, "Failed to add route, route parameter is null");
Debug.Console(DebugInfo, this, "Server has already been started");
return;
}
_server.Routes.Add(route);
IsRegistered = _server.Register();
Debug.Console(DebugInfo, this, "Starting server, registration {0}", IsRegistered ? "was successful" : "failed");
}
/// <summary>
/// Removes a route from CWS
/// </summary>
/// <param name="route"></param>
public void RemoveRoute(HttpCwsRoute route)
catch (Exception ex)
{
if (route == null)
Debug.Console(DebugInfo, this, "Start Exception Message: {0}", ex.Message);
Debug.Console(DebugVerbose, this, "Start Exception StackTrace: {0}", ex.StackTrace);
if (ex.InnerException != null)
Debug.Console(DebugVerbose, this, "Start Exception InnerException: {0}", ex.InnerException);
}
finally
{
_serverLock.Leave();
}
}
/// <summary>
/// Stop CWS instance
/// </summary>
public void Stop()
{
try
{
_serverLock.Enter();
if (_server == null)
{
Debug.Console(DebugInfo, this, "Failed to remote route, orute parameter is null");
Debug.Console(DebugInfo, this, "Server is null or has already been stopped");
return;
}
_server.Routes.Remove(route);
}
IsRegistered = _server.Unregister() == false;
/// <summary>
/// Returns a list of the current routes
/// </summary>
public HttpCwsRouteCollection GetRouteCollection()
Debug.Console(DebugInfo, this, "Stopping server, unregistration {0}", IsRegistered ? "failed" : "was successful");
_server.Dispose();
_server = null;
}
catch (Exception ex)
{
return _server.Routes;
Debug.Console(DebugInfo, this, "Server Stop Exception Message: {0}", ex.Message);
Debug.Console(DebugVerbose, this, "Server Stop Exception StackTrace: {0}", ex.StackTrace);
if (ex.InnerException != null)
Debug.Console(DebugVerbose, this, "Server Stop Exception InnerException: {0}", ex.InnerException);
}
/// <summary>
/// Starts CWS instance
/// </summary>
public void Start()
finally
{
try
{
_serverLock.Enter();
if (_server == null)
{
Debug.Console(DebugInfo, this, "Server is null, unable to start");
return;
}
if (IsRegistered)
{
Debug.Console(DebugInfo, this, "Server has already been started");
return;
}
IsRegistered = _server.Register();
Debug.Console(DebugInfo, this, "Starting server, registration {0}", IsRegistered ? "was successful" : "failed");
}
catch (Exception ex)
{
Debug.Console(DebugInfo, this, "Start Exception Message: {0}", ex.Message);
Debug.Console(DebugVerbose, this, "Start Exception StackTrace: {0}", ex.StackTrace);
if (ex.InnerException != null)
Debug.Console(DebugVerbose, this, "Start Exception InnerException: {0}", ex.InnerException);
}
finally
{
_serverLock.Leave();
}
_serverLock.Leave();
}
}
/// <summary>
/// Stop CWS instance
/// </summary>
public void Stop()
/// <summary>
/// Received request handler
/// </summary>
/// <remarks>
/// This is here for development and testing
/// </remarks>
/// <param name="sender"></param>
/// <param name="args"></param>
public void ReceivedRequestEventHandler(object sender, HttpCwsRequestEventArgs args)
{
try
{
try
{
_serverLock.Enter();
if (_server == null)
{
Debug.Console(DebugInfo, this, "Server is null or has already been stopped");
return;
}
IsRegistered = _server.Unregister() == false;
Debug.Console(DebugInfo, this, "Stopping server, unregistration {0}", IsRegistered ? "failed" : "was successful");
_server.Dispose();
_server = null;
}
catch (Exception ex)
{
Debug.Console(DebugInfo, this, "Server Stop Exception Message: {0}", ex.Message);
Debug.Console(DebugVerbose, this, "Server Stop Exception StackTrace: {0}", ex.StackTrace);
if (ex.InnerException != null)
Debug.Console(DebugVerbose, this, "Server Stop Exception InnerException: {0}", ex.InnerException);
}
finally
{
_serverLock.Leave();
}
var j = JsonConvert.SerializeObject(args.Context, Formatting.Indented);
Debug.Console(DebugVerbose, this, "RecieveRequestEventHandler Context:\x0d\x0a{0}", j);
}
/// <summary>
/// Received request handler
/// </summary>
/// <remarks>
/// This is here for development and testing
/// </remarks>
/// <param name="sender"></param>
/// <param name="args"></param>
public void ReceivedRequestEventHandler(object sender, HttpCwsRequestEventArgs args)
catch (Exception ex)
{
try
{
var j = JsonConvert.SerializeObject(args.Context, Formatting.Indented);
Debug.Console(DebugVerbose, this, "RecieveRequestEventHandler Context:\x0d\x0a{0}", j);
}
catch (Exception ex)
{
Debug.Console(DebugInfo, this, "ReceivedRequestEventHandler Exception Message: {0}", ex.Message);
Debug.Console(DebugVerbose, this, "ReceivedRequestEventHandler Exception StackTrace: {0}", ex.StackTrace);
if (ex.InnerException != null)
Debug.Console(DebugVerbose, this, "ReceivedRequestEventHandler Exception InnerException: {0}", ex.InnerException);
}
Debug.Console(DebugInfo, this, "ReceivedRequestEventHandler Exception Message: {0}", ex.Message);
Debug.Console(DebugVerbose, this, "ReceivedRequestEventHandler Exception StackTrace: {0}", ex.StackTrace);
if (ex.InnerException != null)
Debug.Console(DebugVerbose, this, "ReceivedRequestEventHandler Exception InnerException: {0}", ex.InnerException);
}
}
}
}

View File

@@ -1,11 +1,11 @@
using System;
using System.IO;
using Crestron.SimplSharp; // For Basic SIMPL# Classes
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Net.Http;
using Crestron.SimplSharp.Net.Https;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core.JsonToSimpl;
using static Crestron.SimplSharp.Net.Http;
using static Crestron.SimplSharp.Net.Https;
namespace PepperDash.Core.WebApi.Presets;

View File

@@ -1,6 +1,6 @@
using System;
using System.IO;
using System.Linq;
using Crestron.SimplSharp.CrestronIO;
using PepperDash.Core.Intersystem.Serialization;
using PepperDash.Core.Intersystem.Tokens;

View File

@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using Crestron.SimplSharp.CrestronIO;
using System.IO;
using PepperDash.Core.Intersystem.Serialization;
using PepperDash.Core.Intersystem.Tokens;
@@ -82,7 +82,7 @@ public sealed class XSigTokenStreamReader : IDisposable
{
if (ch == -1) // Reached end of stream without end of data marker
return null;
chars[n++] = (char)ch;
}

View File

@@ -1,7 +1,7 @@
using System;
using System.Linq;
using System.Collections.Generic;
using Crestron.SimplSharp.CrestronIO;
using System.IO;
using System.Linq;
using PepperDash.Core.Intersystem.Serialization;
using PepperDash.Core.Intersystem.Tokens;

View File

@@ -2,10 +2,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
@@ -14,230 +13,230 @@ using Serilog.Events;
namespace PepperDash.Essentials.Core;
/// <summary>
///
/// </summary>
public static class IRPortHelper
/// <summary>
///
/// </summary>
public static class IRPortHelper
{
public static string IrDriverPathPrefix
{
public static string IrDriverPathPrefix
get
{
get
{
return Global.FilePathPrefix + "IR" + Global.DirectorySeparator;
}
return Global.FilePathPrefix + "IR" + Global.DirectorySeparator;
}
/// <summary>
/// Finds either the ControlSystem or a device controller that contains IR ports and
/// returns a port from the hardware device
/// </summary>
/// <param name="propsToken"></param>
/// <returns>IrPortConfig object. The port and or filename will be empty/null
/// if valid values don't exist on config</returns>
public static IrOutPortConfig GetIrPort(JToken propsToken)
{
var control = propsToken["control"];
if (control == null)
return null;
if (control["method"].Value<string>() != "ir")
{
Debug.LogMessage(LogEventLevel.Information, "IRPortHelper called with non-IR properties");
return null;
}
var port = new IrOutPortConfig();
var portDevKey = control.Value<string>("controlPortDevKey");
var portNum = control.Value<uint>("controlPortNumber");
if (portDevKey == null || portNum == 0)
{
Debug.LogMessage(LogEventLevel.Debug, "WARNING: Properties is missing port device or port number");
return port;
}
IIROutputPorts irDev = null;
if (portDevKey.Equals("controlSystem", StringComparison.OrdinalIgnoreCase)
|| portDevKey.Equals("processor", StringComparison.OrdinalIgnoreCase))
irDev = Global.ControlSystem;
else
irDev = DeviceManager.GetDeviceForKey(portDevKey) as IIROutputPorts;
if (irDev == null)
{
Debug.LogMessage(LogEventLevel.Debug, "[Config] Error, device with IR ports '{0}' not found", portDevKey);
return port;
}
if (portNum <= irDev.NumberOfIROutputPorts) // success!
{
var file = IrDriverPathPrefix + control["irFile"].Value<string>();
port.Port = irDev.IROutputPorts[portNum];
port.FileName = file;
return port; // new IrOutPortConfig { Port = irDev.IROutputPorts[portNum], FileName = file };
}
else
{
Debug.LogMessage(LogEventLevel.Debug, "[Config] Error, device '{0}' IR port {1} out of range",
portDevKey, portNum);
return port;
}
}
public static IROutputPort GetIrOutputPort(DeviceConfig dc)
{
var irControllerKey = dc.Key + "-ir";
if (dc.Properties == null)
{
Debug.LogMessage(LogEventLevel.Information, "[{0}] WARNING: Device config does not include properties. IR will not function.", dc.Key);
return null;
}
var control = dc.Properties["control"];
if (control == null)
{
Debug.LogMessage(LogEventLevel.Information,
"WARNING: Device config does not include control properties. IR will not function for {0}", dc.Key);
return null;
}
var portDevKey = control.Value<string>("controlPortDevKey");
var portNum = control.Value<uint>("controlPortNumber");
IIROutputPorts irDev = null;
if (portDevKey == null)
{
Debug.LogMessage(LogEventLevel.Information, "WARNING: control properties is missing ir device for {0}", dc.Key);
return null;
}
if (portNum == 0)
{
Debug.LogMessage(LogEventLevel.Information, "WARNING: control properties is missing ir port number for {0}", dc.Key);
return null;
}
if (portDevKey.Equals("controlSystem", StringComparison.OrdinalIgnoreCase)
|| portDevKey.Equals("processor", StringComparison.OrdinalIgnoreCase))
irDev = Global.ControlSystem;
else
irDev = DeviceManager.GetDeviceForKey(portDevKey) as IIROutputPorts;
if (irDev == null)
{
Debug.LogMessage(LogEventLevel.Information, "WARNING: device with IR ports '{0}' not found", portDevKey);
return null;
}
if (portNum > irDev.NumberOfIROutputPorts)
{
Debug.LogMessage(LogEventLevel.Information, "WARNING: device '{0}' IR port {1} out of range",
portDevKey, portNum);
return null;
}
var port = irDev.IROutputPorts[portNum];
return port;
}
public static IrOutputPortController GetIrOutputPortController(DeviceConfig config)
{
Debug.LogMessage(LogEventLevel.Debug, "Attempting to create new Ir Port Controller");
if (config == null)
{
return null;
}
var postActivationFunc = new Func<DeviceConfig,IROutputPort> (GetIrOutputPort);
var irDevice = new IrOutputPortController(config.Key + "-ir", postActivationFunc, config);
return irDevice;
}
/*
/// <summary>
/// Returns a ready-to-go IrOutputPortController from a DeviceConfig object.
/// </summary>
public static IrOutputPortController GetIrOutputPortController(DeviceConfig devConf)
{
var irControllerKey = devConf.Key + "-ir";
if (devConf.Properties == null)
{
Debug.LogMessage(LogEventLevel.Information, "[{0}] WARNING: Device config does not include properties. IR will not function.", devConf.Key);
return new IrOutputPortController(irControllerKey, null, "");
}
var control = devConf.Properties["control"];
if (control == null)
{
var c = new IrOutputPortController(irControllerKey, null, "");
Debug.LogMessage(LogEventLevel.Information, c, "WARNING: Device config does not include control properties. IR will not function");
return c;
}
var portDevKey = control.Value<string>("controlPortDevKey");
var portNum = control.Value<uint>("controlPortNumber");
IIROutputPorts irDev = null;
if (portDevKey == null)
{
var c = new IrOutputPortController(irControllerKey, null, "");
Debug.LogMessage(LogEventLevel.Information, c, "WARNING: control properties is missing ir device");
return c;
}
if (portNum == 0)
{
var c = new IrOutputPortController(irControllerKey, null, "");
Debug.LogMessage(LogEventLevel.Information, c, "WARNING: control properties is missing ir port number");
return c;
}
if (portDevKey.Equals("controlSystem", StringComparison.OrdinalIgnoreCase)
|| portDevKey.Equals("processor", StringComparison.OrdinalIgnoreCase))
irDev = Global.ControlSystem;
else
irDev = DeviceManager.GetDeviceForKey(portDevKey) as IIROutputPorts;
if (irDev == null)
{
var c = new IrOutputPortController(irControllerKey, null, "");
Debug.LogMessage(LogEventLevel.Information, c, "WARNING: device with IR ports '{0}' not found", portDevKey);
return c;
}
if (portNum <= irDev.NumberOfIROutputPorts) // success!
return new IrOutputPortController(irControllerKey, irDev.IROutputPorts[portNum],
IrDriverPathPrefix + control["irFile"].Value<string>());
else
{
var c = new IrOutputPortController(irControllerKey, null, "");
Debug.LogMessage(LogEventLevel.Information, c, "WARNING: device '{0}' IR port {1} out of range",
portDevKey, portNum);
return c;
}
}*/
}
/// <summary>
/// Wrapper to help in IR port creation
/// Finds either the ControlSystem or a device controller that contains IR ports and
/// returns a port from the hardware device
/// </summary>
public class IrOutPortConfig
/// <param name="propsToken"></param>
/// <returns>IrPortConfig object. The port and or filename will be empty/null
/// if valid values don't exist on config</returns>
public static IrOutPortConfig GetIrPort(JToken propsToken)
{
[JsonProperty("port")]
public IROutputPort Port { get; set; }
[JsonProperty("fileName")]
public string FileName { get; set; }
[JsonProperty("useBridgeJoinMap")]
public bool UseBridgeJoinMap { get; set; }
public IrOutPortConfig()
var control = propsToken["control"];
if (control == null)
return null;
if (control["method"].Value<string>() != "ir")
{
FileName = "";
Debug.LogMessage(LogEventLevel.Information, "IRPortHelper called with non-IR properties");
return null;
}
}
var port = new IrOutPortConfig();
var portDevKey = control.Value<string>("controlPortDevKey");
var portNum = control.Value<uint>("controlPortNumber");
if (portDevKey == null || portNum == 0)
{
Debug.LogMessage(LogEventLevel.Debug, "WARNING: Properties is missing port device or port number");
return port;
}
IIROutputPorts irDev = null;
if (portDevKey.Equals("controlSystem", StringComparison.OrdinalIgnoreCase)
|| portDevKey.Equals("processor", StringComparison.OrdinalIgnoreCase))
irDev = Global.ControlSystem;
else
irDev = DeviceManager.GetDeviceForKey(portDevKey) as IIROutputPorts;
if (irDev == null)
{
Debug.LogMessage(LogEventLevel.Debug, "[Config] Error, device with IR ports '{0}' not found", portDevKey);
return port;
}
if (portNum <= irDev.NumberOfIROutputPorts) // success!
{
var file = IrDriverPathPrefix + control["irFile"].Value<string>();
port.Port = irDev.IROutputPorts[portNum];
port.FileName = file;
return port; // new IrOutPortConfig { Port = irDev.IROutputPorts[portNum], FileName = file };
}
else
{
Debug.LogMessage(LogEventLevel.Debug, "[Config] Error, device '{0}' IR port {1} out of range",
portDevKey, portNum);
return port;
}
}
public static IROutputPort GetIrOutputPort(DeviceConfig dc)
{
var irControllerKey = dc.Key + "-ir";
if (dc.Properties == null)
{
Debug.LogMessage(LogEventLevel.Information, "[{0}] WARNING: Device config does not include properties. IR will not function.", dc.Key);
return null;
}
var control = dc.Properties["control"];
if (control == null)
{
Debug.LogMessage(LogEventLevel.Information,
"WARNING: Device config does not include control properties. IR will not function for {0}", dc.Key);
return null;
}
var portDevKey = control.Value<string>("controlPortDevKey");
var portNum = control.Value<uint>("controlPortNumber");
IIROutputPorts irDev = null;
if (portDevKey == null)
{
Debug.LogMessage(LogEventLevel.Information, "WARNING: control properties is missing ir device for {0}", dc.Key);
return null;
}
if (portNum == 0)
{
Debug.LogMessage(LogEventLevel.Information, "WARNING: control properties is missing ir port number for {0}", dc.Key);
return null;
}
if (portDevKey.Equals("controlSystem", StringComparison.OrdinalIgnoreCase)
|| portDevKey.Equals("processor", StringComparison.OrdinalIgnoreCase))
irDev = Global.ControlSystem;
else
irDev = DeviceManager.GetDeviceForKey(portDevKey) as IIROutputPorts;
if (irDev == null)
{
Debug.LogMessage(LogEventLevel.Information, "WARNING: device with IR ports '{0}' not found", portDevKey);
return null;
}
if (portNum > irDev.NumberOfIROutputPorts)
{
Debug.LogMessage(LogEventLevel.Information, "WARNING: device '{0}' IR port {1} out of range",
portDevKey, portNum);
return null;
}
var port = irDev.IROutputPorts[portNum];
return port;
}
public static IrOutputPortController GetIrOutputPortController(DeviceConfig config)
{
Debug.LogMessage(LogEventLevel.Debug, "Attempting to create new Ir Port Controller");
if (config == null)
{
return null;
}
var postActivationFunc = new Func<DeviceConfig, IROutputPort>(GetIrOutputPort);
var irDevice = new IrOutputPortController(config.Key + "-ir", postActivationFunc, config);
return irDevice;
}
/*
/// <summary>
/// Returns a ready-to-go IrOutputPortController from a DeviceConfig object.
/// </summary>
public static IrOutputPortController GetIrOutputPortController(DeviceConfig devConf)
{
var irControllerKey = devConf.Key + "-ir";
if (devConf.Properties == null)
{
Debug.LogMessage(LogEventLevel.Information, "[{0}] WARNING: Device config does not include properties. IR will not function.", devConf.Key);
return new IrOutputPortController(irControllerKey, null, "");
}
var control = devConf.Properties["control"];
if (control == null)
{
var c = new IrOutputPortController(irControllerKey, null, "");
Debug.LogMessage(LogEventLevel.Information, c, "WARNING: Device config does not include control properties. IR will not function");
return c;
}
var portDevKey = control.Value<string>("controlPortDevKey");
var portNum = control.Value<uint>("controlPortNumber");
IIROutputPorts irDev = null;
if (portDevKey == null)
{
var c = new IrOutputPortController(irControllerKey, null, "");
Debug.LogMessage(LogEventLevel.Information, c, "WARNING: control properties is missing ir device");
return c;
}
if (portNum == 0)
{
var c = new IrOutputPortController(irControllerKey, null, "");
Debug.LogMessage(LogEventLevel.Information, c, "WARNING: control properties is missing ir port number");
return c;
}
if (portDevKey.Equals("controlSystem", StringComparison.OrdinalIgnoreCase)
|| portDevKey.Equals("processor", StringComparison.OrdinalIgnoreCase))
irDev = Global.ControlSystem;
else
irDev = DeviceManager.GetDeviceForKey(portDevKey) as IIROutputPorts;
if (irDev == null)
{
var c = new IrOutputPortController(irControllerKey, null, "");
Debug.LogMessage(LogEventLevel.Information, c, "WARNING: device with IR ports '{0}' not found", portDevKey);
return c;
}
if (portNum <= irDev.NumberOfIROutputPorts) // success!
return new IrOutputPortController(irControllerKey, irDev.IROutputPorts[portNum],
IrDriverPathPrefix + control["irFile"].Value<string>());
else
{
var c = new IrOutputPortController(irControllerKey, null, "");
Debug.LogMessage(LogEventLevel.Information, c, "WARNING: device '{0}' IR port {1} out of range",
portDevKey, portNum);
return c;
}
}*/
}
/// <summary>
/// Wrapper to help in IR port creation
/// </summary>
public class IrOutPortConfig
{
[JsonProperty("port")]
public IROutputPort Port { get; set; }
[JsonProperty("fileName")]
public string FileName { get; set; }
[JsonProperty("useBridgeJoinMap")]
public bool UseBridgeJoinMap { get; set; }
public IrOutPortConfig()
{
FileName = "";
}
}

View File

@@ -2,10 +2,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
@@ -47,7 +46,7 @@ public class DeviceConfig
//Properties = JToken.FromObject(dc.Properties);
}
public DeviceConfig() {}
public DeviceConfig() { }
}
/// <summary>

View File

@@ -1,10 +1,10 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
@@ -13,24 +13,24 @@ using Serilog.Events;
namespace PepperDash.Essentials.Core.Config;
/// <summary>
/// Loads the ConfigObject from the file
/// </summary>
public class ConfigReader
{
public const string LocalConfigPresent =
@"
/// <summary>
/// Loads the ConfigObject from the file
/// </summary>
public class ConfigReader
{
public const string LocalConfigPresent =
@"
***************************************************
************* Using Local config file *************
***************************************************";
public static EssentialsConfig ConfigObject { get; private set; }
public static EssentialsConfig ConfigObject { get; private set; }
public static bool LoadConfig2()
{
Debug.LogMessage(LogEventLevel.Information, "Loading unmerged system/template portal configuration file.");
try
{
public static bool LoadConfig2()
{
Debug.LogMessage(LogEventLevel.Information, "Loading unmerged system/template portal configuration file.");
try
{
// Check for local config file first
var filePath = Global.FilePathPrefix + ConfigWriter.LocalConfigFolder + Global.DirectorySeparator + Global.ConfigFileName;
@@ -50,10 +50,10 @@ namespace PepperDash.Essentials.Core.Config;
"****Error: Multiple Local Configuration files present. Please ensure only a single file exists and reset program.****");
return false;
}
if(configFiles.Length == 1)
if (configFiles.Length == 1)
{
localConfigFound = true;
}
}
else
@@ -64,7 +64,7 @@ namespace PepperDash.Essentials.Core.Config;
}
// Check for Portal Config
if(!localConfigFound)
if (!localConfigFound)
{
filePath = Global.FilePathPrefix + Global.ConfigFileName;
@@ -104,10 +104,10 @@ namespace PepperDash.Essentials.Core.Config;
filePath = configFiles[0].FullName;
// Generate debug statement if using a local file.
if (localConfigFound)
{
if (localConfigFound)
{
GetLocalFileMessage(filePath);
}
}
// Read the file
using (StreamReader fs = new StreamReader(filePath))
@@ -144,13 +144,13 @@ namespace PepperDash.Essentials.Core.Config;
return true;
}
}
catch (Exception e)
{
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Information, "ERROR: Config load failed: \r{0}", e);
return false;
}
}
return false;
}
}
/// <summary>
/// Returns all the files from the directory specified.
@@ -184,19 +184,19 @@ namespace PepperDash.Essentials.Core.Config;
}
}
/// <summary>
/// Returns the group for a given device key in config
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
/// <summary>
/// Returns the group for a given device key in config
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static string GetGroupForDeviceKey(string key)
{
var dev = ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
return dev == null ? null : dev.Group;
}
private static void GetLocalFileMessage(string filePath)
{
private static void GetLocalFileMessage(string filePath)
{
var filePathLength = filePath.Length + 2;
var debugStringWidth = filePathLength + 12;
@@ -211,46 +211,46 @@ namespace PepperDash.Essentials.Core.Config;
var bookend2 = (debugStringWidth - filePathLength) / 2;
var newDebugString = new StringBuilder()
.Append(CrestronEnvironment.NewLine)
var newDebugString = new StringBuilder()
.Append(CrestronEnvironment.NewLine)
// Line 1
.Append(new string('*', debugStringWidth))
.Append(CrestronEnvironment.NewLine)
.Append(new string('*', debugStringWidth))
.Append(CrestronEnvironment.NewLine)
// Line 2
.Append(new string('*', debugStringWidth))
.Append(CrestronEnvironment.NewLine)
.Append(new string('*', debugStringWidth))
.Append(CrestronEnvironment.NewLine)
// Line 3
.Append(new string('*', 2))
.Append(new string(' ', debugStringWidth - 4))
.Append(new string('*', 2))
.Append(CrestronEnvironment.NewLine)
.Append(new string('*', 2))
.Append(new string(' ', debugStringWidth - 4))
.Append(new string('*', 2))
.Append(CrestronEnvironment.NewLine)
// Line 4
.Append(new string('*', 2))
.Append(new string(' ', bookend1 - 2))
.Append(qualifier)
.Append(new string(' ', bookend1 - 2))
.Append(new string('*', 2))
.Append(CrestronEnvironment.NewLine)
.Append(new string('*', 2))
.Append(new string(' ', bookend1 - 2))
.Append(qualifier)
.Append(new string(' ', bookend1 - 2))
.Append(new string('*', 2))
.Append(CrestronEnvironment.NewLine)
// Line 5
.Append(new string('*', 2))
.Append(new string(' ', bookend2 - 2))
.Append(" " + filePath + " ")
.Append(new string(' ', bookend2 - 2))
.Append(new string('*', 2))
.Append(CrestronEnvironment.NewLine)
.Append(new string('*', 2))
.Append(new string(' ', bookend2 - 2))
.Append(" " + filePath + " ")
.Append(new string(' ', bookend2 - 2))
.Append(new string('*', 2))
.Append(CrestronEnvironment.NewLine)
// Line 6
.Append(new string('*', 2))
.Append(new string(' ', debugStringWidth - 4))
.Append(new string('*', 2))
.Append(CrestronEnvironment.NewLine)
.Append(new string('*', 2))
.Append(new string(' ', debugStringWidth - 4))
.Append(new string('*', 2))
.Append(CrestronEnvironment.NewLine)
// Line 7
.Append(new string('*', debugStringWidth))
.Append(CrestronEnvironment.NewLine)
.Append(new string('*', debugStringWidth))
.Append(CrestronEnvironment.NewLine)
// Line 8
.Append(new string('*', debugStringWidth));
.Append(new string('*', debugStringWidth));
Debug.LogMessage(LogEventLevel.Verbose, "Found Local config file: '{0}'", filePath);
Debug.LogMessage(LogEventLevel.Information, newDebugString.ToString());
}
}
}
}

View File

@@ -2,15 +2,14 @@
using System;
using System.Collections.Generic;
using System.IO;
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 Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using Serilog.Events;
@@ -71,7 +70,7 @@ public static class ConfigUpdater
{
var handler = ConfigStatusChanged;
if(handler != null)
if (handler != null)
{
handler(typeof(ConfigUpdater), new ConfigStatusEventArgs(status));
}
@@ -79,7 +78,7 @@ public static class ConfigUpdater
static void WriteConfigToFile(string configData)
{
var filePath = Global.FilePathPrefix+ "configurationFile-updated.json";
var filePath = Global.FilePathPrefix + "configurationFile-updated.json";
try
{
@@ -94,7 +93,7 @@ public static class ConfigUpdater
Debug.LogMessage(LogEventLevel.Debug, "Error parsing new config: {0}", e);
OnStatusUpdate(eUpdateStatus.UpdateFailed);
}
}
}
/// <summary>
@@ -132,18 +131,18 @@ public static class ConfigUpdater
if (!Directory.Exists(archiveDirectoryPath))
{
// Directory does not exist, create it
Directory.Create(archiveDirectoryPath);
Directory.CreateDirectory(archiveDirectoryPath);
}
else
{
// Directory exists, first clear any contents
var archivedConfigFiles = ConfigReader.GetConfigFiles(archiveDirectoryPath + Global.DirectorySeparator + Global.ConfigFileName + ".bak");
if(archivedConfigFiles != null || archivedConfigFiles.Length > 0)
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++ )
for (int i = 0; i < archivedConfigFiles.Length; i++)
{
var file = archivedConfigFiles[i];
Debug.LogMessage(LogEventLevel.Information, "Deleting archived file: '{0}'", file.FullName);
@@ -160,9 +159,9 @@ public static class ConfigUpdater
// Moves the file and appends the .bak extension
var fileDest = archiveDirectoryPath + "/" + file.Name + ".bak";
if(!File.Exists(fileDest))
if (!File.Exists(fileDest))
{
file.MoveTo(fileDest);
file.MoveTo(fileDest);
}
else
Debug.LogMessage(LogEventLevel.Information, "Cannot move file to archive folder. Existing file already exists with same name: '{0}'", fileDest);
@@ -197,12 +196,12 @@ public static class ConfigUpdater
CrestronConsole.SendControlSystemCommand(string.Format("progreset -p:{0}", InitialParametersClass.ApplicationNumber), ref response);
Debug.LogMessage(LogEventLevel.Debug, "Console Response: {0}", response);
Debug.LogMessage(LogEventLevel.Debug, "Console Response: {0}", response);
}
}
public enum eUpdateStatus
public enum eUpdateStatus
{
UpdateStarted,
ConfigFileReceived,

View File

@@ -2,10 +2,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
@@ -23,7 +23,7 @@ public class ConfigWriter
public const long WriteTimeout = 30000;
public static CTimer WriteTimer;
static CCriticalSection fileLock = new CCriticalSection();
static CCriticalSection fileLock = new CCriticalSection();
/// <summary>
/// Updates the config properties of a device
@@ -77,9 +77,9 @@ public class ConfigWriter
{
bool success = false;
var roomConfigIndex = ConfigReader.ConfigObject.Rooms.FindIndex(d => d.Key.Equals(config.Key));
var roomConfigIndex = ConfigReader.ConfigObject.Rooms.FindIndex(d => d.Key.Equals(config.Key));
if (roomConfigIndex >= 0)
if (roomConfigIndex >= 0)
{
ConfigReader.ConfigObject.Rooms[roomConfigIndex] = config;

View File

@@ -2,88 +2,88 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json;
using PepperDash.Core;
namespace PepperDash.Essentials.Core.Config;
/// <summary>
/// Loads the ConfigObject from the file
/// </summary>
public class EssentialsConfig : BasicConfig
/// <summary>
/// Loads the ConfigObject from the file
/// </summary>
public class EssentialsConfig : BasicConfig
{
[JsonProperty("system_url")]
public string SystemUrl { get; set; }
[JsonProperty("template_url")]
public string TemplateUrl { get; set; }
[JsonProperty("systemUuid")]
public string SystemUuid
{
[JsonProperty("system_url")]
public string SystemUrl { get; set; }
get
{
if (string.IsNullOrEmpty(SystemUrl))
return "missing url";
[JsonProperty("template_url")]
public string TemplateUrl { get; set; }
[JsonProperty("systemUuid")]
public string SystemUuid
{
get
{
if (string.IsNullOrEmpty(SystemUrl))
return "missing url";
if (SystemUrl.Contains("#"))
{
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/#.*");
string uuid = result.Groups[1].Value;
return uuid;
} else
{
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/.*");
string uuid = result.Groups[1].Value;
return uuid;
}
}
}
[JsonProperty("templateUuid")]
public string TemplateUuid
{
get
{
if (string.IsNullOrEmpty(TemplateUrl))
return "missing template url";
if (TemplateUrl.Contains("#"))
{
var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/templates\/(.*)\/#.*");
string uuid = result.Groups[1].Value;
return uuid;
} else
{
var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/system-templates\/(.*)\/system-template-versions\/(.*)\/.*");
string uuid = result.Groups[2].Value;
return uuid;
}
}
}
[JsonProperty("rooms")]
public List<DeviceConfig> Rooms { get; set; }
public EssentialsConfig()
: base()
{
Rooms = new List<DeviceConfig>();
}
if (SystemUrl.Contains("#"))
{
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/#.*");
string uuid = result.Groups[1].Value;
return uuid;
}
else
{
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/.*");
string uuid = result.Groups[1].Value;
return uuid;
}
}
}
/// <summary>
///
/// </summary>
public class SystemTemplateConfigs
{
public EssentialsConfig System { get; set; }
public EssentialsConfig Template { get; set; }
}
[JsonProperty("templateUuid")]
public string TemplateUuid
{
get
{
if (string.IsNullOrEmpty(TemplateUrl))
return "missing template url";
if (TemplateUrl.Contains("#"))
{
var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/templates\/(.*)\/#.*");
string uuid = result.Groups[1].Value;
return uuid;
}
else
{
var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/system-templates\/(.*)\/system-template-versions\/(.*)\/.*");
string uuid = result.Groups[2].Value;
return uuid;
}
}
}
[JsonProperty("rooms")]
public List<DeviceConfig> Rooms { get; set; }
public EssentialsConfig()
: base()
{
Rooms = new List<DeviceConfig>();
}
}
/// <summary>
///
/// </summary>
public class SystemTemplateConfigs
{
public EssentialsConfig System { get; set; }
public EssentialsConfig Template { get; set; }
}

View File

@@ -1,276 +1,276 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using PepperDash.Core;
using Crestron.SimplSharpPro.CrestronThread;
using PepperDash.Core;
using Serilog.Events;
namespace PepperDash.Essentials.Core;
public static class FileIO
public static class FileIO
{
static CCriticalSection fileLock = new CCriticalSection();
public delegate void GotFileEventHandler(object sender, FileEventArgs e);
public static event GotFileEventHandler GotFileEvent;
/// <summary>
/// Get the full file info from a path/filename, can include wildcards.
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public static FileInfo[] GetFiles(string fileName)
{
static CCriticalSection fileLock = new CCriticalSection();
public delegate void GotFileEventHandler(object sender, FileEventArgs e);
public static event GotFileEventHandler GotFileEvent;
/// <summary>
/// Get the full file info from a path/filename, can include wildcards.
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public static FileInfo[] GetFiles(string fileName)
{
string fullFilePath = Global.FilePathPrefix + fileName;
DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(fullFilePath));
var files = dirInfo.GetFiles(Path.GetFileName(fullFilePath));
Debug.LogMessage(LogEventLevel.Information, "FileIO found: {0}, {1}", files.Count(), fullFilePath);
if (files.Count() > 0)
{
return files;
}
else
{
return null;
}
}
public static FileInfo GetFile(string fileName)
{
string fullFilePath = Global.FilePathPrefix + fileName;
DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(fullFilePath));
var files = dirInfo.GetFiles(Path.GetFileName(fullFilePath));
Debug.LogMessage(LogEventLevel.Information, "FileIO found: {0}, {1}", files.Count(), fullFilePath);
if (files.Count() > 0)
{
return files.FirstOrDefault();
}
else
{
return null;
}
}
/// <summary>
/// Get the data from string path/filename
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public static string ReadDataFromFile(string fileName)
string fullFilePath = Global.FilePathPrefix + fileName;
DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(fullFilePath));
var files = dirInfo.GetFiles(Path.GetFileName(fullFilePath));
Debug.LogMessage(LogEventLevel.Information, "FileIO found: {0}, {1}", files.Count(), fullFilePath);
if (files.Count() > 0)
{
try
{
return ReadDataFromFile(GetFile(fileName));
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Information, "Error: FileIO read failed: \r{0}", e);
return "";
}
return files;
}
/// <summary>
/// Get the data with fileInfo object
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public static string ReadDataFromFile(FileInfo file)
else
{
try
{
if (fileLock.TryEnter())
{
DirectoryInfo dirInfo = new DirectoryInfo(file.DirectoryName);
Debug.LogMessage(LogEventLevel.Verbose, "FileIO Getting Data {0}", file.FullName);
return null;
}
}
if (File.Exists(file.FullName))
public static FileInfo GetFile(string fileName)
{
string fullFilePath = Global.FilePathPrefix + fileName;
DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(fullFilePath));
var files = dirInfo.GetFiles(Path.GetFileName(fullFilePath));
Debug.LogMessage(LogEventLevel.Information, "FileIO found: {0}, {1}", files.Count(), fullFilePath);
if (files.Count() > 0)
{
return files.FirstOrDefault();
}
else
{
return null;
}
}
/// <summary>
/// Get the data from string path/filename
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public static string ReadDataFromFile(string fileName)
{
try
{
return ReadDataFromFile(GetFile(fileName));
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Information, "Error: FileIO read failed: \r{0}", e);
return "";
}
}
/// <summary>
/// Get the data with fileInfo object
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public static string ReadDataFromFile(FileInfo file)
{
try
{
if (fileLock.TryEnter())
{
DirectoryInfo dirInfo = new DirectoryInfo(file.DirectoryName);
Debug.LogMessage(LogEventLevel.Verbose, "FileIO Getting Data {0}", file.FullName);
if (File.Exists(file.FullName))
{
using (StreamReader r = new StreamReader(file.FullName))
{
using (StreamReader r = new StreamReader(file.FullName))
{
return r.ReadToEnd();
}
}
else
{
Debug.LogMessage(LogEventLevel.Verbose, "File {0} does not exsist", file.FullName);
return "";
return r.ReadToEnd();
}
}
else
{
Debug.LogMessage(LogEventLevel.Information, "FileIO Unable to enter FileLock");
Debug.LogMessage(LogEventLevel.Verbose, "File {0} does not exsist", file.FullName);
return "";
}
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Information, "Error: FileIO read failed: \r{0}", e);
return "";
}
finally
{
if (fileLock != null && !fileLock.Disposed)
fileLock.Leave();
}
}
public static void ReadDataFromFileASync(string fileName)
{
try
{
ReadDataFromFileASync(GetFile(fileName));
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Information, "Error: FileIO read failed: \r{0}", e);
}
}
public static void ReadDataFromFileASync(FileInfo file)
{
try
{
CrestronInvoke.BeginInvoke(o => _ReadDataFromFileASync(file));
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Information, "Error: FileIO read failed: \r{0}", e);
}
}
private static void _ReadDataFromFileASync(FileInfo file)
{
string data;
try
{
if (fileLock.TryEnter())
{
DirectoryInfo dirInfo = new DirectoryInfo(file.Name);
Debug.LogMessage(LogEventLevel.Verbose, "FileIO Getting Data {0}", file.FullName);
if (File.Exists(file.FullName))
{
using (StreamReader r = new StreamReader(file.FullName))
{
data = r.ReadToEnd();
}
}
else
{
Debug.LogMessage(LogEventLevel.Verbose, "File {0} Does not exsist", file.FullName);
data = "";
}
GotFileEvent.Invoke(null, new FileEventArgs(data));
}
else
{
Debug.LogMessage(LogEventLevel.Information, "FileIO Unable to enter FileLock");
}
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Information, "Error: FileIO read failed: \r{0}", e);
data = "";
}
finally
{
if (fileLock != null && !fileLock.Disposed)
fileLock.Leave();
}
}
/// <summary>
///
/// </summary>
/// <param name="data"></param>
/// <param name="filePath"></param>
public static void WriteDataToFile(string data, string filePath)
{
Thread _WriteFileThread;
_WriteFileThread = new Thread((O) => _WriteFileMethod(data, Global.FilePathPrefix + "/" + filePath), null, Thread.eThreadStartOptions.CreateSuspended);
_WriteFileThread.Priority = Thread.eThreadPriority.LowestPriority;
_WriteFileThread.Start();
Debug.LogMessage(LogEventLevel.Information, "New WriteFile Thread");
}
static object _WriteFileMethod(string data, string filePath)
{
Debug.LogMessage(LogEventLevel.Information, "Attempting to write file: '{0}'", filePath);
try
{
if (fileLock.TryEnter())
{
using (StreamWriter sw = new StreamWriter(filePath))
{
sw.Write(data);
sw.Flush();
}
}
else
{
Debug.LogMessage(LogEventLevel.Information, "FileIO Unable to enter FileLock");
}
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Error, "Error: FileIO write failed: \r{0}", e);
}
finally
{
if (fileLock != null && !fileLock.Disposed)
fileLock.Leave();
}
return null;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public static bool FileIoUnitTest()
{
var testData = "Testing FileIO";
FileIO.WriteDataToFile(testData, "\\user\\FileIOTest.pdt");
var file = FileIO.GetFile("\\user\\*FileIOTest*");
var readData = FileIO.ReadDataFromFile(file);
Debug.LogMessage(LogEventLevel.Information, "Returned {0}", readData);
File.Delete(file.FullName);
if (testData == readData)
{
return true;
}
else
{
return false;
Debug.LogMessage(LogEventLevel.Information, "FileIO Unable to enter FileLock");
return "";
}
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Information, "Error: FileIO read failed: \r{0}", e);
return "";
}
finally
{
if (fileLock != null && !fileLock.Disposed)
fileLock.Leave();
}
}
public static void ReadDataFromFileASync(string fileName)
{
try
{
ReadDataFromFileASync(GetFile(fileName));
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Information, "Error: FileIO read failed: \r{0}", e);
}
}
public static void ReadDataFromFileASync(FileInfo file)
{
try
{
CrestronInvoke.BeginInvoke(o => _ReadDataFromFileASync(file));
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Information, "Error: FileIO read failed: \r{0}", e);
}
}
private static void _ReadDataFromFileASync(FileInfo file)
{
string data;
try
{
if (fileLock.TryEnter())
{
DirectoryInfo dirInfo = new DirectoryInfo(file.Name);
Debug.LogMessage(LogEventLevel.Verbose, "FileIO Getting Data {0}", file.FullName);
if (File.Exists(file.FullName))
{
using (StreamReader r = new StreamReader(file.FullName))
{
data = r.ReadToEnd();
}
}
else
{
Debug.LogMessage(LogEventLevel.Verbose, "File {0} Does not exsist", file.FullName);
data = "";
}
GotFileEvent.Invoke(null, new FileEventArgs(data));
}
else
{
Debug.LogMessage(LogEventLevel.Information, "FileIO Unable to enter FileLock");
}
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Information, "Error: FileIO read failed: \r{0}", e);
data = "";
}
finally
{
if (fileLock != null && !fileLock.Disposed)
fileLock.Leave();
}
}
public class FileEventArgs
{
public FileEventArgs(string data) { Data = data; }
public string Data { get; private set; } // readonly
}
}
/// <summary>
///
/// </summary>
/// <param name="data"></param>
/// <param name="filePath"></param>
public static void WriteDataToFile(string data, string filePath)
{
Thread _WriteFileThread;
_WriteFileThread = new Thread((O) => _WriteFileMethod(data, Global.FilePathPrefix + "/" + filePath), null, Thread.eThreadStartOptions.CreateSuspended);
_WriteFileThread.Priority = Thread.eThreadPriority.LowestPriority;
_WriteFileThread.Start();
Debug.LogMessage(LogEventLevel.Information, "New WriteFile Thread");
}
static object _WriteFileMethod(string data, string filePath)
{
Debug.LogMessage(LogEventLevel.Information, "Attempting to write file: '{0}'", filePath);
try
{
if (fileLock.TryEnter())
{
using (StreamWriter sw = new StreamWriter(filePath))
{
sw.Write(data);
sw.Flush();
}
}
else
{
Debug.LogMessage(LogEventLevel.Information, "FileIO Unable to enter FileLock");
}
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Error, "Error: FileIO write failed: \r{0}", e);
}
finally
{
if (fileLock != null && !fileLock.Disposed)
fileLock.Leave();
}
return null;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public static bool FileIoUnitTest()
{
var testData = "Testing FileIO";
FileIO.WriteDataToFile(testData, "\\user\\FileIOTest.pdt");
var file = FileIO.GetFile("\\user\\*FileIOTest*");
var readData = FileIO.ReadDataFromFile(file);
Debug.LogMessage(LogEventLevel.Information, "Returned {0}", readData);
File.Delete(file.FullName);
if (testData == readData)
{
return true;
}
else
{
return false;
}
}
}
public class FileEventArgs
{
public FileEventArgs(string data) { Data = data; }
public string Data { get; private set; } // readonly
}

View File

@@ -1,7 +1,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.CrestronXml;
using Crestron.SimplSharp.CrestronXml.Serialization;
using Crestron.SimplSharpPro;
@@ -11,10 +15,6 @@ using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using Serilog.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PepperDash.Essentials.Core.Fusion;
@@ -107,7 +107,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
JoinMap.SetCustomJoinData(customJoins);
}
}
Room = room;
_ipId = ipId;
@@ -137,7 +137,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
File.Delete(oldGuidFilePath);
}
_guidFileExists = File.Exists(guidFilePath);
_guidFileExists = File.Exists(guidFilePath);
// Check if file exists
if (!_guidFileExists)
@@ -301,7 +301,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
if (File.Exists(filePath))
{
var json = File.ReadToEnd(filePath, Encoding.ASCII);
var json = File.ReadAllText(filePath, Encoding.ASCII);
_guiDs = JsonConvert.DeserializeObject<FusionRoomGuids>(json);
@@ -466,7 +466,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
// Interface 1
if (InitialParametersClass.NumberOfEthernetInterfaces > 1)
// Only get these values if the processor has more than 1 NIC
// Only get these values if the processor has more than 1 NIC
{
_ip2.InputSig.StringValue =
CrestronEthernetHelper.GetEthernetParameter(
@@ -490,7 +490,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
{
var join = JoinMap.ProgramNameStart.JoinNumber + i;
var progNum = i + 1;
_program[i] = FusionRoom.CreateOffsetStringSig((uint) join,
_program[i] = FusionRoom.CreateOffsetStringSig((uint)join,
string.Format("{0} {1}", JoinMap.ProgramNameStart.AttributeName, progNum), eSigIoMask.InputSigOnly);
}
}
@@ -519,7 +519,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
{
if (args.DeviceOnLine)
{
CrestronInvoke.BeginInvoke( (o) =>
CrestronInvoke.BeginInvoke((o) =>
{
CrestronEnvironment.Sleep(200);
@@ -658,7 +658,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
var extendTime = _currentMeeting.dtEnd - DateTime.Now;
var extendMinutesRaw = extendTime.TotalMinutes;
extendMinutes += (int) Math.Round(extendMinutesRaw);
extendMinutes += (int)Math.Round(extendMinutesRaw);
}
@@ -766,11 +766,11 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
var parameters = actionResponse["Parameters"];
foreach (var isRegistered in from XmlElement parameter in parameters
where parameter.HasAttributes
select parameter.Attributes
where parameter.HasAttributes
select parameter.Attributes
into attributes
where attributes["ID"].Value == "Registered"
select Int32.Parse(attributes["Value"].Value))
where attributes["ID"].Value == "Registered"
select Int32.Parse(attributes["Value"].Value))
{
switch (isRegistered)
{
@@ -827,9 +827,9 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
Debug.LogMessage(LogEventLevel.Debug, this, "DateTime from Fusion Server: {0}", currentTime);
// Parse time and date from response and insert values
CrestronEnvironment.SetTimeAndDate((ushort) currentTime.Hour, (ushort) currentTime.Minute,
(ushort) currentTime.Second, (ushort) currentTime.Month, (ushort) currentTime.Day,
(ushort) currentTime.Year);
CrestronEnvironment.SetTimeAndDate((ushort)currentTime.Hour, (ushort)currentTime.Minute,
(ushort)currentTime.Second, (ushort)currentTime.Month, (ushort)currentTime.Day,
(ushort)currentTime.Year);
Debug.LogMessage(LogEventLevel.Debug, this, "Processor time set to {0}", CrestronEnvironment.GetLocalTime());
}
@@ -1093,7 +1093,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
foreach (var usageDevice in dict.Select(kvp => kvp.Value.SourceDevice).OfType<IUsageTracking>())
{
usageDevice.UsageTracker = new UsageTracking(usageDevice as Device) {UsageIsTracked = true};
usageDevice.UsageTracker = new UsageTracking(usageDevice as Device) { UsageIsTracked = true };
usageDevice.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
}
}
@@ -1279,7 +1279,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
foreach (var display in displays.Cast<IDisplay>())
{
display.UsageTracker = new UsageTracking(display as Device) {UsageIsTracked = true};
display.UsageTracker = new UsageTracking(display as Device) { UsageIsTracked = true };
display.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
}
@@ -1392,7 +1392,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
// Power on
var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint) joinOffset, displayName + "Power On",
var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On",
eSigIoMask.InputOutputSig);
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b =>
{
@@ -1403,7 +1403,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
});
// Power Off
var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint) joinOffset + 1, displayName + "Power Off",
var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off",
eSigIoMask.InputOutputSig);
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b =>
{
@@ -1421,7 +1421,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
}
// Current Source
var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint) joinOffset + 8,
var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8,
displayName + "Source None", eSigIoMask.InputOutputSig);
defaultDisplaySourceNone.OutputSig.UserObject = new Action<bool>(b =>
{
@@ -1514,7 +1514,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
occRoom.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
}
RoomOccupancyRemoteStringFeedback = new StringFeedback(() => _roomOccupancyRemoteString);
RoomOccupancyRemoteStringFeedback.LinkInputSig(occSensorAsset.RoomOccupancyInfo.InputSig);
//}

View File

@@ -1,34 +1,32 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Globalization;
using Crestron.SimplSharp;
using System.Collections.Generic;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.CrestronDataStore;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DM;
using PepperDash.Core;
using PepperDash.Essentials.License;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;
using PepperDash.Core;
using PepperDash.Essentials.License;
using Serilog.Events;
namespace PepperDash.Essentials.Core;
public static class Global
{
public static CrestronControlSystem ControlSystem { get; set; }
public static class Global
{
public static CrestronControlSystem ControlSystem { get; set; }
public static eDevicePlatform Platform { get { return CrestronEnvironment.DevicePlatform; } }
public static Dictionary<short, EthernetAdapterInfo> EthernetAdapterInfoCollection { get; private set; }
public static LicenseManager LicenseManager { get; set; }
public static LicenseManager LicenseManager { get; set; }
public static eCrestronSeries ProcessorSeries { get { return CrestronEnvironment.ProgramCompatibility; } }
@@ -43,12 +41,12 @@ namespace PepperDash.Essentials.Core;
{
get
{
if(ControlSystem.SystemControl != null)
if (ControlSystem.SystemControl != null)
{
if(ControlSystem.SystemControl.SystemControlType > 0)
if (ControlSystem.SystemControl.SystemControlType > 0)
{
return true;
}
}
}
return false;
}
@@ -61,37 +59,37 @@ namespace PepperDash.Essentials.Core;
{
get
{
if(ControlSystem.SystemControl != null)
if (ControlSystem.SystemControl != null)
{
if(ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K150CSystemControl ||
if (ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K150CSystemControl ||
ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K200CSystemControl ||
ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K250CSystemControl ||
ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K300CSystemControl ||
ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K350CSystemControl)
{
return true;
}
}
}
return false;
}
}
/// <summary>
/// <summary>
/// True when the processor type is a DMPS 4K 200/300/250/350 variant
/// </summary>
public static bool ControlSystemIsDmps4k3xxType
{
get
{
if(ControlSystem.SystemControl != null)
if (ControlSystem.SystemControl != null)
{
if(ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K200CSystemControl ||
if (ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K200CSystemControl ||
ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K250CSystemControl ||
ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K300CSystemControl ||
ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K350CSystemControl)
{
return true;
}
}
}
return false;
}
@@ -105,11 +103,11 @@ namespace PepperDash.Essentials.Core;
/// <summary>
/// The file path prefix to the applciation directory
/// </summary>
public static string ApplicationDirectoryPathPrefix
public static string ApplicationDirectoryPathPrefix
{
get
{
return Crestron.SimplSharp.CrestronIO.Directory.GetApplicationDirectory();
return Directory.GetCurrentDirectory();
}
}
@@ -166,37 +164,37 @@ namespace PepperDash.Essentials.Core;
AssemblyVersion = assemblyVersion;
}
public static bool IsRunningDevelopmentVersion(List<string> developmentVersions, string minimumVersion)
{
if (Regex.Match(AssemblyVersion, @"^(\d*).(\d*).(\d*).*").Groups[1].Value == "0")
{
public static bool IsRunningDevelopmentVersion(List<string> developmentVersions, string minimumVersion)
{
if (Regex.Match(AssemblyVersion, @"^(\d*).(\d*).(\d*).*").Groups[1].Value == "0")
{
Debug.LogMessage(LogEventLevel.Verbose, "Running Local Build. Bypassing Dependency Check.");
return true;
}
}
if (developmentVersions == null)
{
Debug.LogMessage(LogEventLevel.Information,
"Development Plugin does not specify a list of versions. Loading plugin may not work as expected. Checking Minumum version");
if (developmentVersions == null)
{
Debug.LogMessage(LogEventLevel.Information,
"Development Plugin does not specify a list of versions. Loading plugin may not work as expected. Checking Minumum version");
return IsRunningMinimumVersionOrHigher(minimumVersion);
}
}
Debug.LogMessage(LogEventLevel.Verbose, "Comparing running version '{0}' to minimum versions '{1}'", AssemblyVersion, developmentVersions);
var versionMatch = developmentVersions.FirstOrDefault(x => x == AssemblyVersion);
var versionMatch = developmentVersions.FirstOrDefault(x => x == AssemblyVersion);
if (String.IsNullOrEmpty(versionMatch))
{
Debug.LogMessage(LogEventLevel.Information, "Essentials Build does not match any builds required for plugin load. Bypassing Plugin Load.");
return false;
}
if (String.IsNullOrEmpty(versionMatch))
{
Debug.LogMessage(LogEventLevel.Information, "Essentials Build does not match any builds required for plugin load. Bypassing Plugin Load.");
return false;
}
Debug.LogMessage(LogEventLevel.Verbose, "Essentials Build {0} matches list of development builds", AssemblyVersion);
return IsRunningMinimumVersionOrHigher(minimumVersion);
return IsRunningMinimumVersionOrHigher(minimumVersion);
}
}
/// <summary>
/// Checks to see if the running version meets or exceed the minimum specified version. For beta versions (0.xx.yy), will always return true.
@@ -209,10 +207,10 @@ namespace PepperDash.Essentials.Core;
if (String.IsNullOrEmpty(minimumVersion))
{
Debug.LogMessage(LogEventLevel.Information,"Plugin does not specify a minimum version. Loading plugin may not work as expected. Proceeding with loading plugin");
Debug.LogMessage(LogEventLevel.Information, "Plugin does not specify a minimum version. Loading plugin may not work as expected. Proceeding with loading plugin");
return true;
}
var runtimeVersion = Regex.Match(AssemblyVersion, @"^(\d*).(\d*).(\d*).*");
var runtimeVersionMajor = Int16.Parse(runtimeVersion.Groups[1].Value);
@@ -269,15 +267,15 @@ namespace PepperDash.Essentials.Core;
*/
}
static Global()
{
// Fire up CrestronDataStoreStatic
var err = CrestronDataStoreStatic.InitCrestronDataStore();
if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
{
CrestronConsole.PrintLine("Error starting CrestronDataStoreStatic: {0}", err);
return;
}
static Global()
{
// Fire up CrestronDataStoreStatic
var err = CrestronDataStoreStatic.InitCrestronDataStore();
if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
{
CrestronConsole.PrintLine("Error starting CrestronDataStoreStatic: {0}", err);
return;
}
try
{
@@ -290,6 +288,6 @@ namespace PepperDash.Essentials.Core;
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture;
}
}
}
}
}

View File

@@ -3,16 +3,14 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Reflection;
using Crestron.SimplSharp.CrestronIO;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
using Newtonsoft.Json;
using Serilog.Events;
namespace PepperDash.Essentials.Core;
@@ -101,16 +99,16 @@ public abstract class JoinMapBaseAdvanced
JoinOffset = joinStart - 1;
}
protected JoinMapBaseAdvanced(uint joinStart, Type type):this(joinStart)
protected JoinMapBaseAdvanced(uint joinStart, Type type) : this(joinStart)
{
AddJoins(type);
}
protected void AddJoins(Type type)
{
{
var fields =
type.GetFields(BindingFlags.Public | BindingFlags.Instance)
.Where(f => f.IsDefined(typeof (JoinNameAttribute), true)).ToList();
.Where(f => f.IsDefined(typeof(JoinNameAttribute), true)).ToList();
Debug.LogMessage(LogEventLevel.Debug, "Got {fields} with JoinNameAttribute", fields.Count);
@@ -177,16 +175,16 @@ public abstract class JoinMapBaseAdvanced
sb.Append($"## Digitals{lineEnding}");
sb.Append(lineEnding);
// Get the joins of each type and print them
var digitalSb = AppendJoinList(GetSortedJoins(digitals));
digitalSb.Append($"## Analogs{lineEnding}");
digitalSb.Append(lineEnding);
var analogSb = AppendJoinList(GetSortedJoins(analogs));
analogSb.Append($"## Serials{lineEnding}");
analogSb.Append(lineEnding);
var serialSb = AppendJoinList(GetSortedJoins(serials));
sb.EnsureCapacity(sb.Length + digitalSb.Length + analogSb.Length + serialSb.Length);
@@ -244,7 +242,7 @@ public abstract class JoinMapBaseAdvanced
const int joinSpanLen = 9;
const int typeLen = 19;
const int capabilitiesLen = 12;
var descriptionLen = (from @join in joins select @join.Value into j select j.Metadata.Description.Length).Concat(new[] {11}).Max();
var descriptionLen = (from @join in joins select @join.Value into j select j.Metadata.Description.Length).Concat(new[] { 11 }).Max();
//build header
sb.Append(string.Format(stringFormatter,
@@ -488,7 +486,7 @@ public class JoinDataComplete
/// </summary>
public uint JoinNumber
{
get { return _data.JoinNumber+ _joinOffset; }
get { return _data.JoinNumber + _joinOffset; }
set { _data.JoinNumber = value; }
}
@@ -529,7 +527,7 @@ public class JoinNameAttribute : Attribute
public JoinNameAttribute(string name)
{
Debug.LogMessage(LogEventLevel.Verbose, "Setting Attribute Name: {0}",null, name);
Debug.LogMessage(LogEventLevel.Verbose, "Setting Attribute Name: {0}", null, name);
_Name = name;
}

View File

@@ -1,13 +1,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json;
using PepperDash.Core;
//using SSMono.IO;
using PepperDash.Core.WebApi.Presets;
using Serilog.Events;
@@ -127,7 +126,7 @@ public class DevicePresetsModel : Device
PresetsAreLoaded = false;
try
{
var pl = JsonConvert.DeserializeObject<PresetsList>(File.ReadToEnd(_filePath, Encoding.ASCII));
var pl = JsonConvert.DeserializeObject<PresetsList>(File.ReadAllText(_filePath, Encoding.ASCII));
Name = pl.Name;
PresetsList = pl.Channels;
@@ -271,19 +270,20 @@ public class DevicePresetsModel : Device
try
{
_fileOps.Enter();
var pl = new PresetsList {Channels = PresetsList, Name = Name};
var pl = new PresetsList { Channels = PresetsList, Name = Name };
var json = JsonConvert.SerializeObject(pl, Formatting.Indented);
using (var file = File.Open(_filePath, FileMode.Truncate))
{
file.Write(json, Encoding.UTF8);
var bytes = Encoding.UTF8.GetBytes(json);
file.Write(bytes, 0, bytes.Length);
}
}
finally
{
_fileOps.Leave();
}
}
private void OnPresetsSaved()

View File

@@ -1,9 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
@@ -13,109 +12,109 @@ using Serilog.Events;
namespace PepperDash.Essentials.Core.Config;
/// <summary>
/// Represents the configuration data for a single tie line between two routing ports.
/// </summary>
public class TieLineConfig
{
/// <summary>
/// Represents the configuration data for a single tie line between two routing ports.
/// The key of the source device.
/// </summary>
public class TieLineConfig
public string SourceKey { get; set; }
/// <summary>
/// The key of the source card (if applicable, e.g., in a modular chassis).
/// </summary>
public string SourceCard { get; set; }
/// <summary>
/// The key of the source output port.
/// </summary>
public string SourcePort { get; set; }
/// <summary>
/// The key of the destination device.
/// </summary>
public string DestinationKey { get; set; }
/// <summary>
/// The key of the destination card (if applicable).
/// </summary>
public string DestinationCard { get; set; }
/// <summary>
/// The key of the destination input port.
/// </summary>
public string DestinationPort { get; set; }
/// <summary>
/// Optional override for the signal type of the tie line. If set, this overrides the destination port's type for routing calculations.
/// </summary>
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))]
public eRoutingSignalType? OverrideType { get; set; }
/// <summary>
/// Returns the appropriate tie line for either a card-based device or
/// regular device with ports on-device.
/// </summary>
/// <returns>null if config data does not match ports, cards or devices</returns>
public TieLine GetTieLine()
{
/// <summary>
/// The key of the source device.
/// </summary>
public string SourceKey { get; set; }
/// <summary>
/// The key of the source card (if applicable, e.g., in a modular chassis).
/// </summary>
public string SourceCard { get; set; }
/// <summary>
/// The key of the source output port.
/// </summary>
public string SourcePort { get; set; }
/// <summary>
/// The key of the destination device.
/// </summary>
public string DestinationKey { get; set; }
/// <summary>
/// The key of the destination card (if applicable).
/// </summary>
public string DestinationCard { get; set; }
/// <summary>
/// The key of the destination input port.
/// </summary>
public string DestinationPort { get; set; }
/// <summary>
/// Optional override for the signal type of the tie line. If set, this overrides the destination port's type for routing calculations.
/// </summary>
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))]
public eRoutingSignalType? OverrideType { get; set; }
/// <summary>
/// Returns the appropriate tie line for either a card-based device or
/// regular device with ports on-device.
/// </summary>
/// <returns>null if config data does not match ports, cards or devices</returns>
public TieLine GetTieLine()
Debug.LogMessage(LogEventLevel.Information, "Build TieLine: {0}", null, this);
// Get the source device
var sourceDev = DeviceManager.GetDeviceForKey(SourceKey) as IRoutingOutputs;
if (sourceDev == null)
{
Debug.LogMessage(LogEventLevel.Information, "Build TieLine: {0}",null, this);
// Get the source device
var sourceDev = DeviceManager.GetDeviceForKey(SourceKey) as IRoutingOutputs;
if (sourceDev == null)
{
LogError("Routable source not found");
return null;
}
// Get the destination device
var destDev = DeviceManager.GetDeviceForKey(DestinationKey) as IRoutingInputs;
if (destDev == null)
{
LogError("Routable destination not found");
return null;
}
//Get the source port
var sourceOutputPort = sourceDev.OutputPorts[SourcePort];
if (sourceOutputPort == null)
{
LogError("Source does not contain port");
return null;
}
//Get the Destination port
var destinationInputPort = destDev.InputPorts[DestinationPort];
if (destinationInputPort == null)
{
LogError("Destination does not contain port");
return null;
}
return new TieLine(sourceOutputPort, destinationInputPort, OverrideType);
LogError("Routable source not found");
return null;
}
/// <summary>
/// Logs an error message related to creating this tie line configuration.
/// </summary>
/// <param name="msg">The specific error message.</param>
void LogError(string msg)
// Get the destination device
var destDev = DeviceManager.GetDeviceForKey(DestinationKey) as IRoutingInputs;
if (destDev == null)
{
Debug.LogMessage(LogEventLevel.Error, "WARNING: Cannot create tie line: {message}:\r {tieLineConfig}",null, msg, this);
LogError("Routable destination not found");
return null;
}
/// <summary>
/// Returns a string representation of the tie line configuration.
/// </summary>
/// <returns>A string describing the source and destination of the configured tie line.</returns>
public override string ToString()
//Get the source port
var sourceOutputPort = sourceDev.OutputPorts[SourcePort];
if (sourceOutputPort == null)
{
return string.Format("{0}.{1}.{2} --> {3}.{4}.{5}", SourceKey, SourceCard, SourcePort,
DestinationKey, DestinationCard, DestinationPort);
LogError("Source does not contain port");
return null;
}
}
//Get the Destination port
var destinationInputPort = destDev.InputPorts[DestinationPort];
if (destinationInputPort == null)
{
LogError("Destination does not contain port");
return null;
}
return new TieLine(sourceOutputPort, destinationInputPort, OverrideType);
}
/// <summary>
/// Logs an error message related to creating this tie line configuration.
/// </summary>
/// <param name="msg">The specific error message.</param>
void LogError(string msg)
{
Debug.LogMessage(LogEventLevel.Error, "WARNING: Cannot create tie line: {message}:\r {tieLineConfig}", null, msg, this);
}
/// <summary>
/// Returns a string representation of the tie line configuration.
/// </summary>
/// <returns>A string describing the source and destination of the configured tie line.</returns>
public override string ToString()
{
return string.Format("{0}.{1}.{2} --> {3}.{4}.{5}", SourceKey, SourceCard, SourcePort,
DestinationKey, DestinationCard, DestinationPort);
}
}

View File

@@ -1,19 +1,19 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using Crestron.SimplSharpPro.UI;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.UI;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using Serilog.Events;
namespace PepperDash.Essentials.Core.UI;
public abstract class TouchpanelBase: EssentialsDevice, IHasBasicTriListWithSmartObject
public abstract class TouchpanelBase : EssentialsDevice, IHasBasicTriListWithSmartObject
{
protected CrestronTouchpanelPropertiesConfig _config;
public BasicTriListWithSmartObject Panel { get; private set; }
@@ -29,7 +29,7 @@ public abstract class TouchpanelBase: EssentialsDevice, IHasBasicTriListWithSmar
/// <param name="config">Touchpanel Configuration</param>
/// <param name="id">IP-ID to use for touch panel</param>
protected TouchpanelBase(string key, string name, BasicTriListWithSmartObject panel, CrestronTouchpanelPropertiesConfig config)
:base(key, name)
: base(key, name)
{
if (panel == null)
@@ -52,9 +52,10 @@ public abstract class TouchpanelBase: EssentialsDevice, IHasBasicTriListWithSmar
tsw.ButtonStateChange += Tsw_ButtonStateChange;
}
_config = config;
_config = config;
AddPreActivationAction(() => {
AddPreActivationAction(() =>
{
if (Panel.Register() != eDeviceRegistrationUnRegistrationResponse.Success)
Debug.LogMessage(LogEventLevel.Information, this, "WARNING: Registration failed. Continuing, but panel may not function: {0}", Panel.RegistrationFailureReason);
@@ -154,21 +155,21 @@ public abstract class TouchpanelBase: EssentialsDevice, IHasBasicTriListWithSmar
}
private void Panel_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args)
{
Debug.LogMessage(LogEventLevel.Verbose, this, "Sig change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
var uo = args.Sig.UserObject;
if (uo is Action<bool>)
(uo as Action<bool>)(args.Sig.BoolValue);
else if (uo is Action<ushort>)
(uo as Action<ushort>)(args.Sig.UShortValue);
else if (uo is Action<string>)
(uo as Action<string>)(args.Sig.StringValue);
}
private void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args)
{
var uo = args.Button.UserObject;
if(uo is Action<bool>)
(uo as Action<bool>)(args.Button.State == eButtonState.Pressed);
}
{
Debug.LogMessage(LogEventLevel.Verbose, this, "Sig change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
var uo = args.Sig.UserObject;
if (uo is Action<bool>)
(uo as Action<bool>)(args.Sig.BoolValue);
else if (uo is Action<ushort>)
(uo as Action<ushort>)(args.Sig.UShortValue);
else if (uo is Action<string>)
(uo as Action<string>)(args.Sig.StringValue);
}
private void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args)
{
var uo = args.Button.UserObject;
if (uo is Action<bool>)
(uo as Action<bool>)(args.Button.State == eButtonState.Pressed);
}
}

View File

@@ -1,11 +1,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Net.Http;
using Crestron.SimplSharp.WebScripting;
using Newtonsoft.Json;
@@ -1829,7 +1829,7 @@ public class MobileControlSystemController : EssentialsDevice, IMobileControl
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void HandleError(object sender, ErrorEventArgs e)
private void HandleError(object sender, WebSocketSharp.ErrorEventArgs e)
{
this.LogError("Websocket error {0}", e.Message);

View File

@@ -1,6 +1,9 @@
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.CrestronThread;
using Crestron.SimplSharpPro.Diagnostics;
@@ -9,19 +12,16 @@ using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Core.Web;
using System;
using System.Linq;
using Serilog.Events;
using PepperDash.Essentials.Core.Routing;
using System.Threading;
using PepperDash.Essentials.Core.Web;
using Serilog.Events;
using Timeout = Crestron.SimplSharp.Timeout;
namespace PepperDash.Essentials;
/// <summary>
/// Represents the main control system for the application, providing initialization, configuration loading, and device
/// management functionality.
/// <summary>
/// Represents the main control system for the application, providing initialization, configuration loading, and device
/// management functionality.
/// </summary>
/// <remarks>This class extends <see cref="CrestronControlSystem"/> and serves as the entry point for the control
/// system. It manages the initialization of devices, rooms, tie lines, and other system components. Additionally, it
@@ -34,9 +34,9 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
private ManualResetEventSlim _initializeEvent;
private const long StartupTime = 500;
/// <summary>
/// Initializes a new instance of the <see cref="ControlSystem"/> class, setting up the system's global state and
/// dependencies.
/// <summary>
/// Initializes a new instance of the <see cref="ControlSystem"/> class, setting up the system's global state and
/// dependencies.
/// </summary>
/// <remarks>This constructor configures the control system by initializing key components such as the
/// device manager and secrets manager, and sets global properties like the maximum number of user threads and the
@@ -45,26 +45,26 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
public ControlSystem()
: base()
{
try
{
Crestron.SimplSharpPro.CrestronThread.Thread.MaxNumberOfUserThreads = 400;
Global.ControlSystem = this;
DeviceManager.Initialize(this);
SecretsManager.Initialize();
SystemMonitor.ProgramInitialization.ProgramInitializationUnderUserControl = true;
Debug.SetErrorLogMinimumDebugLevel(CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? LogEventLevel.Warning : LogEventLevel.Verbose);
{
try
{
Crestron.SimplSharpPro.CrestronThread.Thread.MaxNumberOfUserThreads = 400;
Global.ControlSystem = this;
DeviceManager.Initialize(this);
SecretsManager.Initialize();
SystemMonitor.ProgramInitialization.ProgramInitializationUnderUserControl = true;
Debug.SetErrorLogMinimumDebugLevel(CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? LogEventLevel.Warning : LogEventLevel.Verbose);
}
catch (Exception e)
{
Debug.LogError(e, "FATAL INITIALIZE ERROR. System is in an inconsistent state");
Debug.LogError(e, "FATAL INITIALIZE ERROR. System is in an inconsistent state");
}
}
/// <summary>
/// Initializes the control system and prepares it for operation.
/// <summary>
/// Initializes the control system and prepares it for operation.
/// </summary>
/// <remarks>This method ensures that all devices in the system are properly registered and initialized
/// before the system is fully operational. If the control system is of a DMPS type, the method waits for all
@@ -78,7 +78,7 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
if (preventInitializationComplete)
{
Debug.LogMessage(LogEventLevel.Debug, "******************* Initializing System **********************");
_startTimer = new Timer(StartSystem, preventInitializationComplete, StartupTime, Timeout.Infinite);
_initializeEvent = new ManualResetEventSlim(false);
@@ -91,7 +91,7 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
_initializeEvent.Wait(30000);
Debug.LogMessage(LogEventLevel.Debug, "******************* System Initialization Complete **********************");
SystemMonitor.ProgramInitialization.ProgramInitializationComplete = true;
}
else
@@ -101,7 +101,7 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
}
private void StartSystem(object preventInitialization)
{
{
DeterminePlatform();
// Print .NET runtime version
@@ -154,7 +154,7 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
CrestronConsole.AddNewConsoleCommand(DeviceManager.GetRoutingPorts,
"getroutingports", "Reports all routing ports, if any. Requires a device key", ConsoleAccessLevelEnum.AccessOperator);
if (!Debug.DoNotLoadConfigOnNextBoot)
{
@@ -183,16 +183,16 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
var dirSeparator = Global.DirectorySeparator;
string directoryPrefix;
string directoryPrefix;
directoryPrefix = Directory.GetApplicationRootDirectory();
directoryPrefix = Directory.GetCurrentDirectory();
Global.SetAssemblyVersion(PluginLoader.GetAssemblyVersion(Assembly.GetExecutingAssembly()));
if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server) // Handles 3-series running Windows CE OS
{
string userFolder = "user";
string nvramFolder = "nvram";
string nvramFolder = "nvram";
Debug.LogMessage(LogEventLevel.Information, "Starting Essentials v{version:l} on {processorSeries:l} Appliance", Global.AssemblyVersion, "4-series");
//Debug.LogMessage(LogEventLevel.Information, "Starting Essentials v{0} on {1} Appliance", Global.AssemblyVersion, is4series ? "4-series" : "3-series");
@@ -201,8 +201,8 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
if (Directory.Exists(Global.ApplicationDirectoryPathPrefix + dirSeparator + userFolder
+ dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber)))
{
Debug.LogMessage(LogEventLevel.Information, "{userFolder:l}/program{applicationNumber} directory found", userFolder, InitialParametersClass.ApplicationNumber);
Debug.LogMessage(LogEventLevel.Information, "{userFolder:l}/program{applicationNumber} directory found", userFolder, InitialParametersClass.ApplicationNumber);
filePathPrefix = directoryPrefix + dirSeparator + userFolder
+ dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator;
}
@@ -211,7 +211,7 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
+ dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber)))
{
Debug.LogMessage(LogEventLevel.Information, "{nvramFolder:l}/program{applicationNumber} directory found", nvramFolder, InitialParametersClass.ApplicationNumber);
filePathPrefix = directoryPrefix + dirSeparator + nvramFolder
+ dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator;
}
@@ -219,7 +219,7 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
else
{
Debug.LogMessage(LogEventLevel.Information, "{userFolder:l}/program{applicationNumber} directory found", userFolder, InitialParametersClass.ApplicationNumber);
filePathPrefix = directoryPrefix + dirSeparator + userFolder
+ dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator;
}
@@ -227,7 +227,7 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
else // Handles Linux OS (Virtual Control)
{
//Debug.SetDebugLevel(2);
Debug.LogMessage(LogEventLevel.Information, "Starting Essentials v{version:l} on Virtual Control Server", Global.AssemblyVersion);
Debug.LogMessage(LogEventLevel.Information, "Starting Essentials v{version:l} on Virtual Control Server", Global.AssemblyVersion);
// Set path to User/
filePathPrefix = directoryPrefix + dirSeparator + "User" + dirSeparator;
@@ -237,7 +237,7 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
}
catch (Exception e)
{
Debug.LogMessage(e, "Unable to determine platform due to exception");
Debug.LogMessage(e, "Unable to determine platform due to exception");
}
}
@@ -252,7 +252,7 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
PluginLoader.AddProgramAssemblies();
_ = new Core.DeviceFactory();
_ = new Core.DeviceFactory();
Debug.LogMessage(LogEventLevel.Information, "Starting Essentials load from configuration");
@@ -299,7 +299,7 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
}
/// <summary>
/// Verifies filesystem is set up. IR, SGD, and programX folders
@@ -312,54 +312,54 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
Debug.LogMessage(LogEventLevel.Information, "FilePathPrefix: {filePathPrefix:l}", configDir);
var configExists = Directory.Exists(configDir);
if (!configExists)
Directory.Create(configDir);
Directory.CreateDirectory(configDir);
var irDir = Global.FilePathPrefix + "ir";
if (!Directory.Exists(irDir))
Directory.Create(irDir);
Directory.CreateDirectory(irDir);
var sgdDir = Global.FilePathPrefix + "sgd";
if (!Directory.Exists(sgdDir))
Directory.Create(sgdDir);
if (!Directory.Exists(sgdDir))
Directory.CreateDirectory(sgdDir);
var pluginDir = Global.FilePathPrefix + "plugins";
if (!Directory.Exists(pluginDir))
Directory.Create(pluginDir);
Directory.CreateDirectory(pluginDir);
var joinmapDir = Global.FilePathPrefix + "joinmaps";
if(!Directory.Exists(joinmapDir))
Directory.Create(joinmapDir);
if (!Directory.Exists(joinmapDir))
Directory.CreateDirectory(joinmapDir);
return configExists;
}
return configExists;
}
/// <summary>
///
/// </summary>
public void TearDown()
{
Debug.LogMessage(LogEventLevel.Information, "Tearing down existing system");
DeviceManager.DeactivateAll();
/// <summary>
///
/// </summary>
public void TearDown()
{
Debug.LogMessage(LogEventLevel.Information, "Tearing down existing system");
DeviceManager.DeactivateAll();
TieLineCollection.Default.Clear();
TieLineCollection.Default.Clear();
foreach (var key in DeviceManager.GetDevices())
DeviceManager.RemoveDevice(key);
foreach (var key in DeviceManager.GetDevices())
DeviceManager.RemoveDevice(key);
Debug.LogMessage(LogEventLevel.Information, "Tear down COMPLETE");
}
Debug.LogMessage(LogEventLevel.Information, "Tear down COMPLETE");
}
/// <summary>
///
/// </summary>
/// <summary>
///
/// </summary>
void Load()
{
LoadDevices();
LoadRooms();
LoadLogoServer();
void Load()
{
LoadDevices();
LoadRooms();
LoadLogoServer();
DeviceManager.ActivateAll();
DeviceManager.ActivateAll();
LoadTieLines();
@@ -368,8 +368,8 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
if (mobileControl == null) return;
mobileControl.LinkSystemMonitorToAppServer();*/
}
}
/// <summary>
/// Reads all devices from config and adds them to DeviceManager
@@ -417,14 +417,14 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
if (newDev == null)
newDev = Core.DeviceFactory.GetDevice(devConf);
if (newDev != null)
DeviceManager.AddDevice(newDev);
else
if (newDev != null)
DeviceManager.AddDevice(newDev);
else
Debug.LogMessage(LogEventLevel.Information, "ERROR: Cannot load unknown device type '{deviceType:l}', key '{deviceKey:l}'.", devConf.Type, devConf.Key);
}
catch (Exception e)
{
Debug.LogMessage(e, "ERROR: Creating device {deviceKey:l}. Skipping device.",args: new[] { devConf.Key });
Debug.LogMessage(e, "ERROR: Creating device {deviceKey:l}. Skipping device.", args: new[] { devConf.Key });
}
}
Debug.LogMessage(LogEventLevel.Information, "All Devices Loaded.");
@@ -462,27 +462,28 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
/// Reads all rooms from config and adds them to DeviceManager
/// </summary>
public void LoadRooms()
{
{
if (ConfigReader.ConfigObject.Rooms == null)
{
Debug.LogMessage(LogEventLevel.Information, "Notice: Configuration contains no rooms - Is this intentional? This may be a valid configuration.");
return;
}
foreach (var roomConfig in ConfigReader.ConfigObject.Rooms)
foreach (var roomConfig in ConfigReader.ConfigObject.Rooms)
{
try
{
var room = Core.DeviceFactory.GetDevice(roomConfig);
if(room == null)
if (room == null)
{
Debug.LogWarning("ERROR: Cannot load unknown room type '{roomType:l}', key '{roomKey:l}'.", roomConfig.Type, roomConfig.Key);
continue;
}
DeviceManager.AddDevice(room);
} catch (Exception ex)
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Exception loading room {roomKey}:{roomType}", null, roomConfig.Key, roomConfig.Type);
continue;
@@ -551,7 +552,7 @@ public class ControlSystem : CrestronControlSystem, ILoadConfig
}
catch
{
Debug.LogMessage(LogEventLevel.Information, "Unable to find logo information in any room config");
Debug.LogMessage(LogEventLevel.Information, "Unable to find logo information in any room config");
return false;
}
}

View File

@@ -2,12 +2,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro;
using System.Reflection;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
@@ -40,7 +39,7 @@ public class DeviceFactory
}
catch (Exception e)
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Error, "Unable to load type: '{exception}' DeviceFactory: {factoryName}", e, type.Name);
Debug.LogMessage(Serilog.Events.LogEventLevel.Error, "Unable to load type: '{exception}' DeviceFactory: {factoryName}", e, type.Name);
}
}
}

View File

@@ -1,9 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Net.Http;
using PepperDash.Core;
using Serilog.Events;
@@ -34,21 +33,21 @@ public class HttpLogoServer
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" },
{ ".jpeg", "image/jpeg" },
//{ ".js", "application/javascript" },
//{ ".json", "application/json" },
//{ ".map", "application/x-navimap" },
{ ".pdf", "application/pdf" },
{ ".png", "image/png" },
{ ".png", "image/png" },
//{ ".txt", "text/plain" },
};
_server = new HttpServer {Port = port};
_server = new HttpServer { Port = port };
_fileDirectory = directory;
_server.OnHttpRequest += Server_OnHttpRequest;
_server.Open();
@@ -62,7 +61,7 @@ public class HttpLogoServer
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);
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "HTTP Request with path: '{requestPath:l}'", args.Request.Path);
try
{
@@ -75,7 +74,9 @@ public class HttpLogoServer
if (File.Exists(localPath))
{
args.Response.Header.ContentType = GetContentType(new FileInfo(localPath).Extension);
args.Response.ContentStream = new FileStream(localPath, FileMode.Open, FileAccess.Read);
// For .NET 8 migration, read file content as bytes since ContentStream expects Crestron.SimplSharp.CrestronIO.Stream
var fileBytes = File.ReadAllBytes(localPath);
args.Response.ContentBytes = fileBytes;
}
else
{