diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/BasicConfig.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/BasicConfig.cs index 3673a384..5601c0fb 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/BasicConfig.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/BasicConfig.cs @@ -17,15 +17,27 @@ namespace PepperDash.Essentials.Core.Config [JsonProperty("info")] public InfoConfig Info { get; set; } + /// + /// Defines the devices in the system + /// [JsonProperty("devices")] public List Devices { get; set; } + /// + /// Defines the source list for the system + /// [JsonProperty("sourceLists")] public Dictionary> SourceLists { get; set; } + /// + /// Defines all the tie lines for system routing + /// [JsonProperty("tieLines")] public List TieLines { get; set; } + /// + /// Defines any join maps to override the default join maps + /// [JsonProperty("joinMaps")] public Dictionary JoinMaps { get; set; } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/DeviceConfig.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/DeviceConfig.cs index f3a00d43..d1df4f45 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/DeviceConfig.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/DeviceConfig.cs @@ -13,99 +13,43 @@ namespace PepperDash.Essentials.Core.Config { public class DeviceConfig : PropertiesConfigBase { + /// + /// The unique idendifier for the device + /// [JsonProperty("key", Required = Required.Always)] public string Key { get; set; } + /// + /// A unique ID for each device instance. Used to differentiate between devices of the same type that may have + /// been added/removed from the system + /// [JsonProperty("uid")] public int Uid { get; set; } + /// + /// The name of the device + /// [JsonProperty("name")] public string Name { get; set; } + /// + /// The group for the device + /// [JsonProperty("group")] public string Group { get; set; } + /// + /// The type of the device to instantiate + /// [JsonProperty("type", Required = Required.Always)] public string Type { get; set; } + /// + /// The properties necessary to define the device + /// [JsonProperty("properties", Required = Required.Always)] [JsonConverter(typeof(DevicePropertiesConverter))] public JToken Properties { get; set; } - - public DeviceConfig() - { - SchemaJson = @" -{ - 'definitions': {}, - '$schema': 'http://json-schema.org/draft-07/schema#', - '$id': 'http://example.com/root.json', - 'type': 'object', - 'title': 'The Root Schema', - 'properties': { - 'name': { - '$id': '#/properties/name', - 'type': 'string', - 'title': 'The Name Schema', - 'default': '', - 'examples': [ - 'App Server' - ], - 'pattern': '^(.*)$' - }, - 'group': { - '$id': '#/properties/group', - 'type': 'string', - 'title': 'The Group Schema', - 'default': '', - 'examples': [ - 'appServer' - ], - 'pattern': '^(.*)$' - }, - 'properties': { - '$id': '#/properties/properties', - 'type': 'object', - 'title': 'The Properties Schema' - }, - 'uid': { - '$id': '#/properties/uid', - 'type': 'integer', - 'title': 'The Uid Schema', - 'default': 0, - 'examples': [ - 4 - ] - }, - 'key': { - '$id': '#/properties/key', - 'type': 'string', - 'title': 'The Key Schema', - 'default': '', - 'examples': [ - 'display-1' - ], - 'pattern': '^(.*)$' - }, - 'type': { - '$id': '#/properties/type', - 'type': 'string', - 'title': 'The Type Schema', - 'default': '', - 'examples': [ - 'appServer' - ], - 'pattern': '^(.*)$' - } - }, - 'required': [ - 'group', - 'properties', - 'key', - 'type' - ] -} -"; - } } /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/Essentials/ConfigReader.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/Essentials/ConfigReader.cs index 8c601210..8c0a7ea1 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/Essentials/ConfigReader.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/Essentials/ConfigReader.cs @@ -92,8 +92,18 @@ namespace PepperDash.Essentials.Core.Config { Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading config file: '{0}'", filePath); - // Attempt to validate config against schema - ValidateSchema(fs.ReadToEnd()); + var directoryPrefix = Crestron.SimplSharp.CrestronIO.Directory.GetApplicationRootDirectory(); + + var schemaFilePath = directoryPrefix + Global.DirectorySeparator + "Config" + Global.DirectorySeparator + "Schema" + Global.DirectorySeparator + "EssentialsConfigSchema.json"; + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading Schema from path: {0}", schemaFilePath); + + if(File.Exists(schemaFilePath)) + { + // Attempt to validate config against schema + ValidateSchema(fs.ReadToEnd(), schemaFilePath); + } + else + Debug.Console(0, Debug.ErrorLogLevel.Warning, "No Schema found at path: {0}", schemaFilePath); if (localConfigFound) { @@ -133,20 +143,31 @@ namespace PepperDash.Essentials.Core.Config } } - public static void ValidateSchema(string json) + /// + /// Attempts to validate the JSON against the specified schema + /// + /// JSON to be validated + /// File name of schema to validate against + public static void ValidateSchema(string json, string schemaFileName) { JToken config = JToken.Parse(json); - var deviceConfig = new DeviceConfig(); + using (StreamReader fs = new StreamReader(schemaFileName)) + { + JsonSchema schema = JsonSchema.Parse(fs.ReadToEnd()); - JsonSchema schema = JsonSchema.Parse(deviceConfig.SchemaJson); - - config.Validate(schema, _ValidationEventHandler); + config.Validate(schema, Json_ValidationEventHandler); + } } - public static void _ValidationEventHandler(object sender, ValidationEventArgs args) + /// + /// Event Handler callback for JSON validation + /// + /// + /// + public static void Json_ValidationEventHandler(object sender, ValidationEventArgs args) { - Debug.Console(0, "{0}", args.Message); + Debug.Console(0, "JSON Validation error at line {0} position {1}: {2}", args.Exception.LineNumber, args.Exception.LinePosition, args.Message); } /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/Schema/EssentialsConfigSchema.json b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/Schema/EssentialsConfigSchema.json index f3a53c12..198b449b 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/Schema/EssentialsConfigSchema.json +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Config/Schema/EssentialsConfigSchema.json @@ -35,43 +35,7 @@ "template" ], "title": "Essentials Configuration" - }, - "Info": { - "type": "object", - "additionalProperties": false, - "properties": { - "name":{ - "type":"string" - }, - "date":{ - "type":"string", - "format": "date-time" - }, - "version":{ - "type":"string" - }, - "runtimeInfo":{ - "type":"object" - }, - "comment":{ - "type":"string" - }, - "hostname":{ - "type":"string" - }, - "appNumber":{ - "type":"integer" - }, - "lastModifiedDate": { - "type": "string", - "format": "date-time" - } - }, - "required": [ - "lastModifiedDate" - ], - "title": "SystemInfo" - }, + }, "BasicConfig": { "type": "object", "additionalProperties": false, @@ -96,32 +60,84 @@ } }, "required": [ - "devices", - "info", - "rooms", - "sourceLists", - "tieLines" ], "title": "Template" }, + "Info": { + "type": "object", + "additionalProperties": true, + "properties": { + "name":{ + "type":"string" + }, + "date":{ + "type":"string", + "format": "date-time" + }, + "version":{ + "type":"string" + }, + "runtimeInfo":{ + "$ref":"#/definitions/RuntimeInfo" + }, + "comment":{ + "type":"string" + }, + "hostname":{ + "type":"string" + }, + "appNumber":{ + "type":"integer" + }, + "lastModifiedDate": { + "type": "string", + "format": "date-time" + }, + "lastUid":{ + "type":"integer" + }, + "processorType":{ + "type":"string" + }, + "systemType":{ + "type":"string" + }, + "requiredControlSoftwareVersion":{ + "type":"string" + } + }, + "required": [ + + ], + "title": "Info" + }, + "RuntimeInfo":{ + "type":"object", + "additionalProperties": false, + "properties": { + "appName":{ + "type":"string" + }, + "assemblyVersion": { + "type":"string" + }, + "osVersion":{ + "type":"string" + } + } + }, "Device": { "type": "object", - "additionalProperties": false, + "additionalProperties": true, "properties": { "name": { "type": "string" }, - "supportedConfigModes": { - "type": "array", - "items": { - "type": "string" - } - }, "group": { "type": "string" }, "properties": { - "$ref": "#/definitions/DeviceProperties" + "type":"object" }, "uid": { "type": "integer" @@ -131,302 +147,17 @@ }, "type": { "type": "string" - }, - "supportsCompliance": { - "type": "boolean" - }, - "supportedSystemTypes": { - "type": "array", - "items": { - "type": "string" - } } }, "required": [ "group", "key", - "name", "properties", - "type", - "uid" + "type" ], "title": "Device" }, - "DeviceProperties": { - "type": "object", - "additionalProperties": false, - "properties": { - "numberOfRelays": { - "type": "integer" - }, - "numberOfComPorts": { - "type": "integer" - }, - "numberOfDIOPorts": { - "type": "integer" - }, - "numberOfIrPorts": { - "type": "integer" - }, - "hasControls": { - "type": "boolean" - }, - "isDefault": { - "type": "boolean" - }, - "hasAudio": { - "type": "boolean" - }, - "hasDpad": { - "type": "boolean" - }, - "hasNumeric": { - "type": "boolean" - }, - "hasDvr": { - "type": "boolean" - }, - "disableCodecSharing": { - "type": "boolean" - }, - "control": { - "$ref": "#/definitions/Control" - }, - "serverUrl": { - "type": "string" - }, - "communicationMonitorProperties": { - "$ref": "#/definitions/CommunicationMonitorProperties" - }, - "phonebookMode": { - "type": "string" - }, - "occupancy": { - "$ref": "#/definitions/Occupancy" - }, - "favorites": { - "type": "array", - "items": { - "$ref": "#/definitions/Favorite" - } - }, - "sgdFile": { - "type": "string" - }, - "showTime": { - "type": "boolean" - }, - "showVolumeGauge": { - "type": "boolean" - }, - "sourcesOverflowCount": { - "type": "integer" - }, - "showDate": { - "type": "boolean" - }, - "headerStyle": { - "type": "string" - }, - "usesSplashPage": { - "type": "boolean" - }, - "roomListKey": { - "type": "string" - }, - "defaultRoomKey": { - "type": "string" - } - }, - "required": [], - "title": "DeviceProperties" - }, - "CommunicationMonitorProperties": { - "type": "object", - "additionalProperties": false, - "properties": { - "timeToError": { - "type": "integer" - }, - "timeToWarning": { - "type": "integer" - }, - "pollInterval": { - "type": "integer" - }, - "pollString": { - "type": "string" - } - }, - "required": [ - "pollInterval", - "pollString", - "timeToError", - "timeToWarning" - ], - "title": "CommunicationMonitorProperties" - }, - "Control": { - "type": "object", - "additionalProperties": false, - "properties": { - "irFile": { - "type": "string" - }, - "controlPortNumber": { - "type": "integer" - }, - "controlPortDevKey": { - "type": "string" - }, - "method": { - "type": "string" - }, - "tcpSshProperties": { - "$ref": "#/definitions/TCPSSHProperties" - }, - "controlPortName": { - "type": "string" - }, - "ipid": { - "type": "string", - "format": "integer" - }, - "endOfLineChar": { - "type": "string" - }, - "endOfLineString": { - "type": "string" - }, - "deviceReadyResponsePattern": { - "type": "string" - }, - "params": { - "$ref": "#/definitions/Params" - } - }, - "required": [], - "title": "Control" - }, - "Params": { - "type": "object", - "additionalProperties": false, - "properties": { - "deviceReadyResponsePattern": { - "type": "string" - }, - "endOfLineString": { - "type": "string" - } - }, - "required": [ - "deviceReadyResponsePattern", - "endOfLineString" - ], - "title": "Params" - }, - "TCPSSHProperties": { - "type": "object", - "additionalProperties": false, - "properties": { - "username": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "address": { - "type": "string" - }, - "password": { - "type": "string" - }, - "autoReconnect": { - "type": "boolean" - }, - "autoReconnectIntervalMs": { - "type": "integer" - }, - "bufferSize": { - "type": "integer" - } - }, - "required": [ - "address", - "autoReconnect", - "autoReconnectIntervalMs", - "bufferSize", - "password", - "port", - "username" - ], - "title": "TCPSSHProperties" - }, - "Favorite": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "number": { - "type": "string", - "format": "integer" - } - }, - "required": [ - "name", - "number" - ], - "title": "Favorite" - }, - "Occupancy": { - "type": "object", - "additionalProperties": false, - "properties": { - "available": { - "type": "boolean" - } - }, - "required": [ - "available" - ], - "title": "Occupancy" - }, - "TemplateInfo": { - "type": "object", - "additionalProperties": false, - "properties": { - "lastUid": { - "type": "integer" - }, - "processorType": { - "type": "string" - }, - "systemType": { - "type": "string" - }, - "lastModifiedDate": { - "type": "string", - "format": "date-time" - }, - "requiredControlSofwareVersion": { - "type": "string" - }, - "comment": { - "type": "string" - } - }, - "required": [ - "comment", - "lastModifiedDate", - "lastUid", - "processorType", - "requiredControlSofwareVersion", - "systemType" - ], - "title": "TemplateInfo" - }, + "Room": { "type": "object", "additionalProperties": false, @@ -438,7 +169,7 @@ "type": "string" }, "properties": { - "$ref": "#/definitions/RoomProperties" + "type": "object" }, "type": { "type": "string" @@ -452,246 +183,22 @@ ], "title": "Room" }, - "RoomProperties": { - "type": "object", - "additionalProperties": false, - "properties": { - "description": { - "type": "string" - }, - "volumes": { - "$ref": "#/definitions/Volumes" - }, - "defaultDisplayKey": { - "type": "string" - }, - "defaultAudioKey": { - "type": "string" - }, - "helpMessage": { - "type": "string" - }, - "hasDsp": { - "type": "boolean" - }, - "defaultSourceItem": { - "type": "string" - }, - "logo": { - "$ref": "#/definitions/Logo" - }, - "environment": { - "$ref": "#/definitions/Environment" - }, - "defaultVideoBehavior": { - "type": "string" - }, - "videoCodecKey": { - "type": "string" - }, - "sourceListKey": { - "type": "string" - } - }, - "required": [ - "defaultAudioKey", - "defaultDisplayKey", - "defaultSourceItem", - "defaultVideoBehavior", - "description", - "environment", - "hasDsp", - "helpMessage", - "logo", - "sourceListKey", - "videoCodecKey", - "volumes" - ], - "title": "RoomProperties" - }, - "Environment": { - "type": "object", - "additionalProperties": false, - "properties": { - "deviceKeys": { - "type": "array", - "items": {} - } - }, - "required": [ - "deviceKeys" - ], - "title": "Environment" - }, - "Logo": { - "type": "object", - "additionalProperties": false, - "properties": { - "url": { - "type": "string" - }, - "type": { - "type": "string" - } - }, - "required": [ - "type", - "url" - ], - "title": "Logo" - }, - "Volumes": { - "type": "object", - "additionalProperties": false, - "properties": { - "master": { - "$ref": "#/definitions/Master" - } - }, - "required": [ - "master" - ], - "title": "Volumes" - }, - "Master": { - "type": "object", - "additionalProperties": false, - "properties": { - "level": { - "type": "integer" - }, - "deviceKey": { - "type": "string" - }, - "label": { - "type": "string" - } - }, - "required": [ - "deviceKey", - "label", - "level" - ], - "title": "Master" - }, "SourceLists": { "type": "object", - "additionalProperties": false, + "additionalProperties": true, "properties": { - "default": { - "$ref": "#/definitions/Default" + "default":{ + "$ref":"#/definitions/SourceList" } }, - "required": [ - "default" - ], "title": "SourceLists" }, - "Default": { + "SourceList": { "type": "object", - "additionalProperties": false, + "additionalProperties": true, "properties": { - "codecOsd": { - "$ref": "#/definitions/CodecOsd" - }, - "source-1": { - "$ref": "#/definitions/Source" - }, - "roomOff": { - "$ref": "#/definitions/RoomOff" - }, - "source-2": { - "$ref": "#/definitions/Source" - } }, - "required": [ - "codecOsd", - "roomOff", - "source-1", - "source-2" - ], - "title": "Default" - }, - "CodecOsd": { - "type": "object", - "additionalProperties": false, - "properties": { - "sourceKey": { - "type": "string" - }, - "name": { - "type": "string" - }, - "routeList": { - "type": "array", - "items": { - "$ref": "#/definitions/RouteList" - } - }, - "includeInSourceList": { - "type": "boolean" - }, - "type": { - "type": "string" - }, - "order": { - "type": "integer" - } - }, - "required": [ - "includeInSourceList", - "name", - "order", - "routeList", - "sourceKey", - "type" - ], - "title": "CodecOsd" - }, - "RouteList": { - "type": "object", - "additionalProperties": false, - "properties": { - "destinationKey": { - "type": "string" - }, - "sourceKey": { - "type": "string" - }, - "type": { - "type": "string" - } - }, - "required": [ - "destinationKey", - "sourceKey", - "type" - ], - "title": "RouteList" - }, - "RoomOff": { - "type": "object", - "additionalProperties": false, - "properties": { - "sourceKey": { - "type": "string" - }, - "routeList": { - "type": "array", - "items": { - "$ref": "#/definitions/RouteList" - } - }, - "type": { - "type": "string" - } - }, - "required": [ - "routeList", - "sourceKey", - "type" - ], - "title": "RoomOff" + "title": "Source List" }, "Source": { "type": "object", @@ -716,7 +223,12 @@ "type": "boolean" }, "type": { - "type": "string" + "type": "string", + "enum":[ + "route", + "off", + "other" + ] }, "altIcon": { "type": "string" @@ -729,8 +241,6 @@ } }, "required": [ - "altIcon", - "icon", "includeInSourceList", "order", "routeList", @@ -739,6 +249,34 @@ "volumeControlKey" ], "title": "Source" + }, + "RouteList": { + "type": "object", + "additionalProperties": false, + "properties": { + "destinationKey": { + "type": "string" + }, + "sourceKey": { + "type": "string" + }, + "type": { + "type": "string", + "enum":[ + "audio", + "video", + "audioVideo", + "usbOutput", + "usbInput" + ] + } + }, + "required": [ + "destinationKey", + "sourceKey", + "type" + ], + "title": "RouteList" } } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/SourceListItem.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/SourceListItem.cs index efa2b2ad..43836b13 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/SourceListItem.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/SourceListItem.cs @@ -67,34 +67,64 @@ namespace PepperDash.Essentials.Core [JsonProperty("name")] public string Name { get; set; } + /// + /// The icon to display + /// [JsonProperty("icon")] public string Icon { get; set; } + /// + /// Alternate icon to display + /// [JsonProperty("altIcon")] public string AltIcon { get; set; } + /// + /// Indicates if the source should be included in the list + /// [JsonProperty("includeInSourceList")] public bool IncludeInSourceList { get; set; } + /// + /// Determines the order the source appears in the list (ascending) + /// [JsonProperty("order")] public int Order { get; set; } + /// + /// Key of the volume control device for the source + /// [JsonProperty("volumeControlKey")] public string VolumeControlKey { get; set; } + /// + /// The type of source list item + /// [JsonProperty("type")] [JsonConverter(typeof(StringEnumConverter))] public eSourceListItemType Type { get; set; } + /// + /// The list of routes to run when source is selected + /// [JsonProperty("routeList")] public List RouteList { get; set; } + /// + /// Indicates if this source should be disabled for sharing via codec content + /// [JsonProperty("disableCodecSharing")] public bool DisableCodecSharing { get; set; } + /// + /// Indicates if this source should be disabled for local routing + /// [JsonProperty("disableRoutedSharing")] public bool DisableRoutedSharing { get; set; } + /// + /// The list of valid destination types for this source + /// [JsonProperty("destinations")] public List Destinations { get; set; } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 72ca8bab..dadc2255 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -267,11 +267,13 @@ + + Always + - diff --git a/essentials-framework/Essentials DM/Essentials_DM/Config/DMChassisConfig.cs b/essentials-framework/Essentials DM/Essentials_DM/Config/DMChassisConfig.cs index d347fbc8..15a74f21 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Config/DMChassisConfig.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Config/DMChassisConfig.cs @@ -17,21 +17,39 @@ namespace PepperDash.Essentials.DM.Config [JsonProperty("control")] public ControlPropertiesConfig Control { get; set; } + /// + /// The available volume controls + /// [JsonProperty("volumeControls")] public Dictionary VolumeControls { get; set; } + /// + /// The input cards + /// [JsonProperty("inputSlots")] public Dictionary InputSlots { get; set; } + /// + /// The output cards (each card represents a pair of outputs) + /// [JsonProperty("outputSlots")] public Dictionary OutputSlots { get; set; } + /// + /// The names of the Inputs + /// [JsonProperty("inputNames")] public Dictionary InputNames { get; set; } + /// + /// The names of the Outputs + /// [JsonProperty("outputNames")] public Dictionary OutputNames { get; set; } + /// + /// The string to use when no route is set for a given output + /// [JsonProperty("noRouteText")] public string NoRouteText { get; set; } @@ -49,9 +67,15 @@ namespace PepperDash.Essentials.DM.Config /// public class DmCardAudioPropertiesConfig { + /// + /// The level to set on the output + /// [JsonProperty("outLevel")] public int OutLevel { get; set; } + /// + /// Defines if this level is adjustable or not + /// [JsonProperty("isVolumeControlPoint")] public bool IsVolumeControlPoint { get; set; } }