Merge pull request #1344 from PepperDash/feature/allow-config-tool-v2-structure

Feature/allow config tool v2 structure
This commit is contained in:
cdenig
2025-10-23 10:15:03 -04:00
committed by GitHub
3 changed files with 164 additions and 67 deletions

View File

@@ -9,40 +9,59 @@ using Serilog.Events;
namespace PepperDash.Core.Config 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> const string template = "template";
/// Reads the config file, checks if it needs a merge, merges and saves, then returns the merged Object. const string system = "system";
/// </summary> const string systemUrl = "system_url";
/// <returns>JObject of config file</returns> const string templateUrl = "template_url";
public static void ReadAndMergeFileIfNecessary(string filePath, string savePath) const string info = "info";
const string devices = "devices";
const string rooms = "rooms";
const string sourceLists = "sourceLists";
const string destinationLists = "destinationLists";
const string cameraLists = "cameraLists";
const string audioControlPointLists = "audioControlPointLists";
const string tieLines = "tieLines";
const string joinMaps = "joinMaps";
const string global = "global";
/// <summary>
/// Reads the config file, checks if it needs a merge, merges and saves, then returns the merged Object.
/// </summary>
/// <returns>JObject of config file</returns>
public static void ReadAndMergeFileIfNecessary(string filePath, string savePath)
{ {
try try
{ {
if (!File.Exists(filePath)) if (!File.Exists(filePath))
{ {
Debug.Console(1, Debug.ErrorLogLevel.Error, Debug.LogError(
"ERROR: Configuration file not present. Please load file to {0} and reset program", filePath); "ERROR: Configuration file not present. Please load file to {0} and reset program", filePath);
} }
using (StreamReader fs = new StreamReader(filePath)) using (StreamReader fs = new StreamReader(filePath))
{ {
var jsonObj = JObject.Parse(fs.ReadToEnd()); var jsonObj = JObject.Parse(fs.ReadToEnd());
if(jsonObj["template"] != null && jsonObj["system"] != null) if(jsonObj[template] != null && jsonObj[system] != null)
{ {
// it's a double-config, merge it. // it's a double-config, merge it.
var merged = MergeConfigs(jsonObj); var merged = MergeConfigs(jsonObj);
if (jsonObj["system_url"] != null) if (jsonObj[systemUrl] != null)
{ {
merged["systemUrl"] = jsonObj["system_url"].Value<string>(); merged[systemUrl] = jsonObj[systemUrl].Value<string>();
} }
if (jsonObj["template_url"] != null) if (jsonObj[templateUrl] != null)
{ {
merged["templateUrl"] = jsonObj["template_url"].Value<string>(); merged[templateUrl] = jsonObj[templateUrl].Value<string>();
} }
jsonObj = merged; jsonObj = merged;
@@ -77,62 +96,62 @@ namespace PepperDash.Core.Config
var merged = new JObject(); var merged = new JObject();
// Put together top-level objects // Put together top-level objects
if (system["info"] != null) if (system[info] != null)
merged.Add("info", Merge(template["info"], system["info"], "infO")); merged.Add(info, Merge(template[info], system[info], info));
else else
merged.Add("info", template["info"]); merged.Add(info, template[info]);
merged.Add("devices", MergeArraysOnTopLevelProperty(template["devices"] as JArray, merged.Add(devices, MergeArraysOnTopLevelProperty(template[devices] as JArray,
system["devices"] as JArray, "key", "devices")); system[devices] as JArray, "key", devices));
if (system["rooms"] == null) if (system[rooms] == null)
merged.Add("rooms", template["rooms"]); merged.Add(rooms, template[rooms]);
else else
merged.Add("rooms", MergeArraysOnTopLevelProperty(template["rooms"] as JArray, merged.Add(rooms, MergeArraysOnTopLevelProperty(template[rooms] as JArray,
system["rooms"] as JArray, "key", "rooms")); system[rooms] as JArray, "key", rooms));
if (system["sourceLists"] == null) if (system[sourceLists] == null)
merged.Add("sourceLists", template["sourceLists"]); merged.Add(sourceLists, template[sourceLists]);
else else
merged.Add("sourceLists", Merge(template["sourceLists"], system["sourceLists"], "sourceLists")); merged.Add(sourceLists, Merge(template[sourceLists], system[sourceLists], sourceLists));
if (system["destinationLists"] == null) if (system[destinationLists] == null)
merged.Add("destinationLists", template["destinationLists"]); merged.Add(destinationLists, template[destinationLists]);
else else
merged.Add("destinationLists", merged.Add(destinationLists,
Merge(template["destinationLists"], system["destinationLists"], "destinationLists")); Merge(template[destinationLists], system[destinationLists], destinationLists));
if (system["cameraLists"] == null) if (system[cameraLists] == null)
merged.Add("cameraLists", template["cameraLists"]); merged.Add(cameraLists, template[cameraLists]);
else else
merged.Add("cameraLists", Merge(template["cameraLists"], system["cameraLists"], "cameraLists")); merged.Add(cameraLists, Merge(template[cameraLists], system[cameraLists], cameraLists));
if (system["audioControlPointLists"] == null) if (system[audioControlPointLists] == null)
merged.Add("audioControlPointLists", template["audioControlPointLists"]); merged.Add(audioControlPointLists, template[audioControlPointLists]);
else else
merged.Add("audioControlPointLists", merged.Add(audioControlPointLists,
Merge(template["audioControlPointLists"], system["audioControlPointLists"], "audioControlPointLists")); Merge(template[audioControlPointLists], system[audioControlPointLists], audioControlPointLists));
// Template tie lines take precedence. Config tool doesn't do them at system // Template tie lines take precedence. Config tool doesn't do them at system
// level anyway... // level anyway...
if (template["tieLines"] != null) if (template[tieLines] != null)
merged.Add("tieLines", template["tieLines"]); merged.Add(tieLines, template[tieLines]);
else if (system["tieLines"] != null) else if (system[tieLines] != null)
merged.Add("tieLines", system["tieLines"]); merged.Add(tieLines, system[tieLines]);
else else
merged.Add("tieLines", new JArray()); merged.Add(tieLines, new JArray());
if (template["joinMaps"] != null) if (template[joinMaps] != null)
merged.Add("joinMaps", template["joinMaps"]); merged.Add(joinMaps, template[joinMaps]);
else else
merged.Add("joinMaps", new JObject()); merged.Add(joinMaps, new JObject());
if (system["global"] != null) if (system[global] != null)
merged.Add("global", Merge(template["global"], system["global"], "global")); merged.Add(global, Merge(template[global], system[global], global));
else else
merged.Add("global", template["global"]); merged.Add(global, template[global]);
//Debug.Console(2, "MERGED CONFIG RESULT: \x0d\x0a{0}", merged); //Debug.Console(2, "MERGED CONFIG RESULT: \x0d\x0a{0}", merged);
return merged; return merged;
@@ -228,7 +247,7 @@ namespace PepperDash.Core.Config
} }
catch (Exception e) catch (Exception e)
{ {
Debug.Console(1, Debug.ErrorLogLevel.Warning, "Cannot merge items at path {0}: \r{1}", propPath, e); Debug.LogError($"Cannot merge items at path {propPath}: \r{e}");
} }
} }
} }

View File

@@ -124,22 +124,35 @@ namespace PepperDash.Essentials.Core.Config
Debug.LogMessage(LogEventLevel.Information, "Successfully Loaded Local Config"); Debug.LogMessage(LogEventLevel.Information, "Successfully Loaded Local Config");
return true; return true;
} }
else else
{ {
var doubleObj = JObject.Parse(fs.ReadToEnd()); var parsedConfig = JObject.Parse(fs.ReadToEnd());
ConfigObject = PortalConfigReader.MergeConfigs(doubleObj).ToObject<EssentialsConfig>();
// Extract SystemUrl and TemplateUrl into final config output // Check if it's a v2 config (check for "version" node)
// this means it's already merged by the Portal API
if (doubleObj["system_url"] != null) // from the v2 config tool
var isV2Config = parsedConfig["versions"] != null;
if (isV2Config)
{ {
ConfigObject.SystemUrl = doubleObj["system_url"].Value<string>(); Debug.LogMessage(LogEventLevel.Information, "Config file is a v2 format, no merge necessary.");
ConfigObject = parsedConfig.ToObject<EssentialsConfig>();
Debug.LogMessage(LogEventLevel.Information, "Successfully Loaded v2 Config");
return true;
} }
if (doubleObj["template_url"] != null) // Extract SystemUrl and TemplateUrl into final config output
ConfigObject = PortalConfigReader.MergeConfigs(parsedConfig).ToObject<EssentialsConfig>();
if (parsedConfig["system_url"] != null)
{ {
ConfigObject.TemplateUrl = doubleObj["template_url"].Value<string>(); ConfigObject.SystemUrl = parsedConfig["system_url"].Value<string>();
}
if (parsedConfig["template_url"] != null)
{
ConfigObject.TemplateUrl = parsedConfig["template_url"].Value<string>();
} }
} }

View File

@@ -16,13 +16,21 @@ namespace PepperDash.Essentials.Core.Config
/// </summary> /// </summary>
public class EssentialsConfig : BasicConfig public class EssentialsConfig : BasicConfig
{ {
[JsonProperty("system_url")] /// <summary>
/// Gets or sets the SystemUrl
/// </summary>
[JsonProperty("system_url")]
public string SystemUrl { get; set; } public string SystemUrl { get; set; }
[JsonProperty("template_url")] /// <summary>
/// Gets or sets the TemplateUrl
/// </summary>
[JsonProperty("template_url")]
public string TemplateUrl { get; set; } public string TemplateUrl { get; set; }
/// <summary>
/// Gets the SystemUuid extracted from the SystemUrl
/// </summary>
[JsonProperty("systemUuid")] [JsonProperty("systemUuid")]
public string SystemUuid public string SystemUuid
{ {
@@ -45,6 +53,9 @@ namespace PepperDash.Essentials.Core.Config
} }
} }
/// <summary>
/// Gets the TemplateUuid extracted from the TemplateUrl
/// </summary>
[JsonProperty("templateUuid")] [JsonProperty("templateUuid")]
public string TemplateUuid public string TemplateUuid
{ {
@@ -67,30 +78,84 @@ namespace PepperDash.Essentials.Core.Config
} }
} }
[JsonProperty("rooms")]
/// <summary> /// <summary>
/// Gets or sets the Rooms /// Gets or sets the Rooms
/// </summary> /// </summary>
[JsonProperty("rooms")]
public List<DeviceConfig> Rooms { get; set; } public List<DeviceConfig> Rooms { get; set; }
/// <summary>
/// Gets or sets the Versions
/// </summary>
public VersionData Versions { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="EssentialsConfig"/> class.
/// </summary>
public EssentialsConfig() public EssentialsConfig()
: base() : base()
{ {
Rooms = new List<DeviceConfig>(); Rooms = new List<DeviceConfig>();
} }
} }
/// <summary> /// <summary>
/// Represents a SystemTemplateConfigs /// Represents version data for Essentials and its packages
/// </summary> /// </summary>
public class SystemTemplateConfigs public class VersionData
{
/// <summary>
/// Gets or sets the Essentials version
/// </summary>
[JsonProperty("essentials")]
public NugetVersion Essentials { get; set; }
/// <summary>
/// Gets or sets the list of Packages
/// </summary>
[JsonProperty("packages")]
public List<NugetVersion> Packages { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="VersionData"/> class.
/// </summary>
public VersionData()
{
Packages = new List<NugetVersion>();
}
}
/// <summary>
/// Represents a NugetVersion
/// </summary>
public class NugetVersion
{
/// <summary>
/// Gets or sets the Version
/// </summary>
[JsonProperty("version")]
public string Version { get; set; }
/// <summary>
/// Gets or sets the PackageId
/// </summary>
[JsonProperty("packageId")]
public string PackageId { get; set; }
}
/// <summary>
/// Represents a SystemTemplateConfigs
/// </summary>
public class SystemTemplateConfigs
{ {
/// <summary> /// <summary>
/// Gets or sets the System /// Gets or sets the System
/// </summary> /// </summary>
public EssentialsConfig System { get; set; } public EssentialsConfig System { get; set; }
/// <summary>
/// Gets or sets the Template
/// </summary>
public EssentialsConfig Template { get; set; } public EssentialsConfig Template { get; set; }
} }
} }