diff --git a/src/PasswordManagement/Config.cs b/src/PasswordManagement/Config.cs
deleted file mode 100644
index 22aa488..0000000
--- a/src/PasswordManagement/Config.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Crestron.SimplSharp;
-
-namespace PepperDash.Core.PasswordManagement
-{
- ///
- /// JSON password configuration
- ///
- public class PasswordConfig
- {
- ///
- /// Password object configured password
- ///
- public string password { get; set; }
- ///
- /// Constructor
- ///
- public PasswordConfig()
- {
-
- }
- }
-}
\ No newline at end of file
diff --git a/src/PasswordManagement/OLD-ARRAY-Config.cs b/src/PasswordManagement/OLD-ARRAY-Config.cs
deleted file mode 100644
index 8167c4f..0000000
--- a/src/PasswordManagement/OLD-ARRAY-Config.cs
+++ /dev/null
@@ -1,149 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Crestron.SimplSharp;
-
-namespace PepperDash.Core.PasswordManagement
-{
- // Example JSON password array configuration object
- //{
- // "global":{
- // "passwords":[
- // {
- // "key": "Password01",
- // "name": "Technician Password",
- // "enabled": true,
- // "password": "1988"
- // }
- // ]
- // }
- //}
-
- ///
- /// JSON password array configuration object
- ///
- //public class PasswordConfig
- //{
- // ///
- // /// Key used to search for object in JSON array
- // ///
- // public string key { get; set; }
- // ///
- // /// Friendly name of password object
- // ///
- // public string name { get; set; }
- // ///
- // /// Password object enabled
- // ///
- // public bool enabled { get; set; }
- // ///
- // ///
- // ///
- // public ushort simplEnabled
- // {
- // get { return (ushort)(enabled ? 1 : 0); }
- // set { enabled = Convert.ToBoolean(value); }
- // }
- // ///
- // /// Password object configured password
- // ///
- // public string password { get; set; }
- // ///
- // /// Password type
- // ///
- // private int type { get; set; }
- // ///
- // /// Password Type for S+
- // ///
- // public ushort simplType
- // {
- // get { return Convert.ToUInt16(type); }
- // set { type = value; }
- // }
- // ///
- // /// Password path
- // /// **FUTURE** implementation of saving passwords recieved from Fusion or other external sources back to config
- // ///
- // public string path { get; set; }
- // ///
- // /// Constructor
- // ///
- // public PasswordConfig()
- // {
- // simplEnabled = 0;
- // simplType = 0;
- // }
- //}
-
- // Example JSON password collections configuration object
- //{
- // "global": {
- // "passwords": {
- // "1": {
- // "name": "Technician Password",
- // "password": "2468"
- // },
- // "2": {
- // "name": "System Password",
- // "password": "123456"
- // },
- // "3": {
- // "name": "Master Password",
- // "password": "abc123"
- // },
- // "5": {
- // "name": "Backdoor Password",
- // "password": "1988"
- // },
- // "10": {
- // "name": "Backdoor Password",
- // "password": "1988"
- // }
- // }
- // }
- //}
-
- ///
- /// JSON password array configuration object
- ///
- public class PasswordConfig
- {
- ///
- /// Password object configured password
- ///
- public string password { get; set; }
- ///
- /// Constructor
- ///
- public PasswordConfig()
- {
-
- }
- }
-
- ///
- /// Global JSON object
- ///
- //public class GlobalConfig
- //{
- // //public List passwords { get; set; }
- // public Dictionary passwords { get; set; }
-
- // ///
- // /// Constructor
- // ///
- // public GlobalConfig()
- // {
-
- // }
- //}
-
- ///
- /// Root JSON object
- ///
- //public class RootObject
- //{
- // public GlobalConfig global { get; set; }
- //}
-}
\ No newline at end of file
diff --git a/src/PasswordManagement/OLD-ARRAY-PasswordClient.cs b/src/PasswordManagement/OLD-ARRAY-PasswordClient.cs
deleted file mode 100644
index 540d935..0000000
--- a/src/PasswordManagement/OLD-ARRAY-PasswordClient.cs
+++ /dev/null
@@ -1,207 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Crestron.SimplSharp;
-
-namespace PepperDash.Core.PasswordManagement
-{
- public class PasswordClient
- {
- ///
- /// Password Client
- ///
- public PasswordConfig Client { get; set; }
- ///
- /// Used to build the password entered by the user
- ///
- public string PasswordToValidate { get; set; }
-
- ///
- /// Boolean event
- ///
- public event EventHandler BoolChange;
- ///
- /// Ushort event
- ///
- public event EventHandler UshrtChange;
- ///
- /// String event
- ///
- public event EventHandler StringChange;
-
- ///
- /// Constructor
- ///
- public PasswordClient()
- {
-
- }
-
- ///
- /// Initialize method
- ///
- ///
- public void Initialize(string key)
- {
- OnBoolChange(false, 0, PasswordManagementConstants.BoolEvaluatedChange);
-
- Client = new PasswordConfig();
- PasswordToValidate = "";
-
- // there has to be a better way to get the index of the current index of password
- ushort i = 0;
- foreach (var password in PasswordManager.Passwords)
- {
- i++;
- OnUshrtChange((ushort)password.Key, (ushort)password.Key, PasswordManagementConstants.PasswordKey);
- }
-
- OnBoolChange(true, 0, PasswordManagementConstants.BoolEvaluatedChange);
- }
-
- ///
- /// Retrieves password by key
- ///
- ///
- //public void GetPasswordByKey(string key)
- //{
- // if (string.IsNullOrEmpty(key))
- // {
- // Debug.Console(1, "PassowrdClient.GetPasswordByKey failed:\rKey {0} is null or empty", key);
- // return;
- // }
-
- // PasswordConfig password = PasswordManager.Passwords.FirstOrDefault(p => p.key.Equals(key));
- // if (password == null)
- // {
- // OnUshrtChange(0, 0, PasswordManagementConstants.SelectedPasswordLength);
- // return;
- // }
-
- // Client = password;
- // OnUshrtChange((ushort)Client.password.Length, 0, PasswordManagementConstants.SelectedPasswordLength);
- // OnStringChange(Client.key, 0, PasswordManagementConstants.PasswordKeySelected);
- //}
-
- ///
- /// Retrieve password by index
- ///
- ///
- public void GetPasswordByIndex(ushort key)
- {
- PasswordConfig pw = PasswordManager.Passwords[key];
- if (pw == null)
- {
- OnUshrtChange(0, 0, PasswordManagementConstants.SelectedPasswordLength);
- return;
- }
-
- Client = pw;
- OnUshrtChange((ushort)Client.password.Length, 0, PasswordManagementConstants.SelectedPasswordLength);
- OnUshrtChange(key, 0, PasswordManagementConstants.PasswordKeySelected);
- }
-
- ///
- /// Password validation method
- ///
- ///
- public void ValidatePassword(string password)
- {
- if (string.IsNullOrEmpty(password))
- return;
-
- if (string.Equals(Client.password, password))
- {
- OnBoolChange(true, 0, PasswordManagementConstants.PasswordIsValid);
- }
- else
- {
- OnBoolChange(true, 0, PasswordManagementConstants.PasswordIsInvalid);
- }
-
-
- OnBoolChange(false, 0, PasswordManagementConstants.PasswordIsValid);
- OnBoolChange(false, 0, PasswordManagementConstants.PasswordIsInvalid);
-
- ClearPassword();
- }
-
- ///
- /// Builds the user entered passwrod string, will attempt to validate the user entered
- /// password against the selected password when the length of the 2 are equal
- ///
- ///
- public void BuildPassword(string data)
- {
- PasswordToValidate = String.Concat(PasswordToValidate, data);
- OnBoolChange(true, (ushort)PasswordToValidate.Length, PasswordManagementConstants.PasswordLedChange);
-
- if (PasswordToValidate.Length == Client.password.Length)
- ValidatePassword(PasswordToValidate);
- }
-
- ///
- /// Clears the user entered password and resets the LEDs
- ///
- public void ClearPassword()
- {
- PasswordToValidate = "";
- OnBoolChange(true, (ushort)PasswordToValidate.Length, PasswordManagementConstants.PasswordLedChange);
-
- for(var i = 1; i <= Client.password.Length; i++)
- OnBoolChange(false, (ushort)i, PasswordManagementConstants.PasswordLedChange);
- }
-
- ///
- /// Protected boolean change event handler
- ///
- ///
- ///
- ///
- protected void OnBoolChange(bool state, ushort index, ushort type)
- {
- var handler = BoolChange;
- if (handler != null)
- {
- var args = new BoolChangeEventArgs(state, type);
- args.Index = index;
- BoolChange(this, args);
- }
- }
-
- ///
- /// Protected ushort change event handler
- ///
- ///
- ///
- ///
- protected void OnUshrtChange(ushort value, ushort index, ushort type)
- {
- var handler = UshrtChange;
- if (handler != null)
- {
- var args = new UshrtChangeEventArgs(value, type);
- args.Index = index;
- UshrtChange(this, args);
- }
- }
-
- ///
- /// Protected string change event handler
- ///
- ///
- ///
- ///
- protected void OnStringChange(string value, ushort index, ushort type)
- {
- var handler = StringChange;
- if (handler != null)
- {
- var args = new StringChangeEventArgs(value, type);
- args.Index = index;
- StringChange(this, args);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/PasswordManagement/OLD-ARRAY-PasswordManager.cs b/src/PasswordManagement/OLD-ARRAY-PasswordManager.cs
deleted file mode 100644
index 45b65e9..0000000
--- a/src/PasswordManagement/OLD-ARRAY-PasswordManager.cs
+++ /dev/null
@@ -1,233 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using Crestron.SimplSharp;
-using PepperDash.Core.JsonToSimpl;
-using PepperDash.Core.JsonStandardObjects;
-
-namespace PepperDash.Core.PasswordManagement
-{
- public class PasswordManager
- {
- ///
- /// List of passwords configured
- ///
- public static Dictionary Passwords = new Dictionary();
- private Dictionary TempPasswords = new Dictionary();
-
- CTimer UpdateTimer;
- public long UpdateTimerElapsedMs = 5000;
-
- ///
- /// Boolean event
- ///
- public event EventHandler BoolChange;
- ///
- /// Ushort event
- ///
- public event EventHandler UshrtChange;
- ///
- /// String event
- ///
- public event EventHandler StringChange;
-
-
- ///
- /// Constructor
- ///
- public PasswordManager()
- {
- Passwords.Clear();
- }
-
- ///
- /// Initialize method
- ///
- ///
- ///
- //public void Initialize(string uniqueId, string key)
- //{
- // OnBoolChange(false, 0, PasswordManagementConstants.BoolEvaluatedChange);
-
- // try
- // {
- // if(string.IsNullOrEmpty(uniqueId) || string.IsNullOrEmpty(key))
- // {
- // Debug.Console(1, "PasswordManager.Initialize({0}, {1}) null or empty parameters", uniqueId, key);
- // return;
- // }
-
- // JsonToSimplMaster master = J2SGlobal.GetMasterByFile(uniqueId);
- // if(master == null)
- // {
- // Debug.Console(1, "PassowrdManager.Initialize failed:\rCould not find JSON file with uniqueID {0}", uniqueId);
- // return;
- // }
-
- // var global = master.JsonObject.ToObject().global;
- // var passwords = global.passwords;
- // if(passwords == null)
- // {
- // Debug.Console(1, "PasswordManager.Initialize failed:\rCould not find password object");
- // return;
- // }
-
- // foreach(var password in passwords)
- // {
- // if (password != null)
- // {
- // var index = passwords.IndexOf(password);
-
- // password.path = string.Format("global.passwords[{0}]", index);
- // Debug.Console(1, "PasswordManager.Initialize: {0}, {1}, {2}, {3}, {4}, {5}", password.key, password.name, password.simplEnabled, password.simplType, password.password, password.path);
- // //AddPassword(password);
-
- // OnStringChange(password.path, (ushort)index, PasswordManagementConstants.FullPathToPassword);
- // OnStringChange(password.key, (ushort)index, PasswordManagementConstants.PasswordKey);
- // }
- // }
-
- // OnUshrtChange(Convert.ToUInt16(Passwords.Count), 0, PasswordManagementConstants.PasswordListCount);
- // }
- // catch(Exception e)
- // {
- // var msg = string.Format("PasswordManager.Initialize({0}, {1}) failed:\r{2}", uniqueId, key, e.Message);
- // CrestronConsole.PrintLine(msg);
- // ErrorLog.Error(msg);
- // }
- // finally
- // {
- // OnBoolChange(true, 0, PasswordManagementConstants.BoolEvaluatedChange);
- // }
- //}
-
- ///
- /// Adds password to the list
- ///
- ///
- //private void AddPassword(PasswordConfig password)
- //{
- // if (password == null)
- // return;
-
- // var item = Passwords.FirstOrDefault(i => i.key.Equals(password.key));
- // if (item != null)
- // Passwords.Remove(item);
- // Passwords.Add(password);
-
- // Passwords.Sort((x, y) => string.Compare(x.key, y.key));
- //}
-
- ///
- /// Removes password from the list
- ///
- ///
- //private void RemovePassword(PasswordConfig password)
- //{
- // if (password == null)
- // return;
-
- // var item = Passwords.FirstOrDefault(i => i.key.Equals(password.key));
- // if (item != null)
- // Passwords.Remove(item);
- //}
-
- ///
- /// Updates password stored in the dictonary
- ///
- ///
- ///
- ///
- public void UpdatePassword(ushort key, string password)
- {
- if (string.IsNullOrEmpty(password))
- return;
-
- var pw = TempPasswords[key];
- if (pw == null)
- {
- pw = new PasswordConfig();
- }
- pw.password = password;
-
- if (UpdateTimer == null)
- {
- // (o) => SavePasswords removes the need to create a callback method that takes in an object
- UpdateTimer = new CTimer((o) => StorePassword(), UpdateTimerElapsedMs);
- }
- else
- {
- UpdateTimer.Reset();
- }
- }
-
- ///
- /// Stores the updated passwords in TempPassword in the Passwords dictionary
- ///
- private void StorePassword()
- {
- UpdateTimer.Stop();
-
- foreach (var tempPw in TempPasswords)
- {
- Passwords[tempPw.Key] = tempPw.Value;
- }
-
- TempPasswords.Clear();
- }
-
- ///
- /// Protected boolean change event handler
- ///
- ///
- ///
- ///
- protected void OnBoolChange(bool state, ushort index, ushort type)
- {
- var handler = BoolChange;
- if (handler != null)
- {
- var args = new BoolChangeEventArgs(state, type);
- args.Index = index;
- BoolChange(this, args);
- }
- }
-
- ///
- /// Protected ushort change event handler
- ///
- ///
- ///
- ///
- protected void OnUshrtChange(ushort value, ushort index, ushort type)
- {
- var handler = UshrtChange;
- if (handler != null)
- {
- var args = new UshrtChangeEventArgs(value, type);
- args.Index = index;
- UshrtChange(this, args);
- }
- }
-
- ///
- /// Protected string change event handler
- ///
- ///
- ///
- ///
- protected void OnStringChange(string value, ushort index, ushort type)
- {
- var handler = StringChange;
- if (handler != null)
- {
- var args = new StringChangeEventArgs(value, type);
- args.Index = index;
- StringChange(this, args);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/PasswordManagement/PasswordClient.cs b/src/PasswordManagement/PasswordClient.cs
index 2d66c52..dcb81c2 100644
--- a/src/PasswordManagement/PasswordClient.cs
+++ b/src/PasswordManagement/PasswordClient.cs
@@ -1,7 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Core.PasswordManagement
@@ -11,14 +8,16 @@ namespace PepperDash.Core.PasswordManagement
///
public class PasswordClient
{
+ ///
+ /// Password selected key
+ ///
+ public string Username { get; set; }
+
///
/// Password selected
///
public string Password { get; set; }
- ///
- /// Password selected key
- ///
- public ushort Key { get; set; }
+
///
/// Used to build the password entered by the user
///
@@ -42,7 +41,11 @@ namespace PepperDash.Core.PasswordManagement
///
public PasswordClient()
{
- PasswordManager.PasswordChange += new EventHandler(PasswordManager_PasswordChange);
+ PasswordManager.Initialized += (sender, args) => Initialize();
+ PasswordManager.PasswordChange += PasswordManager_PasswordChange;
+
+ if (PasswordManager.IsInitialized)
+ Initialize();
}
///
@@ -50,52 +53,108 @@ namespace PepperDash.Core.PasswordManagement
///
public void Initialize()
{
- OnBoolChange(false, 0, PasswordManagementConstants.PasswordInitializedChange);
+ OnBoolChange(false, 0, PasswordConstants.Initialized);
- Password = "";
- PasswordToValidate = "";
+ Username = string.Empty;
+ Password = string.Empty;
+ PasswordToValidate = string.Empty;
- OnUshrtChange((ushort)PasswordManager.Passwords.Count, 0, PasswordManagementConstants.PasswordManagerCountChange);
- OnBoolChange(true, 0, PasswordManagementConstants.PasswordInitializedChange);
+ OnUshrtChange((ushort)PasswordManager.Passwords.Count, 0, PasswordConstants.Count);
+ OnUshrtChange(0, 0, PasswordConstants.PasswordLength);
+ OnStringChange(string.Empty, 0, PasswordConstants.UsernameValidated);
+ OnStringChange("Password client initilaized", 0, PasswordConstants.Message);
+ OnBoolChange(true, 0, PasswordConstants.Initialized);
}
///
- /// Retrieve password by index
+ /// Sends clear/0 values to S+ wrapper
///
- ///
- public void GetPasswordByIndex(ushort key)
+ public void ClearOutputs()
{
- OnUshrtChange((ushort)PasswordManager.Passwords.Count, 0, PasswordManagementConstants.PasswordManagerCountChange);
+ //OnBoolChange(false, 0, PasswordConstants.UsernameValidated);
+ OnUshrtChange(0, 0, PasswordConstants.PasswordLength);
+ OnStringChange(string.Empty, 0, PasswordConstants.UsernameValidated);
+ OnStringChange(string.Empty, 0, PasswordConstants.Message);
+ }
- Key = key;
+ ///
+ /// Sends clear/0 values to S+ wrapper
+ ///
+ ///
+ public void UpdateOutputs(PasswordValidationResult result)
+ {
+ OnBoolChange(result.IsValid, 0, PasswordConstants.UsernameValidated);
+ OnUshrtChange((ushort)(string.IsNullOrEmpty(result.Password) ? 0 : result.Password.Length), 0, PasswordConstants.PasswordLength);
+ OnStringChange(string.Empty, 0, PasswordConstants.UsernameValidated);
+ OnStringChange(result.Message, 0, PasswordConstants.Message);
+ }
- var pw = PasswordManager.Passwords[Key];
- if (pw == null)
+ ///
+ /// Validate username
+ ///
+ ///
+ public void ValidateUsername(string username)
+ {
+ if (string.IsNullOrEmpty(username))
{
- OnUshrtChange(0, 0, PasswordManagementConstants.PasswordLengthChange);
+ OnStringChange("Username is null or empty", 0, PasswordConstants.Message);
return;
}
- Password = pw;
- OnUshrtChange((ushort)Password.Length, 0, PasswordManagementConstants.PasswordLengthChange);
- OnUshrtChange(key, 0, PasswordManagementConstants.PasswordSelectIndexChange);
- }
+ var result = PasswordManager.ValidateUsername(username);
+ if (!result.IsValid)
+ {
+ UpdateOutputs(result);
+ return;
+ }
+
+ Username = username;
+ Password = result.Password;
+ PasswordToValidate = string.Empty;
+
+ OnStringChange(Username, 0, PasswordConstants.UsernameValidated);
+ OnBoolChange(result.IsValid, 0, PasswordConstants.UsernameValidated);
+ OnUshrtChange((ushort)result.Password.Length, 0, PasswordConstants.PasswordLength);
+ OnStringChange(result.Message, 0, PasswordConstants.Message);
+ }
///
- /// Password validation method
+ /// Validate username and passowrd
///
+ ///
///
- public void ValidatePassword(string password)
+ public void ValidateUsernameAndPassword(string username, string password)
{
- if (string.IsNullOrEmpty(password))
+ if (string.IsNullOrEmpty(username))
+ {
+ OnStringChange("Username is null or empty", 0, PasswordConstants.Message);
return;
+ }
- if (string.Equals(Password, password))
- OnBoolChange(true, 0, PasswordManagementConstants.PasswordValidationChange);
- else
- OnBoolChange(false, 0, PasswordManagementConstants.PasswordValidationChange);
+ if (string.IsNullOrEmpty(password))
+ {
+ OnStringChange("Password is null or empty", 0, PasswordConstants.Message);
+ return;
+ }
- ClearPassword();
+ var result = PasswordManager.ValidateUsernameAndPassword(username, password);
+ if (!result.IsValid)
+ {
+ UpdateOutputs(result);
+ return;
+ }
+
+ OnBoolChange(result.IsValid, 0, PasswordConstants.PasswordValidated);
+ OnStringChange(result.Message, 0, PasswordConstants.Message);
+
+ // Clear entered password and reset outputs after a delay (make configurable as needed)
+ const long clearDelayMs = 5000;
+
+ new CTimer(_ =>
+ {
+ ClearPassword();
+ ClearOutputs();
+ }, clearDelayMs);
}
///
@@ -106,10 +165,22 @@ namespace PepperDash.Core.PasswordManagement
public void BuildPassword(string data)
{
PasswordToValidate = String.Concat(PasswordToValidate, data);
- OnBoolChange(true, (ushort)PasswordToValidate.Length, PasswordManagementConstants.PasswordLedFeedbackChange);
+ OnBoolChange(true, (ushort)PasswordToValidate.Length, PasswordConstants.LedFeedback);
- if (PasswordToValidate.Length == Password.Length)
- ValidatePassword(PasswordToValidate);
+ if (string.IsNullOrEmpty(Password))
+ {
+ OnStringChange("Cannot validate password, password is null or empty", 0, PasswordConstants.Message);
+ return;
+ }
+ if (PasswordToValidate.Length != Password.Length) return;
+
+ if (string.IsNullOrEmpty(Username))
+ {
+ OnStringChange("Cannot validate password, username is null or empty", 0, PasswordConstants.Message);
+ return;
+ }
+
+ ValidateUsernameAndPassword(Username, PasswordToValidate);
}
///
@@ -117,8 +188,8 @@ namespace PepperDash.Core.PasswordManagement
///
public void ClearPassword()
{
- PasswordToValidate = "";
- OnBoolChange(false, (ushort)PasswordToValidate.Length, PasswordManagementConstants.PasswordLedFeedbackChange);
+ PasswordToValidate = string.Empty;
+ OnBoolChange(true, (ushort)PasswordToValidate.Length, PasswordConstants.LedFeedback);
}
///
@@ -126,12 +197,23 @@ namespace PepperDash.Core.PasswordManagement
///
public void DeletePasswordCharacter()
{
- ushort PasswordLengthBeforeDelete = (ushort)PasswordToValidate.Length;
- PasswordToValidate = PasswordToValidate.Substring(0, PasswordToValidate.Length - 1);
- OnBoolChange(false, (ushort)PasswordLengthBeforeDelete, PasswordManagementConstants.PasswordLedFeedbackChange);
- // Verify if OnStringChange is needed to update the S+ wrapper with the entered PasswordToValidate
+ if (string.IsNullOrEmpty(PasswordToValidate))
+ return;
+
+ var previousLength = (ushort)PasswordToValidate.Length;
+
+ // Remove last entered character
+ PasswordToValidate = PasswordToValidate.Substring(0, PasswordToValidate.Length - 1);
+
+ // Turn off the last LED that was on (old length index)
+ OnBoolChange(false, previousLength, PasswordConstants.LedFeedback);
+
+ // Send updated length back to S+
+ OnUshrtChange((ushort)PasswordToValidate.Length, 0, PasswordConstants.PasswordLength);
}
+ #region event handlers
+
///
/// Protected boolean change event handler
///
@@ -141,12 +223,10 @@ namespace PepperDash.Core.PasswordManagement
protected void OnBoolChange(bool state, ushort index, ushort type)
{
var handler = BoolChange;
- if (handler != null)
- {
- var args = new BoolChangeEventArgs(state, type);
- args.Index = index;
- BoolChange(this, args);
- }
+ if (handler == null) return;
+
+ var args = new BoolChangeEventArgs(state, type) {Index = index};
+ BoolChange(this, args);
}
///
@@ -158,12 +238,10 @@ namespace PepperDash.Core.PasswordManagement
protected void OnUshrtChange(ushort value, ushort index, ushort type)
{
var handler = UshrtChange;
- if (handler != null)
- {
- var args = new UshrtChangeEventArgs(value, type);
- args.Index = index;
- UshrtChange(this, args);
- }
+ if (handler == null) return;
+
+ var args = new UshrtChangeEventArgs(value, type) {Index = index};
+ UshrtChange(this, args);
}
///
@@ -175,12 +253,20 @@ namespace PepperDash.Core.PasswordManagement
protected void OnStringChange(string value, ushort index, ushort type)
{
var handler = StringChange;
- if (handler != null)
- {
- var args = new StringChangeEventArgs(value, type);
- args.Index = index;
- StringChange(this, args);
- }
+ if (handler == null) return;
+
+ var args = new StringChangeEventArgs(value, type) { Index = index };
+ StringChange(this, args);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected void PasswordManager_Initialized(object sender, BoolChangeEventArgs args)
+ {
+ Initialize();
}
///
@@ -190,13 +276,12 @@ namespace PepperDash.Core.PasswordManagement
///
protected void PasswordManager_PasswordChange(object sender, StringChangeEventArgs args)
{
- //throw new NotImplementedException();
- if (Key == args.Index)
- {
- //PasswordSelectedKey = args.Index;
- //PasswordSelected = args.StringValue;
- GetPasswordByIndex(args.Index);
+ if (Username == args.StringValue && args.Type == PasswordConstants.PasswordUpdated)
+ {
+ // TODO - If the current username password changes, do something
}
}
+
+ #endregion
}
}
\ No newline at end of file
diff --git a/src/PasswordManagement/PasswordConfig.cs b/src/PasswordManagement/PasswordConfig.cs
new file mode 100644
index 0000000..1a2c823
--- /dev/null
+++ b/src/PasswordManagement/PasswordConfig.cs
@@ -0,0 +1,24 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+
+namespace PepperDash.Core.PasswordManagement
+{
+ ///
+ /// JSON password configuration
+ ///
+ public class PasswordConfig
+ {
+ ///
+ /// Dictionary of user passwords. Key is the username, value is the password
+ ///
+ [JsonProperty("passwords")]
+ public Dictionary Passwords { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ public PasswordConfig()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/PasswordManagement/Constants.cs b/src/PasswordManagement/PasswordConstants.cs
similarity index 52%
rename from src/PasswordManagement/Constants.cs
rename to src/PasswordManagement/PasswordConstants.cs
index 65a1bf4..25e14b4 100644
--- a/src/PasswordManagement/Constants.cs
+++ b/src/PasswordManagement/PasswordConstants.cs
@@ -1,57 +1,73 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Crestron.SimplSharp;
-
-namespace PepperDash.Core.PasswordManagement
-{
- ///
- /// Constants
- ///
- public class PasswordManagementConstants
- {
- ///
- /// Generic boolean value change constant
- ///
- public const ushort BoolValueChange = 1;
- ///
- /// Evaluated boolean change constant
- ///
- public const ushort PasswordInitializedChange = 2;
- ///
- /// Update busy change const
- ///
- public const ushort PasswordUpdateBusyChange = 3;
- ///
- /// Password is valid change constant
- ///
- public const ushort PasswordValidationChange = 4;
- ///
- /// Password LED change constant
- ///
- public const ushort PasswordLedFeedbackChange = 5;
-
- ///
- /// Generic ushort value change constant
- ///
- public const ushort UshrtValueChange = 101;
- ///
- /// Password count
- ///
- public const ushort PasswordManagerCountChange = 102;
- ///
- /// Password selecte index change constant
- ///
- public const ushort PasswordSelectIndexChange = 103;
- ///
- /// Password length
- ///
- public const ushort PasswordLengthChange = 104;
-
- ///
- /// Generic string value change constant
- ///
- public const ushort StringValueChange = 201;
- }
+
+namespace PepperDash.Core.PasswordManagement
+{
+ ///
+ /// Constants
+ ///
+ public class PasswordConstants
+ {
+ ///
+ /// Generic boolean value change constant
+ ///
+ public const ushort BoolValueChange = 1;
+
+ ///
+ /// Evaluated boolean change constant
+ ///
+ public const ushort Initialized = 2;
+
+ ///
+ /// Update busy change const
+ ///
+ public const ushort UpdateBusy = 3;
+
+ ///
+ /// Username is valid change constant
+ ///
+ public const ushort UsernameValidated = 4;
+
+ ///
+ /// Password is valid change constant
+ ///
+ public const ushort PasswordValidated = 5;
+
+ ///
+ /// Password LED change constant
+ ///
+ public const ushort LedFeedback = 6;
+
+
+
+ ///
+ /// Generic ushort value change constant
+ ///
+ public const ushort UshrtValueChange = 101;
+
+ ///
+ /// Password count
+ ///
+ public const ushort Count = 102;
+
+ ///
+ /// Password length
+ ///
+ public const ushort PasswordLength = 104;
+
+
+
+ ///
+ /// Generic string value change constant
+ ///
+ public const ushort StringValueChange = 201;
+
+ ///
+ /// Password message constant, used to send the password string to clients when a password is updated
+ ///
+ public const ushort Message = 202;
+
+ ///
+ /// Password updated
+ ///
+ public const ushort PasswordUpdated = 203;
+ }
}
\ No newline at end of file
diff --git a/src/PasswordManagement/PasswordManager.cs b/src/PasswordManagement/PasswordManager.cs
index 8c8f1b7..1dee71b 100644
--- a/src/PasswordManagement/PasswordManager.cs
+++ b/src/PasswordManagement/PasswordManager.cs
@@ -1,247 +1,285 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using Crestron.SimplSharp;
-using PepperDash.Core.JsonToSimpl;
-using PepperDash.Core.JsonStandardObjects;
-
-namespace PepperDash.Core.PasswordManagement
-{
- ///
- /// Allows passwords to be stored and managed
- ///
- public class PasswordManager
- {
- ///
- /// Public dictionary of known passwords
- ///
- public static Dictionary Passwords = new Dictionary();
- ///
- /// Private dictionary, used when passwords are updated
- ///
- private Dictionary _passwords = new Dictionary();
-
- ///
- /// Timer used to wait until password changes have stopped before updating the dictionary
- ///
- CTimer PasswordTimer;
- ///
- /// Timer length
- ///
- public long PasswordTimerElapsedMs = 5000;
-
- ///
- /// Boolean event
- ///
- public event EventHandler BoolChange;
- ///
- /// Ushort event
- ///
- public event EventHandler UshrtChange;
- ///
- /// String event
- ///
- public event EventHandler StringChange;
- ///
- /// Event to notify clients of an updated password at the specified index (uint)
- ///
- public static event EventHandler PasswordChange;
-
- ///
- /// Constructor
- ///
- public PasswordManager()
- {
-
- }
-
- ///
- /// Initialize password manager
- ///
- public void Initialize()
- {
- if (Passwords == null)
- Passwords = new Dictionary();
-
- if (_passwords == null)
- _passwords = new Dictionary();
-
- OnBoolChange(true, 0, PasswordManagementConstants.PasswordInitializedChange);
- }
-
- ///
- /// Updates password stored in the dictonary
- ///
- ///
- ///
- public void UpdatePassword(ushort key, string password)
- {
- // validate the parameters
- if (key > 0 && string.IsNullOrEmpty(password))
- {
- Debug.Console(1, string.Format("PasswordManager.UpdatePassword: key [{0}] or password are not valid", key, password));
- return;
- }
-
- try
- {
- // if key exists, update the value
- if(_passwords.ContainsKey(key))
- _passwords[key] = password;
- // else add the key & value
- else
- _passwords.Add(key, password);
-
- Debug.Console(1, string.Format("PasswordManager.UpdatePassword: _password[{0}] = {1}", key, _passwords[key]));
-
- if (PasswordTimer == null)
- {
- PasswordTimer = new CTimer((o) => PasswordTimerElapsed(), PasswordTimerElapsedMs);
- Debug.Console(1, string.Format("PasswordManager.UpdatePassword: CTimer Started"));
- OnBoolChange(true, 0, PasswordManagementConstants.PasswordUpdateBusyChange);
- }
- else
- {
- PasswordTimer.Reset(PasswordTimerElapsedMs);
- Debug.Console(1, string.Format("PasswordManager.UpdatePassword: CTimer Reset"));
- }
- }
- catch (Exception e)
- {
- var msg = string.Format("PasswordManager.UpdatePassword key-value[{0}, {1}] failed:\r{2}", key, password, e);
- Debug.Console(1, msg);
- }
- }
-
- ///
- /// CTimer callback function
- ///
- private void PasswordTimerElapsed()
- {
- try
- {
- PasswordTimer.Stop();
- Debug.Console(1, string.Format("PasswordManager.PasswordTimerElapsed: CTimer Stopped"));
- OnBoolChange(false, 0, PasswordManagementConstants.PasswordUpdateBusyChange);
- foreach (var pw in _passwords)
- {
- // if key exists, continue
- if (Passwords.ContainsKey(pw.Key))
- {
- Debug.Console(1, string.Format("PasswordManager.PasswordTimerElapsed: pw.key[{0}] = {1}", pw.Key, pw.Value));
- if (Passwords[pw.Key] != _passwords[pw.Key])
- {
- Passwords[pw.Key] = _passwords[pw.Key];
- Debug.Console(1, string.Format("PasswordManager.PasswordTimerElapsed: Updated Password[{0} = {1}", pw.Key, Passwords[pw.Key]));
- OnPasswordChange(Passwords[pw.Key], (ushort)pw.Key, PasswordManagementConstants.StringValueChange);
- }
- }
- // else add the key & value
- else
- {
- Passwords.Add(pw.Key, pw.Value);
- }
- }
- OnUshrtChange((ushort)Passwords.Count, 0, PasswordManagementConstants.PasswordManagerCountChange);
- }
- catch (Exception e)
- {
- var msg = string.Format("PasswordManager.PasswordTimerElapsed failed:\r{0}", e);
- Debug.Console(1, msg);
- }
- }
-
- ///
- /// Method to change the default timer value, (default 5000ms/5s)
- ///
- ///
- public void PasswordTimerMs(ushort time)
- {
- PasswordTimerElapsedMs = Convert.ToInt64(time);
- }
-
- ///
- /// Helper method for debugging to see what passwords are in the lists
- ///
- public void ListPasswords()
- {
- Debug.Console(0, "PasswordManager.ListPasswords:\r");
- foreach (var pw in Passwords)
- Debug.Console(0, "Passwords[{0}]: {1}\r", pw.Key, pw.Value);
- Debug.Console(0, "\n");
- foreach (var pw in _passwords)
- Debug.Console(0, "_passwords[{0}]: {1}\r", pw.Key, pw.Value);
- }
-
- ///
- /// Protected boolean change event handler
- ///
- ///
- ///
- ///
- protected void OnBoolChange(bool state, ushort index, ushort type)
- {
- var handler = BoolChange;
- if (handler != null)
- {
- var args = new BoolChangeEventArgs(state, type);
- args.Index = index;
- BoolChange(this, args);
- }
- }
-
- ///
- /// Protected ushort change event handler
- ///
- ///
- ///
- ///
- protected void OnUshrtChange(ushort value, ushort index, ushort type)
- {
- var handler = UshrtChange;
- if (handler != null)
- {
- var args = new UshrtChangeEventArgs(value, type);
- args.Index = index;
- UshrtChange(this, args);
- }
- }
-
- ///
- /// Protected string change event handler
- ///
- ///
- ///
- ///
- protected void OnStringChange(string value, ushort index, ushort type)
- {
- var handler = StringChange;
- if (handler != null)
- {
- var args = new StringChangeEventArgs(value, type);
- args.Index = index;
- StringChange(this, args);
- }
- }
-
- ///
- /// Protected password change event handler
- ///
- ///
- ///
- ///
- protected void OnPasswordChange(string value, ushort index, ushort type)
- {
- var handler = PasswordChange;
- if (handler != null)
- {
- var args = new StringChangeEventArgs(value, type);
- args.Index = index;
- PasswordChange(this, args);
- }
- }
- }
+using System;
+using System.Collections.Generic;
+using Crestron.SimplSharp;
+
+namespace PepperDash.Core.PasswordManagement
+{
+ ///
+ /// Allows passwords to be stored and managed
+ ///
+ public class PasswordManager
+ {
+ ///
+ /// Public dictionary of known passwords
+ ///
+ public static Dictionary Passwords = new Dictionary();
+
+ ///
+ /// Indicates whether the manager has been initialized
+ ///
+ public static bool IsInitialized { get; private set; }
+
+ ///
+ /// Tracks keys changed during the debounce window for notification
+ ///
+ private readonly List _pendingChanges = new List();
+
+ ///
+ /// Timer used to wait until password changes have stopped before updating the dictionary
+ ///
+ CTimer _passwordTimer;
+ ///
+ /// Timer length
+ ///
+ public long PasswordTimerElapsedMs = 5000;
+
+ ///
+ /// Boolean event
+ ///
+ public event EventHandler BoolChange;
+ ///
+ /// Ushort event
+ ///
+ public event EventHandler UshrtChange;
+ ///
+ /// String event
+ ///
+ public event EventHandler StringChange;
+ ///
+ /// Event to notify clients of an updated password at the specified index (uint)
+ ///
+ public static event EventHandler PasswordChange;
+
+ ///
+ /// Event to notify clients when the manager has been initialized
+ ///
+ public static event EventHandler Initialized;
+
+ ///
+ /// Constructor (empty constructor required by S+)
+ ///
+ public PasswordManager()
+ {
+ }
+
+ ///
+ /// Initialize password manager
+ ///
+ public void Initialize()
+ {
+ if (Passwords == null)
+ {
+ Passwords = new Dictionary();
+ }
+
+ OnBoolChange(true, 0, PasswordConstants.Initialized);
+
+ IsInitialized = true;
+
+ var handler = Initialized;
+ if (handler != null)
+ handler(this, new BoolChangeEventArgs(true, PasswordConstants.Initialized));
+ }
+
+ ///
+ /// Updates password stored in the dictonary
+ ///
+ ///
+ ///
+ public void UpdatePassword(string key, string password)
+ {
+ // validate the parameters
+ if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(password))
+ {
+ Debug.Console(1, string.Format("PasswordManager.UpdatePassword: key [{0}] or password are not valid", key, password));
+ return;
+ }
+
+ try
+ {
+ Passwords[key] = password;
+ if (!_pendingChanges.Contains(key))
+ _pendingChanges.Add(key);
+
+ Debug.Console(1, string.Format("PasswordManager.UpdatePassword: Passwords[{0}] = {1}", key, Passwords[key]));
+
+ if (_passwordTimer == null)
+ {
+ _passwordTimer = new CTimer((o) => PasswordTimerElapsed(), PasswordTimerElapsedMs);
+ Debug.Console(1, string.Format("PasswordManager.UpdatePassword: CTimer Started"));
+ OnBoolChange(true, 0, PasswordConstants.UpdateBusy);
+ }
+ else
+ {
+ _passwordTimer.Reset(PasswordTimerElapsedMs);
+ Debug.Console(1, string.Format("PasswordManager.UpdatePassword: CTimer Reset"));
+ }
+ }
+ catch (Exception e)
+ {
+ var msg = string.Format("PasswordManager.UpdatePassword key-value[{0}, {1}] failed:\r{2}", key, password, e);
+ Debug.Console(1, msg);
+ }
+ }
+
+ ///
+ /// Helper method for debugging to see what passwords are in the lists
+ ///
+ public void ListEntries()
+ {
+ Debug.Console(0, "PasswordManager.ListEntries:\r");
+ foreach (var pw in Passwords)
+ {
+ var maskedValue = string.IsNullOrEmpty(pw.Value) ? string.Empty : new string('*', pw.Value.Length);
+ Debug.Console(0, "Passwords[{0}]: {1}\r", pw.Key, maskedValue);
+ }
+ }
+
+ ///
+ /// Validates the username against the known entries
+ ///
+ ///
+ public static PasswordValidationResult ValidateUsername(string username)
+ {
+ if (Passwords == null)
+ return PasswordValidationResult.Failure("No entires defined, verify list is initilaized");
+
+ if (string.IsNullOrEmpty(username))
+ return PasswordValidationResult.Failure("Username or password is empty");
+
+ string storedPassword;
+ return !Passwords.TryGetValue(username, out storedPassword)
+ ? PasswordValidationResult.Failure(string.Format("Username '{0}' not found", username))
+ : PasswordValidationResult.Success("Valid username", storedPassword);
+ }
+
+ ///
+ /// Validates the username password against the known entries
+ ///
+ ///
+ ///
+ public static PasswordValidationResult ValidateUsernameAndPassword(string username, string password)
+ {
+ if (Passwords == null)
+ return PasswordValidationResult.Failure("No entires defined, verify list is initilaized");
+
+ if (string.IsNullOrEmpty(username))
+ return PasswordValidationResult.Failure("Username is empty or null");
+
+ if(string.IsNullOrEmpty(password))
+ return PasswordValidationResult.Failure("Password is empty or null");
+
+ string storedPassword;
+ if (!Passwords.TryGetValue(username, out storedPassword))
+ return PasswordValidationResult.Failure(string.Format("Username '{0}' not found", username));
+
+ return !string.Equals(storedPassword, password, StringComparison.Ordinal)
+ ? PasswordValidationResult.Failure("Invalid password, verify password and try again")
+ : PasswordValidationResult.Success("Valid credentials, login was successfull", storedPassword);
+ }
+
+ ///
+ /// CTimer callback function
+ ///
+ private void PasswordTimerElapsed()
+ {
+ try
+ {
+ _passwordTimer.Stop();
+ Debug.Console(1, string.Format("PasswordManager.PasswordTimerElapsed: CTimer Stopped"));
+ OnBoolChange(false, 0, PasswordConstants.UpdateBusy);
+
+ foreach (var key in _pendingChanges)
+ {
+ string value;
+ if (!Passwords.TryGetValue(key, out value)) continue;
+
+ Debug.Console(1, string.Format("PasswordManager.PasswordTimerElapsed: Notifying change for [{0}]", key));
+ OnPasswordChange(key, 0, PasswordConstants.PasswordUpdated);
+ }
+
+ _pendingChanges.Clear();
+ OnUshrtChange((ushort)Passwords.Count, 0, PasswordConstants.Count);
+ }
+ catch (Exception e)
+ {
+ var msg = string.Format("PasswordManager.PasswordTimerElapsed failed:\r{0}", e);
+ Debug.Console(1, msg);
+ }
+ }
+
+ ///
+ /// Method to change the default timer value, (default 5000ms/5s)
+ ///
+ ///
+ public void PasswordTimerMs(ushort time)
+ {
+ PasswordTimerElapsedMs = Convert.ToInt64(time);
+ }
+
+
+ #region event handlers
+
+ ///
+ /// Protected boolean change event handler
+ ///
+ ///
+ ///
+ ///
+ protected void OnBoolChange(bool state, ushort index, ushort type)
+ {
+ var handler = BoolChange;
+ if (handler == null) return;
+
+ var args = new BoolChangeEventArgs(state, type) {Index = index};
+ BoolChange(this, args);
+ }
+
+ ///
+ /// Protected ushort change event handler
+ ///
+ ///
+ ///
+ ///
+ protected void OnUshrtChange(ushort value, ushort index, ushort type)
+ {
+ var handler = UshrtChange;
+ if (handler == null) return;
+
+ var args = new UshrtChangeEventArgs(value, type) {Index = index};
+ UshrtChange(this, args);
+ }
+
+ ///
+ /// Protected string change event handler
+ ///
+ ///
+ ///
+ ///
+ protected void OnStringChange(string value, ushort index, ushort type)
+ {
+ var handler = StringChange;
+ if (handler == null) return;
+
+ var args = new StringChangeEventArgs(value, type) {Index = index};
+ StringChange(this, args);
+ }
+
+ ///
+ /// Protected password change event handler
+ ///
+ ///
+ ///
+ ///
+ protected void OnPasswordChange(string value, ushort index, ushort type)
+ {
+ var handler = PasswordChange;
+ if (handler == null) return;
+
+ var args = new StringChangeEventArgs(value, type) {Index = index};
+ PasswordChange(this, args);
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/src/PasswordManagement/PasswordValidationResult.cs b/src/PasswordManagement/PasswordValidationResult.cs
new file mode 100644
index 0000000..d77796f
--- /dev/null
+++ b/src/PasswordManagement/PasswordValidationResult.cs
@@ -0,0 +1,54 @@
+namespace PepperDash.Core.PasswordManagement
+{
+ ///
+ /// Represents the result of a password validation attempt
+ ///
+ public class PasswordValidationResult
+ {
+ ///
+ /// Indicates whether the validation was successful
+ ///
+ public bool IsValid { get; private set; }
+
+ ///
+ /// Password
+ ///
+ public string Password { get; private set; }
+
+ ///
+ /// Message describing the validation result
+ ///
+ public string Message { get; private set; }
+
+ ///
+ /// Constructor
+ ///
+ /// Whether the validation was successful
+ /// Message describing the result
+ ///
+ public PasswordValidationResult(bool isValid, string message, string password)
+ {
+ IsValid = isValid;
+ Message = message;
+ Password = password;
+ }
+
+ ///
+ /// Creates a successful validation result
+ ///
+ /// The success message
+ public static PasswordValidationResult Success(string message, string password)
+ {
+ return new PasswordValidationResult(true, message, password);
+ }
+
+ ///
+ /// Creates a failed validation result with the specified message
+ ///
+ /// The failure reason
+ public static PasswordValidationResult Failure(string message)
+ {
+ return new PasswordValidationResult(false, message, null);
+ }
+ }
+}
diff --git a/src/PasswordManagement/PepperDash_Core_Password_Client_A4sA3s_v02.00.ush b/src/PasswordManagement/PepperDash_Core_Password_Client_A4sA3s_v02.00.ush
new file mode 100644
index 0000000..2638009
--- /dev/null
+++ b/src/PasswordManagement/PepperDash_Core_Password_Client_A4sA3s_v02.00.ush
@@ -0,0 +1,247 @@
+[BEGIN]
+ Version=1
+[END]
+[BEGIN]
+ ObjTp=FSgntr
+ Sgntr=UserSPlus
+ RelVrs=1
+ IntStrVrs=1
+ SPlusVrs=4.06.00
+ CrossCplrVrs=1.3
+[END]
+[BEGIN]
+ ObjTp=Hd
+ IncludePath1=..\bin
+ Cmn1=INPUTS\\--------------------------------------------------------
+ Cmn2=-----\\Debug (d) \\- enables/disables debugging of password client||1
+ Cmn3=class\\\\Initialize (d) - REMOVED\\- Clients are automatically initialized||1
+ Cmn4=via event subscription with the Manager\\\\PasswordValidate (d)||1
+ Cmn5=*Optional\\- Triggers validate method, the module will automatically||1
+ Cmn6=trigger the \\ validate method when the entered password equals||1
+ Cmn7=the length of the \\ selected password\\ \\Keypad (d)\\- Used||1
+ Cmn8=for basic numeric pins\\\\PasswordSelect[1-10] (d)\\- Allows developer||1
+ Cmn9=to select different passwords used for validation\\\\PasswordSelectByIndex||1
+ Cmn10=(a)\\- Alternate method for selecting password used for validation\\
+ Cmn11=\\PasswordtoValidate (s)\\- Allows developer to supply raw alpha-
+ Cmn12=numeric text as the password \\ to validate. Typically fed from||1
+ Cmn13=a keyboard raw output\\ \\OUTPUTS\\----------------------------
+ Cmn14=---------------------------------\\InitializedFb (d)\\- Feedback||1
+ Cmn15=the client is initialized\\\\PasswordIsValid (d) *Pulse\\- Pulses||1
+ Cmn16=when the password entered (pin or raw text) is valid\\\\PasswordIsInvalid||1
+ Cmn17=(d) *Pulse\\- Pulses when the password entered (pin or raw text)||1
+ Cmn18=is not valid\\\\PasswordLedFb[1-10] (d)\\- Remains high while the||1
+ Cmn19=entered password length matches the LED length\\\\PasswordSelectedIndex||1
+ Cmn20=(a)\\- Feedback of the selected password\\\\PasswordSelectedLength||1
+ Cmn21=(a)\\- Feedback of the selected password length. Typically drives||1
+ Cmn22=the LED\\ SRL analog input 'Set Number of Items'\\ \\PasswordToValidateLength||1
+ Cmn23=(a)\\- Analog feedback of characters entered by user
+[END]
+[BEGIN]
+ ObjTp=Symbol
+ Exclusions=1,19,20,21,88,89,167,168,179,213,214,215,216,217,225,226,248,249,266,267,310,362,378,380,405,407,408,409,478,522,537,554,586,590,611,624,718,756,767,830,841,842,854,883,955,1032,1062,1079,1128,1129,1134,1140,1157,1158,1195,1199,1220,1221,1222,1223,1299,1348,1349,1439,1472,1473,1499,1746,1803,1975,2229,2354,2514,2523,2532,2706,2707,3235,3236,3427,3454,3567,3568,3601,3602,3708,3902,3903,3912,3918,3925,3926,4206,4207,
+ Exclusions_CDS=5
+ Inclusions_CDS=6,7
+ Name=PepperDash_Core_Password_Client_A4sA3s_v02.00
+ SmplCName=PepperDash_Core_Password_Client_A4sA3s_v02.00.usp
+ Code=1
+ SysRev5=4.006
+ SMWRev=3.00.00
+ InputCue1=[~UNUSED~]
+ InputSigType1=Digital
+ InputCue2=[~UNUSED~]
+ InputSigType2=Digital
+ InputCue3=[~UNUSED~]
+ InputSigType3=Digital
+ InputCue4=DebugEnable
+ InputSigType4=Digital
+ InputCue5=[~UNUSED~]
+ InputSigType5=Digital
+ InputCue6=[~UNUSED~]
+ InputSigType6=Digital
+ InputCue7=ValidateUsername
+ InputSigType7=Digital
+ InputCue8=ValidatePassword
+ InputSigType8=Digital
+ InputCue9=[~UNUSED~]
+ InputSigType9=Digital
+ InputCue10=KeypadClear
+ InputSigType10=Digital
+ InputCue11=KeypadBackspace
+ InputSigType11=Digital
+ InputCue12=Keypad00
+ InputSigType12=Digital
+ InputCue13=Keypad01
+ InputSigType13=Digital
+ InputCue14=Keypad02
+ InputSigType14=Digital
+ InputCue15=Keypad03
+ InputSigType15=Digital
+ InputCue16=Keypad04
+ InputSigType16=Digital
+ InputCue17=Keypad05
+ InputSigType17=Digital
+ InputCue18=Keypad06
+ InputSigType18=Digital
+ InputCue19=Keypad07
+ InputSigType19=Digital
+ InputCue20=Keypad08
+ InputSigType20=Digital
+ InputCue21=Keypad09
+ InputSigType21=Digital
+ OutputCue1=[~UNUSED~]
+ OutputSigType1=Digital
+ OutputCue2=[~UNUSED~]
+ OutputSigType2=Digital
+ OutputCue3=[~UNUSED~]
+ OutputSigType3=Digital
+ OutputCue4=[~UNUSED~]
+ OutputSigType4=Digital
+ OutputCue5=InitializedFb
+ OutputSigType5=Digital
+ OutputCue6=[~UNUSED~]
+ OutputSigType6=Digital
+ OutputCue7=UsernameIsValid
+ OutputSigType7=Digital
+ OutputCue8=UsernameIsInvalid
+ OutputSigType8=Digital
+ OutputCue9=[~UNUSED~]
+ OutputSigType9=Digital
+ OutputCue10=PasswordIsValid
+ OutputSigType10=Digital
+ OutputCue11=PasswordIsInvalid
+ OutputSigType11=Digital
+ OutputCue12=[~UNUSED~]
+ OutputSigType12=Digital
+ OutputCue13=PasswordLedFb[#]
+ OutputSigType13=Digital
+ InputList2Cue1=[~UNUSED~]
+ InputList2SigType1=Serial
+ InputList2Cue2=[~UNUSED~]
+ InputList2SigType2=Serial
+ InputList2Cue3=[~UNUSED~]
+ InputList2SigType3=Serial
+ InputList2Cue4=[~UNUSED~]
+ InputList2SigType4=Serial
+ InputList2Cue5=[~UNUSED~]
+ InputList2SigType5=Serial
+ InputList2Cue6=Username
+ InputList2SigType6=Serial
+ InputList2Cue7=Password
+ InputList2SigType7=Serial
+ OutputList2Cue1=[~UNUSED~]
+ OutputList2SigType1=Analog
+ OutputList2Cue2=PasswordSelectedLength
+ OutputList2SigType2=Analog
+ OutputList2Cue3=PasswordToValidateLength
+ OutputList2SigType3=Analog
+ OutputList2Cue4=[~UNUSED~]
+ OutputList2SigType4=Serial
+ OutputList2Cue5=UsernameFb
+ OutputList2SigType5=Serial
+ OutputList2Cue6=MessageFb
+ OutputList2SigType6=Serial
+ ParamCue1=[Reference Name]
+ ParamCue2=ValidatePulseLength
+ ParamSigType2=Constant
+ ParamCue3=ValidateUsernameOnChange,0d,1d
+ ParamSigType3=List
+ ParamCue4=ValidatePasswordOnChange,0d,1d
+ ParamSigType4=List
+ MinVariableInputs=21
+ MaxVariableInputs=21
+ MinVariableInputsList2=7
+ MaxVariableInputsList2=7
+ MinVariableOutputs=22
+ MaxVariableOutputs=22
+ MinVariableOutputsList2=6
+ MaxVariableOutputsList2=6
+ MinVariableParams=3
+ MaxVariableParams=3
+ Expand=expand_separately
+ Expand2=expand_inputs_with_outputs
+ ProgramTree=Logic
+ SymbolTree=46
+ UserSymTreeName=PepperDash Technology
+ Hint=
+ PdfHelp=
+ HelpID=
+ Render=4
+ Smpl-C=16
+ CompilerCode=-48
+ CompilerParamCode=27
+ CompilerParamCode5=14
+ NumFixedParams=1
+ Pp1=1
+ Pp2=2
+ Pp3=3
+ Pp4=4
+ MPp=4
+ NVStorage=10
+ ParamSigType1=String
+ SmplCInputCue1=o#
+ SmplCOutputCue1=i#
+ SmplCInputList2Cue1=an#
+ SmplCOutputList2Cue1=ai#
+ SPlus2CompiledName=S2_PepperDash_Core_Password_Client_A4sA3s_v02_00
+ SymJam=NonExclusive
+ FileName=PepperDash_Core_Password_Client_A4sA3s_v02.00.ush
+ SIMPLPlusModuleEncoding=0
+ clz1=PepperDash_Core
+[END]
+[BEGIN]
+ ObjTp=Dp
+ H=1
+ Tp=1
+ NoS=False
+[END]
+[BEGIN]
+ ObjTp=Dp
+ H=2
+ Tp=1
+ HD=True
+ DV=500d
+ Sgn=0
+ Lng=False
+ NF=1
+ NoS=True
+ DNF=1
+ VVS=1
+ LR=50d
+ HR=1000d
+[END]
+[BEGIN]
+ ObjTp=Dp
+ H=3
+ Tp=1
+ HD=True
+ DV=0d
+ Sgn=0
+ Lng=False
+ NF=1
+ NoS=True
+ DNF=1
+ VVS=2
+ VN=2
+ Val1=0d
+ Lbl1=False
+ Val2=1d
+ Lbl2=True
+[END]
+[BEGIN]
+ ObjTp=Dp
+ H=4
+ Tp=1
+ HD=True
+ DV=0d
+ Sgn=0
+ Lng=False
+ NF=1
+ NoS=True
+ DNF=1
+ VVS=2
+ VN=2
+ Val1=0d
+ Lbl1=False
+ Val2=1d
+ Lbl2=True
+[END]
diff --git a/src/PasswordManagement/PepperDash_Core_Password_Client_A4sA3s_v02.00.usp b/src/PasswordManagement/PepperDash_Core_Password_Client_A4sA3s_v02.00.usp
new file mode 100644
index 0000000..8a0e19a
--- /dev/null
+++ b/src/PasswordManagement/PepperDash_Core_Password_Client_A4sA3s_v02.00.usp
@@ -0,0 +1,389 @@
+/*******************************************************************************************
+Dealer Name: PepperDash Technology Corp.
+Programmer: PepperDash Technology Corp.
+Copyright: 2018
+********************************************************************************************
+Notice of Ownership and Copyright
+
+The material in which this notice appears is the property of PepperDash Technology Corporation,
+which claims copyright under the laws of the United States of America in the entire body of
+material and in all parts thereof, regardless of the use to which it is being put. Any use,
+in whole or in part, of this material by another party without the express written permission
+of PepperDash Technology Corporation is prohibited.
+
+PepperDash Technology Corporation reserves all rights under applicable laws.
+*******************************************************************************************/
+/*******************************************************************************************
+Compiler Directives
+(Uncomment and declare compiler directives as needed)
+*******************************************************************************************/
+#CATEGORY "46" "PepperDash Technology"
+#DEFAULT_VOLATILE
+#ENABLE_STACK_CHECKING
+#ENABLE_TRACE
+#ANALOG_SERIAL_EXPAND InputsWithOutputs
+
+#DEFINE_CONSTANT MAX_LEN_SYMBOL 50
+#DEFINE_CONSTANT MAX_LEN_MSG 200
+#DEFINE_CONSTANT MAX_LEN_STR 250
+#DEFINE_CONSTANT MAX_LEN_PULSE 50
+
+#DEFINE_CONSTANT MAX_PASSWORDS 10
+#DEFINE_CONSTANT MAX_LEDS 10
+
+#DEFINE_CONSTANT ENUM_TYPE_NONE 0
+#DEFINE_CONSTANT ENUM_TYPE_BACKDOOR 1
+#DEFINE_CONSTANT ENUM_TYPE_GLOBAL 2
+#DEFINE_CONSTANT ENUM_TYPE_SYSTEM 3
+#DEFINE_CONSTANT ENUM_TYPE_ROOM 4
+#DEFINE_CONSTANT ENUM_TYPE_TECH 5
+#DEFINE_CONSTANT ENUM_TYPE_USER 6
+
+#HELP_BEGIN
+INPUTS
+-------------------------------------------------------------
+Debug (d)
+- enables/disables debugging of password client class
+
+Initialize (d) - REMOVED
+- Clients are automatically initialized via event subscription with the Manager
+
+PasswordValidate (d) *Optional
+- Triggers validate method, the module will automatically trigger the
+ validate method when the entered password equals the length of the
+ selected password
+
+Keypad (d)
+- Used for basic numeric pins
+
+PasswordSelect[1-10] (d)
+- Allows developer to select different passwords used for validation
+
+PasswordSelectByIndex (a)
+- Alternate method for selecting password used for validation
+
+PasswordtoValidate (s)
+- Allows developer to supply raw alpha-numeric text as the password
+ to validate. Typically fed from a keyboard raw output
+
+OUTPUTS
+-------------------------------------------------------------
+InitializedFb (d)
+- Feedback the client is initialized
+
+PasswordIsValid (d) *Pulse
+- Pulses when the password entered (pin or raw text) is valid
+
+PasswordIsInvalid (d) *Pulse
+- Pulses when the password entered (pin or raw text) is not valid
+
+PasswordLedFb[1-10] (d)
+- Remains high while the entered password length matches the LED length
+
+PasswordSelectedIndex (a)
+- Feedback of the selected password
+
+PasswordSelectedLength (a)
+- Feedback of the selected password length. Typically drives the LED
+ SRL analog input 'Set Number of Items'
+
+PasswordToValidateLength (a)
+- Analog feedback of characters entered by user
+#HELP_END
+
+/*******************************************************************************************
+Include Libraries
+(Uncomment and include additional libraries as needed)
+*******************************************************************************************/
+// comment out or remove when PepperDash_Core.clz is local to the module
+#INCLUDEPATH "..\bin"
+#USER_SIMPLSHARP_LIBRARY "PepperDash_Core"
+
+/*******************************************************************************************
+DIGITAL, ANALOG and SERIAL INPUTS and OUTPUTS
+(Uncomment and declare inputs and outputs as needed)
+*******************************************************************************************/
+DIGITAL_INPUT
+ _SKIP_,
+ _SKIP_,
+ _SKIP_,
+ DebugEnable,
+ _SKIP_,
+ _SKIP_,
+ ValidateUsername,
+ ValidatePassword,
+ _SKIP_,
+ KeypadClear,
+ KeypadBackspace,
+ Keypad00,
+ Keypad01,
+ Keypad02,
+ Keypad03,
+ Keypad04,
+ Keypad05,
+ Keypad06,
+ Keypad07,
+ Keypad08,
+ Keypad09;
+
+STRING_INPUT
+ _SKIP_,
+ _SKIP_,
+ _SKIP_,
+ _SKIP_,
+ _SKIP_,
+ Username[MAX_LEN_STR],
+ Password[MAX_LEN_STR];
+
+DIGITAL_OUTPUT
+ _SKIP_,
+ _SKIP_,
+ _SKIP_,
+ _SKIP_,
+ InitializedFb,
+ _SKIP_,
+ UsernameIsValid,
+ UsernameIsInvalid,
+ _SKIP_,
+ PasswordIsValid,
+ PasswordIsInvalid;
+
+ANALOG_OUTPUT
+ _SKIP_,
+ PasswordSelectedLength,
+ PasswordToValidateLength;
+
+STRING_OUTPUT
+ _SKIP_,
+ UsernameFb,
+ MessageFb;
+
+DIGITAL_OUTPUT
+ _SKIP_,
+ PasswordLedFb[MAX_LEDS, MAX_LEDS];
+
+/*******************************************************************************************
+SIMPL # Class to be instantiated
+*******************************************************************************************/
+PasswordClient thisClient;
+
+/*******************************************************************************************
+Parameters
+(Uncomment and declare parameters as needed)
+*******************************************************************************************/
+INTEGER_PARAMETER
+ ValidatePulseLength,
+ ValidateUsernameOnChange,
+ ValidatePasswordOnChange;
+
+/*******************************************************************************************
+Parameter Properties
+(Uncomment and declare parameter properties as needed)
+*******************************************************************************************/
+#BEGIN_PARAMETER_PROPERTIES ValidatePulseLength
+ propValidUnits = unitDecimal;
+ propBounds = 50d, 1000d;
+ propDefaultValue = 500d;
+#END_PARAMETER_PROPERTIES
+
+#BEGIN_PARAMETER_PROPERTIES ValidateUsernameOnChange
+ propValidUnits = unitDecimal;
+ propDefaultValue = 0d;
+ propList = { 0d, "False" }, { 1d, "True" };
+#END_PARAMETER_PROPERTIES
+
+#BEGIN_PARAMETER_PROPERTIES ValidatePasswordOnChange
+ propValidUnits = unitDecimal;
+ propDefaultValue = 0d;
+ propList = { 0d, "False" }, { 1d, "True" };
+#END_PARAMETER_PROPERTIES
+
+/*******************************************************************************************
+Structure Definitions
+(Uncomment and define structure definitions as needed)
+Note: Be sure to initialize all declared STRING variables as needed
+ For example, in Function Main: struct.myString = "";
+*******************************************************************************************/
+
+/*******************************************************************************************
+Global Variables
+(Uncomment and declare global variables as needed)
+Note: Be sure to initialize all declared STRING variables as needed
+ For example, in Function Main: myString = "";
+*******************************************************************************************/
+String
+ strUsername[MAX_LEN_STR],
+ strPassword[MAX_LEN_STR];
+
+/*******************************************************************************************
+Functions
+(Add any additional functions here)
+Note: Functions must be physically placed before the location in
+ the code that calls them.
+*******************************************************************************************/
+EventHandler BoolChanged(PasswordClient sender, BoolChangeEventArgs args)
+{
+ Switch(args.Type)
+ {
+ Case(PasswordConstants.BoolValueChange):
+ {
+ // generic bool change
+ }
+ Case(PasswordConstants.Initialized):
+ {
+ InitializedFb = args.IntValue;
+ }
+ Case(PasswordConstants.UsernameValidated):
+ {
+ If(args.IntValue = 1)
+ {
+ Pulse(ValidatePulseLength, UsernameIsValid);
+
+ strPassword = "";
+ }
+ Else
+ {
+ Pulse(ValidatePulseLength, UsernameIsInvalid);
+
+ strUsername = "";
+ strPassword = "";
+ }
+ }
+ Case(PasswordConstants.PasswordValidated):
+ {
+ If(args.IntValue = 1)
+ {
+ Pulse(ValidatePulseLength, PasswordIsValid);
+
+ strUsername = "";
+ strPassword = "";
+ }
+ Else
+ {
+ Pulse(ValidatePulseLength, PasswordIsInvalid);
+
+ //strUsername = "";
+ strPassword = "";
+ }
+ }
+ Case(PasswordConstants.LedFeedback):
+ {
+ If(DebugEnable) Trace("LedFeedback: Type[%u] Index[%u] IntValue[%u]\r", args.Type, args.Index, args.IntValue);
+
+ If(args.Index = 0)
+ SetArray(PasswordLedFb, 0);
+ Else
+ {
+ PasswordToValidateLength = args.Index;
+ PasswordLedFb[args.Index] = args.IntValue;
+ }
+ }
+ Default:
+ {
+ If(DebugEnable) Trace("BoolChanged: args[%u].Type[%u] = %u\r", args.Index, args.Type, args.IntValue);
+ }
+ }
+}
+
+EventHandler UshrtChanged(PasswordClient sender, UshrtChangeEventArgs args)
+{
+ Switch(args.Type)
+ {
+ Case(PasswordConstants.UshrtValueChange):
+ {
+ // generic ushort change
+ }
+ Case(PasswordConstants.PasswordLength):
+ {
+ PasswordSelectedLength = args.IntValue;
+ }
+ Default:
+ {
+ If(DebugEnable) Trace("UshortChanged: args[%u].Type[%u] = %u\r", args.Index, args.Type, args.IntValue);
+ }
+ }
+}
+
+EventHandler StringChanged(PasswordClient sender, StringChangeEventArgs args)
+{
+ Switch(args.Type)
+ {
+ Case(PasswordConstants.StringValueChange):
+ {
+ // generic string change
+ }
+ Case(PasswordConstants.UsernameValidated):
+ {
+ UsernameFb = args.StringValue;
+ }
+ Case(PasswordConstants.Message):
+ {
+ MessageFb = args.StringValue;
+ }
+ Default:
+ {
+ If(DebugEnable) Trace("StringChanged: args[%u].Type[%u] = %s\r", args.Index, args.Type, args.StringValue);
+ }
+ }
+}
+
+/*******************************************************************************************
+Event Handlers
+(Uncomment and declare additional event handlers as needed)
+*******************************************************************************************/
+Threadsafe Change Username
+{
+ strUsername = Username;
+
+ If(ValidateUsernameOnChange)
+ {
+ thisClient.ValidateUsername(strUsername);
+ }
+}
+
+Threadsafe Change Password
+{
+ strPassword = Password;
+
+ If(ValidatePasswordOnChange)
+ {
+ thisClient.ValidateUsernameAndPassword(strUsername, strPassword);
+ }
+}
+
+Push ValidateUsername
+{
+ thisClient.ValidateUsername(strUsername);
+}
+
+Push ValidatePassword
+{
+ thisClient.ValidateUsernameAndPassword(strUsername, strPassword);
+}
+
+Push Keypad00 { thisClient.BuildPassword("0"); }
+Push Keypad01 { thisClient.BuildPassword("1"); }
+Push Keypad02 { thisClient.BuildPassword("2"); }
+Push Keypad03 { thisClient.BuildPassword("3"); }
+Push Keypad04 { thisClient.BuildPassword("4"); }
+Push Keypad05 { thisClient.BuildPassword("5"); }
+Push Keypad06 { thisClient.BuildPassword("6"); }
+Push Keypad07 { thisClient.BuildPassword("7"); }
+Push Keypad08 { thisClient.BuildPassword("8"); }
+Push Keypad09 { thisClient.BuildPassword("9"); }
+Push KeypadClear { thisClient.ClearPassword(); }
+Push KeypadBackspace { thisClient.DeletePasswordCharacter(); }
+
+/*******************************************************************************************
+Main()
+Uncomment and place one-time startup code here
+(This code will get called when the system starts up)
+*******************************************************************************************/
+Function Main()
+{
+ WaitForInitializationComplete();
+
+ RegisterEvent(thisClient, BoolChange, BoolChanged);
+ RegisterEvent(thisClient, UshrtChange, UshrtChanged);
+ RegisterEvent(thisClient, StringChange, StringChanged);
+}
diff --git a/src/PasswordManagement/PepperDash_Core_Password_Manager_A4sA3s_v02.00.ush b/src/PasswordManagement/PepperDash_Core_Password_Manager_A4sA3s_v02.00.ush
new file mode 100644
index 0000000..52658c0
--- /dev/null
+++ b/src/PasswordManagement/PepperDash_Core_Password_Manager_A4sA3s_v02.00.ush
@@ -0,0 +1,134 @@
+[BEGIN]
+ Version=1
+[END]
+[BEGIN]
+ ObjTp=FSgntr
+ Sgntr=UserSPlus
+ RelVrs=1
+ IntStrVrs=1
+ SPlusVrs=4.06.00
+ CrossCplrVrs=1.3
+[END]
+[BEGIN]
+ ObjTp=Hd
+ IncludePath1=..\bin
+ Cmn1=INPUTS\\--------------------------------------------------------
+ Cmn2=-------------\\DebugEnable (d)\\- Enables/disables debug of the||1
+ Cmn3=password manager class\\\\Initialize (d)\\- Initializes the password||1
+ Cmn4=manager class\\\\ListPassword (d)\\- Prints the configured passwords||1
+ Cmn5=to console\\\\PasswordUpdate[1-10] (s)\\- Accepts alpha-numeric||1
+ Cmn6=pins/passwords that will be used\\ to validate clients against\\
+ Cmn7=- These values can be driven statically from code (msend/sio), from||1
+ Cmn8=config,\\ or from Fusion custom propeties.\\\\ \\OUTPUTS\\---
+ Cmn9=----------------------------------------------------------------
+ Cmn10=--\\InitializeFb (d)\\- Password manager class initialized feedback\\
+ Cmn11=\\PasswordCout (a)\\- Analog feedback of current number of passwords||1
+ Cmn12=configured\\\\Username\\- Can be an alpha-numeric username OR will||1
+ Cmn13=become the index represented as a sring\\\\Password\\- Passowrd||1
+ Cmn14=for the username||1
+[END]
+[BEGIN]
+ ObjTp=Symbol
+ Exclusions=1,19,20,21,88,89,167,168,179,213,214,215,216,217,225,226,248,249,266,267,310,362,378,380,405,407,408,409,478,522,537,554,586,590,611,624,718,756,767,830,841,842,854,883,955,1032,1062,1079,1128,1129,1134,1140,1157,1158,1195,1199,1220,1221,1222,1223,1299,1348,1349,1439,1472,1473,1499,1746,1803,1975,2229,2354,2514,2523,2532,2706,2707,3235,3236,3427,3454,3567,3568,3601,3602,3708,3902,3903,3912,3918,3925,3926,4206,4207,
+ Exclusions_CDS=5
+ Inclusions_CDS=6,7
+ Name=PepperDash_Core_Password_Manager_A4sA3s_v02.00
+ SmplCName=PepperDash_Core_Password_Manager_A4sA3s_v02.00.usp
+ Code=1
+ SysRev5=4.006
+ SMWRev=3.00.00
+ InputCue1=[~UNUSED~]
+ InputSigType1=Digital
+ InputCue2=DebugEnable
+ InputSigType2=Digital
+ InputCue3=Initialize
+ InputSigType3=Digital
+ InputCue4=[~UNUSED~]
+ InputSigType4=Digital
+ InputCue5=ListEntries
+ InputSigType5=Digital
+ OutputCue1=[~UNUSED~]
+ OutputSigType1=Digital
+ OutputCue2=[~UNUSED~]
+ OutputSigType2=Digital
+ OutputCue3=InitializedFb
+ OutputSigType3=Digital
+ OutputCue4=[~UNUSED~]
+ OutputSigType4=Digital
+ OutputCue5=[~UNUSED~]
+ OutputSigType5=Digital
+ InputList2Cue1=[~UNUSED~]
+ InputList2SigType1=Serial
+ InputList2Cue2=Username[1]
+ InputList2SigType2=Serial
+ InputList2Cue3=Username[2]
+ InputList2SigType3=Serial
+ InputList2Cue4=Username[3]
+ InputList2SigType4=Serial
+ InputList2Cue5=Username[4]
+ InputList2SigType5=Serial
+ InputList2Cue6=Username[5]
+ InputList2SigType6=Serial
+ InputList2Cue7=Username[6]
+ InputList2SigType7=Serial
+ InputList2Cue8=Username[7]
+ InputList2SigType8=Serial
+ InputList2Cue9=Username[8]
+ InputList2SigType9=Serial
+ InputList2Cue10=Username[9]
+ InputList2SigType10=Serial
+ InputList2Cue11=Username[10]
+ InputList2SigType11=Serial
+ InputList2Cue12=[~UNUSED~]
+ InputList2SigType12=Serial
+ InputList2Cue13=Password[#]
+ InputList2SigType13=Serial
+ OutputList2Cue1=[~UNUSED~]
+ OutputList2SigType1=Analog
+ OutputList2Cue2=PasswordCount
+ OutputList2SigType2=Analog
+ ParamCue1=[Reference Name]
+ MinVariableInputs=5
+ MaxVariableInputs=5
+ MinVariableInputsList2=22
+ MaxVariableInputsList2=22
+ MinVariableOutputs=5
+ MaxVariableOutputs=5
+ MinVariableOutputsList2=2
+ MaxVariableOutputsList2=2
+ MinVariableParams=0
+ MaxVariableParams=0
+ Expand=expand_inputs_with_outputs
+ Expand2=expand_inputs_with_outputs
+ ProgramTree=Logic
+ SymbolTree=46
+ UserSymTreeName=PepperDash Technology
+ Hint=
+ PdfHelp=
+ HelpID=
+ Render=4
+ Smpl-C=16
+ CompilerCode=-48
+ CompilerParamCode=27
+ CompilerParamCode5=14
+ NumFixedParams=1
+ Pp1=1
+ MPp=1
+ NVStorage=10
+ ParamSigType1=String
+ SmplCInputCue1=o#
+ SmplCOutputCue1=i#
+ SmplCInputList2Cue1=an#
+ SmplCOutputList2Cue1=ai#
+ SPlus2CompiledName=S2_PepperDash_Core_Password_Manager_A4sA3s_v02_00
+ SymJam=NonExclusive
+ FileName=PepperDash_Core_Password_Manager_A4sA3s_v02.00.ush
+ SIMPLPlusModuleEncoding=0
+ clz1=PepperDash_Core
+[END]
+[BEGIN]
+ ObjTp=Dp
+ H=1
+ Tp=1
+ NoS=False
+[END]
diff --git a/src/PasswordManagement/PepperDash_Core_Password_Manager_A4sA3s_v02.00.usp b/src/PasswordManagement/PepperDash_Core_Password_Manager_A4sA3s_v02.00.usp
new file mode 100644
index 0000000..ea48295
--- /dev/null
+++ b/src/PasswordManagement/PepperDash_Core_Password_Manager_A4sA3s_v02.00.usp
@@ -0,0 +1,257 @@
+ /*******************************************************************************************
+Dealer Name: PepperDash Technology Corp.
+Programmer: PepperDash Technology Corp.
+Copyright: 2026
+********************************************************************************************
+Notice of Ownership and Copyright
+
+The material in which this notice appears is the property of PepperDash Technology Corporation,
+which claims copyright under the laws of the United States of America in the entire body of
+material and in all parts thereof, regardless of the use to which it is being put. Any use,
+in whole or in part, of this material by another party without the express written permission
+of PepperDash Technology Corporation is prohibited.
+
+PepperDash Technology Corporation reserves all rights under applicable laws.
+*******************************************************************************************/
+/*******************************************************************************************
+Compiler Directives
+(Uncomment and declare compiler directives as needed)
+*******************************************************************************************/
+#CATEGORY "46" "PepperDash Technology"
+#DEFAULT_VOLATILE
+#ENABLE_STACK_CHECKING
+#ENABLE_TRACE
+#DIGITAL_EXPAND InputsWithOutputs
+#ANALOG_SERIAL_EXPAND InputsWithOutputs
+
+#DEFINE_CONSTANT MAX_LEN_SYMBOL 50
+#DEFINE_CONSTANT MAX_LEN_MSG 200
+#DEFINE_CONSTANT MAX_LEN_STR 250
+
+#DEFINE_CONSTANT MAX_PASSWORDS 10
+
+#HELP_BEGIN
+INPUTS
+---------------------------------------------------------------------
+DebugEnable (d)
+- Enables/disables debug of the password manager class
+
+Initialize (d)
+- Initializes the password manager class
+
+ListPassword (d)
+- Prints the configured passwords to console
+
+PasswordUpdate[1-10] (s)
+- Accepts alpha-numeric pins/passwords that will be used
+ to validate clients against
+- These values can be driven statically from code (msend/sio), from config,
+ or from Fusion custom propeties.
+
+
+OUTPUTS
+---------------------------------------------------------------------
+InitializeFb (d)
+- Password manager class initialized feedback
+
+PasswordCout (a)
+- Analog feedback of current number of passwords configured
+#HELP_END
+
+/*******************************************************************************************
+Include Libraries
+(Uncomment and include additional libraries as needed)
+*******************************************************************************************/
+// comment out or remove when PepperDash_Core.clz is local to the module
+#INCLUDEPATH "..\bin"
+#USER_SIMPLSHARP_LIBRARY "PepperDash_Core"
+
+/*******************************************************************************************
+DIGITAL, ANALOG and SERIAL INPUTS and OUTPUTS
+(Uncomment and declare inputs and outputs as needed)
+*******************************************************************************************/
+DIGITAL_INPUT
+ _SKIP_,
+ DebugEnable,
+ Initialize,
+ _SKIP_,
+ ListEntries;
+
+STRING_INPUT
+ _SKIP_,
+ Username[MAX_PASSWORDS][MAX_LEN_STR],
+ _SKIP_,
+ Password[MAX_PASSWORDS,MAX_PASSWORDS][MAX_LEN_STR];
+
+DIGITAL_OUTPUT
+ _SKIP_,
+ _SKIP_,
+ InitializedFb,
+ _SKIP_,
+ _SKIP_;
+
+ANALOG_OUTPUT
+ _SKIP_,
+ PasswordCount;
+
+#HELP_BEGIN
+Username
+- Can be an alpha-numeric username OR will become the index represented as a sring
+
+Password
+- Passowrd for the username
+#HELP_END
+
+/*******************************************************************************************
+SIMPL # Class to be instantiated
+*******************************************************************************************/
+PasswordManager thisManager;
+
+/*******************************************************************************************
+Parameters
+(Uncomment and declare parameters as needed)
+*******************************************************************************************/
+
+/*******************************************************************************************
+Parameter Properties
+(Uncomment and declare parameter properties as needed)
+*******************************************************************************************/
+
+/*******************************************************************************************
+Structure Definitions
+(Uncomment and define structure definitions as needed)
+Note: Be sure to initialize all declared STRING variables as needed
+ For example, in Function Main: struct.myString = "";
+*******************************************************************************************/
+
+/*******************************************************************************************
+Global Variables
+(Uncomment and declare global variables as needed)
+Note: Be sure to initialize all declared STRING variables as needed
+ For example, in Function Main: myString = "";
+*******************************************************************************************/
+
+/*******************************************************************************************
+Functions
+(Add any additional functions here)
+Note: Functions must be physically placed before the location in
+ the code that calls them.
+*******************************************************************************************/
+Function UpdatePassword(Integer nKey)
+{
+ String un[MAX_LEN_STR];
+
+ If(Len(Username[nKey]) = 0)
+ {
+ un = ItoA(nKey);
+ }
+ Else
+ {
+ un = Username[nKey];
+ }
+ thisManager.UpdatePassword(un, Password[nKey]);
+}
+
+EventHandler BoolChanged(PasswordManager sender, BoolChangeEventArgs args)
+{
+ Integer i;
+
+ Switch(args.Type)
+ {
+ Case(PasswordConstants.BoolValueChange):
+ {
+ // generic bool change
+ }
+ Case(PasswordConstants.Initialized):
+ {
+ InitializedFb = args.IntValue;
+
+ If(InitializedFb)
+ {
+ For(i = 1 To MAX_PASSWORDS)
+ {
+ UpdatePassword(i);
+ }
+ }
+ }
+ Case(PasswordConstants.UpdateBusy):
+ {
+ If(DebugEnable) Trace("UpdateBusy: args[%u].Type[%u] = %u\r", args.Index, args.Type, args.IntValue);
+ }
+ Default:
+ {
+ If(DebugEnable) Trace("BoolChanged: args[%u].Type[%u] = %u\r", args.Index, args.Type, args.IntValue);
+ }
+ }
+}
+
+EventHandler UshrtChanged(PasswordManager sender, UshrtChangeEventArgs args)
+{
+ Switch(args.Type)
+ {
+ Case(PasswordConstants.UshrtValueChange):
+ {
+ // generic ushort change
+ }
+ Case(PasswordConstants.Count):
+ {
+ PasswordCount = args.IntValue;
+ }
+ Default:
+ {
+ If(DebugEnable) Trace("UshortChanged: args[%u].Type[%u] = %u\r", args.Index, args.Type, args.IntValue);
+ }
+ }
+}
+
+EventHandler StringChanged(PasswordManager sender, StringChangeEventArgs args)
+{
+ Switch(args.Type)
+ {
+ Case(PasswordConstants.StringValueChange):
+ {
+ // generic string change
+ }
+ Default:
+ {
+ If(DebugEnable) Trace("StringChanged: args[%u].Type[%u] = %s\r", args.Index, args.Type, args.StringValue);
+ }
+ }
+}
+
+/*******************************************************************************************
+Event Handlers
+(Uncomment and declare additional event handlers as needed)
+*******************************************************************************************/
+Push Initialize
+{
+ If(InitializedFb)
+ Return;
+
+ thisManager.Initialize();
+}
+
+Push ListEntries
+{
+ thisManager.ListEntries();
+}
+
+Threadsafe Change Password
+{
+ If(InitializedFb)
+ UpdatePassword(GetLastModifiedArrayIndex());
+}
+
+/*******************************************************************************************
+Main()
+Uncomment and place one-time startup code here
+(This code will get called when the system starts up)
+*******************************************************************************************/
+Function Main()
+{
+ RegisterEvent(thisManager, BoolChange, BoolChanged);
+ RegisterEvent(thisManager, UshrtChange, UshrtChanged);
+ RegisterEvent(thisManager, StringChange, StringChanged);
+
+ WaitForInitializationComplete();
+}
diff --git a/src/PasswordManagement/PepperDash_Core_Passwords-e4s-v02.00_compiled.zip b/src/PasswordManagement/PepperDash_Core_Passwords-e4s-v02.00_compiled.zip
new file mode 100644
index 0000000..0db8e5b
Binary files /dev/null and b/src/PasswordManagement/PepperDash_Core_Passwords-e4s-v02.00_compiled.zip differ
diff --git a/src/PepperDash_Core.csproj b/src/PepperDash_Core.csproj
index 372ad04..4b81397 100644
--- a/src/PepperDash_Core.csproj
+++ b/src/PepperDash_Core.csproj
@@ -1,156 +1,157 @@
-
-
- Release
- AnyCPU
- 9.0.30729
- 2.0
- {87E29B4C-569B-4368-A4ED-984AC1440C96}
- Library
- Properties
- PepperDash.Core
- PepperDash_Core
- {0B4745B0-194B-4BB6-8E21-E9057CA92500};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- WindowsCE
- E2BECB1F-8C8C-41ba-B736-9BE7D946A398
- 5.0
- SmartDeviceProject1
- v3.5
- Windows CE
-
-
-
-
- .allowedReferenceRelatedFileExtensions
- true
- full
- false
- bin\
- DEBUG;TRACE;
- prompt
- 4
- 512
- true
- true
- bin\PepperDash_Core.xml
-
-
- .allowedReferenceRelatedFileExtensions
- none
- true
- bin\
- prompt
- 4
- 512
- true
- true
- bin\PepperDash_Core.xml
-
-
-
-
- False
- ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll
-
-
- False
- ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCWSHelperInterface.dll
-
-
- False
- ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll
-
-
- False
- ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll
-
-
- False
- ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Code
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- rem S# preparation will execute after these operations
+
+
+ Release
+ AnyCPU
+ 9.0.30729
+ 2.0
+ {87E29B4C-569B-4368-A4ED-984AC1440C96}
+ Library
+ Properties
+ PepperDash.Core
+ PepperDash_Core
+ {0B4745B0-194B-4BB6-8E21-E9057CA92500};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ WindowsCE
+ E2BECB1F-8C8C-41ba-B736-9BE7D946A398
+ 5.0
+ SmartDeviceProject1
+ v3.5
+ Windows CE
+
+
+
+
+ .allowedReferenceRelatedFileExtensions
+ true
+ full
+ false
+ bin\
+ DEBUG;TRACE;
+ prompt
+ 4
+ 512
+ true
+ true
+ bin\PepperDash_Core.xml
+
+
+ .allowedReferenceRelatedFileExtensions
+ none
+ true
+ bin\
+ prompt
+ 4
+ 512
+ true
+ true
+ bin\PepperDash_Core.xml
+
+
+
+
+ False
+ ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll
+
+
+ False
+ ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCWSHelperInterface.dll
+
+
+ False
+ ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll
+
+
+ False
+ ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll
+
+
+ False
+ ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ rem S# preparation will execute after these operations
del "$(TargetDir)PepperDash_Core.*" /q
-
-
+
+
\ No newline at end of file