diff --git a/PepperDashEssentials/Example Configuration/SIMPLBridging/SIMPLBridgeExample_configurationFile.json b/PepperDashEssentials/Example Configuration/SIMPLBridging/SIMPLBridgeExample_configurationFile.json
index 3fb02ce8..f66add0c 100644
--- a/PepperDashEssentials/Example Configuration/SIMPLBridging/SIMPLBridgeExample_configurationFile.json
+++ b/PepperDashEssentials/Example Configuration/SIMPLBridging/SIMPLBridgeExample_configurationFile.json
@@ -175,6 +175,10 @@
{
"deviceKey": "gls-odt-1",
"joinStart": 2751
+ },
+ {
+ "deviceKey": "gls-part-1",
+ "joinStart": 2781
}
]
}
@@ -427,6 +431,19 @@
"method": "cresnet"
}
}
+ },
+ {
+ "key": "gls-part-1",
+ "uid": 19,
+ "name": "GLS-PART-CN 1",
+ "type": "glspartcn",
+ "group": "partition",
+ "properties": {
+ "control": {
+ "cresnetId": "90",
+ "method": "cresnet"
+ }
+ }
}
],
"rooms": [],
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/GlsPartitionSensorJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/GlsPartitionSensorJoinMap.cs
new file mode 100644
index 00000000..cc554790
--- /dev/null
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/GlsPartitionSensorJoinMap.cs
@@ -0,0 +1,130 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using PepperDash.Essentials.Core;
+
+namespace PepperDash_Essentials_Core.Bridges.JoinMaps
+{
+ public class GlsPartitionSensorJoinMap : JoinMapBaseAdvanced
+ {
+ [JoinName("IsOnline")]
+ public JoinDataComplete IsOnline = new JoinDataComplete(
+ new JoinData()
+ {
+ JoinNumber = 1,
+ JoinSpan = 1
+ },
+ new JoinMetadata()
+ {
+ Description = "Sensor Is Online",
+ JoinCapabilities = eJoinCapabilities.ToSIMPL,
+ JoinType = eJoinType.Digital
+ });
+
+ [JoinName("Name")]
+ public JoinDataComplete Name = new JoinDataComplete(
+ new JoinData()
+ {
+ JoinNumber = 1,
+ JoinSpan = 1
+ },
+ new JoinMetadata()
+ {
+ Description = "Sensor Name",
+ JoinCapabilities = eJoinCapabilities.ToSIMPL,
+ JoinType = eJoinType.Serial
+ });
+
+ [JoinName("Enable")]
+ public JoinDataComplete Enable = new JoinDataComplete(
+ new JoinData()
+ {
+ JoinNumber = 2,
+ JoinSpan = 1
+ },
+ new JoinMetadata()
+ {
+ Description = "Sensor Enable",
+ JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
+ JoinType = eJoinType.Digital
+ });
+
+ [JoinName("PartitionSensed")]
+ public JoinDataComplete PartitionSensed = new JoinDataComplete(
+ new JoinData()
+ {
+ JoinNumber = 3,
+ JoinSpan = 1
+ },
+ new JoinMetadata()
+ {
+ Description = "Sensor Partition Sensed",
+ JoinCapabilities = eJoinCapabilities.ToSIMPL,
+ JoinType = eJoinType.Digital
+ });
+
+ [JoinName("PartitionNotSensed")]
+ public JoinDataComplete PartitionNotSensed = new JoinDataComplete(
+ new JoinData()
+ {
+ JoinNumber = 4,
+ JoinSpan = 1
+ },
+ new JoinMetadata()
+ {
+ Description = "Sensor Partition Not Sensed",
+ JoinCapabilities = eJoinCapabilities.ToSIMPL,
+ JoinType = eJoinType.Digital
+ });
+
+ [JoinName("IncreaseSensitivity")]
+ public JoinDataComplete IncreaseSensitivity = new JoinDataComplete(
+ new JoinData()
+ {
+ JoinNumber = 6,
+ JoinSpan = 1
+ },
+ new JoinMetadata()
+ {
+ Description = "Sensor Increase Sensitivity",
+ JoinCapabilities = eJoinCapabilities.FromSIMPL,
+ JoinType = eJoinType.Digital
+ });
+
+ [JoinName("DecreaseSensitivity")]
+ public JoinDataComplete DecreaseSensitivity = new JoinDataComplete(
+ new JoinData()
+ {
+ JoinNumber = 7,
+ JoinSpan = 1
+ },
+ new JoinMetadata()
+ {
+ Description = "Sensor Decrease Sensitivity",
+ JoinCapabilities = eJoinCapabilities.FromSIMPL,
+ JoinType = eJoinType.Digital
+ });
+
+ [JoinName("Sensitivity")]
+ public JoinDataComplete Sensitivity = new JoinDataComplete(
+ new JoinData()
+ {
+ JoinNumber = 2,
+ JoinSpan = 1
+ },
+ new JoinMetadata()
+ {
+ Description = "Sensor Sensitivity",
+ JoinCapabilities = eJoinCapabilities.ToFromSIMPL,
+ JoinType = eJoinType.Analog
+ });
+
+ public GlsPartitionSensorJoinMap(uint joinStart)
+ : base(joinStart, typeof (GlsPartitionSensorJoinMap))
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs
index 676299e5..ba6b3482 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs
@@ -1,488 +1,488 @@
-using System;
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
-using Crestron.SimplSharp.Reflection;
-
-using PepperDash.Core;
-using PepperDash.Essentials.Core.Config;
-
-using Newtonsoft.Json;
-
-namespace PepperDash.Essentials.Core
-{
- public static class JoinMapHelper
- {
- ///
- /// Attempts to get the serialized join map from config
- ///
- ///
- ///
- public static string GetSerializedJoinMapForDevice(string joinMapKey)
- {
- if (string.IsNullOrEmpty(joinMapKey))
- return null;
-
- var joinMap = ConfigReader.ConfigObject.JoinMaps[joinMapKey];
-
- return joinMap;
- }
-
- ///
- /// Attempts to get the serialized join map from config
- ///
- ///
- ///
- public static string GetJoinMapForDevice(string joinMapKey)
- {
- return GetSerializedJoinMapForDevice(joinMapKey);
- }
-
- ///
- /// Attempts to find a custom join map by key and returns it deserialized if found
- ///
- ///
- ///
- public static Dictionary TryGetJoinMapAdvancedForDevice(string joinMapKey)
- {
- if (string.IsNullOrEmpty(joinMapKey))
- return null;
-
- var joinMapSerialzed = ConfigReader.ConfigObject.JoinMaps[joinMapKey];
-
- if (joinMapSerialzed == null) return null;
-
- var joinMapData = JsonConvert.DeserializeObject>(joinMapSerialzed);
-
- return joinMapData;
- }
-
- }
-
- ///
- /// Base class for join maps
- ///
- [Obsolete("This is being deprecated in favor of JoinMapBaseAdvanced")]
- public abstract class JoinMapBase
- {
- ///
- /// Modifies all the join numbers by adding the offset. This should never be called twice
- ///
- ///
- public abstract void OffsetJoinNumbers(uint joinStart);
-
- ///
- /// The collection of joins and associated metadata
- ///
- public Dictionary Joins = new Dictionary();
-
- ///
- /// Prints the join information to console
- ///
- public void PrintJoinMapInfo()
- {
- Debug.Console(0, "{0}:\n", GetType().Name);
-
- // Get the joins of each type and print them
- Debug.Console(0, "Digitals:");
- var digitals = Joins.Where(j => (j.Value.JoinType & eJoinType.Digital) == eJoinType.Digital).ToDictionary(j => j.Key, j => j.Value);
- Debug.Console(2, "Found {0} Digital Joins", digitals.Count);
- PrintJoinList(GetSortedJoins(digitals));
-
- Debug.Console(0, "Analogs:");
- var analogs = Joins.Where(j => (j.Value.JoinType & eJoinType.Analog) == eJoinType.Analog).ToDictionary(j => j.Key, j => j.Value);
- Debug.Console(2, "Found {0} Analog Joins", analogs.Count);
- PrintJoinList(GetSortedJoins(analogs));
-
- Debug.Console(0, "Serials:");
- var serials = Joins.Where(j => (j.Value.JoinType & eJoinType.Serial) == eJoinType.Serial).ToDictionary(j => j.Key, j => j.Value);
- Debug.Console(2, "Found {0} Serial Joins", serials.Count);
- PrintJoinList(GetSortedJoins(serials));
-
- }
-
- ///
- /// Returns a sorted list by JoinNumber
- ///
- ///
- ///
- List> GetSortedJoins(Dictionary joins)
- {
- var sortedJoins = joins.ToList();
-
- sortedJoins.Sort((pair1, pair2) => pair1.Value.JoinNumber.CompareTo(pair2.Value.JoinNumber));
-
- return sortedJoins;
- }
-
- void PrintJoinList(List> joins)
- {
- foreach (var join in joins)
- {
- Debug.Console(0,
- @"Join Number: {0} | Label: '{1}' | JoinSpan: '{2}' | Type: '{3}' | Capabilities: '{4}'",
- join.Value.JoinNumber,
- join.Value.Label,
- join.Value.JoinSpan,
- join.Value.JoinType.ToString(),
- join.Value.JoinCapabilities.ToString());
- }
- }
-
- ///
- /// Returns the join number for the join with the specified key
- ///
- ///
- ///
- public uint GetJoinForKey(string key)
- {
- return Joins.ContainsKey(key) ? Joins[key].JoinNumber : 0;
- }
-
- ///
- /// Returns the join span for the join with the specified key
- ///
- ///
- ///
- public uint GetJoinSpanForKey(string key)
- {
- return Joins.ContainsKey(key) ? Joins[key].JoinSpan : 0;
- }
- }
-
- ///
- /// Base class for join maps
- ///
- public abstract class JoinMapBaseAdvanced
- {
- protected uint JoinOffset;
-
- ///
- /// The collection of joins and associated metadata
- ///
- public Dictionary Joins { get; private set; }
-
- protected JoinMapBaseAdvanced(uint joinStart)
- {
- Joins = new Dictionary();
-
- JoinOffset = joinStart - 1;
- }
-
- protected JoinMapBaseAdvanced(uint joinStart, Type type):this(joinStart)
- {
- AddJoins(type);
- }
-
- protected void AddJoins(Type type)
- {
- // Add all the JoinDataComplete properties to the Joins Dictionary and pass in the offset
- //Joins = this.GetType()
- // .GetCType()
- // .GetFields(BindingFlags.Public | BindingFlags.Instance)
- // .Where(field => field.IsDefined(typeof(JoinNameAttribute), true))
- // .Select(field => (JoinDataComplete)field.GetValue(this))
- // .ToDictionary(join => join.GetNameAttribute(), join =>
- // {
- // join.SetJoinOffset(_joinOffset);
- // return join;
- // });
-
- //type = this.GetType(); <- this wasn't working because 'this' was always the base class, never the derived class
- var fields =
- type.GetCType()
- .GetFields(BindingFlags.Public | BindingFlags.Instance)
- .Where(f => f.IsDefined(typeof (JoinNameAttribute), true));
-
- foreach (var field in fields)
- {
- var childClass = Convert.ChangeType(this, type, null);
-
- var value = field.GetValue(childClass) as JoinDataComplete; //this here is JoinMapBaseAdvanced, not the child class. JoinMapBaseAdvanced has no fields.
-
- if (value == null)
- {
- Debug.Console(0, "Unable to caset base class to {0}", type.Name);
- continue;
- }
-
- value.SetJoinOffset(JoinOffset);
-
- var joinName = value.GetNameAttribute(field);
-
- if (String.IsNullOrEmpty(joinName)) continue;
-
- Joins.Add(joinName, value);
- }
-
-
- PrintJoinMapInfo();
- }
-
- ///
- /// Prints the join information to console
- ///
- public void PrintJoinMapInfo()
- {
- Debug.Console(0, "{0}:\n", GetType().Name);
-
- // Get the joins of each type and print them
- Debug.Console(0, "Digitals:");
- var digitals = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Digital) == eJoinType.Digital).ToDictionary(j => j.Key, j => j.Value);
- Debug.Console(2, "Found {0} Digital Joins", digitals.Count);
- PrintJoinList(GetSortedJoins(digitals));
-
- Debug.Console(0, "Analogs:");
- var analogs = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Analog) == eJoinType.Analog).ToDictionary(j => j.Key, j => j.Value);
- Debug.Console(2, "Found {0} Analog Joins", analogs.Count);
- PrintJoinList(GetSortedJoins(analogs));
-
- Debug.Console(0, "Serials:");
- var serials = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Serial) == eJoinType.Serial).ToDictionary(j => j.Key, j => j.Value);
- Debug.Console(2, "Found {0} Serial Joins", serials.Count);
- PrintJoinList(GetSortedJoins(serials));
-
- }
-
- ///
- /// Returns a sorted list by JoinNumber
- ///
- ///
- ///
- List> GetSortedJoins(Dictionary joins)
- {
- var sortedJoins = joins.ToList();
-
- sortedJoins.Sort((pair1, pair2) => pair1.Value.JoinNumber.CompareTo(pair2.Value.JoinNumber));
-
- return sortedJoins;
- }
-
- void PrintJoinList(List> joins)
- {
- foreach (var join in joins)
- {
- Debug.Console(0,
- @"Join Number: {0} | JoinSpan: '{1}' | Label: '{2}' | Type: '{3}' | Capabilities: '{4}'",
- join.Value.JoinNumber,
- join.Value.JoinSpan,
- join.Value.Metadata.Label,
- join.Value.Metadata.JoinType.ToString(),
- join.Value.Metadata.JoinCapabilities.ToString());
- }
- }
-
- ///
- /// Attempts to find the matching key for the custom join and if found overwrites the default JoinData with the custom
- ///
- ///
- public void SetCustomJoinData(Dictionary joinData)
- {
- foreach (var customJoinData in joinData)
- {
- var join = Joins[customJoinData.Key];
-
- if (join != null)
- {
- join.SetCustomJoinData(customJoinData.Value);
- }
- else
- {
- Debug.Console(2, "No mathcing key found in join map for: '{0}'", customJoinData.Key);
- }
- }
-
- PrintJoinMapInfo();
- }
-
- /////
- ///// Returns the join number for the join with the specified key
- /////
- /////
- /////
- //public uint GetJoinForKey(string key)
- //{
- // return Joins.ContainsKey(key) ? Joins[key].JoinNumber : 0;
- //}
-
-
- /////
- ///// Returns the join span for the join with the specified key
- /////
- /////
- /////
- //public uint GetJoinSpanForKey(string key)
- //{
- // return Joins.ContainsKey(key) ? Joins[key].JoinSpan : 0;
- //}
- }
-
- ///
- /// Read = Provides feedback to SIMPL
- /// Write = Responds to sig values from SIMPL
- ///
- [Flags]
- public enum eJoinCapabilities
- {
- None = 0,
- ToSIMPL = 1,
- FromSIMPL = 2,
- ToFromSIMPL = ToSIMPL | FromSIMPL
- }
-
- [Flags]
- public enum eJoinType
- {
- None = 0,
- Digital = 1,
- Analog = 2,
- Serial = 4,
- DigitalAnalog = Digital | Analog,
- DigitalSerial = Digital | Serial,
- AnalogSerial = Analog | Serial,
- DigitalAnalogSerial = Digital | Analog | Serial
- }
-
- ///
- /// Metadata describing the join
- ///
- public class JoinMetadata
+using Crestron.SimplSharp.Reflection;
+
+using PepperDash.Core;
+using PepperDash.Essentials.Core.Config;
+
+using Newtonsoft.Json;
+
+namespace PepperDash.Essentials.Core
+{
+ public static class JoinMapHelper
{
- private string _description;
-
- ///
- /// Join number (based on join offset value)
- ///
- [JsonProperty("joinNumber")]
- [Obsolete]
- public uint JoinNumber { get; set; }
- ///
- /// Join range span. If join indicates the start of a range of joins, this indicated the maximum number of joins in the range
- ///
- [Obsolete]
- [JsonProperty("joinSpan")]
- public uint JoinSpan { get; set; }
-
- ///
- /// A label for the join to better describe its usage
- ///
- [Obsolete("Use Description instead")]
- [JsonProperty("label")]
- public string Label { get { return _description; } set { _description = value; } }
-
///
- /// A description for the join to better describe its usage
- ///
- [JsonProperty("description")]
- public string Description { get { return _description; } set { _description = value; } }
- ///
- /// Signal type(s)
- ///
- [JsonProperty("joinType")]
- public eJoinType JoinType { get; set; }
- ///
- /// Indicates whether the join is read and/or write
- ///
- [JsonProperty("joinCapabilities")]
- public eJoinCapabilities JoinCapabilities { get; set; }
- ///
- /// Indicates a set of valid values (particularly if this translates to an enum
- ///
- [JsonProperty("validValues")]
- public string[] ValidValues { get; set; }
-
- }
-
- ///
- /// Data describing the join. Can be
- ///
- public class JoinData
- {
- ///
- /// Join number (based on join offset value)
- ///
- [JsonProperty("joinNumber")]
- public uint JoinNumber { get; set; }
- ///
- /// Join range span. If join indicates the start of a range of joins, this indicated the maximum number of joins in the range
- ///
- [JsonProperty("joinSpan")]
- public uint JoinSpan { get; set; }
- }
-
- ///
- /// A class to aggregate the JoinData and JoinMetadata for a join
- ///
- public class JoinDataComplete
- {
- private uint _joinOffset;
-
- private JoinData _data;
- public JoinMetadata Metadata { get; set; }
-
- public JoinDataComplete(JoinData data, JoinMetadata metadata)
- {
- _data = data;
- Metadata = metadata;
- }
-
- ///
- /// Sets the join offset value
- ///
- ///
- public void SetJoinOffset(uint joinOffset)
- {
- _joinOffset = joinOffset;
- }
-
- ///
- /// The join number (including the offset)
- ///
- public uint JoinNumber
- {
- get { return _data.JoinNumber+ _joinOffset; }
- set { _data.JoinNumber = value; }
- }
-
- public uint JoinSpan
- {
- get { return _data.JoinSpan; }
- }
-
- public void SetCustomJoinData(JoinData customJoinData)
- {
- _data = customJoinData;
- }
-
- public string GetNameAttribute(MemberInfo memberInfo)
- {
- var name = string.Empty;
- var attribute = (JoinNameAttribute)CAttribute.GetCustomAttribute(memberInfo, typeof(JoinNameAttribute));
-
- if (attribute == null) return name;
-
- name = attribute.Name;
- Debug.Console(2, "JoinName Attribute value: {0}", name);
- return name;
+ /// Attempts to get the serialized join map from config
+ ///
+ ///
+ ///
+ public static string GetSerializedJoinMapForDevice(string joinMapKey)
+ {
+ if (string.IsNullOrEmpty(joinMapKey))
+ return null;
+
+ var joinMap = ConfigReader.ConfigObject.JoinMaps[joinMapKey];
+
+ return joinMap;
+ }
+
+ ///
+ /// Attempts to get the serialized join map from config
+ ///
+ ///
+ ///
+ public static string GetJoinMapForDevice(string joinMapKey)
+ {
+ return GetSerializedJoinMapForDevice(joinMapKey);
+ }
+
+ ///
+ /// Attempts to find a custom join map by key and returns it deserialized if found
+ ///
+ ///
+ ///
+ public static Dictionary TryGetJoinMapAdvancedForDevice(string joinMapKey)
+ {
+ if (string.IsNullOrEmpty(joinMapKey))
+ return null;
+
+ var joinMapSerialzed = ConfigReader.ConfigObject.JoinMaps[joinMapKey];
+
+ if (joinMapSerialzed == null) return null;
+
+ var joinMapData = JsonConvert.DeserializeObject>(joinMapSerialzed);
+
+ return joinMapData;
+ }
+
+ }
+
+ ///
+ /// Base class for join maps
+ ///
+ [Obsolete("This is being deprecated in favor of JoinMapBaseAdvanced")]
+ public abstract class JoinMapBase
+ {
+ ///
+ /// Modifies all the join numbers by adding the offset. This should never be called twice
+ ///
+ ///
+ public abstract void OffsetJoinNumbers(uint joinStart);
+
+ ///
+ /// The collection of joins and associated metadata
+ ///
+ public Dictionary Joins = new Dictionary();
+
+ ///
+ /// Prints the join information to console
+ ///
+ public void PrintJoinMapInfo()
+ {
+ Debug.Console(0, "{0}:\n", GetType().Name);
+
+ // Get the joins of each type and print them
+ Debug.Console(0, "Digitals:");
+ var digitals = Joins.Where(j => (j.Value.JoinType & eJoinType.Digital) == eJoinType.Digital).ToDictionary(j => j.Key, j => j.Value);
+ Debug.Console(2, "Found {0} Digital Joins", digitals.Count);
+ PrintJoinList(GetSortedJoins(digitals));
+
+ Debug.Console(0, "Analogs:");
+ var analogs = Joins.Where(j => (j.Value.JoinType & eJoinType.Analog) == eJoinType.Analog).ToDictionary(j => j.Key, j => j.Value);
+ Debug.Console(2, "Found {0} Analog Joins", analogs.Count);
+ PrintJoinList(GetSortedJoins(analogs));
+
+ Debug.Console(0, "Serials:");
+ var serials = Joins.Where(j => (j.Value.JoinType & eJoinType.Serial) == eJoinType.Serial).ToDictionary(j => j.Key, j => j.Value);
+ Debug.Console(2, "Found {0} Serial Joins", serials.Count);
+ PrintJoinList(GetSortedJoins(serials));
+
+ }
+
+ ///
+ /// Returns a sorted list by JoinNumber
+ ///
+ ///
+ ///
+ List> GetSortedJoins(Dictionary joins)
+ {
+ var sortedJoins = joins.ToList();
+
+ sortedJoins.Sort((pair1, pair2) => pair1.Value.JoinNumber.CompareTo(pair2.Value.JoinNumber));
+
+ return sortedJoins;
+ }
+
+ void PrintJoinList(List> joins)
+ {
+ foreach (var join in joins)
+ {
+ Debug.Console(0,
+ @"Join Number: {0} | Label: '{1}' | JoinSpan: '{2}' | Type: '{3}' | Capabilities: '{4}'",
+ join.Value.JoinNumber,
+ join.Value.Label,
+ join.Value.JoinSpan,
+ join.Value.JoinType.ToString(),
+ join.Value.JoinCapabilities.ToString());
+ }
+ }
+
+ ///
+ /// Returns the join number for the join with the specified key
+ ///
+ ///
+ ///
+ public uint GetJoinForKey(string key)
+ {
+ return Joins.ContainsKey(key) ? Joins[key].JoinNumber : 0;
+ }
+
+ ///
+ /// Returns the join span for the join with the specified key
+ ///
+ ///
+ ///
+ public uint GetJoinSpanForKey(string key)
+ {
+ return Joins.ContainsKey(key) ? Joins[key].JoinSpan : 0;
}
}
-
-
- [AttributeUsage(AttributeTargets.All)]
- public class JoinNameAttribute : CAttribute
- {
- private string _Name;
-
- public JoinNameAttribute(string name)
- {
- Debug.Console(2, "Setting Attribute Name: {0}", name);
- _Name = name;
- }
-
- public string Name
- {
- get { return _Name; }
- }
+ ///
+ /// Base class for join maps
+ ///
+ public abstract class JoinMapBaseAdvanced
+ {
+ protected uint JoinOffset;
+
+ ///
+ /// The collection of joins and associated metadata
+ ///
+ public Dictionary Joins { get; private set; }
+
+ protected JoinMapBaseAdvanced(uint joinStart)
+ {
+ Joins = new Dictionary();
+
+ JoinOffset = joinStart - 1;
+ }
+
+ protected JoinMapBaseAdvanced(uint joinStart, Type type):this(joinStart)
+ {
+ AddJoins(type);
+ }
+
+ protected void AddJoins(Type type)
+ {
+ // Add all the JoinDataComplete properties to the Joins Dictionary and pass in the offset
+ //Joins = this.GetType()
+ // .GetCType()
+ // .GetFields(BindingFlags.Public | BindingFlags.Instance)
+ // .Where(field => field.IsDefined(typeof(JoinNameAttribute), true))
+ // .Select(field => (JoinDataComplete)field.GetValue(this))
+ // .ToDictionary(join => join.GetNameAttribute(), join =>
+ // {
+ // join.SetJoinOffset(_joinOffset);
+ // return join;
+ // });
+
+ //type = this.GetType(); <- this wasn't working because 'this' was always the base class, never the derived class
+ var fields =
+ type.GetCType()
+ .GetFields(BindingFlags.Public | BindingFlags.Instance)
+ .Where(f => f.IsDefined(typeof (JoinNameAttribute), true));
+
+ foreach (var field in fields)
+ {
+ var childClass = Convert.ChangeType(this, type, null);
+
+ var value = field.GetValue(childClass) as JoinDataComplete; //this here is JoinMapBaseAdvanced, not the child class. JoinMapBaseAdvanced has no fields.
+
+ if (value == null)
+ {
+ Debug.Console(0, "Unable to caset base class to {0}", type.Name);
+ continue;
+ }
+
+ value.SetJoinOffset(JoinOffset);
+
+ var joinName = value.GetNameAttribute(field);
+
+ if (String.IsNullOrEmpty(joinName)) continue;
+
+ Joins.Add(joinName, value);
+ }
+
+
+ PrintJoinMapInfo();
+ }
+
+ ///
+ /// Prints the join information to console
+ ///
+ public void PrintJoinMapInfo()
+ {
+ Debug.Console(0, "{0}:\n", GetType().Name);
+
+ // Get the joins of each type and print them
+ Debug.Console(0, "Digitals:");
+ var digitals = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Digital) == eJoinType.Digital).ToDictionary(j => j.Key, j => j.Value);
+ Debug.Console(2, "Found {0} Digital Joins", digitals.Count);
+ PrintJoinList(GetSortedJoins(digitals));
+
+ Debug.Console(0, "Analogs:");
+ var analogs = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Analog) == eJoinType.Analog).ToDictionary(j => j.Key, j => j.Value);
+ Debug.Console(2, "Found {0} Analog Joins", analogs.Count);
+ PrintJoinList(GetSortedJoins(analogs));
+
+ Debug.Console(0, "Serials:");
+ var serials = Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Serial) == eJoinType.Serial).ToDictionary(j => j.Key, j => j.Value);
+ Debug.Console(2, "Found {0} Serial Joins", serials.Count);
+ PrintJoinList(GetSortedJoins(serials));
+
+ }
+
+ ///
+ /// Returns a sorted list by JoinNumber
+ ///
+ ///
+ ///
+ List> GetSortedJoins(Dictionary joins)
+ {
+ var sortedJoins = joins.ToList();
+
+ sortedJoins.Sort((pair1, pair2) => pair1.Value.JoinNumber.CompareTo(pair2.Value.JoinNumber));
+
+ return sortedJoins;
+ }
+
+ void PrintJoinList(List> joins)
+ {
+ foreach (var join in joins)
+ {
+ Debug.Console(0,
+ @"Join Number: {0} | JoinSpan: '{1}' | Label: '{2}' | Type: '{3}' | Capabilities: '{4}'",
+ join.Value.JoinNumber,
+ join.Value.JoinSpan,
+ join.Value.Metadata.Label,
+ join.Value.Metadata.JoinType.ToString(),
+ join.Value.Metadata.JoinCapabilities.ToString());
+ }
+ }
+
+ ///
+ /// Attempts to find the matching key for the custom join and if found overwrites the default JoinData with the custom
+ ///
+ ///
+ public void SetCustomJoinData(Dictionary joinData)
+ {
+ foreach (var customJoinData in joinData)
+ {
+ var join = Joins[customJoinData.Key];
+
+ if (join != null)
+ {
+ join.SetCustomJoinData(customJoinData.Value);
+ }
+ else
+ {
+ Debug.Console(2, "No mathcing key found in join map for: '{0}'", customJoinData.Key);
+ }
+ }
+
+ PrintJoinMapInfo();
+ }
+
+ /////
+ ///// Returns the join number for the join with the specified key
+ /////
+ /////
+ /////
+ //public uint GetJoinForKey(string key)
+ //{
+ // return Joins.ContainsKey(key) ? Joins[key].JoinNumber : 0;
+ //}
+
+
+ /////
+ ///// Returns the join span for the join with the specified key
+ /////
+ /////
+ /////
+ //public uint GetJoinSpanForKey(string key)
+ //{
+ // return Joins.ContainsKey(key) ? Joins[key].JoinSpan : 0;
+ //}
+ }
+
+ ///
+ /// Read = Provides feedback to SIMPL
+ /// Write = Responds to sig values from SIMPL
+ ///
+ [Flags]
+ public enum eJoinCapabilities
+ {
+ None = 0,
+ ToSIMPL = 1,
+ FromSIMPL = 2,
+ ToFromSIMPL = ToSIMPL | FromSIMPL
+ }
+
+ [Flags]
+ public enum eJoinType
+ {
+ None = 0,
+ Digital = 1,
+ Analog = 2,
+ Serial = 4,
+ DigitalAnalog = Digital | Analog,
+ DigitalSerial = Digital | Serial,
+ AnalogSerial = Analog | Serial,
+ DigitalAnalogSerial = Digital | Analog | Serial
+ }
+
+ ///
+ /// Metadata describing the join
+ ///
+ public class JoinMetadata
+ {
+ private string _description;
+
+ ///
+ /// Join number (based on join offset value)
+ ///
+ [JsonProperty("joinNumber")]
+ [Obsolete]
+ public uint JoinNumber { get; set; }
+ ///
+ /// Join range span. If join indicates the start of a range of joins, this indicated the maximum number of joins in the range
+ ///
+ [Obsolete]
+ [JsonProperty("joinSpan")]
+ public uint JoinSpan { get; set; }
+
+ ///
+ /// A label for the join to better describe its usage
+ ///
+ [Obsolete("Use Description instead")]
+ [JsonProperty("label")]
+ public string Label { get { return _description; } set { _description = value; } }
+
+ ///
+ /// A description for the join to better describe its usage
+ ///
+ [JsonProperty("description")]
+ public string Description { get { return _description; } set { _description = value; } }
+ ///
+ /// Signal type(s)
+ ///
+ [JsonProperty("joinType")]
+ public eJoinType JoinType { get; set; }
+ ///
+ /// Indicates whether the join is read and/or write
+ ///
+ [JsonProperty("joinCapabilities")]
+ public eJoinCapabilities JoinCapabilities { get; set; }
+ ///
+ /// Indicates a set of valid values (particularly if this translates to an enum
+ ///
+ [JsonProperty("validValues")]
+ public string[] ValidValues { get; set; }
+
+ }
+
+ ///
+ /// Data describing the join. Can be
+ ///
+ public class JoinData
+ {
+ ///
+ /// Join number (based on join offset value)
+ ///
+ [JsonProperty("joinNumber")]
+ public uint JoinNumber { get; set; }
+ ///
+ /// Join range span. If join indicates the start of a range of joins, this indicated the maximum number of joins in the range
+ ///
+ [JsonProperty("joinSpan")]
+ public uint JoinSpan { get; set; }
+ }
+
+ ///
+ /// A class to aggregate the JoinData and JoinMetadata for a join
+ ///
+ public class JoinDataComplete
+ {
+ private uint _joinOffset;
+
+ private JoinData _data;
+ public JoinMetadata Metadata { get; set; }
+
+ public JoinDataComplete(JoinData data, JoinMetadata metadata)
+ {
+ _data = data;
+ Metadata = metadata;
+ }
+
+ ///
+ /// Sets the join offset value
+ ///
+ ///
+ public void SetJoinOffset(uint joinOffset)
+ {
+ _joinOffset = joinOffset;
+ }
+
+ ///
+ /// The join number (including the offset)
+ ///
+ public uint JoinNumber
+ {
+ get { return _data.JoinNumber+ _joinOffset; }
+ set { _data.JoinNumber = value; }
+ }
+
+ public uint JoinSpan
+ {
+ get { return _data.JoinSpan; }
+ }
+
+ public void SetCustomJoinData(JoinData customJoinData)
+ {
+ _data = customJoinData;
+ }
+
+ public string GetNameAttribute(MemberInfo memberInfo)
+ {
+ var name = string.Empty;
+ var attribute = (JoinNameAttribute)CAttribute.GetCustomAttribute(memberInfo, typeof(JoinNameAttribute));
+
+ if (attribute == null) return name;
+
+ name = attribute.Name;
+ Debug.Console(2, "JoinName Attribute value: {0}", name);
+ return name;
+ }
+ }
+
+
+
+ [AttributeUsage(AttributeTargets.All)]
+ public class JoinNameAttribute : CAttribute
+ {
+ private string _Name;
+
+ public JoinNameAttribute(string name)
+ {
+ Debug.Console(2, "Setting Attribute Name: {0}", name);
+ _Name = name;
+ }
+
+ public string Name
+ {
+ get { return _Name; }
+ }
}
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj
index 55a157b4..f4eeabe5 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj
@@ -137,6 +137,7 @@
+
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj
index ba12a129..78a6e565 100644
--- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj
@@ -116,6 +116,8 @@
+
+
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/PartitionSensor/GlsPartitionSensorController.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/PartitionSensor/GlsPartitionSensorController.cs
new file mode 100644
index 00000000..256b2496
--- /dev/null
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/PartitionSensor/GlsPartitionSensorController.cs
@@ -0,0 +1,257 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharpPro;
+using Crestron.SimplSharpPro.DeviceSupport;
+using Crestron.SimplSharpPro.GeneralIO;
+using Newtonsoft.Json;
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Core.Config;
+using PepperDash.Essentials.Core.Bridges;
+using PepperDash_Essentials_Core.Bridges.JoinMaps;
+
+namespace PepperDash.Essentials.Devices.Common.PartitionSensor
+{
+ [Description("Wrapper class for GLS Cresnet Partition Sensor")]
+ public class GlsPartitionSensorController : CrestronGenericBridgeableBaseDevice
+ {
+ public GlsPartCn PartitionSensor { get; private set; }
+
+ public StringFeedback NameFeedback { get; private set; }
+
+ public BoolFeedback EnableFeedback { get; private set; }
+
+ public BoolFeedback PartitionSensedFeedback { get; private set; }
+ public BoolFeedback PartitionNotSensedFeedback { get; private set; }
+
+ public IntFeedback SensitivityFeedback { get; private set; }
+
+ public bool InTestMode { get; private set; }
+ public bool TestEnableFeedback { get; private set; }
+ public bool TestPartitionSensedFeedback { get; private set; }
+ public int TestSensitivityFeedback { get; private set; }
+
+ public Func NameFeedbackFunc
+ {
+ get { return () => Name; }
+ }
+
+ public Func EnableFeedbackFunc
+ {
+ get { return () => InTestMode ? TestEnableFeedback : PartitionSensor.EnableFeedback.BoolValue; }
+ }
+
+ public Func PartitionSensedFeedbackFunc
+ {
+ get { return () => InTestMode ? TestPartitionSensedFeedback : PartitionSensor.PartitionSensedFeedback.BoolValue; }
+ }
+
+ public Func PartitionNotSensedFeedbackFunc
+ {
+ get { return () => InTestMode ? TestPartitionSensedFeedback : PartitionSensor.PartitionNotSensedFeedback.BoolValue; }
+ }
+
+ public Func SensitivityFeedbackFunc
+ {
+ get { return () => InTestMode ? TestSensitivityFeedback : PartitionSensor.SensitivityFeedback.UShortValue; }
+ }
+
+ ///
+ /// Constructor
+ ///
+ ///
+ ///
+ ///
+ public GlsPartitionSensorController(string key, string name, GlsPartCn hardware)
+ : base(key, name, hardware)
+ {
+ PartitionSensor = hardware;
+
+ NameFeedback = new StringFeedback(NameFeedbackFunc);
+ EnableFeedback = new BoolFeedback(EnableFeedbackFunc);
+ PartitionSensedFeedback = new BoolFeedback(PartitionSensedFeedbackFunc);
+ PartitionNotSensedFeedback = new BoolFeedback(PartitionNotSensedFeedbackFunc);
+ SensitivityFeedback = new IntFeedback(SensitivityFeedbackFunc);
+
+ if (PartitionSensor != null) PartitionSensor.BaseEvent += PartitionSensor_BaseEvent;
+ }
+
+
+ private void PartitionSensor_BaseEvent(GenericBase device, BaseEventArgs args)
+ {
+ Debug.Console(2, this, "EventId: {0}, Index: {1}", args.EventId, args.Index);
+
+ switch (args.EventId)
+ {
+ case (GlsPartCn.EnableFeedbackEventId):
+ {
+ EnableFeedback.FireUpdate();
+ break;
+ }
+ case (GlsPartCn.PartitionSensedFeedbackEventId):
+ {
+ PartitionSensedFeedback.FireUpdate();
+ break;
+ }
+ case (GlsPartCn.PartitionNotSensedFeedbackEventId):
+ {
+ PartitionNotSensedFeedback.FireUpdate();
+ break;
+ }
+ case (GlsPartCn.SensitivityFeedbackEventId):
+ {
+ SensitivityFeedback.FireUpdate();
+ break;
+ }
+ default:
+ {
+ Debug.Console(2, this, "args.EventId: {0}", args.EventId);
+ break;
+ }
+ }
+ }
+
+ public void SetTestMode(bool mode)
+ {
+ InTestMode = mode;
+ Debug.Console(1, this, "InTestMode: {0}", InTestMode.ToString());
+ }
+
+ public void SetTestEnableState(bool state)
+ {
+ if (InTestMode)
+ {
+ TestEnableFeedback = state;
+ Debug.Console(1, this, "TestEnableFeedback: {0}", TestEnableFeedback.ToString());
+ return;
+ }
+
+ Debug.Console(1, this, "InTestMode: {0}, unable to set enable state: {1}", InTestMode.ToString(), state.ToString());
+ }
+
+ public void SetTestPartitionSensedState(bool state)
+ {
+ if (InTestMode)
+ {
+ TestPartitionSensedFeedback = state;
+ Debug.Console(1, this, "TestPartitionSensedFeedback: {0}", TestPartitionSensedFeedback.ToString());
+ return;
+ }
+
+ Debug.Console(1, this, "InTestMode: {0}, unable to set partition state: {1}", InTestMode.ToString(), state.ToString());
+ }
+
+ public void SetTestSensitivityValue(int value)
+ {
+ if (InTestMode)
+ {
+ TestSensitivityFeedback = value;
+ Debug.Console(1, this, "TestSensitivityFeedback: {0}", TestSensitivityFeedback);
+ return;
+ }
+
+ Debug.Console(1, this, "InTestMode: {0}, unable to set sensitivity value: {1}", InTestMode.ToString(), value);
+ }
+
+ public void SetEnableState(bool state)
+ {
+ if (PartitionSensor == null)
+ return;
+
+ PartitionSensor.Enable.BoolValue = state;
+ }
+
+ public void IncreaseSensitivity()
+ {
+ if (PartitionSensor == null)
+ return;
+
+ PartitionSensor.IncreaseSensitivity();
+ }
+
+ public void DecreaseSensitivity()
+ {
+ if (PartitionSensor == null)
+ return;
+
+ PartitionSensor.DecreaseSensitivity();
+ }
+
+ public void SetSensitivity(ushort value)
+ {
+ if (PartitionSensor == null)
+ return;
+
+ PartitionSensor.Sensitivity.UShortValue = (ushort)value;
+ }
+
+
+ public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
+ {
+ var joinMap = new GlsPartitionSensorJoinMap(joinStart);
+ var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
+
+ if (!string.IsNullOrEmpty(joinMapSerialized))
+ joinMap = JsonConvert.DeserializeObject(joinMapSerialized);
+
+ if (bridge != null)
+ {
+ bridge.AddJoinMap(Key, joinMap);
+ }
+ else
+ {
+ Debug.Console(0, this, "Please update config to use 'type': 'EiscApiAdvanced' to get all join map features for this device");
+ }
+
+ Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
+ Debug.Console(0, this, "Linking to Bridge Type {0}", GetType().Name);
+
+ // link input from simpl
+ trilist.SetSigTrueAction(joinMap.Enable.JoinNumber, () => SetEnableState(true));
+ trilist.SetSigFalseAction(joinMap.Enable.JoinNumber, () => SetEnableState(false));
+ trilist.SetSigTrueAction(joinMap.IncreaseSensitivity.JoinNumber, IncreaseSensitivity);
+ trilist.SetSigTrueAction(joinMap.DecreaseSensitivity.JoinNumber, DecreaseSensitivity);
+ trilist.SetUShortSigAction(joinMap.Sensitivity.JoinNumber, SetSensitivity);
+
+ // link output to simpl
+ IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
+ EnableFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Enable.JoinNumber]);
+ PartitionSensedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionSensed.JoinNumber]);
+ PartitionNotSensedFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PartitionNotSensed.JoinNumber]);
+ SensitivityFeedback.LinkInputSig(trilist.UShortInput[joinMap.Sensitivity.JoinNumber]);
+
+ FeedbacksFireUpdates();
+
+ // update when device is online
+ PartitionSensor.OnlineStatusChange += (o, a) =>
+ {
+ if (a.DeviceOnLine)
+ {
+ FeedbacksFireUpdates();
+ }
+ };
+
+ // update when trilist is online
+ trilist.OnlineStatusChange += (o, a) =>
+ {
+ if (a.DeviceOnLine)
+ {
+ FeedbacksFireUpdates();
+ }
+ };
+ }
+
+ private void FeedbacksFireUpdates()
+ {
+ IsOnline.FireUpdate();
+ NameFeedback.FireUpdate();
+ EnableFeedback.FireUpdate();
+ PartitionSensedFeedback.FireUpdate();
+ PartitionNotSensedFeedback.FireUpdate();
+ SensitivityFeedback.FireUpdate();
+ }
+ }
+}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/PartitionSensor/GlsPartitionSensorControllerFactory.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/PartitionSensor/GlsPartitionSensorControllerFactory.cs
new file mode 100644
index 00000000..543fc799
--- /dev/null
+++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/PartitionSensor/GlsPartitionSensorControllerFactory.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharpPro.GeneralIO;
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Core.Config;
+using PepperDash.Essentials.Devices.Common.Occupancy;
+
+namespace PepperDash.Essentials.Devices.Common.PartitionSensor
+{
+ public class GlsPartitionSensorControllerFactory : EssentialsDeviceFactory
+ {
+ public GlsPartitionSensorControllerFactory()
+ {
+ TypeNames = new List() { "glspartcn" };
+ }
+
+ public override EssentialsDevice BuildDevice(DeviceConfig dc)
+ {
+ Debug.Console(2, "Factory Attempting to create new GLS-PART-CN Device");
+
+ var typeName = dc.Type.ToLower();
+ var key = dc.Key;
+ var name = dc.Name;
+ var comm = CommFactory.GetControlPropertiesConfig(dc);
+ if (comm == null)
+ {
+ Debug.Console(0, "ERROR: Control Properties Config are null");
+ return null;
+ }
+
+ var sensor = new GlsPartCn(comm.CresnetIdInt, Global.ControlSystem);
+ return new GlsPartitionSensorController(dc.Key, dc.Name, sensor);
+ }
+ }
+}
\ No newline at end of file