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;
using System.IO;
using System.Linq; using System.Linq;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using PepperDash.Core; using PepperDash.Core;
@@ -12,223 +12,223 @@ namespace PepperDash.Core.Config;
/// <summary> /// <summary>
/// Reads a Portal formatted config file /// Reads a Portal formatted config file
/// </summary> /// </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> try
/// 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 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, // it's a double-config, merge it.
"ERROR: Configuration file not present. Please load file to {0} and reset program", filePath); 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()); fw.Write(jsonObj.ToString(Formatting.Indented));
if(jsonObj["template"] != null && jsonObj["system"] != null) Debug.LogMessage(LogEventLevel.Debug, "JSON config merged and saved to {0}", savePath);
{
// 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);
}
} }
}
catch (Exception e)
{
Debug.LogMessage(e, "ERROR: Config load failed");
} }
} }
catch (Exception e)
/// <summary>
///
/// </summary>
/// <param name="doubleConfig"></param>
/// <returns></returns>
public static JObject MergeConfigs(JObject doubleConfig)
{ {
var system = JObject.FromObject(doubleConfig["system"]); Debug.LogMessage(e, "ERROR: Config load failed");
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> /// <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 /// </summary>
/// a matched item in base array will not be merged. Non keyed system items will replace the template items. /// <param name="doubleConfig"></param>
/// </summary> /// <returns></returns>
static JArray MergeArraysOnTopLevelProperty(JArray a1, JArray a2, string propertyName, string path) 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[0]["key"] == null) // If the first item in the system array has no key, overwrite the template array
if (a2 == null || a2.Count == 0) // If the system array is null or empty, return the template array { // with the system array
return a1; return a2;
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);
}
}
} }
return result; else // The arrays are keyed, merge them by key
}
/// <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; for (int i = 0; i < a1.Count(); i++)
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); var a1Dev = a1[i];
} // Try to get a system device and if found, merge it onto template
// otherwise merge them var a2Match = a2.FirstOrDefault(t => t[propertyName].Equals(a1Dev[propertyName]));// t.Value<int>("uid") == tmplDev.Value<int>("uid"));
else if (a2Match != null)
{
// Drill down
var propPath = String.Format("{0}.{1}", path, propKey);
try
{ {
var mergedItem = Merge(a1Dev, a2Match, string.Format("{0}[{1}].", path, i));// Merge(JObject.FromObject(a1Dev), JObject.FromObject(a2Match));
if (o1Value is JArray) result.Add(mergedItem);
{
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);
} }
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.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using static Crestron.SimplSharp.Net.Http; using Crestron.SimplSharp.Net.Http;
using static Crestron.SimplSharp.Net.Https; using Crestron.SimplSharp.Net.Https;
namespace PepperDash.Core.GenericRESTfulCommunications; namespace PepperDash.Core.GenericRESTfulCommunications;

View File

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

View File

@@ -1,8 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using PepperDash.Core.Config; using PepperDash.Core.Config;
@@ -13,178 +13,178 @@ namespace PepperDash.Core.JsonToSimpl;
/// </summary> /// </summary>
public class JsonToSimplPortalFileMaster : JsonToSimplMaster public class JsonToSimplPortalFileMaster : JsonToSimplMaster
{ {
/// <summary> /// <summary>
/// Sets the filepath as well as registers this with the Global.Masters list /// Sets the filepath as well as registers this with the Global.Masters list
/// </summary> /// </summary>
public string PortalFilepath { get; private set; } public string PortalFilepath { get; private set; }
/// <summary> /// <summary>
/// File path of the actual file being read (Portal or local) /// File path of the actual file being read (Portal or local)
/// </summary> /// </summary>
public string ActualFilePath { get; private set; } public string ActualFilePath { get; private set; }
/*****************************************************************************************/ /*****************************************************************************************/
/** Privates **/ /** Privates **/
// To prevent multiple same-file access // To prevent multiple same-file access
object StringBuilderLock = new object(); object StringBuilderLock = new object();
static object FileLock = new object(); static object FileLock = new object();
/*****************************************************************************************/ /*****************************************************************************************/
/// <summary> /// <summary>
/// SIMPL+ default constructor. /// SIMPL+ default constructor.
/// </summary> /// </summary>
public JsonToSimplPortalFileMaster() 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> // Resolve possible wildcarded filename
/// Read, evaluate and udpate status
/// </summary> // If the portal file is xyz.json, then
public void EvaluateFile(string portalFilepath) // 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; ActualFilePath = actualLocalFile.FullName;
OnStringChange(ActualFilePath, 0, JsonToSimplConstants.ActualFilePathChange);
OnBoolChange(false, 0, JsonToSimplConstants.JsonIsValidBoolChange); }
if (string.IsNullOrEmpty(PortalFilepath)) // 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"); var newLocalPath = Path.ChangeExtension(actualPortalFile.FullName, "local.json");
return; // 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 else
{ {
Debug.Console(1, this, "Local JSON file not found {0}\rLoading portal JSON file", localFilepath); var msg = string.Format("Portal JSON file not found: {0}", PortalFilepath);
var actualPortalFile = GetActualFileInfoFromPath(portalFilepath); Debug.Console(1, this, msg);
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);
ErrorLog.Error(msg); ErrorLog.Error(msg);
return; return;
} }
} }
/// <summary> // At this point we should have a local file. Do it.
/// Returns the FileInfo object for a given path, with possible wildcards Debug.Console(1, "Reading local JSON file {0}", ActualFilePath);
/// </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> string json = File.ReadAllText(ActualFilePath, System.Text.Encoding.ASCII);
///
/// </summary>
/// <param name="level"></param>
public void setDebugLevel(uint level)
{
Debug.SetDebugLevel(level);
}
/// <summary> try
///
/// </summary>
public override void Save()
{ {
// this code is duplicated in the other masters!!!!!!!!!!!!! JsonObject = JObject.Parse(json);
UnsavedValues = new Dictionary<string, JValue>();
// Make each child update their values into master object
foreach (var child in Children) foreach (var child in Children)
{ child.ProcessAll();
Debug.Console(1, "Master [{0}] checking child [{1}] for updates to save", UniqueID, child.Key); OnBoolChange(true, 0, JsonToSimplConstants.JsonIsValidBoolChange);
child.UpdateInputsForMaster(); }
} 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); var tokenToReplace = JsonObject.SelectToken(path);
return; if (tokenToReplace != null)
} {// It's found
lock (FileLock) tokenToReplace.Replace(UnsavedValues[path]);
{ Debug.Console(1, "JSON Master[{0}] Updating '{1}'", UniqueID, path);
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);
}
} }
using (StreamWriter sw = new StreamWriter(ActualFilePath)) else // No token. Let's make one
{ {
try //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);
sw.Write(JsonObject.ToString());
sw.Flush(); }
} }
catch (Exception e) using (StreamWriter sw = new StreamWriter(ActualFilePath))
{ {
string err = string.Format("Error writing JSON file:\r{0}", e); try
Debug.Console(0, err); {
ErrorLog.Warn(err); sw.Write(JsonObject.ToString());
return; 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Reflection; using System.Reflection;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronDataStore; using Crestron.SimplSharp.CrestronDataStore;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.CrestronLogger; using Crestron.SimplSharp.CrestronLogger;
using Newtonsoft.Json; using Newtonsoft.Json;
using PepperDash.Core.Logging; using PepperDash.Core.Logging;
@@ -142,8 +142,8 @@ public static class Debug
_websocketSink = new DebugWebsocketSink(new JsonFormatter(renderMessage: true)); _websocketSink = new DebugWebsocketSink(new JsonFormatter(renderMessage: true));
var logFilePath = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? 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.GetCurrentDirectory()}{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}room{InitialParametersClass.RoomId}{Path.DirectorySeparatorChar}global-log.log";
CrestronConsole.PrintLine($"Saving log files to {logFilePath}"); 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(@"\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> /// <summary>

View File

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

View File

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

View File

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

View File

@@ -4,22 +4,22 @@ using Crestron.SimplSharp.WebScripting;
namespace PepperDash.Core.Web.RequestHandlers; 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> /// <summary>
/// CWS Base Handler, implements IHttpCwsHandler /// Constructor
/// </summary> /// </summary>
public abstract class WebApiBaseRequestHandler : IHttpCwsHandler protected WebApiBaseRequestHandler(bool enableCors)
{ {
private readonly Dictionary<string, Action<HttpCwsContext>> _handlers; EnableCors = enableCors;
protected readonly bool EnableCors;
/// <summary> _handlers = new Dictionary<string, Action<HttpCwsContext>>
/// Constructor
/// </summary>
protected WebApiBaseRequestHandler(bool enableCors)
{
EnableCors = enableCors;
_handlers = new Dictionary<string, Action<HttpCwsContext>>
{ {
{"CONNECT", HandleConnect}, {"CONNECT", HandleConnect},
{"DELETE", HandleDelete}, {"DELETE", HandleDelete},
@@ -31,134 +31,134 @@ namespace PepperDash.Core.Web.RequestHandlers;
{"PUT", HandlePut}, {"PUT", HandlePut},
{"TRACE", HandleTrace} {"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> if (EnableCors)
/// Constructor
/// </summary>
protected WebApiBaseRequestHandler()
: this(false)
{ {
} context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
context.Response.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
/// <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> handler(context);
/// 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);
}
}

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Crestron.SimplSharp.CrestronIO; using System.IO;
using PepperDash.Core.Intersystem.Serialization; using PepperDash.Core.Intersystem.Serialization;
using PepperDash.Core.Intersystem.Tokens; 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 if (ch == -1) // Reached end of stream without end of data marker
return null; return null;
chars[n++] = (char)ch; chars[n++] = (char)ch;
} }

View File

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

View File

@@ -2,10 +2,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro; using Crestron.SimplSharpPro;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using PepperDash.Core; using PepperDash.Core;
@@ -14,230 +13,230 @@ using Serilog.Events;
namespace PepperDash.Essentials.Core; namespace PepperDash.Essentials.Core;
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public static class IRPortHelper 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> /// <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> /// </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")] var control = propsToken["control"];
public IROutputPort Port { get; set; } if (control == null)
return null;
[JsonProperty("fileName")] if (control["method"].Value<string>() != "ir")
public string FileName { get; set; }
[JsonProperty("useBridgeJoinMap")]
public bool UseBridgeJoinMap { get; set; }
public IrOutPortConfig()
{ {
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;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro; using Crestron.SimplSharpPro;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using PepperDash.Core; using PepperDash.Core;
@@ -47,7 +46,7 @@ public class DeviceConfig
//Properties = JToken.FromObject(dc.Properties); //Properties = JToken.FromObject(dc.Properties);
} }
public DeviceConfig() {} public DeviceConfig() { }
} }
/// <summary> /// <summary>

View File

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

View File

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

View File

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

View File

@@ -2,88 +2,88 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json; using Newtonsoft.Json;
using PepperDash.Core; using PepperDash.Core;
namespace PepperDash.Essentials.Core.Config; namespace PepperDash.Essentials.Core.Config;
/// <summary> /// <summary>
/// Loads the ConfigObject from the file /// Loads the ConfigObject from the file
/// </summary> /// </summary>
public class EssentialsConfig : BasicConfig 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")] get
public string SystemUrl { get; set; } {
if (string.IsNullOrEmpty(SystemUrl))
return "missing url";
[JsonProperty("template_url")] if (SystemUrl.Contains("#"))
public string TemplateUrl { get; set; } {
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/#.*");
string uuid = result.Groups[1].Value;
[JsonProperty("systemUuid")] return uuid;
public string SystemUuid }
{ else
get {
{ var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/.*");
if (string.IsNullOrEmpty(SystemUrl)) string uuid = result.Groups[1].Value;
return "missing url"; return uuid;
}
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>();
}
} }
/// <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;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using PepperDash.Core;
using Crestron.SimplSharpPro.CrestronThread; using Crestron.SimplSharpPro.CrestronThread;
using PepperDash.Core;
using Serilog.Events; using Serilog.Events;
namespace PepperDash.Essentials.Core; 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)
{ {
string fullFilePath = Global.FilePathPrefix + fileName;
static CCriticalSection fileLock = new CCriticalSection(); DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(fullFilePath));
public delegate void GotFileEventHandler(object sender, FileEventArgs e); var files = dirInfo.GetFiles(Path.GetFileName(fullFilePath));
public static event GotFileEventHandler GotFileEvent; Debug.LogMessage(LogEventLevel.Information, "FileIO found: {0}, {1}", files.Count(), fullFilePath);
if (files.Count() > 0)
/// <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)
{ {
try return files;
{
return ReadDataFromFile(GetFile(fileName));
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Information, "Error: FileIO read failed: \r{0}", e);
return "";
}
} }
else
/// <summary>
/// Get the data with fileInfo object
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public static string ReadDataFromFile(FileInfo file)
{ {
try return null;
{ }
if (fileLock.TryEnter()) }
{
DirectoryInfo dirInfo = new DirectoryInfo(file.DirectoryName);
Debug.LogMessage(LogEventLevel.Verbose, "FileIO Getting Data {0}", file.FullName);
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();
{
return r.ReadToEnd();
}
}
else
{
Debug.LogMessage(LogEventLevel.Verbose, "File {0} does not exsist", file.FullName);
return "";
} }
} }
else else
{ {
Debug.LogMessage(LogEventLevel.Information, "FileIO Unable to enter FileLock"); Debug.LogMessage(LogEventLevel.Verbose, "File {0} does not exsist", file.FullName);
return ""; 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 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;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.CrestronXml; using Crestron.SimplSharp.CrestronXml;
using Crestron.SimplSharp.CrestronXml.Serialization; using Crestron.SimplSharp.CrestronXml.Serialization;
using Crestron.SimplSharpPro; using Crestron.SimplSharpPro;
@@ -11,10 +15,6 @@ using PepperDash.Core;
using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.DeviceTypeInterfaces; using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using Serilog.Events; using Serilog.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PepperDash.Essentials.Core.Fusion; namespace PepperDash.Essentials.Core.Fusion;
@@ -107,7 +107,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
JoinMap.SetCustomJoinData(customJoins); JoinMap.SetCustomJoinData(customJoins);
} }
} }
Room = room; Room = room;
_ipId = ipId; _ipId = ipId;
@@ -137,7 +137,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
File.Delete(oldGuidFilePath); File.Delete(oldGuidFilePath);
} }
_guidFileExists = File.Exists(guidFilePath); _guidFileExists = File.Exists(guidFilePath);
// Check if file exists // Check if file exists
if (!_guidFileExists) if (!_guidFileExists)
@@ -301,7 +301,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
if (File.Exists(filePath)) if (File.Exists(filePath))
{ {
var json = File.ReadToEnd(filePath, Encoding.ASCII); var json = File.ReadAllText(filePath, Encoding.ASCII);
_guiDs = JsonConvert.DeserializeObject<FusionRoomGuids>(json); _guiDs = JsonConvert.DeserializeObject<FusionRoomGuids>(json);
@@ -466,7 +466,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
// Interface 1 // Interface 1
if (InitialParametersClass.NumberOfEthernetInterfaces > 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 = _ip2.InputSig.StringValue =
CrestronEthernetHelper.GetEthernetParameter( CrestronEthernetHelper.GetEthernetParameter(
@@ -490,7 +490,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
{ {
var join = JoinMap.ProgramNameStart.JoinNumber + i; var join = JoinMap.ProgramNameStart.JoinNumber + i;
var progNum = i + 1; 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); string.Format("{0} {1}", JoinMap.ProgramNameStart.AttributeName, progNum), eSigIoMask.InputSigOnly);
} }
} }
@@ -519,7 +519,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
{ {
if (args.DeviceOnLine) if (args.DeviceOnLine)
{ {
CrestronInvoke.BeginInvoke( (o) => CrestronInvoke.BeginInvoke((o) =>
{ {
CrestronEnvironment.Sleep(200); CrestronEnvironment.Sleep(200);
@@ -658,7 +658,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
var extendTime = _currentMeeting.dtEnd - DateTime.Now; var extendTime = _currentMeeting.dtEnd - DateTime.Now;
var extendMinutesRaw = extendTime.TotalMinutes; 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"]; var parameters = actionResponse["Parameters"];
foreach (var isRegistered in from XmlElement parameter in parameters foreach (var isRegistered in from XmlElement parameter in parameters
where parameter.HasAttributes where parameter.HasAttributes
select parameter.Attributes select parameter.Attributes
into attributes into attributes
where attributes["ID"].Value == "Registered" where attributes["ID"].Value == "Registered"
select Int32.Parse(attributes["Value"].Value)) select Int32.Parse(attributes["Value"].Value))
{ {
switch (isRegistered) switch (isRegistered)
{ {
@@ -827,9 +827,9 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
Debug.LogMessage(LogEventLevel.Debug, this, "DateTime from Fusion Server: {0}", currentTime); Debug.LogMessage(LogEventLevel.Debug, this, "DateTime from Fusion Server: {0}", currentTime);
// Parse time and date from response and insert values // Parse time and date from response and insert values
CrestronEnvironment.SetTimeAndDate((ushort) currentTime.Hour, (ushort) currentTime.Minute, CrestronEnvironment.SetTimeAndDate((ushort)currentTime.Hour, (ushort)currentTime.Minute,
(ushort) currentTime.Second, (ushort) currentTime.Month, (ushort) currentTime.Day, (ushort)currentTime.Second, (ushort)currentTime.Month, (ushort)currentTime.Day,
(ushort) currentTime.Year); (ushort)currentTime.Year);
Debug.LogMessage(LogEventLevel.Debug, this, "Processor time set to {0}", CrestronEnvironment.GetLocalTime()); 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>()) 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; usageDevice.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
} }
} }
@@ -1279,7 +1279,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
foreach (var display in displays.Cast<IDisplay>()) 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; display.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
} }
@@ -1392,7 +1392,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
// Power on // Power on
var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint) joinOffset, displayName + "Power On", var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On",
eSigIoMask.InputOutputSig); eSigIoMask.InputOutputSig);
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b => defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b =>
{ {
@@ -1403,7 +1403,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
}); });
// Power Off // Power Off
var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint) joinOffset + 1, displayName + "Power Off", var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off",
eSigIoMask.InputOutputSig); eSigIoMask.InputOutputSig);
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b => defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b =>
{ {
@@ -1421,7 +1421,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
} }
// Current Source // Current Source
var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint) joinOffset + 8, var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8,
displayName + "Source None", eSigIoMask.InputOutputSig); displayName + "Source None", eSigIoMask.InputOutputSig);
defaultDisplaySourceNone.OutputSig.UserObject = new Action<bool>(b => defaultDisplaySourceNone.OutputSig.UserObject = new Action<bool>(b =>
{ {
@@ -1514,7 +1514,7 @@ public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupanc
occRoom.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange; occRoom.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
} }
RoomOccupancyRemoteStringFeedback = new StringFeedback(() => _roomOccupancyRemoteString); RoomOccupancyRemoteStringFeedback = new StringFeedback(() => _roomOccupancyRemoteString);
RoomOccupancyRemoteStringFeedback.LinkInputSig(occSensorAsset.RoomOccupancyInfo.InputSig); RoomOccupancyRemoteStringFeedback.LinkInputSig(occSensorAsset.RoomOccupancyInfo.InputSig);
//} //}

View File

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

View File

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

View File

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

View File

@@ -1,9 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro; using Crestron.SimplSharpPro;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
@@ -13,109 +12,109 @@ using Serilog.Events;
namespace PepperDash.Essentials.Core.Config; namespace PepperDash.Essentials.Core.Config;
/// <summary>
/// Represents the configuration data for a single tie line between two routing ports.
/// </summary>
public class TieLineConfig
{
/// <summary> /// <summary>
/// Represents the configuration data for a single tie line between two routing ports. /// The key of the source device.
/// </summary> /// </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> Debug.LogMessage(LogEventLevel.Information, "Build TieLine: {0}", null, this);
/// The key of the source device. // Get the source device
/// </summary> var sourceDev = DeviceManager.GetDeviceForKey(SourceKey) as IRoutingOutputs;
public string SourceKey { get; set; } if (sourceDev == null)
/// <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); LogError("Routable source not found");
// Get the source device return null;
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);
} }
/// <summary> // Get the destination device
/// Logs an error message related to creating this tie line configuration. var destDev = DeviceManager.GetDeviceForKey(DestinationKey) as IRoutingInputs;
/// </summary> if (destDev == null)
/// <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); LogError("Routable destination not found");
return null;
} }
/// <summary> //Get the source port
/// Returns a string representation of the tie line configuration. var sourceOutputPort = sourceDev.OutputPorts[SourcePort];
/// </summary>
/// <returns>A string describing the source and destination of the configured tie line.</returns> if (sourceOutputPort == null)
public override string ToString()
{ {
return string.Format("{0}.{1}.{2} --> {3}.{4}.{5}", SourceKey, SourceCard, SourcePort, LogError("Source does not contain port");
DestinationKey, DestinationCard, DestinationPort); 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; 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;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.UI;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using Serilog.Events; using Serilog.Events;
namespace PepperDash.Essentials.Core.UI; namespace PepperDash.Essentials.Core.UI;
public abstract class TouchpanelBase: EssentialsDevice, IHasBasicTriListWithSmartObject public abstract class TouchpanelBase : EssentialsDevice, IHasBasicTriListWithSmartObject
{ {
protected CrestronTouchpanelPropertiesConfig _config; protected CrestronTouchpanelPropertiesConfig _config;
public BasicTriListWithSmartObject Panel { get; private set; } public BasicTriListWithSmartObject Panel { get; private set; }
@@ -29,7 +29,7 @@ public abstract class TouchpanelBase: EssentialsDevice, IHasBasicTriListWithSmar
/// <param name="config">Touchpanel Configuration</param> /// <param name="config">Touchpanel Configuration</param>
/// <param name="id">IP-ID to use for touch panel</param> /// <param name="id">IP-ID to use for touch panel</param>
protected TouchpanelBase(string key, string name, BasicTriListWithSmartObject panel, CrestronTouchpanelPropertiesConfig config) protected TouchpanelBase(string key, string name, BasicTriListWithSmartObject panel, CrestronTouchpanelPropertiesConfig config)
:base(key, name) : base(key, name)
{ {
if (panel == null) if (panel == null)
@@ -52,9 +52,10 @@ public abstract class TouchpanelBase: EssentialsDevice, IHasBasicTriListWithSmar
tsw.ButtonStateChange += Tsw_ButtonStateChange; tsw.ButtonStateChange += Tsw_ButtonStateChange;
} }
_config = config; _config = config;
AddPreActivationAction(() => { AddPreActivationAction(() =>
{
if (Panel.Register() != eDeviceRegistrationUnRegistrationResponse.Success) if (Panel.Register() != eDeviceRegistrationUnRegistrationResponse.Success)
Debug.LogMessage(LogEventLevel.Information, this, "WARNING: Registration failed. Continuing, but panel may not function: {0}", Panel.RegistrationFailureReason); 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) 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); Debug.LogMessage(LogEventLevel.Verbose, this, "Sig change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
var uo = args.Sig.UserObject; var uo = args.Sig.UserObject;
if (uo is Action<bool>) if (uo is Action<bool>)
(uo as Action<bool>)(args.Sig.BoolValue); (uo as Action<bool>)(args.Sig.BoolValue);
else if (uo is Action<ushort>) else if (uo is Action<ushort>)
(uo as Action<ushort>)(args.Sig.UShortValue); (uo as Action<ushort>)(args.Sig.UShortValue);
else if (uo is Action<string>) else if (uo is Action<string>)
(uo as Action<string>)(args.Sig.StringValue); (uo as Action<string>)(args.Sig.StringValue);
} }
private void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args) private void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args)
{ {
var uo = args.Button.UserObject; var uo = args.Button.UserObject;
if(uo is Action<bool>) if (uo is Action<bool>)
(uo as Action<bool>)(args.Button.State == eButtonState.Pressed); (uo as Action<bool>)(args.Button.State == eButtonState.Pressed);
} }
} }

View File

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

View File

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

View File

@@ -2,12 +2,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro;
using System.Reflection; using System.Reflection;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using PepperDash.Core; using PepperDash.Core;
@@ -40,7 +39,7 @@ public class DeviceFactory
} }
catch (Exception e) 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Net.Http; using Crestron.SimplSharp.Net.Http;
using PepperDash.Core; using PepperDash.Core;
using Serilog.Events; using Serilog.Events;
@@ -34,21 +33,21 @@ public class HttpLogoServer
public HttpLogoServer(int port, string directory) public HttpLogoServer(int port, string directory)
{ {
ExtensionContentTypes = new Dictionary<string, string> ExtensionContentTypes = new Dictionary<string, string>
{ {
//{ ".css", "text/css" }, //{ ".css", "text/css" },
//{ ".htm", "text/html" }, //{ ".htm", "text/html" },
//{ ".html", "text/html" }, //{ ".html", "text/html" },
{ ".jpg", "image/jpeg" }, { ".jpg", "image/jpeg" },
{ ".jpeg", "image/jpeg" }, { ".jpeg", "image/jpeg" },
//{ ".js", "application/javascript" }, //{ ".js", "application/javascript" },
//{ ".json", "application/json" }, //{ ".json", "application/json" },
//{ ".map", "application/x-navimap" }, //{ ".map", "application/x-navimap" },
{ ".pdf", "application/pdf" }, { ".pdf", "application/pdf" },
{ ".png", "image/png" }, { ".png", "image/png" },
//{ ".txt", "text/plain" }, //{ ".txt", "text/plain" },
}; };
_server = new HttpServer {Port = port}; _server = new HttpServer { Port = port };
_fileDirectory = directory; _fileDirectory = directory;
_server.OnHttpRequest += Server_OnHttpRequest; _server.OnHttpRequest += Server_OnHttpRequest;
_server.Open(); _server.Open();
@@ -62,7 +61,7 @@ public class HttpLogoServer
void Server_OnHttpRequest(object sender, OnHttpRequestArgs args) void Server_OnHttpRequest(object sender, OnHttpRequestArgs args)
{ {
var path = args.Request.Path; 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 try
{ {
@@ -75,7 +74,9 @@ public class HttpLogoServer
if (File.Exists(localPath)) if (File.Exists(localPath))
{ {
args.Response.Header.ContentType = GetContentType(new FileInfo(localPath).Extension); 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 else
{ {