diff --git a/.github/workflows/essentials-3-dev-build.yml b/.github/workflows/essentials-3-dev-build.yml new file mode 100644 index 000000000..3943d5be1 --- /dev/null +++ b/.github/workflows/essentials-3-dev-build.yml @@ -0,0 +1,247 @@ +name: Essentials v3 Development Build + +on: + push: + branches: + - feature-3.0.0/* + - hotfix-3.0.0/* + - release-3.0.0/* + - development-3.0.0 + +env: + SOLUTION_PATH: . + SOLUTION_FILE: PepperDash.Essentials + VERSION: 0.0.0-buildtype-buildnumber + BUILD_TYPE: Debug + RELEASE_BRANCH: main +jobs: + Build_Project_4-Series: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + # Detect environment (Act vs GitHub) + - name: Detect environment + id: detect_env + run: | + if [ -n "$ACT" ]; then + echo "is_local=true" >> $GITHUB_OUTPUT + else + echo "is_local=false" >> $GITHUB_OUTPUT + fi + + - name: Install prerequisites + run: | + if [ "${{ steps.detect_env.outputs.is_local }}" == "true" ]; then + # For Act - no sudo needed + apt-get update + apt-get install -y curl wget libicu-dev git unzip + else + # For GitHub runners - sudo required + sudo apt-get update + sudo apt-get install -y curl wget libicu-dev git unzip + fi + + - name: Set Version Number + id: setVersion + shell: bash + run: | + latestVersion="3.0.0" + newVersion=$latestVersion + phase="" + newVersionString="" + + if [[ $GITHUB_REF =~ ^refs/pull/.* ]]; then + phase="beta" + newVersionString="${newVersion}-${phase}-${GITHUB_RUN_NUMBER}" + elif [[ $GITHUB_REF =~ ^refs/heads/hotfix-3.0.0/.* ]]; then + phase="hotfix" + newVersionString="${newVersion}-${phase}-${GITHUB_RUN_NUMBER}" + elif [[ $GITHUB_REF =~ ^refs/heads/feature-3.0.0/.* ]]; then + phase="alpha" + newVersionString="${newVersion}-${phase}-${GITHUB_RUN_NUMBER}" + elif [[ $GITHUB_REF == "refs/heads/development-3.0.0" ]]; then + phase="beta" + newVersionString="${newVersion}-${phase}-${GITHUB_RUN_NUMBER}" + elif [[ $GITHUB_REF =~ ^refs/heads/release-3.0.0/.* ]]; then + version=$(echo $GITHUB_REF | awk -F '/' '{print $NF}' | sed 's/v//') + phase="rc" + newVersionString="${version}-${phase}-${GITHUB_RUN_NUMBER}" + else + # For local builds or unrecognized branches + newVersionString="${newVersion}-local" + fi + + echo "version=$newVersionString" >> $GITHUB_OUTPUT + + # Create Build Properties file + - name: Create Build Properties + run: | + cat > Directory.Build.props << EOF + + + ${{ steps.setVersion.outputs.version }} + ${{ steps.setVersion.outputs.version }} + ${{ steps.setVersion.outputs.version }} + ${{ steps.setVersion.outputs.version }} + ${{ steps.setVersion.outputs.version }} + ${{ steps.setVersion.outputs.version }} + + + EOF + + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.0.x' + + - name: Restore NuGet Packages + run: dotnet restore ${SOLUTION_FILE}.sln + + - name: Build Solution + run: dotnet build ${SOLUTION_FILE}.sln --configuration ${BUILD_TYPE} --no-restore + + # Copy the CPZ file to the output directory with version in the filename + - name: Copy and Rename CPZ Files + run: | + mkdir -p ./output/cpz + + # Find the main CPZ file in the build output + if [ -f "./src/PepperDash.Essentials/bin/${BUILD_TYPE}/net8/PepperDashEssentials.cpz" ]; then + cp "./src/PepperDash.Essentials/bin/${BUILD_TYPE}/net8/PepperDashEssentials.cpz" "./output/cpz/PepperDashEssentials.${{ steps.setVersion.outputs.version }}.cpz" + echo "Main CPZ file copied and renamed successfully." + else + echo "Warning: Main CPZ file not found at expected location." + find ./src -name "*.cpz" | xargs -I {} cp {} ./output/cpz/ + fi + + - name: Pack Solution + run: dotnet pack ${SOLUTION_FILE}.sln --configuration ${BUILD_TYPE} --output ./output/nuget --no-build + + # List build artifacts (runs in both environments) + - name: List Build Artifacts + run: | + echo "=== Build Artifacts ===" + echo "NuGet Packages:" + find ./output/nuget -type f | sort + echo "" + echo "CPZ/CPLZ Files:" + find ./output -name "*.cpz" -o -name "*.cplz" | sort + echo "=======================" + + # Enhanced package inspection for local runs + - name: Inspect NuGet Packages + if: steps.detect_env.outputs.is_local == 'true' + run: | + echo "=== NuGet Package Details ===" + for pkg in $(find ./output/nuget -name "*.nupkg"); do + echo "Package: $(basename "$pkg")" + echo "Size: $(du -h "$pkg" | cut -f1)" + + # Extract and show package contents + echo "Contents:" + unzip -l "$pkg" | tail -n +4 | head -n -2 + echo "--------------------------" + + # Try to extract and show the nuspec file (contains metadata) + echo "Metadata:" + unzip -p "$pkg" "*.nuspec" 2>/dev/null | grep -E "(||||)" || echo "Metadata extraction failed" + echo "--------------------------" + done + echo "===========================" + + # Tag creation - GitHub version + - name: Create tag for non-rc builds (GitHub) + if: ${{ !contains(steps.setVersion.outputs.version, 'rc') && steps.detect_env.outputs.is_local == 'false' }} + run: | + git config --global user.name "GitHub Actions" + git config --global user.email "actions@github.com" + git tag ${{ steps.setVersion.outputs.version }} + git push --tags origin + + # Tag creation - Act mock version + - name: Create tag for non-rc builds (Act Mock) + if: ${{ !contains(steps.setVersion.outputs.version, 'rc') && steps.detect_env.outputs.is_local == 'true' }} + run: | + echo "Would create git tag: ${{ steps.setVersion.outputs.version }}" + echo "Would push tag to: origin" + + # Release creation - GitHub version + - name: Create Release (GitHub) + if: steps.detect_env.outputs.is_local == 'false' + id: create_release + uses: ncipollo/release-action@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + artifacts: 'output/cpz/*,output/**/*.cplz' + generateReleaseNotes: true + prerelease: ${{contains('debug', env.BUILD_TYPE)}} + tag: ${{ steps.setVersion.outputs.version }} + + # Release creation - Act mock version with enhanced output + - name: Create Release (Act Mock) + if: steps.detect_env.outputs.is_local == 'true' + run: | + echo "=== Mock Release Creation ===" + echo "Would create release with:" + echo "- Tag: ${{ steps.setVersion.outputs.version }}" + echo "- Prerelease: ${{contains('debug', env.BUILD_TYPE)}}" + echo "- Artifacts matching pattern: output/cpz/*,output/**/*.cplz" + echo "" + echo "Matching artifacts:" + find ./output/cpz -type f + find ./output -name "*.cplz" + + # Detailed info about release artifacts + echo "" + echo "Artifact Details:" + for artifact in $(find ./output/cpz -type f; find ./output -name "*.cplz"); do + echo "File: $(basename "$artifact")" + echo "Size: $(du -h "$artifact" | cut -f1)" + echo "Created: $(stat -c %y "$artifact")" + echo "MD5: $(md5sum "$artifact" | cut -d' ' -f1)" + echo "--------------------------" + done + echo "============================" + + # NuGet setup - GitHub version + - name: Setup NuGet (GitHub) + if: steps.detect_env.outputs.is_local == 'false' + run: | + dotnet nuget add source https://nuget.pkg.github.com/pepperdash/index.json -n github -u pepperdash -p ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text + + # NuGet setup - Act mock version + - name: Setup NuGet (Act Mock) + if: steps.detect_env.outputs.is_local == 'true' + run: | + echo "=== Mock NuGet Setup ===" + echo "Would add GitHub NuGet source: https://nuget.pkg.github.com/pepperdash/index.json" + echo "=======================" + + # Publish to NuGet - GitHub version + - name: Publish to Nuget (GitHub) + if: steps.detect_env.outputs.is_local == 'false' + run: dotnet nuget push ./output/nuget/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }} + + # Publish to NuGet - Act mock version + - name: Publish to Nuget (Act Mock) + if: steps.detect_env.outputs.is_local == 'true' + run: | + echo "=== Mock Publish to NuGet ===" + echo "Would publish the following packages to https://api.nuget.org/v3/index.json:" + find ./output/nuget -name "*.nupkg" | sort + echo "=============================" + + # Publish to GitHub NuGet - GitHub version + - name: Publish to Github Nuget (GitHub) + if: steps.detect_env.outputs.is_local == 'false' + run: dotnet nuget push ./output/nuget/*.nupkg --source github --api-key ${{ secrets.GITHUB_TOKEN }} + + # Publish to GitHub NuGet - Act mock version + - name: Publish to Github Nuget (Act Mock) + if: steps.detect_env.outputs.is_local == 'true' + run: | + echo "=== Mock Publish to GitHub NuGet ===" + echo "Would publish the following packages to the GitHub NuGet registry:" + find ./output/nuget -name "*.nupkg" | sort + echo "==================================" \ No newline at end of file diff --git a/Crestron-Library-Usage-Analysis.md b/Crestron-Library-Usage-Analysis.md new file mode 100644 index 000000000..e69de29bb diff --git a/runtimeconfig.json b/runtimeconfig.json new file mode 100644 index 000000000..32835bac5 --- /dev/null +++ b/runtimeconfig.json @@ -0,0 +1,7 @@ +{ + "runtimeOptions": { + "configProperties": { + "System.Globalization.Invariant": false + } + } +} diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 152c9f180..ef8e86b0e 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,6 +1,6 @@ - 2.4.0-local + 3.0.0-local $(Version) PepperDash Technology PepperDash Technology diff --git a/src/PepperDash.Core/Comm/CommunicationGather.cs b/src/PepperDash.Core/Comm/CommunicationGather.cs index 9ffe8262b..27d42888d 100644 --- a/src/PepperDash.Core/Comm/CommunicationGather.cs +++ b/src/PepperDash.Core/Comm/CommunicationGather.cs @@ -8,8 +8,8 @@ using PepperDash.Core; -namespace PepperDash.Core -{ +namespace PepperDash.Core; + /// /// Defines the string event handler for line events on the gather /// @@ -30,7 +30,7 @@ public class CommunicationGather /// /// The communication port that this gathers on /// - public ICommunicationReceiver Port { get; private set; } + public ICommunicationReceiver Port { get; private set; } /// /// Default false. If true, the delimiter will be included in the line output @@ -67,22 +67,22 @@ public CommunicationGather(ICommunicationReceiver port, char delimiter) /// /// /// - public CommunicationGather(ICommunicationReceiver port, string delimiter) - :this(port, new string[] { delimiter} ) + public CommunicationGather(ICommunicationReceiver port, string delimiter) + :this(port, new string[] { delimiter} ) { } - /// - /// Constructor for using an array of string delimiters - /// - /// - /// - public CommunicationGather(ICommunicationReceiver port, string[] delimiters) - { - Port = port; - StringDelimiters = delimiters; - port.TextReceived += Port_TextReceivedStringDelimiter; - } + /// + /// Constructor for using an array of string delimiters + /// + /// + /// + public CommunicationGather(ICommunicationReceiver port, string[] delimiters) + { + Port = port; + StringDelimiters = delimiters; + port.TextReceived += Port_TextReceivedStringDelimiter; + } /// /// Disconnects this gather from the Port's TextReceived event. This will not fire LineReceived @@ -136,35 +136,35 @@ void Port_TextReceivedStringDelimiter(object sender, GenericCommMethodReceiveTex ReceiveBuffer.Append(args.Text); var str = ReceiveBuffer.ToString(); - // Case: Receiving DEVICE get version\x0d\0x0a+OK "value":"1234"\x0d\x0a - - // RX: DEV - // Split: (1) "DEV" - // RX: I - // Split: (1) "DEVI" - // RX: CE get version - // Split: (1) "DEVICE get version" - // RX: \x0d\x0a+OK "value":"1234"\x0d\x0a - // Split: (2) DEVICE get version, +OK "value":"1234" - - // Iterate the delimiters and fire an event for any matching delimiter - foreach (var delimiter in StringDelimiters) + // Case: Receiving DEVICE get version\x0d\0x0a+OK "value":"1234"\x0d\x0a + + // RX: DEV + // Split: (1) "DEV" + // RX: I + // Split: (1) "DEVI" + // RX: CE get version + // Split: (1) "DEVICE get version" + // RX: \x0d\x0a+OK "value":"1234"\x0d\x0a + // Split: (2) DEVICE get version, +OK "value":"1234" + + // Iterate the delimiters and fire an event for any matching delimiter + foreach (var delimiter in StringDelimiters) + { + var lines = Regex.Split(str, delimiter); + if (lines.Length == 1) + continue; + + for (int i = 0; i < lines.Length - 1; i++) { - var lines = Regex.Split(str, delimiter); - if (lines.Length == 1) - continue; - - for (int i = 0; i < lines.Length - 1; i++) - { - string strToSend = null; - if (IncludeDelimiter) - strToSend = lines[i] + delimiter; - else - strToSend = lines[i]; - handler(this, new GenericCommMethodReceiveTextArgs(strToSend, delimiter)); - } - ReceiveBuffer = new StringBuilder(lines[lines.Length - 1]); + string strToSend = null; + if (IncludeDelimiter) + strToSend = lines[i] + delimiter; + else + strToSend = lines[i]; + handler(this, new GenericCommMethodReceiveTextArgs(strToSend, delimiter)); } + ReceiveBuffer = new StringBuilder(lines[lines.Length - 1]); + } } } @@ -175,5 +175,4 @@ void Port_TextReceivedStringDelimiter(object sender, GenericCommMethodReceiveTex { Stop(); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/Comm/CommunicationStreamDebugging.cs b/src/PepperDash.Core/Comm/CommunicationStreamDebugging.cs index 0a38d826e..1b3cfb1f2 100644 --- a/src/PepperDash.Core/Comm/CommunicationStreamDebugging.cs +++ b/src/PepperDash.Core/Comm/CommunicationStreamDebugging.cs @@ -5,173 +5,172 @@ using Crestron.SimplSharp; using PepperDash.Core; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// Controls the ability to disable/enable debugging of TX/RX data sent to/from a device with a built in timer to disable +/// +public class CommunicationStreamDebugging { /// - /// Controls the ability to disable/enable debugging of TX/RX data sent to/from a device with a built in timer to disable + /// Device Key that this instance configures + /// + public string ParentDeviceKey { get; private set; } + + /// + /// Timer to disable automatically if not manually disabled + /// + private CTimer DebugExpiryPeriod; + + /// + /// The current debug setting + /// + public eStreamDebuggingSetting DebugSetting { get; private set; } + + private uint _DebugTimeoutInMs; + private const uint _DefaultDebugTimeoutMin = 30; + + /// + /// Timeout in Minutes /// - public class CommunicationStreamDebugging + public uint DebugTimeoutMinutes { - /// - /// Device Key that this instance configures - /// - public string ParentDeviceKey { get; private set; } - - /// - /// Timer to disable automatically if not manually disabled - /// - private CTimer DebugExpiryPeriod; - - /// - /// The current debug setting - /// - public eStreamDebuggingSetting DebugSetting { get; private set; } - - private uint _DebugTimeoutInMs; - private const uint _DefaultDebugTimeoutMin = 30; - - /// - /// Timeout in Minutes - /// - public uint DebugTimeoutMinutes + get { - get - { - return _DebugTimeoutInMs/60000; - } + return _DebugTimeoutInMs/60000; } + } + + /// + /// Indicates that receive stream debugging is enabled + /// + public bool RxStreamDebuggingIsEnabled{ get; private set; } + + /// + /// Indicates that transmit stream debugging is enabled + /// + public bool TxStreamDebuggingIsEnabled { get; private set; } + + /// + /// Constructor + /// + /// + public CommunicationStreamDebugging(string parentDeviceKey) + { + ParentDeviceKey = parentDeviceKey; + } + - /// - /// Indicates that receive stream debugging is enabled - /// - public bool RxStreamDebuggingIsEnabled{ get; private set; } - - /// - /// Indicates that transmit stream debugging is enabled - /// - public bool TxStreamDebuggingIsEnabled { get; private set; } - - /// - /// Constructor - /// - /// - public CommunicationStreamDebugging(string parentDeviceKey) + /// + /// Sets the debugging setting and if not setting to off, assumes the default of 30 mintues + /// + /// + public void SetDebuggingWithDefaultTimeout(eStreamDebuggingSetting setting) + { + if (setting == eStreamDebuggingSetting.Off) { - ParentDeviceKey = parentDeviceKey; + DisableDebugging(); + return; } + SetDebuggingWithSpecificTimeout(setting, _DefaultDebugTimeoutMin); + } - /// - /// Sets the debugging setting and if not setting to off, assumes the default of 30 mintues - /// - /// - public void SetDebuggingWithDefaultTimeout(eStreamDebuggingSetting setting) + /// + /// Sets the debugging setting for the specified number of minutes + /// + /// + /// + public void SetDebuggingWithSpecificTimeout(eStreamDebuggingSetting setting, uint minutes) + { + if (setting == eStreamDebuggingSetting.Off) { - if (setting == eStreamDebuggingSetting.Off) - { - DisableDebugging(); - return; - } - - SetDebuggingWithSpecificTimeout(setting, _DefaultDebugTimeoutMin); + DisableDebugging(); + return; } - /// - /// Sets the debugging setting for the specified number of minutes - /// - /// - /// - public void SetDebuggingWithSpecificTimeout(eStreamDebuggingSetting setting, uint minutes) - { - if (setting == eStreamDebuggingSetting.Off) - { - DisableDebugging(); - return; - } + _DebugTimeoutInMs = minutes * 60000; - _DebugTimeoutInMs = minutes * 60000; + StopDebugTimer(); - StopDebugTimer(); + DebugExpiryPeriod = new CTimer((o) => DisableDebugging(), _DebugTimeoutInMs); - DebugExpiryPeriod = new CTimer((o) => DisableDebugging(), _DebugTimeoutInMs); + if ((setting & eStreamDebuggingSetting.Rx) == eStreamDebuggingSetting.Rx) + RxStreamDebuggingIsEnabled = true; - if ((setting & eStreamDebuggingSetting.Rx) == eStreamDebuggingSetting.Rx) - RxStreamDebuggingIsEnabled = true; + if ((setting & eStreamDebuggingSetting.Tx) == eStreamDebuggingSetting.Tx) + TxStreamDebuggingIsEnabled = true; - if ((setting & eStreamDebuggingSetting.Tx) == eStreamDebuggingSetting.Tx) - TxStreamDebuggingIsEnabled = true; + Debug.SetDeviceDebugSettings(ParentDeviceKey, setting); + + } - Debug.SetDeviceDebugSettings(ParentDeviceKey, setting); - - } + /// + /// Disabled debugging + /// + private void DisableDebugging() + { + StopDebugTimer(); - /// - /// Disabled debugging - /// - private void DisableDebugging() - { - StopDebugTimer(); + Debug.SetDeviceDebugSettings(ParentDeviceKey, eStreamDebuggingSetting.Off); + } - Debug.SetDeviceDebugSettings(ParentDeviceKey, eStreamDebuggingSetting.Off); - } + private void StopDebugTimer() + { + RxStreamDebuggingIsEnabled = false; + TxStreamDebuggingIsEnabled = false; - private void StopDebugTimer() + if (DebugExpiryPeriod == null) { - RxStreamDebuggingIsEnabled = false; - TxStreamDebuggingIsEnabled = false; - - if (DebugExpiryPeriod == null) - { - return; - } - - DebugExpiryPeriod.Stop(); - DebugExpiryPeriod.Dispose(); - DebugExpiryPeriod = null; + return; } + + DebugExpiryPeriod.Stop(); + DebugExpiryPeriod.Dispose(); + DebugExpiryPeriod = null; } +} +/// +/// The available settings for stream debugging +/// +[Flags] +public enum eStreamDebuggingSetting +{ /// - /// The available settings for stream debugging + /// Debug off /// - [Flags] - public enum eStreamDebuggingSetting - { - /// - /// Debug off - /// - Off = 0, - /// - /// Debug received data - /// - Rx = 1, - /// - /// Debug transmitted data - /// - Tx = 2, - /// - /// Debug both received and transmitted data - /// - Both = Rx | Tx - } + Off = 0, + /// + /// Debug received data + /// + Rx = 1, + /// + /// Debug transmitted data + /// + Tx = 2, + /// + /// Debug both received and transmitted data + /// + Both = Rx | Tx +} +/// +/// The available settings for stream debugging response types +/// +[Flags] +public enum eStreamDebuggingDataTypeSettings +{ /// - /// The available settings for stream debugging response types + /// Debug data in byte format /// - [Flags] - public enum eStreamDebuggingDataTypeSettings - { - /// - /// Debug data in byte format - /// - Bytes = 0, - /// - /// Debug data in text format - /// - Text = 1, - /// - /// Debug data in both byte and text formats - /// - Both = Bytes | Text, - } + Bytes = 0, + /// + /// Debug data in text format + /// + Text = 1, + /// + /// Debug data in both byte and text formats + /// + Both = Bytes | Text, } diff --git a/src/PepperDash.Core/Comm/ControlPropertiesConfig.cs b/src/PepperDash.Core/Comm/ControlPropertiesConfig.cs index ff869f779..d0dd2b97a 100644 --- a/src/PepperDash.Core/Comm/ControlPropertiesConfig.cs +++ b/src/PepperDash.Core/Comm/ControlPropertiesConfig.cs @@ -3,91 +3,90 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// Config properties that indicate how to communicate with a device for control +/// +public class ControlPropertiesConfig { /// - /// Config properties that indicate how to communicate with a device for control + /// The method of control /// - public class ControlPropertiesConfig - { - /// - /// The method of control - /// - [JsonProperty("method")] - [JsonConverter(typeof(StringEnumConverter))] - public eControlMethod Method { get; set; } + [JsonProperty("method")] + [JsonConverter(typeof(StringEnumConverter))] + public eControlMethod Method { get; set; } - /// - /// The key of the device that contains the control port - /// - [JsonProperty("controlPortDevKey", NullValueHandling = NullValueHandling.Ignore)] - public string ControlPortDevKey { get; set; } + /// + /// The key of the device that contains the control port + /// + [JsonProperty("controlPortDevKey", NullValueHandling = NullValueHandling.Ignore)] + public string ControlPortDevKey { get; set; } - /// - /// The number of the control port on the device specified by ControlPortDevKey - /// - [JsonProperty("controlPortNumber", NullValueHandling = NullValueHandling.Ignore)] // In case "null" is present in config on this value - public uint? ControlPortNumber { get; set; } + /// + /// The number of the control port on the device specified by ControlPortDevKey + /// + [JsonProperty("controlPortNumber", NullValueHandling = NullValueHandling.Ignore)] // In case "null" is present in config on this value + public uint? ControlPortNumber { get; set; } - /// - /// The name of the control port on the device specified by ControlPortDevKey - /// - [JsonProperty("controlPortName", NullValueHandling = NullValueHandling.Ignore)] // In case "null" is present in config on this value - public string ControlPortName { get; set; } + /// + /// The name of the control port on the device specified by ControlPortDevKey + /// + [JsonProperty("controlPortName", NullValueHandling = NullValueHandling.Ignore)] // In case "null" is present in config on this value + public string ControlPortName { get; set; } - /// - /// Properties for ethernet based communications - /// - [JsonProperty("tcpSshProperties", NullValueHandling = NullValueHandling.Ignore)] - public TcpSshPropertiesConfig TcpSshProperties { get; set; } + /// + /// Properties for ethernet based communications + /// + [JsonProperty("tcpSshProperties", NullValueHandling = NullValueHandling.Ignore)] + public TcpSshPropertiesConfig TcpSshProperties { get; set; } - /// - /// The filename and path for the IR file - /// - [JsonProperty("irFile", NullValueHandling = NullValueHandling.Ignore)] - public string IrFile { get; set; } + /// + /// The filename and path for the IR file + /// + [JsonProperty("irFile", NullValueHandling = NullValueHandling.Ignore)] + public string IrFile { get; set; } - /// - /// The IpId of a Crestron device - /// - [JsonProperty("ipId", NullValueHandling = NullValueHandling.Ignore)] - public string IpId { get; set; } + /// + /// The IpId of a Crestron device + /// + [JsonProperty("ipId", NullValueHandling = NullValueHandling.Ignore)] + public string IpId { get; set; } - /// - /// Readonly uint representation of the IpId - /// - [JsonIgnore] - public uint IpIdInt { get { return Convert.ToUInt32(IpId, 16); } } + /// + /// Readonly uint representation of the IpId + /// + [JsonIgnore] + public uint IpIdInt { get { return Convert.ToUInt32(IpId, 16); } } - /// - /// Char indicating end of line - /// - [JsonProperty("endOfLineChar", NullValueHandling = NullValueHandling.Ignore)] - public char EndOfLineChar { get; set; } + /// + /// Char indicating end of line + /// + [JsonProperty("endOfLineChar", NullValueHandling = NullValueHandling.Ignore)] + public char EndOfLineChar { get; set; } - /// - /// Defaults to Environment.NewLine; - /// - [JsonProperty("endOfLineString", NullValueHandling = NullValueHandling.Ignore)] - public string EndOfLineString { get; set; } + /// + /// Defaults to Environment.NewLine; + /// + [JsonProperty("endOfLineString", NullValueHandling = NullValueHandling.Ignore)] + public string EndOfLineString { get; set; } - /// - /// Indicates - /// - [JsonProperty("deviceReadyResponsePattern", NullValueHandling = NullValueHandling.Ignore)] - public string DeviceReadyResponsePattern { get; set; } + /// + /// Indicates + /// + [JsonProperty("deviceReadyResponsePattern", NullValueHandling = NullValueHandling.Ignore)] + public string DeviceReadyResponsePattern { get; set; } - /// - /// Used when communcating to programs running in VC-4 - /// - [JsonProperty("roomId", NullValueHandling = NullValueHandling.Ignore)] - public string RoomId { get; set; } + /// + /// Used when communcating to programs running in VC-4 + /// + [JsonProperty("roomId", NullValueHandling = NullValueHandling.Ignore)] + public string RoomId { get; set; } - /// - /// Constructor - /// - public ControlPropertiesConfig() - { - } + /// + /// Constructor + /// + public ControlPropertiesConfig() + { } } \ No newline at end of file diff --git a/src/PepperDash.Core/Comm/EventArgs.cs b/src/PepperDash.Core/Comm/EventArgs.cs index cf76d6b38..f018d0729 100644 --- a/src/PepperDash.Core/Comm/EventArgs.cs +++ b/src/PepperDash.Core/Comm/EventArgs.cs @@ -16,28 +16,28 @@ PepperDash Technology Corporation reserves all rights under applicable laws. using Crestron.SimplSharp.CrestronSockets; -namespace PepperDash.Core -{ - /// - /// Delegate for notifying of socket status changes - /// - /// - public delegate void GenericSocketStatusChangeEventDelegate(ISocketStatus client); +namespace PepperDash.Core; - /// - /// EventArgs class for socket status changes - /// +/// +/// Delegate for notifying of socket status changes +/// +/// +public delegate void GenericSocketStatusChangeEventDelegate(ISocketStatus client); + +/// +/// EventArgs class for socket status changes +/// public class GenericSocketStatusChageEventArgs : EventArgs { - /// - /// - /// + /// + /// + /// public ISocketStatus Client { get; private set; } - /// - /// - /// - /// + /// + /// + /// + /// public GenericSocketStatusChageEventArgs(ISocketStatus client) { Client = client; @@ -46,105 +46,105 @@ public GenericSocketStatusChageEventArgs(ISocketStatus client) /// S+ Constructor /// public GenericSocketStatusChageEventArgs() { } - } - +} + +/// +/// Delegate for notifying of TCP Server state changes +/// +/// +public delegate void GenericTcpServerStateChangedEventDelegate(ServerState state); + +/// +/// EventArgs class for TCP Server state changes +/// +public class GenericTcpServerStateChangedEventArgs : EventArgs +{ /// - /// Delegate for notifying of TCP Server state changes + /// /// - /// - public delegate void GenericTcpServerStateChangedEventDelegate(ServerState state); + public ServerState State { get; private set; } /// - /// EventArgs class for TCP Server state changes + /// /// - public class GenericTcpServerStateChangedEventArgs : EventArgs + /// + public GenericTcpServerStateChangedEventArgs(ServerState state) { - /// - /// - /// - public ServerState State { get; private set; } - - /// - /// - /// - /// - public GenericTcpServerStateChangedEventArgs(ServerState state) - { - State = state; - } + State = state; + } /// /// S+ Constructor /// public GenericTcpServerStateChangedEventArgs() { } - } +} + +/// +/// Delegate for TCP Server socket status changes +/// +/// +/// +/// +public delegate void GenericTcpServerSocketStatusChangeEventDelegate(object socket, uint clientIndex, SocketStatus clientStatus); +/// +/// EventArgs for TCP server socket status changes +/// +public class GenericTcpServerSocketStatusChangeEventArgs : EventArgs +{ + /// + /// + /// + public object Socket { get; private set; } + /// + /// + /// + public uint ReceivedFromClientIndex { get; private set; } + /// + /// + /// + public SocketStatus ClientStatus { get; set; } /// - /// Delegate for TCP Server socket status changes + /// /// /// - /// /// - public delegate void GenericTcpServerSocketStatusChangeEventDelegate(object socket, uint clientIndex, SocketStatus clientStatus); + public GenericTcpServerSocketStatusChangeEventArgs(object socket, SocketStatus clientStatus) + { + Socket = socket; + ClientStatus = clientStatus; + } + /// - /// EventArgs for TCP server socket status changes + /// /// - public class GenericTcpServerSocketStatusChangeEventArgs : EventArgs + /// + /// + /// + public GenericTcpServerSocketStatusChangeEventArgs(object socket, uint clientIndex, SocketStatus clientStatus) { - /// - /// - /// - public object Socket { get; private set; } - /// - /// - /// - public uint ReceivedFromClientIndex { get; private set; } - /// - /// - /// - public SocketStatus ClientStatus { get; set; } - - /// - /// - /// - /// - /// - public GenericTcpServerSocketStatusChangeEventArgs(object socket, SocketStatus clientStatus) - { - Socket = socket; - ClientStatus = clientStatus; - } - - /// - /// - /// - /// - /// - /// - public GenericTcpServerSocketStatusChangeEventArgs(object socket, uint clientIndex, SocketStatus clientStatus) - { - Socket = socket; - ReceivedFromClientIndex = clientIndex; - ClientStatus = clientStatus; - } + Socket = socket; + ReceivedFromClientIndex = clientIndex; + ClientStatus = clientStatus; + } /// /// S+ Constructor /// public GenericTcpServerSocketStatusChangeEventArgs() { } - } +} +/// +/// EventArgs for TCP server com method receive text +/// +public class GenericTcpServerCommMethodReceiveTextArgs : EventArgs +{ /// - /// EventArgs for TCP server com method receive text + /// + /// + public uint ReceivedFromClientIndex { get; private set; } + + /// + /// /// - public class GenericTcpServerCommMethodReceiveTextArgs : EventArgs - { - /// - /// - /// - public uint ReceivedFromClientIndex { get; private set; } - - /// - /// - /// public ushort ReceivedFromClientIndexShort { get @@ -153,99 +153,96 @@ public ushort ReceivedFromClientIndexShort } } - /// - /// - /// - public string Text { get; private set; } - - /// - /// - /// - /// - public GenericTcpServerCommMethodReceiveTextArgs(string text) - { - Text = text; - } - - /// - /// - /// - /// - /// - public GenericTcpServerCommMethodReceiveTextArgs(string text, uint clientIndex) - { - Text = text; - ReceivedFromClientIndex = clientIndex; - } + /// + /// + /// + public string Text { get; private set; } + + /// + /// + /// + /// + public GenericTcpServerCommMethodReceiveTextArgs(string text) + { + Text = text; + } + + /// + /// + /// + /// + /// + public GenericTcpServerCommMethodReceiveTextArgs(string text, uint clientIndex) + { + Text = text; + ReceivedFromClientIndex = clientIndex; + } /// /// S+ Constructor /// public GenericTcpServerCommMethodReceiveTextArgs() { } - } +} + +/// +/// EventArgs for TCP server client ready for communication +/// +public class GenericTcpServerClientReadyForcommunicationsEventArgs : EventArgs +{ + /// + /// + /// + public bool IsReady; /// - /// EventArgs for TCP server client ready for communication + /// /// - public class GenericTcpServerClientReadyForcommunicationsEventArgs : EventArgs + /// + public GenericTcpServerClientReadyForcommunicationsEventArgs(bool isReady) { - /// - /// - /// - public bool IsReady; - - /// - /// - /// - /// - public GenericTcpServerClientReadyForcommunicationsEventArgs(bool isReady) - { - IsReady = isReady; - } + IsReady = isReady; + } /// /// S+ Constructor /// public GenericTcpServerClientReadyForcommunicationsEventArgs() { } - } +} + +/// +/// EventArgs for UDP connected +/// +public class GenericUdpConnectedEventArgs : EventArgs +{ + /// + /// + /// + public ushort UConnected; + /// + /// + /// + public bool Connected; + + /// + /// Constructor + /// + public GenericUdpConnectedEventArgs() { } /// - /// EventArgs for UDP connected + /// /// - public class GenericUdpConnectedEventArgs : EventArgs + /// + public GenericUdpConnectedEventArgs(ushort uconnected) { - /// - /// - /// - public ushort UConnected; - /// - /// - /// - public bool Connected; - - /// - /// Constructor - /// - public GenericUdpConnectedEventArgs() { } - - /// - /// - /// - /// - public GenericUdpConnectedEventArgs(ushort uconnected) - { - UConnected = uconnected; - } - - /// - /// - /// - /// - public GenericUdpConnectedEventArgs(bool connected) - { - Connected = connected; - } + UConnected = uconnected; + } + /// + /// + /// + /// + public GenericUdpConnectedEventArgs(bool connected) + { + Connected = connected; } - +} -} \ No newline at end of file diff --git a/src/PepperDash.Core/Comm/GenericSecureTcpIpClient.cs b/src/PepperDash.Core/Comm/GenericSecureTcpIpClient.cs index 5ad2e29de..f78672865 100644 --- a/src/PepperDash.Core/Comm/GenericSecureTcpIpClient.cs +++ b/src/PepperDash.Core/Comm/GenericSecureTcpIpClient.cs @@ -7,949 +7,947 @@ using Crestron.SimplSharp.CrestronSockets; using PepperDash.Core.Logging; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// A class to handle secure TCP/IP communications with a server +/// +public class GenericSecureTcpIpClient : Device, ISocketStatusWithStreamDebugging, IAutoReconnect { + private const string SplusKey = "Uninitialized Secure Tcp _client"; /// - /// A class to handle secure TCP/IP communications with a server + /// Stream debugging /// - public class GenericSecureTcpIpClient : Device, ISocketStatusWithStreamDebugging, IAutoReconnect - { - private const string SplusKey = "Uninitialized Secure Tcp _client"; - /// - /// Stream debugging - /// - public CommunicationStreamDebugging StreamDebugging { get; private set; } + public CommunicationStreamDebugging StreamDebugging { get; private set; } - /// - /// Fires when data is received from the server and returns it as a Byte array - /// - public event EventHandler BytesReceived; + /// + /// Fires when data is received from the server and returns it as a Byte array + /// + public event EventHandler BytesReceived; - /// - /// Fires when data is received from the server and returns it as text - /// - public event EventHandler TextReceived; + /// + /// Fires when data is received from the server and returns it as text + /// + public event EventHandler TextReceived; - #region GenericSecureTcpIpClient Events & Delegates + #region GenericSecureTcpIpClient Events & Delegates - /// - /// - /// - //public event GenericSocketStatusChangeEventDelegate SocketStatusChange; - public event EventHandler ConnectionChange; + /// + /// + /// + //public event GenericSocketStatusChangeEventDelegate SocketStatusChange; + public event EventHandler ConnectionChange; - /// - /// Auto reconnect evant handler - /// - public event EventHandler AutoReconnectTriggered; + /// + /// Auto reconnect evant handler + /// + public event EventHandler AutoReconnectTriggered; - /// - /// Event for Receiving text. Once subscribed to this event the receive callback will start a thread that dequeues the messages and invokes the event on a new thread. - /// It is not recommended to use both the TextReceived event and the TextReceivedQueueInvoke event. - /// - public event EventHandler TextReceivedQueueInvoke; - - /// - /// For a client with a pre shared key, this will fire after the communication is established and the key exchange is complete. If you require - /// a key and subscribe to the socket change event and try to send data on a connection the data sent will interfere with the key exchange and disconnect. - /// - public event EventHandler ClientReadyForCommunications; + /// + /// Event for Receiving text. Once subscribed to this event the receive callback will start a thread that dequeues the messages and invokes the event on a new thread. + /// It is not recommended to use both the TextReceived event and the TextReceivedQueueInvoke event. + /// + public event EventHandler TextReceivedQueueInvoke; + + /// + /// For a client with a pre shared key, this will fire after the communication is established and the key exchange is complete. If you require + /// a key and subscribe to the socket change event and try to send data on a connection the data sent will interfere with the key exchange and disconnect. + /// + public event EventHandler ClientReadyForCommunications; - #endregion + #endregion - #region GenricTcpIpClient properties + #region GenricTcpIpClient properties - private string _hostname; + private string _hostname; - /// - /// Address of server - /// - public string Hostname + /// + /// Address of server + /// + public string Hostname + { + get { return _hostname; } + set { - get { return _hostname; } - set + _hostname = value; + if (_client != null) { - _hostname = value; - if (_client != null) - { - _client.AddressClientConnectedTo = _hostname; - } + _client.AddressClientConnectedTo = _hostname; } } + } - /// - /// Port on server - /// - public int Port { get; set; } + /// + /// Port on server + /// + public int Port { get; set; } - /// - /// S+ helper - /// - public ushort UPort - { - get { return Convert.ToUInt16(Port); } - set { Port = Convert.ToInt32(value); } - } + /// + /// S+ helper + /// + public ushort UPort + { + get { return Convert.ToUInt16(Port); } + set { Port = Convert.ToInt32(value); } + } - /// - /// Defaults to 2000 - /// - public int BufferSize { get; set; } + /// + /// Defaults to 2000 + /// + public int BufferSize { get; set; } - /// - /// Internal secure client - /// - private SecureTCPClient _client; + /// + /// Internal secure client + /// + private SecureTCPClient _client; - /// - /// Bool showing if socket is connected - /// - public bool IsConnected - { - get { return _client != null && _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } - } + /// + /// Bool showing if socket is connected + /// + public bool IsConnected + { + get { return _client != null && _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } + } - /// - /// S+ helper for IsConnected - /// - public ushort UIsConnected - { - get { return (ushort)(IsConnected ? 1 : 0); } - } + /// + /// S+ helper for IsConnected + /// + public ushort UIsConnected + { + get { return (ushort)(IsConnected ? 1 : 0); } + } - /// - /// _client socket status Read only - /// - public SocketStatus ClientStatus + /// + /// _client socket status Read only + /// + public SocketStatus ClientStatus + { + get { - get - { - return _client == null ? SocketStatus.SOCKET_STATUS_NO_CONNECT : _client.ClientStatus; - } + return _client == null ? SocketStatus.SOCKET_STATUS_NO_CONNECT : _client.ClientStatus; } + } - /// - /// Contains the familiar Simpl analog status values. This drives the ConnectionChange event - /// and IsConnected would be true when this == 2. - /// - public ushort UStatus - { - get { return (ushort)ClientStatus; } - } + /// + /// Contains the familiar Simpl analog status values. This drives the ConnectionChange event + /// and IsConnected would be true when this == 2. + /// + public ushort UStatus + { + get { return (ushort)ClientStatus; } + } - /// - /// Status text shows the message associated with socket status - /// - public string ClientStatusText { get { return ClientStatus.ToString(); } } + /// + /// Status text shows the message associated with socket status + /// + public string ClientStatusText { get { return ClientStatus.ToString(); } } - /// - /// Connection failure reason - /// - public string ConnectionFailure { get { return ClientStatus.ToString(); } } + /// + /// Connection failure reason + /// + public string ConnectionFailure { get { return ClientStatus.ToString(); } } - /// - /// bool to track if auto reconnect should be set on the socket - /// - public bool AutoReconnect { get; set; } + /// + /// bool to track if auto reconnect should be set on the socket + /// + public bool AutoReconnect { get; set; } - /// - /// S+ helper for AutoReconnect - /// - public ushort UAutoReconnect - { - get { return (ushort)(AutoReconnect ? 1 : 0); } - set { AutoReconnect = value == 1; } - } + /// + /// S+ helper for AutoReconnect + /// + public ushort UAutoReconnect + { + get { return (ushort)(AutoReconnect ? 1 : 0); } + set { AutoReconnect = value == 1; } + } - /// - /// Milliseconds to wait before attempting to reconnect. Defaults to 5000 - /// - public int AutoReconnectIntervalMs { get; set; } + /// + /// Milliseconds to wait before attempting to reconnect. Defaults to 5000 + /// + public int AutoReconnectIntervalMs { get; set; } - /// - /// Flag Set only when the disconnect method is called. - /// - bool DisconnectCalledByUser; + /// + /// Flag Set only when the disconnect method is called. + /// + bool DisconnectCalledByUser; - /// - /// - /// - public bool Connected - { - get { return _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } - } + /// + /// + /// + public bool Connected + { + get { return _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } + } - // private Timer for auto reconnect - private CTimer RetryTimer; + // private Timer for auto reconnect + private CTimer RetryTimer; - #endregion + #endregion - #region GenericSecureTcpIpClient properties + #region GenericSecureTcpIpClient properties - /// - /// Bool to show whether the server requires a preshared key. This is used in the DynamicTCPServer class - /// - public bool SharedKeyRequired { get; set; } + /// + /// Bool to show whether the server requires a preshared key. This is used in the DynamicTCPServer class + /// + public bool SharedKeyRequired { get; set; } - /// - /// S+ helper for requires shared key bool - /// - public ushort USharedKeyRequired + /// + /// S+ helper for requires shared key bool + /// + public ushort USharedKeyRequired + { + set { - set - { - if (value == 1) - SharedKeyRequired = true; - else - SharedKeyRequired = false; - } + if (value == 1) + SharedKeyRequired = true; + else + SharedKeyRequired = false; } + } - /// - /// SharedKey is sent for varification to the server. Shared key can be any text (255 char limit in SIMPL+ Module), but must match the Shared Key on the Server module - /// - public string SharedKey { get; set; } + /// + /// SharedKey is sent for varification to the server. Shared key can be any text (255 char limit in SIMPL+ Module), but must match the Shared Key on the Server module + /// + public string SharedKey { get; set; } - /// - /// flag to show the client is waiting for the server to send the shared key - /// - private bool WaitingForSharedKeyResponse { get; set; } + /// + /// flag to show the client is waiting for the server to send the shared key + /// + private bool WaitingForSharedKeyResponse { get; set; } - /// - /// Semaphore on connect method - /// - bool IsTryingToConnect; - - /// - /// Bool showing if socket is ready for communication after shared key exchange - /// - public bool IsReadyForCommunication { get; set; } - - /// - /// S+ helper for IsReadyForCommunication - /// - public ushort UIsReadyForCommunication - { - get { return (ushort)(IsReadyForCommunication ? 1 : 0); } - } + /// + /// Semaphore on connect method + /// + bool IsTryingToConnect; - /// - /// Bool Heartbeat Enabled flag - /// - public bool HeartbeatEnabled { get; set; } + /// + /// Bool showing if socket is ready for communication after shared key exchange + /// + public bool IsReadyForCommunication { get; set; } - /// - /// S+ helper for Heartbeat Enabled - /// - public ushort UHeartbeatEnabled - { - get { return (ushort)(HeartbeatEnabled ? 1 : 0); } - set { HeartbeatEnabled = value == 1; } - } + /// + /// S+ helper for IsReadyForCommunication + /// + public ushort UIsReadyForCommunication + { + get { return (ushort)(IsReadyForCommunication ? 1 : 0); } + } - /// - /// Heartbeat String - /// - public string HeartbeatString { get; set; } - //public int HeartbeatInterval = 50000; + /// + /// Bool Heartbeat Enabled flag + /// + public bool HeartbeatEnabled { get; set; } - /// - /// Milliseconds before server expects another heartbeat. Set by property HeartbeatRequiredIntervalInSeconds which is driven from S+ - /// - public int HeartbeatInterval { get; set; } + /// + /// S+ helper for Heartbeat Enabled + /// + public ushort UHeartbeatEnabled + { + get { return (ushort)(HeartbeatEnabled ? 1 : 0); } + set { HeartbeatEnabled = value == 1; } + } - /// - /// Simpl+ Heartbeat Analog value in seconds - /// - public ushort HeartbeatRequiredIntervalInSeconds { set { HeartbeatInterval = (value * 1000); } } + /// + /// Heartbeat String + /// + public string HeartbeatString { get; set; } + //public int HeartbeatInterval = 50000; - CTimer HeartbeatSendTimer; - CTimer HeartbeatAckTimer; + /// + /// Milliseconds before server expects another heartbeat. Set by property HeartbeatRequiredIntervalInSeconds which is driven from S+ + /// + public int HeartbeatInterval { get; set; } - // Used to force disconnection on a dead connect attempt - CTimer ConnectFailTimer; - CTimer WaitForSharedKey; - private int ConnectionCount; + /// + /// Simpl+ Heartbeat Analog value in seconds + /// + public ushort HeartbeatRequiredIntervalInSeconds { set { HeartbeatInterval = (value * 1000); } } - bool ProgramIsStopping; + CTimer HeartbeatSendTimer; + CTimer HeartbeatAckTimer; - /// - /// Queue lock - /// - CCriticalSection DequeueLock = new CCriticalSection(); + // Used to force disconnection on a dead connect attempt + CTimer ConnectFailTimer; + CTimer WaitForSharedKey; + private int ConnectionCount; - /// - /// Receive Queue size. Defaults to 20. Will set to 20 if QueueSize property is less than 20. Use constructor or set queue size property before - /// calling initialize. - /// - public int ReceiveQueueSize { get; set; } + bool ProgramIsStopping; - /// - /// Queue to temporarily store received messages with the source IP and Port info. Defaults to size 20. Use constructor or set queue size property before - /// calling initialize. - /// - private CrestronQueue MessageQueue; + /// + /// Queue lock + /// + CCriticalSection DequeueLock = new CCriticalSection(); - #endregion + /// + /// Receive Queue size. Defaults to 20. Will set to 20 if QueueSize property is less than 20. Use constructor or set queue size property before + /// calling initialize. + /// + public int ReceiveQueueSize { get; set; } - #region Constructors + /// + /// Queue to temporarily store received messages with the source IP and Port info. Defaults to size 20. Use constructor or set queue size property before + /// calling initialize. + /// + private CrestronQueue MessageQueue; - /// - /// Constructor - /// - /// - /// - /// - /// - public GenericSecureTcpIpClient(string key, string address, int port, int bufferSize) - : base(key) - { - StreamDebugging = new CommunicationStreamDebugging(key); - Hostname = address; - Port = port; - BufferSize = bufferSize; - AutoReconnectIntervalMs = 5000; + #endregion - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - } + #region Constructors - /// - /// Contstructor that sets all properties by calling the initialize method with a config object. - /// - /// - /// - public GenericSecureTcpIpClient(string key, TcpClientConfigObject clientConfigObject) - : base(key) - { - StreamDebugging = new CommunicationStreamDebugging(key); - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - AutoReconnectIntervalMs = 5000; - BufferSize = 2000; + /// + /// Constructor + /// + /// + /// + /// + /// + public GenericSecureTcpIpClient(string key, string address, int port, int bufferSize) + : base(key) + { + StreamDebugging = new CommunicationStreamDebugging(key); + Hostname = address; + Port = port; + BufferSize = bufferSize; + AutoReconnectIntervalMs = 5000; - Initialize(clientConfigObject); - } + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + } - /// - /// Default constructor for S+ - /// - public GenericSecureTcpIpClient() - : base(SplusKey) - { - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - AutoReconnectIntervalMs = 5000; - BufferSize = 2000; - } + /// + /// Contstructor that sets all properties by calling the initialize method with a config object. + /// + /// + /// + public GenericSecureTcpIpClient(string key, TcpClientConfigObject clientConfigObject) + : base(key) + { + StreamDebugging = new CommunicationStreamDebugging(key); + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + AutoReconnectIntervalMs = 5000; + BufferSize = 2000; + + Initialize(clientConfigObject); + } + + /// + /// Default constructor for S+ + /// + public GenericSecureTcpIpClient() + : base(SplusKey) + { + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + AutoReconnectIntervalMs = 5000; + BufferSize = 2000; + } + + /// + /// Just to help S+ set the key + /// + public void Initialize(string key) + { + Key = key; + } - /// - /// Just to help S+ set the key - /// - public void Initialize(string key) + /// + /// Initialize called by the constructor that accepts a client config object. Can be called later to reset properties of client. + /// + /// + public void Initialize(TcpClientConfigObject config) + { + if (config == null) { - Key = key; + Debug.Console(0, this, "Could not initialize client with key: {0}", Key); + return; } - - /// - /// Initialize called by the constructor that accepts a client config object. Can be called later to reset properties of client. - /// - /// - public void Initialize(TcpClientConfigObject config) + try { - if (config == null) - { - Debug.Console(0, this, "Could not initialize client with key: {0}", Key); - return; - } - try - { - Hostname = config.Control.TcpSshProperties.Address; - Port = config.Control.TcpSshProperties.Port > 0 && config.Control.TcpSshProperties.Port <= 65535 - ? config.Control.TcpSshProperties.Port - : 80; + Hostname = config.Control.TcpSshProperties.Address; + Port = config.Control.TcpSshProperties.Port > 0 && config.Control.TcpSshProperties.Port <= 65535 + ? config.Control.TcpSshProperties.Port + : 80; - AutoReconnect = config.Control.TcpSshProperties.AutoReconnect; - AutoReconnectIntervalMs = config.Control.TcpSshProperties.AutoReconnectIntervalMs > 1000 - ? config.Control.TcpSshProperties.AutoReconnectIntervalMs - : 5000; + AutoReconnect = config.Control.TcpSshProperties.AutoReconnect; + AutoReconnectIntervalMs = config.Control.TcpSshProperties.AutoReconnectIntervalMs > 1000 + ? config.Control.TcpSshProperties.AutoReconnectIntervalMs + : 5000; - SharedKey = config.SharedKey; - SharedKeyRequired = config.SharedKeyRequired; + SharedKey = config.SharedKey; + SharedKeyRequired = config.SharedKeyRequired; - HeartbeatEnabled = config.HeartbeatRequired; - HeartbeatRequiredIntervalInSeconds = config.HeartbeatRequiredIntervalInSeconds > 0 - ? config.HeartbeatRequiredIntervalInSeconds - : (ushort)15; + HeartbeatEnabled = config.HeartbeatRequired; + HeartbeatRequiredIntervalInSeconds = config.HeartbeatRequiredIntervalInSeconds > 0 + ? config.HeartbeatRequiredIntervalInSeconds + : (ushort)15; - HeartbeatString = string.IsNullOrEmpty(config.HeartbeatStringToMatch) - ? "heartbeat" - : config.HeartbeatStringToMatch; + HeartbeatString = string.IsNullOrEmpty(config.HeartbeatStringToMatch) + ? "heartbeat" + : config.HeartbeatStringToMatch; - BufferSize = config.Control.TcpSshProperties.BufferSize > 2000 - ? config.Control.TcpSshProperties.BufferSize - : 2000; + BufferSize = config.Control.TcpSshProperties.BufferSize > 2000 + ? config.Control.TcpSshProperties.BufferSize + : 2000; - ReceiveQueueSize = config.ReceiveQueueSize > 20 - ? config.ReceiveQueueSize - : 20; + ReceiveQueueSize = config.ReceiveQueueSize > 20 + ? config.ReceiveQueueSize + : 20; - MessageQueue = new CrestronQueue(ReceiveQueueSize); - } - catch (Exception ex) - { - Debug.Console(0, this, "Exception initializing client with key: {0}\rException: {1}", Key, ex); - } + MessageQueue = new CrestronQueue(ReceiveQueueSize); + } + catch (Exception ex) + { + Debug.Console(0, this, "Exception initializing client with key: {0}\rException: {1}", Key, ex); } + } - #endregion + #endregion - /// - /// Handles closing this up when the program shuts down - /// - void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + /// + /// Handles closing this up when the program shuts down + /// + void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + { + if (programEventType == eProgramStatusEventType.Stopping || programEventType == eProgramStatusEventType.Paused) { - if (programEventType == eProgramStatusEventType.Stopping || programEventType == eProgramStatusEventType.Paused) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Program stopping. Closing _client connection"); - ProgramIsStopping = true; - Disconnect(); - } - + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Program stopping. Closing _client connection"); + ProgramIsStopping = true; + Disconnect(); } - /// - /// Deactivate the client - /// - /// - public override bool Deactivate() + } + + /// + /// Deactivate the client + /// + /// + public override bool Deactivate() + { + if (_client != null) { - if (_client != null) - { - _client.SocketStatusChange -= this.Client_SocketStatusChange; - DisconnectClient(); - } - return true; + _client.SocketStatusChange -= this.Client_SocketStatusChange; + DisconnectClient(); } + return true; + } - /// - /// Connect Method. Will return if already connected. Will write errors if missing address, port, or unique key/name. - /// - public void Connect() - { - ConnectionCount++; - Debug.Console(2, this, "Attempting connect Count:{0}", ConnectionCount); + /// + /// Connect Method. Will return if already connected. Will write errors if missing address, port, or unique key/name. + /// + public void Connect() + { + ConnectionCount++; + Debug.Console(2, this, "Attempting connect Count:{0}", ConnectionCount); - if (IsConnected) + if (IsConnected) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Already connected. Ignoring."); + return; + } + if (IsTryingToConnect) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Already trying to connect. Ignoring."); + return; + } + try + { + IsTryingToConnect = true; + if (RetryTimer != null) + { + RetryTimer.Stop(); + RetryTimer = null; + } + if (string.IsNullOrEmpty(Hostname)) { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Already connected. Ignoring."); + Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: No address set"); return; } - if (IsTryingToConnect) + if (Port < 1 || Port > 65535) { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Already trying to connect. Ignoring."); + Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: Invalid port"); return; } - try + if (string.IsNullOrEmpty(SharedKey) && SharedKeyRequired) { - IsTryingToConnect = true; - if (RetryTimer != null) - { - RetryTimer.Stop(); - RetryTimer = null; - } - if (string.IsNullOrEmpty(Hostname)) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: No address set"); - return; - } - if (Port < 1 || Port > 65535) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: Invalid port"); - return; - } - if (string.IsNullOrEmpty(SharedKey) && SharedKeyRequired) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: No Shared Key set"); - return; - } + Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: No Shared Key set"); + return; + } - // clean up previous client - if (_client != null) - { - Disconnect(); - } - DisconnectCalledByUser = false; + // clean up previous client + if (_client != null) + { + Disconnect(); + } + DisconnectCalledByUser = false; - _client = new SecureTCPClient(Hostname, Port, BufferSize); - _client.SocketStatusChange += Client_SocketStatusChange; - if (HeartbeatEnabled) - _client.SocketSendOrReceiveTimeOutInMs = (HeartbeatInterval * 5); - _client.AddressClientConnectedTo = Hostname; - _client.PortNumber = Port; - // SecureClient = c; + _client = new SecureTCPClient(Hostname, Port, BufferSize); + _client.SocketStatusChange += Client_SocketStatusChange; + if (HeartbeatEnabled) + _client.SocketSendOrReceiveTimeOutInMs = (HeartbeatInterval * 5); + _client.AddressClientConnectedTo = Hostname; + _client.PortNumber = Port; + // SecureClient = c; - //var timeOfConnect = DateTime.Now.ToString("HH:mm:ss.fff"); + //var timeOfConnect = DateTime.Now.ToString("HH:mm:ss.fff"); - ConnectFailTimer = new CTimer(o => + ConnectFailTimer = new CTimer(o => + { + Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Connect attempt has not finished after 30sec Count:{0}", ConnectionCount); + if (IsTryingToConnect) { - Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Connect attempt has not finished after 30sec Count:{0}", ConnectionCount); - if (IsTryingToConnect) - { - IsTryingToConnect = false; - - //if (ConnectionHasHungCallback != null) - //{ - // ConnectionHasHungCallback(); - //} - //SecureClient.DisconnectFromServer(); - //CheckClosedAndTryReconnect(); - } - }, 30000); + IsTryingToConnect = false; + + //if (ConnectionHasHungCallback != null) + //{ + // ConnectionHasHungCallback(); + //} + //SecureClient.DisconnectFromServer(); + //CheckClosedAndTryReconnect(); + } + }, 30000); - Debug.Console(2, this, "Making Connection Count:{0}", ConnectionCount); - _client.ConnectToServerAsync(o => + Debug.Console(2, this, "Making Connection Count:{0}", ConnectionCount); + _client.ConnectToServerAsync(o => + { + Debug.Console(2, this, "ConnectToServerAsync Count:{0} Ran!", ConnectionCount); + + if (ConnectFailTimer != null) { - Debug.Console(2, this, "ConnectToServerAsync Count:{0} Ran!", ConnectionCount); + ConnectFailTimer.Stop(); + } + IsTryingToConnect = false; - if (ConnectFailTimer != null) - { - ConnectFailTimer.Stop(); - } - IsTryingToConnect = false; + if (o.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) + { + Debug.Console(2, this, "_client connected to {0} on port {1}", o.AddressClientConnectedTo, o.LocalPortNumberOfClient); + o.ReceiveDataAsync(Receive); - if (o.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) + if (SharedKeyRequired) { - Debug.Console(2, this, "_client connected to {0} on port {1}", o.AddressClientConnectedTo, o.LocalPortNumberOfClient); - o.ReceiveDataAsync(Receive); - - if (SharedKeyRequired) + WaitingForSharedKeyResponse = true; + WaitForSharedKey = new CTimer(timer => { - WaitingForSharedKeyResponse = true; - WaitForSharedKey = new CTimer(timer => - { - - Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Shared key exchange timer expired. IsReadyForCommunication={0}", IsReadyForCommunication); - // Debug.Console(1, this, "Connect attempt failed {0}", c.ClientStatus); - // This is the only case where we should call DisconectFromServer...Event handeler will trigger the cleanup - o.DisconnectFromServer(); - //CheckClosedAndTryReconnect(); - //OnClientReadyForcommunications(false); // Should send false event - }, 15000); - } - else - { - //CLient connected and shared key is not required so just raise the ready for communication event. if Shared key - //required this is called by the shared key being negotiated - if (IsReadyForCommunication == false) - { - OnClientReadyForcommunications(true); // Key not required - } - } + + Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Shared key exchange timer expired. IsReadyForCommunication={0}", IsReadyForCommunication); + // Debug.Console(1, this, "Connect attempt failed {0}", c.ClientStatus); + // This is the only case where we should call DisconectFromServer...Event handeler will trigger the cleanup + o.DisconnectFromServer(); + //CheckClosedAndTryReconnect(); + //OnClientReadyForcommunications(false); // Should send false event + }, 15000); } else { - Debug.Console(1, this, "Connect attempt failed {0}", o.ClientStatus); - CheckClosedAndTryReconnect(); + //CLient connected and shared key is not required so just raise the ready for communication event. if Shared key + //required this is called by the shared key being negotiated + if (IsReadyForCommunication == false) + { + OnClientReadyForcommunications(true); // Key not required + } } - }); - } - catch (Exception ex) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Error, "_client connection exception: {0}", ex.Message); - IsTryingToConnect = false; - CheckClosedAndTryReconnect(); - } + } + else + { + Debug.Console(1, this, "Connect attempt failed {0}", o.ClientStatus); + CheckClosedAndTryReconnect(); + } + }); } - - /// - /// - /// - public void Disconnect() + catch (Exception ex) { - this.LogVerbose("Disconnect Called"); + Debug.Console(0, this, Debug.ErrorLogLevel.Error, "_client connection exception: {0}", ex.Message); + IsTryingToConnect = false; + CheckClosedAndTryReconnect(); + } + } - DisconnectCalledByUser = true; + /// + /// + /// + public void Disconnect() + { + this.LogVerbose("Disconnect Called"); - // stop trying reconnects, if we are - if (RetryTimer != null) - { - RetryTimer.Stop(); - RetryTimer = null; - } + DisconnectCalledByUser = true; - if (_client != null) - { - DisconnectClient(); - this.LogDebug("Disconnected"); - } + // stop trying reconnects, if we are + if (RetryTimer != null) + { + RetryTimer.Stop(); + RetryTimer = null; } - /// - /// Does the actual disconnect business - /// - public void DisconnectClient() + if (_client != null) { - if (_client == null) return; + DisconnectClient(); + this.LogDebug("Disconnected"); + } + } - Debug.Console(1, this, "Disconnecting client"); - if (IsConnected) - _client.DisconnectFromServer(); + /// + /// Does the actual disconnect business + /// + public void DisconnectClient() + { + if (_client == null) return; - // close up client. ALWAYS use this when disconnecting. - IsTryingToConnect = false; + Debug.Console(1, this, "Disconnecting client"); + if (IsConnected) + _client.DisconnectFromServer(); - Debug.Console(2, this, "Disconnecting _client {0}", DisconnectCalledByUser ? ", Called by user" : ""); - _client.SocketStatusChange -= Client_SocketStatusChange; - _client.Dispose(); - _client = null; + // close up client. ALWAYS use this when disconnecting. + IsTryingToConnect = false; - if (ConnectFailTimer == null) return; - ConnectFailTimer.Stop(); - ConnectFailTimer.Dispose(); - ConnectFailTimer = null; - } - - #region Methods + Debug.Console(2, this, "Disconnecting _client {0}", DisconnectCalledByUser ? ", Called by user" : ""); + _client.SocketStatusChange -= Client_SocketStatusChange; + _client.Dispose(); + _client = null; + + if (ConnectFailTimer == null) return; + ConnectFailTimer.Stop(); + ConnectFailTimer.Dispose(); + ConnectFailTimer = null; + } + + #region Methods - /// - /// Called from Connect failure or Socket Status change if - /// auto reconnect and socket disconnected (Not disconnected by user) - /// - void CheckClosedAndTryReconnect() + /// + /// Called from Connect failure or Socket Status change if + /// auto reconnect and socket disconnected (Not disconnected by user) + /// + void CheckClosedAndTryReconnect() + { + if (_client != null) { - if (_client != null) - { - Debug.Console(2, this, "Cleaning up remotely closed/failed connection."); - Disconnect(); - } - if (!DisconnectCalledByUser && AutoReconnect) + Debug.Console(2, this, "Cleaning up remotely closed/failed connection."); + Disconnect(); + } + if (!DisconnectCalledByUser && AutoReconnect) + { + var halfInterval = AutoReconnectIntervalMs / 2; + var rndTime = new Random().Next(-halfInterval, halfInterval) + AutoReconnectIntervalMs; + Debug.Console(2, this, "Attempting reconnect in {0} ms, randomized", rndTime); + if (RetryTimer != null) { - var halfInterval = AutoReconnectIntervalMs / 2; - var rndTime = new Random().Next(-halfInterval, halfInterval) + AutoReconnectIntervalMs; - Debug.Console(2, this, "Attempting reconnect in {0} ms, randomized", rndTime); - if (RetryTimer != null) - { - RetryTimer.Stop(); - RetryTimer = null; - } - if (AutoReconnectTriggered != null) - AutoReconnectTriggered(this, new EventArgs()); - RetryTimer = new CTimer(o => Connect(), rndTime); + RetryTimer.Stop(); + RetryTimer = null; } + if (AutoReconnectTriggered != null) + AutoReconnectTriggered(this, new EventArgs()); + RetryTimer = new CTimer(o => Connect(), rndTime); } + } - /// - /// Receive callback - /// - /// - /// - void Receive(SecureTCPClient client, int numBytes) + /// + /// Receive callback + /// + /// + /// + void Receive(SecureTCPClient client, int numBytes) + { + if (numBytes > 0) { - if (numBytes > 0) + string str = string.Empty; + var handler = TextReceivedQueueInvoke; + try { - string str = string.Empty; - var handler = TextReceivedQueueInvoke; - try + var bytes = client.IncomingDataBuffer.Take(numBytes).ToArray(); + str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); + Debug.Console(2, this, "_client Received:\r--------\r{0}\r--------", str); + if (!string.IsNullOrEmpty(checkHeartbeat(str))) { - var bytes = client.IncomingDataBuffer.Take(numBytes).ToArray(); - str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); - Debug.Console(2, this, "_client Received:\r--------\r{0}\r--------", str); - if (!string.IsNullOrEmpty(checkHeartbeat(str))) - { - if (SharedKeyRequired && str == "SharedKey:") - { - Debug.Console(2, this, "Server asking for shared key, sending"); - SendText(SharedKey + "\n"); - } - else if (SharedKeyRequired && str == "Shared Key Match") - { - StopWaitForSharedKeyTimer(); + if (SharedKeyRequired && str == "SharedKey:") + { + Debug.Console(2, this, "Server asking for shared key, sending"); + SendText(SharedKey + "\n"); + } + else if (SharedKeyRequired && str == "Shared Key Match") + { + StopWaitForSharedKeyTimer(); - Debug.Console(2, this, "Shared key confirmed. Ready for communication"); - OnClientReadyForcommunications(true); // Successful key exchange - } - else + Debug.Console(2, this, "Shared key confirmed. Ready for communication"); + OnClientReadyForcommunications(true); // Successful key exchange + } + else + { + //var bytesHandler = BytesReceived; + //if (bytesHandler != null) + // bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); + var textHandler = TextReceived; + if (textHandler != null) + textHandler(this, new GenericCommMethodReceiveTextArgs(str)); + if (handler != null) { - //var bytesHandler = BytesReceived; - //if (bytesHandler != null) - // bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); - var textHandler = TextReceived; - if (textHandler != null) - textHandler(this, new GenericCommMethodReceiveTextArgs(str)); - if (handler != null) - { - MessageQueue.TryToEnqueue(new GenericTcpServerCommMethodReceiveTextArgs(str)); - } + MessageQueue.TryToEnqueue(new GenericTcpServerCommMethodReceiveTextArgs(str)); } } } - catch (Exception ex) - { - Debug.Console(1, this, "Error receiving data: {1}. Error: {0}", ex.Message, str); - } - if (client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) - client.ReceiveDataAsync(Receive); - - //Check to see if there is a subscription to the TextReceivedQueueInvoke event. If there is start the dequeue thread. - if (handler != null) - { - var gotLock = DequeueLock.TryEnter(); - if (gotLock) - CrestronInvoke.BeginInvoke((o) => DequeueEvent()); - } } - else //JAG added this as I believe the error return is 0 bytes like the server. See help when hover on ReceiveAsync + catch (Exception ex) { - client.DisconnectFromServer(); + Debug.Console(1, this, "Error receiving data: {1}. Error: {0}", ex.Message, str); } - } + if (client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) + client.ReceiveDataAsync(Receive); - /// - /// This method gets spooled up in its own thread an protected by a CCriticalSection to prevent multiple threads from running concurrently. - /// It will dequeue items as they are enqueued automatically. - /// - void DequeueEvent() - { - try + //Check to see if there is a subscription to the TextReceivedQueueInvoke event. If there is start the dequeue thread. + if (handler != null) { - while (true) - { - // Pull from Queue and fire an event. Block indefinitely until an item can be removed, similar to a Gather. - var message = MessageQueue.Dequeue(); - var handler = TextReceivedQueueInvoke; - if (handler != null) - { - handler(this, message); - } - } - } - catch (Exception e) - { - this.LogException(e, "DequeueEvent error"); - } - // Make sure to leave the CCritical section in case an exception above stops this thread, or we won't be able to restart it. - if (DequeueLock != null) - { - DequeueLock.Leave(); + var gotLock = DequeueLock.TryEnter(); + if (gotLock) + CrestronInvoke.BeginInvoke((o) => DequeueEvent()); } } + else //JAG added this as I believe the error return is 0 bytes like the server. See help when hover on ReceiveAsync + { + client.DisconnectFromServer(); + } + } - void HeartbeatStart() + /// + /// This method gets spooled up in its own thread an protected by a CCriticalSection to prevent multiple threads from running concurrently. + /// It will dequeue items as they are enqueued automatically. + /// + void DequeueEvent() + { + try { - if (HeartbeatEnabled) + while (true) { - this.LogVerbose("Starting Heartbeat"); - if (HeartbeatSendTimer == null) - { - - HeartbeatSendTimer = new CTimer(this.SendHeartbeat, null, HeartbeatInterval, HeartbeatInterval); - } - if (HeartbeatAckTimer == null) + // Pull from Queue and fire an event. Block indefinitely until an item can be removed, similar to a Gather. + var message = MessageQueue.Dequeue(); + var handler = TextReceivedQueueInvoke; + if (handler != null) { - HeartbeatAckTimer = new CTimer(HeartbeatAckTimerFail, null, (HeartbeatInterval * 2), (HeartbeatInterval * 2)); + handler(this, message); } } - } - void HeartbeatStop() + catch (Exception e) { + this.LogException(e, "DequeueEvent error"); + } + // Make sure to leave the CCritical section in case an exception above stops this thread, or we won't be able to restart it. + if (DequeueLock != null) + { + DequeueLock.Leave(); + } + } - if (HeartbeatSendTimer != null) + void HeartbeatStart() + { + if (HeartbeatEnabled) + { + this.LogVerbose("Starting Heartbeat"); + if (HeartbeatSendTimer == null) { - Debug.Console(2, this, "Stoping Heartbeat Send"); - HeartbeatSendTimer.Stop(); - HeartbeatSendTimer = null; + + HeartbeatSendTimer = new CTimer(this.SendHeartbeat, null, HeartbeatInterval, HeartbeatInterval); } - if (HeartbeatAckTimer != null) + if (HeartbeatAckTimer == null) { - Debug.Console(2, this, "Stoping Heartbeat Ack"); - HeartbeatAckTimer.Stop(); - HeartbeatAckTimer = null; + HeartbeatAckTimer = new CTimer(HeartbeatAckTimerFail, null, (HeartbeatInterval * 2), (HeartbeatInterval * 2)); } + } + + } + void HeartbeatStop() + { + if (HeartbeatSendTimer != null) + { + Debug.Console(2, this, "Stoping Heartbeat Send"); + HeartbeatSendTimer.Stop(); + HeartbeatSendTimer = null; } - void SendHeartbeat(object notused) + if (HeartbeatAckTimer != null) { - this.SendText(HeartbeatString); - Debug.Console(2, this, "Sending Heartbeat"); - + Debug.Console(2, this, "Stoping Heartbeat Ack"); + HeartbeatAckTimer.Stop(); + HeartbeatAckTimer = null; } - //private method to check heartbeat requirements and start or reset timer - string checkHeartbeat(string received) + } + void SendHeartbeat(object notused) + { + this.SendText(HeartbeatString); + Debug.Console(2, this, "Sending Heartbeat"); + + } + + //private method to check heartbeat requirements and start or reset timer + string checkHeartbeat(string received) + { + try { - try + if (HeartbeatEnabled) { - if (HeartbeatEnabled) + if (!string.IsNullOrEmpty(HeartbeatString)) { - if (!string.IsNullOrEmpty(HeartbeatString)) + var remainingText = received.Replace(HeartbeatString, ""); + var noDelimiter = received.Trim(new char[] { '\r', '\n' }); + if (noDelimiter.Contains(HeartbeatString)) { - var remainingText = received.Replace(HeartbeatString, ""); - var noDelimiter = received.Trim(new char[] { '\r', '\n' }); - if (noDelimiter.Contains(HeartbeatString)) + if (HeartbeatAckTimer != null) + { + HeartbeatAckTimer.Reset(HeartbeatInterval * 2); + } + else { - if (HeartbeatAckTimer != null) - { - HeartbeatAckTimer.Reset(HeartbeatInterval * 2); - } - else - { - HeartbeatAckTimer = new CTimer(HeartbeatAckTimerFail, null, (HeartbeatInterval * 2), (HeartbeatInterval * 2)); - } - Debug.Console(2, this, "Heartbeat Received: {0}, from Server", HeartbeatString); - return remainingText; + HeartbeatAckTimer = new CTimer(HeartbeatAckTimerFail, null, (HeartbeatInterval * 2), (HeartbeatInterval * 2)); } + Debug.Console(2, this, "Heartbeat Received: {0}, from Server", HeartbeatString); + return remainingText; } } } - catch (Exception ex) - { - Debug.Console(1, this, "Error checking heartbeat: {0}", ex.Message); - } - return received; } + catch (Exception ex) + { + Debug.Console(1, this, "Error checking heartbeat: {0}", ex.Message); + } + return received; + } - void HeartbeatAckTimerFail(object o) + void HeartbeatAckTimerFail(object o) + { + try { - try - { - if (IsConnected) - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "Heartbeat not received from Server...DISCONNECTING BECAUSE HEARTBEAT REQUIRED IS TRUE"); - SendText("Heartbeat not received by server, closing connection"); - CheckClosedAndTryReconnect(); - } - - } - catch (Exception ex) + if (IsConnected) { - ErrorLog.Error("Heartbeat timeout Error on _client: {0}, {1}", Key, ex); + Debug.Console(1, Debug.ErrorLogLevel.Warning, "Heartbeat not received from Server...DISCONNECTING BECAUSE HEARTBEAT REQUIRED IS TRUE"); + SendText("Heartbeat not received by server, closing connection"); + CheckClosedAndTryReconnect(); } + + } + catch (Exception ex) + { + ErrorLog.Error("Heartbeat timeout Error on _client: {0}, {1}", Key, ex); } + } - /// - /// - /// - void StopWaitForSharedKeyTimer() + /// + /// + /// + void StopWaitForSharedKeyTimer() + { + if (WaitForSharedKey != null) { - if (WaitForSharedKey != null) - { - WaitForSharedKey.Stop(); - WaitForSharedKey = null; - } + WaitForSharedKey.Stop(); + WaitForSharedKey = null; } + } - /// - /// General send method - /// - public void SendText(string text) + /// + /// General send method + /// + public void SendText(string text) + { + if (!string.IsNullOrEmpty(text)) { - if (!string.IsNullOrEmpty(text)) + try { - try + var bytes = Encoding.GetEncoding(28591).GetBytes(text); + if (_client != null && _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) { - var bytes = Encoding.GetEncoding(28591).GetBytes(text); - if (_client != null && _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) + _client.SendDataAsync(bytes, bytes.Length, (c, n) => { - _client.SendDataAsync(bytes, bytes.Length, (c, n) => + // HOW IN THE HELL DO WE CATCH AN EXCEPTION IN SENDING????? + if (n <= 0) { - // HOW IN THE HELL DO WE CATCH AN EXCEPTION IN SENDING????? - if (n <= 0) - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "[{0}] Sent zero bytes. Was there an error?", this.Key); - } - }); - } - } - catch (Exception ex) - { - Debug.Console(0, this, "Error sending text: {1}. Error: {0}", ex.Message, text); + Debug.Console(1, Debug.ErrorLogLevel.Warning, "[{0}] Sent zero bytes. Was there an error?", this.Key); + } + }); } } - } - - /// - /// - /// - public void SendBytes(byte[] bytes) - { - if (bytes.Length > 0) + catch (Exception ex) { - try - { - if (_client != null && _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) - _client.SendData(bytes, bytes.Length); - } - catch (Exception ex) - { - Debug.Console(0, this, "Error sending bytes. Error: {0}", ex.Message); - } + Debug.Console(0, this, "Error sending text: {1}. Error: {0}", ex.Message, text); } } + } - /// - /// SocketStatusChange Callback - /// - /// - /// - void Client_SocketStatusChange(SecureTCPClient client, SocketStatus clientSocketStatus) + /// + /// + /// + public void SendBytes(byte[] bytes) + { + if (bytes.Length > 0) { - if (ProgramIsStopping) - { - ProgramIsStopping = false; - return; - } try { - Debug.Console(2, this, "Socket status change: {0} ({1})", client.ClientStatus, (ushort)(client.ClientStatus)); - - OnConnectionChange(); - // The client could be null or disposed by this time... - if (_client == null || _client.ClientStatus != SocketStatus.SOCKET_STATUS_CONNECTED) - { - HeartbeatStop(); - OnClientReadyForcommunications(false); // socket has gone low - CheckClosedAndTryReconnect(); - } + if (_client != null && _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) + _client.SendData(bytes, bytes.Length); } catch (Exception ex) { - Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Error in socket status change callback. Error: {0}\r\r{1}", ex, ex.InnerException); + Debug.Console(0, this, "Error sending bytes. Error: {0}", ex.Message); } } + } - /// - /// Helper for ConnectionChange event - /// - void OnConnectionChange() + /// + /// SocketStatusChange Callback + /// + /// + /// + void Client_SocketStatusChange(SecureTCPClient client, SocketStatus clientSocketStatus) + { + if (ProgramIsStopping) { - var handler = ConnectionChange; - if (handler == null) return; - - handler(this, new GenericSocketStatusChageEventArgs(this)); + ProgramIsStopping = false; + return; } - - /// - /// Helper to fire ClientReadyForCommunications event - /// - void OnClientReadyForcommunications(bool isReady) + try { - IsReadyForCommunication = isReady; - if (IsReadyForCommunication) - HeartbeatStart(); + Debug.Console(2, this, "Socket status change: {0} ({1})", client.ClientStatus, (ushort)(client.ClientStatus)); - var handler = ClientReadyForCommunications; - if (handler == null) return; - - handler(this, new GenericTcpServerClientReadyForcommunicationsEventArgs(IsReadyForCommunication)); + OnConnectionChange(); + // The client could be null or disposed by this time... + if (_client == null || _client.ClientStatus != SocketStatus.SOCKET_STATUS_CONNECTED) + { + HeartbeatStop(); + OnClientReadyForcommunications(false); // socket has gone low + CheckClosedAndTryReconnect(); + } } - #endregion + catch (Exception ex) + { + Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Error in socket status change callback. Error: {0}\r\r{1}", ex, ex.InnerException); + } + } + + /// + /// Helper for ConnectionChange event + /// + void OnConnectionChange() + { + var handler = ConnectionChange; + if (handler == null) return; + + handler(this, new GenericSocketStatusChageEventArgs(this)); } + /// + /// Helper to fire ClientReadyForCommunications event + /// + void OnClientReadyForcommunications(bool isReady) + { + IsReadyForCommunication = isReady; + if (IsReadyForCommunication) + HeartbeatStart(); + + var handler = ClientReadyForCommunications; + if (handler == null) return; + + handler(this, new GenericTcpServerClientReadyForcommunicationsEventArgs(IsReadyForCommunication)); + } + #endregion } \ No newline at end of file diff --git a/src/PepperDash.Core/Comm/GenericSecureTcpIpClient_ForServer.cs b/src/PepperDash.Core/Comm/GenericSecureTcpIpClient_ForServer.cs index 93b195cad..297233b1d 100644 --- a/src/PepperDash.Core/Comm/GenericSecureTcpIpClient_ForServer.cs +++ b/src/PepperDash.Core/Comm/GenericSecureTcpIpClient_ForServer.cs @@ -19,891 +19,889 @@ PepperDash Technology Corporation reserves all rights under applicable laws. using Crestron.SimplSharp.CrestronSockets; using PepperDash.Core.Logging; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// Generic secure TCP/IP client for server +/// +public class GenericSecureTcpIpClient_ForServer : Device, IAutoReconnect { /// - /// Generic secure TCP/IP client for server + /// Band aid delegate for choked server /// - public class GenericSecureTcpIpClient_ForServer : Device, IAutoReconnect - { - /// - /// Band aid delegate for choked server - /// - internal delegate void ConnectionHasHungCallbackDelegate(); + internal delegate void ConnectionHasHungCallbackDelegate(); - #region Events + #region Events - //public event EventHandler BytesReceived; + //public event EventHandler BytesReceived; - /// - /// Notifies of text received - /// - public event EventHandler TextReceived; + /// + /// Notifies of text received + /// + public event EventHandler TextReceived; - /// - /// Notifies of auto reconnect sequence triggered - /// - public event EventHandler AutoReconnectTriggered; + /// + /// Notifies of auto reconnect sequence triggered + /// + public event EventHandler AutoReconnectTriggered; - /// - /// Event for Receiving text. Once subscribed to this event the receive callback will start a thread that dequeues the messages and invokes the event on a new thread. - /// It is not recommended to use both the TextReceived event and the TextReceivedQueueInvoke event. - /// - public event EventHandler TextReceivedQueueInvoke; + /// + /// Event for Receiving text. Once subscribed to this event the receive callback will start a thread that dequeues the messages and invokes the event on a new thread. + /// It is not recommended to use both the TextReceived event and the TextReceivedQueueInvoke event. + /// + public event EventHandler TextReceivedQueueInvoke; - /// - /// Notifies of socket status change - /// - public event EventHandler ConnectionChange; + /// + /// Notifies of socket status change + /// + public event EventHandler ConnectionChange; - /// - /// This is something of a band-aid callback. If the client times out during the connection process, because the server - /// is stuck, this will fire. It is intended to be used by the Server class monitor client, to help - /// keep a watch on the server and reset it if necessary. - /// - internal ConnectionHasHungCallbackDelegate ConnectionHasHungCallback; + /// + /// This is something of a band-aid callback. If the client times out during the connection process, because the server + /// is stuck, this will fire. It is intended to be used by the Server class monitor client, to help + /// keep a watch on the server and reset it if necessary. + /// + internal ConnectionHasHungCallbackDelegate ConnectionHasHungCallback; - /// - /// For a client with a pre shared key, this will fire after the communication is established and the key exchange is complete. If you require - /// a key and subscribe to the socket change event and try to send data on a connection the data sent will interfere with the key exchange and disconnect. - /// - public event EventHandler ClientReadyForCommunications; + /// + /// For a client with a pre shared key, this will fire after the communication is established and the key exchange is complete. If you require + /// a key and subscribe to the socket change event and try to send data on a connection the data sent will interfere with the key exchange and disconnect. + /// + public event EventHandler ClientReadyForCommunications; - #endregion + #endregion - #region Properties & Variables + #region Properties & Variables - /// - /// Address of server - /// - public string Hostname { get; set; } + /// + /// Address of server + /// + public string Hostname { get; set; } - /// - /// Port on server - /// - public int Port { get; set; } + /// + /// Port on server + /// + public int Port { get; set; } - /// - /// S+ helper - /// - public ushort UPort - { - get { return Convert.ToUInt16(Port); } - set { Port = Convert.ToInt32(value); } - } + /// + /// S+ helper + /// + public ushort UPort + { + get { return Convert.ToUInt16(Port); } + set { Port = Convert.ToInt32(value); } + } - /// - /// Bool to show whether the server requires a preshared key. This is used in the DynamicTCPServer class - /// - public bool SharedKeyRequired { get; set; } + /// + /// Bool to show whether the server requires a preshared key. This is used in the DynamicTCPServer class + /// + public bool SharedKeyRequired { get; set; } - /// - /// S+ helper for requires shared key bool - /// - public ushort USharedKeyRequired + /// + /// S+ helper for requires shared key bool + /// + public ushort USharedKeyRequired + { + set { - set - { - if (value == 1) - SharedKeyRequired = true; - else - SharedKeyRequired = false; - } + if (value == 1) + SharedKeyRequired = true; + else + SharedKeyRequired = false; } + } - /// - /// SharedKey is sent for varification to the server. Shared key can be any text (255 char limit in SIMPL+ Module), but must match the Shared Key on the Server module - /// - public string SharedKey { get; set; } + /// + /// SharedKey is sent for varification to the server. Shared key can be any text (255 char limit in SIMPL+ Module), but must match the Shared Key on the Server module + /// + public string SharedKey { get; set; } - /// - /// flag to show the client is waiting for the server to send the shared key - /// - private bool WaitingForSharedKeyResponse { get; set; } + /// + /// flag to show the client is waiting for the server to send the shared key + /// + private bool WaitingForSharedKeyResponse { get; set; } - /// - /// Defaults to 2000 - /// - public int BufferSize { get; set; } + /// + /// Defaults to 2000 + /// + public int BufferSize { get; set; } - /// - /// Semaphore on connect method - /// - bool IsTryingToConnect; + /// + /// Semaphore on connect method + /// + bool IsTryingToConnect; - /// - /// Bool showing if socket is connected - /// - public bool IsConnected + /// + /// Bool showing if socket is connected + /// + public bool IsConnected + { + get { - get - { - if (Client != null) - return Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; - else - return false; - } + if (Client != null) + return Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; + else + return false; } + } - /// - /// S+ helper for IsConnected - /// - public ushort UIsConnected - { - get { return (ushort)(IsConnected ? 1 : 0); } - } + /// + /// S+ helper for IsConnected + /// + public ushort UIsConnected + { + get { return (ushort)(IsConnected ? 1 : 0); } + } - /// - /// Bool showing if socket is ready for communication after shared key exchange - /// - public bool IsReadyForCommunication { get; set; } + /// + /// Bool showing if socket is ready for communication after shared key exchange + /// + public bool IsReadyForCommunication { get; set; } - /// - /// S+ helper for IsReadyForCommunication - /// - public ushort UIsReadyForCommunication - { - get { return (ushort)(IsReadyForCommunication ? 1 : 0); } - } + /// + /// S+ helper for IsReadyForCommunication + /// + public ushort UIsReadyForCommunication + { + get { return (ushort)(IsReadyForCommunication ? 1 : 0); } + } - /// - /// Client socket status Read only - /// - public SocketStatus ClientStatus + /// + /// Client socket status Read only + /// + public SocketStatus ClientStatus + { + get { - get - { - if (Client != null) - return Client.ClientStatus; - else - return SocketStatus.SOCKET_STATUS_NO_CONNECT; - } + if (Client != null) + return Client.ClientStatus; + else + return SocketStatus.SOCKET_STATUS_NO_CONNECT; } + } - /// - /// Contains the familiar Simpl analog status values. This drives the ConnectionChange event - /// and IsConnected would be true when this == 2. - /// - public ushort UStatus - { - get { return (ushort)ClientStatus; } - } + /// + /// Contains the familiar Simpl analog status values. This drives the ConnectionChange event + /// and IsConnected would be true when this == 2. + /// + public ushort UStatus + { + get { return (ushort)ClientStatus; } + } - /// - /// Status text shows the message associated with socket status - /// - public string ClientStatusText { get { return ClientStatus.ToString(); } } - - /// - /// bool to track if auto reconnect should be set on the socket - /// - public bool AutoReconnect { get; set; } - - /// - /// S+ helper for AutoReconnect - /// - public ushort UAutoReconnect - { - get { return (ushort)(AutoReconnect ? 1 : 0); } - set { AutoReconnect = value == 1; } - } - /// - /// Milliseconds to wait before attempting to reconnect. Defaults to 5000 - /// - public int AutoReconnectIntervalMs { get; set; } - - /// - /// Flag Set only when the disconnect method is called. - /// - bool DisconnectCalledByUser; - - /// - /// private Timer for auto reconnect - /// - CTimer RetryTimer; - - - /// - /// - /// - public bool HeartbeatEnabled { get; set; } - /// - /// - /// - public ushort UHeartbeatEnabled - { - get { return (ushort)(HeartbeatEnabled ? 1 : 0); } - set { HeartbeatEnabled = value == 1; } - } + /// + /// Status text shows the message associated with socket status + /// + public string ClientStatusText { get { return ClientStatus.ToString(); } } - /// - /// - /// - public string HeartbeatString { get; set; } - //public int HeartbeatInterval = 50000; + /// + /// bool to track if auto reconnect should be set on the socket + /// + public bool AutoReconnect { get; set; } - /// - /// Milliseconds before server expects another heartbeat. Set by property HeartbeatRequiredIntervalInSeconds which is driven from S+ - /// - public int HeartbeatInterval { get; set; } + /// + /// S+ helper for AutoReconnect + /// + public ushort UAutoReconnect + { + get { return (ushort)(AutoReconnect ? 1 : 0); } + set { AutoReconnect = value == 1; } + } + /// + /// Milliseconds to wait before attempting to reconnect. Defaults to 5000 + /// + public int AutoReconnectIntervalMs { get; set; } - /// - /// Simpl+ Heartbeat Analog value in seconds - /// - public ushort HeartbeatRequiredIntervalInSeconds { set { HeartbeatInterval = (value * 1000); } } + /// + /// Flag Set only when the disconnect method is called. + /// + bool DisconnectCalledByUser; - CTimer HeartbeatSendTimer; - CTimer HeartbeatAckTimer; - /// - /// Used to force disconnection on a dead connect attempt - /// - CTimer ConnectFailTimer; - CTimer WaitForSharedKey; - private int ConnectionCount; - /// - /// Internal secure client - /// - SecureTCPClient Client; + /// + /// private Timer for auto reconnect + /// + CTimer RetryTimer; - bool ProgramIsStopping; - /// - /// Queue lock - /// - CCriticalSection DequeueLock = new CCriticalSection(); + /// + /// + /// + public bool HeartbeatEnabled { get; set; } + /// + /// + /// + public ushort UHeartbeatEnabled + { + get { return (ushort)(HeartbeatEnabled ? 1 : 0); } + set { HeartbeatEnabled = value == 1; } + } - /// - /// Receive Queue size. Defaults to 20. Will set to 20 if QueueSize property is less than 20. Use constructor or set queue size property before - /// calling initialize. - /// - public int ReceiveQueueSize { get; set; } + /// + /// + /// + public string HeartbeatString { get; set; } + //public int HeartbeatInterval = 50000; - /// - /// Queue to temporarily store received messages with the source IP and Port info. Defaults to size 20. Use constructor or set queue size property before - /// calling initialize. - /// - private CrestronQueue MessageQueue; + /// + /// Milliseconds before server expects another heartbeat. Set by property HeartbeatRequiredIntervalInSeconds which is driven from S+ + /// + public int HeartbeatInterval { get; set; } + /// + /// Simpl+ Heartbeat Analog value in seconds + /// + public ushort HeartbeatRequiredIntervalInSeconds { set { HeartbeatInterval = (value * 1000); } } - #endregion + CTimer HeartbeatSendTimer; + CTimer HeartbeatAckTimer; + /// + /// Used to force disconnection on a dead connect attempt + /// + CTimer ConnectFailTimer; + CTimer WaitForSharedKey; + private int ConnectionCount; + /// + /// Internal secure client + /// + SecureTCPClient Client; - #region Constructors - - /// - /// Constructor - /// - /// - /// - /// - /// - public GenericSecureTcpIpClient_ForServer(string key, string address, int port, int bufferSize) - : base(key) - { - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - Hostname = address; - Port = port; - BufferSize = bufferSize; - AutoReconnectIntervalMs = 5000; - - } + bool ProgramIsStopping; - /// - /// Constructor for S+ - /// - public GenericSecureTcpIpClient_ForServer() - : base("Uninitialized Secure Tcp Client For Server") - { - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - AutoReconnectIntervalMs = 5000; - BufferSize = 2000; - } + /// + /// Queue lock + /// + CCriticalSection DequeueLock = new CCriticalSection(); - /// - /// Contstructor that sets all properties by calling the initialize method with a config object. - /// - /// - /// - public GenericSecureTcpIpClient_ForServer(string key, TcpClientConfigObject clientConfigObject) - : base(key) - { - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - Initialize(clientConfigObject); - } + /// + /// Receive Queue size. Defaults to 20. Will set to 20 if QueueSize property is less than 20. Use constructor or set queue size property before + /// calling initialize. + /// + public int ReceiveQueueSize { get; set; } - #endregion + /// + /// Queue to temporarily store received messages with the source IP and Port info. Defaults to size 20. Use constructor or set queue size property before + /// calling initialize. + /// + private CrestronQueue MessageQueue; - #region Methods - /// - /// Just to help S+ set the key - /// - public void Initialize(string key) - { - Key = key; - } + #endregion - /// - /// Initialize called by the constructor that accepts a client config object. Can be called later to reset properties of client. - /// - /// - public void Initialize(TcpClientConfigObject clientConfigObject) - { - try - { - if (clientConfigObject != null) - { - var TcpSshProperties = clientConfigObject.Control.TcpSshProperties; - Hostname = TcpSshProperties.Address; - AutoReconnect = TcpSshProperties.AutoReconnect; - AutoReconnectIntervalMs = TcpSshProperties.AutoReconnectIntervalMs > 1000 ? - TcpSshProperties.AutoReconnectIntervalMs : 5000; - SharedKey = clientConfigObject.SharedKey; - SharedKeyRequired = clientConfigObject.SharedKeyRequired; - HeartbeatEnabled = clientConfigObject.HeartbeatRequired; - HeartbeatRequiredIntervalInSeconds = clientConfigObject.HeartbeatRequiredIntervalInSeconds > 0 ? - clientConfigObject.HeartbeatRequiredIntervalInSeconds : (ushort)15; - HeartbeatString = string.IsNullOrEmpty(clientConfigObject.HeartbeatStringToMatch) ? "heartbeat" : clientConfigObject.HeartbeatStringToMatch; - Port = TcpSshProperties.Port; - BufferSize = TcpSshProperties.BufferSize > 2000 ? TcpSshProperties.BufferSize : 2000; - ReceiveQueueSize = clientConfigObject.ReceiveQueueSize > 20 ? clientConfigObject.ReceiveQueueSize : 20; - MessageQueue = new CrestronQueue(ReceiveQueueSize); - } - else - { - ErrorLog.Error("Could not initialize client with key: {0}", Key); - } - } - catch + #region Constructors + + /// + /// Constructor + /// + /// + /// + /// + /// + public GenericSecureTcpIpClient_ForServer(string key, string address, int port, int bufferSize) + : base(key) + { + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + Hostname = address; + Port = port; + BufferSize = bufferSize; + AutoReconnectIntervalMs = 5000; + + } + + /// + /// Constructor for S+ + /// + public GenericSecureTcpIpClient_ForServer() + : base("Uninitialized Secure Tcp Client For Server") + { + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + AutoReconnectIntervalMs = 5000; + BufferSize = 2000; + } + + /// + /// Contstructor that sets all properties by calling the initialize method with a config object. + /// + /// + /// + public GenericSecureTcpIpClient_ForServer(string key, TcpClientConfigObject clientConfigObject) + : base(key) + { + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + Initialize(clientConfigObject); + } + + #endregion + + #region Methods + + /// + /// Just to help S+ set the key + /// + public void Initialize(string key) + { + Key = key; + } + + /// + /// Initialize called by the constructor that accepts a client config object. Can be called later to reset properties of client. + /// + /// + public void Initialize(TcpClientConfigObject clientConfigObject) + { + try + { + if (clientConfigObject != null) + { + var TcpSshProperties = clientConfigObject.Control.TcpSshProperties; + Hostname = TcpSshProperties.Address; + AutoReconnect = TcpSshProperties.AutoReconnect; + AutoReconnectIntervalMs = TcpSshProperties.AutoReconnectIntervalMs > 1000 ? + TcpSshProperties.AutoReconnectIntervalMs : 5000; + SharedKey = clientConfigObject.SharedKey; + SharedKeyRequired = clientConfigObject.SharedKeyRequired; + HeartbeatEnabled = clientConfigObject.HeartbeatRequired; + HeartbeatRequiredIntervalInSeconds = clientConfigObject.HeartbeatRequiredIntervalInSeconds > 0 ? + clientConfigObject.HeartbeatRequiredIntervalInSeconds : (ushort)15; + HeartbeatString = string.IsNullOrEmpty(clientConfigObject.HeartbeatStringToMatch) ? "heartbeat" : clientConfigObject.HeartbeatStringToMatch; + Port = TcpSshProperties.Port; + BufferSize = TcpSshProperties.BufferSize > 2000 ? TcpSshProperties.BufferSize : 2000; + ReceiveQueueSize = clientConfigObject.ReceiveQueueSize > 20 ? clientConfigObject.ReceiveQueueSize : 20; + MessageQueue = new CrestronQueue(ReceiveQueueSize); + } + else { ErrorLog.Error("Could not initialize client with key: {0}", Key); } } - - /// - /// Handles closing this up when the program shuts down - /// - void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + catch { - if (programEventType == eProgramStatusEventType.Stopping || programEventType == eProgramStatusEventType.Paused) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Program stopping. Closing Client connection"); - ProgramIsStopping = true; - Disconnect(); - } - + ErrorLog.Error("Could not initialize client with key: {0}", Key); } + } - /// - /// Connect Method. Will return if already connected. Will write errors if missing address, port, or unique key/name. - /// - public void Connect() + /// + /// Handles closing this up when the program shuts down + /// + void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + { + if (programEventType == eProgramStatusEventType.Stopping || programEventType == eProgramStatusEventType.Paused) { - ConnectionCount++; - Debug.Console(2, this, "Attempting connect Count:{0}", ConnectionCount); + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Program stopping. Closing Client connection"); + ProgramIsStopping = true; + Disconnect(); + } + } - if (IsConnected) + /// + /// Connect Method. Will return if already connected. Will write errors if missing address, port, or unique key/name. + /// + public void Connect() + { + ConnectionCount++; + Debug.Console(2, this, "Attempting connect Count:{0}", ConnectionCount); + + + if (IsConnected) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Already connected. Ignoring."); + return; + } + if (IsTryingToConnect) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Already trying to connect. Ignoring."); + return; + } + try + { + IsTryingToConnect = true; + if (RetryTimer != null) { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Already connected. Ignoring."); + RetryTimer.Stop(); + RetryTimer = null; + } + if (string.IsNullOrEmpty(Hostname)) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: No address set"); return; } - if (IsTryingToConnect) + if (Port < 1 || Port > 65535) { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Already trying to connect. Ignoring."); + Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: Invalid port"); return; } - try + if (string.IsNullOrEmpty(SharedKey) && SharedKeyRequired) { - IsTryingToConnect = true; - if (RetryTimer != null) - { - RetryTimer.Stop(); - RetryTimer = null; - } - if (string.IsNullOrEmpty(Hostname)) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: No address set"); - return; - } - if (Port < 1 || Port > 65535) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: Invalid port"); - return; - } - if (string.IsNullOrEmpty(SharedKey) && SharedKeyRequired) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: No Shared Key set"); - return; - } + Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: No Shared Key set"); + return; + } - // clean up previous client - if (Client != null) - { - Cleanup(); - } - DisconnectCalledByUser = false; + // clean up previous client + if (Client != null) + { + Cleanup(); + } + DisconnectCalledByUser = false; - Client = new SecureTCPClient(Hostname, Port, BufferSize); - Client.SocketStatusChange += Client_SocketStatusChange; - if (HeartbeatEnabled) - Client.SocketSendOrReceiveTimeOutInMs = (HeartbeatInterval * 5); - Client.AddressClientConnectedTo = Hostname; - Client.PortNumber = Port; - // SecureClient = c; + Client = new SecureTCPClient(Hostname, Port, BufferSize); + Client.SocketStatusChange += Client_SocketStatusChange; + if (HeartbeatEnabled) + Client.SocketSendOrReceiveTimeOutInMs = (HeartbeatInterval * 5); + Client.AddressClientConnectedTo = Hostname; + Client.PortNumber = Port; + // SecureClient = c; - //var timeOfConnect = DateTime.Now.ToString("HH:mm:ss.fff"); + //var timeOfConnect = DateTime.Now.ToString("HH:mm:ss.fff"); - ConnectFailTimer = new CTimer(o => + ConnectFailTimer = new CTimer(o => + { + Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Connect attempt has not finished after 30sec Count:{0}", ConnectionCount); + if (IsTryingToConnect) { - Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Connect attempt has not finished after 30sec Count:{0}", ConnectionCount); - if (IsTryingToConnect) - { - IsTryingToConnect = false; - - //if (ConnectionHasHungCallback != null) - //{ - // ConnectionHasHungCallback(); - //} - //SecureClient.DisconnectFromServer(); - //CheckClosedAndTryReconnect(); - } - }, 30000); + IsTryingToConnect = false; + + //if (ConnectionHasHungCallback != null) + //{ + // ConnectionHasHungCallback(); + //} + //SecureClient.DisconnectFromServer(); + //CheckClosedAndTryReconnect(); + } + }, 30000); - Debug.Console(2, this, "Making Connection Count:{0}", ConnectionCount); - Client.ConnectToServerAsync(o => + Debug.Console(2, this, "Making Connection Count:{0}", ConnectionCount); + Client.ConnectToServerAsync(o => + { + Debug.Console(2, this, "ConnectToServerAsync Count:{0} Ran!", ConnectionCount); + + if (ConnectFailTimer != null) { - Debug.Console(2, this, "ConnectToServerAsync Count:{0} Ran!", ConnectionCount); + ConnectFailTimer.Stop(); + } + IsTryingToConnect = false; - if (ConnectFailTimer != null) - { - ConnectFailTimer.Stop(); - } - IsTryingToConnect = false; + if (o.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) + { + Debug.Console(2, this, "Client connected to {0} on port {1}", o.AddressClientConnectedTo, o.LocalPortNumberOfClient); + o.ReceiveDataAsync(Receive); - if (o.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) + if (SharedKeyRequired) { - Debug.Console(2, this, "Client connected to {0} on port {1}", o.AddressClientConnectedTo, o.LocalPortNumberOfClient); - o.ReceiveDataAsync(Receive); - - if (SharedKeyRequired) + WaitingForSharedKeyResponse = true; + WaitForSharedKey = new CTimer(timer => { - WaitingForSharedKeyResponse = true; - WaitForSharedKey = new CTimer(timer => - { - - Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Shared key exchange timer expired. IsReadyForCommunication={0}", IsReadyForCommunication); - // Debug.Console(1, this, "Connect attempt failed {0}", c.ClientStatus); - // This is the only case where we should call DisconectFromServer...Event handeler will trigger the cleanup - o.DisconnectFromServer(); - //CheckClosedAndTryReconnect(); - //OnClientReadyForcommunications(false); // Should send false event - }, 15000); - } - else - { - //CLient connected and shared key is not required so just raise the ready for communication event. if Shared key - //required this is called by the shared key being negotiated - if (IsReadyForCommunication == false) - { - OnClientReadyForcommunications(true); // Key not required - } - } + + Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Shared key exchange timer expired. IsReadyForCommunication={0}", IsReadyForCommunication); + // Debug.Console(1, this, "Connect attempt failed {0}", c.ClientStatus); + // This is the only case where we should call DisconectFromServer...Event handeler will trigger the cleanup + o.DisconnectFromServer(); + //CheckClosedAndTryReconnect(); + //OnClientReadyForcommunications(false); // Should send false event + }, 15000); } else { - Debug.Console(1, this, "Connect attempt failed {0}", o.ClientStatus); - CheckClosedAndTryReconnect(); + //CLient connected and shared key is not required so just raise the ready for communication event. if Shared key + //required this is called by the shared key being negotiated + if (IsReadyForCommunication == false) + { + OnClientReadyForcommunications(true); // Key not required + } } - }); - } - catch (Exception ex) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Client connection exception: {0}", ex.Message); - IsTryingToConnect = false; - CheckClosedAndTryReconnect(); - } + } + else + { + Debug.Console(1, this, "Connect attempt failed {0}", o.ClientStatus); + CheckClosedAndTryReconnect(); + } + }); } - - /// - /// - /// - public void Disconnect() + catch (Exception ex) { - this.LogVerbose("Disconnect Called"); + Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Client connection exception: {0}", ex.Message); + IsTryingToConnect = false; + CheckClosedAndTryReconnect(); + } + } - DisconnectCalledByUser = true; - if (IsConnected) - { - Client.DisconnectFromServer(); + /// + /// + /// + public void Disconnect() + { + this.LogVerbose("Disconnect Called"); - } - if (RetryTimer != null) - { - RetryTimer.Stop(); - RetryTimer = null; - } - Cleanup(); - } + DisconnectCalledByUser = true; + if (IsConnected) + { + Client.DisconnectFromServer(); - /// - /// Internal call to close up client. ALWAYS use this when disconnecting. - /// - void Cleanup() + } + if (RetryTimer != null) { - IsTryingToConnect = false; + RetryTimer.Stop(); + RetryTimer = null; + } + Cleanup(); + } - if (Client != null) - { - //SecureClient.DisconnectFromServer(); - Debug.Console(2, this, "Disconnecting Client {0}", DisconnectCalledByUser ? ", Called by user" : ""); - Client.SocketStatusChange -= Client_SocketStatusChange; - Client.Dispose(); - Client = null; - } - if (ConnectFailTimer != null) - { - ConnectFailTimer.Stop(); - ConnectFailTimer.Dispose(); - ConnectFailTimer = null; - } + /// + /// Internal call to close up client. ALWAYS use this when disconnecting. + /// + void Cleanup() + { + IsTryingToConnect = false; + + if (Client != null) + { + //SecureClient.DisconnectFromServer(); + Debug.Console(2, this, "Disconnecting Client {0}", DisconnectCalledByUser ? ", Called by user" : ""); + Client.SocketStatusChange -= Client_SocketStatusChange; + Client.Dispose(); + Client = null; + } + if (ConnectFailTimer != null) + { + ConnectFailTimer.Stop(); + ConnectFailTimer.Dispose(); + ConnectFailTimer = null; } + } - /// ff - /// Called from Connect failure or Socket Status change if - /// auto reconnect and socket disconnected (Not disconnected by user) - /// - void CheckClosedAndTryReconnect() + /// ff + /// Called from Connect failure or Socket Status change if + /// auto reconnect and socket disconnected (Not disconnected by user) + /// + void CheckClosedAndTryReconnect() + { + if (Client != null) { - if (Client != null) - { - Debug.Console(2, this, "Cleaning up remotely closed/failed connection."); - Cleanup(); - } - if (!DisconnectCalledByUser && AutoReconnect) + Debug.Console(2, this, "Cleaning up remotely closed/failed connection."); + Cleanup(); + } + if (!DisconnectCalledByUser && AutoReconnect) + { + var halfInterval = AutoReconnectIntervalMs / 2; + var rndTime = new Random().Next(-halfInterval, halfInterval) + AutoReconnectIntervalMs; + Debug.Console(2, this, "Attempting reconnect in {0} ms, randomized", rndTime); + if (RetryTimer != null) { - var halfInterval = AutoReconnectIntervalMs / 2; - var rndTime = new Random().Next(-halfInterval, halfInterval) + AutoReconnectIntervalMs; - Debug.Console(2, this, "Attempting reconnect in {0} ms, randomized", rndTime); - if (RetryTimer != null) - { - RetryTimer.Stop(); - RetryTimer = null; - } - if(AutoReconnectTriggered != null) - AutoReconnectTriggered(this, new EventArgs()); - RetryTimer = new CTimer(o => Connect(), rndTime); + RetryTimer.Stop(); + RetryTimer = null; } + if(AutoReconnectTriggered != null) + AutoReconnectTriggered(this, new EventArgs()); + RetryTimer = new CTimer(o => Connect(), rndTime); } + } - /// - /// Receive callback - /// - /// - /// - void Receive(SecureTCPClient client, int numBytes) + /// + /// Receive callback + /// + /// + /// + void Receive(SecureTCPClient client, int numBytes) + { + if (numBytes > 0) { - if (numBytes > 0) + string str = string.Empty; + var handler = TextReceivedQueueInvoke; + try { - string str = string.Empty; - var handler = TextReceivedQueueInvoke; - try + var bytes = client.IncomingDataBuffer.Take(numBytes).ToArray(); + str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); + Debug.Console(2, this, "Client Received:\r--------\r{0}\r--------", str); + if (!string.IsNullOrEmpty(checkHeartbeat(str))) { - var bytes = client.IncomingDataBuffer.Take(numBytes).ToArray(); - str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); - Debug.Console(2, this, "Client Received:\r--------\r{0}\r--------", str); - if (!string.IsNullOrEmpty(checkHeartbeat(str))) - { - if (SharedKeyRequired && str == "SharedKey:") - { - Debug.Console(2, this, "Server asking for shared key, sending"); - SendText(SharedKey + "\n"); - } - else if (SharedKeyRequired && str == "Shared Key Match") - { - StopWaitForSharedKeyTimer(); + if (SharedKeyRequired && str == "SharedKey:") + { + Debug.Console(2, this, "Server asking for shared key, sending"); + SendText(SharedKey + "\n"); + } + else if (SharedKeyRequired && str == "Shared Key Match") + { + StopWaitForSharedKeyTimer(); - Debug.Console(2, this, "Shared key confirmed. Ready for communication"); - OnClientReadyForcommunications(true); // Successful key exchange - } - else + Debug.Console(2, this, "Shared key confirmed. Ready for communication"); + OnClientReadyForcommunications(true); // Successful key exchange + } + else + { + //var bytesHandler = BytesReceived; + //if (bytesHandler != null) + // bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); + var textHandler = TextReceived; + if (textHandler != null) + textHandler(this, new GenericTcpServerCommMethodReceiveTextArgs(str)); + if (handler != null) { - //var bytesHandler = BytesReceived; - //if (bytesHandler != null) - // bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); - var textHandler = TextReceived; - if (textHandler != null) - textHandler(this, new GenericTcpServerCommMethodReceiveTextArgs(str)); - if (handler != null) - { - MessageQueue.TryToEnqueue(new GenericTcpServerCommMethodReceiveTextArgs(str)); - } + MessageQueue.TryToEnqueue(new GenericTcpServerCommMethodReceiveTextArgs(str)); } } } - catch (Exception ex) - { - Debug.Console(1, this, "Error receiving data: {1}. Error: {0}", ex.Message, str); - } - if (client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) - client.ReceiveDataAsync(Receive); - - //Check to see if there is a subscription to the TextReceivedQueueInvoke event. If there is start the dequeue thread. - if (handler != null) - { - var gotLock = DequeueLock.TryEnter(); - if (gotLock) - CrestronInvoke.BeginInvoke((o) => DequeueEvent()); - } } - else //JAG added this as I believe the error return is 0 bytes like the server. See help when hover on ReceiveAsync + catch (Exception ex) { - client.DisconnectFromServer(); + Debug.Console(1, this, "Error receiving data: {1}. Error: {0}", ex.Message, str); } - } + if (client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) + client.ReceiveDataAsync(Receive); - /// - /// This method gets spooled up in its own thread an protected by a CCriticalSection to prevent multiple threads from running concurrently. - /// It will dequeue items as they are enqueued automatically. - /// - void DequeueEvent() - { - try - { - while (true) - { - // Pull from Queue and fire an event. Block indefinitely until an item can be removed, similar to a Gather. - var message = MessageQueue.Dequeue(); - var handler = TextReceivedQueueInvoke; - if (handler != null) - { - handler(this, message); - } - } - } - catch (Exception e) - { - this.LogException(e, "DequeueEvent error"); - } - // Make sure to leave the CCritical section in case an exception above stops this thread, or we won't be able to restart it. - if (DequeueLock != null) + //Check to see if there is a subscription to the TextReceivedQueueInvoke event. If there is start the dequeue thread. + if (handler != null) { - DequeueLock.Leave(); + var gotLock = DequeueLock.TryEnter(); + if (gotLock) + CrestronInvoke.BeginInvoke((o) => DequeueEvent()); } } + else //JAG added this as I believe the error return is 0 bytes like the server. See help when hover on ReceiveAsync + { + client.DisconnectFromServer(); + } + } - void HeartbeatStart() + /// + /// This method gets spooled up in its own thread an protected by a CCriticalSection to prevent multiple threads from running concurrently. + /// It will dequeue items as they are enqueued automatically. + /// + void DequeueEvent() + { + try { - if (HeartbeatEnabled) + while (true) { - Debug.Console(2, this, "Starting Heartbeat"); - if (HeartbeatSendTimer == null) - { - - HeartbeatSendTimer = new CTimer(this.SendHeartbeat, null, HeartbeatInterval, HeartbeatInterval); - } - if (HeartbeatAckTimer == null) + // Pull from Queue and fire an event. Block indefinitely until an item can be removed, similar to a Gather. + var message = MessageQueue.Dequeue(); + var handler = TextReceivedQueueInvoke; + if (handler != null) { - HeartbeatAckTimer = new CTimer(HeartbeatAckTimerFail, null, (HeartbeatInterval * 2), (HeartbeatInterval * 2)); + handler(this, message); } } - } - void HeartbeatStop() + catch (Exception e) + { + this.LogException(e, "DequeueEvent error"); + } + // Make sure to leave the CCritical section in case an exception above stops this thread, or we won't be able to restart it. + if (DequeueLock != null) { + DequeueLock.Leave(); + } + } - if (HeartbeatSendTimer != null) + void HeartbeatStart() + { + if (HeartbeatEnabled) + { + Debug.Console(2, this, "Starting Heartbeat"); + if (HeartbeatSendTimer == null) { - Debug.Console(2, this, "Stoping Heartbeat Send"); - HeartbeatSendTimer.Stop(); - HeartbeatSendTimer = null; + + HeartbeatSendTimer = new CTimer(this.SendHeartbeat, null, HeartbeatInterval, HeartbeatInterval); } - if (HeartbeatAckTimer != null) + if (HeartbeatAckTimer == null) { - Debug.Console(2, this, "Stoping Heartbeat Ack"); - HeartbeatAckTimer.Stop(); - HeartbeatAckTimer = null; + HeartbeatAckTimer = new CTimer(HeartbeatAckTimerFail, null, (HeartbeatInterval * 2), (HeartbeatInterval * 2)); } + } + } + void HeartbeatStop() + { + + if (HeartbeatSendTimer != null) + { + Debug.Console(2, this, "Stoping Heartbeat Send"); + HeartbeatSendTimer.Stop(); + HeartbeatSendTimer = null; } - void SendHeartbeat(object notused) + if (HeartbeatAckTimer != null) { - this.SendText(HeartbeatString); - Debug.Console(2, this, "Sending Heartbeat"); - + Debug.Console(2, this, "Stoping Heartbeat Ack"); + HeartbeatAckTimer.Stop(); + HeartbeatAckTimer = null; } - //private method to check heartbeat requirements and start or reset timer - string checkHeartbeat(string received) + } + void SendHeartbeat(object notused) + { + this.SendText(HeartbeatString); + Debug.Console(2, this, "Sending Heartbeat"); + + } + + //private method to check heartbeat requirements and start or reset timer + string checkHeartbeat(string received) + { + try { - try + if (HeartbeatEnabled) { - if (HeartbeatEnabled) + if (!string.IsNullOrEmpty(HeartbeatString)) { - if (!string.IsNullOrEmpty(HeartbeatString)) + var remainingText = received.Replace(HeartbeatString, ""); + var noDelimiter = received.Trim(new char[] { '\r', '\n' }); + if (noDelimiter.Contains(HeartbeatString)) { - var remainingText = received.Replace(HeartbeatString, ""); - var noDelimiter = received.Trim(new char[] { '\r', '\n' }); - if (noDelimiter.Contains(HeartbeatString)) + if (HeartbeatAckTimer != null) { - if (HeartbeatAckTimer != null) - { - HeartbeatAckTimer.Reset(HeartbeatInterval * 2); - } - else - { - HeartbeatAckTimer = new CTimer(HeartbeatAckTimerFail, null, (HeartbeatInterval * 2), (HeartbeatInterval * 2)); - } - Debug.Console(2, this, "Heartbeat Received: {0}, from Server", HeartbeatString); - return remainingText; + HeartbeatAckTimer.Reset(HeartbeatInterval * 2); } + else + { + HeartbeatAckTimer = new CTimer(HeartbeatAckTimerFail, null, (HeartbeatInterval * 2), (HeartbeatInterval * 2)); + } + Debug.Console(2, this, "Heartbeat Received: {0}, from Server", HeartbeatString); + return remainingText; } } } - catch (Exception ex) - { - Debug.Console(1, this, "Error checking heartbeat: {0}", ex.Message); - } - return received; } + catch (Exception ex) + { + Debug.Console(1, this, "Error checking heartbeat: {0}", ex.Message); + } + return received; + } - void HeartbeatAckTimerFail(object o) + void HeartbeatAckTimerFail(object o) + { + try { - try - { - if (IsConnected) - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "Heartbeat not received from Server...DISCONNECTING BECAUSE HEARTBEAT REQUIRED IS TRUE"); - SendText("Heartbeat not received by server, closing connection"); - CheckClosedAndTryReconnect(); - } - - } - catch (Exception ex) + if (IsConnected) { - ErrorLog.Error("Heartbeat timeout Error on Client: {0}, {1}", Key, ex); + Debug.Console(1, Debug.ErrorLogLevel.Warning, "Heartbeat not received from Server...DISCONNECTING BECAUSE HEARTBEAT REQUIRED IS TRUE"); + SendText("Heartbeat not received by server, closing connection"); + CheckClosedAndTryReconnect(); } + } + catch (Exception ex) + { + ErrorLog.Error("Heartbeat timeout Error on Client: {0}, {1}", Key, ex); + } + } - /// - /// - /// - void StopWaitForSharedKeyTimer() + /// + /// + /// + void StopWaitForSharedKeyTimer() + { + if (WaitForSharedKey != null) { - if (WaitForSharedKey != null) - { - WaitForSharedKey.Stop(); - WaitForSharedKey = null; - } + WaitForSharedKey.Stop(); + WaitForSharedKey = null; } + } - /// - /// General send method - /// - public void SendText(string text) + /// + /// General send method + /// + public void SendText(string text) + { + if (!string.IsNullOrEmpty(text)) { - if (!string.IsNullOrEmpty(text)) + try { - try + var bytes = Encoding.GetEncoding(28591).GetBytes(text); + if (Client != null && Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) { - var bytes = Encoding.GetEncoding(28591).GetBytes(text); - if (Client != null && Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) + Client.SendDataAsync(bytes, bytes.Length, (c, n) => { - Client.SendDataAsync(bytes, bytes.Length, (c, n) => + // HOW IN THE HELL DO WE CATCH AN EXCEPTION IN SENDING????? + if (n <= 0) { - // HOW IN THE HELL DO WE CATCH AN EXCEPTION IN SENDING????? - if (n <= 0) - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "[{0}] Sent zero bytes. Was there an error?", this.Key); - } - }); - } - } - catch (Exception ex) - { - Debug.Console(0, this, "Error sending text: {1}. Error: {0}", ex.Message, text); + Debug.Console(1, Debug.ErrorLogLevel.Warning, "[{0}] Sent zero bytes. Was there an error?", this.Key); + } + }); } } - } - - /// - /// - /// - public void SendBytes(byte[] bytes) - { - if (bytes.Length > 0) + catch (Exception ex) { - try - { - if (Client != null && Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) - Client.SendData(bytes, bytes.Length); - } - catch (Exception ex) - { - Debug.Console(0, this, "Error sending bytes. Error: {0}", ex.Message); - } + Debug.Console(0, this, "Error sending text: {1}. Error: {0}", ex.Message, text); } } + } - /// - /// SocketStatusChange Callback - /// - /// - /// - void Client_SocketStatusChange(SecureTCPClient client, SocketStatus clientSocketStatus) + /// + /// + /// + public void SendBytes(byte[] bytes) + { + if (bytes.Length > 0) { - if (ProgramIsStopping) - { - ProgramIsStopping = false; - return; - } try { - Debug.Console(2, this, "Socket status change: {0} ({1})", client.ClientStatus, (ushort)(client.ClientStatus)); - - OnConnectionChange(); - // The client could be null or disposed by this time... - if (Client == null || Client.ClientStatus != SocketStatus.SOCKET_STATUS_CONNECTED) - { - HeartbeatStop(); - OnClientReadyForcommunications(false); // socket has gone low - CheckClosedAndTryReconnect(); - } + if (Client != null && Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) + Client.SendData(bytes, bytes.Length); } catch (Exception ex) { - Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Error in socket status change callback. Error: {0}\r\r{1}", ex, ex.InnerException); + Debug.Console(0, this, "Error sending bytes. Error: {0}", ex.Message); } } + } - /// - /// Helper for ConnectionChange event - /// - void OnConnectionChange() + /// + /// SocketStatusChange Callback + /// + /// + /// + void Client_SocketStatusChange(SecureTCPClient client, SocketStatus clientSocketStatus) + { + if (ProgramIsStopping) { - var handler = ConnectionChange; - if (handler != null) - ConnectionChange(this, new GenericTcpServerSocketStatusChangeEventArgs(this, Client.ClientStatus)); + ProgramIsStopping = false; + return; } + try + { + Debug.Console(2, this, "Socket status change: {0} ({1})", client.ClientStatus, (ushort)(client.ClientStatus)); - /// - /// Helper to fire ClientReadyForCommunications event - /// - void OnClientReadyForcommunications(bool isReady) + OnConnectionChange(); + // The client could be null or disposed by this time... + if (Client == null || Client.ClientStatus != SocketStatus.SOCKET_STATUS_CONNECTED) + { + HeartbeatStop(); + OnClientReadyForcommunications(false); // socket has gone low + CheckClosedAndTryReconnect(); + } + } + catch (Exception ex) { - IsReadyForCommunication = isReady; - if (this.IsReadyForCommunication) { HeartbeatStart(); } - var handler = ClientReadyForCommunications; - if (handler != null) - handler(this, new GenericTcpServerClientReadyForcommunicationsEventArgs(IsReadyForCommunication)); + Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Error in socket status change callback. Error: {0}\r\r{1}", ex, ex.InnerException); } - #endregion } + /// + /// Helper for ConnectionChange event + /// + void OnConnectionChange() + { + var handler = ConnectionChange; + if (handler != null) + ConnectionChange(this, new GenericTcpServerSocketStatusChangeEventArgs(this, Client.ClientStatus)); + } + + /// + /// Helper to fire ClientReadyForCommunications event + /// + void OnClientReadyForcommunications(bool isReady) + { + IsReadyForCommunication = isReady; + if (this.IsReadyForCommunication) { HeartbeatStart(); } + var handler = ClientReadyForCommunications; + if (handler != null) + handler(this, new GenericTcpServerClientReadyForcommunicationsEventArgs(IsReadyForCommunication)); + } + #endregion } \ No newline at end of file diff --git a/src/PepperDash.Core/Comm/GenericSecureTcpIpServer.cs b/src/PepperDash.Core/Comm/GenericSecureTcpIpServer.cs index e0da068f9..7804369c8 100644 --- a/src/PepperDash.Core/Comm/GenericSecureTcpIpServer.cs +++ b/src/PepperDash.Core/Comm/GenericSecureTcpIpServer.cs @@ -17,403 +17,403 @@ PepperDash Technology Corporation reserves all rights under applicable laws. using Crestron.SimplSharp.CrestronSockets; using PepperDash.Core.Logging; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// Generic secure TCP/IP server +/// +public class GenericSecureTcpIpServer : Device { + #region Events /// - /// Generic secure TCP/IP server + /// Event for Receiving text /// - public class GenericSecureTcpIpServer : Device - { - #region Events - /// - /// Event for Receiving text - /// - public event EventHandler TextReceived; - - /// - /// Event for Receiving text. Once subscribed to this event the receive callback will start a thread that dequeues the messages and invokes the event on a new thread. - /// It is not recommended to use both the TextReceived event and the TextReceivedQueueInvoke event. - /// - public event EventHandler TextReceivedQueueInvoke; - - /// - /// Event for client connection socket status change - /// - public event EventHandler ClientConnectionChange; - - /// - /// Event for Server State Change - /// - public event EventHandler ServerStateChange; - - /// - /// For a server with a pre shared key, this will fire after the communication is established and the key exchange is complete. If no shared key, this will fire - /// after connection is successful. Use this event to know when the client is ready for communication to avoid stepping on shared key. - /// - public event EventHandler ServerClientReadyForCommunications; - - /// - /// A band aid event to notify user that the server has choked. - /// - public ServerHasChokedCallbackDelegate ServerHasChoked { get; set; } - - /// - /// - /// - public delegate void ServerHasChokedCallbackDelegate(); - - #endregion - - #region Properties/Variables - - /// - /// Server listen lock - /// - CCriticalSection ServerCCSection = new CCriticalSection(); - - /// - /// Queue lock - /// - CCriticalSection DequeueLock = new CCriticalSection(); - - /// - /// Receive Queue size. Defaults to 20. Will set to 20 if QueueSize property is less than 20. Use constructor or set queue size property before - /// calling initialize. - /// - public int ReceiveQueueSize { get; set; } - - /// - /// Queue to temporarily store received messages with the source IP and Port info. Defaults to size 20. Use constructor or set queue size property before - /// calling initialize. - /// - private CrestronQueue MessageQueue; - - /// - /// A bandaid client that monitors whether the server is reachable - /// - GenericSecureTcpIpClient_ForServer MonitorClient; - - /// - /// Timer to operate the bandaid monitor client in a loop. - /// - CTimer MonitorClientTimer; - - /// - /// - /// - int MonitorClientFailureCount; - - /// - /// 3 by default - /// - public int MonitorClientMaxFailureCount { get; set; } - - /// - /// Text representation of the Socket Status enum values for the server - /// - public string Status - { - get - { - if (SecureServer != null) - return SecureServer.State.ToString(); - return ServerState.SERVER_NOT_LISTENING.ToString(); + public event EventHandler TextReceived; - } + /// + /// Event for Receiving text. Once subscribed to this event the receive callback will start a thread that dequeues the messages and invokes the event on a new thread. + /// It is not recommended to use both the TextReceived event and the TextReceivedQueueInvoke event. + /// + public event EventHandler TextReceivedQueueInvoke; - } + /// + /// Event for client connection socket status change + /// + public event EventHandler ClientConnectionChange; - /// - /// Bool showing if socket is connected - /// - public bool IsConnected - { - get - { - if (SecureServer != null) - return (SecureServer.State & ServerState.SERVER_CONNECTED) == ServerState.SERVER_CONNECTED; - return false; + /// + /// Event for Server State Change + /// + public event EventHandler ServerStateChange; - //return (Secure ? SecureServer != null : UnsecureServer != null) && - //(Secure ? (SecureServer.State & ServerState.SERVER_CONNECTED) == ServerState.SERVER_CONNECTED : - // (UnsecureServer.State & ServerState.SERVER_CONNECTED) == ServerState.SERVER_CONNECTED); - } - } + /// + /// For a server with a pre shared key, this will fire after the communication is established and the key exchange is complete. If no shared key, this will fire + /// after connection is successful. Use this event to know when the client is ready for communication to avoid stepping on shared key. + /// + public event EventHandler ServerClientReadyForCommunications; + + /// + /// A band aid event to notify user that the server has choked. + /// + public ServerHasChokedCallbackDelegate ServerHasChoked { get; set; } + + /// + /// + /// + public delegate void ServerHasChokedCallbackDelegate(); + + #endregion + + #region Properties/Variables + + /// + /// Server listen lock + /// + CCriticalSection ServerCCSection = new CCriticalSection(); - /// - /// S+ helper for IsConnected - /// - public ushort UIsConnected + /// + /// Queue lock + /// + CCriticalSection DequeueLock = new CCriticalSection(); + + /// + /// Receive Queue size. Defaults to 20. Will set to 20 if QueueSize property is less than 20. Use constructor or set queue size property before + /// calling initialize. + /// + public int ReceiveQueueSize { get; set; } + + /// + /// Queue to temporarily store received messages with the source IP and Port info. Defaults to size 20. Use constructor or set queue size property before + /// calling initialize. + /// + private CrestronQueue MessageQueue; + + /// + /// A bandaid client that monitors whether the server is reachable + /// + GenericSecureTcpIpClient_ForServer MonitorClient; + + /// + /// Timer to operate the bandaid monitor client in a loop. + /// + CTimer MonitorClientTimer; + + /// + /// + /// + int MonitorClientFailureCount; + + /// + /// 3 by default + /// + public int MonitorClientMaxFailureCount { get; set; } + + /// + /// Text representation of the Socket Status enum values for the server + /// + public string Status + { + get { - get { return (ushort)(IsConnected ? 1 : 0); } + if (SecureServer != null) + return SecureServer.State.ToString(); + return ServerState.SERVER_NOT_LISTENING.ToString(); + } - /// - /// Bool showing if socket is connected - /// - public bool IsListening + } + + /// + /// Bool showing if socket is connected + /// + public bool IsConnected + { + get { - get - { - if (SecureServer != null) - return (SecureServer.State & ServerState.SERVER_LISTENING) == ServerState.SERVER_LISTENING; - else - return false; - //return (Secure ? SecureServer != null : UnsecureServer != null) && - //(Secure ? (SecureServer.State & ServerState.SERVER_LISTENING) == ServerState.SERVER_LISTENING : - // (UnsecureServer.State & ServerState.SERVER_LISTENING) == ServerState.SERVER_LISTENING); - } + if (SecureServer != null) + return (SecureServer.State & ServerState.SERVER_CONNECTED) == ServerState.SERVER_CONNECTED; + return false; + + //return (Secure ? SecureServer != null : UnsecureServer != null) && + //(Secure ? (SecureServer.State & ServerState.SERVER_CONNECTED) == ServerState.SERVER_CONNECTED : + // (UnsecureServer.State & ServerState.SERVER_CONNECTED) == ServerState.SERVER_CONNECTED); } + } + + /// + /// S+ helper for IsConnected + /// + public ushort UIsConnected + { + get { return (ushort)(IsConnected ? 1 : 0); } + } - /// - /// S+ helper for IsConnected - /// - public ushort UIsListening + /// + /// Bool showing if socket is connected + /// + public bool IsListening + { + get { - get { return (ushort)(IsListening ? 1 : 0); } + if (SecureServer != null) + return (SecureServer.State & ServerState.SERVER_LISTENING) == ServerState.SERVER_LISTENING; + else + return false; + //return (Secure ? SecureServer != null : UnsecureServer != null) && + //(Secure ? (SecureServer.State & ServerState.SERVER_LISTENING) == ServerState.SERVER_LISTENING : + // (UnsecureServer.State & ServerState.SERVER_LISTENING) == ServerState.SERVER_LISTENING); } - /// - /// Max number of clients this server will allow for connection. Crestron max is 64. This number should be less than 65 - /// - public ushort MaxClients { get; set; } // should be set by parameter in SIMPL+ in the MAIN method, Should not ever need to be configurable - /// - /// Number of clients currently connected. - /// - public ushort NumberOfClientsConnected + } + + /// + /// S+ helper for IsConnected + /// + public ushort UIsListening + { + get { return (ushort)(IsListening ? 1 : 0); } + } + /// + /// Max number of clients this server will allow for connection. Crestron max is 64. This number should be less than 65 + /// + public ushort MaxClients { get; set; } // should be set by parameter in SIMPL+ in the MAIN method, Should not ever need to be configurable + /// + /// Number of clients currently connected. + /// + public ushort NumberOfClientsConnected + { + get { - get - { - if (SecureServer != null) - return (ushort)SecureServer.NumberOfClientsConnected; - return 0; - } + if (SecureServer != null) + return (ushort)SecureServer.NumberOfClientsConnected; + return 0; } + } + + /// + /// Port Server should listen on + /// + public int Port { get; set; } + + /// + /// S+ helper for Port + /// + public ushort UPort + { + get { return Convert.ToUInt16(Port); } + set { Port = Convert.ToInt32(value); } + } - /// - /// Port Server should listen on - /// - public int Port { get; set; } + /// + /// Bool to show whether the server requires a preshared key. Must be set the same in the client, and if true shared keys must be identical on server/client + /// + public bool SharedKeyRequired { get; set; } - /// - /// S+ helper for Port - /// - public ushort UPort + /// + /// S+ helper for requires shared key bool + /// + public ushort USharedKeyRequired + { + set { - get { return Convert.ToUInt16(Port); } - set { Port = Convert.ToInt32(value); } + if (value == 1) + SharedKeyRequired = true; + else + SharedKeyRequired = false; } + } - /// - /// Bool to show whether the server requires a preshared key. Must be set the same in the client, and if true shared keys must be identical on server/client - /// - public bool SharedKeyRequired { get; set; } + /// + /// SharedKey is sent for varification to the server. Shared key can be any text (255 char limit in SIMPL+ Module), but must match the Shared Key on the Server module. + /// If SharedKey changes while server is listening or clients are connected, disconnect and stop listening will be called + /// + public string SharedKey { get; set; } - /// - /// S+ helper for requires shared key bool - /// - public ushort USharedKeyRequired - { - set - { - if (value == 1) - SharedKeyRequired = true; - else - SharedKeyRequired = false; - } - } + /// + /// Heartbeat Required bool sets whether server disconnects client if heartbeat is not received + /// + public bool HeartbeatRequired { get; set; } - /// - /// SharedKey is sent for varification to the server. Shared key can be any text (255 char limit in SIMPL+ Module), but must match the Shared Key on the Server module. - /// If SharedKey changes while server is listening or clients are connected, disconnect and stop listening will be called - /// - public string SharedKey { get; set; } - - /// - /// Heartbeat Required bool sets whether server disconnects client if heartbeat is not received - /// - public bool HeartbeatRequired { get; set; } - - /// - /// S+ Helper for Heartbeat Required - /// - public ushort UHeartbeatRequired + /// + /// S+ Helper for Heartbeat Required + /// + public ushort UHeartbeatRequired + { + set { - set - { - if (value == 1) - HeartbeatRequired = true; - else - HeartbeatRequired = false; - } + if (value == 1) + HeartbeatRequired = true; + else + HeartbeatRequired = false; } + } - /// - /// Milliseconds before server expects another heartbeat. Set by property HeartbeatRequiredIntervalInSeconds which is driven from S+ - /// - public int HeartbeatRequiredIntervalMs { get; set; } + /// + /// Milliseconds before server expects another heartbeat. Set by property HeartbeatRequiredIntervalInSeconds which is driven from S+ + /// + public int HeartbeatRequiredIntervalMs { get; set; } - /// - /// Simpl+ Heartbeat Analog value in seconds - /// - public ushort HeartbeatRequiredIntervalInSeconds { set { HeartbeatRequiredIntervalMs = (value * 1000); } } + /// + /// Simpl+ Heartbeat Analog value in seconds + /// + public ushort HeartbeatRequiredIntervalInSeconds { set { HeartbeatRequiredIntervalMs = (value * 1000); } } - /// - /// String to Match for heartbeat. If null or empty any string will reset heartbeat timer - /// - public string HeartbeatStringToMatch { get; set; } + /// + /// String to Match for heartbeat. If null or empty any string will reset heartbeat timer + /// + public string HeartbeatStringToMatch { get; set; } - //private timers for Heartbeats per client - Dictionary HeartbeatTimerDictionary = new Dictionary(); + //private timers for Heartbeats per client + Dictionary HeartbeatTimerDictionary = new Dictionary(); - //flags to show the secure server is waiting for client at index to send the shared key - List WaitingForSharedKey = new List(); + //flags to show the secure server is waiting for client at index to send the shared key + List WaitingForSharedKey = new List(); - List ClientReadyAfterKeyExchange = new List(); + List ClientReadyAfterKeyExchange = new List(); - /// - /// The connected client indexes - /// - public List ConnectedClientsIndexes = new List(); + /// + /// The connected client indexes + /// + public List ConnectedClientsIndexes = new List(); - /// - /// Defaults to 2000 - /// - public int BufferSize { get; set; } + /// + /// Defaults to 2000 + /// + public int BufferSize { get; set; } - /// - /// Private flag to note that the server has stopped intentionally - /// - private bool ServerStopped { get; set; } + /// + /// Private flag to note that the server has stopped intentionally + /// + private bool ServerStopped { get; set; } - //Servers - SecureTCPServer SecureServer; + //Servers + SecureTCPServer SecureServer; - /// - /// - /// - bool ProgramIsStopping; + /// + /// + /// + bool ProgramIsStopping; - #endregion + #endregion - #region Constructors - /// - /// constructor S+ Does not accept a key. Use initialze with key to set the debug key on this device. If using with + make sure to set all properties manually. - /// - public GenericSecureTcpIpServer() - : base("Uninitialized Secure TCP Server") - { - HeartbeatRequiredIntervalInSeconds = 15; - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - BufferSize = 2000; - MonitorClientMaxFailureCount = 3; - } + #region Constructors + /// + /// constructor S+ Does not accept a key. Use initialze with key to set the debug key on this device. If using with + make sure to set all properties manually. + /// + public GenericSecureTcpIpServer() + : base("Uninitialized Secure TCP Server") + { + HeartbeatRequiredIntervalInSeconds = 15; + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + BufferSize = 2000; + MonitorClientMaxFailureCount = 3; + } - /// - /// constructor with debug key set at instantiation. Make sure to set all properties before listening. - /// - /// - public GenericSecureTcpIpServer(string key) - : base("Uninitialized Secure TCP Server") - { - HeartbeatRequiredIntervalInSeconds = 15; - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - BufferSize = 2000; - MonitorClientMaxFailureCount = 3; - Key = key; - } + /// + /// constructor with debug key set at instantiation. Make sure to set all properties before listening. + /// + /// + public GenericSecureTcpIpServer(string key) + : base("Uninitialized Secure TCP Server") + { + HeartbeatRequiredIntervalInSeconds = 15; + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + BufferSize = 2000; + MonitorClientMaxFailureCount = 3; + Key = key; + } - /// - /// Contstructor that sets all properties by calling the initialize method with a config object. This does set Queue size. - /// - /// - public GenericSecureTcpIpServer(TcpServerConfigObject serverConfigObject) - : base("Uninitialized Secure TCP Server") - { - HeartbeatRequiredIntervalInSeconds = 15; - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - BufferSize = 2000; - MonitorClientMaxFailureCount = 3; - Initialize(serverConfigObject); - } - #endregion + /// + /// Contstructor that sets all properties by calling the initialize method with a config object. This does set Queue size. + /// + /// + public GenericSecureTcpIpServer(TcpServerConfigObject serverConfigObject) + : base("Uninitialized Secure TCP Server") + { + HeartbeatRequiredIntervalInSeconds = 15; + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + BufferSize = 2000; + MonitorClientMaxFailureCount = 3; + Initialize(serverConfigObject); + } + #endregion - #region Methods - Server Actions - /// - /// Disconnects all clients and stops the server - /// - public void KillServer() + #region Methods - Server Actions + /// + /// Disconnects all clients and stops the server + /// + public void KillServer() + { + ServerStopped = true; + if (MonitorClient != null) { - ServerStopped = true; - if (MonitorClient != null) - { - MonitorClient.Disconnect(); - } - DisconnectAllClientsForShutdown(); - StopListening(); + MonitorClient.Disconnect(); } + DisconnectAllClientsForShutdown(); + StopListening(); + } - /// - /// Initialize Key for device using client name from SIMPL+. Called on Listen from SIMPL+ - /// - /// - public void Initialize(string key) - { - Key = key; - } + /// + /// Initialize Key for device using client name from SIMPL+. Called on Listen from SIMPL+ + /// + /// + public void Initialize(string key) + { + Key = key; + } - /// - /// Initialze the server - /// - /// - public void Initialize(TcpServerConfigObject serverConfigObject) + /// + /// Initialze the server + /// + /// + public void Initialize(TcpServerConfigObject serverConfigObject) + { + try { - try + if (serverConfigObject != null || string.IsNullOrEmpty(serverConfigObject.Key)) { - if (serverConfigObject != null || string.IsNullOrEmpty(serverConfigObject.Key)) - { - Key = serverConfigObject.Key; - MaxClients = serverConfigObject.MaxClients; - Port = serverConfigObject.Port; - SharedKeyRequired = serverConfigObject.SharedKeyRequired; - SharedKey = serverConfigObject.SharedKey; - HeartbeatRequired = serverConfigObject.HeartbeatRequired; - HeartbeatRequiredIntervalInSeconds = serverConfigObject.HeartbeatRequiredIntervalInSeconds; - HeartbeatStringToMatch = serverConfigObject.HeartbeatStringToMatch; - BufferSize = serverConfigObject.BufferSize; - ReceiveQueueSize = serverConfigObject.ReceiveQueueSize > 20 ? serverConfigObject.ReceiveQueueSize : 20; - MessageQueue = new CrestronQueue(ReceiveQueueSize); - } - else - { - ErrorLog.Error("Could not initialize server with key: {0}", serverConfigObject.Key); - } + Key = serverConfigObject.Key; + MaxClients = serverConfigObject.MaxClients; + Port = serverConfigObject.Port; + SharedKeyRequired = serverConfigObject.SharedKeyRequired; + SharedKey = serverConfigObject.SharedKey; + HeartbeatRequired = serverConfigObject.HeartbeatRequired; + HeartbeatRequiredIntervalInSeconds = serverConfigObject.HeartbeatRequiredIntervalInSeconds; + HeartbeatStringToMatch = serverConfigObject.HeartbeatStringToMatch; + BufferSize = serverConfigObject.BufferSize; + ReceiveQueueSize = serverConfigObject.ReceiveQueueSize > 20 ? serverConfigObject.ReceiveQueueSize : 20; + MessageQueue = new CrestronQueue(ReceiveQueueSize); } - catch + else { ErrorLog.Error("Could not initialize server with key: {0}", serverConfigObject.Key); } } + catch + { + ErrorLog.Error("Could not initialize server with key: {0}", serverConfigObject.Key); + } + } - /// - /// Start listening on the specified port - /// - public void Listen() + /// + /// Start listening on the specified port + /// + public void Listen() + { + ServerCCSection.Enter(); + try { - ServerCCSection.Enter(); - try + if (Port < 1 || Port > 65535) { - if (Port < 1 || Port > 65535) - { - Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Server '{0}': Invalid port", Key); - ErrorLog.Warn(string.Format("Server '{0}': Invalid port", Key)); - return; - } - if (string.IsNullOrEmpty(SharedKey) && SharedKeyRequired) - { - Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Server '{0}': No Shared Key set", Key); - ErrorLog.Warn(string.Format("Server '{0}': No Shared Key set", Key)); - return; - } + Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Server '{0}': Invalid port", Key); + ErrorLog.Warn(string.Format("Server '{0}': Invalid port", Key)); + return; + } + if (string.IsNullOrEmpty(SharedKey) && SharedKeyRequired) + { + Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Server '{0}': No Shared Key set", Key); + ErrorLog.Warn(string.Format("Server '{0}': No Shared Key set", Key)); + return; + } if (SecureServer == null) @@ -444,19 +444,19 @@ public void Listen() Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Secure Server Status: {0}, Socket Status: {1}", SecureServer.State, SecureServer.ServerSocketStatus); ServerCCSection.Leave(); - } - catch (Exception ex) - { - ServerCCSection.Leave(); - ErrorLog.Error("{1} Error with Dynamic Server: {0}", ex.ToString(), Key); - } } - - /// - /// Stop Listeneing - /// - public void StopListening() + catch (Exception ex) { + ServerCCSection.Leave(); + ErrorLog.Error("{1} Error with Dynamic Server: {0}", ex.ToString(), Key); + } + } + + /// + /// Stop Listeneing + /// + public void StopListening() + { try { Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Stopping Listener"); @@ -472,144 +472,129 @@ public void StopListening() { Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error stopping server. Error: {0}", ex); } - } + } - /// - /// Disconnects Client - /// - /// - public void DisconnectClient(uint client) + /// + /// Disconnects Client + /// + /// + public void DisconnectClient(uint client) + { + try { - try - { - SecureServer.Disconnect(client); - Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Disconnected client index: {0}", client); - } - catch (Exception ex) - { - Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error Disconnecting client index: {0}. Error: {1}", client, ex); - } + SecureServer.Disconnect(client); + Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Disconnected client index: {0}", client); } - /// - /// Disconnect All Clients - /// - public void DisconnectAllClientsForShutdown() + catch (Exception ex) { - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Disconnecting All Clients"); - if (SecureServer != null) + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error Disconnecting client index: {0}. Error: {1}", client, ex); + } + } + /// + /// Disconnect All Clients + /// + public void DisconnectAllClientsForShutdown() + { + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Disconnecting All Clients"); + if (SecureServer != null) + { + SecureServer.SocketStatusChange -= SecureServer_SocketStatusChange; + foreach (var index in ConnectedClientsIndexes.ToList()) // copy it here so that it iterates properly { - SecureServer.SocketStatusChange -= SecureServer_SocketStatusChange; - foreach (var index in ConnectedClientsIndexes.ToList()) // copy it here so that it iterates properly + var i = index; + if (!SecureServer.ClientConnected(index)) + continue; + try { - var i = index; - if (!SecureServer.ClientConnected(index)) - continue; - try - { - SecureServer.Disconnect(i); - Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Disconnected client index: {0}", i); - } - catch (Exception ex) - { - Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error Disconnecting client index: {0}. Error: {1}", i, ex); - } + SecureServer.Disconnect(i); + Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Disconnected client index: {0}", i); + } + catch (Exception ex) + { + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error Disconnecting client index: {0}. Error: {1}", i, ex); } - Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Server Status: {0}", SecureServer.ServerSocketStatus); } + Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Server Status: {0}", SecureServer.ServerSocketStatus); + } - Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Disconnected All Clients"); - ConnectedClientsIndexes.Clear(); - - if (!ProgramIsStopping) - { - OnConnectionChange(); - OnServerStateChange(SecureServer.State); //State shows both listening and connected - } + Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Disconnected All Clients"); + ConnectedClientsIndexes.Clear(); - // var o = new { }; + if (!ProgramIsStopping) + { + OnConnectionChange(); + OnServerStateChange(SecureServer.State); //State shows both listening and connected } - /// - /// Broadcast text from server to all connected clients - /// - /// - public void BroadcastText(string text) + // var o = new { }; + } + + /// + /// Broadcast text from server to all connected clients + /// + /// + public void BroadcastText(string text) + { + CCriticalSection CCBroadcast = new CCriticalSection(); + CCBroadcast.Enter(); + try { - CCriticalSection CCBroadcast = new CCriticalSection(); - CCBroadcast.Enter(); - try + if (ConnectedClientsIndexes.Count > 0) { - if (ConnectedClientsIndexes.Count > 0) + byte[] b = Encoding.GetEncoding(28591).GetBytes(text); + foreach (uint i in ConnectedClientsIndexes) { - byte[] b = Encoding.GetEncoding(28591).GetBytes(text); - foreach (uint i in ConnectedClientsIndexes) + if (!SharedKeyRequired || (SharedKeyRequired && ClientReadyAfterKeyExchange.Contains(i))) { - if (!SharedKeyRequired || (SharedKeyRequired && ClientReadyAfterKeyExchange.Contains(i))) - { - SocketErrorCodes error = SecureServer.SendDataAsync(i, b, b.Length, (x, y, z) => { }); - if (error != SocketErrorCodes.SOCKET_OK && error != SocketErrorCodes.SOCKET_OPERATION_PENDING) - this.LogVerbose("{error}", error); - } + SocketErrorCodes error = SecureServer.SendDataAsync(i, b, b.Length, (x, y, z) => { }); + if (error != SocketErrorCodes.SOCKET_OK && error != SocketErrorCodes.SOCKET_OPERATION_PENDING) + this.LogVerbose("{error}", error); } } - CCBroadcast.Leave(); - } - catch (Exception ex) - { - CCBroadcast.Leave(); - Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error Broadcasting messages from server. Error: {0}", ex.Message); } + CCBroadcast.Leave(); + } + catch (Exception ex) + { + CCBroadcast.Leave(); + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error Broadcasting messages from server. Error: {0}", ex.Message); } + } - /// - /// Not sure this is useful in library, maybe Pro?? - /// - /// - /// - public void SendTextToClient(string text, uint clientIndex) + /// + /// Not sure this is useful in library, maybe Pro?? + /// + /// + /// + public void SendTextToClient(string text, uint clientIndex) + { + try { - try - { - byte[] b = Encoding.GetEncoding(28591).GetBytes(text); - if (SecureServer != null && SecureServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) - { - if (!SharedKeyRequired || (SharedKeyRequired && ClientReadyAfterKeyExchange.Contains(clientIndex))) - SecureServer.SendDataAsync(clientIndex, b, b.Length, (x, y, z) => { }); - } - } - catch (Exception ex) + byte[] b = Encoding.GetEncoding(28591).GetBytes(text); + if (SecureServer != null && SecureServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) { - Debug.Console(2, this, "Error sending text to client. Text: {1}. Error: {0}", ex.Message, text); + if (!SharedKeyRequired || (SharedKeyRequired && ClientReadyAfterKeyExchange.Contains(clientIndex))) + SecureServer.SendDataAsync(clientIndex, b, b.Length, (x, y, z) => { }); } } + catch (Exception ex) + { + Debug.Console(2, this, "Error sending text to client. Text: {1}. Error: {0}", ex.Message, text); + } + } - //private method to check heartbeat requirements and start or reset timer - string checkHeartbeat(uint clientIndex, string received) + //private method to check heartbeat requirements and start or reset timer + string checkHeartbeat(uint clientIndex, string received) + { + try { - try + if (HeartbeatRequired) { - if (HeartbeatRequired) + if (!string.IsNullOrEmpty(HeartbeatStringToMatch)) { - if (!string.IsNullOrEmpty(HeartbeatStringToMatch)) - { - var remainingText = received.Replace(HeartbeatStringToMatch, ""); - var noDelimiter = received.Trim(new char[] { '\r', '\n' }); - if (noDelimiter.Contains(HeartbeatStringToMatch)) - { - if (HeartbeatTimerDictionary.ContainsKey(clientIndex)) - HeartbeatTimerDictionary[clientIndex].Reset(HeartbeatRequiredIntervalMs); - else - { - CTimer HeartbeatTimer = new CTimer(HeartbeatTimer_CallbackFunction, clientIndex, HeartbeatRequiredIntervalMs); - HeartbeatTimerDictionary.Add(clientIndex, HeartbeatTimer); - } - Debug.Console(1, this, "Heartbeat Received: {0}, from client index: {1}", HeartbeatStringToMatch, clientIndex); - // Return Heartbeat - SendTextToClient(HeartbeatStringToMatch, clientIndex); - return remainingText; - } - } - else + var remainingText = received.Replace(HeartbeatStringToMatch, ""); + var noDelimiter = received.Trim(new char[] { '\r', '\n' }); + if (noDelimiter.Contains(HeartbeatStringToMatch)) { if (HeartbeatTimerDictionary.ContainsKey(clientIndex)) HeartbeatTimerDictionary[clientIndex].Reset(HeartbeatRequiredIntervalMs); @@ -618,179 +603,194 @@ string checkHeartbeat(uint clientIndex, string received) CTimer HeartbeatTimer = new CTimer(HeartbeatTimer_CallbackFunction, clientIndex, HeartbeatRequiredIntervalMs); HeartbeatTimerDictionary.Add(clientIndex, HeartbeatTimer); } - Debug.Console(1, this, "Heartbeat Received: {0}, from client index: {1}", received, clientIndex); + Debug.Console(1, this, "Heartbeat Received: {0}, from client index: {1}", HeartbeatStringToMatch, clientIndex); + // Return Heartbeat + SendTextToClient(HeartbeatStringToMatch, clientIndex); + return remainingText; } } + else + { + if (HeartbeatTimerDictionary.ContainsKey(clientIndex)) + HeartbeatTimerDictionary[clientIndex].Reset(HeartbeatRequiredIntervalMs); + else + { + CTimer HeartbeatTimer = new CTimer(HeartbeatTimer_CallbackFunction, clientIndex, HeartbeatRequiredIntervalMs); + HeartbeatTimerDictionary.Add(clientIndex, HeartbeatTimer); + } + Debug.Console(1, this, "Heartbeat Received: {0}, from client index: {1}", received, clientIndex); + } } - catch (Exception ex) - { - Debug.Console(1, this, "Error checking heartbeat: {0}", ex.Message); - } - return received; } + catch (Exception ex) + { + Debug.Console(1, this, "Error checking heartbeat: {0}", ex.Message); + } + return received; + } - /// - /// Get the IP Address for the client at the specifed index - /// - /// - /// - public string GetClientIPAddress(uint clientIndex) + /// + /// Get the IP Address for the client at the specifed index + /// + /// + /// + public string GetClientIPAddress(uint clientIndex) + { + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "GetClientIPAddress Index: {0}", clientIndex); + if (!SharedKeyRequired || (SharedKeyRequired && ClientReadyAfterKeyExchange.Contains(clientIndex))) { - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "GetClientIPAddress Index: {0}", clientIndex); - if (!SharedKeyRequired || (SharedKeyRequired && ClientReadyAfterKeyExchange.Contains(clientIndex))) - { - var ipa = this.SecureServer.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex); - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "GetClientIPAddress IPAddreess: {0}", ipa); - return ipa; + var ipa = this.SecureServer.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex); + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "GetClientIPAddress IPAddreess: {0}", ipa); + return ipa; - } - else - { - return ""; - } } + else + { + return ""; + } + } - #endregion + #endregion - #region Methods - HeartbeatTimer Callback + #region Methods - HeartbeatTimer Callback - void HeartbeatTimer_CallbackFunction(object o) + void HeartbeatTimer_CallbackFunction(object o) + { + uint clientIndex = 99999; + string address = string.Empty; + try { - uint clientIndex = 99999; - string address = string.Empty; - try - { - clientIndex = (uint)o; - address = SecureServer.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex); + clientIndex = (uint)o; + address = SecureServer.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex); - Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Heartbeat not received for Client index {2} IP: {0}, DISCONNECTING BECAUSE HEARTBEAT REQUIRED IS TRUE {1}", - address, string.IsNullOrEmpty(HeartbeatStringToMatch) ? "" : ("HeartbeatStringToMatch: " + HeartbeatStringToMatch), clientIndex); + Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Heartbeat not received for Client index {2} IP: {0}, DISCONNECTING BECAUSE HEARTBEAT REQUIRED IS TRUE {1}", + address, string.IsNullOrEmpty(HeartbeatStringToMatch) ? "" : ("HeartbeatStringToMatch: " + HeartbeatStringToMatch), clientIndex); - if (SecureServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) - SendTextToClient("Heartbeat not received by server, closing connection", clientIndex); + if (SecureServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) + SendTextToClient("Heartbeat not received by server, closing connection", clientIndex); - var discoResult = SecureServer.Disconnect(clientIndex); - //Debug.Console(1, this, "{0}", discoResult); + var discoResult = SecureServer.Disconnect(clientIndex); + //Debug.Console(1, this, "{0}", discoResult); - if (HeartbeatTimerDictionary.ContainsKey(clientIndex)) - { - HeartbeatTimerDictionary[clientIndex].Stop(); - HeartbeatTimerDictionary[clientIndex].Dispose(); - HeartbeatTimerDictionary.Remove(clientIndex); - } - } - catch (Exception ex) + if (HeartbeatTimerDictionary.ContainsKey(clientIndex)) { - ErrorLog.Error("{3}: Heartbeat timeout Error on Client Index: {0}, at address: {1}, error: {2}", clientIndex, address, ex.Message, Key); + HeartbeatTimerDictionary[clientIndex].Stop(); + HeartbeatTimerDictionary[clientIndex].Dispose(); + HeartbeatTimerDictionary.Remove(clientIndex); } } + catch (Exception ex) + { + ErrorLog.Error("{3}: Heartbeat timeout Error on Client Index: {0}, at address: {1}, error: {2}", clientIndex, address, ex.Message, Key); + } + } - #endregion + #endregion - #region Methods - Socket Status Changed Callbacks - /// - /// Secure Server Socket Status Changed Callback - /// - /// - /// - /// - void SecureServer_SocketStatusChange(SecureTCPServer server, uint clientIndex, SocketStatus serverSocketStatus) + #region Methods - Socket Status Changed Callbacks + /// + /// Secure Server Socket Status Changed Callback + /// + /// + /// + /// + void SecureServer_SocketStatusChange(SecureTCPServer server, uint clientIndex, SocketStatus serverSocketStatus) + { + try { - try - { - // Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "SecureServerSocketStatusChange Index:{0} status:{1} Port:{2} IP:{3}", clientIndex, serverSocketStatus, this.SecureServer.GetPortNumberServerAcceptedConnectionFromForSpecificClient(clientIndex), this.SecureServer.GetLocalAddressServerAcceptedConnectionFromForSpecificClient(clientIndex)); - if (serverSocketStatus != SocketStatus.SOCKET_STATUS_CONNECTED) - { + // Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "SecureServerSocketStatusChange Index:{0} status:{1} Port:{2} IP:{3}", clientIndex, serverSocketStatus, this.SecureServer.GetPortNumberServerAcceptedConnectionFromForSpecificClient(clientIndex), this.SecureServer.GetLocalAddressServerAcceptedConnectionFromForSpecificClient(clientIndex)); + if (serverSocketStatus != SocketStatus.SOCKET_STATUS_CONNECTED) + { Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "SecureServerSocketStatusChange ConnectedCLients: {0} ServerState: {1} Port: {2}", SecureServer.NumberOfClientsConnected, SecureServer.State, SecureServer.PortNumber); - - if (ConnectedClientsIndexes.Contains(clientIndex)) - ConnectedClientsIndexes.Remove(clientIndex); - if (HeartbeatRequired && HeartbeatTimerDictionary.ContainsKey(clientIndex)) - { - HeartbeatTimerDictionary[clientIndex].Stop(); - HeartbeatTimerDictionary[clientIndex].Dispose(); - HeartbeatTimerDictionary.Remove(clientIndex); - } - if (ClientReadyAfterKeyExchange.Contains(clientIndex)) - ClientReadyAfterKeyExchange.Remove(clientIndex); + + if (ConnectedClientsIndexes.Contains(clientIndex)) + ConnectedClientsIndexes.Remove(clientIndex); + if (HeartbeatRequired && HeartbeatTimerDictionary.ContainsKey(clientIndex)) + { + HeartbeatTimerDictionary[clientIndex].Stop(); + HeartbeatTimerDictionary[clientIndex].Dispose(); + HeartbeatTimerDictionary.Remove(clientIndex); + } + if (ClientReadyAfterKeyExchange.Contains(clientIndex)) + ClientReadyAfterKeyExchange.Remove(clientIndex); if (WaitingForSharedKey.Contains(clientIndex)) WaitingForSharedKey.Remove(clientIndex); if (SecureServer.MaxNumberOfClientSupported > SecureServer.NumberOfClientsConnected) { Listen(); } - } } - catch (Exception ex) - { - Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error in Socket Status Change Callback. Error: {0}", ex); - } - //Use a thread for this event so that the server state updates to listening while this event is processed. Listening must be added to the server state - //after every client connection so that the server can check and see if it is at max clients. Due to this the event fires and server listening enum bit flag - //is not set. Putting in a thread allows the state to update before this event processes so that the subscribers to this event get accurate isListening in the event. - CrestronInvoke.BeginInvoke(o => onConnectionChange(clientIndex, server.GetServerSocketStatusForSpecificClient(clientIndex)), null); } + catch (Exception ex) + { + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error in Socket Status Change Callback. Error: {0}", ex); + } + //Use a thread for this event so that the server state updates to listening while this event is processed. Listening must be added to the server state + //after every client connection so that the server can check and see if it is at max clients. Due to this the event fires and server listening enum bit flag + //is not set. Putting in a thread allows the state to update before this event processes so that the subscribers to this event get accurate isListening in the event. + CrestronInvoke.BeginInvoke(o => onConnectionChange(clientIndex, server.GetServerSocketStatusForSpecificClient(clientIndex)), null); + } - #endregion + #endregion - #region Methods Connected Callbacks - /// - /// Secure TCP Client Connected to Secure Server Callback - /// - /// - /// - void SecureConnectCallback(SecureTCPServer server, uint clientIndex) + #region Methods Connected Callbacks + /// + /// Secure TCP Client Connected to Secure Server Callback + /// + /// + /// + void SecureConnectCallback(SecureTCPServer server, uint clientIndex) + { + try { - try + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "ConnectCallback: IPAddress: {0}. Index: {1}. Status: {2}", + server.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex), + clientIndex, server.GetServerSocketStatusForSpecificClient(clientIndex)); + if (clientIndex != 0) { - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "ConnectCallback: IPAddress: {0}. Index: {1}. Status: {2}", - server.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex), - clientIndex, server.GetServerSocketStatusForSpecificClient(clientIndex)); - if (clientIndex != 0) + if (server.ClientConnected(clientIndex)) { - if (server.ClientConnected(clientIndex)) - { - if (!ConnectedClientsIndexes.Contains(clientIndex)) - { - ConnectedClientsIndexes.Add(clientIndex); - } - if (SharedKeyRequired) - { - if (!WaitingForSharedKey.Contains(clientIndex)) - { - WaitingForSharedKey.Add(clientIndex); - } - byte[] b = Encoding.GetEncoding(28591).GetBytes("SharedKey:"); - server.SendDataAsync(clientIndex, b, b.Length, (x, y, z) => { }); - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Sent Shared Key Request to client at {0}", server.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex)); - } - else + if (!ConnectedClientsIndexes.Contains(clientIndex)) + { + ConnectedClientsIndexes.Add(clientIndex); + } + if (SharedKeyRequired) + { + if (!WaitingForSharedKey.Contains(clientIndex)) { - OnServerClientReadyForCommunications(clientIndex); + WaitingForSharedKey.Add(clientIndex); } - if (HeartbeatRequired) + byte[] b = Encoding.GetEncoding(28591).GetBytes("SharedKey:"); + server.SendDataAsync(clientIndex, b, b.Length, (x, y, z) => { }); + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Sent Shared Key Request to client at {0}", server.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex)); + } + else + { + OnServerClientReadyForCommunications(clientIndex); + } + if (HeartbeatRequired) + { + if (!HeartbeatTimerDictionary.ContainsKey(clientIndex)) { - if (!HeartbeatTimerDictionary.ContainsKey(clientIndex)) - { - HeartbeatTimerDictionary.Add(clientIndex, new CTimer(HeartbeatTimer_CallbackFunction, clientIndex, HeartbeatRequiredIntervalMs)); - } + HeartbeatTimerDictionary.Add(clientIndex, new CTimer(HeartbeatTimer_CallbackFunction, clientIndex, HeartbeatRequiredIntervalMs)); } - - server.ReceiveDataAsync(clientIndex, SecureReceivedDataAsyncCallback); } - } - else - { - Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Client attempt faulty."); + + server.ReceiveDataAsync(clientIndex, SecureReceivedDataAsyncCallback); } } - catch (Exception ex) + else { - Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error in Socket Status Connect Callback. Error: {0}", ex); + Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Client attempt faulty."); } + } + catch (Exception ex) + { + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error in Socket Status Connect Callback. Error: {0}", ex); + } // Rearm the listner SocketErrorCodes status = server.WaitForConnectionAsync(IPAddress.Any, SecureConnectCallback); @@ -806,279 +806,278 @@ void SecureConnectCallback(SecureTCPServer server, uint clientIndex) } } - #endregion + #endregion - #region Methods - Send/Receive Callbacks - /// - /// Secure Received Data Async Callback - /// - /// - /// - /// - void SecureReceivedDataAsyncCallback(SecureTCPServer mySecureTCPServer, uint clientIndex, int numberOfBytesReceived) + #region Methods - Send/Receive Callbacks + /// + /// Secure Received Data Async Callback + /// + /// + /// + /// + void SecureReceivedDataAsyncCallback(SecureTCPServer mySecureTCPServer, uint clientIndex, int numberOfBytesReceived) + { + if (numberOfBytesReceived > 0) { - if (numberOfBytesReceived > 0) - { - string received = "Nothing"; - var handler = TextReceivedQueueInvoke; - try + string received = "Nothing"; + var handler = TextReceivedQueueInvoke; + try + { + byte[] bytes = mySecureTCPServer.GetIncomingDataBufferForSpecificClient(clientIndex); + received = System.Text.Encoding.GetEncoding(28591).GetString(bytes, 0, numberOfBytesReceived); + if (WaitingForSharedKey.Contains(clientIndex)) { - byte[] bytes = mySecureTCPServer.GetIncomingDataBufferForSpecificClient(clientIndex); - received = System.Text.Encoding.GetEncoding(28591).GetString(bytes, 0, numberOfBytesReceived); - if (WaitingForSharedKey.Contains(clientIndex)) + received = received.Replace("\r", ""); + received = received.Replace("\n", ""); + if (received != SharedKey) { - received = received.Replace("\r", ""); - received = received.Replace("\n", ""); - if (received != SharedKey) - { - byte[] b = Encoding.GetEncoding(28591).GetBytes("Shared key did not match server. Disconnecting"); - Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Client at index {0} Shared key did not match the server, disconnecting client. Key: {1}", clientIndex, received); - mySecureTCPServer.SendData(clientIndex, b, b.Length); - mySecureTCPServer.Disconnect(clientIndex); - - return; - } - - WaitingForSharedKey.Remove(clientIndex); - byte[] success = Encoding.GetEncoding(28591).GetBytes("Shared Key Match"); - mySecureTCPServer.SendDataAsync(clientIndex, success, success.Length, null); - OnServerClientReadyForCommunications(clientIndex); - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Client with index {0} provided the shared key and successfully connected to the server", clientIndex); + byte[] b = Encoding.GetEncoding(28591).GetBytes("Shared key did not match server. Disconnecting"); + Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Client at index {0} Shared key did not match the server, disconnecting client. Key: {1}", clientIndex, received); + mySecureTCPServer.SendData(clientIndex, b, b.Length); + mySecureTCPServer.Disconnect(clientIndex); + + return; } - else if (!string.IsNullOrEmpty(checkHeartbeat(clientIndex, received))) - { - onTextReceived(received, clientIndex); - if (handler != null) - { - MessageQueue.TryToEnqueue(new GenericTcpServerCommMethodReceiveTextArgs(received, clientIndex)); - } - } - } - catch (Exception ex) - { - Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error Receiving data: {0}. Error: {1}", received, ex); - } - if (mySecureTCPServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) - mySecureTCPServer.ReceiveDataAsync(clientIndex, SecureReceivedDataAsyncCallback); - //Check to see if there is a subscription to the TextReceivedQueueInvoke event. If there is start the dequeue thread. - if (handler != null) - { - var gotLock = DequeueLock.TryEnter(); - if (gotLock) - CrestronInvoke.BeginInvoke((o) => DequeueEvent()); + WaitingForSharedKey.Remove(clientIndex); + byte[] success = Encoding.GetEncoding(28591).GetBytes("Shared Key Match"); + mySecureTCPServer.SendDataAsync(clientIndex, success, success.Length, null); + OnServerClientReadyForCommunications(clientIndex); + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Client with index {0} provided the shared key and successfully connected to the server", clientIndex); } - } - else - { - mySecureTCPServer.Disconnect(clientIndex); - } - } - - /// - /// This method gets spooled up in its own thread an protected by a CCriticalSection to prevent multiple threads from running concurrently. - /// It will dequeue items as they are enqueued automatically. - /// - void DequeueEvent() - { - try - { - while (true) + else if (!string.IsNullOrEmpty(checkHeartbeat(clientIndex, received))) { - // Pull from Queue and fire an event. Block indefinitely until an item can be removed, similar to a Gather. - var message = MessageQueue.Dequeue(); - var handler = TextReceivedQueueInvoke; + onTextReceived(received, clientIndex); if (handler != null) { - handler(this, message); + MessageQueue.TryToEnqueue(new GenericTcpServerCommMethodReceiveTextArgs(received, clientIndex)); } } } - catch (Exception e) + catch (Exception ex) { - this.LogException(e, "DequeueEvent error"); + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error Receiving data: {0}. Error: {1}", received, ex); } - // Make sure to leave the CCritical section in case an exception above stops this thread, or we won't be able to restart it. - if (DequeueLock != null) + if (mySecureTCPServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) + mySecureTCPServer.ReceiveDataAsync(clientIndex, SecureReceivedDataAsyncCallback); + + //Check to see if there is a subscription to the TextReceivedQueueInvoke event. If there is start the dequeue thread. + if (handler != null) { - DequeueLock.Leave(); + var gotLock = DequeueLock.TryEnter(); + if (gotLock) + CrestronInvoke.BeginInvoke((o) => DequeueEvent()); } } + else + { + mySecureTCPServer.Disconnect(clientIndex); + } + } - #endregion - - #region Methods - EventHelpers/Callbacks - - //Private Helper method to call the Connection Change Event - void onConnectionChange(uint clientIndex, SocketStatus clientStatus) + /// + /// This method gets spooled up in its own thread an protected by a CCriticalSection to prevent multiple threads from running concurrently. + /// It will dequeue items as they are enqueued automatically. + /// + void DequeueEvent() + { + try { - if (clientIndex != 0) //0 is error not valid client change + while (true) { - var handler = ClientConnectionChange; + // Pull from Queue and fire an event. Block indefinitely until an item can be removed, similar to a Gather. + var message = MessageQueue.Dequeue(); + var handler = TextReceivedQueueInvoke; if (handler != null) { - handler(this, new GenericTcpServerSocketStatusChangeEventArgs(SecureServer, clientIndex, clientStatus)); + handler(this, message); } } } + catch (Exception e) + { + this.LogException(e, "DequeueEvent error"); + } + // Make sure to leave the CCritical section in case an exception above stops this thread, or we won't be able to restart it. + if (DequeueLock != null) + { + DequeueLock.Leave(); + } + } + + #endregion - //Private Helper method to call the Connection Change Event - void OnConnectionChange() + #region Methods - EventHelpers/Callbacks + + //Private Helper method to call the Connection Change Event + void onConnectionChange(uint clientIndex, SocketStatus clientStatus) + { + if (clientIndex != 0) //0 is error not valid client change { - if (ProgramIsStopping) - { - return; - } var handler = ClientConnectionChange; if (handler != null) { - handler(this, new GenericTcpServerSocketStatusChangeEventArgs()); + handler(this, new GenericTcpServerSocketStatusChangeEventArgs(SecureServer, clientIndex, clientStatus)); } } + } - //Private Helper Method to call the Text Received Event - void onTextReceived(string text, uint clientIndex) + //Private Helper method to call the Connection Change Event + void OnConnectionChange() + { + if (ProgramIsStopping) { - var handler = TextReceived; - if (handler != null) - handler(this, new GenericTcpServerCommMethodReceiveTextArgs(text, clientIndex)); + return; } - - //Private Helper Method to call the Server State Change Event - void OnServerStateChange(ServerState state) + var handler = ClientConnectionChange; + if (handler != null) { - if (ProgramIsStopping) - { - return; - } - var handler = ServerStateChange; - if (handler != null) - { - handler(this, new GenericTcpServerStateChangedEventArgs(state)); - } + handler(this, new GenericTcpServerSocketStatusChangeEventArgs()); } + } + + //Private Helper Method to call the Text Received Event + void onTextReceived(string text, uint clientIndex) + { + var handler = TextReceived; + if (handler != null) + handler(this, new GenericTcpServerCommMethodReceiveTextArgs(text, clientIndex)); + } - /// - /// Private Event Handler method to handle the closing of connections when the program stops - /// - /// - void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + //Private Helper Method to call the Server State Change Event + void OnServerStateChange(ServerState state) + { + if (ProgramIsStopping) { - if (programEventType == eProgramStatusEventType.Stopping) - { - ProgramIsStopping = true; - // kill bandaid things - if (MonitorClientTimer != null) - MonitorClientTimer.Stop(); - if (MonitorClient != null) - MonitorClient.Disconnect(); - - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Program stopping. Closing server"); - KillServer(); - } + return; } - - //Private event handler method to raise the event that the server is ready to send data after a successful client shared key negotiation - void OnServerClientReadyForCommunications(uint clientIndex) + var handler = ServerStateChange; + if (handler != null) { - ClientReadyAfterKeyExchange.Add(clientIndex); - var handler = ServerClientReadyForCommunications; - if (handler != null) - handler(this, new GenericTcpServerSocketStatusChangeEventArgs( - this, clientIndex, SecureServer.GetServerSocketStatusForSpecificClient(clientIndex))); + handler(this, new GenericTcpServerStateChangedEventArgs(state)); } - #endregion + } - #region Monitor Client - /// - /// Starts the monitor client cycle. Timed wait, then call RunMonitorClient - /// - void StartMonitorClient() + /// + /// Private Event Handler method to handle the closing of connections when the program stops + /// + /// + void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + { + if (programEventType == eProgramStatusEventType.Stopping) { + ProgramIsStopping = true; + // kill bandaid things if (MonitorClientTimer != null) - { - return; - } - MonitorClientTimer = new CTimer(o => RunMonitorClient(), 60000); + MonitorClientTimer.Stop(); + if (MonitorClient != null) + MonitorClient.Disconnect(); + + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Program stopping. Closing server"); + KillServer(); } + } + + //Private event handler method to raise the event that the server is ready to send data after a successful client shared key negotiation + void OnServerClientReadyForCommunications(uint clientIndex) + { + ClientReadyAfterKeyExchange.Add(clientIndex); + var handler = ServerClientReadyForCommunications; + if (handler != null) + handler(this, new GenericTcpServerSocketStatusChangeEventArgs( + this, clientIndex, SecureServer.GetServerSocketStatusForSpecificClient(clientIndex))); + } + #endregion - /// - /// - /// - void RunMonitorClient() + #region Monitor Client + /// + /// Starts the monitor client cycle. Timed wait, then call RunMonitorClient + /// + void StartMonitorClient() + { + if (MonitorClientTimer != null) { - MonitorClient = new GenericSecureTcpIpClient_ForServer(Key + "-MONITOR", "127.0.0.1", Port, 2000); - MonitorClient.SharedKeyRequired = this.SharedKeyRequired; - MonitorClient.SharedKey = this.SharedKey; - MonitorClient.ConnectionHasHungCallback = MonitorClientHasHungCallback; - //MonitorClient.ConnectionChange += MonitorClient_ConnectionChange; - MonitorClient.ClientReadyForCommunications += MonitorClient_IsReadyForComm; + return; + } + MonitorClientTimer = new CTimer(o => RunMonitorClient(), 60000); + } - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Starting monitor check"); + /// + /// + /// + void RunMonitorClient() + { + MonitorClient = new GenericSecureTcpIpClient_ForServer(Key + "-MONITOR", "127.0.0.1", Port, 2000); + MonitorClient.SharedKeyRequired = this.SharedKeyRequired; + MonitorClient.SharedKey = this.SharedKey; + MonitorClient.ConnectionHasHungCallback = MonitorClientHasHungCallback; + //MonitorClient.ConnectionChange += MonitorClient_ConnectionChange; + MonitorClient.ClientReadyForCommunications += MonitorClient_IsReadyForComm; - MonitorClient.Connect(); - // From here MonitorCLient either connects or hangs, MonitorClient will call back + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Starting monitor check"); - } + MonitorClient.Connect(); + // From here MonitorCLient either connects or hangs, MonitorClient will call back - /// - /// - /// - void StopMonitorClient() - { - if (MonitorClient == null) - return; + } - MonitorClient.ClientReadyForCommunications -= MonitorClient_IsReadyForComm; - MonitorClient.Disconnect(); - MonitorClient = null; - } + /// + /// + /// + void StopMonitorClient() + { + if (MonitorClient == null) + return; - /// - /// On monitor connect, restart the operation - /// - void MonitorClient_IsReadyForComm(object sender, GenericTcpServerClientReadyForcommunicationsEventArgs args) - { - if (args.IsReady) - { - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Monitor client connection success. Disconnecting in 2s"); - MonitorClientTimer.Stop(); - MonitorClientTimer = null; - MonitorClientFailureCount = 0; - CrestronEnvironment.Sleep(2000); - StopMonitorClient(); - StartMonitorClient(); - } - } + MonitorClient.ClientReadyForCommunications -= MonitorClient_IsReadyForComm; + MonitorClient.Disconnect(); + MonitorClient = null; + } - /// - /// If the client hangs, add to counter and maybe fire the choke event - /// - void MonitorClientHasHungCallback() + /// + /// On monitor connect, restart the operation + /// + void MonitorClient_IsReadyForComm(object sender, GenericTcpServerClientReadyForcommunicationsEventArgs args) + { + if (args.IsReady) { - MonitorClientFailureCount++; + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Monitor client connection success. Disconnecting in 2s"); MonitorClientTimer.Stop(); MonitorClientTimer = null; + MonitorClientFailureCount = 0; + CrestronEnvironment.Sleep(2000); StopMonitorClient(); - if (MonitorClientFailureCount < MonitorClientMaxFailureCount) - { - Debug.Console(2, this, Debug.ErrorLogLevel.Warning, "Monitor client connection has hung {0} time{1}, maximum {2}", - MonitorClientFailureCount, MonitorClientFailureCount > 1 ? "s" : "", MonitorClientMaxFailureCount); - StartMonitorClient(); - } - else - { - Debug.Console(2, this, Debug.ErrorLogLevel.Error, - "\r***************************\rMonitor client connection has hung a maximum of {0} times. \r***************************", - MonitorClientMaxFailureCount); + StartMonitorClient(); + } + } - var handler = ServerHasChoked; - if (handler != null) - handler(); - // Some external thing is in charge here. Expected reset of program - } + /// + /// If the client hangs, add to counter and maybe fire the choke event + /// + void MonitorClientHasHungCallback() + { + MonitorClientFailureCount++; + MonitorClientTimer.Stop(); + MonitorClientTimer = null; + StopMonitorClient(); + if (MonitorClientFailureCount < MonitorClientMaxFailureCount) + { + Debug.Console(2, this, Debug.ErrorLogLevel.Warning, "Monitor client connection has hung {0} time{1}, maximum {2}", + MonitorClientFailureCount, MonitorClientFailureCount > 1 ? "s" : "", MonitorClientMaxFailureCount); + StartMonitorClient(); + } + else + { + Debug.Console(2, this, Debug.ErrorLogLevel.Error, + "\r***************************\rMonitor client connection has hung a maximum of {0} times. \r***************************", + MonitorClientMaxFailureCount); + + var handler = ServerHasChoked; + if (handler != null) + handler(); + // Some external thing is in charge here. Expected reset of program } - #endregion } + #endregion } \ No newline at end of file diff --git a/src/PepperDash.Core/Comm/GenericSshClient.cs b/src/PepperDash.Core/Comm/GenericSshClient.cs index fa5b95bb5..2030c5f97 100644 --- a/src/PepperDash.Core/Comm/GenericSshClient.cs +++ b/src/PepperDash.Core/Comm/GenericSshClient.cs @@ -8,145 +8,145 @@ using Renci.SshNet; using Renci.SshNet.Common; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// +/// +public class GenericSshClient : Device, ISocketStatusWithStreamDebugging, IAutoReconnect { + private const string SPlusKey = "Uninitialized SshClient"; /// - /// + /// Object to enable stream debugging + /// + public CommunicationStreamDebugging StreamDebugging { get; private set; } + + /// + /// Event that fires when data is received. Delivers args with byte array + /// + public event EventHandler BytesReceived; + + /// + /// Event that fires when data is received. Delivered as text. + /// + public event EventHandler TextReceived; + + /// + /// Event when the connection status changes. + /// + public event EventHandler ConnectionChange; + + ///// + ///// + ///// + //public event GenericSocketStatusChangeEventDelegate SocketStatusChange; + + /// + /// Address of server + /// + public string Hostname { get; set; } + + /// + /// Port on server + /// + public int Port { get; set; } + + /// + /// Username for server /// - public class GenericSshClient : Device, ISocketStatusWithStreamDebugging, IAutoReconnect + public string Username { get; set; } + + /// + /// And... Password for server. That was worth documenting! + /// + public string Password { get; set; } + + /// + /// True when the server is connected - when status == 2. + /// + public bool IsConnected { - private const string SPlusKey = "Uninitialized SshClient"; - /// - /// Object to enable stream debugging - /// - public CommunicationStreamDebugging StreamDebugging { get; private set; } - - /// - /// Event that fires when data is received. Delivers args with byte array - /// - public event EventHandler BytesReceived; - - /// - /// Event that fires when data is received. Delivered as text. - /// - public event EventHandler TextReceived; - - /// - /// Event when the connection status changes. - /// - public event EventHandler ConnectionChange; - - ///// - ///// - ///// - //public event GenericSocketStatusChangeEventDelegate SocketStatusChange; - - /// - /// Address of server - /// - public string Hostname { get; set; } - - /// - /// Port on server - /// - public int Port { get; set; } - - /// - /// Username for server - /// - public string Username { get; set; } - - /// - /// And... Password for server. That was worth documenting! - /// - public string Password { get; set; } - - /// - /// True when the server is connected - when status == 2. - /// - public bool IsConnected - { - // returns false if no client or not connected - get { return Client != null && ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } - } + // returns false if no client or not connected + get { return Client != null && ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } + } - /// - /// S+ helper for IsConnected - /// - public ushort UIsConnected - { - get { return (ushort)(IsConnected ? 1 : 0); } - } + /// + /// S+ helper for IsConnected + /// + public ushort UIsConnected + { + get { return (ushort)(IsConnected ? 1 : 0); } + } - /// - /// - /// - public SocketStatus ClientStatus + /// + /// + /// + public SocketStatus ClientStatus + { + get { return _ClientStatus; } + private set { - get { return _ClientStatus; } - private set - { - if (_ClientStatus == value) - return; - _ClientStatus = value; - OnConnectionChange(); - } + if (_ClientStatus == value) + return; + _ClientStatus = value; + OnConnectionChange(); } - SocketStatus _ClientStatus; + } + SocketStatus _ClientStatus; - /// - /// Contains the familiar Simpl analog status values. This drives the ConnectionChange event - /// and IsConnected with be true when this == 2. - /// - public ushort UStatus - { - get { return (ushort)_ClientStatus; } - } + /// + /// Contains the familiar Simpl analog status values. This drives the ConnectionChange event + /// and IsConnected with be true when this == 2. + /// + public ushort UStatus + { + get { return (ushort)_ClientStatus; } + } - /// - /// Determines whether client will attempt reconnection on failure. Default is true - /// - public bool AutoReconnect { get; set; } + /// + /// Determines whether client will attempt reconnection on failure. Default is true + /// + public bool AutoReconnect { get; set; } - /// - /// Will be set and unset by connect and disconnect only - /// - public bool ConnectEnabled { get; private set; } + /// + /// Will be set and unset by connect and disconnect only + /// + public bool ConnectEnabled { get; private set; } - /// - /// S+ helper for AutoReconnect - /// - public ushort UAutoReconnect - { - get { return (ushort)(AutoReconnect ? 1 : 0); } - set { AutoReconnect = value == 1; } - } + /// + /// S+ helper for AutoReconnect + /// + public ushort UAutoReconnect + { + get { return (ushort)(AutoReconnect ? 1 : 0); } + set { AutoReconnect = value == 1; } + } - /// - /// Millisecond value, determines the timeout period in between reconnect attempts. - /// Set to 5000 by default - /// - public int AutoReconnectIntervalMs { get; set; } + /// + /// Millisecond value, determines the timeout period in between reconnect attempts. + /// Set to 5000 by default + /// + public int AutoReconnectIntervalMs { get; set; } - SshClient Client; + SshClient Client; - ShellStream TheStream; + ShellStream TheStream; - CTimer ReconnectTimer; + CTimer ReconnectTimer; - //Lock object to prevent simulatneous connect/disconnect operations - //private CCriticalSection connectLock = new CCriticalSection(); - private SemaphoreSlim connectLock = new SemaphoreSlim(1); + //Lock object to prevent simulatneous connect/disconnect operations + //private CCriticalSection connectLock = new CCriticalSection(); + private SemaphoreSlim connectLock = new SemaphoreSlim(1); - private bool DisconnectLogged = false; + private bool DisconnectLogged = false; - /// - /// Typical constructor. - /// - public GenericSshClient(string key, string hostname, int port, string username, string password) : - base(key) - { - StreamDebugging = new CommunicationStreamDebugging(key); + /// + /// Typical constructor. + /// + public GenericSshClient(string key, string hostname, int port, string username, string password) : + base(key) + { + StreamDebugging = new CommunicationStreamDebugging(key); CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); Key = key; Hostname = hostname; @@ -155,12 +155,12 @@ public GenericSshClient(string key, string hostname, int port, string username, Password = password; AutoReconnectIntervalMs = 5000; - ReconnectTimer = new CTimer(o => + ReconnectTimer = new CTimer(o => { - if (ConnectEnabled) - { - Connect(); - } + if (ConnectEnabled) + { + Connect(); + } }, System.Threading.Timeout.Infinite); } @@ -173,13 +173,13 @@ public GenericSshClient() CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); AutoReconnectIntervalMs = 5000; - ReconnectTimer = new CTimer(o => + ReconnectTimer = new CTimer(o => + { + if (ConnectEnabled) { - if (ConnectEnabled) - { - Connect(); - } - }, System.Threading.Timeout.Infinite); + Connect(); + } + }, System.Threading.Timeout.Infinite); } /// @@ -192,137 +192,137 @@ void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType progr if (Client != null) { this.LogDebug("Program stopping. Closing connection"); - Disconnect(); - } + Disconnect(); } } + } + + /// + /// Connect to the server, using the provided properties. + /// + public void Connect() + { + // Don't go unless everything is here + if (string.IsNullOrEmpty(Hostname) || Port < 1 || Port > 65535 + || Username == null || Password == null) + { + this.LogError("Connect failed. Check hostname, port, username and password are set or not null"); + return; + } + + ConnectEnabled = true; - /// - /// Connect to the server, using the provided properties. - /// - public void Connect() + try { - // Don't go unless everything is here - if (string.IsNullOrEmpty(Hostname) || Port < 1 || Port > 65535 - || Username == null || Password == null) + connectLock.Wait(); + if (IsConnected) { - this.LogError("Connect failed. Check hostname, port, username and password are set or not null"); - return; + this.LogDebug("Connection already connected. Exiting Connect"); } - - ConnectEnabled = true; - - try + else { - connectLock.Wait(); - if (IsConnected) - { - this.LogDebug("Connection already connected. Exiting Connect"); - } - else - { - this.LogDebug("Attempting connect"); + this.LogDebug("Attempting connect"); - // Cancel reconnect if running. + // Cancel reconnect if running. if (ReconnectTimer != null) { ReconnectTimer.Stop(); } - // Cleanup the old client if it already exists - if (Client != null) + // Cleanup the old client if it already exists + if (Client != null) + { + this.LogDebug("Cleaning up disconnected client"); + KillClient(SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY); + } + + // This handles both password and keyboard-interactive (like on OS-X, 'nixes) + KeyboardInteractiveAuthenticationMethod kauth = new KeyboardInteractiveAuthenticationMethod(Username); + kauth.AuthenticationPrompt += new EventHandler(kauth_AuthenticationPrompt); + PasswordAuthenticationMethod pauth = new PasswordAuthenticationMethod(Username, Password); + + this.LogDebug("Creating new SshClient"); + ConnectionInfo connectionInfo = new ConnectionInfo(Hostname, Port, Username, pauth, kauth); + Client = new SshClient(connectionInfo); + Client.ErrorOccurred += Client_ErrorOccurred; + + //Attempt to connect + ClientStatus = SocketStatus.SOCKET_STATUS_WAITING; + try + { + Client.Connect(); + TheStream = Client.CreateShellStream("PDTShell", 0, 0, 0, 0, 65534); + if (TheStream.DataAvailable) { - this.LogDebug("Cleaning up disconnected client"); - KillClient(SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY); + // empty the buffer if there is data + string str = TheStream.Read(); } + TheStream.DataReceived += Stream_DataReceived; + this.LogInformation("Connected"); + ClientStatus = SocketStatus.SOCKET_STATUS_CONNECTED; + DisconnectLogged = false; + } + catch (SshConnectionException e) + { + var ie = e.InnerException; // The details are inside!! + var errorLogLevel = DisconnectLogged == true ? Debug.ErrorLogLevel.None : Debug.ErrorLogLevel.Error; - // This handles both password and keyboard-interactive (like on OS-X, 'nixes) - KeyboardInteractiveAuthenticationMethod kauth = new KeyboardInteractiveAuthenticationMethod(Username); - kauth.AuthenticationPrompt += new EventHandler(kauth_AuthenticationPrompt); - PasswordAuthenticationMethod pauth = new PasswordAuthenticationMethod(Username, Password); - - this.LogDebug("Creating new SshClient"); - ConnectionInfo connectionInfo = new ConnectionInfo(Hostname, Port, Username, pauth, kauth); - Client = new SshClient(connectionInfo); - Client.ErrorOccurred += Client_ErrorOccurred; + if (ie is SocketException) + { + this.LogException(ie, "CONNECTION failure: Cannot reach host"); + } - //Attempt to connect - ClientStatus = SocketStatus.SOCKET_STATUS_WAITING; - try + if (ie is System.Net.Sockets.SocketException socketException) { - Client.Connect(); - TheStream = Client.CreateShellStream("PDTShell", 0, 0, 0, 0, 65534); - if (TheStream.DataAvailable) - { - // empty the buffer if there is data - string str = TheStream.Read(); - } - TheStream.DataReceived += Stream_DataReceived; - this.LogInformation("Connected"); - ClientStatus = SocketStatus.SOCKET_STATUS_CONNECTED; - DisconnectLogged = false; + this.LogException(ie, "Connection failure: Cannot reach {host} on {port}", + Hostname, Port); } - catch (SshConnectionException e) + if (ie is SshAuthenticationException) { - var ie = e.InnerException; // The details are inside!! - var errorLogLevel = DisconnectLogged == true ? Debug.ErrorLogLevel.None : Debug.ErrorLogLevel.Error; - - if (ie is SocketException) - { - this.LogException(ie, "CONNECTION failure: Cannot reach host"); - } - - if (ie is System.Net.Sockets.SocketException socketException) - { - this.LogException(ie, "Connection failure: Cannot reach {host} on {port}", - Hostname, Port); - } - if (ie is SshAuthenticationException) - { - this.LogException(ie, "Authentication failure for username {userName}", Username); - } - else - this.LogException(ie, "Error on connect"); - - DisconnectLogged = true; - KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED); - if (AutoReconnect) - { - this.LogDebug("Checking autoreconnect: {autoReconnect}, {autoReconnectInterval}ms", AutoReconnect, AutoReconnectIntervalMs); - ReconnectTimer.Reset(AutoReconnectIntervalMs); - } + this.LogException(ie, "Authentication failure for username {userName}", Username); } - catch(SshOperationTimeoutException ex) + else + this.LogException(ie, "Error on connect"); + + DisconnectLogged = true; + KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED); + if (AutoReconnect) { - this.LogWarning("Connection attempt timed out: {message}", ex.Message); - - DisconnectLogged = true; - KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED); - if (AutoReconnect) - { - this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs); - ReconnectTimer.Reset(AutoReconnectIntervalMs); - } + this.LogDebug("Checking autoreconnect: {autoReconnect}, {autoReconnectInterval}ms", AutoReconnect, AutoReconnectIntervalMs); + ReconnectTimer.Reset(AutoReconnectIntervalMs); } - catch (Exception e) + } + catch(SshOperationTimeoutException ex) + { + this.LogWarning("Connection attempt timed out: {message}", ex.Message); + + DisconnectLogged = true; + KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED); + if (AutoReconnect) { - var errorLogLevel = DisconnectLogged == true ? Debug.ErrorLogLevel.None : Debug.ErrorLogLevel.Error; - this.LogException(e, "Unhandled exception on connect"); - DisconnectLogged = true; - KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED); - if (AutoReconnect) - { - this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs); - ReconnectTimer.Reset(AutoReconnectIntervalMs); - } + this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs); + ReconnectTimer.Reset(AutoReconnectIntervalMs); + } + } + catch (Exception e) + { + var errorLogLevel = DisconnectLogged == true ? Debug.ErrorLogLevel.None : Debug.ErrorLogLevel.Error; + this.LogException(e, "Unhandled exception on connect"); + DisconnectLogged = true; + KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED); + if (AutoReconnect) + { + this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs); + ReconnectTimer.Reset(AutoReconnectIntervalMs); } } - } - finally - { - connectLock.Release(); } } + finally + { + connectLock.Release(); + } + } /// /// Disconnect the clients and put away it's resources. @@ -337,54 +337,54 @@ public void Disconnect() // ReconnectTimer = null; } - KillClient(SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY); - } + KillClient(SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY); + } - /// - /// Kills the stream, cleans up the client and sets it to null - /// - private void KillClient(SocketStatus status) - { - KillStream(); + /// + /// Kills the stream, cleans up the client and sets it to null + /// + private void KillClient(SocketStatus status) + { + KillStream(); - try - { - if (Client != null) - { - Client.ErrorOccurred -= Client_ErrorOccurred; - Client.Disconnect(); - Client.Dispose(); - Client = null; - ClientStatus = status; - this.LogDebug("Disconnected"); - } - } - catch (Exception ex) + try + { + if (Client != null) { - this.LogException(ex,"Exception in Kill Client"); + Client.ErrorOccurred -= Client_ErrorOccurred; + Client.Disconnect(); + Client.Dispose(); + Client = null; + ClientStatus = status; + this.LogDebug("Disconnected"); } } + catch (Exception ex) + { + this.LogException(ex,"Exception in Kill Client"); + } + } - /// - /// Kills the stream - /// + /// + /// Kills the stream + /// void KillStream() { - try - { - if (TheStream != null) - { - TheStream.DataReceived -= Stream_DataReceived; - TheStream.Close(); - TheStream.Dispose(); - TheStream = null; - this.LogDebug("Disconnected stream"); - } - } - catch (Exception ex) + try + { + if (TheStream != null) { - this.LogException(ex, "Exception in Kill Stream:{0}"); + TheStream.DataReceived -= Stream_DataReceived; + TheStream.Close(); + TheStream.Dispose(); + TheStream = null; + this.LogDebug("Disconnected stream"); } + } + catch (Exception ex) + { + this.LogException(ex, "Exception in Kill Stream:{0}"); + } } /// @@ -402,32 +402,32 @@ void kauth_AuthenticationPrompt(object sender, AuthenticationPromptEventArgs e) /// void Stream_DataReceived(object sender, ShellDataEventArgs e) { - if (((ShellStream)sender).Length <= 0L) - { - return; - } - var response = ((ShellStream)sender).Read(); - + if (((ShellStream)sender).Length <= 0L) + { + return; + } + var response = ((ShellStream)sender).Read(); + var bytesHandler = BytesReceived; - + if (bytesHandler != null) { - var bytes = Encoding.UTF8.GetBytes(response); + var bytes = Encoding.UTF8.GetBytes(response); if (StreamDebugging.RxStreamDebuggingIsEnabled) { this.LogInformation("Received {1} bytes: '{0}'", ComTextHelper.GetEscapedText(bytes), bytes.Length); } - bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); + bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); } var textHandler = TextReceived; if (textHandler != null) { - if (StreamDebugging.RxStreamDebuggingIsEnabled) - this.LogInformation("Received: '{0}'", ComTextHelper.GetDebugText(response)); + if (StreamDebugging.RxStreamDebuggingIsEnabled) + this.LogInformation("Received: '{0}'", ComTextHelper.GetDebugText(response)); - textHandler(this, new GenericCommMethodReceiveTextArgs(response)); - } + textHandler(this, new GenericCommMethodReceiveTextArgs(response)); + } } @@ -438,39 +438,39 @@ void Stream_DataReceived(object sender, ShellDataEventArgs e) /// void Client_ErrorOccurred(object sender, ExceptionEventArgs e) { - CrestronInvoke.BeginInvoke(o => + CrestronInvoke.BeginInvoke(o => + { + if (e.Exception is SshConnectionException || e.Exception is System.Net.Sockets.SocketException) + this.LogError("Disconnected by remote"); + else + this.LogException(e.Exception, "Unhandled SSH client error"); + try { - if (e.Exception is SshConnectionException || e.Exception is System.Net.Sockets.SocketException) - this.LogError("Disconnected by remote"); - else - this.LogException(e.Exception, "Unhandled SSH client error"); - try - { - connectLock.Wait(); - KillClient(SocketStatus.SOCKET_STATUS_BROKEN_REMOTELY); - } - finally - { - connectLock.Release(); - } - if (AutoReconnect && ConnectEnabled) - { - this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs); - ReconnectTimer.Reset(AutoReconnectIntervalMs); - } - }); - } + connectLock.Wait(); + KillClient(SocketStatus.SOCKET_STATUS_BROKEN_REMOTELY); + } + finally + { + connectLock.Release(); + } + if (AutoReconnect && ConnectEnabled) + { + this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs); + ReconnectTimer.Reset(AutoReconnectIntervalMs); + } + }); + } - /// - /// Helper for ConnectionChange event - /// - void OnConnectionChange() - { - if (ConnectionChange != null) - ConnectionChange(this, new GenericSocketStatusChageEventArgs(this)); - } + /// + /// Helper for ConnectionChange event + /// + void OnConnectionChange() + { + if (ConnectionChange != null) + ConnectionChange(this, new GenericSocketStatusChageEventArgs(this)); + } - #region IBasicCommunication Members + #region IBasicCommunication Members /// /// Sends text to the server @@ -497,52 +497,52 @@ public void SendText(string text) } } catch (ObjectDisposedException) - { - this.LogError("ObjectDisposedException sending '{message}'. Restarting connection...", text.Trim()); + { + this.LogError("ObjectDisposedException sending '{message}'. Restarting connection...", text.Trim()); - KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED); - ReconnectTimer.Reset(); + KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED); + ReconnectTimer.Reset(); } catch (Exception ex) { - this.LogException(ex, "Exception sending text: '{message}'", text); + this.LogException(ex, "Exception sending text: '{message}'", text); } } - /// - /// Sends Bytes to the server - /// - /// + /// + /// Sends Bytes to the server + /// + /// public void SendBytes(byte[] bytes) { - try + try + { + if (Client != null && TheStream != null && IsConnected) { - if (Client != null && TheStream != null && IsConnected) - { - if (StreamDebugging.TxStreamDebuggingIsEnabled) - this.LogInformation("Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); + if (StreamDebugging.TxStreamDebuggingIsEnabled) + this.LogInformation("Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); - TheStream.Write(bytes, 0, bytes.Length); - TheStream.Flush(); - } - else - { - this.LogDebug("Client is null or disconnected. Cannot Send Bytes"); - } + TheStream.Write(bytes, 0, bytes.Length); + TheStream.Flush(); } - catch (ObjectDisposedException ex) + else { - this.LogException(ex, "ObjectDisposedException sending {message}", ComTextHelper.GetEscapedText(bytes)); - - KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED); - ReconnectTimer.Reset(); + this.LogDebug("Client is null or disconnected. Cannot Send Bytes"); } - catch (Exception ex) - { - this.LogException(ex, "Exception sending {message}", ComTextHelper.GetEscapedText(bytes)); - } + } + catch (ObjectDisposedException ex) + { + this.LogException(ex, "ObjectDisposedException sending {message}", ComTextHelper.GetEscapedText(bytes)); + + KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED); + ReconnectTimer.Reset(); + } + catch (Exception ex) + { + this.LogException(ex, "Exception sending {message}", ComTextHelper.GetEscapedText(bytes)); + } } - #endregion +#endregion } @@ -553,40 +553,39 @@ public void SendBytes(byte[] bytes) /// public class SshConnectionChangeEventArgs : EventArgs { - /// - /// Connection State - /// + /// + /// Connection State + /// public bool IsConnected { get; private set; } - /// - /// Connection Status represented as a ushort - /// + /// + /// Connection Status represented as a ushort + /// public ushort UIsConnected { get { return (ushort)(Client.IsConnected ? 1 : 0); } } - /// - /// The client - /// + /// + /// The client + /// public GenericSshClient Client { get; private set; } - /// - /// Socket Status as represented by - /// + /// + /// Socket Status as represented by + /// public ushort Status { get { return Client.UStatus; } } - /// - /// S+ Constructor - /// - public SshConnectionChangeEventArgs() { } + /// + /// S+ Constructor + /// + public SshConnectionChangeEventArgs() { } - /// - /// EventArgs class - /// - /// Connection State - /// The Client + /// + /// EventArgs class + /// + /// Connection State + /// The Client public SshConnectionChangeEventArgs(bool isConnected, GenericSshClient client) - { - IsConnected = isConnected; - Client = client; - } + { + IsConnected = isConnected; + Client = client; } } \ No newline at end of file diff --git a/src/PepperDash.Core/Comm/GenericTcpIpClient.cs b/src/PepperDash.Core/Comm/GenericTcpIpClient.cs index 9529aa29a..ee0df8de0 100644 --- a/src/PepperDash.Core/Comm/GenericTcpIpClient.cs +++ b/src/PepperDash.Core/Comm/GenericTcpIpClient.cs @@ -6,18 +6,18 @@ using Crestron.SimplSharp.CrestronSockets; using Newtonsoft.Json; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// A class to handle basic TCP/IP communications with a server +/// + public class GenericTcpIpClient : Device, ISocketStatusWithStreamDebugging, IAutoReconnect { + private const string SplusKey = "Uninitialized TcpIpClient"; /// - /// A class to handle basic TCP/IP communications with a server + /// Object to enable stream debugging /// - public class GenericTcpIpClient : Device, ISocketStatusWithStreamDebugging, IAutoReconnect - { - private const string SplusKey = "Uninitialized TcpIpClient"; - /// - /// Object to enable stream debugging - /// - public CommunicationStreamDebugging StreamDebugging { get; private set; } + public CommunicationStreamDebugging StreamDebugging { get; private set; } /// /// Fires when data is received from the server and returns it as a Byte array @@ -38,11 +38,11 @@ public class GenericTcpIpClient : Device, ISocketStatusWithStreamDebugging, IAut private string _hostname; - /// - /// Address of server - /// - public string Hostname - { + /// + /// Address of server + /// + public string Hostname + { get { return _hostname; @@ -58,25 +58,25 @@ public string Hostname } } - /// - /// Port on server - /// - public int Port { get; set; } + /// + /// Port on server + /// + public int Port { get; set; } - /// - /// Another damn S+ helper because S+ seems to treat large port nums as signed ints - /// which screws up things - /// - public ushort UPort - { - get { return Convert.ToUInt16(Port); } - set { Port = Convert.ToInt32(value); } - } + /// + /// Another damn S+ helper because S+ seems to treat large port nums as signed ints + /// which screws up things + /// + public ushort UPort + { + get { return Convert.ToUInt16(Port); } + set { Port = Convert.ToInt32(value); } + } - /// - /// Defaults to 2000 - /// - public int BufferSize { get; set; } + /// + /// Defaults to 2000 + /// + public int BufferSize { get; set; } /// /// The actual client class @@ -87,47 +87,47 @@ public ushort UPort /// Bool showing if socket is connected /// public bool IsConnected - { - get { return _client != null && _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } - } - - /// - /// S+ helper for IsConnected - /// - public ushort UIsConnected - { - get { return (ushort)(IsConnected ? 1 : 0); } - } + { + get { return _client != null && _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } + } + + /// + /// S+ helper for IsConnected + /// + public ushort UIsConnected + { + get { return (ushort)(IsConnected ? 1 : 0); } + } /// /// _client socket status Read only /// public SocketStatus ClientStatus - { - get - { - return _client == null ? SocketStatus.SOCKET_STATUS_NO_CONNECT : _client.ClientStatus; - } - } - - /// - /// Contains the familiar Simpl analog status values. This drives the ConnectionChange event - /// and IsConnected would be true when this == 2. - /// - public ushort UStatus + { + get { - get { return (ushort)ClientStatus; } - } + return _client == null ? SocketStatus.SOCKET_STATUS_NO_CONNECT : _client.ClientStatus; + } + } + + /// + /// Contains the familiar Simpl analog status values. This drives the ConnectionChange event + /// and IsConnected would be true when this == 2. + /// + public ushort UStatus + { + get { return (ushort)ClientStatus; } + } /// - /// Status text shows the message associated with socket status + /// Status text shows the message associated with socket status /// public string ClientStatusText { get { return ClientStatus.ToString(); } } /// /// Ushort representation of client status /// - [Obsolete] + [Obsolete] public ushort UClientStatus { get { return (ushort)ClientStatus; } } /// @@ -140,14 +140,14 @@ public ushort UStatus /// public bool AutoReconnect { get; set; } - /// - /// S+ helper for AutoReconnect - /// - public ushort UAutoReconnect - { - get { return (ushort)(AutoReconnect ? 1 : 0); } - set { AutoReconnect = value == 1; } - } + /// + /// S+ helper for AutoReconnect + /// + public ushort UAutoReconnect + { + get { return (ushort)(AutoReconnect ? 1 : 0); } + set { AutoReconnect = value == 1; } + } /// /// Milliseconds to wait before attempting to reconnect. Defaults to 5000 @@ -167,283 +167,283 @@ public bool Connected get { return _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } } - //Lock object to prevent simulatneous connect/disconnect operations - private CCriticalSection connectLock = new CCriticalSection(); + //Lock object to prevent simulatneous connect/disconnect operations + private CCriticalSection connectLock = new CCriticalSection(); - // private Timer for auto reconnect + // private Timer for auto reconnect private CTimer RetryTimer; - /// - /// Constructor - /// - /// unique string to differentiate between instances - /// - /// - /// + /// + /// Constructor + /// + /// unique string to differentiate between instances + /// + /// + /// public GenericTcpIpClient(string key, string address, int port, int bufferSize) : base(key) { - StreamDebugging = new CommunicationStreamDebugging(key); - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - AutoReconnectIntervalMs = 5000; - Hostname = address; - Port = port; - BufferSize = bufferSize; - - RetryTimer = new CTimer(o => - { - Reconnect(); - }, Timeout.Infinite); - } - - /// - /// Constructor - /// - /// - public GenericTcpIpClient(string key) - : base(key) + StreamDebugging = new CommunicationStreamDebugging(key); + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + AutoReconnectIntervalMs = 5000; + Hostname = address; + Port = port; + BufferSize = bufferSize; + + RetryTimer = new CTimer(o => { - StreamDebugging = new CommunicationStreamDebugging(key); - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - AutoReconnectIntervalMs = 5000; - BufferSize = 2000; + Reconnect(); + }, Timeout.Infinite); + } - RetryTimer = new CTimer(o => - { - Reconnect(); - }, Timeout.Infinite); - } + /// + /// Constructor + /// + /// + public GenericTcpIpClient(string key) + : base(key) + { + StreamDebugging = new CommunicationStreamDebugging(key); + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + AutoReconnectIntervalMs = 5000; + BufferSize = 2000; - /// - /// Default constructor for S+ - /// - public GenericTcpIpClient() - : base(SplusKey) + RetryTimer = new CTimer(o => { - StreamDebugging = new CommunicationStreamDebugging(SplusKey); + Reconnect(); + }, Timeout.Infinite); + } + + /// + /// Default constructor for S+ + /// + public GenericTcpIpClient() + : base(SplusKey) + { + StreamDebugging = new CommunicationStreamDebugging(SplusKey); CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); AutoReconnectIntervalMs = 5000; - BufferSize = 2000; + BufferSize = 2000; - RetryTimer = new CTimer(o => - { - Reconnect(); - }, Timeout.Infinite); + RetryTimer = new CTimer(o => + { + Reconnect(); + }, Timeout.Infinite); } - /// - /// Just to help S+ set the key - /// - public void Initialize(string key) - { - Key = key; - } + /// + /// Just to help S+ set the key + /// + public void Initialize(string key) + { + Key = key; + } - /// - /// Handles closing this up when the program shuts down - /// - void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + /// + /// Handles closing this up when the program shuts down + /// + void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + { + if (programEventType == eProgramStatusEventType.Stopping) { - if (programEventType == eProgramStatusEventType.Stopping) - { - Debug.Console(1, this, "Program stopping. Closing connection"); - Deactivate(); - } + Debug.Console(1, this, "Program stopping. Closing connection"); + Deactivate(); } + } - /// - /// - /// - /// + /// + /// + /// + /// public override bool Deactivate() { - RetryTimer.Stop(); - RetryTimer.Dispose(); - if (_client != null) - { - _client.SocketStatusChange -= this.Client_SocketStatusChange; - DisconnectClient(); - } + RetryTimer.Stop(); + RetryTimer.Dispose(); + if (_client != null) + { + _client.SocketStatusChange -= this.Client_SocketStatusChange; + DisconnectClient(); + } return true; } - /// - /// Attempts to connect to the server - /// + /// + /// Attempts to connect to the server + /// public void Connect() { - if (string.IsNullOrEmpty(Hostname)) + if (string.IsNullOrEmpty(Hostname)) + { + Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericTcpIpClient '{0}': No address set", Key); + return; + } + if (Port < 1 || Port > 65535) + { { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericTcpIpClient '{0}': No address set", Key); + Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericTcpIpClient '{0}': Invalid port", Key); return; } - if (Port < 1 || Port > 65535) - { - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericTcpIpClient '{0}': Invalid port", Key); - return; - } - } + } - try + try + { + connectLock.Enter(); + if (IsConnected) { - connectLock.Enter(); - if (IsConnected) - { - Debug.Console(1, this, "Connection already connected. Exiting Connect()"); - } - else - { - //Stop retry timer if running - RetryTimer.Stop(); - _client = new TCPClient(Hostname, Port, BufferSize); - _client.SocketStatusChange -= Client_SocketStatusChange; - _client.SocketStatusChange += Client_SocketStatusChange; - DisconnectCalledByUser = false; - _client.ConnectToServerAsync(ConnectToServerCallback); - } + Debug.Console(1, this, "Connection already connected. Exiting Connect()"); } - finally + else { - connectLock.Leave(); + //Stop retry timer if running + RetryTimer.Stop(); + _client = new TCPClient(Hostname, Port, BufferSize); + _client.SocketStatusChange -= Client_SocketStatusChange; + _client.SocketStatusChange += Client_SocketStatusChange; + DisconnectCalledByUser = false; + _client.ConnectToServerAsync(ConnectToServerCallback); } + } + finally + { + connectLock.Leave(); + } } - private void Reconnect() + private void Reconnect() + { + if (_client == null) { - if (_client == null) - { - return; - } - try + return; + } + try + { + connectLock.Enter(); + if (IsConnected || DisconnectCalledByUser == true) { - connectLock.Enter(); - if (IsConnected || DisconnectCalledByUser == true) - { - Debug.Console(1, this, "Reconnect no longer needed. Exiting Reconnect()"); - } - else - { - Debug.Console(1, this, "Attempting reconnect now"); - _client.ConnectToServerAsync(ConnectToServerCallback); - } + Debug.Console(1, this, "Reconnect no longer needed. Exiting Reconnect()"); } - finally + else { - connectLock.Leave(); + Debug.Console(1, this, "Attempting reconnect now"); + _client.ConnectToServerAsync(ConnectToServerCallback); } } + finally + { + connectLock.Leave(); + } + } - /// - /// Attempts to disconnect the client - /// + /// + /// Attempts to disconnect the client + /// public void Disconnect() { - try - { - connectLock.Enter(); - DisconnectCalledByUser = true; + try + { + connectLock.Enter(); + DisconnectCalledByUser = true; - // Stop trying reconnects, if we are - RetryTimer.Stop(); - DisconnectClient(); - } - finally - { - connectLock.Leave(); - } + // Stop trying reconnects, if we are + RetryTimer.Stop(); + DisconnectClient(); + } + finally + { + connectLock.Leave(); + } } - /// - /// Does the actual disconnect business - /// - public void DisconnectClient() + /// + /// Does the actual disconnect business + /// + public void DisconnectClient() + { + if (_client != null) { - if (_client != null) - { - Debug.Console(1, this, "Disconnecting client"); - if (IsConnected) - _client.DisconnectFromServer(); - } + Debug.Console(1, this, "Disconnecting client"); + if (IsConnected) + _client.DisconnectFromServer(); } + } - /// - /// Callback method for connection attempt - /// - /// + /// + /// Callback method for connection attempt + /// + /// void ConnectToServerCallback(TCPClient c) { - if (c.ClientStatus != SocketStatus.SOCKET_STATUS_CONNECTED) - { - Debug.Console(0, this, "Server connection result: {0}", c.ClientStatus); - WaitAndTryReconnect(); - } - else - { - Debug.Console(1, this, "Server connection result: {0}", c.ClientStatus); - } + if (c.ClientStatus != SocketStatus.SOCKET_STATUS_CONNECTED) + { + Debug.Console(0, this, "Server connection result: {0}", c.ClientStatus); + WaitAndTryReconnect(); + } + else + { + Debug.Console(1, this, "Server connection result: {0}", c.ClientStatus); + } } - /// - /// Disconnects, waits and attemtps to connect again - /// + /// + /// Disconnects, waits and attemtps to connect again + /// void WaitAndTryReconnect() { - CrestronInvoke.BeginInvoke(o => + CrestronInvoke.BeginInvoke(o => + { + try { - try - { - connectLock.Enter(); - if (!IsConnected && AutoReconnect && !DisconnectCalledByUser && _client != null) - { - DisconnectClient(); - Debug.Console(1, this, "Attempting reconnect, status={0}", _client.ClientStatus); - RetryTimer.Reset(AutoReconnectIntervalMs); - } - } - finally + connectLock.Enter(); + if (!IsConnected && AutoReconnect && !DisconnectCalledByUser && _client != null) { - connectLock.Leave(); + DisconnectClient(); + Debug.Console(1, this, "Attempting reconnect, status={0}", _client.ClientStatus); + RetryTimer.Reset(AutoReconnectIntervalMs); } - }); + } + finally + { + connectLock.Leave(); + } + }); } - /// - /// Recieves incoming data - /// - /// - /// + /// + /// Recieves incoming data + /// + /// + /// void Receive(TCPClient client, int numBytes) { - if (client != null) + if (client != null) + { + if (numBytes > 0) { - if (numBytes > 0) + var bytes = client.IncomingDataBuffer.Take(numBytes).ToArray(); + var bytesHandler = BytesReceived; + if (bytesHandler != null) { - var bytes = client.IncomingDataBuffer.Take(numBytes).ToArray(); - var bytesHandler = BytesReceived; - if (bytesHandler != null) + if (StreamDebugging.RxStreamDebuggingIsEnabled) { - if (StreamDebugging.RxStreamDebuggingIsEnabled) - { - Debug.Console(0, this, "Received {1} bytes: '{0}'", ComTextHelper.GetEscapedText(bytes), bytes.Length); - } - bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); + Debug.Console(0, this, "Received {1} bytes: '{0}'", ComTextHelper.GetEscapedText(bytes), bytes.Length); } - var textHandler = TextReceived; - if (textHandler != null) - { - var str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); + bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); + } + var textHandler = TextReceived; + if (textHandler != null) + { + var str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); - if (StreamDebugging.RxStreamDebuggingIsEnabled) - { - Debug.Console(0, this, "Received {1} characters of text: '{0}'", ComTextHelper.GetDebugText(str), str.Length); - } + if (StreamDebugging.RxStreamDebuggingIsEnabled) + { + Debug.Console(0, this, "Received {1} characters of text: '{0}'", ComTextHelper.GetDebugText(str), str.Length); + } - textHandler(this, new GenericCommMethodReceiveTextArgs(str)); - } - } - client.ReceiveDataAsync(Receive); + textHandler(this, new GenericCommMethodReceiveTextArgs(str)); + } } + client.ReceiveDataAsync(Receive); + } } /// @@ -453,9 +453,9 @@ public void SendText(string text) { var bytes = Encoding.GetEncoding(28591).GetBytes(text); // Check debug level before processing byte array - if (StreamDebugging.TxStreamDebuggingIsEnabled) - Debug.Console(0, this, "Sending {0} characters of text: '{1}'", text.Length, ComTextHelper.GetDebugText(text)); - if (_client != null) + if (StreamDebugging.TxStreamDebuggingIsEnabled) + Debug.Console(0, this, "Sending {0} characters of text: '{1}'", text.Length, ComTextHelper.GetDebugText(text)); + if (_client != null) _client.SendData(bytes, bytes.Length); } @@ -472,35 +472,35 @@ public void SendEscapedText(string text) SendText(unescapedText); } - /// - /// Sends Bytes to the server - /// - /// + /// + /// Sends Bytes to the server + /// + /// public void SendBytes(byte[] bytes) { - if (StreamDebugging.TxStreamDebuggingIsEnabled) - Debug.Console(0, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); - if (_client != null) + if (StreamDebugging.TxStreamDebuggingIsEnabled) + Debug.Console(0, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); + if (_client != null) _client.SendData(bytes, bytes.Length); } - /// - /// Socket Status Change Handler - /// - /// - /// + /// + /// Socket Status Change Handler + /// + /// + /// void Client_SocketStatusChange(TCPClient client, SocketStatus clientSocketStatus) { - if (clientSocketStatus != SocketStatus.SOCKET_STATUS_CONNECTED) - { - Debug.Console(0, this, "Socket status change {0} ({1})", clientSocketStatus, ClientStatusText); - WaitAndTryReconnect(); - } - else - { - Debug.Console(1, this, "Socket status change {0} ({1})", clientSocketStatus, ClientStatusText); + if (clientSocketStatus != SocketStatus.SOCKET_STATUS_CONNECTED) + { + Debug.Console(0, this, "Socket status change {0} ({1})", clientSocketStatus, ClientStatusText); + WaitAndTryReconnect(); + } + else + { + Debug.Console(1, this, "Socket status change {0} ({1})", clientSocketStatus, ClientStatusText); _client.ReceiveDataAsync(Receive); - } + } var handler = ConnectionChange; if (handler != null) @@ -508,30 +508,30 @@ void Client_SocketStatusChange(TCPClient client, SocketStatus clientSocketStatus } } - /// - /// Configuration properties for TCP/SSH Connections - /// +/// +/// Configuration properties for TCP/SSH Connections +/// public class TcpSshPropertiesConfig { - /// - /// Address to connect to - /// + /// + /// Address to connect to + /// [JsonProperty(Required = Required.Always)] public string Address { get; set; } - /// - /// Port to connect to - /// + /// + /// Port to connect to + /// [JsonProperty(Required = Required.Always)] public int Port { get; set; } - /// - /// Username credential - /// + /// + /// Username credential + /// public string Username { get; set; } - /// - /// Passord credential - /// + /// + /// Passord credential + /// public string Password { get; set; } /// @@ -549,18 +549,16 @@ public class TcpSshPropertiesConfig /// public int AutoReconnectIntervalMs { get; set; } - /// - /// Default constructor - /// + /// + /// Default constructor + /// public TcpSshPropertiesConfig() { BufferSize = 32768; AutoReconnect = true; AutoReconnectIntervalMs = 5000; - Username = ""; - Password = ""; + Username = ""; + Password = ""; } } - -} diff --git a/src/PepperDash.Core/Comm/GenericTcpIpClient_ForServer.cs b/src/PepperDash.Core/Comm/GenericTcpIpClient_ForServer.cs index 03a278279..a1a0887f3 100644 --- a/src/PepperDash.Core/Comm/GenericTcpIpClient_ForServer.cs +++ b/src/PepperDash.Core/Comm/GenericTcpIpClient_ForServer.cs @@ -19,757 +19,755 @@ PepperDash Technology Corporation reserves all rights under applicable laws. using Crestron.SimplSharp.CrestronSockets; using PepperDash.Core.Logging; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// Generic TCP/IP client for server +/// +public class GenericTcpIpClient_ForServer : Device, IAutoReconnect { /// - /// Generic TCP/IP client for server + /// Band aid delegate for choked server /// - public class GenericTcpIpClient_ForServer : Device, IAutoReconnect - { - /// - /// Band aid delegate for choked server - /// - internal delegate void ConnectionHasHungCallbackDelegate(); + internal delegate void ConnectionHasHungCallbackDelegate(); - #region Events + #region Events - //public event EventHandler BytesReceived; + //public event EventHandler BytesReceived; - /// - /// Notifies of text received - /// - public event EventHandler TextReceived; + /// + /// Notifies of text received + /// + public event EventHandler TextReceived; - /// - /// Notifies of socket status change - /// - public event EventHandler ConnectionChange; + /// + /// Notifies of socket status change + /// + public event EventHandler ConnectionChange; - /// - /// This is something of a band-aid callback. If the client times out during the connection process, because the server - /// is stuck, this will fire. It is intended to be used by the Server class monitor client, to help - /// keep a watch on the server and reset it if necessary. - /// - internal ConnectionHasHungCallbackDelegate ConnectionHasHungCallback; + /// + /// This is something of a band-aid callback. If the client times out during the connection process, because the server + /// is stuck, this will fire. It is intended to be used by the Server class monitor client, to help + /// keep a watch on the server and reset it if necessary. + /// + internal ConnectionHasHungCallbackDelegate ConnectionHasHungCallback; - /// - /// For a client with a pre shared key, this will fire after the communication is established and the key exchange is complete. If you require - /// a key and subscribe to the socket change event and try to send data on a connection the data sent will interfere with the key exchange and disconnect. - /// - public event EventHandler ClientReadyForCommunications; + /// + /// For a client with a pre shared key, this will fire after the communication is established and the key exchange is complete. If you require + /// a key and subscribe to the socket change event and try to send data on a connection the data sent will interfere with the key exchange and disconnect. + /// + public event EventHandler ClientReadyForCommunications; - #endregion + #endregion - #region Properties & Variables + #region Properties & Variables - /// - /// Address of server - /// - public string Hostname { get; set; } + /// + /// Address of server + /// + public string Hostname { get; set; } - /// - /// Port on server - /// - public int Port { get; set; } + /// + /// Port on server + /// + public int Port { get; set; } - /// - /// S+ helper - /// - public ushort UPort - { - get { return Convert.ToUInt16(Port); } - set { Port = Convert.ToInt32(value); } - } + /// + /// S+ helper + /// + public ushort UPort + { + get { return Convert.ToUInt16(Port); } + set { Port = Convert.ToInt32(value); } + } - /// - /// Bool to show whether the server requires a preshared key. This is used in the DynamicTCPServer class - /// - public bool SharedKeyRequired { get; set; } + /// + /// Bool to show whether the server requires a preshared key. This is used in the DynamicTCPServer class + /// + public bool SharedKeyRequired { get; set; } - /// - /// S+ helper for requires shared key bool - /// - public ushort USharedKeyRequired + /// + /// S+ helper for requires shared key bool + /// + public ushort USharedKeyRequired + { + set { - set - { - if (value == 1) - SharedKeyRequired = true; - else - SharedKeyRequired = false; - } + if (value == 1) + SharedKeyRequired = true; + else + SharedKeyRequired = false; } + } - /// - /// SharedKey is sent for varification to the server. Shared key can be any text (255 char limit in SIMPL+ Module), but must match the Shared Key on the Server module - /// - public string SharedKey { get; set; } - - /// - /// flag to show the client is waiting for the server to send the shared key - /// - private bool WaitingForSharedKeyResponse { get; set; } - - /// - /// Defaults to 2000 - /// - public int BufferSize { get; set; } - - /// - /// Semaphore on connect method - /// - bool IsTryingToConnect; - - /// - /// Bool showing if socket is connected - /// - public bool IsConnected - { - get - { - if (Client != null) - return Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; - else - return false; - } - } + /// + /// SharedKey is sent for varification to the server. Shared key can be any text (255 char limit in SIMPL+ Module), but must match the Shared Key on the Server module + /// + public string SharedKey { get; set; } - /// - /// S+ helper for IsConnected - /// - public ushort UIsConnected - { - get { return (ushort)(IsConnected ? 1 : 0); } - } + /// + /// flag to show the client is waiting for the server to send the shared key + /// + private bool WaitingForSharedKeyResponse { get; set; } - /// - /// Bool showing if socket is ready for communication after shared key exchange - /// - public bool IsReadyForCommunication { get; set; } + /// + /// Defaults to 2000 + /// + public int BufferSize { get; set; } - /// - /// S+ helper for IsReadyForCommunication - /// - public ushort UIsReadyForCommunication - { - get { return (ushort)(IsReadyForCommunication ? 1 : 0); } - } + /// + /// Semaphore on connect method + /// + bool IsTryingToConnect; - /// - /// Client socket status Read only - /// - public SocketStatus ClientStatus + /// + /// Bool showing if socket is connected + /// + public bool IsConnected + { + get { - get - { - if (Client != null) - return Client.ClientStatus; - else - return SocketStatus.SOCKET_STATUS_NO_CONNECT; - } + if (Client != null) + return Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; + else + return false; } + } - /// - /// Contains the familiar Simpl analog status values. This drives the ConnectionChange event - /// and IsConnected would be true when this == 2. - /// - public ushort UStatus - { - get { return (ushort)ClientStatus; } - } + /// + /// S+ helper for IsConnected + /// + public ushort UIsConnected + { + get { return (ushort)(IsConnected ? 1 : 0); } + } - /// - /// Status text shows the message associated with socket status - /// - public string ClientStatusText { get { return ClientStatus.ToString(); } } + /// + /// Bool showing if socket is ready for communication after shared key exchange + /// + public bool IsReadyForCommunication { get; set; } - /// - /// bool to track if auto reconnect should be set on the socket - /// - public bool AutoReconnect { get; set; } + /// + /// S+ helper for IsReadyForCommunication + /// + public ushort UIsReadyForCommunication + { + get { return (ushort)(IsReadyForCommunication ? 1 : 0); } + } - /// - /// S+ helper for AutoReconnect - /// - public ushort UAutoReconnect - { - get { return (ushort)(AutoReconnect ? 1 : 0); } - set { AutoReconnect = value == 1; } - } - /// - /// Milliseconds to wait before attempting to reconnect. Defaults to 5000 - /// - public int AutoReconnectIntervalMs { get; set; } - - /// - /// Flag Set only when the disconnect method is called. - /// - bool DisconnectCalledByUser; - - /// - /// private Timer for auto reconnect - /// - CTimer RetryTimer; - - - /// - /// - /// - public bool HeartbeatEnabled { get; set; } - - /// - /// - /// - public ushort UHeartbeatEnabled + /// + /// Client socket status Read only + /// + public SocketStatus ClientStatus + { + get { - get { return (ushort)(HeartbeatEnabled ? 1 : 0); } - set { HeartbeatEnabled = value == 1; } + if (Client != null) + return Client.ClientStatus; + else + return SocketStatus.SOCKET_STATUS_NO_CONNECT; } + } - /// - /// - /// - public string HeartbeatString = "heartbeat"; - - /// - /// - /// - public int HeartbeatInterval = 50000; - - CTimer HeartbeatSendTimer; - CTimer HeartbeatAckTimer; - /// - /// Used to force disconnection on a dead connect attempt - /// - CTimer ConnectFailTimer; - CTimer WaitForSharedKey; - private int ConnectionCount; - /// - /// Internal secure client - /// - TCPClient Client; - - bool ProgramIsStopping; - - #endregion - - #region Constructors - - /// - /// Constructor - /// - /// - /// - /// - /// - public GenericTcpIpClient_ForServer(string key, string address, int port, int bufferSize) - : base(key) - { - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - Hostname = address; - Port = port; - BufferSize = bufferSize; - AutoReconnectIntervalMs = 5000; + /// + /// Contains the familiar Simpl analog status values. This drives the ConnectionChange event + /// and IsConnected would be true when this == 2. + /// + public ushort UStatus + { + get { return (ushort)ClientStatus; } + } - } + /// + /// Status text shows the message associated with socket status + /// + public string ClientStatusText { get { return ClientStatus.ToString(); } } + + /// + /// bool to track if auto reconnect should be set on the socket + /// + public bool AutoReconnect { get; set; } + + /// + /// S+ helper for AutoReconnect + /// + public ushort UAutoReconnect + { + get { return (ushort)(AutoReconnect ? 1 : 0); } + set { AutoReconnect = value == 1; } + } + /// + /// Milliseconds to wait before attempting to reconnect. Defaults to 5000 + /// + public int AutoReconnectIntervalMs { get; set; } + + /// + /// Flag Set only when the disconnect method is called. + /// + bool DisconnectCalledByUser; - /// - /// Constructor for S+ - /// - public GenericTcpIpClient_ForServer() - : base("Uninitialized DynamicTcpClient") + /// + /// private Timer for auto reconnect + /// + CTimer RetryTimer; + + + /// + /// + /// + public bool HeartbeatEnabled { get; set; } + + /// + /// + /// + public ushort UHeartbeatEnabled + { + get { return (ushort)(HeartbeatEnabled ? 1 : 0); } + set { HeartbeatEnabled = value == 1; } + } + + /// + /// + /// + public string HeartbeatString = "heartbeat"; + + /// + /// + /// + public int HeartbeatInterval = 50000; + + CTimer HeartbeatSendTimer; + CTimer HeartbeatAckTimer; + /// + /// Used to force disconnection on a dead connect attempt + /// + CTimer ConnectFailTimer; + CTimer WaitForSharedKey; + private int ConnectionCount; + /// + /// Internal secure client + /// + TCPClient Client; + + bool ProgramIsStopping; + + #endregion + + #region Constructors + + /// + /// Constructor + /// + /// + /// + /// + /// + public GenericTcpIpClient_ForServer(string key, string address, int port, int bufferSize) + : base(key) + { + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + Hostname = address; + Port = port; + BufferSize = bufferSize; + AutoReconnectIntervalMs = 5000; + + } + + /// + /// Constructor for S+ + /// + public GenericTcpIpClient_ForServer() + : base("Uninitialized DynamicTcpClient") + { + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + AutoReconnectIntervalMs = 5000; + BufferSize = 2000; + } + #endregion + + #region Methods + + /// + /// Just to help S+ set the key + /// + public void Initialize(string key) + { + Key = key; + } + + /// + /// Handles closing this up when the program shuts down + /// + void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + { + if (programEventType == eProgramStatusEventType.Stopping || programEventType == eProgramStatusEventType.Paused) { - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - AutoReconnectIntervalMs = 5000; - BufferSize = 2000; + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Program stopping. Closing Client connection"); + ProgramIsStopping = true; + Disconnect(); } - #endregion - #region Methods + } + + /// + /// Connect Method. Will return if already connected. Will write errors if missing address, port, or unique key/name. + /// + public void Connect() + { + ConnectionCount++; + Debug.Console(2, this, "Attempting connect Count:{0}", ConnectionCount); + - /// - /// Just to help S+ set the key - /// - public void Initialize(string key) + if (IsConnected) { - Key = key; + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Already connected. Ignoring."); + return; } - - /// - /// Handles closing this up when the program shuts down - /// - void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + if (IsTryingToConnect) { - if (programEventType == eProgramStatusEventType.Stopping || programEventType == eProgramStatusEventType.Paused) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Program stopping. Closing Client connection"); - ProgramIsStopping = true; - Disconnect(); - } - + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Already trying to connect. Ignoring."); + return; } - - /// - /// Connect Method. Will return if already connected. Will write errors if missing address, port, or unique key/name. - /// - public void Connect() + try { - ConnectionCount++; - Debug.Console(2, this, "Attempting connect Count:{0}", ConnectionCount); - - - if (IsConnected) + IsTryingToConnect = true; + if (RetryTimer != null) + { + RetryTimer.Stop(); + RetryTimer = null; + } + if (string.IsNullOrEmpty(Hostname)) { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Already connected. Ignoring."); + Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: No address set"); return; } - if (IsTryingToConnect) + if (Port < 1 || Port > 65535) { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Already trying to connect. Ignoring."); + Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: Invalid port"); return; } - try + if (string.IsNullOrEmpty(SharedKey) && SharedKeyRequired) { - IsTryingToConnect = true; - if (RetryTimer != null) - { - RetryTimer.Stop(); - RetryTimer = null; - } - if (string.IsNullOrEmpty(Hostname)) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: No address set"); - return; - } - if (Port < 1 || Port > 65535) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: Invalid port"); - return; - } - if (string.IsNullOrEmpty(SharedKey) && SharedKeyRequired) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: No Shared Key set"); - return; - } + Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "DynamicTcpClient: No Shared Key set"); + return; + } - // clean up previous client - if (Client != null) - { - Cleanup(); - } - DisconnectCalledByUser = false; + // clean up previous client + if (Client != null) + { + Cleanup(); + } + DisconnectCalledByUser = false; - Client = new TCPClient(Hostname, Port, BufferSize); - Client.SocketStatusChange += Client_SocketStatusChange; - if(HeartbeatEnabled) - Client.SocketSendOrReceiveTimeOutInMs = (HeartbeatInterval * 5); - Client.AddressClientConnectedTo = Hostname; - Client.PortNumber = Port; - // SecureClient = c; + Client = new TCPClient(Hostname, Port, BufferSize); + Client.SocketStatusChange += Client_SocketStatusChange; + if(HeartbeatEnabled) + Client.SocketSendOrReceiveTimeOutInMs = (HeartbeatInterval * 5); + Client.AddressClientConnectedTo = Hostname; + Client.PortNumber = Port; + // SecureClient = c; - //var timeOfConnect = DateTime.Now.ToString("HH:mm:ss.fff"); + //var timeOfConnect = DateTime.Now.ToString("HH:mm:ss.fff"); - ConnectFailTimer = new CTimer(o => + ConnectFailTimer = new CTimer(o => + { + Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Connect attempt has not finished after 30sec Count:{0}", ConnectionCount); + if (IsTryingToConnect) { - Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Connect attempt has not finished after 30sec Count:{0}", ConnectionCount); - if (IsTryingToConnect) - { - IsTryingToConnect = false; - - //if (ConnectionHasHungCallback != null) - //{ - // ConnectionHasHungCallback(); - //} - //SecureClient.DisconnectFromServer(); - //CheckClosedAndTryReconnect(); - } - }, 30000); + IsTryingToConnect = false; - Debug.Console(2, this, "Making Connection Count:{0}", ConnectionCount); - Client.ConnectToServerAsync(o => + //if (ConnectionHasHungCallback != null) + //{ + // ConnectionHasHungCallback(); + //} + //SecureClient.DisconnectFromServer(); + //CheckClosedAndTryReconnect(); + } + }, 30000); + + Debug.Console(2, this, "Making Connection Count:{0}", ConnectionCount); + Client.ConnectToServerAsync(o => + { + Debug.Console(2, this, "ConnectToServerAsync Count:{0} Ran!", ConnectionCount); + + if (ConnectFailTimer != null) { - Debug.Console(2, this, "ConnectToServerAsync Count:{0} Ran!", ConnectionCount); + ConnectFailTimer.Stop(); + } + IsTryingToConnect = false; - if (ConnectFailTimer != null) - { - ConnectFailTimer.Stop(); - } - IsTryingToConnect = false; + if (o.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) + { + Debug.Console(2, this, "Client connected to {0} on port {1}", o.AddressClientConnectedTo, o.LocalPortNumberOfClient); + o.ReceiveDataAsync(Receive); - if (o.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) + if (SharedKeyRequired) { - Debug.Console(2, this, "Client connected to {0} on port {1}", o.AddressClientConnectedTo, o.LocalPortNumberOfClient); - o.ReceiveDataAsync(Receive); - - if (SharedKeyRequired) - { - WaitingForSharedKeyResponse = true; - WaitForSharedKey = new CTimer(timer => - { - - Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Shared key exchange timer expired. IsReadyForCommunication={0}", IsReadyForCommunication); - // Debug.Console(1, this, "Connect attempt failed {0}", c.ClientStatus); - // This is the only case where we should call DisconectFromServer...Event handeler will trigger the cleanup - o.DisconnectFromServer(); - //CheckClosedAndTryReconnect(); - //OnClientReadyForcommunications(false); // Should send false event - }, 15000); - } - else + WaitingForSharedKeyResponse = true; + WaitForSharedKey = new CTimer(timer => { - //CLient connected and shared key is not required so just raise the ready for communication event. if Shared key - //required this is called by the shared key being negotiated - if (IsReadyForCommunication == false) - { - OnClientReadyForcommunications(true); // Key not required - } - } + + Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Shared key exchange timer expired. IsReadyForCommunication={0}", IsReadyForCommunication); + // Debug.Console(1, this, "Connect attempt failed {0}", c.ClientStatus); + // This is the only case where we should call DisconectFromServer...Event handeler will trigger the cleanup + o.DisconnectFromServer(); + //CheckClosedAndTryReconnect(); + //OnClientReadyForcommunications(false); // Should send false event + }, 15000); } else { - Debug.Console(1, this, "Connect attempt failed {0}", o.ClientStatus); - CheckClosedAndTryReconnect(); + //CLient connected and shared key is not required so just raise the ready for communication event. if Shared key + //required this is called by the shared key being negotiated + if (IsReadyForCommunication == false) + { + OnClientReadyForcommunications(true); // Key not required + } } - }); - } - catch (Exception ex) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Client connection exception: {0}", ex.Message); - IsTryingToConnect = false; - CheckClosedAndTryReconnect(); - } + } + else + { + Debug.Console(1, this, "Connect attempt failed {0}", o.ClientStatus); + CheckClosedAndTryReconnect(); + } + }); + } + catch (Exception ex) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Client connection exception: {0}", ex.Message); + IsTryingToConnect = false; + CheckClosedAndTryReconnect(); } + } + + /// + /// + /// + public void Disconnect() + { + this.LogVerbose("Disconnect Called"); - /// - /// - /// - public void Disconnect() + DisconnectCalledByUser = true; + if (IsConnected) { - this.LogVerbose("Disconnect Called"); + Client.DisconnectFromServer(); - DisconnectCalledByUser = true; - if (IsConnected) - { - Client.DisconnectFromServer(); + } + if (RetryTimer != null) + { + RetryTimer.Stop(); + RetryTimer = null; + } + Cleanup(); + } - } + /// + /// Internal call to close up client. ALWAYS use this when disconnecting. + /// + void Cleanup() + { + IsTryingToConnect = false; + + if (Client != null) + { + //SecureClient.DisconnectFromServer(); + Debug.Console(2, this, "Disconnecting Client {0}", DisconnectCalledByUser ? ", Called by user" : ""); + Client.SocketStatusChange -= Client_SocketStatusChange; + Client.Dispose(); + Client = null; + } + if (ConnectFailTimer != null) + { + ConnectFailTimer.Stop(); + ConnectFailTimer.Dispose(); + ConnectFailTimer = null; + } + } + + + /// ff + /// Called from Connect failure or Socket Status change if + /// auto reconnect and socket disconnected (Not disconnected by user) + /// + void CheckClosedAndTryReconnect() + { + if (Client != null) + { + Debug.Console(2, this, "Cleaning up remotely closed/failed connection."); + Cleanup(); + } + if (!DisconnectCalledByUser && AutoReconnect) + { + var halfInterval = AutoReconnectIntervalMs / 2; + var rndTime = new Random().Next(-halfInterval, halfInterval) + AutoReconnectIntervalMs; + Debug.Console(2, this, "Attempting reconnect in {0} ms, randomized", rndTime); if (RetryTimer != null) { RetryTimer.Stop(); RetryTimer = null; } - Cleanup(); + RetryTimer = new CTimer(o => Connect(), rndTime); } + } - /// - /// Internal call to close up client. ALWAYS use this when disconnecting. - /// - void Cleanup() + /// + /// Receive callback + /// + /// + /// + void Receive(TCPClient client, int numBytes) + { + if (numBytes > 0) { - IsTryingToConnect = false; + string str = string.Empty; - if (Client != null) + try { - //SecureClient.DisconnectFromServer(); - Debug.Console(2, this, "Disconnecting Client {0}", DisconnectCalledByUser ? ", Called by user" : ""); - Client.SocketStatusChange -= Client_SocketStatusChange; - Client.Dispose(); - Client = null; + var bytes = client.IncomingDataBuffer.Take(numBytes).ToArray(); + str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); + Debug.Console(2, this, "Client Received:\r--------\r{0}\r--------", str); + if (!string.IsNullOrEmpty(checkHeartbeat(str))) + { + if (SharedKeyRequired && str == "SharedKey:") + { + Debug.Console(2, this, "Server asking for shared key, sending"); + SendText(SharedKey + "\n"); + } + else if (SharedKeyRequired && str == "Shared Key Match") + { + StopWaitForSharedKeyTimer(); + Debug.Console(2, this, "Shared key confirmed. Ready for communication"); + OnClientReadyForcommunications(true); // Successful key exchange + } + else + { + //var bytesHandler = BytesReceived; + //if (bytesHandler != null) + // bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); + var textHandler = TextReceived; + if (textHandler != null) + textHandler(this, new GenericTcpServerCommMethodReceiveTextArgs(str)); + } + } } - if (ConnectFailTimer != null) + catch (Exception ex) { - ConnectFailTimer.Stop(); - ConnectFailTimer.Dispose(); - ConnectFailTimer = null; + Debug.Console(1, this, "Error receiving data: {1}. Error: {0}", ex.Message, str); } } + if (client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) + client.ReceiveDataAsync(Receive); + } - - /// ff - /// Called from Connect failure or Socket Status change if - /// auto reconnect and socket disconnected (Not disconnected by user) - /// - void CheckClosedAndTryReconnect() + void HeartbeatStart() + { + if (HeartbeatEnabled) { - if (Client != null) + Debug.Console(2, this, "Starting Heartbeat"); + if (HeartbeatSendTimer == null) { - Debug.Console(2, this, "Cleaning up remotely closed/failed connection."); - Cleanup(); + + HeartbeatSendTimer = new CTimer(this.SendHeartbeat, null, HeartbeatInterval, HeartbeatInterval); } - if (!DisconnectCalledByUser && AutoReconnect) + if (HeartbeatAckTimer == null) { - var halfInterval = AutoReconnectIntervalMs / 2; - var rndTime = new Random().Next(-halfInterval, halfInterval) + AutoReconnectIntervalMs; - Debug.Console(2, this, "Attempting reconnect in {0} ms, randomized", rndTime); - if (RetryTimer != null) - { - RetryTimer.Stop(); - RetryTimer = null; - } - RetryTimer = new CTimer(o => Connect(), rndTime); + HeartbeatAckTimer = new CTimer(HeartbeatAckTimerFail, null, (HeartbeatInterval * 2), (HeartbeatInterval * 2)); } } - /// - /// Receive callback - /// - /// - /// - void Receive(TCPClient client, int numBytes) + } + void HeartbeatStop() + { + + if (HeartbeatSendTimer != null) { - if (numBytes > 0) - { - string str = string.Empty; + Debug.Console(2, this, "Stoping Heartbeat Send"); + HeartbeatSendTimer.Stop(); + HeartbeatSendTimer = null; + } + if (HeartbeatAckTimer != null) + { + Debug.Console(2, this, "Stoping Heartbeat Ack"); + HeartbeatAckTimer.Stop(); + HeartbeatAckTimer = null; + } + + } + void SendHeartbeat(object notused) + { + this.SendText(HeartbeatString); + Debug.Console(2, this, "Sending Heartbeat"); - try + } + + //private method to check heartbeat requirements and start or reset timer + string checkHeartbeat(string received) + { + try + { + if (HeartbeatEnabled) + { + if (!string.IsNullOrEmpty(HeartbeatString)) { - var bytes = client.IncomingDataBuffer.Take(numBytes).ToArray(); - str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); - Debug.Console(2, this, "Client Received:\r--------\r{0}\r--------", str); - if (!string.IsNullOrEmpty(checkHeartbeat(str))) + var remainingText = received.Replace(HeartbeatString, ""); + var noDelimiter = received.Trim(new char[] { '\r', '\n' }); + if (noDelimiter.Contains(HeartbeatString)) { - if (SharedKeyRequired && str == "SharedKey:") - { - Debug.Console(2, this, "Server asking for shared key, sending"); - SendText(SharedKey + "\n"); - } - else if (SharedKeyRequired && str == "Shared Key Match") + if (HeartbeatAckTimer != null) { - StopWaitForSharedKeyTimer(); - Debug.Console(2, this, "Shared key confirmed. Ready for communication"); - OnClientReadyForcommunications(true); // Successful key exchange + HeartbeatAckTimer.Reset(HeartbeatInterval * 2); } else { - //var bytesHandler = BytesReceived; - //if (bytesHandler != null) - // bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); - var textHandler = TextReceived; - if (textHandler != null) - textHandler(this, new GenericTcpServerCommMethodReceiveTextArgs(str)); + HeartbeatAckTimer = new CTimer(HeartbeatAckTimerFail, null, (HeartbeatInterval * 2), (HeartbeatInterval * 2)); } + Debug.Console(2, this, "Heartbeat Received: {0}, from Server", HeartbeatString); + return remainingText; } - } - catch (Exception ex) - { - Debug.Console(1, this, "Error receiving data: {1}. Error: {0}", ex.Message, str); - } + } } - if (client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) - client.ReceiveDataAsync(Receive); } - - void HeartbeatStart() + catch (Exception ex) { - if (HeartbeatEnabled) - { - Debug.Console(2, this, "Starting Heartbeat"); - if (HeartbeatSendTimer == null) - { + Debug.Console(1, this, "Error checking heartbeat: {0}", ex.Message); + } + return received; + } - HeartbeatSendTimer = new CTimer(this.SendHeartbeat, null, HeartbeatInterval, HeartbeatInterval); - } - if (HeartbeatAckTimer == null) - { - HeartbeatAckTimer = new CTimer(HeartbeatAckTimerFail, null, (HeartbeatInterval * 2), (HeartbeatInterval * 2)); - } - } - } - void HeartbeatStop() + + void HeartbeatAckTimerFail(object o) + { + try { - if (HeartbeatSendTimer != null) - { - Debug.Console(2, this, "Stoping Heartbeat Send"); - HeartbeatSendTimer.Stop(); - HeartbeatSendTimer = null; - } - if (HeartbeatAckTimer != null) + if (IsConnected) { - Debug.Console(2, this, "Stoping Heartbeat Ack"); - HeartbeatAckTimer.Stop(); - HeartbeatAckTimer = null; + Debug.Console(1, Debug.ErrorLogLevel.Warning, "Heartbeat not received from Server...DISCONNECTING BECAUSE HEARTBEAT REQUIRED IS TRUE"); + SendText("Heartbeat not received by server, closing connection"); + CheckClosedAndTryReconnect(); } } - void SendHeartbeat(object notused) + catch (Exception ex) { - this.SendText(HeartbeatString); - Debug.Console(2, this, "Sending Heartbeat"); + ErrorLog.Error("Heartbeat timeout Error on Client: {0}, {1}", Key, ex); + } + } + /// + /// + /// + void StopWaitForSharedKeyTimer() + { + if (WaitForSharedKey != null) + { + WaitForSharedKey.Stop(); + WaitForSharedKey = null; } + } - //private method to check heartbeat requirements and start or reset timer - string checkHeartbeat(string received) + /// + /// General send method + /// + public void SendText(string text) + { + if (!string.IsNullOrEmpty(text)) { try { - if (HeartbeatEnabled) + var bytes = Encoding.GetEncoding(28591).GetBytes(text); + if (Client != null && Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) { - if (!string.IsNullOrEmpty(HeartbeatString)) + Client.SendDataAsync(bytes, bytes.Length, (c, n) => { - var remainingText = received.Replace(HeartbeatString, ""); - var noDelimiter = received.Trim(new char[] { '\r', '\n' }); - if (noDelimiter.Contains(HeartbeatString)) + // HOW IN THE HELL DO WE CATCH AN EXCEPTION IN SENDING????? + if (n <= 0) { - if (HeartbeatAckTimer != null) - { - HeartbeatAckTimer.Reset(HeartbeatInterval * 2); - } - else - { - HeartbeatAckTimer = new CTimer(HeartbeatAckTimerFail, null, (HeartbeatInterval * 2), (HeartbeatInterval * 2)); - } - Debug.Console(2, this, "Heartbeat Received: {0}, from Server", HeartbeatString); - return remainingText; + Debug.Console(1, Debug.ErrorLogLevel.Warning, "[{0}] Sent zero bytes. Was there an error?", this.Key); } - } + }); } } catch (Exception ex) { - Debug.Console(1, this, "Error checking heartbeat: {0}", ex.Message); + Debug.Console(0, this, "Error sending text: {1}. Error: {0}", ex.Message, text); } - return received; } + } - - - void HeartbeatAckTimerFail(object o) + /// + /// + /// + public void SendBytes(byte[] bytes) + { + if (bytes.Length > 0) { try { - - if (IsConnected) - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "Heartbeat not received from Server...DISCONNECTING BECAUSE HEARTBEAT REQUIRED IS TRUE"); - SendText("Heartbeat not received by server, closing connection"); - CheckClosedAndTryReconnect(); - } - + if (Client != null && Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) + Client.SendData(bytes, bytes.Length); } catch (Exception ex) { - ErrorLog.Error("Heartbeat timeout Error on Client: {0}, {1}", Key, ex); + Debug.Console(0, this, "Error sending bytes. Error: {0}", ex.Message); } } + } - /// - /// - /// - void StopWaitForSharedKeyTimer() + /// + /// SocketStatusChange Callback + /// + /// + /// + void Client_SocketStatusChange(TCPClient client, SocketStatus clientSocketStatus) + { + if (ProgramIsStopping) { - if (WaitForSharedKey != null) - { - WaitForSharedKey.Stop(); - WaitForSharedKey = null; - } + ProgramIsStopping = false; + return; } - - /// - /// General send method - /// - public void SendText(string text) + try { - if (!string.IsNullOrEmpty(text)) - { - try - { - var bytes = Encoding.GetEncoding(28591).GetBytes(text); - if (Client != null && Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) - { - Client.SendDataAsync(bytes, bytes.Length, (c, n) => - { - // HOW IN THE HELL DO WE CATCH AN EXCEPTION IN SENDING????? - if (n <= 0) - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "[{0}] Sent zero bytes. Was there an error?", this.Key); - } - }); - } - } - catch (Exception ex) - { - Debug.Console(0, this, "Error sending text: {1}. Error: {0}", ex.Message, text); - } - } - } + Debug.Console(2, this, "Socket status change: {0} ({1})", client.ClientStatus, (ushort)(client.ClientStatus)); - /// - /// - /// - public void SendBytes(byte[] bytes) - { - if (bytes.Length > 0) + OnConnectionChange(); + + // The client could be null or disposed by this time... + if (Client == null || Client.ClientStatus != SocketStatus.SOCKET_STATUS_CONNECTED) { - try - { - if (Client != null && Client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED) - Client.SendData(bytes, bytes.Length); - } - catch (Exception ex) - { - Debug.Console(0, this, "Error sending bytes. Error: {0}", ex.Message); - } + HeartbeatStop(); + OnClientReadyForcommunications(false); // socket has gone low + CheckClosedAndTryReconnect(); } } - - /// - /// SocketStatusChange Callback - /// - /// - /// - void Client_SocketStatusChange(TCPClient client, SocketStatus clientSocketStatus) + catch (Exception ex) { - if (ProgramIsStopping) - { - ProgramIsStopping = false; - return; - } - try - { - Debug.Console(2, this, "Socket status change: {0} ({1})", client.ClientStatus, (ushort)(client.ClientStatus)); - - OnConnectionChange(); - - // The client could be null or disposed by this time... - if (Client == null || Client.ClientStatus != SocketStatus.SOCKET_STATUS_CONNECTED) - { - HeartbeatStop(); - OnClientReadyForcommunications(false); // socket has gone low - CheckClosedAndTryReconnect(); - } - } - catch (Exception ex) - { - Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Error in socket status change callback. Error: {0}\r\r{1}", ex, ex.InnerException); - } + Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Error in socket status change callback. Error: {0}\r\r{1}", ex, ex.InnerException); } + } - /// - /// Helper for ConnectionChange event - /// - void OnConnectionChange() - { - var handler = ConnectionChange; - if (handler != null) - ConnectionChange(this, new GenericTcpServerSocketStatusChangeEventArgs(this, Client.ClientStatus)); - } + /// + /// Helper for ConnectionChange event + /// + void OnConnectionChange() + { + var handler = ConnectionChange; + if (handler != null) + ConnectionChange(this, new GenericTcpServerSocketStatusChangeEventArgs(this, Client.ClientStatus)); + } - /// - /// Helper to fire ClientReadyForCommunications event - /// - void OnClientReadyForcommunications(bool isReady) - { - IsReadyForCommunication = isReady; - if (this.IsReadyForCommunication) { HeartbeatStart(); } - var handler = ClientReadyForCommunications; - if (handler != null) - handler(this, new GenericTcpServerClientReadyForcommunicationsEventArgs(IsReadyForCommunication)); - } - #endregion + /// + /// Helper to fire ClientReadyForCommunications event + /// + void OnClientReadyForcommunications(bool isReady) + { + IsReadyForCommunication = isReady; + if (this.IsReadyForCommunication) { HeartbeatStart(); } + var handler = ClientReadyForCommunications; + if (handler != null) + handler(this, new GenericTcpServerClientReadyForcommunicationsEventArgs(IsReadyForCommunication)); } - -} \ No newline at end of file + #endregion +} diff --git a/src/PepperDash.Core/Comm/GenericTcpIpServer.cs b/src/PepperDash.Core/Comm/GenericTcpIpServer.cs index 6aa5e6b50..3dce88953 100644 --- a/src/PepperDash.Core/Comm/GenericTcpIpServer.cs +++ b/src/PepperDash.Core/Comm/GenericTcpIpServer.cs @@ -17,578 +17,563 @@ PepperDash Technology Corporation reserves all rights under applicable laws. using Crestron.SimplSharp.CrestronSockets; using PepperDash.Core.Logging; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// Generic TCP/IP server device +/// +public class GenericTcpIpServer : Device { + #region Events /// - /// Generic TCP/IP server device + /// Event for Receiving text /// - public class GenericTcpIpServer : Device - { - #region Events - /// - /// Event for Receiving text - /// - public event EventHandler TextReceived; + public event EventHandler TextReceived; - /// - /// Event for client connection socket status change - /// - public event EventHandler ClientConnectionChange; + /// + /// Event for client connection socket status change + /// + public event EventHandler ClientConnectionChange; - /// - /// Event for Server State Change - /// - public event EventHandler ServerStateChange; + /// + /// Event for Server State Change + /// + public event EventHandler ServerStateChange; - /// - /// For a server with a pre shared key, this will fire after the communication is established and the key exchange is complete. If no shared key, this will fire - /// after connection is successful. Use this event to know when the client is ready for communication to avoid stepping on shared key. - /// - public event EventHandler ServerClientReadyForCommunications; + /// + /// For a server with a pre shared key, this will fire after the communication is established and the key exchange is complete. If no shared key, this will fire + /// after connection is successful. Use this event to know when the client is ready for communication to avoid stepping on shared key. + /// + public event EventHandler ServerClientReadyForCommunications; - /// - /// A band aid event to notify user that the server has choked. - /// - public ServerHasChokedCallbackDelegate ServerHasChoked { get; set; } + /// + /// A band aid event to notify user that the server has choked. + /// + public ServerHasChokedCallbackDelegate ServerHasChoked { get; set; } - /// - /// - /// - public delegate void ServerHasChokedCallbackDelegate(); + /// + /// + /// + public delegate void ServerHasChokedCallbackDelegate(); - #endregion + #endregion - #region Properties/Variables + #region Properties/Variables - /// - /// - /// - CCriticalSection ServerCCSection = new CCriticalSection(); + /// + /// + /// + CCriticalSection ServerCCSection = new CCriticalSection(); - /// - /// A bandaid client that monitors whether the server is reachable - /// - GenericTcpIpClient_ForServer MonitorClient; + /// + /// A bandaid client that monitors whether the server is reachable + /// + GenericTcpIpClient_ForServer MonitorClient; - /// - /// Timer to operate the bandaid monitor client in a loop. - /// - CTimer MonitorClientTimer; + /// + /// Timer to operate the bandaid monitor client in a loop. + /// + CTimer MonitorClientTimer; - /// - /// - /// - int MonitorClientFailureCount; + /// + /// + /// + int MonitorClientFailureCount; - /// - /// 3 by default - /// - public int MonitorClientMaxFailureCount { get; set; } + /// + /// 3 by default + /// + public int MonitorClientMaxFailureCount { get; set; } - /// - /// Text representation of the Socket Status enum values for the server - /// - public string Status + /// + /// Text representation of the Socket Status enum values for the server + /// + public string Status + { + get { - get - { - if (myTcpServer != null) - return myTcpServer.State.ToString(); - return ServerState.SERVER_NOT_LISTENING.ToString(); - - } + if (myTcpServer != null) + return myTcpServer.State.ToString(); + return ServerState.SERVER_NOT_LISTENING.ToString(); } - /// - /// Bool showing if socket is connected - /// - public bool IsConnected + } + + /// + /// Bool showing if socket is connected + /// + public bool IsConnected + { + get { - get - { - if (myTcpServer != null) - return (myTcpServer.State & ServerState.SERVER_CONNECTED) == ServerState.SERVER_CONNECTED; - return false; + if (myTcpServer != null) + return (myTcpServer.State & ServerState.SERVER_CONNECTED) == ServerState.SERVER_CONNECTED; + return false; - //return (Secure ? SecureServer != null : UnsecureServer != null) && - //(Secure ? (SecureServer.State & ServerState.SERVER_CONNECTED) == ServerState.SERVER_CONNECTED : - // (UnsecureServer.State & ServerState.SERVER_CONNECTED) == ServerState.SERVER_CONNECTED); - } + //return (Secure ? SecureServer != null : UnsecureServer != null) && + //(Secure ? (SecureServer.State & ServerState.SERVER_CONNECTED) == ServerState.SERVER_CONNECTED : + // (UnsecureServer.State & ServerState.SERVER_CONNECTED) == ServerState.SERVER_CONNECTED); } + } - /// - /// S+ helper for IsConnected - /// - public ushort UIsConnected - { - get { return (ushort)(IsConnected ? 1 : 0); } - } + /// + /// S+ helper for IsConnected + /// + public ushort UIsConnected + { + get { return (ushort)(IsConnected ? 1 : 0); } + } - /// - /// Bool showing if socket is connected - /// - public bool IsListening + /// + /// Bool showing if socket is connected + /// + public bool IsListening + { + get { - get - { - if (myTcpServer != null) - return (myTcpServer.State & ServerState.SERVER_LISTENING) == ServerState.SERVER_LISTENING; - else - return false; - //return (Secure ? SecureServer != null : UnsecureServer != null) && - //(Secure ? (SecureServer.State & ServerState.SERVER_LISTENING) == ServerState.SERVER_LISTENING : - // (UnsecureServer.State & ServerState.SERVER_LISTENING) == ServerState.SERVER_LISTENING); - } + if (myTcpServer != null) + return (myTcpServer.State & ServerState.SERVER_LISTENING) == ServerState.SERVER_LISTENING; + else + return false; + //return (Secure ? SecureServer != null : UnsecureServer != null) && + //(Secure ? (SecureServer.State & ServerState.SERVER_LISTENING) == ServerState.SERVER_LISTENING : + // (UnsecureServer.State & ServerState.SERVER_LISTENING) == ServerState.SERVER_LISTENING); } + } - /// - /// S+ helper for IsConnected - /// - public ushort UIsListening - { - get { return (ushort)(IsListening ? 1 : 0); } - } + /// + /// S+ helper for IsConnected + /// + public ushort UIsListening + { + get { return (ushort)(IsListening ? 1 : 0); } + } - /// - /// The maximum number of clients. - /// Should be set by parameter in SIMPL+ in the MAIN method, Should not ever need to be configurable - /// - public ushort MaxClients { get; set; } + /// + /// The maximum number of clients. + /// Should be set by parameter in SIMPL+ in the MAIN method, Should not ever need to be configurable + /// + public ushort MaxClients { get; set; } - /// - /// Number of clients currently connected. - /// - public ushort NumberOfClientsConnected + /// + /// Number of clients currently connected. + /// + public ushort NumberOfClientsConnected + { + get { - get - { - if (myTcpServer != null) - return (ushort)myTcpServer.NumberOfClientsConnected; - return 0; - } + if (myTcpServer != null) + return (ushort)myTcpServer.NumberOfClientsConnected; + return 0; } + } - /// - /// Port Server should listen on - /// - public int Port { get; set; } + /// + /// Port Server should listen on + /// + public int Port { get; set; } - /// - /// S+ helper for Port - /// - public ushort UPort - { - get { return Convert.ToUInt16(Port); } - set { Port = Convert.ToInt32(value); } - } + /// + /// S+ helper for Port + /// + public ushort UPort + { + get { return Convert.ToUInt16(Port); } + set { Port = Convert.ToInt32(value); } + } - /// - /// Bool to show whether the server requires a preshared key. Must be set the same in the client, and if true shared keys must be identical on server/client - /// - public bool SharedKeyRequired { get; set; } + /// + /// Bool to show whether the server requires a preshared key. Must be set the same in the client, and if true shared keys must be identical on server/client + /// + public bool SharedKeyRequired { get; set; } - /// - /// S+ helper for requires shared key bool - /// - public ushort USharedKeyRequired + /// + /// S+ helper for requires shared key bool + /// + public ushort USharedKeyRequired + { + set { - set - { - if (value == 1) - SharedKeyRequired = true; - else - SharedKeyRequired = false; - } + if (value == 1) + SharedKeyRequired = true; + else + SharedKeyRequired = false; } + } - /// - /// SharedKey is sent for varification to the server. Shared key can be any text (255 char limit in SIMPL+ Module), but must match the Shared Key on the Server module. - /// If SharedKey changes while server is listening or clients are connected, disconnect and stop listening will be called - /// - public string SharedKey { get; set; } + /// + /// SharedKey is sent for varification to the server. Shared key can be any text (255 char limit in SIMPL+ Module), but must match the Shared Key on the Server module. + /// If SharedKey changes while server is listening or clients are connected, disconnect and stop listening will be called + /// + public string SharedKey { get; set; } - /// - /// Heartbeat Required bool sets whether server disconnects client if heartbeat is not received - /// - public bool HeartbeatRequired { get; set; } + /// + /// Heartbeat Required bool sets whether server disconnects client if heartbeat is not received + /// + public bool HeartbeatRequired { get; set; } - /// - /// S+ Helper for Heartbeat Required - /// - public ushort UHeartbeatRequired + /// + /// S+ Helper for Heartbeat Required + /// + public ushort UHeartbeatRequired + { + set { - set - { - if (value == 1) - HeartbeatRequired = true; - else - HeartbeatRequired = false; - } + if (value == 1) + HeartbeatRequired = true; + else + HeartbeatRequired = false; } + } - /// - /// Milliseconds before server expects another heartbeat. Set by property HeartbeatRequiredIntervalInSeconds which is driven from S+ - /// - public int HeartbeatRequiredIntervalMs { get; set; } + /// + /// Milliseconds before server expects another heartbeat. Set by property HeartbeatRequiredIntervalInSeconds which is driven from S+ + /// + public int HeartbeatRequiredIntervalMs { get; set; } - /// - /// Simpl+ Heartbeat Analog value in seconds - /// - public ushort HeartbeatRequiredIntervalInSeconds { set { HeartbeatRequiredIntervalMs = (value * 1000); } } + /// + /// Simpl+ Heartbeat Analog value in seconds + /// + public ushort HeartbeatRequiredIntervalInSeconds { set { HeartbeatRequiredIntervalMs = (value * 1000); } } - /// - /// String to Match for heartbeat. If null or empty any string will reset heartbeat timer - /// - public string HeartbeatStringToMatch { get; set; } + /// + /// String to Match for heartbeat. If null or empty any string will reset heartbeat timer + /// + public string HeartbeatStringToMatch { get; set; } + + //private timers for Heartbeats per client + Dictionary HeartbeatTimerDictionary = new Dictionary(); - //private timers for Heartbeats per client - Dictionary HeartbeatTimerDictionary = new Dictionary(); + //flags to show the secure server is waiting for client at index to send the shared key + List WaitingForSharedKey = new List(); + + List ClientReadyAfterKeyExchange = new List(); + + /// + /// The connected client indexes + /// + public List ConnectedClientsIndexes = new List(); - //flags to show the secure server is waiting for client at index to send the shared key - List WaitingForSharedKey = new List(); + /// + /// Defaults to 2000 + /// + public int BufferSize { get; set; } - List ClientReadyAfterKeyExchange = new List(); + /// + /// Private flag to note that the server has stopped intentionally + /// + private bool ServerStopped { get; set; } - /// - /// The connected client indexes - /// - public List ConnectedClientsIndexes = new List(); + //Servers + TCPServer myTcpServer; - /// - /// Defaults to 2000 - /// - public int BufferSize { get; set; } + /// + /// + /// + bool ProgramIsStopping; - /// - /// Private flag to note that the server has stopped intentionally - /// - private bool ServerStopped { get; set; } + #endregion - //Servers - TCPServer myTcpServer; + #region Constructors + /// + /// constructor S+ Does not accept a key. Use initialze with key to set the debug key on this device. If using with + make sure to set all properties manually. + /// + public GenericTcpIpServer() + : base("Uninitialized Dynamic TCP Server") + { + HeartbeatRequiredIntervalInSeconds = 15; + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + BufferSize = 2000; + MonitorClientMaxFailureCount = 3; + } - /// - /// - /// - bool ProgramIsStopping; + /// + /// constructor with debug key set at instantiation. Make sure to set all properties before listening. + /// + /// + public GenericTcpIpServer(string key) + : base("Uninitialized Dynamic TCP Server") + { + HeartbeatRequiredIntervalInSeconds = 15; + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + BufferSize = 2000; + MonitorClientMaxFailureCount = 3; + Key = key; + } - #endregion + /// + /// Contstructor that sets all properties by calling the initialize method with a config object. + /// + /// + public GenericTcpIpServer(TcpServerConfigObject serverConfigObject) + : base("Uninitialized Dynamic TCP Server") + { + HeartbeatRequiredIntervalInSeconds = 15; + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + BufferSize = 2000; + MonitorClientMaxFailureCount = 3; + Initialize(serverConfigObject); + } + #endregion - #region Constructors - /// - /// constructor S+ Does not accept a key. Use initialze with key to set the debug key on this device. If using with + make sure to set all properties manually. - /// - public GenericTcpIpServer() - : base("Uninitialized Dynamic TCP Server") + #region Methods - Server Actions + /// + /// Disconnects all clients and stops the server + /// + public void KillServer() + { + ServerStopped = true; + if (MonitorClient != null) { - HeartbeatRequiredIntervalInSeconds = 15; - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - BufferSize = 2000; - MonitorClientMaxFailureCount = 3; + MonitorClient.Disconnect(); } + DisconnectAllClientsForShutdown(); + StopListening(); + } - /// - /// constructor with debug key set at instantiation. Make sure to set all properties before listening. - /// - /// - public GenericTcpIpServer(string key) - : base("Uninitialized Dynamic TCP Server") - { - HeartbeatRequiredIntervalInSeconds = 15; - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - BufferSize = 2000; - MonitorClientMaxFailureCount = 3; - Key = key; - } + /// + /// Initialize Key for device using client name from SIMPL+. Called on Listen from SIMPL+ + /// + /// + public void Initialize(string key) + { + Key = key; + } - /// - /// Contstructor that sets all properties by calling the initialize method with a config object. - /// - /// - public GenericTcpIpServer(TcpServerConfigObject serverConfigObject) - : base("Uninitialized Dynamic TCP Server") + /// + /// Initialze with server configuration object + /// + /// + public void Initialize(TcpServerConfigObject serverConfigObject) + { + try { - HeartbeatRequiredIntervalInSeconds = 15; - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - BufferSize = 2000; - MonitorClientMaxFailureCount = 3; - Initialize(serverConfigObject); - } - #endregion + if (serverConfigObject != null || string.IsNullOrEmpty(serverConfigObject.Key)) + { + Key = serverConfigObject.Key; + MaxClients = serverConfigObject.MaxClients; + Port = serverConfigObject.Port; + SharedKeyRequired = serverConfigObject.SharedKeyRequired; + SharedKey = serverConfigObject.SharedKey; + HeartbeatRequired = serverConfigObject.HeartbeatRequired; + HeartbeatRequiredIntervalInSeconds = serverConfigObject.HeartbeatRequiredIntervalInSeconds; + HeartbeatStringToMatch = serverConfigObject.HeartbeatStringToMatch; + BufferSize = serverConfigObject.BufferSize; - #region Methods - Server Actions - /// - /// Disconnects all clients and stops the server - /// - public void KillServer() - { - ServerStopped = true; - if (MonitorClient != null) + } + else { - MonitorClient.Disconnect(); + ErrorLog.Error("Could not initialize server with key: {0}", serverConfigObject.Key); } - DisconnectAllClientsForShutdown(); - StopListening(); } - - /// - /// Initialize Key for device using client name from SIMPL+. Called on Listen from SIMPL+ - /// - /// - public void Initialize(string key) + catch { - Key = key; + ErrorLog.Error("Could not initialize server with key: {0}", serverConfigObject.Key); } + } - /// - /// Initialze with server configuration object - /// - /// - public void Initialize(TcpServerConfigObject serverConfigObject) + /// + /// Start listening on the specified port + /// + public void Listen() + { + ServerCCSection.Enter(); + try { - try + if (Port < 1 || Port > 65535) { - if (serverConfigObject != null || string.IsNullOrEmpty(serverConfigObject.Key)) - { - Key = serverConfigObject.Key; - MaxClients = serverConfigObject.MaxClients; - Port = serverConfigObject.Port; - SharedKeyRequired = serverConfigObject.SharedKeyRequired; - SharedKey = serverConfigObject.SharedKey; - HeartbeatRequired = serverConfigObject.HeartbeatRequired; - HeartbeatRequiredIntervalInSeconds = serverConfigObject.HeartbeatRequiredIntervalInSeconds; - HeartbeatStringToMatch = serverConfigObject.HeartbeatStringToMatch; - BufferSize = serverConfigObject.BufferSize; - - } - else - { - ErrorLog.Error("Could not initialize server with key: {0}", serverConfigObject.Key); - } + Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Server '{0}': Invalid port", Key); + ErrorLog.Warn(string.Format("Server '{0}': Invalid port", Key)); + return; } - catch + if (string.IsNullOrEmpty(SharedKey) && SharedKeyRequired) { - ErrorLog.Error("Could not initialize server with key: {0}", serverConfigObject.Key); + Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Server '{0}': No Shared Key set", Key); + ErrorLog.Warn(string.Format("Server '{0}': No Shared Key set", Key)); + return; } - } + if (IsListening) + return; - /// - /// Start listening on the specified port - /// - public void Listen() - { - ServerCCSection.Enter(); - try + if (myTcpServer == null) { - if (Port < 1 || Port > 65535) - { - Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Server '{0}': Invalid port", Key); - ErrorLog.Warn(string.Format("Server '{0}': Invalid port", Key)); - return; - } - if (string.IsNullOrEmpty(SharedKey) && SharedKeyRequired) - { - Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Server '{0}': No Shared Key set", Key); - ErrorLog.Warn(string.Format("Server '{0}': No Shared Key set", Key)); - return; - } - if (IsListening) - return; - - if (myTcpServer == null) - { - myTcpServer = new TCPServer(Port, MaxClients); - if(HeartbeatRequired) - myTcpServer.SocketSendOrReceiveTimeOutInMs = (this.HeartbeatRequiredIntervalMs * 5); - + myTcpServer = new TCPServer(Port, MaxClients); + if(HeartbeatRequired) + myTcpServer.SocketSendOrReceiveTimeOutInMs = (this.HeartbeatRequiredIntervalMs * 5); + // myTcpServer.HandshakeTimeout = 30; - } - else - { - KillServer(); - myTcpServer.PortNumber = Port; - } + } + else + { + KillServer(); + myTcpServer.PortNumber = Port; + } - myTcpServer.SocketStatusChange -= TcpServer_SocketStatusChange; - myTcpServer.SocketStatusChange += TcpServer_SocketStatusChange; + myTcpServer.SocketStatusChange -= TcpServer_SocketStatusChange; + myTcpServer.SocketStatusChange += TcpServer_SocketStatusChange; - ServerStopped = false; - myTcpServer.WaitForConnectionAsync(IPAddress.Any, TcpConnectCallback); - OnServerStateChange(myTcpServer.State); - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "TCP Server Status: {0}, Socket Status: {1}", myTcpServer.State, myTcpServer.ServerSocketStatus); + ServerStopped = false; + myTcpServer.WaitForConnectionAsync(IPAddress.Any, TcpConnectCallback); + OnServerStateChange(myTcpServer.State); + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "TCP Server Status: {0}, Socket Status: {1}", myTcpServer.State, myTcpServer.ServerSocketStatus); - // StartMonitorClient(); + // StartMonitorClient(); - ServerCCSection.Leave(); - } - catch (Exception ex) - { - ServerCCSection.Leave(); - ErrorLog.Error("{1} Error with Dynamic Server: {0}", ex.ToString(), Key); - } + ServerCCSection.Leave(); } + catch (Exception ex) + { + ServerCCSection.Leave(); + ErrorLog.Error("{1} Error with Dynamic Server: {0}", ex.ToString(), Key); + } + } - /// - /// Stop Listening - /// - public void StopListening() + /// + /// Stop Listening + /// + public void StopListening() + { + try { - try + Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Stopping Listener"); + if (myTcpServer != null) { - Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Stopping Listener"); - if (myTcpServer != null) - { - myTcpServer.Stop(); - Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Server State: {0}", myTcpServer.State); + myTcpServer.Stop(); + Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Server State: {0}", myTcpServer.State); OnServerStateChange(myTcpServer.State); - } - ServerStopped = true; - } - catch (Exception ex) - { - Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error stopping server. Error: {0}", ex); } + ServerStopped = true; + } + catch (Exception ex) + { + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error stopping server. Error: {0}", ex); } + } - /// - /// Disconnects Client - /// - /// - public void DisconnectClient(uint client) + /// + /// Disconnects Client + /// + /// + public void DisconnectClient(uint client) + { + try { - try - { - myTcpServer.Disconnect(client); - Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Disconnected client index: {0}", client); - } - catch (Exception ex) - { - Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error Disconnecting client index: {0}. Error: {1}", client, ex); - } + myTcpServer.Disconnect(client); + Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Disconnected client index: {0}", client); } - /// - /// Disconnect All Clients - /// - public void DisconnectAllClientsForShutdown() + catch (Exception ex) { - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Disconnecting All Clients"); - if (myTcpServer != null) + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error Disconnecting client index: {0}. Error: {1}", client, ex); + } + } + /// + /// Disconnect All Clients + /// + public void DisconnectAllClientsForShutdown() + { + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Disconnecting All Clients"); + if (myTcpServer != null) + { + myTcpServer.SocketStatusChange -= TcpServer_SocketStatusChange; + foreach (var index in ConnectedClientsIndexes.ToList()) // copy it here so that it iterates properly { - myTcpServer.SocketStatusChange -= TcpServer_SocketStatusChange; - foreach (var index in ConnectedClientsIndexes.ToList()) // copy it here so that it iterates properly + var i = index; + if (!myTcpServer.ClientConnected(index)) + continue; + try { - var i = index; - if (!myTcpServer.ClientConnected(index)) - continue; - try - { - myTcpServer.Disconnect(i); - Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Disconnected client index: {0}", i); - } - catch (Exception ex) - { - Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error Disconnecting client index: {0}. Error: {1}", i, ex); - } + myTcpServer.Disconnect(i); + Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Disconnected client index: {0}", i); + } + catch (Exception ex) + { + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error Disconnecting client index: {0}. Error: {1}", i, ex); } - Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Server Status: {0}", myTcpServer.ServerSocketStatus); } + Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Server Status: {0}", myTcpServer.ServerSocketStatus); + } - Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Disconnected All Clients"); - ConnectedClientsIndexes.Clear(); - - if (!ProgramIsStopping) - { - OnConnectionChange(); - OnServerStateChange(myTcpServer.State); //State shows both listening and connected - } + Debug.Console(2, this, Debug.ErrorLogLevel.Notice, "Disconnected All Clients"); + ConnectedClientsIndexes.Clear(); - // var o = new { }; + if (!ProgramIsStopping) + { + OnConnectionChange(); + OnServerStateChange(myTcpServer.State); //State shows both listening and connected } - /// - /// Broadcast text from server to all connected clients - /// - /// - public void BroadcastText(string text) + // var o = new { }; + } + + /// + /// Broadcast text from server to all connected clients + /// + /// + public void BroadcastText(string text) + { + CCriticalSection CCBroadcast = new CCriticalSection(); + CCBroadcast.Enter(); + try { - CCriticalSection CCBroadcast = new CCriticalSection(); - CCBroadcast.Enter(); - try + if (ConnectedClientsIndexes.Count > 0) { - if (ConnectedClientsIndexes.Count > 0) + byte[] b = Encoding.GetEncoding(28591).GetBytes(text); + foreach (uint i in ConnectedClientsIndexes) { - byte[] b = Encoding.GetEncoding(28591).GetBytes(text); - foreach (uint i in ConnectedClientsIndexes) + if (!SharedKeyRequired || (SharedKeyRequired && ClientReadyAfterKeyExchange.Contains(i))) { - if (!SharedKeyRequired || (SharedKeyRequired && ClientReadyAfterKeyExchange.Contains(i))) - { - SocketErrorCodes error = myTcpServer.SendDataAsync(i, b, b.Length, (x, y, z) => { }); - if (error != SocketErrorCodes.SOCKET_OK && error != SocketErrorCodes.SOCKET_OPERATION_PENDING) - this.LogError("{error}",error.ToString()); - } + SocketErrorCodes error = myTcpServer.SendDataAsync(i, b, b.Length, (x, y, z) => { }); + if (error != SocketErrorCodes.SOCKET_OK && error != SocketErrorCodes.SOCKET_OPERATION_PENDING) + this.LogError("{error}",error.ToString()); } } - CCBroadcast.Leave(); - } - catch (Exception ex) - { - CCBroadcast.Leave(); - Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error Broadcasting messages from server. Error: {0}", ex.Message); } + CCBroadcast.Leave(); + } + catch (Exception ex) + { + CCBroadcast.Leave(); + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error Broadcasting messages from server. Error: {0}", ex.Message); } + } - /// - /// Not sure this is useful in library, maybe Pro?? - /// - /// - /// - public void SendTextToClient(string text, uint clientIndex) + /// + /// Not sure this is useful in library, maybe Pro?? + /// + /// + /// + public void SendTextToClient(string text, uint clientIndex) + { + try { - try + byte[] b = Encoding.GetEncoding(28591).GetBytes(text); + if (myTcpServer != null && myTcpServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) { - byte[] b = Encoding.GetEncoding(28591).GetBytes(text); - if (myTcpServer != null && myTcpServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) - { - if (!SharedKeyRequired || (SharedKeyRequired && ClientReadyAfterKeyExchange.Contains(clientIndex))) - myTcpServer.SendDataAsync(clientIndex, b, b.Length, (x, y, z) => { }); - } - } - catch (Exception ex) - { - Debug.Console(2, this, "Error sending text to client. Text: {1}. Error: {0}", ex.Message, text); + if (!SharedKeyRequired || (SharedKeyRequired && ClientReadyAfterKeyExchange.Contains(clientIndex))) + myTcpServer.SendDataAsync(clientIndex, b, b.Length, (x, y, z) => { }); } } + catch (Exception ex) + { + Debug.Console(2, this, "Error sending text to client. Text: {1}. Error: {0}", ex.Message, text); + } + } - //private method to check heartbeat requirements and start or reset timer - string checkHeartbeat(uint clientIndex, string received) + //private method to check heartbeat requirements and start or reset timer + string checkHeartbeat(uint clientIndex, string received) + { + try { - try + if (HeartbeatRequired) { - if (HeartbeatRequired) + if (!string.IsNullOrEmpty(HeartbeatStringToMatch)) { - if (!string.IsNullOrEmpty(HeartbeatStringToMatch)) - { - var remainingText = received.Replace(HeartbeatStringToMatch, ""); - var noDelimiter = received.Trim(new char[] { '\r', '\n' }); - if (noDelimiter.Contains(HeartbeatStringToMatch)) - { - if (HeartbeatTimerDictionary.ContainsKey(clientIndex)) - HeartbeatTimerDictionary[clientIndex].Reset(HeartbeatRequiredIntervalMs); - else - { - CTimer HeartbeatTimer = new CTimer(HeartbeatTimer_CallbackFunction, clientIndex, HeartbeatRequiredIntervalMs); - HeartbeatTimerDictionary.Add(clientIndex, HeartbeatTimer); - } - Debug.Console(1, this, "Heartbeat Received: {0}, from client index: {1}", HeartbeatStringToMatch, clientIndex); - // Return Heartbeat - SendTextToClient(HeartbeatStringToMatch, clientIndex); - return remainingText; - } - } - else + var remainingText = received.Replace(HeartbeatStringToMatch, ""); + var noDelimiter = received.Trim(new char[] { '\r', '\n' }); + if (noDelimiter.Contains(HeartbeatStringToMatch)) { if (HeartbeatTimerDictionary.ContainsKey(clientIndex)) HeartbeatTimerDictionary[clientIndex].Reset(HeartbeatRequiredIntervalMs); @@ -597,197 +582,212 @@ string checkHeartbeat(uint clientIndex, string received) CTimer HeartbeatTimer = new CTimer(HeartbeatTimer_CallbackFunction, clientIndex, HeartbeatRequiredIntervalMs); HeartbeatTimerDictionary.Add(clientIndex, HeartbeatTimer); } - Debug.Console(1, this, "Heartbeat Received: {0}, from client index: {1}", received, clientIndex); + Debug.Console(1, this, "Heartbeat Received: {0}, from client index: {1}", HeartbeatStringToMatch, clientIndex); + // Return Heartbeat + SendTextToClient(HeartbeatStringToMatch, clientIndex); + return remainingText; } } + else + { + if (HeartbeatTimerDictionary.ContainsKey(clientIndex)) + HeartbeatTimerDictionary[clientIndex].Reset(HeartbeatRequiredIntervalMs); + else + { + CTimer HeartbeatTimer = new CTimer(HeartbeatTimer_CallbackFunction, clientIndex, HeartbeatRequiredIntervalMs); + HeartbeatTimerDictionary.Add(clientIndex, HeartbeatTimer); + } + Debug.Console(1, this, "Heartbeat Received: {0}, from client index: {1}", received, clientIndex); + } } - catch (Exception ex) - { - Debug.Console(1, this, "Error checking heartbeat: {0}", ex.Message); - } - return received; } + catch (Exception ex) + { + Debug.Console(1, this, "Error checking heartbeat: {0}", ex.Message); + } + return received; + } - /// - /// Gets the IP address based on the client index - /// - /// - /// IP address of the client - public string GetClientIPAddress(uint clientIndex) + /// + /// Gets the IP address based on the client index + /// + /// + /// IP address of the client + public string GetClientIPAddress(uint clientIndex) + { + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "GetClientIPAddress Index: {0}", clientIndex); + if (!SharedKeyRequired || (SharedKeyRequired && ClientReadyAfterKeyExchange.Contains(clientIndex))) { - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "GetClientIPAddress Index: {0}", clientIndex); - if (!SharedKeyRequired || (SharedKeyRequired && ClientReadyAfterKeyExchange.Contains(clientIndex))) - { - var ipa = this.myTcpServer.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex); - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "GetClientIPAddress IPAddreess: {0}", ipa); - return ipa; + var ipa = this.myTcpServer.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex); + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "GetClientIPAddress IPAddreess: {0}", ipa); + return ipa; - } - else - { - return ""; - } } + else + { + return ""; + } + } - #endregion + #endregion - #region Methods - HeartbeatTimer Callback + #region Methods - HeartbeatTimer Callback - void HeartbeatTimer_CallbackFunction(object o) + void HeartbeatTimer_CallbackFunction(object o) + { + uint clientIndex = 99999; + string address = string.Empty; + try { - uint clientIndex = 99999; - string address = string.Empty; - try - { - clientIndex = (uint)o; - address = myTcpServer.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex); + clientIndex = (uint)o; + address = myTcpServer.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex); - Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Heartbeat not received for Client index {2} IP: {0}, DISCONNECTING BECAUSE HEARTBEAT REQUIRED IS TRUE {1}", - address, string.IsNullOrEmpty(HeartbeatStringToMatch) ? "" : ("HeartbeatStringToMatch: " + HeartbeatStringToMatch), clientIndex); + Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Heartbeat not received for Client index {2} IP: {0}, DISCONNECTING BECAUSE HEARTBEAT REQUIRED IS TRUE {1}", + address, string.IsNullOrEmpty(HeartbeatStringToMatch) ? "" : ("HeartbeatStringToMatch: " + HeartbeatStringToMatch), clientIndex); - if (myTcpServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) - SendTextToClient("Heartbeat not received by server, closing connection", clientIndex); + if (myTcpServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) + SendTextToClient("Heartbeat not received by server, closing connection", clientIndex); - var discoResult = myTcpServer.Disconnect(clientIndex); - //Debug.Console(1, this, "{0}", discoResult); + var discoResult = myTcpServer.Disconnect(clientIndex); + //Debug.Console(1, this, "{0}", discoResult); - if (HeartbeatTimerDictionary.ContainsKey(clientIndex)) - { - HeartbeatTimerDictionary[clientIndex].Stop(); - HeartbeatTimerDictionary[clientIndex].Dispose(); - HeartbeatTimerDictionary.Remove(clientIndex); - } - } - catch (Exception ex) + if (HeartbeatTimerDictionary.ContainsKey(clientIndex)) { - ErrorLog.Error("{3}: Heartbeat timeout Error on Client Index: {0}, at address: {1}, error: {2}", clientIndex, address, ex.Message, Key); + HeartbeatTimerDictionary[clientIndex].Stop(); + HeartbeatTimerDictionary[clientIndex].Dispose(); + HeartbeatTimerDictionary.Remove(clientIndex); } } + catch (Exception ex) + { + ErrorLog.Error("{3}: Heartbeat timeout Error on Client Index: {0}, at address: {1}, error: {2}", clientIndex, address, ex.Message, Key); + } + } - #endregion + #endregion - #region Methods - Socket Status Changed Callbacks - /// - /// Secure Server Socket Status Changed Callback - /// - /// - /// - /// - void TcpServer_SocketStatusChange(TCPServer server, uint clientIndex, SocketStatus serverSocketStatus) + #region Methods - Socket Status Changed Callbacks + /// + /// Secure Server Socket Status Changed Callback + /// + /// + /// + /// + void TcpServer_SocketStatusChange(TCPServer server, uint clientIndex, SocketStatus serverSocketStatus) + { + try { - try - { - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "SecureServerSocketStatusChange Index:{0} status:{1} Port:{2} IP:{3}", clientIndex, serverSocketStatus, this.myTcpServer.GetPortNumberServerAcceptedConnectionFromForSpecificClient(clientIndex), this.myTcpServer.GetLocalAddressServerAcceptedConnectionFromForSpecificClient(clientIndex)); - if (serverSocketStatus != SocketStatus.SOCKET_STATUS_CONNECTED) + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "SecureServerSocketStatusChange Index:{0} status:{1} Port:{2} IP:{3}", clientIndex, serverSocketStatus, this.myTcpServer.GetPortNumberServerAcceptedConnectionFromForSpecificClient(clientIndex), this.myTcpServer.GetLocalAddressServerAcceptedConnectionFromForSpecificClient(clientIndex)); + if (serverSocketStatus != SocketStatus.SOCKET_STATUS_CONNECTED) + { + if (ConnectedClientsIndexes.Contains(clientIndex)) + ConnectedClientsIndexes.Remove(clientIndex); + if (HeartbeatRequired && HeartbeatTimerDictionary.ContainsKey(clientIndex)) { - if (ConnectedClientsIndexes.Contains(clientIndex)) - ConnectedClientsIndexes.Remove(clientIndex); - if (HeartbeatRequired && HeartbeatTimerDictionary.ContainsKey(clientIndex)) - { - HeartbeatTimerDictionary[clientIndex].Stop(); - HeartbeatTimerDictionary[clientIndex].Dispose(); - HeartbeatTimerDictionary.Remove(clientIndex); - } - if (ClientReadyAfterKeyExchange.Contains(clientIndex)) - ClientReadyAfterKeyExchange.Remove(clientIndex); + HeartbeatTimerDictionary[clientIndex].Stop(); + HeartbeatTimerDictionary[clientIndex].Dispose(); + HeartbeatTimerDictionary.Remove(clientIndex); + } + if (ClientReadyAfterKeyExchange.Contains(clientIndex)) + ClientReadyAfterKeyExchange.Remove(clientIndex); if (WaitingForSharedKey.Contains(clientIndex)) WaitingForSharedKey.Remove(clientIndex); - } - } - catch (Exception ex) - { - Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error in Socket Status Change Callback. Error: {0}", ex); } - onConnectionChange(clientIndex, server.GetServerSocketStatusForSpecificClient(clientIndex)); } + catch (Exception ex) + { + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error in Socket Status Change Callback. Error: {0}", ex); + } + onConnectionChange(clientIndex, server.GetServerSocketStatusForSpecificClient(clientIndex)); + } - #endregion + #endregion - #region Methods Connected Callbacks - /// - /// Secure TCP Client Connected to Secure Server Callback - /// - /// - /// - void TcpConnectCallback(TCPServer server, uint clientIndex) + #region Methods Connected Callbacks + /// + /// Secure TCP Client Connected to Secure Server Callback + /// + /// + /// + void TcpConnectCallback(TCPServer server, uint clientIndex) + { + try { - try + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "ConnectCallback: IPAddress: {0}. Index: {1}. Status: {2}", + server.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex), + clientIndex, server.GetServerSocketStatusForSpecificClient(clientIndex)); + if (clientIndex != 0) { - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "ConnectCallback: IPAddress: {0}. Index: {1}. Status: {2}", - server.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex), - clientIndex, server.GetServerSocketStatusForSpecificClient(clientIndex)); - if (clientIndex != 0) + if (server.ClientConnected(clientIndex)) { - if (server.ClientConnected(clientIndex)) - { - if (!ConnectedClientsIndexes.Contains(clientIndex)) - { - ConnectedClientsIndexes.Add(clientIndex); - } - if (SharedKeyRequired) - { - if (!WaitingForSharedKey.Contains(clientIndex)) - { - WaitingForSharedKey.Add(clientIndex); - } - byte[] b = Encoding.GetEncoding(28591).GetBytes("SharedKey:"); - server.SendDataAsync(clientIndex, b, b.Length, (x, y, z) => { }); - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Sent Shared Key Request to client at {0}", server.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex)); - } - else - { - OnServerClientReadyForCommunications(clientIndex); - } - if (HeartbeatRequired) + if (!ConnectedClientsIndexes.Contains(clientIndex)) + { + ConnectedClientsIndexes.Add(clientIndex); + } + if (SharedKeyRequired) + { + if (!WaitingForSharedKey.Contains(clientIndex)) { - if (!HeartbeatTimerDictionary.ContainsKey(clientIndex)) - { - HeartbeatTimerDictionary.Add(clientIndex, new CTimer(HeartbeatTimer_CallbackFunction, clientIndex, HeartbeatRequiredIntervalMs)); - } + WaitingForSharedKey.Add(clientIndex); } - - server.ReceiveDataAsync(clientIndex, TcpServerReceivedDataAsyncCallback); + byte[] b = Encoding.GetEncoding(28591).GetBytes("SharedKey:"); + server.SendDataAsync(clientIndex, b, b.Length, (x, y, z) => { }); + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Sent Shared Key Request to client at {0}", server.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex)); } - } - else - { - Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Client attempt faulty."); - if (!ServerStopped) + else { - server.WaitForConnectionAsync(IPAddress.Any, TcpConnectCallback); - return; + OnServerClientReadyForCommunications(clientIndex); } + if (HeartbeatRequired) + { + if (!HeartbeatTimerDictionary.ContainsKey(clientIndex)) + { + HeartbeatTimerDictionary.Add(clientIndex, new CTimer(HeartbeatTimer_CallbackFunction, clientIndex, HeartbeatRequiredIntervalMs)); + } + } + + server.ReceiveDataAsync(clientIndex, TcpServerReceivedDataAsyncCallback); } } - catch (Exception ex) + else { - Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error in Socket Status Connect Callback. Error: {0}", ex); + Debug.Console(1, this, Debug.ErrorLogLevel.Error, "Client attempt faulty."); + if (!ServerStopped) + { + server.WaitForConnectionAsync(IPAddress.Any, TcpConnectCallback); + return; + } } - //Debug.Console(1, this, Debug.ErrorLogLevel, "((((((Server State bitfield={0}; maxclient={1}; ServerStopped={2}))))))", - // server.State, - // MaxClients, - // ServerStopped); - if ((server.State & ServerState.SERVER_LISTENING) != ServerState.SERVER_LISTENING && MaxClients > 1 && !ServerStopped) - { - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Waiting for next connection"); - server.WaitForConnectionAsync(IPAddress.Any, TcpConnectCallback); + } + catch (Exception ex) + { + Debug.Console(2, this, Debug.ErrorLogLevel.Error, "Error in Socket Status Connect Callback. Error: {0}", ex); + } + //Debug.Console(1, this, Debug.ErrorLogLevel, "((((((Server State bitfield={0}; maxclient={1}; ServerStopped={2}))))))", + // server.State, + // MaxClients, + // ServerStopped); + if ((server.State & ServerState.SERVER_LISTENING) != ServerState.SERVER_LISTENING && MaxClients > 1 && !ServerStopped) + { + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Waiting for next connection"); + server.WaitForConnectionAsync(IPAddress.Any, TcpConnectCallback); - } } + } - #endregion + #endregion - #region Methods - Send/Receive Callbacks - /// - /// Secure Received Data Async Callback - /// - /// - /// - /// - void TcpServerReceivedDataAsyncCallback(TCPServer myTCPServer, uint clientIndex, int numberOfBytesReceived) - { + #region Methods - Send/Receive Callbacks + /// + /// Secure Received Data Async Callback + /// + /// + /// + /// + void TcpServerReceivedDataAsyncCallback(TCPServer myTCPServer, uint clientIndex, int numberOfBytesReceived) + { if (numberOfBytesReceived > 0) { string received = "Nothing"; @@ -831,181 +831,180 @@ void TcpServerReceivedDataAsyncCallback(TCPServer myTCPServer, uint clientIndex, myTCPServer.Disconnect(); } - } - - #endregion + } - #region Methods - EventHelpers/Callbacks + #endregion - //Private Helper method to call the Connection Change Event - void onConnectionChange(uint clientIndex, SocketStatus clientStatus) - { - if (clientIndex != 0) //0 is error not valid client change - { - var handler = ClientConnectionChange; - if (handler != null) - { - handler(this, new GenericTcpServerSocketStatusChangeEventArgs(myTcpServer, clientIndex, clientStatus)); - } - } - } + #region Methods - EventHelpers/Callbacks - //Private Helper method to call the Connection Change Event - void OnConnectionChange() + //Private Helper method to call the Connection Change Event + void onConnectionChange(uint clientIndex, SocketStatus clientStatus) + { + if (clientIndex != 0) //0 is error not valid client change { - if (ProgramIsStopping) - { - return; - } var handler = ClientConnectionChange; if (handler != null) { - handler(this, new GenericTcpServerSocketStatusChangeEventArgs()); + handler(this, new GenericTcpServerSocketStatusChangeEventArgs(myTcpServer, clientIndex, clientStatus)); } } + } - //Private Helper Method to call the Text Received Event - void onTextReceived(string text, uint clientIndex) + //Private Helper method to call the Connection Change Event + void OnConnectionChange() + { + if (ProgramIsStopping) { - var handler = TextReceived; - if (handler != null) - handler(this, new GenericTcpServerCommMethodReceiveTextArgs(text, clientIndex)); + return; } - - //Private Helper Method to call the Server State Change Event - void OnServerStateChange(ServerState state) + var handler = ClientConnectionChange; + if (handler != null) { - if (ProgramIsStopping) - { - return; - } - var handler = ServerStateChange; - if (handler != null) - { - handler(this, new GenericTcpServerStateChangedEventArgs(state)); - } + handler(this, new GenericTcpServerSocketStatusChangeEventArgs()); } + } + + //Private Helper Method to call the Text Received Event + void onTextReceived(string text, uint clientIndex) + { + var handler = TextReceived; + if (handler != null) + handler(this, new GenericTcpServerCommMethodReceiveTextArgs(text, clientIndex)); + } - /// - /// Private Event Handler method to handle the closing of connections when the program stops - /// - /// - void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + //Private Helper Method to call the Server State Change Event + void OnServerStateChange(ServerState state) + { + if (ProgramIsStopping) { - if (programEventType == eProgramStatusEventType.Stopping) - { - ProgramIsStopping = true; - // kill bandaid things - if (MonitorClientTimer != null) - MonitorClientTimer.Stop(); - if (MonitorClient != null) - MonitorClient.Disconnect(); - - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Program stopping. Closing server"); - KillServer(); - } + return; } - - //Private event handler method to raise the event that the server is ready to send data after a successful client shared key negotiation - void OnServerClientReadyForCommunications(uint clientIndex) + var handler = ServerStateChange; + if (handler != null) { - ClientReadyAfterKeyExchange.Add(clientIndex); - var handler = ServerClientReadyForCommunications; - if (handler != null) - handler(this, new GenericTcpServerSocketStatusChangeEventArgs( - this, clientIndex, myTcpServer.GetServerSocketStatusForSpecificClient(clientIndex))); + handler(this, new GenericTcpServerStateChangedEventArgs(state)); } - #endregion + } - #region Monitor Client - /// - /// Starts the monitor client cycle. Timed wait, then call RunMonitorClient - /// - void StartMonitorClient() + /// + /// Private Event Handler method to handle the closing of connections when the program stops + /// + /// + void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + { + if (programEventType == eProgramStatusEventType.Stopping) { + ProgramIsStopping = true; + // kill bandaid things if (MonitorClientTimer != null) - { - return; - } - MonitorClientTimer = new CTimer(o => RunMonitorClient(), 60000); + MonitorClientTimer.Stop(); + if (MonitorClient != null) + MonitorClient.Disconnect(); + + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Program stopping. Closing server"); + KillServer(); } + } - /// - /// - /// - void RunMonitorClient() + //Private event handler method to raise the event that the server is ready to send data after a successful client shared key negotiation + void OnServerClientReadyForCommunications(uint clientIndex) + { + ClientReadyAfterKeyExchange.Add(clientIndex); + var handler = ServerClientReadyForCommunications; + if (handler != null) + handler(this, new GenericTcpServerSocketStatusChangeEventArgs( + this, clientIndex, myTcpServer.GetServerSocketStatusForSpecificClient(clientIndex))); + } + #endregion + + #region Monitor Client + /// + /// Starts the monitor client cycle. Timed wait, then call RunMonitorClient + /// + void StartMonitorClient() + { + if (MonitorClientTimer != null) { - MonitorClient = new GenericTcpIpClient_ForServer(Key + "-MONITOR", "127.0.0.1", Port, 2000); - MonitorClient.SharedKeyRequired = this.SharedKeyRequired; - MonitorClient.SharedKey = this.SharedKey; - MonitorClient.ConnectionHasHungCallback = MonitorClientHasHungCallback; - //MonitorClient.ConnectionChange += MonitorClient_ConnectionChange; - MonitorClient.ClientReadyForCommunications += MonitorClient_IsReadyForComm; + return; + } + MonitorClientTimer = new CTimer(o => RunMonitorClient(), 60000); + } - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Starting monitor check"); + /// + /// + /// + void RunMonitorClient() + { + MonitorClient = new GenericTcpIpClient_ForServer(Key + "-MONITOR", "127.0.0.1", Port, 2000); + MonitorClient.SharedKeyRequired = this.SharedKeyRequired; + MonitorClient.SharedKey = this.SharedKey; + MonitorClient.ConnectionHasHungCallback = MonitorClientHasHungCallback; + //MonitorClient.ConnectionChange += MonitorClient_ConnectionChange; + MonitorClient.ClientReadyForCommunications += MonitorClient_IsReadyForComm; - MonitorClient.Connect(); - // From here MonitorCLient either connects or hangs, MonitorClient will call back + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Starting monitor check"); - } + MonitorClient.Connect(); + // From here MonitorCLient either connects or hangs, MonitorClient will call back - /// - /// - /// - void StopMonitorClient() - { - if (MonitorClient == null) - return; + } - MonitorClient.ClientReadyForCommunications -= MonitorClient_IsReadyForComm; - MonitorClient.Disconnect(); - MonitorClient = null; - } + /// + /// + /// + void StopMonitorClient() + { + if (MonitorClient == null) + return; - /// - /// On monitor connect, restart the operation - /// - void MonitorClient_IsReadyForComm(object sender, GenericTcpServerClientReadyForcommunicationsEventArgs args) - { - if (args.IsReady) - { - Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Monitor client connection success. Disconnecting in 2s"); - MonitorClientTimer.Stop(); - MonitorClientTimer = null; - MonitorClientFailureCount = 0; - CrestronEnvironment.Sleep(2000); - StopMonitorClient(); - StartMonitorClient(); - } - } + MonitorClient.ClientReadyForCommunications -= MonitorClient_IsReadyForComm; + MonitorClient.Disconnect(); + MonitorClient = null; + } - /// - /// If the client hangs, add to counter and maybe fire the choke event - /// - void MonitorClientHasHungCallback() + /// + /// On monitor connect, restart the operation + /// + void MonitorClient_IsReadyForComm(object sender, GenericTcpServerClientReadyForcommunicationsEventArgs args) + { + if (args.IsReady) { - MonitorClientFailureCount++; + Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Monitor client connection success. Disconnecting in 2s"); MonitorClientTimer.Stop(); MonitorClientTimer = null; + MonitorClientFailureCount = 0; + CrestronEnvironment.Sleep(2000); StopMonitorClient(); - if (MonitorClientFailureCount < MonitorClientMaxFailureCount) - { - Debug.Console(2, this, Debug.ErrorLogLevel.Warning, "Monitor client connection has hung {0} time{1}, maximum {2}", - MonitorClientFailureCount, MonitorClientFailureCount > 1 ? "s" : "", MonitorClientMaxFailureCount); - StartMonitorClient(); - } - else - { - Debug.Console(2, this, Debug.ErrorLogLevel.Error, - "\r***************************\rMonitor client connection has hung a maximum of {0} times.\r***************************", - MonitorClientMaxFailureCount); - - var handler = ServerHasChoked; - if (handler != null) - handler(); - // Some external thing is in charge here. Expected reset of program - } + StartMonitorClient(); + } + } + + /// + /// If the client hangs, add to counter and maybe fire the choke event + /// + void MonitorClientHasHungCallback() + { + MonitorClientFailureCount++; + MonitorClientTimer.Stop(); + MonitorClientTimer = null; + StopMonitorClient(); + if (MonitorClientFailureCount < MonitorClientMaxFailureCount) + { + Debug.Console(2, this, Debug.ErrorLogLevel.Warning, "Monitor client connection has hung {0} time{1}, maximum {2}", + MonitorClientFailureCount, MonitorClientFailureCount > 1 ? "s" : "", MonitorClientMaxFailureCount); + StartMonitorClient(); + } + else + { + Debug.Console(2, this, Debug.ErrorLogLevel.Error, + "\r***************************\rMonitor client connection has hung a maximum of {0} times.\r***************************", + MonitorClientMaxFailureCount); + + var handler = ServerHasChoked; + if (handler != null) + handler(); + // Some external thing is in charge here. Expected reset of program } - #endregion } + #endregion } \ No newline at end of file diff --git a/src/PepperDash.Core/Comm/GenericUdpServer.cs b/src/PepperDash.Core/Comm/GenericUdpServer.cs index a5a68c45e..377b9cbe5 100644 --- a/src/PepperDash.Core/Comm/GenericUdpServer.cs +++ b/src/PepperDash.Core/Comm/GenericUdpServer.cs @@ -8,347 +8,347 @@ using Newtonsoft.Json; using PepperDash.Core.Logging; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// Generic UDP Server device +/// +public class GenericUdpServer : Device, ISocketStatusWithStreamDebugging { + private const string SplusKey = "Uninitialized Udp Server"; /// - /// Generic UDP Server device + /// Object to enable stream debugging + /// + public CommunicationStreamDebugging StreamDebugging { get; private set; } + /// + /// + /// + public event EventHandler BytesReceived; + + /// + /// + /// + public event EventHandler TextReceived; + + /// + /// This event will fire when a message is dequeued that includes the source IP and Port info if needed to determine the source of the received data. /// - public class GenericUdpServer : Device, ISocketStatusWithStreamDebugging - { - private const string SplusKey = "Uninitialized Udp Server"; - /// - /// Object to enable stream debugging - /// - public CommunicationStreamDebugging StreamDebugging { get; private set; } - /// - /// - /// - public event EventHandler BytesReceived; - - /// - /// - /// - public event EventHandler TextReceived; - - /// - /// This event will fire when a message is dequeued that includes the source IP and Port info if needed to determine the source of the received data. - /// public event EventHandler DataRecievedExtra; - /// - /// - /// - public event EventHandler ConnectionChange; + /// + /// + /// + public event EventHandler ConnectionChange; - /// - /// - /// - public event EventHandler UpdateConnectionStatus; + /// + /// + /// + public event EventHandler UpdateConnectionStatus; - /// - /// - /// - public SocketStatus ClientStatus + /// + /// + /// + public SocketStatus ClientStatus + { + get { - get - { - return Server.ServerStatus; - } + return Server.ServerStatus; } + } - /// - /// - /// - public ushort UStatus - { - get { return (ushort)Server.ServerStatus; } - } + /// + /// + /// + public ushort UStatus + { + get { return (ushort)Server.ServerStatus; } + } - /// - /// Address of server - /// - public string Hostname { get; set; } + /// + /// Address of server + /// + public string Hostname { get; set; } - /// - /// Port on server - /// - public int Port { get; set; } + /// + /// Port on server + /// + public int Port { get; set; } - /// - /// Another damn S+ helper because S+ seems to treat large port nums as signed ints - /// which screws up things - /// - public ushort UPort - { - get { return Convert.ToUInt16(Port); } - set { Port = Convert.ToInt32(value); } - } + /// + /// Another damn S+ helper because S+ seems to treat large port nums as signed ints + /// which screws up things + /// + public ushort UPort + { + get { return Convert.ToUInt16(Port); } + set { Port = Convert.ToInt32(value); } + } - /// - /// Indicates that the UDP Server is enabled - /// - public bool IsConnected - { - get; - private set; - } + /// + /// Indicates that the UDP Server is enabled + /// + public bool IsConnected + { + get; + private set; + } - /// - /// Numeric value indicating - /// - public ushort UIsConnected - { - get { return IsConnected ? (ushort)1 : (ushort)0; } - } + /// + /// Numeric value indicating + /// + public ushort UIsConnected + { + get { return IsConnected ? (ushort)1 : (ushort)0; } + } - /// - /// Defaults to 2000 - /// - public int BufferSize { get; set; } - - /// - /// The server - /// - public UDPServer Server { get; private set; } - - /// - /// Constructor for S+. Make sure to set key, address, port, and buffersize using init method - /// - public GenericUdpServer() - : base(SplusKey) - { - StreamDebugging = new CommunicationStreamDebugging(SplusKey); - BufferSize = 5000; + /// + /// Defaults to 2000 + /// + public int BufferSize { get; set; } - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler); - } - - /// - /// - /// - /// - /// - /// - /// - public GenericUdpServer(string key, string address, int port, int buffefSize) - : base(key) - { - StreamDebugging = new CommunicationStreamDebugging(key); - Hostname = address; - Port = port; - BufferSize = buffefSize; + /// + /// The server + /// + public UDPServer Server { get; private set; } - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler); - } + /// + /// Constructor for S+. Make sure to set key, address, port, and buffersize using init method + /// + public GenericUdpServer() + : base(SplusKey) + { + StreamDebugging = new CommunicationStreamDebugging(SplusKey); + BufferSize = 5000; - /// - /// Call from S+ to initialize values - /// - /// - /// - /// - public void Initialize(string key, string address, ushort port) + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler); + } + + /// + /// + /// + /// + /// + /// + /// + public GenericUdpServer(string key, string address, int port, int buffefSize) + : base(key) + { + StreamDebugging = new CommunicationStreamDebugging(key); + Hostname = address; + Port = port; + BufferSize = buffefSize; + + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler); + } + + /// + /// Call from S+ to initialize values + /// + /// + /// + /// + public void Initialize(string key, string address, ushort port) + { + Key = key; + Hostname = address; + UPort = port; + } + + /// + /// + /// + /// + void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs ethernetEventArgs) + { + // Re-enable the server if the link comes back up and the status should be connected + if (ethernetEventArgs.EthernetEventType == eEthernetEventType.LinkUp + && IsConnected) { - Key = key; - Hostname = address; - UPort = port; + Connect(); } + } - /// - /// - /// - /// - void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs ethernetEventArgs) + /// + /// + /// + /// + void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + { + if (programEventType != eProgramStatusEventType.Stopping) + return; + + Debug.Console(1, this, "Program stopping. Disabling Server"); + Disconnect(); + } + + /// + /// Enables the UDP Server + /// + public void Connect() + { + if (Server == null) { - // Re-enable the server if the link comes back up and the status should be connected - if (ethernetEventArgs.EthernetEventType == eEthernetEventType.LinkUp - && IsConnected) - { - Connect(); - } + Server = new UDPServer(); } - /// - /// - /// - /// - void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + if (string.IsNullOrEmpty(Hostname)) { - if (programEventType != eProgramStatusEventType.Stopping) - return; - - Debug.Console(1, this, "Program stopping. Disabling Server"); - Disconnect(); + Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericUdpServer '{0}': No address set", Key); + return; } - - /// - /// Enables the UDP Server - /// - public void Connect() + if (Port < 1 || Port > 65535) { - if (Server == null) { - Server = new UDPServer(); - } - - if (string.IsNullOrEmpty(Hostname)) - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericUdpServer '{0}': No address set", Key); + Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericUdpServer '{0}': Invalid port", Key); return; } - if (Port < 1 || Port > 65535) - { - { - Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericUdpServer '{0}': Invalid port", Key); - return; - } - } + } - var status = Server.EnableUDPServer(Hostname, Port); + var status = Server.EnableUDPServer(Hostname, Port); - Debug.Console(2, this, "SocketErrorCode: {0}", status); - if (status == SocketErrorCodes.SOCKET_OK) - IsConnected = true; + Debug.Console(2, this, "SocketErrorCode: {0}", status); + if (status == SocketErrorCodes.SOCKET_OK) + IsConnected = true; - var handler = UpdateConnectionStatus; - if (handler != null) - handler(this, new GenericUdpConnectedEventArgs(UIsConnected)); + var handler = UpdateConnectionStatus; + if (handler != null) + handler(this, new GenericUdpConnectedEventArgs(UIsConnected)); - // Start receiving data - Server.ReceiveDataAsync(Receive); - } + // Start receiving data + Server.ReceiveDataAsync(Receive); + } - /// - /// Disabled the UDP Server - /// - public void Disconnect() - { - if(Server != null) - Server.DisableUDPServer(); + /// + /// Disabled the UDP Server + /// + public void Disconnect() + { + if(Server != null) + Server.DisableUDPServer(); - IsConnected = false; + IsConnected = false; - var handler = UpdateConnectionStatus; - if (handler != null) - handler(this, new GenericUdpConnectedEventArgs(UIsConnected)); - } + var handler = UpdateConnectionStatus; + if (handler != null) + handler(this, new GenericUdpConnectedEventArgs(UIsConnected)); + } - /// - /// Recursive method to receive data - /// - /// - /// - void Receive(UDPServer server, int numBytes) - { - Debug.Console(2, this, "Received {0} bytes", numBytes); + /// + /// Recursive method to receive data + /// + /// + /// + void Receive(UDPServer server, int numBytes) + { + Debug.Console(2, this, "Received {0} bytes", numBytes); - try - { - if (numBytes <= 0) - return; + try + { + if (numBytes <= 0) + return; - var sourceIp = Server.IPAddressLastMessageReceivedFrom; - var sourcePort = Server.IPPortLastMessageReceivedFrom; - var bytes = server.IncomingDataBuffer.Take(numBytes).ToArray(); - var str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); + var sourceIp = Server.IPAddressLastMessageReceivedFrom; + var sourcePort = Server.IPPortLastMessageReceivedFrom; + var bytes = server.IncomingDataBuffer.Take(numBytes).ToArray(); + var str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); - var dataRecivedExtra = DataRecievedExtra; - if (dataRecivedExtra != null) - dataRecivedExtra(this, new GenericUdpReceiveTextExtraArgs(str, sourceIp, sourcePort, bytes)); + var dataRecivedExtra = DataRecievedExtra; + if (dataRecivedExtra != null) + dataRecivedExtra(this, new GenericUdpReceiveTextExtraArgs(str, sourceIp, sourcePort, bytes)); - Debug.Console(2, this, "Bytes: {0}", bytes.ToString()); - var bytesHandler = BytesReceived; - if (bytesHandler != null) - { - if (StreamDebugging.RxStreamDebuggingIsEnabled) - { - Debug.Console(0, this, "Received {1} bytes: '{0}'", ComTextHelper.GetEscapedText(bytes), bytes.Length); - } - bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); - } - var textHandler = TextReceived; - if (textHandler != null) + Debug.Console(2, this, "Bytes: {0}", bytes.ToString()); + var bytesHandler = BytesReceived; + if (bytesHandler != null) + { + if (StreamDebugging.RxStreamDebuggingIsEnabled) { - if (StreamDebugging.RxStreamDebuggingIsEnabled) - Debug.Console(0, this, "Received {1} characters of text: '{0}'", ComTextHelper.GetDebugText(str), str.Length); - textHandler(this, new GenericCommMethodReceiveTextArgs(str)); + Debug.Console(0, this, "Received {1} bytes: '{0}'", ComTextHelper.GetEscapedText(bytes), bytes.Length); } + bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); } - catch (Exception ex) - { - this.LogException(ex, "GenericUdpServer Receive error"); - } - finally + var textHandler = TextReceived; + if (textHandler != null) { - server.ReceiveDataAsync(Receive); + if (StreamDebugging.RxStreamDebuggingIsEnabled) + Debug.Console(0, this, "Received {1} characters of text: '{0}'", ComTextHelper.GetDebugText(str), str.Length); + textHandler(this, new GenericCommMethodReceiveTextArgs(str)); } } - - /// - /// General send method - /// - /// - public void SendText(string text) + catch (Exception ex) { - var bytes = Encoding.GetEncoding(28591).GetBytes(text); - - if (IsConnected && Server != null) - { - if (StreamDebugging.TxStreamDebuggingIsEnabled) - Debug.Console(0, this, "Sending {0} characters of text: '{1}'", text.Length, ComTextHelper.GetDebugText(text)); - - Server.SendData(bytes, bytes.Length); - } + this.LogException(ex, "GenericUdpServer Receive error"); + } + finally + { + server.ReceiveDataAsync(Receive); } + } - /// - /// - /// - /// - public void SendBytes(byte[] bytes) + /// + /// General send method + /// + /// + public void SendText(string text) + { + var bytes = Encoding.GetEncoding(28591).GetBytes(text); + + if (IsConnected && Server != null) { if (StreamDebugging.TxStreamDebuggingIsEnabled) - Debug.Console(0, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); + Debug.Console(0, this, "Sending {0} characters of text: '{1}'", text.Length, ComTextHelper.GetDebugText(text)); - if (IsConnected && Server != null) - Server.SendData(bytes, bytes.Length); + Server.SendData(bytes, bytes.Length); } - } /// /// /// + /// + public void SendBytes(byte[] bytes) + { + if (StreamDebugging.TxStreamDebuggingIsEnabled) + Debug.Console(0, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); + + if (IsConnected && Server != null) + Server.SendData(bytes, bytes.Length); + } + +} + +/// +/// +/// public class GenericUdpReceiveTextExtraArgs : EventArgs { - /// - /// - /// + /// + /// + /// public string Text { get; private set; } - /// - /// - /// + /// + /// + /// public string IpAddress { get; private set; } - /// - /// - /// + /// + /// + /// public int Port { get; private set; } - /// - /// - /// + /// + /// + /// public byte[] Bytes { get; private set; } - /// - /// - /// - /// - /// - /// - /// + /// + /// + /// + /// + /// + /// + /// public GenericUdpReceiveTextExtraArgs(string text, string ipAddress, int port, byte[] bytes) { Text = text; @@ -363,34 +363,33 @@ public GenericUdpReceiveTextExtraArgs(string text, string ipAddress, int port, b public GenericUdpReceiveTextExtraArgs() { } } +/// +/// +/// +public class UdpServerPropertiesConfig +{ /// /// /// - public class UdpServerPropertiesConfig + [JsonProperty(Required = Required.Always)] + public string Address { get; set; } + + /// + /// + /// + [JsonProperty(Required = Required.Always)] + public int Port { get; set; } + + /// + /// Defaults to 32768 + /// + public int BufferSize { get; set; } + + /// + /// + /// + public UdpServerPropertiesConfig() { - /// - /// - /// - [JsonProperty(Required = Required.Always)] - public string Address { get; set; } - - /// - /// - /// - [JsonProperty(Required = Required.Always)] - public int Port { get; set; } - - /// - /// Defaults to 32768 - /// - public int BufferSize { get; set; } - - /// - /// - /// - public UdpServerPropertiesConfig() - { - BufferSize = 32768; - } + BufferSize = 32768; } } \ No newline at end of file diff --git a/src/PepperDash.Core/Comm/TcpClientConfigObject.cs b/src/PepperDash.Core/Comm/TcpClientConfigObject.cs index c3b3bcec6..a43829385 100644 --- a/src/PepperDash.Core/Comm/TcpClientConfigObject.cs +++ b/src/PepperDash.Core/Comm/TcpClientConfigObject.cs @@ -1,59 +1,58 @@ using Newtonsoft.Json; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// Client config object for TCP client with server that inherits from TcpSshPropertiesConfig and adds properties for shared key and heartbeat +/// +public class TcpClientConfigObject { /// - /// Client config object for TCP client with server that inherits from TcpSshPropertiesConfig and adds properties for shared key and heartbeat - /// - public class TcpClientConfigObject - { - /// - /// TcpSsh Properties - /// - [JsonProperty("control")] - public ControlPropertiesConfig Control { get; set; } - - /// - /// Bool value for secure. Currently not implemented in TCP sockets as they are not dynamic - /// - [JsonProperty("secure")] - public bool Secure { get; set; } - - /// - /// Require a shared key that both server and client negotiate. If negotiation fails server disconnects the client - /// - [JsonProperty("sharedKeyRequired")] - public bool SharedKeyRequired { get; set; } - - /// - /// The shared key that must match on the server and client - /// - [JsonProperty("sharedKey")] - public string SharedKey { get; set; } - - /// - /// Require a heartbeat on the client/server connection that will cause the server/client to disconnect if the heartbeat is not received. - /// heartbeats do not raise received events. - /// - [JsonProperty("heartbeatRequired")] - public bool HeartbeatRequired { get; set; } - - /// - /// The interval in seconds for the heartbeat from the client. If not received client is disconnected - /// - [JsonProperty("heartbeatRequiredIntervalInSeconds")] - public ushort HeartbeatRequiredIntervalInSeconds { get; set; } - - /// - /// HeartbeatString that will be checked against the message received. defaults to heartbeat if no string is provided. - /// - [JsonProperty("heartbeatStringToMatch")] - public string HeartbeatStringToMatch { get; set; } - - /// - /// Receive Queue size must be greater than 20 or defaults to 20 - /// - [JsonProperty("receiveQueueSize")] - public int ReceiveQueueSize { get; set; } - } + /// TcpSsh Properties + /// + [JsonProperty("control")] + public ControlPropertiesConfig Control { get; set; } + + /// + /// Bool value for secure. Currently not implemented in TCP sockets as they are not dynamic + /// + [JsonProperty("secure")] + public bool Secure { get; set; } + + /// + /// Require a shared key that both server and client negotiate. If negotiation fails server disconnects the client + /// + [JsonProperty("sharedKeyRequired")] + public bool SharedKeyRequired { get; set; } + + /// + /// The shared key that must match on the server and client + /// + [JsonProperty("sharedKey")] + public string SharedKey { get; set; } + + /// + /// Require a heartbeat on the client/server connection that will cause the server/client to disconnect if the heartbeat is not received. + /// heartbeats do not raise received events. + /// + [JsonProperty("heartbeatRequired")] + public bool HeartbeatRequired { get; set; } + + /// + /// The interval in seconds for the heartbeat from the client. If not received client is disconnected + /// + [JsonProperty("heartbeatRequiredIntervalInSeconds")] + public ushort HeartbeatRequiredIntervalInSeconds { get; set; } + + /// + /// HeartbeatString that will be checked against the message received. defaults to heartbeat if no string is provided. + /// + [JsonProperty("heartbeatStringToMatch")] + public string HeartbeatStringToMatch { get; set; } + + /// + /// Receive Queue size must be greater than 20 or defaults to 20 + /// + [JsonProperty("receiveQueueSize")] + public int ReceiveQueueSize { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Core/Comm/TcpServerConfigObject.cs b/src/PepperDash.Core/Comm/TcpServerConfigObject.cs index 043cf58d6..b60f486f6 100644 --- a/src/PepperDash.Core/Comm/TcpServerConfigObject.cs +++ b/src/PepperDash.Core/Comm/TcpServerConfigObject.cs @@ -4,57 +4,56 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// Tcp Server Config object with properties for a tcp server with shared key and heartbeat capabilities +/// +public class TcpServerConfigObject { /// - /// Tcp Server Config object with properties for a tcp server with shared key and heartbeat capabilities - /// - public class TcpServerConfigObject - { - /// - /// Uique key - /// - public string Key { get; set; } - /// - /// Max Clients that the server will allow to connect. - /// - public ushort MaxClients { get; set; } - /// - /// Bool value for secure. Currently not implemented in TCP sockets as they are not dynamic - /// - public bool Secure { get; set; } - /// - /// Port for the server to listen on - /// - public int Port { get; set; } - /// - /// Require a shared key that both server and client negotiate. If negotiation fails server disconnects the client - /// - public bool SharedKeyRequired { get; set; } - /// - /// The shared key that must match on the server and client - /// - public string SharedKey { get; set; } - /// - /// Require a heartbeat on the client/server connection that will cause the server/client to disconnect if the heartbeat is not received. - /// heartbeats do not raise received events. - /// - public bool HeartbeatRequired { get; set; } - /// - /// The interval in seconds for the heartbeat from the client. If not received client is disconnected - /// - public ushort HeartbeatRequiredIntervalInSeconds { get; set; } - /// - /// HeartbeatString that will be checked against the message received. defaults to heartbeat if no string is provided. - /// - public string HeartbeatStringToMatch { get; set; } - /// - /// Client buffer size. See Crestron help. defaults to 2000 if not greater than 2000 - /// - public int BufferSize { get; set; } - /// - /// Receive Queue size must be greater than 20 or defaults to 20 - /// - public int ReceiveQueueSize { get; set; } - } + /// Uique key + /// + public string Key { get; set; } + /// + /// Max Clients that the server will allow to connect. + /// + public ushort MaxClients { get; set; } + /// + /// Bool value for secure. Currently not implemented in TCP sockets as they are not dynamic + /// + public bool Secure { get; set; } + /// + /// Port for the server to listen on + /// + public int Port { get; set; } + /// + /// Require a shared key that both server and client negotiate. If negotiation fails server disconnects the client + /// + public bool SharedKeyRequired { get; set; } + /// + /// The shared key that must match on the server and client + /// + public string SharedKey { get; set; } + /// + /// Require a heartbeat on the client/server connection that will cause the server/client to disconnect if the heartbeat is not received. + /// heartbeats do not raise received events. + /// + public bool HeartbeatRequired { get; set; } + /// + /// The interval in seconds for the heartbeat from the client. If not received client is disconnected + /// + public ushort HeartbeatRequiredIntervalInSeconds { get; set; } + /// + /// HeartbeatString that will be checked against the message received. defaults to heartbeat if no string is provided. + /// + public string HeartbeatStringToMatch { get; set; } + /// + /// Client buffer size. See Crestron help. defaults to 2000 if not greater than 2000 + /// + public int BufferSize { get; set; } + /// + /// Receive Queue size must be greater than 20 or defaults to 20 + /// + public int ReceiveQueueSize { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Core/Comm/eControlMethods.cs b/src/PepperDash.Core/Comm/eControlMethods.cs index 28a95b122..bdf6d79e1 100644 --- a/src/PepperDash.Core/Comm/eControlMethods.cs +++ b/src/PepperDash.Core/Comm/eControlMethods.cs @@ -4,76 +4,75 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// Crestron Control Methods for a comm object +/// +public enum eControlMethod { /// - /// Crestron Control Methods for a comm object - /// - public enum eControlMethod - { - /// - /// - /// - None = 0, - /// - /// RS232/422/485 - /// - Com, - /// - /// Crestron IpId (most Crestron ethernet devices) - /// - IpId, - /// - /// Crestron IpIdTcp (HD-MD series, etc.) - /// - IpidTcp, - /// - /// Crestron IR control - /// - IR, - /// - /// SSH client - /// - Ssh, - /// - /// TCP/IP client - /// - Tcpip, - /// - /// Telnet - /// - Telnet, - /// - /// Crestnet device - /// - Cresnet, - /// - /// CEC Control, via a DM HDMI port - /// - Cec, - /// - /// UDP Server - /// - Udp, - /// - /// HTTP client - /// - Http, - /// - /// HTTPS client - /// - Https, - /// - /// Websocket client - /// - Ws, - /// - /// Secure Websocket client - /// - Wss, - /// - /// Secure TCP/IP - /// - SecureTcpIp - } + /// + /// + None = 0, + /// + /// RS232/422/485 + /// + Com, + /// + /// Crestron IpId (most Crestron ethernet devices) + /// + IpId, + /// + /// Crestron IpIdTcp (HD-MD series, etc.) + /// + IpidTcp, + /// + /// Crestron IR control + /// + IR, + /// + /// SSH client + /// + Ssh, + /// + /// TCP/IP client + /// + Tcpip, + /// + /// Telnet + /// + Telnet, + /// + /// Crestnet device + /// + Cresnet, + /// + /// CEC Control, via a DM HDMI port + /// + Cec, + /// + /// UDP Server + /// + Udp, + /// + /// HTTP client + /// + Http, + /// + /// HTTPS client + /// + Https, + /// + /// Websocket client + /// + Ws, + /// + /// Secure Websocket client + /// + Wss, + /// + /// Secure TCP/IP + /// + SecureTcpIp } \ No newline at end of file diff --git a/src/PepperDash.Core/CommunicationExtras.cs b/src/PepperDash.Core/CommunicationExtras.cs index 81fd76c5d..f17e1da0a 100644 --- a/src/PepperDash.Core/CommunicationExtras.cs +++ b/src/PepperDash.Core/CommunicationExtras.cs @@ -7,74 +7,74 @@ using System.Text.RegularExpressions; using Newtonsoft.Json; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// An incoming communication stream +/// +public interface ICommunicationReceiver : IKeyed { /// - /// An incoming communication stream + /// Notifies of bytes received /// - public interface ICommunicationReceiver : IKeyed - { - /// - /// Notifies of bytes received - /// - event EventHandler BytesReceived; - /// - /// Notifies of text received - /// - event EventHandler TextReceived; - - /// - /// Indicates connection status - /// - [JsonProperty("isConnected")] - bool IsConnected { get; } - /// - /// Connect to the device - /// - void Connect(); - /// - /// Disconnect from the device - /// - void Disconnect(); - } + event EventHandler BytesReceived; + /// + /// Notifies of text received + /// + event EventHandler TextReceived; + + /// + /// Indicates connection status + /// + [JsonProperty("isConnected")] + bool IsConnected { get; } + /// + /// Connect to the device + /// + void Connect(); + /// + /// Disconnect from the device + /// + void Disconnect(); +} /// /// Represents a device that uses basic connection /// - public interface IBasicCommunication : ICommunicationReceiver +public interface IBasicCommunication : ICommunicationReceiver { - /// - /// Send text to the device - /// - /// + /// + /// Send text to the device + /// + /// void SendText(string text); - /// - /// Send bytes to the device - /// - /// + /// + /// Send bytes to the device + /// + /// void SendBytes(byte[] bytes); } - /// - /// Represents a device that implements IBasicCommunication and IStreamDebugging - /// - public interface IBasicCommunicationWithStreamDebugging : IBasicCommunication, IStreamDebugging - { +/// +/// Represents a device that implements IBasicCommunication and IStreamDebugging +/// +public interface IBasicCommunicationWithStreamDebugging : IBasicCommunication, IStreamDebugging +{ - } +} +/// +/// Represents a device with stream debugging capablities +/// +public interface IStreamDebugging +{ /// - /// Represents a device with stream debugging capablities + /// Object to enable stream debugging /// - public interface IStreamDebugging - { - /// - /// Object to enable stream debugging - /// - [JsonProperty("streamDebugging")] - CommunicationStreamDebugging StreamDebugging { get; } - } + [JsonProperty("streamDebugging")] + CommunicationStreamDebugging StreamDebugging { get; } +} /// /// For IBasicCommunication classes that have SocketStatus. GenericSshClient, @@ -82,41 +82,41 @@ public interface IStreamDebugging /// public interface ISocketStatus : IBasicCommunication { - /// - /// Notifies of socket status changes - /// + /// + /// Notifies of socket status changes + /// event EventHandler ConnectionChange; - /// - /// The current socket status of the client - /// - [JsonProperty("clientStatus")] - [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] - SocketStatus ClientStatus { get; } - } - /// - /// Describes a device that implements ISocketStatus and IStreamDebugging + /// The current socket status of the client /// - public interface ISocketStatusWithStreamDebugging : ISocketStatus, IStreamDebugging - { + [JsonProperty("clientStatus")] + [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + SocketStatus ClientStatus { get; } + } - } +/// +/// Describes a device that implements ISocketStatus and IStreamDebugging +/// +public interface ISocketStatusWithStreamDebugging : ISocketStatus, IStreamDebugging +{ - /// - /// Describes a device that can automatically attempt to reconnect - /// +} + +/// +/// Describes a device that can automatically attempt to reconnect +/// public interface IAutoReconnect { - /// - /// Enable automatic recconnect - /// - [JsonProperty("autoReconnect")] + /// + /// Enable automatic recconnect + /// + [JsonProperty("autoReconnect")] bool AutoReconnect { get; set; } - /// - /// Interval in ms to attempt automatic recconnections - /// - [JsonProperty("autoReconnectIntervalMs")] + /// + /// Interval in ms to attempt automatic recconnections + /// + [JsonProperty("autoReconnectIntervalMs")] int AutoReconnectIntervalMs { get; set; } } @@ -125,14 +125,14 @@ public interface IAutoReconnect /// public enum eGenericCommMethodStatusChangeType { - /// - /// Connected - /// + /// + /// Connected + /// Connected, - /// - /// Disconnected - /// - Disconnected + /// + /// Disconnected + /// + Disconnected } /// @@ -147,15 +147,15 @@ public enum eGenericCommMethodStatusChangeType /// public class GenericCommMethodReceiveBytesArgs : EventArgs { - /// - /// - /// + /// + /// + /// public byte[] Bytes { get; private set; } - /// - /// - /// - /// + /// + /// + /// + /// public GenericCommMethodReceiveBytesArgs(byte[] bytes) { Bytes = bytes; @@ -172,33 +172,33 @@ public GenericCommMethodReceiveBytesArgs() { } /// public class GenericCommMethodReceiveTextArgs : EventArgs { - /// - /// - /// + /// + /// + /// public string Text { get; private set; } - /// - /// - /// - public string Delimiter { get; private set; } - /// - /// - /// - /// + /// + /// + /// + public string Delimiter { get; private set; } + /// + /// + /// + /// public GenericCommMethodReceiveTextArgs(string text) { Text = text; } - /// - /// - /// - /// - /// - public GenericCommMethodReceiveTextArgs(string text, string delimiter) - :this(text) - { - Delimiter = delimiter; - } + /// + /// + /// + /// + /// + public GenericCommMethodReceiveTextArgs(string text, string delimiter) + :this(text) + { + Delimiter = delimiter; + } /// /// S+ Constructor @@ -213,35 +213,34 @@ public GenericCommMethodReceiveTextArgs() { } /// public class ComTextHelper { - /// - /// Gets escaped text for a byte array - /// - /// - /// + /// + /// Gets escaped text for a byte array + /// + /// + /// public static string GetEscapedText(byte[] bytes) { return String.Concat(bytes.Select(b => string.Format(@"[{0:X2}]", (int)b)).ToArray()); } - /// - /// Gets escaped text for a string - /// - /// - /// + /// + /// Gets escaped text for a string + /// + /// + /// public static string GetEscapedText(string text) { var bytes = Encoding.GetEncoding(28591).GetBytes(text); return String.Concat(bytes.Select(b => string.Format(@"[{0:X2}]", (int)b)).ToArray()); } - /// - /// Gets debug text for a string - /// - /// - /// - public static string GetDebugText(string text) - { - return Regex.Replace(text, @"[^\u0020-\u007E]", a => GetEscapedText(a.Value)); - } - } -} \ No newline at end of file + /// + /// Gets debug text for a string + /// + /// + /// + public static string GetDebugText(string text) + { + return Regex.Replace(text, @"[^\u0020-\u007E]", a => GetEscapedText(a.Value)); + } + } \ No newline at end of file diff --git a/src/PepperDash.Core/Config/PortalConfigReader.cs b/src/PepperDash.Core/Config/PortalConfigReader.cs index 43e9ea1e4..3094e5df0 100644 --- a/src/PepperDash.Core/Config/PortalConfigReader.cs +++ b/src/PepperDash.Core/Config/PortalConfigReader.cs @@ -7,11 +7,11 @@ using PepperDash.Core; using Serilog.Events; -namespace PepperDash.Core.Config -{ - /// - /// Reads a Portal formatted config file - /// +namespace PepperDash.Core.Config; + +/// +/// Reads a Portal formatted config file +/// public class PortalConfigReader { /// @@ -100,31 +100,31 @@ public static JObject MergeConfigs(JObject doubleConfig) Merge(template["destinationLists"], system["destinationLists"], "destinationLists")); - if (system["cameraLists"] == null) - merged.Add("cameraLists", template["cameraLists"]); - else - merged.Add("cameraLists", Merge(template["cameraLists"], system["cameraLists"], "cameraLists")); + if (system["cameraLists"] == null) + merged.Add("cameraLists", template["cameraLists"]); + else + merged.Add("cameraLists", Merge(template["cameraLists"], system["cameraLists"], "cameraLists")); - if (system["audioControlPointLists"] == null) - merged.Add("audioControlPointLists", template["audioControlPointLists"]); - else - merged.Add("audioControlPointLists", - Merge(template["audioControlPointLists"], system["audioControlPointLists"], "audioControlPointLists")); + if (system["audioControlPointLists"] == null) + merged.Add("audioControlPointLists", template["audioControlPointLists"]); + else + merged.Add("audioControlPointLists", + Merge(template["audioControlPointLists"], system["audioControlPointLists"], "audioControlPointLists")); - // Template tie lines take precedence. Config tool doesn't do them at system - // level anyway... - if (template["tieLines"] != null) + // Template tie lines take precedence. Config tool doesn't do them at system + // level anyway... + if (template["tieLines"] != null) merged.Add("tieLines", template["tieLines"]); else if (system["tieLines"] != null) merged.Add("tieLines", system["tieLines"]); else merged.Add("tieLines", new JArray()); - if (template["joinMaps"] != null) - merged.Add("joinMaps", template["joinMaps"]); - else - merged.Add("joinMaps", new JObject()); + if (template["joinMaps"] != null) + merged.Add("joinMaps", template["joinMaps"]); + else + merged.Add("joinMaps", new JObject()); if (system["global"] != null) merged.Add("global", Merge(template["global"], system["global"], "global")); @@ -147,26 +147,26 @@ static JArray MergeArraysOnTopLevelProperty(JArray a1, JArray a2, string propert return a1; else if (a1 != null) { - if (a2[0]["key"] == null) // If the first item in the system array has no key, overwrite the template array - { // with the system array - return a2; - } - else // The arrays are keyed, merge them by key + if (a2[0]["key"] == null) // If the first item in the system array has no key, overwrite the template array + { // with the system array + return a2; + } + else // The arrays are keyed, merge them by key + { + for (int i = 0; i < a1.Count(); i++) { - for (int i = 0; i < a1.Count(); i++) + var a1Dev = a1[i]; + // Try to get a system device and if found, merge it onto template + var a2Match = a2.FirstOrDefault(t => t[propertyName].Equals(a1Dev[propertyName]));// t.Value("uid") == tmplDev.Value("uid")); + if (a2Match != null) { - var a1Dev = a1[i]; - // Try to get a system device and if found, merge it onto template - var a2Match = a2.FirstOrDefault(t => t[propertyName].Equals(a1Dev[propertyName]));// t.Value("uid") == tmplDev.Value("uid")); - if (a2Match != null) - { - var mergedItem = Merge(a1Dev, a2Match, string.Format("{0}[{1}].", path, i));// Merge(JObject.FromObject(a1Dev), JObject.FromObject(a2Match)); - result.Add(mergedItem); - } - else - result.Add(a1Dev); + var mergedItem = Merge(a1Dev, a2Match, string.Format("{0}[{1}].", path, i));// Merge(JObject.FromObject(a1Dev), JObject.FromObject(a2Match)); + result.Add(mergedItem); } + else + result.Add(a1Dev); } + } } return result; } @@ -183,9 +183,9 @@ static JObject Merge(JToken t1, JToken t2, string path) /// /// Merge o2 onto o1 /// - /// - /// - /// + /// + /// + /// static JObject Merge(JObject o1, JObject o2, string path) { foreach (var o2Prop in o2) @@ -231,5 +231,4 @@ static JObject Merge(JObject o1, JObject o2, string path) } return o1; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/Conversion/Convert.cs b/src/PepperDash.Core/Conversion/Convert.cs index 2bafdcb06..13ef72636 100644 --- a/src/PepperDash.Core/Conversion/Convert.cs +++ b/src/PepperDash.Core/Conversion/Convert.cs @@ -4,19 +4,18 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Core +namespace PepperDash.Core; + +public class EncodingHelper { - public class EncodingHelper + public static string ConvertUtf8ToAscii(string utf8String) { - public static string ConvertUtf8ToAscii(string utf8String) - { - return Encoding.ASCII.GetString(Encoding.UTF8.GetBytes(utf8String), 0, utf8String.Length); - } - - public static string ConvertUtf8ToUtf16(string utf8String) - { - return Encoding.Unicode.GetString(Encoding.UTF8.GetBytes(utf8String), 0, utf8String.Length); - } + return Encoding.ASCII.GetString(Encoding.UTF8.GetBytes(utf8String), 0, utf8String.Length); + } + public static string ConvertUtf8ToUtf16(string utf8String) + { + return Encoding.Unicode.GetString(Encoding.UTF8.GetBytes(utf8String), 0, utf8String.Length); } + } \ No newline at end of file diff --git a/src/PepperDash.Core/CoreInterfaces.cs b/src/PepperDash.Core/CoreInterfaces.cs index 6e0b639e9..b66890c8d 100644 --- a/src/PepperDash.Core/CoreInterfaces.cs +++ b/src/PepperDash.Core/CoreInterfaces.cs @@ -6,30 +6,28 @@ using Newtonsoft.Json; using Serilog; -namespace PepperDash.Core -{ - /// - /// Unique key interface to require a unique key for the class - /// +namespace PepperDash.Core; + +/// +/// Unique key interface to require a unique key for the class +/// public interface IKeyed { - /// - /// Unique Key - /// - [JsonProperty("key")] + /// + /// Gets the unique key associated with the object. + /// + [JsonProperty("key")] string Key { get; } - } +} - /// - /// Named Keyed device interface. Forces the device to have a Unique Key and a name. - /// +/// +/// Named Keyed device interface. Forces the device to have a Unique Key and a name. +/// public interface IKeyName : IKeyed - { - /// - /// Isn't it obvious :) - /// - [JsonProperty("name")] +{ + /// + /// Gets the name associated with the current object. + /// + [JsonProperty("name")] string Name { get; } - } - } \ No newline at end of file diff --git a/src/PepperDash.Core/Device.cs b/src/PepperDash.Core/Device.cs index ef9f6111b..8ea632655 100644 --- a/src/PepperDash.Core/Device.cs +++ b/src/PepperDash.Core/Device.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using Serilog.Events; -namespace PepperDash.Core -{ +namespace PepperDash.Core; + //********************************************************************************************************* /// /// The core event and status-bearing class that most if not all device and connectors can derive from. @@ -178,15 +178,14 @@ public void OnFalse(object o, Action a) if (o is bool && !(bool)o) a(); } - /// - /// Returns a string representation of the object, including its key and name. - /// - /// The returned string is formatted as "{Key} - {Name}". If the Name property is - /// null or empty, "---" is used in place of the name. - /// A string that represents the object, containing the key and name in the format "{Key} - {Name}". + /// + /// Returns a string representation of the object, including its key and name. + /// + /// The returned string is formatted as "{Key} - {Name}". If the Name property is + /// null or empty, "---" is used in place of the name. + /// A string that represents the object, containing the key and name in the format "{Key} - {Name}". public override string ToString() { return string.Format("{0} - {1}", Key, string.IsNullOrEmpty(Name) ? "---" : Name); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/EthernetHelper.cs b/src/PepperDash.Core/EthernetHelper.cs index 884298860..67c337bd2 100644 --- a/src/PepperDash.Core/EthernetHelper.cs +++ b/src/PepperDash.Core/EthernetHelper.cs @@ -2,11 +2,11 @@ using Newtonsoft.Json; using Serilog.Events; -namespace PepperDash.Core -{ - /// - /// Class to help with accessing values from the CrestronEthernetHelper class - /// +namespace PepperDash.Core; + +/// +/// Class to help with accessing values from the CrestronEthernetHelper class +/// public class EthernetHelper { /// @@ -113,5 +113,4 @@ public string DefaultGateway CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, 0); } } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/EventArgs.cs b/src/PepperDash.Core/EventArgs.cs index 29ef13a84..adbfb5c8c 100644 --- a/src/PepperDash.Core/EventArgs.cs +++ b/src/PepperDash.Core/EventArgs.cs @@ -4,8 +4,8 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Core -{ +namespace PepperDash.Core; + /// /// Bool change event args /// @@ -168,5 +168,4 @@ public StringChangeEventArgs(string stringValue, ushort type, ushort index) Type = type; Index = index; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/GenericRESTfulCommunications/Constants.cs b/src/PepperDash.Core/GenericRESTfulCommunications/Constants.cs index 1b78c33f1..d8a09e4e4 100644 --- a/src/PepperDash.Core/GenericRESTfulCommunications/Constants.cs +++ b/src/PepperDash.Core/GenericRESTfulCommunications/Constants.cs @@ -4,13 +4,13 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Core.GenericRESTfulCommunications -{ +namespace PepperDash.Core.GenericRESTfulCommunications; + /// /// Constants /// - public class GenericRESTfulConstants - { +public class GenericRESTfulConstants +{ /// /// Generic boolean change /// @@ -35,5 +35,4 @@ public class GenericRESTfulConstants /// Error string change /// public const ushort ErrorStringChange = 203; - } } \ No newline at end of file diff --git a/src/PepperDash.Core/GenericRESTfulCommunications/GenericRESTfulClient.cs b/src/PepperDash.Core/GenericRESTfulCommunications/GenericRESTfulClient.cs index bd33e13cb..16a2ee04a 100644 --- a/src/PepperDash.Core/GenericRESTfulCommunications/GenericRESTfulClient.cs +++ b/src/PepperDash.Core/GenericRESTfulCommunications/GenericRESTfulClient.cs @@ -6,8 +6,8 @@ using Crestron.SimplSharp.Net.Http; using Crestron.SimplSharp.Net.Https; -namespace PepperDash.Core.GenericRESTfulCommunications -{ +namespace PepperDash.Core.GenericRESTfulCommunications; + /// /// Generic RESTful communication class /// @@ -42,7 +42,7 @@ public GenericRESTfulClient() /// /// /// - /// + /// public void SubmitRequest(string url, ushort port, ushort requestType, string contentType, string username, string password) { if (url.StartsWith("https:", StringComparison.OrdinalIgnoreCase)) @@ -65,7 +65,7 @@ public void SubmitRequest(string url, ushort port, ushort requestType, string co /// /// /// - /// + /// /// /// private void SubmitRequestHttp(string url, ushort port, ushort requestType, string contentType, string username, string password) @@ -123,7 +123,7 @@ private void SubmitRequestHttp(string url, ushort port, ushort requestType, stri /// /// /// - /// + /// /// /// private void SubmitRequestHttps(string url, ushort port, ushort requestType, string contentType, string username, string password) @@ -252,5 +252,4 @@ protected void OnStringChange(string value, ushort index, ushort type) StringChange(this, args); } } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/JsonStandardObjects/EventArgs and Constants.cs b/src/PepperDash.Core/JsonStandardObjects/EventArgs and Constants.cs index ed02ccb06..a41345dc6 100644 --- a/src/PepperDash.Core/JsonStandardObjects/EventArgs and Constants.cs +++ b/src/PepperDash.Core/JsonStandardObjects/EventArgs and Constants.cs @@ -4,8 +4,8 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Core.JsonStandardObjects -{ +namespace PepperDash.Core.JsonStandardObjects; + /// /// Constants for simpl modules /// @@ -73,5 +73,4 @@ public DeviceChangeEventArgs(DeviceConfig device, ushort type, ushort index) Type = type; Index = index; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/JsonStandardObjects/JsonToSimplDevice.cs b/src/PepperDash.Core/JsonStandardObjects/JsonToSimplDevice.cs index 3abfd36a1..591cbd5c0 100644 --- a/src/PepperDash.Core/JsonStandardObjects/JsonToSimplDevice.cs +++ b/src/PepperDash.Core/JsonStandardObjects/JsonToSimplDevice.cs @@ -4,8 +4,8 @@ using PepperDash.Core.JsonToSimpl; using Serilog.Events; -namespace PepperDash.Core.JsonStandardObjects -{ +namespace PepperDash.Core.JsonStandardObjects; + /// /// Device class /// @@ -179,5 +179,4 @@ protected void OnObjectChange(DeviceConfig device, ushort index, ushort type) } #endregion EventHandler Helpers - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/JsonStandardObjects/JsonToSimplDeviceConfig.cs b/src/PepperDash.Core/JsonStandardObjects/JsonToSimplDeviceConfig.cs index fa23d87ee..6f1f74c46 100644 --- a/src/PepperDash.Core/JsonStandardObjects/JsonToSimplDeviceConfig.cs +++ b/src/PepperDash.Core/JsonStandardObjects/JsonToSimplDeviceConfig.cs @@ -4,8 +4,8 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Core.JsonStandardObjects -{ +namespace PepperDash.Core.JsonStandardObjects; + /* Convert JSON snippt to C#: http://json2csharp.com/# @@ -52,55 +52,55 @@ namespace PepperDash.Core.JsonStandardObjects /// public class ComParamsConfig { - /// - /// - /// + /// + /// + /// public int baudRate { get; set; } - /// - /// - /// + /// + /// + /// public int dataBits { get; set; } - /// - /// - /// + /// + /// + /// public int stopBits { get; set; } - /// - /// - /// + /// + /// + /// public string parity { get; set; } - /// - /// - /// + /// + /// + /// public string protocol { get; set; } - /// - /// - /// + /// + /// + /// public string hardwareHandshake { get; set; } - /// - /// - /// + /// + /// + /// public string softwareHandshake { get; set; } - /// - /// - /// + /// + /// + /// public int pacing { get; set; } // convert properties for simpl - /// - /// - /// + /// + /// + /// public ushort simplBaudRate { get { return Convert.ToUInt16(baudRate); } } - /// - /// - /// + /// + /// + /// public ushort simplDataBits { get { return Convert.ToUInt16(dataBits); } } - /// - /// - /// + /// + /// + /// public ushort simplStopBits { get { return Convert.ToUInt16(stopBits); } } - /// - /// - /// + /// + /// + /// public ushort simplPacing { get { return Convert.ToUInt16(pacing); } } /// @@ -117,43 +117,43 @@ public ComParamsConfig() /// public class TcpSshPropertiesConfig { - /// - /// - /// + /// + /// + /// public string address { get; set; } - /// - /// - /// + /// + /// + /// public int port { get; set; } - /// - /// - /// + /// + /// + /// public string username { get; set; } - /// - /// - /// + /// + /// + /// public string password { get; set; } - /// - /// - /// + /// + /// + /// public bool autoReconnect { get; set; } - /// - /// - /// + /// + /// + /// public int autoReconnectIntervalMs { get; set; } // convert properties for simpl - /// - /// - /// + /// + /// + /// public ushort simplPort { get { return Convert.ToUInt16(port); } } - /// - /// - /// + /// + /// + /// public ushort simplAutoReconnect { get { return (ushort)(autoReconnect ? 1 : 0); } } - /// - /// - /// + /// + /// + /// public ushort simplAutoReconnectIntervalMs { get { return Convert.ToUInt16(autoReconnectIntervalMs); } } /// @@ -170,31 +170,31 @@ public TcpSshPropertiesConfig() /// public class ControlConfig { - /// - /// - /// + /// + /// + /// public string method { get; set; } - /// - /// - /// + /// + /// + /// public string controlPortDevKey { get; set; } - /// - /// - /// + /// + /// + /// public int controlPortNumber { get; set; } - /// - /// - /// + /// + /// + /// public ComParamsConfig comParams { get; set; } - /// - /// - /// + /// + /// + /// public TcpSshPropertiesConfig tcpSshProperties { get; set; } // convert properties for simpl - /// - /// - /// + /// + /// + /// public ushort simplControlPortNumber { get { return Convert.ToUInt16(controlPortNumber); } } /// @@ -212,27 +212,27 @@ public ControlConfig() /// public class PropertiesConfig { - /// - /// - /// + /// + /// + /// public int deviceId { get; set; } - /// - /// - /// + /// + /// + /// public bool enabled { get; set; } - /// - /// - /// + /// + /// + /// public ControlConfig control { get; set; } // convert properties for simpl - /// - /// - /// + /// + /// + /// public ushort simplDeviceId { get { return Convert.ToUInt16(deviceId); } } - /// - /// - /// + /// + /// + /// public ushort simplEnabled { get { return (ushort)(enabled ? 1 : 0); } } /// @@ -249,9 +249,8 @@ public PropertiesConfig() /// public class RootObject { - /// - /// The collection of devices - /// + /// + /// The collection of devices + /// public List devices { get; set; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/JsonToSimpl/Constants.cs b/src/PepperDash.Core/JsonToSimpl/Constants.cs index d87b50c20..9b8d08ff5 100644 --- a/src/PepperDash.Core/JsonToSimpl/Constants.cs +++ b/src/PepperDash.Core/JsonToSimpl/Constants.cs @@ -4,78 +4,78 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Core.JsonToSimpl -{ +namespace PepperDash.Core.JsonToSimpl; + /// /// Constants for Simpl modules /// public class JsonToSimplConstants { - /// - /// - /// + /// + /// + /// public const ushort BoolValueChange = 1; - /// - /// - /// + /// + /// + /// public const ushort JsonIsValidBoolChange = 2; - /// - /// Reports the if the device is 3-series compatible - /// - public const ushort ProgramCompatibility3SeriesChange = 3; + /// + /// Reports the if the device is 3-series compatible + /// + public const ushort ProgramCompatibility3SeriesChange = 3; - /// - /// Reports the if the device is 4-series compatible - /// - public const ushort ProgramCompatibility4SeriesChange = 4; + /// + /// Reports the if the device is 4-series compatible + /// + public const ushort ProgramCompatibility4SeriesChange = 4; - /// - /// Reports the device platform enum value - /// - public const ushort DevicePlatformValueChange = 5; + /// + /// Reports the device platform enum value + /// + public const ushort DevicePlatformValueChange = 5; - /// - /// - /// + /// + /// + /// public const ushort UshortValueChange = 101; - /// - /// - /// + /// + /// + /// public const ushort StringValueChange = 201; - /// - /// - /// + /// + /// + /// public const ushort FullPathToArrayChange = 202; - /// - /// - /// + /// + /// + /// public const ushort ActualFilePathChange = 203; - /// - /// - /// + /// + /// + /// public const ushort FilenameResolvedChange = 204; - /// - /// - /// + /// + /// + /// public const ushort FilePathResolvedChange = 205; - /// - /// Reports the root directory change - /// - public const ushort RootDirectoryChange = 206; + /// + /// Reports the root directory change + /// + public const ushort RootDirectoryChange = 206; - /// - /// Reports the room ID change - /// - public const ushort RoomIdChange = 207; + /// + /// Reports the room ID change + /// + public const ushort RoomIdChange = 207; - /// - /// Reports the room name change - /// - public const ushort RoomNameChange = 208; + /// + /// Reports the room name change + /// + public const ushort RoomNameChange = 208; } /// @@ -88,33 +88,33 @@ public class JsonToSimplConstants /// public class SPlusValueWrapper { - /// - /// - /// + /// + /// + /// public SPlusType ValueType { get; private set; } - /// - /// - /// + /// + /// + /// public ushort Index { get; private set; } - /// - /// - /// + /// + /// + /// public ushort BoolUShortValue { get; set; } - /// - /// - /// + /// + /// + /// public string StringValue { get; set; } - /// - /// - /// + /// + /// + /// public SPlusValueWrapper() {} - /// - /// - /// - /// - /// + /// + /// + /// + /// + /// public SPlusValueWrapper(SPlusType type, ushort index) { ValueType = type; @@ -127,17 +127,16 @@ public SPlusValueWrapper(SPlusType type, ushort index) /// public enum SPlusType { - /// - /// Digital - /// + /// + /// Digital + /// Digital, - /// - /// Analog - /// - Analog, - /// - /// String - /// - String - } -} \ No newline at end of file + /// + /// Analog + /// + Analog, + /// + /// String + /// + String + } \ No newline at end of file diff --git a/src/PepperDash.Core/JsonToSimpl/Global.cs b/src/PepperDash.Core/JsonToSimpl/Global.cs index 8392fa614..9a30853e0 100644 --- a/src/PepperDash.Core/JsonToSimpl/Global.cs +++ b/src/PepperDash.Core/JsonToSimpl/Global.cs @@ -7,11 +7,11 @@ //using PepperDash.Core; -namespace PepperDash.Core.JsonToSimpl -{ - /// - /// The global class to manage all the instances of JsonToSimplMaster - /// +namespace PepperDash.Core.JsonToSimpl; + +/// +/// The global class to manage all the instances of JsonToSimplMaster +/// public class J2SGlobal { static List Masters = new List(); @@ -22,7 +22,7 @@ public class J2SGlobal /// master, this will fail /// /// New master to add - /// + /// public static void AddMaster(JsonToSimplMaster master) { if (master == null) @@ -56,5 +56,4 @@ public static JsonToSimplMaster GetMasterByFile(string file) { return Masters.FirstOrDefault(m => m.UniqueID.Equals(file, StringComparison.OrdinalIgnoreCase)); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/JsonToSimpl/JsonToSimplArrayLookupChild.cs b/src/PepperDash.Core/JsonToSimpl/JsonToSimplArrayLookupChild.cs index c94dad295..bd5ad8aed 100644 --- a/src/PepperDash.Core/JsonToSimpl/JsonToSimplArrayLookupChild.cs +++ b/src/PepperDash.Core/JsonToSimpl/JsonToSimplArrayLookupChild.cs @@ -3,20 +3,20 @@ using Newtonsoft.Json.Linq; using Serilog.Events; -namespace PepperDash.Core.JsonToSimpl -{ - /// - /// Used to interact with an array of values with the S+ modules - /// +namespace PepperDash.Core.JsonToSimpl; + +/// +/// Used to interact with an array of values with the S+ modules +/// public class JsonToSimplArrayLookupChild : JsonToSimplChildObjectBase { - /// - /// - /// + /// + /// + /// public string SearchPropertyName { get; set; } - /// - /// - /// + /// + /// + /// public string SearchPropertyValue { get; set; } int ArrayIndex; @@ -76,9 +76,9 @@ protected override string GetFullPath(string path) PathSuffix == null ? "" : PathSuffix); } - /// - /// Process all values - /// + /// + /// Process all values + /// public override void ProcessAll() { if (FindInArray()) @@ -158,5 +158,4 @@ bool FindInArray() return false; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/JsonToSimpl/JsonToSimplChildObjectBase.cs b/src/PepperDash.Core/JsonToSimpl/JsonToSimplChildObjectBase.cs index 5aa67c966..7ebb6f27d 100644 --- a/src/PepperDash.Core/JsonToSimpl/JsonToSimplChildObjectBase.cs +++ b/src/PepperDash.Core/JsonToSimpl/JsonToSimplChildObjectBase.cs @@ -3,29 +3,29 @@ using System.Linq; using Newtonsoft.Json.Linq; -namespace PepperDash.Core.JsonToSimpl -{ - /// - /// Base class for JSON objects - /// +namespace PepperDash.Core.JsonToSimpl; + +/// +/// Base class for JSON objects +/// public abstract class JsonToSimplChildObjectBase : IKeyed { - /// - /// Notifies of bool change - /// + /// + /// Notifies of bool change + /// public event EventHandler BoolChange; - /// - /// Notifies of ushort change - /// + /// + /// Notifies of ushort change + /// public event EventHandler UShortChange; - /// - /// Notifies of string change - /// + /// + /// Notifies of string change + /// public event EventHandler StringChange; - /// - /// Delegate to get all values - /// + /// + /// Delegate to get all values + /// public SPlusValuesDelegate GetAllValuesDelegate { get; set; } /// @@ -33,9 +33,9 @@ public abstract class JsonToSimplChildObjectBase : IKeyed /// public SPlusValuesDelegate SetAllPathsDelegate { get; set; } - /// - /// Unique identifier for instance - /// + /// + /// Unique identifier for instance + /// public string Key { get; protected set; } /// @@ -49,33 +49,33 @@ public abstract class JsonToSimplChildObjectBase : IKeyed /// public string PathSuffix { get; protected set; } - /// - /// Indicates if the instance is linked to an object - /// + /// + /// Indicates if the instance is linked to an object + /// public bool LinkedToObject { get; protected set; } - /// - /// Reference to Master instance - /// + /// + /// Reference to Master instance + /// protected JsonToSimplMaster Master; - /// - /// Paths to boolean values in JSON structure - /// - protected Dictionary BoolPaths = new Dictionary(); - /// - /// Paths to numeric values in JSON structure - /// + /// + /// Paths to boolean values in JSON structure + /// + protected Dictionary BoolPaths = new Dictionary(); + /// + /// Paths to numeric values in JSON structure + /// protected Dictionary UshortPaths = new Dictionary(); - /// - /// Paths to string values in JSON structure - /// + /// + /// Paths to string values in JSON structure + /// protected Dictionary StringPaths = new Dictionary(); /// /// Call this before doing anything else /// - /// + /// /// /// /// @@ -92,10 +92,10 @@ public void Initialize(string masterUniqueId, string key, string pathPrefix, str Debug.Console(1, "JSON Child [{0}] cannot link to master {1}", key, masterUniqueId); } - /// - /// Sets the path prefix for the object - /// - /// + /// + /// Sets the path prefix for the object + /// + /// public void SetPathPrefix(string pathPrefix) { PathPrefix = pathPrefix; @@ -170,18 +170,18 @@ void ProcessBoolPath(ushort index) } // Processes the path to a ushort, converting to ushort if able, twos complement if necessary, firing off UshrtChange event - void ProcessUshortPath(ushort index) { - string response; - if (Process(UshortPaths[index], out response)) { - ushort val; - try { val = Convert.ToInt32(response) < 0 ? (ushort)(Convert.ToInt16(response) + 65536) : Convert.ToUInt16(response); } - catch { val = 0; } - - OnUShortChange(val, index, JsonToSimplConstants.UshortValueChange); - } - else { } - // OnUShortChange(0, index, JsonToSimplConstants.UshortValueChange); + void ProcessUshortPath(ushort index) { + string response; + if (Process(UshortPaths[index], out response)) { + ushort val; + try { val = Convert.ToInt32(response) < 0 ? (ushort)(Convert.ToInt16(response) + 65536) : Convert.ToUInt16(response); } + catch { val = 0; } + + OnUShortChange(val, index, JsonToSimplConstants.UshortValueChange); } + else { } + // OnUShortChange(0, index, JsonToSimplConstants.UshortValueChange); + } // Processes the path to a string property and fires of a StringChange event. void ProcessStringPath(ushort index) @@ -272,54 +272,54 @@ public void UpdateInputsForMaster() GetAllValuesDelegate(); } - /// - /// - /// - /// - /// + /// + /// + /// + /// + /// public void USetBoolValue(ushort key, ushort theValue) { SetBoolValue(key, theValue == 1); } - /// - /// - /// - /// - /// + /// + /// + /// + /// + /// public void SetBoolValue(ushort key, bool theValue) { if (BoolPaths.ContainsKey(key)) SetValueOnMaster(BoolPaths[key], new JValue(theValue)); } - /// - /// - /// - /// - /// + /// + /// + /// + /// + /// public void SetUShortValue(ushort key, ushort theValue) { if (UshortPaths.ContainsKey(key)) SetValueOnMaster(UshortPaths[key], new JValue(theValue)); } - /// - /// - /// - /// - /// + /// + /// + /// + /// + /// public void SetStringValue(ushort key, string theValue) { if (StringPaths.ContainsKey(key)) SetValueOnMaster(StringPaths[key], new JValue(theValue)); } - /// - /// - /// - /// - /// + /// + /// + /// + /// + /// public void SetValueOnMaster(string keyPath, JValue valueToSave) { var path = GetFullPath(keyPath); @@ -349,12 +349,12 @@ protected virtual string GetFullPath(string path) // Helpers for events //****************************************************************************************** - /// - /// Event helper - /// - /// - /// - /// + /// + /// Event helper + /// + /// + /// + /// protected void OnBoolChange(bool state, ushort index, ushort type) { var handler = BoolChange; @@ -367,12 +367,12 @@ protected void OnBoolChange(bool state, ushort index, ushort type) } //****************************************************************************************** - /// - /// Event helper - /// - /// - /// - /// + /// + /// Event helper + /// + /// + /// + /// protected void OnUShortChange(ushort state, ushort index, ushort type) { var handler = UShortChange; @@ -384,12 +384,12 @@ protected void OnUShortChange(ushort state, ushort index, ushort type) } } - /// - /// Event helper - /// - /// - /// - /// + /// + /// Event helper + /// + /// + /// + /// protected void OnStringChange(string value, ushort index, ushort type) { var handler = StringChange; @@ -400,5 +400,4 @@ protected void OnStringChange(string value, ushort index, ushort type) StringChange(this, args); } } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/JsonToSimpl/JsonToSimplFileMaster.cs b/src/PepperDash.Core/JsonToSimpl/JsonToSimplFileMaster.cs index 411fbdc52..83c92e80d 100644 --- a/src/PepperDash.Core/JsonToSimpl/JsonToSimplFileMaster.cs +++ b/src/PepperDash.Core/JsonToSimpl/JsonToSimplFileMaster.cs @@ -7,281 +7,280 @@ using Crestron.SimplSharp.CrestronIO; using Newtonsoft.Json.Linq; -namespace PepperDash.Core.JsonToSimpl +namespace PepperDash.Core.JsonToSimpl; + +/// +/// Represents a JSON file that can be read and written to +/// +public class JsonToSimplFileMaster : JsonToSimplMaster { /// - /// Represents a JSON file that can be read and written to + /// Sets the filepath as well as registers this with the Global.Masters list + /// + public string Filepath { get; private set; } + + /// + /// Filepath to the actual file that will be read (Portal or local) + /// + public string ActualFilePath { get; private set; } + + /// + /// /// - public class JsonToSimplFileMaster : JsonToSimplMaster + public string Filename { get; private set; } + /// + /// + /// + public string FilePathName { get; private set; } + + /*****************************************************************************************/ + /** Privates **/ + + + // The JSON file in JObject form + // For gathering the incoming data + object StringBuilderLock = new object(); + // To prevent multiple same-file access + static object FileLock = new object(); + + /*****************************************************************************************/ + + /// + /// SIMPL+ default constructor. + /// + public JsonToSimplFileMaster() { - /// - /// Sets the filepath as well as registers this with the Global.Masters list - /// - public string Filepath { get; private set; } - - /// - /// Filepath to the actual file that will be read (Portal or local) - /// - public string ActualFilePath { get; private set; } - - /// - /// - /// - public string Filename { get; private set; } - /// - /// - /// - public string FilePathName { get; private set; } - - /*****************************************************************************************/ - /** Privates **/ - - - // The JSON file in JObject form - // For gathering the incoming data - object StringBuilderLock = new object(); - // To prevent multiple same-file access - static object FileLock = new object(); - - /*****************************************************************************************/ - - /// - /// SIMPL+ default constructor. - /// - public JsonToSimplFileMaster() - { - } + } - /// - /// Read, evaluate and udpate status - /// - public void EvaluateFile(string filepath) + /// + /// Read, evaluate and udpate status + /// + public void EvaluateFile(string filepath) + { + try { - try - { - OnBoolChange(false, 0, JsonToSimplConstants.JsonIsValidBoolChange); + OnBoolChange(false, 0, JsonToSimplConstants.JsonIsValidBoolChange); - var dirSeparator = Path.DirectorySeparatorChar; - var dirSeparatorAlt = Path.AltDirectorySeparatorChar; + var dirSeparator = Path.DirectorySeparatorChar; + var dirSeparatorAlt = Path.AltDirectorySeparatorChar; - var series = CrestronEnvironment.ProgramCompatibility; + var series = CrestronEnvironment.ProgramCompatibility; - var is3Series = (eCrestronSeries.Series3 == (series & eCrestronSeries.Series3)); - OnBoolChange(is3Series, 0, - JsonToSimplConstants.ProgramCompatibility3SeriesChange); + var is3Series = (eCrestronSeries.Series3 == (series & eCrestronSeries.Series3)); + OnBoolChange(is3Series, 0, + JsonToSimplConstants.ProgramCompatibility3SeriesChange); - var is4Series = (eCrestronSeries.Series4 == (series & eCrestronSeries.Series4)); - OnBoolChange(is4Series, 0, - JsonToSimplConstants.ProgramCompatibility4SeriesChange); + var is4Series = (eCrestronSeries.Series4 == (series & eCrestronSeries.Series4)); + OnBoolChange(is4Series, 0, + JsonToSimplConstants.ProgramCompatibility4SeriesChange); - var isServer = CrestronEnvironment.DevicePlatform == eDevicePlatform.Server; - OnBoolChange(isServer, 0, - JsonToSimplConstants.DevicePlatformValueChange); + var isServer = CrestronEnvironment.DevicePlatform == eDevicePlatform.Server; + OnBoolChange(isServer, 0, + JsonToSimplConstants.DevicePlatformValueChange); - // get the roomID - var roomId = Crestron.SimplSharp.InitialParametersClass.RoomId; - if (!string.IsNullOrEmpty(roomId)) - { - OnStringChange(roomId, 0, JsonToSimplConstants.RoomIdChange); - } + // get the roomID + var roomId = Crestron.SimplSharp.InitialParametersClass.RoomId; + if (!string.IsNullOrEmpty(roomId)) + { + OnStringChange(roomId, 0, JsonToSimplConstants.RoomIdChange); + } - // get the roomName - var roomName = Crestron.SimplSharp.InitialParametersClass.RoomName; - if (!string.IsNullOrEmpty(roomName)) - { - OnStringChange(roomName, 0, JsonToSimplConstants.RoomNameChange); - } + // get the roomName + var roomName = Crestron.SimplSharp.InitialParametersClass.RoomName; + if (!string.IsNullOrEmpty(roomName)) + { + OnStringChange(roomName, 0, JsonToSimplConstants.RoomNameChange); + } - var rootDirectory = Directory.GetApplicationRootDirectory(); - OnStringChange(rootDirectory, 0, JsonToSimplConstants.RootDirectoryChange); - - var splusPath = string.Empty; - if (Regex.IsMatch(filepath, @"user", RegexOptions.IgnoreCase)) - { - if (is4Series) - splusPath = Regex.Replace(filepath, "user", "user", RegexOptions.IgnoreCase); - else if (isServer) - splusPath = Regex.Replace(filepath, "user", "User", RegexOptions.IgnoreCase); - else - splusPath = filepath; - } + var rootDirectory = Directory.GetApplicationRootDirectory(); + OnStringChange(rootDirectory, 0, JsonToSimplConstants.RootDirectoryChange); + + var splusPath = string.Empty; + if (Regex.IsMatch(filepath, @"user", RegexOptions.IgnoreCase)) + { + if (is4Series) + splusPath = Regex.Replace(filepath, "user", "user", RegexOptions.IgnoreCase); + else if (isServer) + splusPath = Regex.Replace(filepath, "user", "User", RegexOptions.IgnoreCase); + else + splusPath = filepath; + } + + filepath = splusPath.Replace(dirSeparatorAlt, dirSeparator); + + Filepath = string.Format("{1}{0}{2}", dirSeparator, rootDirectory, + filepath.TrimStart(dirSeparator, dirSeparatorAlt)); + + OnStringChange(string.Format("Attempting to evaluate {0}", Filepath), 0, JsonToSimplConstants.StringValueChange); - filepath = splusPath.Replace(dirSeparatorAlt, dirSeparator); - - Filepath = string.Format("{1}{0}{2}", dirSeparator, rootDirectory, - filepath.TrimStart(dirSeparator, dirSeparatorAlt)); - - OnStringChange(string.Format("Attempting to evaluate {0}", Filepath), 0, JsonToSimplConstants.StringValueChange); + if (string.IsNullOrEmpty(Filepath)) + { + OnStringChange(string.Format("Cannot evaluate file. JSON file path not set"), 0, JsonToSimplConstants.StringValueChange); + CrestronConsole.PrintLine("Cannot evaluate file. JSON file path not set"); + return; + } + + // get file directory and name to search + var fileDirectory = Path.GetDirectoryName(Filepath); + var fileName = Path.GetFileName(Filepath); + + OnStringChange(string.Format("Checking '{0}' for '{1}'", fileDirectory, fileName), 0, JsonToSimplConstants.StringValueChange); + Debug.Console(1, "Checking '{0}' for '{1}'", fileDirectory, fileName); - if (string.IsNullOrEmpty(Filepath)) + if (Directory.Exists(fileDirectory)) + { + // get the directory info + var directoryInfo = new DirectoryInfo(fileDirectory); + + // get the file to be read + var actualFile = directoryInfo.GetFiles(fileName).FirstOrDefault(); + if (actualFile == null) { - OnStringChange(string.Format("Cannot evaluate file. JSON file path not set"), 0, JsonToSimplConstants.StringValueChange); - CrestronConsole.PrintLine("Cannot evaluate file. JSON file path not set"); + var msg = string.Format("JSON file not found: {0}", Filepath); + OnStringChange(msg, 0, JsonToSimplConstants.StringValueChange); + CrestronConsole.PrintLine(msg); + ErrorLog.Error(msg); return; } - // get file directory and name to search - var fileDirectory = Path.GetDirectoryName(Filepath); - var fileName = Path.GetFileName(Filepath); + // \xSE\xR\PDT000-Template_Main_Config-Combined_DSP_v00.02.json + // \USER\PDT000-Template_Main_Config-Combined_DSP_v00.02.json + ActualFilePath = actualFile.FullName; + OnStringChange(ActualFilePath, 0, JsonToSimplConstants.ActualFilePathChange); + OnStringChange(string.Format("Actual JSON file is {0}", ActualFilePath), 0, JsonToSimplConstants.StringValueChange); + Debug.Console(1, "Actual JSON file is {0}", ActualFilePath); - OnStringChange(string.Format("Checking '{0}' for '{1}'", fileDirectory, fileName), 0, JsonToSimplConstants.StringValueChange); - Debug.Console(1, "Checking '{0}' for '{1}'", fileDirectory, fileName); + Filename = actualFile.Name; + OnStringChange(Filename, 0, JsonToSimplConstants.FilenameResolvedChange); + OnStringChange(string.Format("JSON Filename is {0}", Filename), 0, JsonToSimplConstants.StringValueChange); + Debug.Console(1, "JSON Filename is {0}", Filename); - if (Directory.Exists(fileDirectory)) - { - // get the directory info - var directoryInfo = new DirectoryInfo(fileDirectory); - - // get the file to be read - var actualFile = directoryInfo.GetFiles(fileName).FirstOrDefault(); - if (actualFile == null) - { - var msg = string.Format("JSON file not found: {0}", Filepath); - OnStringChange(msg, 0, JsonToSimplConstants.StringValueChange); - CrestronConsole.PrintLine(msg); - ErrorLog.Error(msg); - return; - } - - // \xSE\xR\PDT000-Template_Main_Config-Combined_DSP_v00.02.json - // \USER\PDT000-Template_Main_Config-Combined_DSP_v00.02.json - ActualFilePath = actualFile.FullName; - OnStringChange(ActualFilePath, 0, JsonToSimplConstants.ActualFilePathChange); - OnStringChange(string.Format("Actual JSON file is {0}", ActualFilePath), 0, JsonToSimplConstants.StringValueChange); - Debug.Console(1, "Actual JSON file is {0}", ActualFilePath); - - Filename = actualFile.Name; - OnStringChange(Filename, 0, JsonToSimplConstants.FilenameResolvedChange); - OnStringChange(string.Format("JSON Filename is {0}", Filename), 0, JsonToSimplConstants.StringValueChange); - Debug.Console(1, "JSON Filename is {0}", Filename); - - - FilePathName = string.Format(@"{0}{1}", actualFile.DirectoryName, dirSeparator); - OnStringChange(string.Format(@"{0}", actualFile.DirectoryName), 0, JsonToSimplConstants.FilePathResolvedChange); - OnStringChange(string.Format(@"JSON File Path is {0}", actualFile.DirectoryName), 0, JsonToSimplConstants.StringValueChange); - Debug.Console(1, "JSON File Path is {0}", FilePathName); - - var json = File.ReadToEnd(ActualFilePath, System.Text.Encoding.ASCII); - - JsonObject = JObject.Parse(json); - foreach (var child in Children) - child.ProcessAll(); - - OnBoolChange(true, 0, JsonToSimplConstants.JsonIsValidBoolChange); - } - else - { - OnStringChange(string.Format("'{0}' not found", fileDirectory), 0, JsonToSimplConstants.StringValueChange); - Debug.Console(1, "'{0}' not found", fileDirectory); - } + + FilePathName = string.Format(@"{0}{1}", actualFile.DirectoryName, dirSeparator); + OnStringChange(string.Format(@"{0}", actualFile.DirectoryName), 0, JsonToSimplConstants.FilePathResolvedChange); + OnStringChange(string.Format(@"JSON File Path is {0}", actualFile.DirectoryName), 0, JsonToSimplConstants.StringValueChange); + Debug.Console(1, "JSON File Path is {0}", FilePathName); + + var json = File.ReadToEnd(ActualFilePath, System.Text.Encoding.ASCII); + + JsonObject = JObject.Parse(json); + foreach (var child in Children) + child.ProcessAll(); + + OnBoolChange(true, 0, JsonToSimplConstants.JsonIsValidBoolChange); } - catch (Exception e) + else { - var msg = string.Format("EvaluateFile Exception: Message\r{0}", e.Message); - OnStringChange(msg, 0, JsonToSimplConstants.StringValueChange); - CrestronConsole.PrintLine(msg); - ErrorLog.Error(msg); - - var stackTrace = string.Format("EvaluateFile: Stack Trace\r{0}", e.StackTrace); - OnStringChange(stackTrace, 0, JsonToSimplConstants.StringValueChange); - CrestronConsole.PrintLine(stackTrace); - ErrorLog.Error(stackTrace); + OnStringChange(string.Format("'{0}' not found", fileDirectory), 0, JsonToSimplConstants.StringValueChange); + Debug.Console(1, "'{0}' not found", fileDirectory); } } + catch (Exception e) + { + var msg = string.Format("EvaluateFile Exception: Message\r{0}", e.Message); + OnStringChange(msg, 0, JsonToSimplConstants.StringValueChange); + CrestronConsole.PrintLine(msg); + ErrorLog.Error(msg); + + var stackTrace = string.Format("EvaluateFile: Stack Trace\r{0}", e.StackTrace); + OnStringChange(stackTrace, 0, JsonToSimplConstants.StringValueChange); + CrestronConsole.PrintLine(stackTrace); + ErrorLog.Error(stackTrace); + } + } - /// - /// Sets the debug level - /// - /// - public void setDebugLevel(uint level) + /// + /// Sets the debug level + /// + /// + public void setDebugLevel(uint level) + { + Debug.SetDebugLevel(level); + } + + /// + /// Saves the values to the file + /// + public override void Save() + { + // this code is duplicated in the other masters!!!!!!!!!!!!! + UnsavedValues = new Dictionary(); + // Make each child update their values into master object + foreach (var child in Children) { - Debug.SetDebugLevel(level); + Debug.Console(1, "Master [{0}] checking child [{1}] for updates to save", UniqueID, child.Key); + child.UpdateInputsForMaster(); } - /// - /// Saves the values to the file - /// - public override void Save() + if (UnsavedValues == null || UnsavedValues.Count == 0) { - // this code is duplicated in the other masters!!!!!!!!!!!!! - UnsavedValues = new Dictionary(); - // Make each child update their values into master object - foreach (var child in Children) - { - Debug.Console(1, "Master [{0}] checking child [{1}] for updates to save", UniqueID, child.Key); - child.UpdateInputsForMaster(); - } - - if (UnsavedValues == null || UnsavedValues.Count == 0) + Debug.Console(1, "Master [{0}] No updated values to save. Skipping", UniqueID); + return; + } + lock (FileLock) + { + Debug.Console(1, "Saving"); + foreach (var path in UnsavedValues.Keys) { - Debug.Console(1, "Master [{0}] No updated values to save. Skipping", UniqueID); - return; + var tokenToReplace = JsonObject.SelectToken(path); + if (tokenToReplace != null) + {// It's found + tokenToReplace.Replace(UnsavedValues[path]); + Debug.Console(1, "JSON Master[{0}] Updating '{1}'", UniqueID, path); + } + else // No token. Let's make one + { + //http://stackoverflow.com/questions/17455052/how-to-set-the-value-of-a-json-path-using-json-net + Debug.Console(1, "JSON Master[{0}] Cannot write value onto missing property: '{1}'", UniqueID, path); + + // JContainer jpart = JsonObject; + // // walk down the path and find where it goes + //#warning Does not handle arrays. + // foreach (var part in path.Split('.')) + // { + + // var openPos = part.IndexOf('['); + // if (openPos > -1) + // { + // openPos++; // move to number + // var closePos = part.IndexOf(']'); + // var arrayName = part.Substring(0, openPos - 1); // get the name + // var index = Convert.ToInt32(part.Substring(openPos, closePos - openPos)); + + // // Check if the array itself exists and add the item if so + // if (jpart[arrayName] != null) + // { + // var arrayObj = jpart[arrayName] as JArray; + // var item = arrayObj[index]; + // if (item == null) + // arrayObj.Add(new JObject()); + // } + + // Debug.Console(0, "IGNORING MISSING ARRAY VALUE FOR NOW"); + // continue; + // } + // // Build the + // if (jpart[part] == null) + // jpart.Add(new JProperty(part, new JObject())); + // jpart = jpart[part] as JContainer; + // } + // jpart.Replace(UnsavedValues[path]); + } } - lock (FileLock) + using (StreamWriter sw = new StreamWriter(ActualFilePath)) { - Debug.Console(1, "Saving"); - foreach (var path in UnsavedValues.Keys) + try { - var tokenToReplace = JsonObject.SelectToken(path); - if (tokenToReplace != null) - {// It's found - tokenToReplace.Replace(UnsavedValues[path]); - Debug.Console(1, "JSON Master[{0}] Updating '{1}'", UniqueID, path); - } - else // No token. Let's make one - { - //http://stackoverflow.com/questions/17455052/how-to-set-the-value-of-a-json-path-using-json-net - Debug.Console(1, "JSON Master[{0}] Cannot write value onto missing property: '{1}'", UniqueID, path); - - // JContainer jpart = JsonObject; - // // walk down the path and find where it goes - //#warning Does not handle arrays. - // foreach (var part in path.Split('.')) - // { - - // var openPos = part.IndexOf('['); - // if (openPos > -1) - // { - // openPos++; // move to number - // var closePos = part.IndexOf(']'); - // var arrayName = part.Substring(0, openPos - 1); // get the name - // var index = Convert.ToInt32(part.Substring(openPos, closePos - openPos)); - - // // Check if the array itself exists and add the item if so - // if (jpart[arrayName] != null) - // { - // var arrayObj = jpart[arrayName] as JArray; - // var item = arrayObj[index]; - // if (item == null) - // arrayObj.Add(new JObject()); - // } - - // Debug.Console(0, "IGNORING MISSING ARRAY VALUE FOR NOW"); - // continue; - // } - // // Build the - // if (jpart[part] == null) - // jpart.Add(new JProperty(part, new JObject())); - // jpart = jpart[part] as JContainer; - // } - // jpart.Replace(UnsavedValues[path]); - } + sw.Write(JsonObject.ToString()); + sw.Flush(); } - using (StreamWriter sw = new StreamWriter(ActualFilePath)) + catch (Exception e) { - try - { - sw.Write(JsonObject.ToString()); - sw.Flush(); - } - catch (Exception e) - { - string err = string.Format("Error writing JSON file:\r{0}", e); - Debug.Console(0, err); - ErrorLog.Warn(err); - return; - } + string err = string.Format("Error writing JSON file:\r{0}", e); + Debug.Console(0, err); + ErrorLog.Warn(err); + return; } } } diff --git a/src/PepperDash.Core/JsonToSimpl/JsonToSimplFixedPathObject.cs b/src/PepperDash.Core/JsonToSimpl/JsonToSimplFixedPathObject.cs index 3e69ed9db..6338e3090 100644 --- a/src/PepperDash.Core/JsonToSimpl/JsonToSimplFixedPathObject.cs +++ b/src/PepperDash.Core/JsonToSimpl/JsonToSimplFixedPathObject.cs @@ -1,18 +1,17 @@  -namespace PepperDash.Core.JsonToSimpl -{ - /// - /// - /// +namespace PepperDash.Core.JsonToSimpl; + +/// +/// +/// public class JsonToSimplFixedPathObject : JsonToSimplChildObjectBase { - /// - /// Constructor - /// + /// + /// Constructor + /// public JsonToSimplFixedPathObject() { this.LinkedToObject = true; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/JsonToSimpl/JsonToSimplGenericMaster.cs b/src/PepperDash.Core/JsonToSimpl/JsonToSimplGenericMaster.cs index e0f42f8e0..3399e0793 100644 --- a/src/PepperDash.Core/JsonToSimpl/JsonToSimplGenericMaster.cs +++ b/src/PepperDash.Core/JsonToSimpl/JsonToSimplGenericMaster.cs @@ -3,35 +3,35 @@ using Crestron.SimplSharp; using Newtonsoft.Json.Linq; -namespace PepperDash.Core.JsonToSimpl -{ - /// - /// Generic Master - /// +namespace PepperDash.Core.JsonToSimpl; + +/// +/// Generic Master +/// public class JsonToSimplGenericMaster : JsonToSimplMaster - { +{ /*****************************************************************************************/ /** Privates **/ - + // The JSON file in JObject form // For gathering the incoming data object StringBuilderLock = new object(); // To prevent multiple same-file access static object WriteLock = new object(); - /// - /// Callback action for saving - /// + /// + /// Callback action for saving + /// public Action SaveCallback { get; set; } /*****************************************************************************************/ /// - /// SIMPL+ default constructor. - /// + /// SIMPL+ default constructor. + /// public JsonToSimplGenericMaster() - { + { } /// @@ -78,7 +78,7 @@ public void SetJsonWithoutEvaluating(string json) public override void Save() { // this code is duplicated in the other masters!!!!!!!!!!!!! - UnsavedValues = new Dictionary(); + UnsavedValues = new Dictionary(); // Make each child update their values into master object foreach (var child in Children) { @@ -114,5 +114,4 @@ public override void Save() else Debug.Console(0, this, "WARNING: No save callback defined."); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/JsonToSimpl/JsonToSimplMaster.cs b/src/PepperDash.Core/JsonToSimpl/JsonToSimplMaster.cs index 2f872e41d..928d4e777 100644 --- a/src/PepperDash.Core/JsonToSimpl/JsonToSimplMaster.cs +++ b/src/PepperDash.Core/JsonToSimpl/JsonToSimplMaster.cs @@ -2,33 +2,32 @@ using System.Collections.Generic; using System.IO; using Crestron.SimplSharp; -using Crestron.SimplSharp.CrestronIO; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -namespace PepperDash.Core.JsonToSimpl -{ - /// - /// Abstract base class for JsonToSimpl interactions - /// +namespace PepperDash.Core.JsonToSimpl; + +/// +/// Abstract base class for JsonToSimpl interactions +/// public abstract class JsonToSimplMaster : IKeyed { - /// - /// Notifies of bool change - /// + /// + /// Notifies of bool change + /// public event EventHandler BoolChange; - /// - /// Notifies of ushort change - /// + /// + /// Notifies of ushort change + /// public event EventHandler UshrtChange; - /// - /// Notifies of string change - /// + /// + /// Notifies of string change + /// public event EventHandler StringChange; - /// - /// A collection of associated child modules - /// + /// + /// A collection of associated child modules + /// protected List Children = new List(); /*****************************************************************************************/ @@ -38,9 +37,9 @@ public abstract class JsonToSimplMaster : IKeyed /// public string Key { get { return UniqueID; } } - /// - /// A unique ID - /// + /// + /// A unique ID + /// public string UniqueID { get; protected set; } /// @@ -83,9 +82,9 @@ public ushort UDebug } } - /// - /// - /// + /// + /// + /// public JObject JsonObject { get; protected set; } /*****************************************************************************************/ @@ -142,9 +141,9 @@ public void AddUnsavedValue(string path, JValue value) //Debug.Console(0, "Master[{0}] Unsaved size={1}", UniqueID, UnsavedValues.Count); } - /// - /// Saves the file - /// + /// + /// Saves the file + /// public abstract void Save(); @@ -153,18 +152,14 @@ public void AddUnsavedValue(string path, JValue value) /// public static class JsonFixes { - /// - /// Deserializes a string into a JObject - /// - /// - /// + /// + /// Deserializes a string into a JObject + /// + /// + /// public static JObject ParseObject(string json) { - #if NET6_0 - using (var reader = new JsonTextReader(new System.IO.StringReader(json))) -#else - using (var reader = new JsonTextReader(new Crestron.SimplSharp.CrestronIO.StringReader(json))) -#endif + using (var reader = new JsonTextReader(new StringReader(json))) { var startDepth = reader.Depth; var obj = JObject.Load(reader); @@ -174,18 +169,15 @@ public static JObject ParseObject(string json) } } - /// - /// Deserializes a string into a JArray - /// - /// - /// + /// + /// Deserializes a string into a JArray + /// + /// + /// public static JArray ParseArray(string json) { - #if NET6_0 - using (var reader = new JsonTextReader(new System.IO.StringReader(json))) -#else - using (var reader = new JsonTextReader(new Crestron.SimplSharp.CrestronIO.StringReader(json))) -#endif + + using (var reader = new JsonTextReader(new StringReader(json))) { var startDepth = reader.Depth; var obj = JArray.Load(reader); @@ -228,12 +220,12 @@ protected void OnUshrtChange(ushort state, ushort index, ushort type) } } - /// - /// Helper event - /// - /// - /// - /// + /// + /// Helper event + /// + /// + /// + /// protected void OnStringChange(string value, ushort index, ushort type) { if (StringChange != null) @@ -244,4 +236,3 @@ protected void OnStringChange(string value, ushort index, ushort type) } } } -} diff --git a/src/PepperDash.Core/JsonToSimpl/JsonToSimplPortalFileMaster.cs b/src/PepperDash.Core/JsonToSimpl/JsonToSimplPortalFileMaster.cs index c170a9a17..30c66dd21 100644 --- a/src/PepperDash.Core/JsonToSimpl/JsonToSimplPortalFileMaster.cs +++ b/src/PepperDash.Core/JsonToSimpl/JsonToSimplPortalFileMaster.cs @@ -6,22 +6,22 @@ using Newtonsoft.Json.Linq; using PepperDash.Core.Config; -namespace PepperDash.Core.JsonToSimpl +namespace PepperDash.Core.JsonToSimpl; + +/// +/// Portal File Master +/// +public class JsonToSimplPortalFileMaster : JsonToSimplMaster { - /// - /// Portal File Master - /// - public class JsonToSimplPortalFileMaster : JsonToSimplMaster - { /// /// Sets the filepath as well as registers this with the Global.Masters list /// public string PortalFilepath { get; private set; } - /// - /// File path of the actual file being read (Portal or local) - /// - public string ActualFilePath { get; private set; } + /// + /// File path of the actual file being read (Portal or local) + /// + public string ActualFilePath { get; private set; } /*****************************************************************************************/ /** Privates **/ @@ -33,10 +33,10 @@ public class JsonToSimplPortalFileMaster : JsonToSimplMaster /*****************************************************************************************/ /// - /// SIMPL+ default constructor. - /// + /// SIMPL+ default constructor. + /// public JsonToSimplPortalFileMaster() - { + { } /// @@ -64,7 +64,7 @@ public void EvaluateFile(string portalFilepath) if (actualLocalFile != null) { ActualFilePath = actualLocalFile.FullName; - OnStringChange(ActualFilePath, 0, JsonToSimplConstants.ActualFilePathChange); + OnStringChange(ActualFilePath, 0, JsonToSimplConstants.ActualFilePathChange); } // If the local file does not exist, then read the portal file xyz.json // and create the local. @@ -78,7 +78,7 @@ public void EvaluateFile(string portalFilepath) // got the portal file, hand off to the merge / save method PortalConfigReader.ReadAndMergeFileIfNecessary(actualPortalFile.FullName, newLocalPath); ActualFilePath = newLocalPath; - OnStringChange(ActualFilePath, 0, JsonToSimplConstants.ActualFilePathChange); + OnStringChange(ActualFilePath, 0, JsonToSimplConstants.ActualFilePathChange); } else { @@ -188,4 +188,3 @@ public override void Save() } } } -} diff --git a/src/PepperDash.Core/Logging/CrestronEnricher.cs b/src/PepperDash.Core/Logging/CrestronEnricher.cs index 902ce8d57..1f8799258 100644 --- a/src/PepperDash.Core/Logging/CrestronEnricher.cs +++ b/src/PepperDash.Core/Logging/CrestronEnricher.cs @@ -7,31 +7,30 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Core.Logging +namespace PepperDash.Core.Logging; + +public class CrestronEnricher : ILogEventEnricher { - public class CrestronEnricher : ILogEventEnricher - { - static readonly string _appName; + static readonly string _appName; - static CrestronEnricher() + static CrestronEnricher() + { + switch (CrestronEnvironment.DevicePlatform) { - switch (CrestronEnvironment.DevicePlatform) - { - case eDevicePlatform.Appliance: - _appName = $"App {InitialParametersClass.ApplicationNumber}"; - break; - case eDevicePlatform.Server: - _appName = $"{InitialParametersClass.RoomId}"; - break; - } + case eDevicePlatform.Appliance: + _appName = $"App {InitialParametersClass.ApplicationNumber}"; + break; + case eDevicePlatform.Server: + _appName = $"{InitialParametersClass.RoomId}"; + break; } - + } + - public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) - { - var property = propertyFactory.CreateProperty("App", _appName); + public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) + { + var property = propertyFactory.CreateProperty("App", _appName); - logEvent.AddOrUpdateProperty(property); - } + logEvent.AddOrUpdateProperty(property); } } diff --git a/src/PepperDash.Core/Logging/Debug.cs b/src/PepperDash.Core/Logging/Debug.cs index 38dfa0348..592a401fe 100644 --- a/src/PepperDash.Core/Logging/Debug.cs +++ b/src/PepperDash.Core/Logging/Debug.cs @@ -1,4 +1,8 @@ -using Crestron.SimplSharp; +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text.RegularExpressions; +using Crestron.SimplSharp; using Crestron.SimplSharp.CrestronDataStore; using Crestron.SimplSharp.CrestronIO; using Crestron.SimplSharp.CrestronLogger; @@ -11,112 +15,111 @@ using Serilog.Formatting.Compact; using Serilog.Formatting.Json; using Serilog.Templates; -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text.RegularExpressions; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// Contains debug commands for use in various situations +/// +public static class Debug { - /// - /// Contains debug commands for use in various situations - /// - public static class Debug - { - private static readonly string LevelStoreKey = "ConsoleDebugLevel"; - private static readonly string WebSocketLevelStoreKey = "WebsocketDebugLevel"; - private static readonly string ErrorLogLevelStoreKey = "ErrorLogDebugLevel"; - private static readonly string FileLevelStoreKey = "FileDebugLevel"; + private static readonly string LevelStoreKey = "ConsoleDebugLevel"; + private static readonly string WebSocketLevelStoreKey = "WebsocketDebugLevel"; + private static readonly string ErrorLogLevelStoreKey = "ErrorLogDebugLevel"; + private static readonly string FileLevelStoreKey = "FileDebugLevel"; + private static readonly string DoNotLoadOnNextBootKey = "DoNotLoadOnNextBoot"; - private static readonly Dictionary _logLevels = new Dictionary() - { - {0, LogEventLevel.Information }, - {3, LogEventLevel.Warning }, - {4, LogEventLevel.Error }, - {5, LogEventLevel.Fatal }, - {1, LogEventLevel.Debug }, - {2, LogEventLevel.Verbose }, - }; + private static readonly Dictionary _logLevels = new Dictionary() + { + {0, LogEventLevel.Information }, + {3, LogEventLevel.Warning }, + {4, LogEventLevel.Error }, + {5, LogEventLevel.Fatal }, + {1, LogEventLevel.Debug }, + {2, LogEventLevel.Verbose }, + }; - private static ILogger _logger; + private static ILogger _logger; - private static readonly LoggingLevelSwitch _consoleLoggingLevelSwitch; + private static readonly LoggingLevelSwitch _consoleLoggingLevelSwitch; - private static readonly LoggingLevelSwitch _websocketLoggingLevelSwitch; + private static readonly LoggingLevelSwitch _websocketLoggingLevelSwitch; - private static readonly LoggingLevelSwitch _errorLogLevelSwitch; + private static readonly LoggingLevelSwitch _errorLogLevelSwitch; - private static readonly LoggingLevelSwitch _fileLevelSwitch; + private static readonly LoggingLevelSwitch _fileLevelSwitch; - public static LogEventLevel WebsocketMinimumLogLevel - { - get { return _websocketLoggingLevelSwitch.MinimumLevel; } - } + public static LogEventLevel WebsocketMinimumLogLevel + { + get { return _websocketLoggingLevelSwitch.MinimumLevel; } + } - private static readonly DebugWebsocketSink _websocketSink; + private static readonly DebugWebsocketSink _websocketSink; - public static DebugWebsocketSink WebsocketSink - { - get { return _websocketSink; } - } + public static DebugWebsocketSink WebsocketSink + { + get { return _websocketSink; } + } - /// - /// Describes the folder location where a given program stores it's debug level memory. By default, the - /// file written will be named appNdebug where N is 1-10. - /// - public static string OldFilePathPrefix = @"\nvram\debug\"; + /// + /// Describes the folder location where a given program stores it's debug level memory. By default, the + /// file written will be named appNdebug where N is 1-10. + /// + public static string OldFilePathPrefix = @"\nvram\debug\"; - /// - /// Describes the new folder location where a given program stores it's debug level memory. By default, the - /// file written will be named appNdebug where N is 1-10. - /// - public static string NewFilePathPrefix = @"\user\debug\"; + /// + /// Describes the new folder location where a given program stores it's debug level memory. By default, the + /// file written will be named appNdebug where N is 1-10. + /// + public static string NewFilePathPrefix = @"\user\debug\"; - /// - /// The name of the file containing the current debug settings. - /// - public static string FileName = string.Format(@"app{0}Debug.json", InitialParametersClass.ApplicationNumber); + /// + /// The name of the file containing the current debug settings. + /// + public static string FileName = string.Format(@"app{0}Debug.json", InitialParametersClass.ApplicationNumber); - /// - /// Debug level to set for a given program. - /// - public static int Level { get; private set; } + /// + /// Debug level to set for a given program. + /// + public static int Level { get; private set; } - /// - /// When this is true, the configuration file will NOT be loaded until triggered by either a console command or a signal - /// - public static bool DoNotLoadConfigOnNextBoot { get; private set; } + /// + /// When this is true, the configuration file will NOT be loaded until triggered by either a console command or a signal + /// + public static bool DoNotLoadConfigOnNextBoot { get; private set; } - private static DebugContextCollection _contexts; + private static DebugContextCollection _contexts; - private const int SaveTimeoutMs = 30000; + private const int SaveTimeoutMs = 30000; - public static bool IsRunningOnAppliance = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance; + public static bool IsRunningOnAppliance = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance; - /// - /// Version for the currently loaded PepperDashCore dll - /// - public static string PepperDashCoreVersion { get; private set; } + /// + /// Version for the currently loaded PepperDashCore dll + /// + public static string PepperDashCoreVersion { get; private set; } - private static CTimer _saveTimer; + private static CTimer _saveTimer; - /// - /// When true, the IncludedExcludedKeys dict will contain keys to include. - /// When false (default), IncludedExcludedKeys will contain keys to exclude. - /// - private static bool _excludeAllMode; + /// + /// When true, the IncludedExcludedKeys dict will contain keys to include. + /// When false (default), IncludedExcludedKeys will contain keys to exclude. + /// + private static bool _excludeAllMode; - //static bool ExcludeNoKeyMessages; + //static bool ExcludeNoKeyMessages; - private static readonly Dictionary IncludedExcludedKeys; + private static readonly Dictionary IncludedExcludedKeys; - private static readonly LoggerConfiguration _defaultLoggerConfiguration; + private static readonly LoggerConfiguration _defaultLoggerConfiguration; - private static LoggerConfiguration _loggerConfiguration; + private static LoggerConfiguration _loggerConfiguration; - public static LoggerConfiguration LoggerConfiguration => _loggerConfiguration; + public static LoggerConfiguration LoggerConfiguration => _loggerConfiguration; - static Debug() + static Debug() + { + try { CrestronDataStoreStatic.InitCrestronDataStore(); @@ -128,7 +131,7 @@ static Debug() var defaultFileLogLevel = GetStoredLogEventLevel(FileLevelStoreKey); - _consoleLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultConsoleLevel); + _consoleLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultConsoleLevel); _websocketLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultWebsocketLevel); @@ -144,7 +147,7 @@ static Debug() CrestronConsole.PrintLine($"Saving log files to {logFilePath}"); - var errorLogTemplate = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance + var errorLogTemplate = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? "{@t:fff}ms [{@l:u4}]{#if Key is not null}[{Key}]{#end} {@m}{#if @x is not null}\r\n{@x}{#end}" : "[{@t:yyyy-MM-dd HH:mm:ss.fff}][{@l:u4}][{App}]{#if Key is not null}[{Key}]{#end} {@m}{#if @x is not null}\r\n{@x}{#end}"; @@ -155,28 +158,13 @@ static Debug() .WriteTo.Sink(new DebugConsoleSink(new ExpressionTemplate("[{@t:yyyy-MM-dd HH:mm:ss.fff}][{@l:u4}][{App}]{#if Key is not null}[{Key}]{#end} {@m}{#if @x is not null}\r\n{@x}{#end}")), levelSwitch: _consoleLoggingLevelSwitch) .WriteTo.Sink(_websocketSink, levelSwitch: _websocketLoggingLevelSwitch) .WriteTo.Sink(new DebugErrorLogSink(new ExpressionTemplate(errorLogTemplate)), levelSwitch: _errorLogLevelSwitch) - .WriteTo.File(new RenderedCompactJsonFormatter(), logFilePath, + .WriteTo.File(new RenderedCompactJsonFormatter(), logFilePath, rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Debug, retainedFileCountLimit: CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? 30 : 60, levelSwitch: _fileLevelSwitch ); - try - { - if (InitialParametersClass.NumberOfRemovableDrives > 0) - { - CrestronConsole.PrintLine("{0} RM Drive(s) Present. Initializing CrestronLogger", InitialParametersClass.NumberOfRemovableDrives); - _defaultLoggerConfiguration.WriteTo.Sink(new DebugCrestronLoggerSink()); - } - else - CrestronConsole.PrintLine("No RM Drive(s) Present. Not using Crestron Logger"); - } - catch (Exception e) - { - CrestronConsole.PrintLine("Initializing of CrestronLogger failed: {0}", e); - } - // Instantiate the root logger _loggerConfiguration = _defaultLoggerConfiguration; @@ -193,38 +181,34 @@ static Debug() CrestronConsole.PrintLine(msg); - LogMessage(LogEventLevel.Information,msg); + LogMessage(LogEventLevel.Information, msg); + + IncludedExcludedKeys = new Dictionary(); - IncludedExcludedKeys = new Dictionary(); - if (CrestronEnvironment.RuntimeEnvironment == eRuntimeEnvironment.SimplSharpPro) { // Add command to console - CrestronConsole.AddNewConsoleCommand(SetDoNotLoadOnNextBootFromConsole, "donotloadonnextboot", + CrestronConsole.AddNewConsoleCommand(SetDoNotLoadOnNextBootFromConsole, "donotloadonnextboot", "donotloadonnextboot:P [true/false]: Should the application load on next boot", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(SetDebugFromConsole, "appdebug", "appdebug:P [0-5]: Sets the application's console debug message level", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(ShowDebugLog, "appdebuglog", - "appdebuglog:P [all] Use \"all\" for full log.", + "appdebuglog:P [all] Use \"all\" for full log.", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(s => CrestronLogger.Clear(false), "appdebugclear", - "appdebugclear:P Clears the current custom log", + "appdebugclear:P Clears the current custom log", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(SetDebugFilterFromConsole, "appdebugfilter", - "appdebugfilter [params]", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(SetDebugFilterFromConsole, "appdebugfilter", + "appdebugfilter [params]", ConsoleAccessLevelEnum.AccessOperator); } CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler; - LoadMemory(); + DoNotLoadConfigOnNextBoot = GetDoNotLoadOnNextBoot(); - var context = _contexts.GetOrCreateItem("DEFAULT"); - Level = context.Level; - DoNotLoadConfigOnNextBoot = context.DoNotLoadOnNextBoot; - - if(DoNotLoadConfigOnNextBoot) + if (DoNotLoadConfigOnNextBoot) CrestronConsole.PrintLine(string.Format("Program {0} will not load config after next boot. Use console command go:{0} to load the config manually", InitialParametersClass.ApplicationNumber)); _consoleLoggingLevelSwitch.MinimumLevelChanged += (sender, args) => @@ -232,726 +216,749 @@ static Debug() LogMessage(LogEventLevel.Information, "Console debug level set to {minimumLevel}", _consoleLoggingLevelSwitch.MinimumLevel); }; } - - public static void UpdateLoggerConfiguration(LoggerConfiguration config) + catch (Exception ex) { - _loggerConfiguration = config; - - _logger = config.CreateLogger(); + LogError(ex, "Exception in Debug static constructor: {message}", ex.Message); } + } - public static void ResetLoggerConfiguration() - { - _loggerConfiguration = _defaultLoggerConfiguration; + private static bool GetDoNotLoadOnNextBoot() + { + var err = CrestronDataStoreStatic.GetLocalBoolValue(DoNotLoadOnNextBootKey, out var doNotLoad); - _logger = _loggerConfiguration.CreateLogger(); + if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + { + LogError("Error retrieving DoNotLoadOnNextBoot value: {err}", err); + doNotLoad = false; } - private static LogEventLevel GetStoredLogEventLevel(string levelStoreKey) - { - try - { - var result = CrestronDataStoreStatic.GetLocalIntValue(levelStoreKey, out int logLevel); + return doNotLoad; + } - if (result != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) - { - CrestronConsole.Print($"Unable to retrieve stored log level for {levelStoreKey}.\r\nError: {result}.\r\nSetting level to {LogEventLevel.Information}\r\n"); - return LogEventLevel.Information; - } + public static void UpdateLoggerConfiguration(LoggerConfiguration config) + { + _loggerConfiguration = config; - if(logLevel < 0 || logLevel > 5) - { - CrestronConsole.PrintLine($"Stored Log level not valid for {levelStoreKey}: {logLevel}. Setting level to {LogEventLevel.Information}"); - return LogEventLevel.Information; - } + _logger = config.CreateLogger(); + } + + public static void ResetLoggerConfiguration() + { + _loggerConfiguration = _defaultLoggerConfiguration; + + _logger = _loggerConfiguration.CreateLogger(); + } - return (LogEventLevel)logLevel; - } catch (Exception ex) + private static LogEventLevel GetStoredLogEventLevel(string levelStoreKey) + { + try + { + var result = CrestronDataStoreStatic.GetLocalIntValue(levelStoreKey, out int logLevel); + + if (result != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) { - CrestronConsole.PrintLine($"Exception retrieving log level for {levelStoreKey}: {ex.Message}"); + CrestronConsole.Print($"Unable to retrieve stored log level for {levelStoreKey}.\r\nError: {result}.\r\nSetting level to {LogEventLevel.Information}\r\n"); return LogEventLevel.Information; } - } - - private static void GetVersion() - { - var assembly = Assembly.GetExecutingAssembly(); - var ver = - assembly - .GetCustomAttributes(typeof (AssemblyInformationalVersionAttribute), false); - if (ver != null && ver.Length > 0) + if (logLevel < 0 || logLevel > 5) { - if (ver[0] is AssemblyInformationalVersionAttribute verAttribute) - { - PepperDashCoreVersion = verAttribute.InformationalVersion; - } + CrestronConsole.PrintLine($"Stored Log level not valid for {levelStoreKey}: {logLevel}. Setting level to {LogEventLevel.Information}"); + return LogEventLevel.Information; } - else + + return (LogEventLevel)logLevel; + } + catch (Exception ex) + { + CrestronConsole.PrintLine($"Exception retrieving log level for {levelStoreKey}: {ex.Message}"); + return LogEventLevel.Information; + } + } + + private static void GetVersion() + { + var assembly = Assembly.GetExecutingAssembly(); + var ver = + assembly + .GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false); + + if (ver != null && ver.Length > 0) + { + if (ver[0] is AssemblyInformationalVersionAttribute verAttribute) { - var version = assembly.GetName().Version; - PepperDashCoreVersion = version.ToString(); + PepperDashCoreVersion = verAttribute.InformationalVersion; } } + else + { + var version = assembly.GetName().Version; + PepperDashCoreVersion = version.ToString(); + } + } - /// - /// Used to save memory when shutting down - /// - /// - static void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + /// + /// Used to save memory when shutting down + /// + /// + static void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + { + + if (programEventType == eProgramStatusEventType.Stopping) { + Log.CloseAndFlush(); - if (programEventType == eProgramStatusEventType.Stopping) + if (_saveTimer != null) { - Log.CloseAndFlush(); - - if (_saveTimer != null) - { - _saveTimer.Stop(); - _saveTimer = null; - } - LogMessage(LogEventLevel.Information, "Saving debug settings"); - SaveMemory(); + _saveTimer.Stop(); + _saveTimer = null; } + LogMessage(LogEventLevel.Information, "Saving debug settings"); + SaveMemory(); } + } - /// - /// Callback for console command - /// - /// - public static void SetDebugFromConsole(string levelString) + /// + /// Callback for console command + /// + /// + public static void SetDebugFromConsole(string levelString) + { + try { - try + if (levelString.Trim() == "?") { - if (levelString.Trim() == "?") - { - CrestronConsole.ConsoleCommandResponse( - $@"Used to set the minimum level of debug messages to be printed to the console: -{_logLevels[0]} = 0 -{_logLevels[1]} = 1 -{_logLevels[2]} = 2 -{_logLevels[3]} = 3 -{_logLevels[4]} = 4 -{_logLevels[5]} = 5"); - return; - } - - if (string.IsNullOrEmpty(levelString.Trim())) - { - CrestronConsole.ConsoleCommandResponse("AppDebug level = {0}", _consoleLoggingLevelSwitch.MinimumLevel); - return; - } + CrestronConsole.ConsoleCommandResponse( + "Used to set the minimum level of debug messages to be printed to the console:\r\n" + + $"{_logLevels[0]} = 0\r\n" + + $"{_logLevels[1]} = 1\r\n" + + $"{_logLevels[2]} = 2\r\n" + + $"{_logLevels[3]} = 3\r\n" + + $"{_logLevels[4]} = 4\r\n" + + $"{_logLevels[5]} = 5"); + return; + } - if(int.TryParse(levelString, out var levelInt)) - { - if(levelInt < 0 || levelInt > 5) - { - CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level. If using a number, value must be between 0-5"); - return; - } - SetDebugLevel((uint) levelInt); - return; - } + if (string.IsNullOrEmpty(levelString.Trim())) + { + CrestronConsole.ConsoleCommandResponse("AppDebug level = {0}", _consoleLoggingLevelSwitch.MinimumLevel); + return; + } - if(Enum.TryParse(levelString, out var levelEnum)) + if (int.TryParse(levelString, out var levelInt)) + { + if (levelInt < 0 || levelInt > 5) { - SetDebugLevel(levelEnum); + CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level. If using a number, value must be between 0-5"); return; } + SetDebugLevel((uint)levelInt); + return; + } - CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level"); - } - catch + if (Enum.TryParse(levelString, out var levelEnum)) { - CrestronConsole.ConsoleCommandResponse("Usage: appdebug:P [0-5]"); + SetDebugLevel(levelEnum); + return; } - } - /// - /// Sets the debug level - /// - /// Valid values 0-5 - public static void SetDebugLevel(uint level) + CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level"); + } + catch { - if(!_logLevels.TryGetValue(level, out var logLevel)) - { - logLevel = LogEventLevel.Information; + CrestronConsole.ConsoleCommandResponse("Usage: appdebug:P [0-5]"); + } + } - CrestronConsole.ConsoleCommandResponse($"{level} not valid. Setting level to {logLevel}"); + /// + /// Sets the debug level + /// + /// Valid values 0-5 + public static void SetDebugLevel(uint level) + { + if (!_logLevels.TryGetValue(level, out var logLevel)) + { + logLevel = LogEventLevel.Information; - SetDebugLevel(logLevel); - } + CrestronConsole.ConsoleCommandResponse($"{level} not valid. Setting level to {logLevel}"); SetDebugLevel(logLevel); } - public static void SetDebugLevel(LogEventLevel level) - { - _consoleLoggingLevelSwitch.MinimumLevel = level; + SetDebugLevel(logLevel); + } - CrestronConsole.ConsoleCommandResponse("[Application {0}], Debug level set to {1}\r\n", - InitialParametersClass.ApplicationNumber, _consoleLoggingLevelSwitch.MinimumLevel); + public static void SetDebugLevel(LogEventLevel level) + { + _consoleLoggingLevelSwitch.MinimumLevel = level; - CrestronConsole.ConsoleCommandResponse($"Storing level {level}:{(int) level}"); + CrestronConsole.ConsoleCommandResponse("[Application {0}], Debug level set to {1}\r\n", + InitialParametersClass.ApplicationNumber, _consoleLoggingLevelSwitch.MinimumLevel); - var err = CrestronDataStoreStatic.SetLocalIntValue(LevelStoreKey, (int) level); + CrestronConsole.ConsoleCommandResponse($"Storing level {level}:{(int)level}"); - CrestronConsole.ConsoleCommandResponse($"Store result: {err}:{(int)level}"); + var err = CrestronDataStoreStatic.SetLocalIntValue(LevelStoreKey, (int)level); - if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) - CrestronConsole.PrintLine($"Error saving console debug level setting: {err}"); - } + CrestronConsole.ConsoleCommandResponse($"Store result: {err}:{(int)level}"); - public static void SetWebSocketMinimumDebugLevel(LogEventLevel level) - { - _websocketLoggingLevelSwitch.MinimumLevel = level; + if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + CrestronConsole.PrintLine($"Error saving console debug level setting: {err}"); + } - var err = CrestronDataStoreStatic.SetLocalUintValue(WebSocketLevelStoreKey, (uint) level); + public static void SetWebSocketMinimumDebugLevel(LogEventLevel level) + { + _websocketLoggingLevelSwitch.MinimumLevel = level; - if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) - LogMessage(LogEventLevel.Information, "Error saving websocket debug level setting: {erro}", err); + var err = CrestronDataStoreStatic.SetLocalUintValue(WebSocketLevelStoreKey, (uint)level); - LogMessage(LogEventLevel.Information, "Websocket debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel); - } + if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + LogMessage(LogEventLevel.Information, "Error saving websocket debug level setting: {erro}", err); - public static void SetErrorLogMinimumDebugLevel(LogEventLevel level) - { - _errorLogLevelSwitch.MinimumLevel = level; + LogMessage(LogEventLevel.Information, "Websocket debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel); + } - var err = CrestronDataStoreStatic.SetLocalUintValue(ErrorLogLevelStoreKey, (uint)level); + public static void SetErrorLogMinimumDebugLevel(LogEventLevel level) + { + _errorLogLevelSwitch.MinimumLevel = level; - if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) - LogMessage(LogEventLevel.Information, "Error saving Error Log debug level setting: {error}", err); + var err = CrestronDataStoreStatic.SetLocalUintValue(ErrorLogLevelStoreKey, (uint)level); - LogMessage(LogEventLevel.Information, "Error log debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel); - } + if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + LogMessage(LogEventLevel.Information, "Error saving Error Log debug level setting: {error}", err); - public static void SetFileMinimumDebugLevel(LogEventLevel level) - { - _errorLogLevelSwitch.MinimumLevel = level; + LogMessage(LogEventLevel.Information, "Error log debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel); + } - var err = CrestronDataStoreStatic.SetLocalUintValue(ErrorLogLevelStoreKey, (uint)level); + public static void SetFileMinimumDebugLevel(LogEventLevel level) + { + _errorLogLevelSwitch.MinimumLevel = level; + + var err = CrestronDataStoreStatic.SetLocalUintValue(ErrorLogLevelStoreKey, (uint)level); - if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) - LogMessage(LogEventLevel.Information, "Error saving File debug level setting: {error}", err); + if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + LogMessage(LogEventLevel.Information, "Error saving File debug level setting: {error}", err); + + LogMessage(LogEventLevel.Information, "File debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel); + } + + /// + /// Callback for console command + /// + /// + public static void SetDoNotLoadOnNextBootFromConsole(string stateString) + { + try + { + if (string.IsNullOrEmpty(stateString.Trim())) + { + CrestronConsole.ConsoleCommandResponse("DoNotLoadOnNextBoot = {0}", DoNotLoadConfigOnNextBoot); + return; + } - LogMessage(LogEventLevel.Information, "File debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel); + SetDoNotLoadConfigOnNextBoot(bool.Parse(stateString)); } + catch + { + CrestronConsole.ConsoleCommandResponse("Usage: donotloadonnextboot:P [true/false]"); + } + } - /// - /// Callback for console command - /// - /// - public static void SetDoNotLoadOnNextBootFromConsole(string stateString) + /// + /// Callback for console command + /// + /// + public static void SetDebugFilterFromConsole(string items) + { + var str = items.Trim(); + if (str == "?") { - try + CrestronConsole.ConsoleCommandResponse("Usage:\r APPDEBUGFILTER key1 key2 key3....\r " + + "+all: at beginning puts filter into 'default include' mode\r" + + " All keys that follow will be excluded from output.\r" + + "-all: at beginning puts filter into 'default exclude all' mode.\r" + + " All keys that follow will be the only keys that are shown\r" + + "+nokey: Enables messages with no key (default)\r" + + "-nokey: Disables messages with no key.\r" + + "(nokey settings are independent of all other settings)"); + return; + } + var keys = Regex.Split(str, @"\s*"); + foreach (var keyToken in keys) + { + var lkey = keyToken.ToLower(); + if (lkey == "+all") + { + IncludedExcludedKeys.Clear(); + _excludeAllMode = false; + } + else if (lkey == "-all") + { + IncludedExcludedKeys.Clear(); + _excludeAllMode = true; + } + //else if (lkey == "+nokey") + //{ + // ExcludeNoKeyMessages = false; + //} + //else if (lkey == "-nokey") + //{ + // ExcludeNoKeyMessages = true; + //} + else { - if (string.IsNullOrEmpty(stateString.Trim())) + string key; + if (lkey.StartsWith("-")) { - CrestronConsole.ConsoleCommandResponse("DoNotLoadOnNextBoot = {0}", DoNotLoadConfigOnNextBoot); - return; + key = lkey.Substring(1); + // if in exclude all mode, we need to remove this from the inclusions + if (_excludeAllMode) + { + if (IncludedExcludedKeys.ContainsKey(key)) + IncludedExcludedKeys.Remove(key); + } + // otherwise include all mode, add to the exclusions + else + { + IncludedExcludedKeys[key] = new object(); + } } + else if (lkey.StartsWith("+")) + { + key = lkey.Substring(1); + // if in exclude all mode, we need to add this as inclusion + if (_excludeAllMode) + { - SetDoNotLoadConfigOnNextBoot(bool.Parse(stateString)); - } - catch - { - CrestronConsole.ConsoleCommandResponse("Usage: donotloadonnextboot:P [true/false]"); + IncludedExcludedKeys[key] = new object(); + } + // otherwise include all mode, remove this from exclusions + else + { + if (IncludedExcludedKeys.ContainsKey(key)) + IncludedExcludedKeys.Remove(key); + } + } } } - - /// - /// Callback for console command - /// - /// - public static void SetDebugFilterFromConsole(string items) - { - var str = items.Trim(); - if (str == "?") - { - CrestronConsole.ConsoleCommandResponse("Usage:\r APPDEBUGFILTER key1 key2 key3....\r " + - "+all: at beginning puts filter into 'default include' mode\r" + - " All keys that follow will be excluded from output.\r" + - "-all: at beginning puts filter into 'default exclude all' mode.\r" + - " All keys that follow will be the only keys that are shown\r" + - "+nokey: Enables messages with no key (default)\r" + - "-nokey: Disables messages with no key.\r" + - "(nokey settings are independent of all other settings)"); - return; - } - var keys = Regex.Split(str, @"\s*"); - foreach (var keyToken in keys) - { - var lkey = keyToken.ToLower(); - if (lkey == "+all") - { - IncludedExcludedKeys.Clear(); - _excludeAllMode = false; - } - else if (lkey == "-all") - { - IncludedExcludedKeys.Clear(); - _excludeAllMode = true; - } - //else if (lkey == "+nokey") - //{ - // ExcludeNoKeyMessages = false; - //} - //else if (lkey == "-nokey") - //{ - // ExcludeNoKeyMessages = true; - //} - else - { - string key; - if (lkey.StartsWith("-")) - { - key = lkey.Substring(1); - // if in exclude all mode, we need to remove this from the inclusions - if (_excludeAllMode) - { - if (IncludedExcludedKeys.ContainsKey(key)) - IncludedExcludedKeys.Remove(key); - } - // otherwise include all mode, add to the exclusions - else - { - IncludedExcludedKeys[key] = new object(); - } - } - else if (lkey.StartsWith("+")) - { - key = lkey.Substring(1); - // if in exclude all mode, we need to add this as inclusion - if (_excludeAllMode) - { - - IncludedExcludedKeys[key] = new object(); - } - // otherwise include all mode, remove this from exclusions - else - { - if (IncludedExcludedKeys.ContainsKey(key)) - IncludedExcludedKeys.Remove(key); - } - } - } - } - } + } - /// - /// sets the settings for a device or creates a new entry - /// - /// - /// - /// - public static void SetDeviceDebugSettings(string deviceKey, object settings) - { - _contexts.SetDebugSettingsForKey(deviceKey, settings); - SaveMemoryOnTimeout(); - } + /// + /// sets the settings for a device or creates a new entry + /// + /// + /// + /// + public static void SetDeviceDebugSettings(string deviceKey, object settings) + { + _contexts.SetDebugSettingsForKey(deviceKey, settings); + SaveMemoryOnTimeout(); + } - /// - /// Gets the device settings for a device by key or returns null - /// - /// - /// - public static object GetDeviceDebugSettingsForKey(string deviceKey) - { - return _contexts.GetDebugSettingsForKey(deviceKey); - } + /// + /// Gets the device settings for a device by key or returns null + /// + /// + /// + public static object GetDeviceDebugSettingsForKey(string deviceKey) + { + return _contexts.GetDebugSettingsForKey(deviceKey); + } - /// - /// Sets the flag to prevent application starting on next boot - /// - /// - public static void SetDoNotLoadConfigOnNextBoot(bool state) - { - DoNotLoadConfigOnNextBoot = state; - _contexts.GetOrCreateItem("DEFAULT").DoNotLoadOnNextBoot = state; - SaveMemoryOnTimeout(); + /// + /// Sets the flag to prevent application starting on next boot + /// + /// + public static void SetDoNotLoadConfigOnNextBoot(bool state) + { + DoNotLoadConfigOnNextBoot = state; - CrestronConsole.ConsoleCommandResponse("[Application {0}], Do Not Load Config on Next Boot set to {1}", - InitialParametersClass.ApplicationNumber, DoNotLoadConfigOnNextBoot); - } + var err = CrestronDataStoreStatic.SetLocalBoolValue(DoNotLoadOnNextBootKey, state); - /// - /// - /// - public static void ShowDebugLog(string s) - { - var loglist = CrestronLogger.PrintTheLog(s.ToLower() == "all"); - foreach (var l in loglist) - CrestronConsole.ConsoleCommandResponse(l + CrestronEnvironment.NewLine); - } + if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS) + LogError("Error saving console debug level setting: {err}", err); - /// - /// Log an Exception as an Error - /// - /// Exception to log - /// Message template - /// Optional IKeyed device. If provided, the Key of the device will be added to the log message - /// Args to put into message template - public static void LogMessage(Exception ex, string message, IKeyed device = null, params object[] args) - { - using (LogContext.PushProperty("Key", device?.Key)) - { - _logger.Error(ex, message, args); - } - } + LogInformation("Do Not Load Config on Next Boot set to {state}", DoNotLoadConfigOnNextBoot); + } - /// - /// Log a message - /// - /// Level to log at - /// Message template - /// Optional IKeyed device. If provided, the Key of the device will be added to the log message - /// Args to put into message template - public static void LogMessage(LogEventLevel level, string message, IKeyed device = null, params object[] args) - { - using (LogContext.PushProperty("Key", device?.Key)) - { - _logger.Write(level, message, args); - } - } + /// + /// + /// + public static void ShowDebugLog(string s) + { + var loglist = CrestronLogger.PrintTheLog(s.ToLower() == "all"); + foreach (var l in loglist) + CrestronConsole.ConsoleCommandResponse(l + CrestronEnvironment.NewLine); + } - public static void LogMessage(LogEventLevel level, string message, params object[] args) + /// + /// Log an Exception as an Error + /// + /// Exception to log + /// Message template + /// Optional IKeyed device. If provided, the Key of the device will be added to the log message + /// Args to put into message template + public static void LogMessage(Exception ex, string message, IKeyed device = null, params object[] args) + { + using (LogContext.PushProperty("Key", device?.Key)) { - _logger.Write(level, message, args); + _logger.Error(ex, message, args); } + } - public static void LogMessage(LogEventLevel level, Exception ex, string message, params object[] args) + /// + /// Log a message + /// + /// Level to log at + /// Message template + /// Optional IKeyed device. If provided, the Key of the device will be added to the log message + /// Args to put into message template + public static void LogMessage(LogEventLevel level, string message, IKeyed device = null, params object[] args) + { + using (LogContext.PushProperty("Key", device?.Key)) { - _logger.Write(level, ex, message, args); + _logger.Write(level, message, args); } + } - public static void LogMessage(LogEventLevel level, IKeyed keyed, string message, params object[] args) - { - LogMessage(level, message, keyed, args); - } + public static void LogMessage(LogEventLevel level, string message, params object[] args) + { + _logger.Write(level, message, args); + } - public static void LogMessage(LogEventLevel level, Exception ex, IKeyed device, string message, params object[] args) - { - using (LogContext.PushProperty("Key", device?.Key)) - { - _logger.Write(level, ex, message, args); - } - } + public static void LogMessage(LogEventLevel level, Exception ex, string message, params object[] args) + { + _logger.Write(level, ex, message, args); + } - #region Explicit methods for logging levels - public static void LogVerbose(IKeyed keyed, string message, params object[] args) - { - using(LogContext.PushProperty("Key", keyed?.Key)) - { - _logger.Write(LogEventLevel.Verbose, message, args); - } - } + public static void LogMessage(LogEventLevel level, IKeyed keyed, string message, params object[] args) + { + LogMessage(level, message, keyed, args); + } - public static void LogVerbose(Exception ex, IKeyed keyed, string message, params object[] args) + public static void LogMessage(LogEventLevel level, Exception ex, IKeyed device, string message, params object[] args) + { + using (LogContext.PushProperty("Key", device?.Key)) { - using(LogContext.PushProperty("Key", keyed?.Key)) - { - _logger.Write(LogEventLevel.Verbose, ex, message, args); - } + _logger.Write(level, ex, message, args); } + } - public static void LogVerbose(string message, params object[] args) + #region Explicit methods for logging levels + public static void LogVerbose(IKeyed keyed, string message, params object[] args) + { + using (LogContext.PushProperty("Key", keyed?.Key)) { _logger.Write(LogEventLevel.Verbose, message, args); } + } - public static void LogVerbose(Exception ex, string message, params object[] args) + public static void LogVerbose(Exception ex, IKeyed keyed, string message, params object[] args) + { + using (LogContext.PushProperty("Key", keyed?.Key)) { - _logger.Write(LogEventLevel.Verbose, ex, null, message, args); + _logger.Write(LogEventLevel.Verbose, ex, message, args); } + } - public static void LogDebug(IKeyed keyed, string message, params object[] args) - { - using (LogContext.PushProperty("Key", keyed?.Key)) - { - _logger.Write(LogEventLevel.Debug, message, args); - } - } + public static void LogVerbose(string message, params object[] args) + { + _logger.Write(LogEventLevel.Verbose, message, args); + } - public static void LogDebug(Exception ex, IKeyed keyed, string message, params object[] args) - { - using (LogContext.PushProperty("Key", keyed?.Key)) - { - _logger.Write(LogEventLevel.Debug, ex, message, args); - } - } + public static void LogVerbose(Exception ex, string message, params object[] args) + { + _logger.Write(LogEventLevel.Verbose, ex, null, message, args); + } - public static void LogDebug(string message, params object[] args) + public static void LogDebug(IKeyed keyed, string message, params object[] args) + { + using (LogContext.PushProperty("Key", keyed?.Key)) { _logger.Write(LogEventLevel.Debug, message, args); } + } - public static void LogDebug(Exception ex, string message, params object[] args) + public static void LogDebug(Exception ex, IKeyed keyed, string message, params object[] args) + { + using (LogContext.PushProperty("Key", keyed?.Key)) { - _logger.Write(LogEventLevel.Debug, ex, null, message, args); + _logger.Write(LogEventLevel.Debug, ex, message, args); } + } - public static void LogInformation(IKeyed keyed, string message, params object[] args) - { - using (LogContext.PushProperty("Key", keyed?.Key)) - { - _logger.Write(LogEventLevel.Information, message, args); - } - } + public static void LogDebug(string message, params object[] args) + { + _logger.Write(LogEventLevel.Debug, message, args); + } - public static void LogInformation(Exception ex, IKeyed keyed, string message, params object[] args) - { - using (LogContext.PushProperty("Key", keyed?.Key)) - { - _logger.Write(LogEventLevel.Information, ex, message, args); - } - } + public static void LogDebug(Exception ex, string message, params object[] args) + { + _logger.Write(LogEventLevel.Debug, ex, null, message, args); + } - public static void LogInformation(string message, params object[] args) + public static void LogInformation(IKeyed keyed, string message, params object[] args) + { + using (LogContext.PushProperty("Key", keyed?.Key)) { _logger.Write(LogEventLevel.Information, message, args); } + } - public static void LogInformation(Exception ex, string message, params object[] args) + public static void LogInformation(Exception ex, IKeyed keyed, string message, params object[] args) + { + using (LogContext.PushProperty("Key", keyed?.Key)) { - _logger.Write(LogEventLevel.Information, ex, null, message, args); + _logger.Write(LogEventLevel.Information, ex, message, args); } + } - public static void LogWarning(IKeyed keyed, string message, params object[] args) - { - using (LogContext.PushProperty("Key", keyed?.Key)) - { - _logger.Write(LogEventLevel.Warning, message, args); - } - } + public static void LogInformation(string message, params object[] args) + { + _logger.Write(LogEventLevel.Information, message, args); + } - public static void LogWarning(Exception ex, IKeyed keyed, string message, params object[] args) - { - using (LogContext.PushProperty("Key", keyed?.Key)) - { - _logger.Write(LogEventLevel.Warning, ex, message, args); - } - } + public static void LogInformation(Exception ex, string message, params object[] args) + { + _logger.Write(LogEventLevel.Information, ex, null, message, args); + } - public static void LogWarning(string message, params object[] args) + public static void LogWarning(IKeyed keyed, string message, params object[] args) + { + using (LogContext.PushProperty("Key", keyed?.Key)) { _logger.Write(LogEventLevel.Warning, message, args); } + } - public static void LogWarning(Exception ex, string message, params object[] args) + public static void LogWarning(Exception ex, IKeyed keyed, string message, params object[] args) + { + using (LogContext.PushProperty("Key", keyed?.Key)) { - _logger.Write(LogEventLevel.Warning, ex, null, message, args); + _logger.Write(LogEventLevel.Warning, ex, message, args); } + } - public static void LogError(IKeyed keyed, string message, params object[] args) - { - using (LogContext.PushProperty("Key", keyed?.Key)) - { - _logger.Write(LogEventLevel.Error, message, args); - } - } + public static void LogWarning(string message, params object[] args) + { + _logger.Write(LogEventLevel.Warning, message, args); + } - public static void LogError(Exception ex, IKeyed keyed, string message, params object[] args) - { - using (LogContext.PushProperty("Key", keyed?.Key)) - { - _logger.Write(LogEventLevel.Error, ex, message, args); - } - } + public static void LogWarning(Exception ex, string message, params object[] args) + { + _logger.Write(LogEventLevel.Warning, ex, null, message, args); + } - public static void LogError(string message, params object[] args) + public static void LogError(IKeyed keyed, string message, params object[] args) + { + using (LogContext.PushProperty("Key", keyed?.Key)) { _logger.Write(LogEventLevel.Error, message, args); } + } - public static void LogError(Exception ex, string message, params object[] args) + public static void LogError(Exception ex, IKeyed keyed, string message, params object[] args) + { + using (LogContext.PushProperty("Key", keyed?.Key)) { - _logger.Write(LogEventLevel.Error, ex, null, message, args); + _logger.Write(LogEventLevel.Error, ex, message, args); } + } - public static void LogFatal(IKeyed keyed, string message, params object[] args) - { - using (LogContext.PushProperty("Key", keyed?.Key)) - { - _logger.Write(LogEventLevel.Fatal, message, args); - } - } + public static void LogError(string message, params object[] args) + { + _logger.Write(LogEventLevel.Error, message, args); + } - public static void LogFatal(Exception ex, IKeyed keyed, string message, params object[] args) - { - using (LogContext.PushProperty("Key", keyed?.Key)) - { - _logger.Write(LogEventLevel.Fatal, ex, message, args); - } - } + public static void LogError(Exception ex, string message, params object[] args) + { + _logger.Write(LogEventLevel.Error, ex, null, message, args); + } - public static void LogFatal(string message, params object[] args) + public static void LogFatal(IKeyed keyed, string message, params object[] args) + { + using (LogContext.PushProperty("Key", keyed?.Key)) { _logger.Write(LogEventLevel.Fatal, message, args); } + } - public static void LogFatal(Exception ex, string message, params object[] args) + public static void LogFatal(Exception ex, IKeyed keyed, string message, params object[] args) + { + using (LogContext.PushProperty("Key", keyed?.Key)) { - _logger.Write(LogEventLevel.Fatal, ex, null, message, args); + _logger.Write(LogEventLevel.Fatal, ex, message, args); } + } - #endregion + public static void LogFatal(string message, params object[] args) + { + _logger.Write(LogEventLevel.Fatal, message, args); + } + public static void LogFatal(Exception ex, string message, params object[] args) + { + _logger.Write(LogEventLevel.Fatal, ex, null, message, args); + } - private static void LogMessage(uint level, string format, params object[] items) - { - if (!_logLevels.ContainsKey(level)) return; + #endregion - var logLevel = _logLevels[level]; - - LogMessage(logLevel, format, items); - } - private static void LogMessage(uint level, IKeyed keyed, string format, params object[] items) - { - if (!_logLevels.ContainsKey(level)) return; + private static void LogMessage(uint level, string format, params object[] items) + { + if (!_logLevels.ContainsKey(level)) return; - var logLevel = _logLevels[level]; + var logLevel = _logLevels[level]; - LogMessage(logLevel, keyed, format, items); - } + LogMessage(logLevel, format, items); + } + private static void LogMessage(uint level, IKeyed keyed, string format, params object[] items) + { + if (!_logLevels.ContainsKey(level)) return; - /// - /// Prints message to console if current debug level is equal to or higher than the level of this message. - /// Uses CrestronConsole.PrintLine. - /// - /// - /// Console format string - /// Object parameters - [Obsolete("Use LogMessage methods. Will be removed in 2.2.0 and later versions")] - public static void Console(uint level, string format, params object[] items) - { + var logLevel = _logLevels[level]; - LogMessage(level, format, items); + LogMessage(logLevel, keyed, format, items); + } - //if (IsRunningOnAppliance) - //{ - // CrestronConsole.PrintLine("[{0}]App {1} Lvl {2}:{3}", DateTime.Now.ToString("HH:mm:ss.fff"), - // InitialParametersClass.ApplicationNumber, - // level, - // string.Format(format, items)); - //} - } - /// - /// Logs to Console when at-level, and all messages to error log, including device key - /// - [Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")] - public static void Console(uint level, IKeyed dev, string format, params object[] items) - { - LogMessage(level, dev, format, items); + /// + /// Prints message to console if current debug level is equal to or higher than the level of this message. + /// Uses CrestronConsole.PrintLine. + /// + /// + /// Console format string + /// Object parameters + [Obsolete("Use LogMessage methods. Will be removed in 2.2.0 and later versions")] + public static void Console(uint level, string format, params object[] items) + { - //if (Level >= level) - // Console(level, "[{0}] {1}", dev.Key, message); - } + LogMessage(level, format, items); - /// - /// Prints message to console if current debug level is equal to or higher than the level of this message. Always sends message to Error Log. - /// Uses CrestronConsole.PrintLine. - /// - [Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")] - public static void Console(uint level, IKeyed dev, ErrorLogLevel errorLogLevel, - string format, params object[] items) - { - LogMessage(level, dev, format, items); - } + //if (IsRunningOnAppliance) + //{ + // CrestronConsole.PrintLine("[{0}]App {1} Lvl {2}:{3}", DateTime.Now.ToString("HH:mm:ss.fff"), + // InitialParametersClass.ApplicationNumber, + // level, + // string.Format(format, items)); + //} + } - /// - /// Logs to Console when at-level, and all messages to error log - /// - [Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")] - public static void Console(uint level, ErrorLogLevel errorLogLevel, - string format, params object[] items) - { - LogMessage(level, format, items); - } + /// + /// Logs to Console when at-level, and all messages to error log, including device key + /// + [Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")] + public static void Console(uint level, IKeyed dev, string format, params object[] items) + { + LogMessage(level, dev, format, items); - /// - /// Logs to both console and the custom user log (not the built-in error log). If appdebug level is set at - /// or above the level provided, then the output will be written to both console and the log. Otherwise - /// it will only be written to the log. - /// - [Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")] - public static void ConsoleWithLog(uint level, string format, params object[] items) - { - LogMessage(level, format, items); + //if (Level >= level) + // Console(level, "[{0}] {1}", dev.Key, message); + } - // var str = string.Format(format, items); - //if (Level >= level) - // CrestronConsole.PrintLine("App {0}:{1}", InitialParametersClass.ApplicationNumber, str); - // CrestronLogger.WriteToLog(str, level); - } + /// + /// Prints message to console if current debug level is equal to or higher than the level of this message. Always sends message to Error Log. + /// Uses CrestronConsole.PrintLine. + /// + [Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")] + public static void Console(uint level, IKeyed dev, ErrorLogLevel errorLogLevel, + string format, params object[] items) + { + LogMessage(level, dev, format, items); + } - /// - /// Logs to both console and the custom user log (not the built-in error log). If appdebug level is set at - /// or above the level provided, then the output will be written to both console and the log. Otherwise - /// it will only be written to the log. - /// - [Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")] - public static void ConsoleWithLog(uint level, IKeyed dev, string format, params object[] items) - { - LogMessage(level, dev, format, items); + /// + /// Logs to Console when at-level, and all messages to error log + /// + [Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")] + public static void Console(uint level, ErrorLogLevel errorLogLevel, + string format, params object[] items) + { + LogMessage(level, format, items); + } - // var str = string.Format(format, items); - // CrestronLogger.WriteToLog(string.Format("[{0}] {1}", dev.Key, str), level); - } + /// + /// Logs to both console and the custom user log (not the built-in error log). If appdebug level is set at + /// or above the level provided, then the output will be written to both console and the log. Otherwise + /// it will only be written to the log. + /// + [Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")] + public static void ConsoleWithLog(uint level, string format, params object[] items) + { + LogMessage(level, format, items); - /// - /// Prints to log and error log - /// - /// - /// - [Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")] - public static void LogError(ErrorLogLevel errorLogLevel, string str) - { - switch (errorLogLevel) - { - case ErrorLogLevel.Error: - LogMessage(LogEventLevel.Error, str); - break; - case ErrorLogLevel.Warning: - LogMessage(LogEventLevel.Warning, str); - break; - case ErrorLogLevel.Notice: - LogMessage(LogEventLevel.Information, str); - break; - } - } + // var str = string.Format(format, items); + //if (Level >= level) + // CrestronConsole.PrintLine("App {0}:{1}", InitialParametersClass.ApplicationNumber, str); + // CrestronLogger.WriteToLog(str, level); + } - /// - /// Writes the memory object after timeout - /// - static void SaveMemoryOnTimeout() + /// + /// Logs to both console and the custom user log (not the built-in error log). If appdebug level is set at + /// or above the level provided, then the output will be written to both console and the log. Otherwise + /// it will only be written to the log. + /// + [Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")] + public static void ConsoleWithLog(uint level, IKeyed dev, string format, params object[] items) + { + LogMessage(level, dev, format, items); + + // var str = string.Format(format, items); + // CrestronLogger.WriteToLog(string.Format("[{0}] {1}", dev.Key, str), level); + } + + /// + /// Prints to log and error log + /// + /// + /// + [Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")] + public static void LogError(ErrorLogLevel errorLogLevel, string str) + { + switch (errorLogLevel) { - Console(0, "Saving debug settings"); - if (_saveTimer == null) - _saveTimer = new CTimer(o => - { - _saveTimer = null; - SaveMemory(); - }, SaveTimeoutMs); - else - _saveTimer.Reset(SaveTimeoutMs); + case ErrorLogLevel.Error: + LogMessage(LogEventLevel.Error, str); + break; + case ErrorLogLevel.Warning: + LogMessage(LogEventLevel.Warning, str); + break; + case ErrorLogLevel.Notice: + LogMessage(LogEventLevel.Information, str); + break; } + } - /// - /// Writes the memory - use SaveMemoryOnTimeout - /// - static void SaveMemory() - { - //var dir = @"\NVRAM\debug"; - //if (!Directory.Exists(dir)) - // Directory.Create(dir); + /// + /// Writes the memory object after timeout + /// + static void SaveMemoryOnTimeout() + { + Console(0, "Saving debug settings"); + if (_saveTimer == null) + _saveTimer = new CTimer(o => + { + _saveTimer = null; + SaveMemory(); + }, SaveTimeoutMs); + else + _saveTimer.Reset(SaveTimeoutMs); + } + + /// + /// Writes the memory - use SaveMemoryOnTimeout + /// + static void SaveMemory() + { + //var dir = @"\NVRAM\debug"; + //if (!Directory.Exists(dir)) + // Directory.Create(dir); + try + { var fileName = GetMemoryFileName(); LogMessage(LogEventLevel.Information, "Loading debug settings file from {fileName}", fileName); @@ -963,66 +970,72 @@ static void SaveMemory() sw.Flush(); } } + catch (Exception ex) + { + ErrorLog.Error("Exception saving debug settings: {message}", ex); + CrestronConsole.PrintLine("Exception saving debug settings: {message}", ex.Message); + return; + } + } - /// - /// - /// - static void LoadMemory() + /// + /// + /// + static void LoadMemory() + { + var file = GetMemoryFileName(); + if (File.Exists(file)) { - var file = GetMemoryFileName(); - if (File.Exists(file)) + using (var sr = new StreamReader(file)) { - using (var sr = new StreamReader(file)) - { - var json = sr.ReadToEnd(); - _contexts = JsonConvert.DeserializeObject(json); + var json = sr.ReadToEnd(); + _contexts = JsonConvert.DeserializeObject(json); - if (_contexts != null) - { - LogMessage(LogEventLevel.Debug, "Debug memory restored from file"); - return; - } + if (_contexts != null) + { + LogMessage(LogEventLevel.Debug, "Debug memory restored from file"); + return; } } - - _contexts = new DebugContextCollection(); } - /// - /// Helper to get the file path for this app's debug memory - /// - static string GetMemoryFileName() - { - if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance) - { - // CheckForMigration(); - return string.Format(@"\user\debugSettings\program{0}", InitialParametersClass.ApplicationNumber); - } + _contexts = new DebugContextCollection(); + } - return string.Format("{0}{1}user{1}debugSettings{1}{2}.json",Directory.GetApplicationRootDirectory(), Path.DirectorySeparatorChar, InitialParametersClass.RoomId); + /// + /// Helper to get the file path for this app's debug memory + /// + static string GetMemoryFileName() + { + if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance) + { + // CheckForMigration(); + return string.Format(@"\user\debugSettings\program{0}", InitialParametersClass.ApplicationNumber); } + return string.Format("{0}{1}user{1}debugSettings{1}{2}.json", Directory.GetApplicationRootDirectory(), Path.DirectorySeparatorChar, InitialParametersClass.RoomId); + } + + /// + /// Error level to for message to be logged at + /// + public enum ErrorLogLevel + { /// - /// Error level to for message to be logged at + /// Error /// - public enum ErrorLogLevel - { - /// - /// Error - /// - Error, - /// - /// Warning - /// - Warning, - /// - /// Notice - /// - Notice, - /// - /// None - /// - None, - } + Error, + /// + /// Warning + /// + Warning, + /// + /// Notice + /// + Notice, + /// + /// None + /// + None, } } \ No newline at end of file diff --git a/src/PepperDash.Core/Logging/DebugConsoleSink.cs b/src/PepperDash.Core/Logging/DebugConsoleSink.cs index a6c7f8935..5e32a8a51 100644 --- a/src/PepperDash.Core/Logging/DebugConsoleSink.cs +++ b/src/PepperDash.Core/Logging/DebugConsoleSink.cs @@ -9,47 +9,45 @@ using System.Text; -namespace PepperDash.Core -{ - public class DebugConsoleSink : ILogEventSink - { - private readonly ITextFormatter _textFormatter; - - public void Emit(LogEvent logEvent) - { - if (!Debug.IsRunningOnAppliance) return; +namespace PepperDash.Core; - /*string message = $"[{logEvent.Timestamp}][{logEvent.Level}][App {InitialParametersClass.ApplicationNumber}]{logEvent.RenderMessage()}"; +public class DebugConsoleSink : ILogEventSink +{ + private readonly ITextFormatter _textFormatter; - if(logEvent.Properties.TryGetValue("Key",out var value) && value is ScalarValue sv && sv.Value is string rawValue) - { - message = $"[{logEvent.Timestamp}][{logEvent.Level}][App {InitialParametersClass.ApplicationNumber}][{rawValue,3}]: {logEvent.RenderMessage()}"; - }*/ + public void Emit(LogEvent logEvent) + { + if (!Debug.IsRunningOnAppliance) return; - var buffer = new StringWriter(new StringBuilder(256)); + /*string message = $"[{logEvent.Timestamp}][{logEvent.Level}][App {InitialParametersClass.ApplicationNumber}]{logEvent.RenderMessage()}"; - _textFormatter.Format(logEvent, buffer); + if(logEvent.Properties.TryGetValue("Key",out var value) && value is ScalarValue sv && sv.Value is string rawValue) + { + message = $"[{logEvent.Timestamp}][{logEvent.Level}][App {InitialParametersClass.ApplicationNumber}][{rawValue,3}]: {logEvent.RenderMessage()}"; + }*/ - var message = buffer.ToString(); + var buffer = new StringWriter(new StringBuilder(256)); - CrestronConsole.PrintLine(message); - } + _textFormatter.Format(logEvent, buffer); - public DebugConsoleSink(ITextFormatter formatProvider ) - { - _textFormatter = formatProvider ?? new JsonFormatter(); - } + var message = buffer.ToString(); + CrestronConsole.PrintLine(message); } - public static class DebugConsoleSinkExtensions + public DebugConsoleSink(ITextFormatter formatProvider ) { - public static LoggerConfiguration DebugConsoleSink( - this LoggerSinkConfiguration loggerConfiguration, - ITextFormatter formatProvider = null) - { - return loggerConfiguration.Sink(new DebugConsoleSink(formatProvider)); - } + _textFormatter = formatProvider ?? new JsonFormatter(); } } + +public static class DebugConsoleSinkExtensions +{ + public static LoggerConfiguration DebugConsoleSink( + this LoggerSinkConfiguration loggerConfiguration, + ITextFormatter formatProvider = null) + { + return loggerConfiguration.Sink(new DebugConsoleSink(formatProvider)); + } +} diff --git a/src/PepperDash.Core/Logging/DebugContext.cs b/src/PepperDash.Core/Logging/DebugContext.cs index 54c874144..8b8d5f2c6 100644 --- a/src/PepperDash.Core/Logging/DebugContext.cs +++ b/src/PepperDash.Core/Logging/DebugContext.cs @@ -6,276 +6,275 @@ using Newtonsoft.Json; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// Represents a debugging context +/// +public class DebugContext { /// - /// Represents a debugging context + /// Describes the folder location where a given program stores it's debug level memory. By default, the + /// file written will be named appNdebug where N is 1-10. /// - public class DebugContext - { - /// - /// Describes the folder location where a given program stores it's debug level memory. By default, the - /// file written will be named appNdebug where N is 1-10. - /// - public string Key { get; private set; } + public string Key { get; private set; } - ///// - ///// The name of the file containing the current debug settings. - ///// - //string FileName = string.Format(@"\nvram\debug\app{0}Debug.json", InitialParametersClass.ApplicationNumber); + ///// + ///// The name of the file containing the current debug settings. + ///// + //string FileName = string.Format(@"\nvram\debug\app{0}Debug.json", InitialParametersClass.ApplicationNumber); - DebugContextSaveData SaveData; + DebugContextSaveData SaveData; - int SaveTimeoutMs = 30000; + int SaveTimeoutMs = 30000; - CTimer SaveTimer; + CTimer SaveTimer; - static List Contexts = new List(); + static List Contexts = new List(); - /// - /// Creates or gets a debug context - /// - /// - /// - public static DebugContext GetDebugContext(string key) + /// + /// Creates or gets a debug context + /// + /// + /// + public static DebugContext GetDebugContext(string key) + { + var context = Contexts.FirstOrDefault(c => c.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); + if (context == null) { - var context = Contexts.FirstOrDefault(c => c.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); - if (context == null) - { - context = new DebugContext(key); - Contexts.Add(context); - } - return context; + context = new DebugContext(key); + Contexts.Add(context); } + return context; + } - /// - /// Do not use. For S+ access. - /// - public DebugContext() { } + /// + /// Do not use. For S+ access. + /// + public DebugContext() { } - DebugContext(string key) + DebugContext(string key) + { + Key = key; + if (CrestronEnvironment.RuntimeEnvironment == eRuntimeEnvironment.SimplSharpPro) { - Key = key; - if (CrestronEnvironment.RuntimeEnvironment == eRuntimeEnvironment.SimplSharpPro) - { - // Add command to console - CrestronConsole.AddNewConsoleCommand(SetDebugFromConsole, "appdebug", - "appdebug:P [0-2]: Sets the application's console debug message level", - ConsoleAccessLevelEnum.AccessOperator); - } + // Add command to console + CrestronConsole.AddNewConsoleCommand(SetDebugFromConsole, "appdebug", + "appdebug:P [0-2]: Sets the application's console debug message level", + ConsoleAccessLevelEnum.AccessOperator); + } - CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler; + CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler; - LoadMemory(); - } + LoadMemory(); + } - /// - /// Used to save memory when shutting down - /// - /// - void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + /// + /// Used to save memory when shutting down + /// + /// + void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + { + if (programEventType == eProgramStatusEventType.Stopping) { - if (programEventType == eProgramStatusEventType.Stopping) + if (SaveTimer != null) { - if (SaveTimer != null) - { - SaveTimer.Stop(); - SaveTimer = null; - } - Console(0, "Saving debug settings"); - SaveMemory(); + SaveTimer.Stop(); + SaveTimer = null; } + Console(0, "Saving debug settings"); + SaveMemory(); } + } - /// - /// Callback for console command - /// - /// - public void SetDebugFromConsole(string levelString) + /// + /// Callback for console command + /// + /// + public void SetDebugFromConsole(string levelString) + { + try { - try + if (string.IsNullOrEmpty(levelString.Trim())) { - if (string.IsNullOrEmpty(levelString.Trim())) - { - CrestronConsole.ConsoleCommandResponse("AppDebug level = {0}", SaveData.Level); - return; - } - - SetDebugLevel(Convert.ToInt32(levelString)); + CrestronConsole.ConsoleCommandResponse("AppDebug level = {0}", SaveData.Level); + return; } - catch - { - CrestronConsole.PrintLine("Usage: appdebug:P [0-2]"); - } - } - /// - /// Sets the debug level - /// - /// Valid values 0 (no debug), 1 (critical), 2 (all messages) - public void SetDebugLevel(int level) - { - if (level <= 2) - { - SaveData.Level = level; - SaveMemoryOnTimeout(); - - CrestronConsole.PrintLine("[Application {0}], Debug level set to {1}", - InitialParametersClass.ApplicationNumber, SaveData.Level); - } + SetDebugLevel(Convert.ToInt32(levelString)); } - - /// - /// Prints message to console if current debug level is equal to or higher than the level of this message. - /// Uses CrestronConsole.PrintLine. - /// - /// - /// Console format string - /// Object parameters - public void Console(uint level, string format, params object[] items) + catch { - if (SaveData.Level >= level) - CrestronConsole.PrintLine("App {0}:{1}", InitialParametersClass.ApplicationNumber, - string.Format(format, items)); + CrestronConsole.PrintLine("Usage: appdebug:P [0-2]"); } + } - /// - /// Appends a device Key to the beginning of a message - /// - public void Console(uint level, IKeyed dev, string format, params object[] items) + /// + /// Sets the debug level + /// + /// Valid values 0 (no debug), 1 (critical), 2 (all messages) + public void SetDebugLevel(int level) + { + if (level <= 2) { - if (SaveData.Level >= level) - Console(level, "[{0}] {1}", dev.Key, string.Format(format, items)); - } + SaveData.Level = level; + SaveMemoryOnTimeout(); - /// - /// - /// - /// - /// - /// - /// - /// - public void Console(uint level, IKeyed dev, Debug.ErrorLogLevel errorLogLevel, - string format, params object[] items) - { - if (SaveData.Level >= level) - { - var str = string.Format("[{0}] {1}", dev.Key, string.Format(format, items)); - Console(level, str); - LogError(errorLogLevel, str); - } + CrestronConsole.PrintLine("[Application {0}], Debug level set to {1}", + InitialParametersClass.ApplicationNumber, SaveData.Level); } + } + + /// + /// Prints message to console if current debug level is equal to or higher than the level of this message. + /// Uses CrestronConsole.PrintLine. + /// + /// + /// Console format string + /// Object parameters + public void Console(uint level, string format, params object[] items) + { + if (SaveData.Level >= level) + CrestronConsole.PrintLine("App {0}:{1}", InitialParametersClass.ApplicationNumber, + string.Format(format, items)); + } - /// - /// - /// - /// - /// - /// - /// - public void Console(uint level, Debug.ErrorLogLevel errorLogLevel, - string format, params object[] items) + /// + /// Appends a device Key to the beginning of a message + /// + public void Console(uint level, IKeyed dev, string format, params object[] items) + { + if (SaveData.Level >= level) + Console(level, "[{0}] {1}", dev.Key, string.Format(format, items)); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public void Console(uint level, IKeyed dev, Debug.ErrorLogLevel errorLogLevel, + string format, params object[] items) + { + if (SaveData.Level >= level) { - if (SaveData.Level >= level) - { - var str = string.Format(format, items); - Console(level, str); - LogError(errorLogLevel, str); - } + var str = string.Format("[{0}] {1}", dev.Key, string.Format(format, items)); + Console(level, str); + LogError(errorLogLevel, str); } + } - /// - /// - /// - /// - /// - public void LogError(Debug.ErrorLogLevel errorLogLevel, string str) + /// + /// + /// + /// + /// + /// + /// + public void Console(uint level, Debug.ErrorLogLevel errorLogLevel, + string format, params object[] items) + { + if (SaveData.Level >= level) { - string msg = string.Format("App {0}:{1}", InitialParametersClass.ApplicationNumber, str); - switch (errorLogLevel) - { - case Debug.ErrorLogLevel.Error: - ErrorLog.Error(msg); - break; - case Debug.ErrorLogLevel.Warning: - ErrorLog.Warn(msg); - break; - case Debug.ErrorLogLevel.Notice: - ErrorLog.Notice(msg); - break; - } + var str = string.Format(format, items); + Console(level, str); + LogError(errorLogLevel, str); } + } - /// - /// Writes the memory object after timeout - /// - void SaveMemoryOnTimeout() + /// + /// + /// + /// + /// + public void LogError(Debug.ErrorLogLevel errorLogLevel, string str) + { + string msg = string.Format("App {0}:{1}", InitialParametersClass.ApplicationNumber, str); + switch (errorLogLevel) { - if (SaveTimer == null) - SaveTimer = new CTimer(o => - { - SaveTimer = null; - SaveMemory(); - }, SaveTimeoutMs); - else - SaveTimer.Reset(SaveTimeoutMs); + case Debug.ErrorLogLevel.Error: + ErrorLog.Error(msg); + break; + case Debug.ErrorLogLevel.Warning: + ErrorLog.Warn(msg); + break; + case Debug.ErrorLogLevel.Notice: + ErrorLog.Notice(msg); + break; } + } - /// - /// Writes the memory - use SaveMemoryOnTimeout - /// - void SaveMemory() - { - using (StreamWriter sw = new StreamWriter(GetMemoryFileName())) + /// + /// Writes the memory object after timeout + /// + void SaveMemoryOnTimeout() + { + if (SaveTimer == null) + SaveTimer = new CTimer(o => { - var json = JsonConvert.SerializeObject(SaveData); - sw.Write(json); - sw.Flush(); - } + SaveTimer = null; + SaveMemory(); + }, SaveTimeoutMs); + else + SaveTimer.Reset(SaveTimeoutMs); + } + + /// + /// Writes the memory - use SaveMemoryOnTimeout + /// + void SaveMemory() + { + using (StreamWriter sw = new StreamWriter(GetMemoryFileName())) + { + var json = JsonConvert.SerializeObject(SaveData); + sw.Write(json); + sw.Flush(); } + } - /// - /// - /// - void LoadMemory() + /// + /// + /// + void LoadMemory() + { + var file = GetMemoryFileName(); + if (File.Exists(file)) { - var file = GetMemoryFileName(); - if (File.Exists(file)) + using (StreamReader sr = new StreamReader(file)) { - using (StreamReader sr = new StreamReader(file)) + var data = JsonConvert.DeserializeObject(sr.ReadToEnd()); + if (data != null) { - var data = JsonConvert.DeserializeObject(sr.ReadToEnd()); - if (data != null) - { - SaveData = data; - Debug.Console(1, "Debug memory restored from file"); - return; - } - else - SaveData = new DebugContextSaveData(); + SaveData = data; + Debug.Console(1, "Debug memory restored from file"); + return; } + else + SaveData = new DebugContextSaveData(); } } - - /// - /// Helper to get the file path for this app's debug memory - /// - string GetMemoryFileName() - { - return string.Format(@"\NVRAM\debugSettings\program{0}-{1}", InitialParametersClass.ApplicationNumber, Key); - } } /// - /// + /// Helper to get the file path for this app's debug memory /// - public class DebugContextSaveData + string GetMemoryFileName() { - /// - /// - /// - public int Level { get; set; } + return string.Format(@"\NVRAM\debugSettings\program{0}-{1}", InitialParametersClass.ApplicationNumber, Key); } +} + +/// +/// +/// +public class DebugContextSaveData +{ + /// + /// + /// + public int Level { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Core/Logging/DebugCrestronLoggerSink.cs b/src/PepperDash.Core/Logging/DebugCrestronLoggerSink.cs index 0814453b6..a2e82ec8d 100644 --- a/src/PepperDash.Core/Logging/DebugCrestronLoggerSink.cs +++ b/src/PepperDash.Core/Logging/DebugCrestronLoggerSink.cs @@ -3,27 +3,26 @@ using Serilog.Core; using Serilog.Events; -namespace PepperDash.Core.Logging +namespace PepperDash.Core.Logging; + +public class DebugCrestronLoggerSink : ILogEventSink { - public class DebugCrestronLoggerSink : ILogEventSink + public void Emit(LogEvent logEvent) { - public void Emit(LogEvent logEvent) - { - if (!Debug.IsRunningOnAppliance) return; - - string message = $"[{logEvent.Timestamp}][{logEvent.Level}][App {InitialParametersClass.ApplicationNumber}]{logEvent.RenderMessage()}"; + if (!Debug.IsRunningOnAppliance) return; - if (logEvent.Properties.TryGetValue("Key", out var value) && value is ScalarValue sv && sv.Value is string rawValue) - { - message = $"[{logEvent.Timestamp}][{logEvent.Level}][App {InitialParametersClass.ApplicationNumber}][{rawValue}]: {logEvent.RenderMessage()}"; - } - - CrestronLogger.WriteToLog(message, (uint)logEvent.Level); - } + string message = $"[{logEvent.Timestamp}][{logEvent.Level}][App {InitialParametersClass.ApplicationNumber}]{logEvent.RenderMessage()}"; - public DebugCrestronLoggerSink() + if (logEvent.Properties.TryGetValue("Key", out var value) && value is ScalarValue sv && sv.Value is string rawValue) { - CrestronLogger.Initialize(1, LoggerModeEnum.RM); + message = $"[{logEvent.Timestamp}][{logEvent.Level}][App {InitialParametersClass.ApplicationNumber}][{rawValue}]: {logEvent.RenderMessage()}"; } + + CrestronLogger.WriteToLog(message, (uint)logEvent.Level); + } + + public DebugCrestronLoggerSink() + { + CrestronLogger.Initialize(1, LoggerModeEnum.RM); } } diff --git a/src/PepperDash.Core/Logging/DebugErrorLogSink.cs b/src/PepperDash.Core/Logging/DebugErrorLogSink.cs index 3885982b0..3c2e67615 100644 --- a/src/PepperDash.Core/Logging/DebugErrorLogSink.cs +++ b/src/PepperDash.Core/Logging/DebugErrorLogSink.cs @@ -9,57 +9,56 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Core.Logging +namespace PepperDash.Core.Logging; + +public class DebugErrorLogSink : ILogEventSink { - public class DebugErrorLogSink : ILogEventSink + private ITextFormatter _formatter; + + private Dictionary> _errorLogMap = new Dictionary> { - private ITextFormatter _formatter; + { LogEventLevel.Verbose, (msg) => ErrorLog.Notice(msg) }, + {LogEventLevel.Debug, (msg) => ErrorLog.Notice(msg) }, + {LogEventLevel.Information, (msg) => ErrorLog.Notice(msg) }, + {LogEventLevel.Warning, (msg) => ErrorLog.Warn(msg) }, + {LogEventLevel.Error, (msg) => ErrorLog.Error(msg) }, + {LogEventLevel.Fatal, (msg) => ErrorLog.Error(msg) } + }; + public void Emit(LogEvent logEvent) + { + string message; - private Dictionary> _errorLogMap = new Dictionary> - { - { LogEventLevel.Verbose, (msg) => ErrorLog.Notice(msg) }, - {LogEventLevel.Debug, (msg) => ErrorLog.Notice(msg) }, - {LogEventLevel.Information, (msg) => ErrorLog.Notice(msg) }, - {LogEventLevel.Warning, (msg) => ErrorLog.Warn(msg) }, - {LogEventLevel.Error, (msg) => ErrorLog.Error(msg) }, - {LogEventLevel.Fatal, (msg) => ErrorLog.Error(msg) } - }; - public void Emit(LogEvent logEvent) + if (_formatter == null) { - string message; + var programId = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance + ? $"App {InitialParametersClass.ApplicationNumber}" + : $"Room {InitialParametersClass.RoomId}"; - if (_formatter == null) - { - var programId = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance - ? $"App {InitialParametersClass.ApplicationNumber}" - : $"Room {InitialParametersClass.RoomId}"; - - message = $"[{logEvent.Timestamp}][{logEvent.Level}][{programId}]{logEvent.RenderMessage()}"; + message = $"[{logEvent.Timestamp}][{logEvent.Level}][{programId}]{logEvent.RenderMessage()}"; - if (logEvent.Properties.TryGetValue("Key", out var value) && value is ScalarValue sv && sv.Value is string rawValue) - { - message = $"[{logEvent.Timestamp}][{logEvent.Level}][{programId}][{rawValue}]: {logEvent.RenderMessage()}"; - } - } else + if (logEvent.Properties.TryGetValue("Key", out var value) && value is ScalarValue sv && sv.Value is string rawValue) { - var buffer = new StringWriter(new StringBuilder(256)); - - _formatter.Format(logEvent, buffer); - - message = buffer.ToString(); + message = $"[{logEvent.Timestamp}][{logEvent.Level}][{programId}][{rawValue}]: {logEvent.RenderMessage()}"; } + } else + { + var buffer = new StringWriter(new StringBuilder(256)); - if(!_errorLogMap.TryGetValue(logEvent.Level, out var handler)) - { - return; - } + _formatter.Format(logEvent, buffer); - handler(message); + message = buffer.ToString(); } - public DebugErrorLogSink(ITextFormatter formatter = null) + if(!_errorLogMap.TryGetValue(logEvent.Level, out var handler)) { - _formatter = formatter; + return; } + + handler(message); + } + + public DebugErrorLogSink(ITextFormatter formatter = null) + { + _formatter = formatter; } } diff --git a/src/PepperDash.Core/Logging/DebugExtensions.cs b/src/PepperDash.Core/Logging/DebugExtensions.cs index a8b7bd555..05d36276d 100644 --- a/src/PepperDash.Core/Logging/DebugExtensions.cs +++ b/src/PepperDash.Core/Logging/DebugExtensions.cs @@ -2,73 +2,72 @@ using System; using Log = PepperDash.Core.Debug; -namespace PepperDash.Core.Logging +namespace PepperDash.Core.Logging; + +public static class DebugExtensions { - public static class DebugExtensions + public static void LogException(this IKeyed device, Exception ex, string message, params object[] args) { - public static void LogException(this IKeyed device, Exception ex, string message, params object[] args) - { - Log.LogMessage(ex, message, device, args); - } + Log.LogMessage(ex, message, device, args); + } - public static void LogVerbose(this IKeyed device, Exception ex, string message, params object[] args) - { - Log.LogMessage(LogEventLevel.Verbose, ex, message, device, args); - } + public static void LogVerbose(this IKeyed device, Exception ex, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Verbose, ex, message, device, args); + } - public static void LogVerbose(this IKeyed device, string message, params object[] args) - { - Log.LogMessage(LogEventLevel.Verbose, device, message, args); - } + public static void LogVerbose(this IKeyed device, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Verbose, device, message, args); + } - public static void LogDebug(this IKeyed device, Exception ex, string message, params object[] args) - { - Log.LogMessage(LogEventLevel.Debug, ex, message, device, args); - } + public static void LogDebug(this IKeyed device, Exception ex, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Debug, ex, message, device, args); + } - public static void LogDebug(this IKeyed device, string message, params object[] args) - { - Log.LogMessage(LogEventLevel.Debug, device, message, args); - } + public static void LogDebug(this IKeyed device, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Debug, device, message, args); + } - public static void LogInformation(this IKeyed device, Exception ex, string message, params object[] args) - { - Log.LogMessage(LogEventLevel.Information, ex, message, device, args); - } + public static void LogInformation(this IKeyed device, Exception ex, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Information, ex, message, device, args); + } - public static void LogInformation(this IKeyed device, string message, params object[] args) - { - Log.LogMessage(LogEventLevel.Information, device, message, args); - } + public static void LogInformation(this IKeyed device, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Information, device, message, args); + } - public static void LogWarning(this IKeyed device, Exception ex, string message, params object[] args) - { - Log.LogMessage(LogEventLevel.Warning, ex, message, device, args); - } + public static void LogWarning(this IKeyed device, Exception ex, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Warning, ex, message, device, args); + } - public static void LogWarning(this IKeyed device, string message, params object[] args) - { - Log.LogMessage(LogEventLevel.Warning, device, message, args); - } + public static void LogWarning(this IKeyed device, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Warning, device, message, args); + } - public static void LogError(this IKeyed device, Exception ex, string message, params object[] args) - { - Log.LogMessage(LogEventLevel.Error, ex, message, device, args); - } + public static void LogError(this IKeyed device, Exception ex, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Error, ex, message, device, args); + } - public static void LogError(this IKeyed device, string message, params object[] args) - { - Log.LogMessage(LogEventLevel.Error, device, message, args); - } + public static void LogError(this IKeyed device, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Error, device, message, args); + } - public static void LogFatal(this IKeyed device, Exception ex, string message, params object[] args) - { - Log.LogMessage(LogEventLevel.Fatal, ex, message, device, args); - } + public static void LogFatal(this IKeyed device, Exception ex, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Fatal, ex, message, device, args); + } - public static void LogFatal(this IKeyed device, string message, params object[] args) - { - Log.LogMessage(LogEventLevel.Fatal, device, message, args); - } + public static void LogFatal(this IKeyed device, string message, params object[] args) + { + Log.LogMessage(LogEventLevel.Fatal, device, message, args); } } diff --git a/src/PepperDash.Core/Logging/DebugMemory.cs b/src/PepperDash.Core/Logging/DebugMemory.cs index a5737af98..7eb586938 100644 --- a/src/PepperDash.Core/Logging/DebugMemory.cs +++ b/src/PepperDash.Core/Logging/DebugMemory.cs @@ -2,25 +2,25 @@ using Crestron.SimplSharp; using Newtonsoft.Json; -namespace PepperDash.Core.Logging -{ - /// - /// Class to persist current Debug settings across program restarts - /// +namespace PepperDash.Core.Logging; + +/// +/// Class to persist current Debug settings across program restarts +/// public class DebugContextCollection { - /// - /// To prevent threading issues with the DeviceDebugSettings collection - /// - private readonly CCriticalSection _deviceDebugSettingsLock; + /// + /// To prevent threading issues with the DeviceDebugSettings collection + /// + private readonly CCriticalSection _deviceDebugSettingsLock; [JsonProperty("items")] private readonly Dictionary _items; - /// - /// Collection of the debug settings for each device where the dictionary key is the device key - /// - [JsonProperty("deviceDebugSettings")] - private Dictionary DeviceDebugSettings { get; set; } + /// + /// Collection of the debug settings for each device where the dictionary key is the device key + /// + [JsonProperty("deviceDebugSettings")] + private Dictionary DeviceDebugSettings { get; set; } /// @@ -28,8 +28,8 @@ public class DebugContextCollection /// public DebugContextCollection() { - _deviceDebugSettingsLock = new CCriticalSection(); - DeviceDebugSettings = new Dictionary(); + _deviceDebugSettingsLock = new CCriticalSection(); + DeviceDebugSettings = new Dictionary(); _items = new Dictionary(); } @@ -59,40 +59,40 @@ public DebugContextItem GetOrCreateItem(string contextKey) } - /// - /// sets the settings for a device or creates a new entry - /// - /// - /// - /// - public void SetDebugSettingsForKey(string deviceKey, object settings) + /// + /// sets the settings for a device or creates a new entry + /// + /// + /// + /// + public void SetDebugSettingsForKey(string deviceKey, object settings) + { + try { - try - { - _deviceDebugSettingsLock.Enter(); + _deviceDebugSettingsLock.Enter(); - if (DeviceDebugSettings.ContainsKey(deviceKey)) - { - DeviceDebugSettings[deviceKey] = settings; - } - else - DeviceDebugSettings.Add(deviceKey, settings); - } - finally + if (DeviceDebugSettings.ContainsKey(deviceKey)) { - _deviceDebugSettingsLock.Leave(); + DeviceDebugSettings[deviceKey] = settings; } + else + DeviceDebugSettings.Add(deviceKey, settings); } - - /// - /// Gets the device settings for a device by key or returns null - /// - /// - /// - public object GetDebugSettingsForKey(string deviceKey) + finally { - return DeviceDebugSettings[deviceKey]; + _deviceDebugSettingsLock.Leave(); } + } + + /// + /// Gets the device settings for a device by key or returns null + /// + /// + /// + public object GetDebugSettingsForKey(string deviceKey) + { + return DeviceDebugSettings[deviceKey]; + } } /// @@ -100,16 +100,15 @@ public object GetDebugSettingsForKey(string deviceKey) /// public class DebugContextItem { - /// - /// The level of debug messages to print - /// + /// + /// The level of debug messages to print + /// [JsonProperty("level")] public int Level { get; set; } - /// - /// Property to tell the program not to intitialize when it boots, if desired - /// - [JsonProperty("doNotLoadOnNextBoot")] - public bool DoNotLoadOnNextBoot { get; set; } - } -} \ No newline at end of file + /// + /// Property to tell the program not to intitialize when it boots, if desired + /// + [JsonProperty("doNotLoadOnNextBoot")] + public bool DoNotLoadOnNextBoot { get; set; } + } \ No newline at end of file diff --git a/src/PepperDash.Core/Logging/DebugWebsocketSink.cs b/src/PepperDash.Core/Logging/DebugWebsocketSink.cs index d818977e6..d80d1c7b1 100644 --- a/src/PepperDash.Core/Logging/DebugWebsocketSink.cs +++ b/src/PepperDash.Core/Logging/DebugWebsocketSink.cs @@ -1,271 +1,332 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Crestron.SimplSharp; +using Org.BouncyCastle.Asn1.X509; using Serilog; +using Serilog.Configuration; using Serilog.Core; using Serilog.Events; -using Serilog.Configuration; -using WebSocketSharp.Server; -using Crestron.SimplSharp; -using WebSocketSharp; -using System.Security.Authentication; -using WebSocketSharp.Net; -using X509Certificate2 = System.Security.Cryptography.X509Certificates.X509Certificate2; -using System.IO; -using Org.BouncyCastle.Asn1.X509; using Serilog.Formatting; -using Newtonsoft.Json.Linq; using Serilog.Formatting.Json; +using System; +using System.IO; +using System.Security.Authentication; +using WebSocketSharp; +using WebSocketSharp.Server; +using X509Certificate2 = System.Security.Cryptography.X509Certificates.X509Certificate2; + +namespace PepperDash.Core; -namespace PepperDash.Core +/// +/// Provides a WebSocket-based logging sink for debugging purposes, allowing log events to be broadcast to connected +/// WebSocket clients. +/// +/// This class implements the interface and is designed to send +/// formatted log events to WebSocket clients connected to a secure WebSocket server. The server is hosted locally +/// and uses a self-signed certificate for SSL/TLS encryption. +public class DebugWebsocketSink : ILogEventSink, IKeyed { - public class DebugWebsocketSink : ILogEventSink + private HttpServer _httpsServer; + + private readonly string _path = "/debug/join/"; + private const string _certificateName = "selfCres"; + private const string _certificatePassword = "cres12345"; + + /// + /// Gets the port number on which the HTTPS server is currently running. + /// + public int Port + { get + { + + if(_httpsServer == null) return 0; + return _httpsServer.Port; + } + } + + /// + /// Gets the WebSocket URL for the current server instance. + /// + /// The URL is dynamically constructed based on the server's current IP address, port, + /// and WebSocket path. + public string Url { - private HttpServer _httpsServer; - - private string _path = "/debug/join/"; - private const string _certificateName = "selfCres"; - private const string _certificatePassword = "cres12345"; - - public int Port - { get - { - - if(_httpsServer == null) return 0; - return _httpsServer.Port; - } + get + { + if (_httpsServer == null) return ""; + return $"wss://{CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0)}:{_httpsServer.Port}{_httpsServer.WebSocketServices[_path].Path}"; } + } + + /// + /// Gets a value indicating whether the HTTPS server is currently listening for incoming connections. + /// + public bool IsRunning { get => _httpsServer?.IsListening ?? false; } + + /// + public string Key => "DebugWebsocketSink"; + + private readonly ITextFormatter _textFormatter; + + /// + /// Initializes a new instance of the class with the specified text formatter. + /// + /// This constructor initializes the WebSocket sink and ensures that a certificate is + /// available for secure communication. If the required certificate does not exist, it will be created + /// automatically. Additionally, the sink is configured to stop the server when the program is + /// stopping. + /// The text formatter used to format log messages. If null, a default JSON formatter is used. + public DebugWebsocketSink(ITextFormatter formatProvider) + { - public string Url + _textFormatter = formatProvider ?? new JsonFormatter(); + + if (!File.Exists($"\\user\\{_certificateName}.pfx")) + CreateCert(); + + CrestronEnvironment.ProgramStatusEventHandler += type => { - get + if (type == eProgramStatusEventType.Stopping) { - if (_httpsServer == null) return ""; - return $"wss://{CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0)}:{_httpsServer.Port}{_httpsServer.WebSocketServices[_path].Path}"; + StopServer(); } - } - - public bool IsRunning { get => _httpsServer?.IsListening ?? false; } - + }; + } - private readonly ITextFormatter _textFormatter; + private static void CreateCert() + { + try + { + var utility = new BouncyCertificate(); + + var ipAddress = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0); + var hostName = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0); + var domainName = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DOMAIN_NAME, 0); - public DebugWebsocketSink(ITextFormatter formatProvider) - { + CrestronConsole.PrintLine(string.Format("DomainName: {0} | HostName: {1} | {1}.{0}@{2}", domainName, hostName, ipAddress)); - _textFormatter = formatProvider ?? new JsonFormatter(); + var certificate = utility.CreateSelfSignedCertificate(string.Format("CN={0}.{1}", hostName, domainName), [string.Format("{0}.{1}", hostName, domainName), ipAddress], [KeyPurposeID.id_kp_serverAuth, KeyPurposeID.id_kp_clientAuth]); - if (!File.Exists($"\\user\\{_certificateName}.pfx")) - CreateCert(null); + //Crestron fails to let us do this...perhaps it should be done through their Dll's but haven't tested - CrestronEnvironment.ProgramStatusEventHandler += type => - { - if (type == eProgramStatusEventType.Stopping) - { - StopServer(); - } - }; + var separator = Path.DirectorySeparatorChar; + + utility.CertificatePassword = _certificatePassword; + utility.WriteCertificate(certificate, @$"{separator}user{separator}", _certificateName); } - - private void CreateCert(string[] args) + catch (Exception ex) { - try - { - //Debug.Console(0,"CreateCert Creating Utility"); - CrestronConsole.PrintLine("CreateCert Creating Utility"); - //var utility = new CertificateUtility(); - var utility = new BouncyCertificate(); - //Debug.Console(0, "CreateCert Calling CreateCert"); - CrestronConsole.PrintLine("CreateCert Calling CreateCert"); - //utility.CreateCert(); - var ipAddress = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0); - var hostName = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0); - var domainName = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DOMAIN_NAME, 0); - - //Debug.Console(0, "DomainName: {0} | HostName: {1} | {1}.{0}@{2}", domainName, hostName, ipAddress); - CrestronConsole.PrintLine(string.Format("DomainName: {0} | HostName: {1} | {1}.{0}@{2}", domainName, hostName, ipAddress)); - - var certificate = utility.CreateSelfSignedCertificate(string.Format("CN={0}.{1}", hostName, domainName), new[] { string.Format("{0}.{1}", hostName, domainName), ipAddress }, new[] { KeyPurposeID.id_kp_serverAuth, KeyPurposeID.id_kp_clientAuth }); - //Crestron fails to let us do this...perhaps it should be done through their Dll's but haven't tested - //Debug.Print($"CreateCert Storing Certificate To My.LocalMachine"); - //utility.AddCertToStore(certificate, StoreName.My, StoreLocation.LocalMachine); - //Debug.Console(0, "CreateCert Saving Cert to \\user\\"); - CrestronConsole.PrintLine("CreateCert Saving Cert to \\user\\"); - utility.CertificatePassword = _certificatePassword; - utility.WriteCertificate(certificate, @"\user\", _certificateName); - //Debug.Console(0, "CreateCert Ending CreateCert"); - CrestronConsole.PrintLine("CreateCert Ending CreateCert"); - } - catch (Exception ex) - { - //Debug.Console(0, "WSS CreateCert Failed\r\n{0}\r\n{1}", ex.Message, ex.StackTrace); - CrestronConsole.PrintLine(string.Format("WSS CreateCert Failed\r\n{0}\r\n{1}", ex.Message, ex.StackTrace)); - } + //Debug.Console(0, "WSS CreateCert Failed\r\n{0}\r\n{1}", ex.Message, ex.StackTrace); + CrestronConsole.PrintLine("WSS CreateCert Failed\r\n{0}\r\n{1}", ex.Message, ex.StackTrace); } + } - public void Emit(LogEvent logEvent) - { - if (_httpsServer == null || !_httpsServer.IsListening) return; - - var sw = new StringWriter(); - _textFormatter.Format(logEvent, sw); + /// + /// Sends a log event to all connected WebSocket clients. + /// + /// The log event is formatted using the configured text formatter and then broadcasted + /// to all clients connected to the WebSocket server. If the WebSocket server is not initialized or not + /// listening, the method exits without performing any action. + /// The log event to be formatted and broadcasted. Cannot be null. + public void Emit(LogEvent logEvent) + { + if (_httpsServer == null || !_httpsServer.IsListening) return; - _httpsServer.WebSocketServices.Broadcast(sw.ToString()); + var sw = new StringWriter(); + _textFormatter.Format(logEvent, sw); - } + _httpsServer.WebSocketServices[_path].Sessions.Broadcast(sw.ToString()); + } - public void StartServerAndSetPort(int port) - { - Debug.Console(0, "Starting Websocket Server on port: {0}", port); + /// + /// Starts the WebSocket server on the specified port and configures it with the appropriate certificate. + /// + /// This method initializes the WebSocket server and binds it to the specified port. It + /// also applies the server's certificate for secure communication. Ensure that the port is not already in use + /// and that the certificate file is accessible. + /// The port number on which the WebSocket server will listen. Must be a valid, non-negative port number. + public void StartServerAndSetPort(int port) + { + Debug.Console(0, "Starting Websocket Server on port: {0}", port); - Start(port, $"\\user\\{_certificateName}.pfx", _certificatePassword); - } + Start(port, $"\\user\\{_certificateName}.pfx", _certificatePassword); + } - private void Start(int port, string certPath = "", string certPassword = "") + private void Start(int port, string certPath = "", string certPassword = "") + { + try { - try - { - _httpsServer = new HttpServer(port, true); + _httpsServer = new HttpServer(port, true); + if (!string.IsNullOrWhiteSpace(certPath)) + { + Debug.Console(0, "Assigning SSL Configuration"); + + _httpsServer.SslConfiguration.ServerCertificate = new X509Certificate2(certPath, certPassword); + _httpsServer.SslConfiguration.ClientCertificateRequired = false; + _httpsServer.SslConfiguration.CheckCertificateRevocation = false; + _httpsServer.SslConfiguration.EnabledSslProtocols = SslProtocols.Tls12; + //this is just to test, you might want to actually validate + _httpsServer.SslConfiguration.ClientCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => + { + Debug.Console(0, "HTTPS ClientCerticateValidation Callback triggered"); + return true; + }; + } + Debug.Console(0, "Adding Debug Client Service"); + _httpsServer.AddWebSocketService(_path); + Debug.Console(0, "Assigning Log Info"); + _httpsServer.Log.Level = LogLevel.Trace; + _httpsServer.Log.Output = (d, s) => + { + uint level; - if (!string.IsNullOrWhiteSpace(certPath)) + switch(d.Level) { - Debug.Console(0, "Assigning SSL Configuration"); - _httpsServer.SslConfiguration = new ServerSslConfiguration(new X509Certificate2(certPath, certPassword)) - { - ClientCertificateRequired = false, - CheckCertificateRevocation = false, - EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls, - //this is just to test, you might want to actually validate - ClientCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => - { - Debug.Console(0, "HTTPS ClientCerticateValidation Callback triggered"); - return true; - } - }; + case WebSocketSharp.LogLevel.Fatal: + level = 3; + break; + case WebSocketSharp.LogLevel.Error: + level = 2; + break; + case WebSocketSharp.LogLevel.Warn: + level = 1; + break; + case WebSocketSharp.LogLevel.Info: + level = 0; + break; + case WebSocketSharp.LogLevel.Debug: + level = 4; + break; + case WebSocketSharp.LogLevel.Trace: + level = 5; + break; + default: + level = 4; + break; } - Debug.Console(0, "Adding Debug Client Service"); - _httpsServer.AddWebSocketService(_path); - Debug.Console(0, "Assigning Log Info"); - _httpsServer.Log.Level = LogLevel.Trace; - _httpsServer.Log.Output = (d, s) => - { - uint level; + + Debug.Console(level, "{1} {0}\rCaller:{2}\rMessage:{3}\rs:{4}", d.Level.ToString(), d.Date.ToString(), d.Caller.ToString(), d.Message, s); + }; + Debug.Console(0, "Starting"); - switch(d.Level) - { - case WebSocketSharp.LogLevel.Fatal: - level = 3; - break; - case WebSocketSharp.LogLevel.Error: - level = 2; - break; - case WebSocketSharp.LogLevel.Warn: - level = 1; - break; - case WebSocketSharp.LogLevel.Info: - level = 0; - break; - case WebSocketSharp.LogLevel.Debug: - level = 4; - break; - case WebSocketSharp.LogLevel.Trace: - level = 5; - break; - default: - level = 4; - break; - } - - Debug.Console(level, "{1} {0}\rCaller:{2}\rMessage:{3}\rs:{4}", d.Level.ToString(), d.Date.ToString(), d.Caller.ToString(), d.Message, s); - }; - Debug.Console(0, "Starting"); - - _httpsServer.Start(); - Debug.Console(0, "Ready"); - } - catch (Exception ex) - { - Debug.Console(0, "WebSocket Failed to start {0}", ex.Message); - } + _httpsServer.Start(); + Debug.Console(0, "Ready"); } - - public void StopServer() + catch (Exception ex) { - Debug.Console(0, "Stopping Websocket Server"); - _httpsServer?.Stop(); - - _httpsServer = null; + Debug.Console(0, "WebSocket Failed to start {0}", ex.Message); } } - public static class DebugWebsocketSinkExtensions + /// + /// Stops the WebSocket server if it is currently running. + /// + /// This method halts the WebSocket server and releases any associated resources. After + /// calling this method, the server will no longer accept or process incoming connections. + public void StopServer() { - public static LoggerConfiguration DebugWebsocketSink( - this LoggerSinkConfiguration loggerConfiguration, - ITextFormatter formatProvider = null) - { - return loggerConfiguration.Sink(new DebugWebsocketSink(formatProvider)); - } + Debug.Console(0, "Stopping Websocket Server"); + _httpsServer?.Stop(); + + _httpsServer = null; } +} - public class DebugClient : WebSocketBehavior +/// +/// Configures the logger to write log events to a debug WebSocket sink. +/// +/// This extension method allows you to direct log events to a WebSocket sink for debugging +/// purposes. +public static class DebugWebsocketSinkExtensions +{ + /// + /// Configures a logger to write log events to a debug WebSocket sink. + /// + /// This method adds a sink that writes log events to a WebSocket for debugging purposes. + /// It is typically used during development to stream log events in real-time. + /// The logger sink configuration to apply the WebSocket sink to. + /// An optional text formatter to format the log events. If not provided, a default formatter will be used. + /// A object that can be used to further configure the logger. + public static LoggerConfiguration DebugWebsocketSink( + this LoggerSinkConfiguration loggerConfiguration, + ITextFormatter formatProvider = null) { - private DateTime _connectionTime; + return loggerConfiguration.Sink(new DebugWebsocketSink(formatProvider)); + } +} + +/// +/// Represents a WebSocket client for debugging purposes, providing connection lifecycle management and message +/// handling functionality. +/// +/// The class extends to handle +/// WebSocket connections, including events for opening, closing, receiving messages, and errors. It tracks the +/// duration of the connection and logs relevant events for debugging. +public class DebugClient : WebSocketBehavior +{ + private DateTime _connectionTime; - public TimeSpan ConnectedDuration + /// + /// Gets the duration of time the WebSocket connection has been active. + /// + public TimeSpan ConnectedDuration + { + get { - get + if (Context.WebSocket.IsAlive) { - if (Context.WebSocket.IsAlive) - { - return DateTime.Now - _connectionTime; - } - else - { - return new TimeSpan(0); - } + return DateTime.Now - _connectionTime; + } + else + { + return new TimeSpan(0); } } + } - public DebugClient() - { - Debug.Console(0, "DebugClient Created"); - } + /// + /// Initializes a new instance of the class. + /// + /// This constructor creates a new instance and logs its + /// creation using the method with a debug level of 0. + public DebugClient() + { + Debug.Console(0, "DebugClient Created"); + } - protected override void OnOpen() - { - base.OnOpen(); + /// + protected override void OnOpen() + { + base.OnOpen(); - var url = Context.WebSocket.Url; - Debug.Console(0, Debug.ErrorLogLevel.Notice, "New WebSocket Connection from: {0}", url); + var url = Context.WebSocket.Url; + Debug.Console(0, Debug.ErrorLogLevel.Notice, "New WebSocket Connection from: {0}", url); - _connectionTime = DateTime.Now; - } + _connectionTime = DateTime.Now; + } - protected override void OnMessage(MessageEventArgs e) - { - base.OnMessage(e); + /// + protected override void OnMessage(MessageEventArgs e) + { + base.OnMessage(e); - Debug.Console(0, "WebSocket UiClient Message: {0}", e.Data); - } + Debug.Console(0, "WebSocket UiClient Message: {0}", e.Data); + } - protected override void OnClose(CloseEventArgs e) - { - base.OnClose(e); + /// + protected override void OnClose(CloseEventArgs e) + { + base.OnClose(e); - Debug.Console(0, Debug.ErrorLogLevel.Notice, "WebSocket UiClient Closing: {0} reason: {1}", e.Code, e.Reason); + Debug.Console(0, Debug.ErrorLogLevel.Notice, "WebSocket UiClient Closing: {0} reason: {1}", e.Code, e.Reason); - } + } - protected override void OnError(WebSocketSharp.ErrorEventArgs e) - { - base.OnError(e); + /// + protected override void OnError(WebSocketSharp.ErrorEventArgs e) + { + base.OnError(e); - Debug.Console(2, Debug.ErrorLogLevel.Notice, "WebSocket UiClient Error: {0} message: {1}", e.Exception, e.Message); - } + Debug.Console(2, Debug.ErrorLogLevel.Notice, "WebSocket UiClient Error: {0} message: {1}", e.Exception, e.Message); } } diff --git a/src/PepperDash.Core/Network/DiscoveryThings.cs b/src/PepperDash.Core/Network/DiscoveryThings.cs index 973c03a4e..c01613b74 100644 --- a/src/PepperDash.Core/Network/DiscoveryThings.cs +++ b/src/PepperDash.Core/Network/DiscoveryThings.cs @@ -4,19 +4,17 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Core -{ +namespace PepperDash.Core; + +/// +/// Not in use +/// + public static class NetworkComm + { /// /// Not in use /// - public static class NetworkComm - { - /// - /// Not in use - /// static NetworkComm() { } - } - -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/PasswordManagement/Config.cs b/src/PepperDash.Core/PasswordManagement/Config.cs index 22aa48816..a5f071a4a 100644 --- a/src/PepperDash.Core/PasswordManagement/Config.cs +++ b/src/PepperDash.Core/PasswordManagement/Config.cs @@ -4,8 +4,8 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Core.PasswordManagement -{ +namespace PepperDash.Core.PasswordManagement; + /// /// JSON password configuration /// @@ -22,5 +22,4 @@ public PasswordConfig() { } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/PasswordManagement/Constants.cs b/src/PepperDash.Core/PasswordManagement/Constants.cs index 65a1bf45a..d4cf1e0bb 100644 --- a/src/PepperDash.Core/PasswordManagement/Constants.cs +++ b/src/PepperDash.Core/PasswordManagement/Constants.cs @@ -4,8 +4,8 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Core.PasswordManagement -{ +namespace PepperDash.Core.PasswordManagement; + /// /// Constants /// @@ -53,5 +53,4 @@ public class PasswordManagementConstants /// Generic string value change constant /// public const ushort StringValueChange = 201; - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/PasswordManagement/PasswordClient.cs b/src/PepperDash.Core/PasswordManagement/PasswordClient.cs index 225a563c1..27d71e956 100644 --- a/src/PepperDash.Core/PasswordManagement/PasswordClient.cs +++ b/src/PepperDash.Core/PasswordManagement/PasswordClient.cs @@ -1,10 +1,10 @@ using System; -namespace PepperDash.Core.PasswordManagement -{ - /// - /// A class to allow user interaction with the PasswordManager - /// +namespace PepperDash.Core.PasswordManagement; + +/// +/// A class to allow user interaction with the PasswordManager +/// public class PasswordClient { /// @@ -183,5 +183,4 @@ protected void PasswordManager_PasswordChange(object sender, StringChangeEventAr GetPasswordByIndex(args.Index); } } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/PasswordManagement/PasswordManager.cs b/src/PepperDash.Core/PasswordManagement/PasswordManager.cs index d15ac1e1b..da44e0592 100644 --- a/src/PepperDash.Core/PasswordManagement/PasswordManager.cs +++ b/src/PepperDash.Core/PasswordManagement/PasswordManager.cs @@ -2,11 +2,11 @@ using System.Collections.Generic; using Crestron.SimplSharp; -namespace PepperDash.Core.PasswordManagement -{ - /// - /// Allows passwords to be stored and managed - /// +namespace PepperDash.Core.PasswordManagement; + +/// +/// Allows passwords to be stored and managed +/// public class PasswordManager { /// @@ -190,7 +190,7 @@ protected void OnBoolChange(bool state, ushort index, ushort type) /// /// Protected ushort change event handler /// - /// + /// /// /// protected void OnUshrtChange(ushort value, ushort index, ushort type) @@ -237,5 +237,4 @@ protected void OnPasswordChange(string value, ushort index, ushort type) PasswordChange(this, args); } } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/PepperDash.Core.csproj b/src/PepperDash.Core/PepperDash.Core.csproj index daa5c6da4..b8745b2ee 100644 --- a/src/PepperDash.Core/PepperDash.Core.csproj +++ b/src/PepperDash.Core/PepperDash.Core.csproj @@ -5,7 +5,7 @@ PepperDash.Core PepperDashCore - net472 + net8 true en bin\$(Configuration)\ @@ -35,22 +35,18 @@ - - - - - - + - - - - - - - - - + + + + + + + + + + diff --git a/src/PepperDash.Core/SystemInfo/EventArgs and Constants.cs b/src/PepperDash.Core/SystemInfo/EventArgs and Constants.cs index cc71e3038..46d990721 100644 --- a/src/PepperDash.Core/SystemInfo/EventArgs and Constants.cs +++ b/src/PepperDash.Core/SystemInfo/EventArgs and Constants.cs @@ -4,68 +4,68 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Core.SystemInfo -{ +namespace PepperDash.Core.SystemInfo; + /// /// Constants /// public class SystemInfoConstants { - /// - /// - /// + /// + /// + /// public const ushort BoolValueChange = 1; /// /// /// - public const ushort CompleteBoolChange = 2; + public const ushort CompleteBoolChange = 2; /// /// /// - public const ushort BusyBoolChange = 3; - - /// - /// - /// + public const ushort BusyBoolChange = 3; + + /// + /// + /// public const ushort UshortValueChange = 101; - /// - /// - /// + /// + /// + /// public const ushort StringValueChange = 201; /// /// /// - public const ushort ConsoleResponseChange = 202; + public const ushort ConsoleResponseChange = 202; /// /// /// - public const ushort ProcessorUptimeChange = 203; + public const ushort ProcessorUptimeChange = 203; /// /// /// - public const ushort ProgramUptimeChange = 204; + public const ushort ProgramUptimeChange = 204; - /// - /// - /// + /// + /// + /// public const ushort ObjectChange = 301; /// /// /// - public const ushort ProcessorConfigChange = 302; + public const ushort ProcessorConfigChange = 302; /// /// /// - public const ushort EthernetConfigChange = 303; + public const ushort EthernetConfigChange = 303; /// /// /// - public const ushort ControlSubnetConfigChange = 304; + public const ushort ControlSubnetConfigChange = 304; /// /// /// - public const ushort ProgramConfigChange = 305; + public const ushort ProgramConfigChange = 305; } /// @@ -73,18 +73,18 @@ public class SystemInfoConstants /// public class ProcessorChangeEventArgs : EventArgs { - /// - /// - /// + /// + /// + /// public ProcessorInfo Processor { get; set; } /// /// /// - public ushort Type { get; set; } + public ushort Type { get; set; } /// /// /// - public ushort Index { get; set; } + public ushort Index { get; set; } /// /// Constructor @@ -119,18 +119,18 @@ public ProcessorChangeEventArgs(ProcessorInfo processor, ushort type, ushort ind /// public class EthernetChangeEventArgs : EventArgs { - /// - /// - /// + /// + /// + /// public EthernetInfo Adapter { get; set; } /// /// /// - public ushort Type { get; set; } + public ushort Type { get; set; } /// /// /// - public ushort Index { get; set; } + public ushort Index { get; set; } /// /// Constructor @@ -143,7 +143,7 @@ public EthernetChangeEventArgs() /// /// Constructor overload /// - /// + /// /// public EthernetChangeEventArgs(EthernetInfo ethernet, ushort type) { @@ -154,9 +154,9 @@ public EthernetChangeEventArgs(EthernetInfo ethernet, ushort type) /// /// Constructor overload /// - /// + /// /// - /// + /// public EthernetChangeEventArgs(EthernetInfo ethernet, ushort type, ushort index) { Adapter = ethernet; @@ -170,18 +170,18 @@ public EthernetChangeEventArgs(EthernetInfo ethernet, ushort type, ushort index) /// public class ControlSubnetChangeEventArgs : EventArgs { - /// - /// - /// + /// + /// + /// public ControlSubnetInfo Adapter { get; set; } /// /// /// - public ushort Type { get; set; } + public ushort Type { get; set; } /// /// /// - public ushort Index { get; set; } + public ushort Index { get; set; } /// /// Constructor @@ -216,18 +216,18 @@ public ControlSubnetChangeEventArgs(ControlSubnetInfo controlSubnet, ushort type /// public class ProgramChangeEventArgs : EventArgs { - /// - /// - /// + /// + /// + /// public ProgramInfo Program { get; set; } /// /// /// - public ushort Type { get; set; } + public ushort Type { get; set; } /// /// /// - public ushort Index { get; set; } + public ushort Index { get; set; } /// /// Constructor @@ -240,7 +240,7 @@ public ProgramChangeEventArgs() /// /// Constructor overload /// - /// + /// /// public ProgramChangeEventArgs(ProgramInfo program, ushort type) { @@ -251,14 +251,13 @@ public ProgramChangeEventArgs(ProgramInfo program, ushort type) /// /// Constructor overload /// - /// + /// /// - /// + /// public ProgramChangeEventArgs(ProgramInfo program, ushort type, ushort index) { Program = program; Type = type; Index = index; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/SystemInfo/SystemInfoConfig.cs b/src/PepperDash.Core/SystemInfo/SystemInfoConfig.cs index 8dc3acaf2..950abecb4 100644 --- a/src/PepperDash.Core/SystemInfo/SystemInfoConfig.cs +++ b/src/PepperDash.Core/SystemInfo/SystemInfoConfig.cs @@ -4,52 +4,52 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Core.SystemInfo -{ +namespace PepperDash.Core.SystemInfo; + /// /// Processor info class /// public class ProcessorInfo { - /// - /// - /// + /// + /// + /// public string Model { get; set; } - /// - /// - /// + /// + /// + /// public string SerialNumber { get; set; } - /// - /// - /// + /// + /// + /// public string Firmware { get; set; } - /// - /// - /// + /// + /// + /// public string FirmwareDate { get; set; } - /// - /// - /// + /// + /// + /// public string OsVersion { get; set; } - /// - /// - /// + /// + /// + /// public string RuntimeEnvironment { get; set; } - /// - /// - /// + /// + /// + /// public string DevicePlatform { get; set; } - /// - /// - /// + /// + /// + /// public string ModuleDirectory { get; set; } - /// - /// - /// + /// + /// + /// public string LocalTimeZone { get; set; } - /// - /// - /// + /// + /// + /// public string ProgramIdTag { get; set; } /// @@ -66,45 +66,45 @@ public ProcessorInfo() /// public class EthernetInfo { - /// - /// - /// + /// + /// + /// public ushort DhcpIsOn { get; set; } - /// - /// - /// + /// + /// + /// public string Hostname { get; set; } - /// - /// - /// + /// + /// + /// public string MacAddress { get; set; } - /// - /// - /// + /// + /// + /// public string IpAddress { get; set; } - /// - /// - /// + /// + /// + /// public string Subnet { get; set; } - /// - /// - /// + /// + /// + /// public string Gateway { get; set; } - /// - /// - /// + /// + /// + /// public string Dns1 { get; set; } - /// - /// - /// + /// + /// + /// public string Dns2 { get; set; } - /// - /// - /// + /// + /// + /// public string Dns3 { get; set; } - /// - /// - /// + /// + /// + /// public string Domain { get; set; } /// @@ -121,29 +121,29 @@ public EthernetInfo() /// public class ControlSubnetInfo { - /// - /// - /// + /// + /// + /// public ushort Enabled { get; set; } - /// - /// - /// + /// + /// + /// public ushort IsInAutomaticMode { get; set; } - /// - /// - /// + /// + /// + /// public string MacAddress { get; set; } - /// - /// - /// + /// + /// + /// public string IpAddress { get; set; } - /// - /// - /// + /// + /// + /// public string Subnet { get; set; } - /// - /// - /// + /// + /// + /// public string RouterPrefix { get; set; } /// @@ -160,37 +160,37 @@ public ControlSubnetInfo() /// public class ProgramInfo { - /// - /// - /// + /// + /// + /// public string Name { get; set; } - /// - /// - /// + /// + /// + /// public string Header { get; set; } - /// - /// - /// + /// + /// + /// public string System { get; set; } - /// - /// - /// + /// + /// + /// public string ProgramIdTag { get; set; } - /// - /// - /// + /// + /// + /// public string CompileTime { get; set; } - /// - /// - /// + /// + /// + /// public string Database { get; set; } - /// - /// - /// + /// + /// + /// public string Environment { get; set; } - /// - /// - /// + /// + /// + /// public string Programmer { get; set; } /// @@ -200,5 +200,4 @@ public ProgramInfo() { } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/SystemInfo/SystemInfoToSimpl.cs b/src/PepperDash.Core/SystemInfo/SystemInfoToSimpl.cs index 6677b9efd..be24be57a 100644 --- a/src/PepperDash.Core/SystemInfo/SystemInfoToSimpl.cs +++ b/src/PepperDash.Core/SystemInfo/SystemInfoToSimpl.cs @@ -4,37 +4,37 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Core.SystemInfo -{ +namespace PepperDash.Core.SystemInfo; + /// /// System Info class /// public class SystemInfoToSimpl { - /// - /// Notifies of bool change - /// + /// + /// Notifies of bool change + /// public event EventHandler BoolChange; - /// - /// Notifies of string change - /// + /// + /// Notifies of string change + /// public event EventHandler StringChange; - /// - /// Notifies of processor change - /// + /// + /// Notifies of processor change + /// public event EventHandler ProcessorChange; - /// - /// Notifies of ethernet change - /// + /// + /// Notifies of ethernet change + /// public event EventHandler EthernetChange; - /// - /// Notifies of control subnet change - /// + /// + /// Notifies of control subnet change + /// public event EventHandler ControlSubnetChange; - /// - /// Notifies of program change - /// + /// + /// Notifies of program change + /// public event EventHandler ProgramChange; /// @@ -327,10 +327,10 @@ public void SendConsoleCommand(string cmd) /// /// private method to parse console messages /// - /// + /// /// - /// - /// + /// + /// /// private string ParseConsoleResponse(string data, string line, string dataStart, string dataEnd) { @@ -458,5 +458,4 @@ protected void OnProgramChange(ProgramInfo program, ushort index, ushort type) ProgramChange(this, args); } } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/Web/BouncyCertificate.cs b/src/PepperDash.Core/Web/BouncyCertificate.cs index bf8b0f4c0..148b6eb1d 100644 --- a/src/PepperDash.Core/Web/BouncyCertificate.cs +++ b/src/PepperDash.Core/Web/BouncyCertificate.cs @@ -20,337 +20,336 @@ using BigInteger = Org.BouncyCastle.Math.BigInteger; using X509Certificate = Org.BouncyCastle.X509.X509Certificate; -namespace PepperDash.Core +namespace PepperDash.Core; + +/// +/// Taken From https://github.com/rlipscombe/bouncy-castle-csharp/ +/// +internal class BouncyCertificate { - /// - /// Taken From https://github.com/rlipscombe/bouncy-castle-csharp/ - /// - internal class BouncyCertificate + public string CertificatePassword { get; set; } = "password"; + public X509Certificate2 LoadCertificate(string issuerFileName, string password) { - public string CertificatePassword { get; set; } = "password"; - public X509Certificate2 LoadCertificate(string issuerFileName, string password) - { - // We need to pass 'Exportable', otherwise we can't get the private key. - var issuerCertificate = new X509Certificate2(issuerFileName, password, X509KeyStorageFlags.Exportable); - return issuerCertificate; - } + // We need to pass 'Exportable', otherwise we can't get the private key. + var issuerCertificate = new X509Certificate2(issuerFileName, password, X509KeyStorageFlags.Exportable); + return issuerCertificate; + } - public X509Certificate2 IssueCertificate(string subjectName, X509Certificate2 issuerCertificate, string[] subjectAlternativeNames, KeyPurposeID[] usages) - { - // It's self-signed, so these are the same. - var issuerName = issuerCertificate.Subject; + public X509Certificate2 IssueCertificate(string subjectName, X509Certificate2 issuerCertificate, string[] subjectAlternativeNames, KeyPurposeID[] usages) + { + // It's self-signed, so these are the same. + var issuerName = issuerCertificate.Subject; - var random = GetSecureRandom(); - var subjectKeyPair = GenerateKeyPair(random, 2048); + var random = GetSecureRandom(); + var subjectKeyPair = GenerateKeyPair(random, 2048); - var issuerKeyPair = DotNetUtilities.GetKeyPair(issuerCertificate.PrivateKey); + var issuerKeyPair = DotNetUtilities.GetKeyPair(issuerCertificate.PrivateKey); - var serialNumber = GenerateSerialNumber(random); - var issuerSerialNumber = new BigInteger(issuerCertificate.GetSerialNumber()); + var serialNumber = GenerateSerialNumber(random); + var issuerSerialNumber = new BigInteger(issuerCertificate.GetSerialNumber()); - const bool isCertificateAuthority = false; - var certificate = GenerateCertificate(random, subjectName, subjectKeyPair, serialNumber, - subjectAlternativeNames, issuerName, issuerKeyPair, - issuerSerialNumber, isCertificateAuthority, - usages); - return ConvertCertificate(certificate, subjectKeyPair, random); - } + const bool isCertificateAuthority = false; + var certificate = GenerateCertificate(random, subjectName, subjectKeyPair, serialNumber, + subjectAlternativeNames, issuerName, issuerKeyPair, + issuerSerialNumber, isCertificateAuthority, + usages); + return ConvertCertificate(certificate, subjectKeyPair, random); + } - public X509Certificate2 CreateCertificateAuthorityCertificate(string subjectName, string[] subjectAlternativeNames, KeyPurposeID[] usages) - { - // It's self-signed, so these are the same. - var issuerName = subjectName; + public X509Certificate2 CreateCertificateAuthorityCertificate(string subjectName, string[] subjectAlternativeNames, KeyPurposeID[] usages) + { + // It's self-signed, so these are the same. + var issuerName = subjectName; - var random = GetSecureRandom(); - var subjectKeyPair = GenerateKeyPair(random, 2048); + var random = GetSecureRandom(); + var subjectKeyPair = GenerateKeyPair(random, 2048); - // It's self-signed, so these are the same. - var issuerKeyPair = subjectKeyPair; + // It's self-signed, so these are the same. + var issuerKeyPair = subjectKeyPair; - var serialNumber = GenerateSerialNumber(random); - var issuerSerialNumber = serialNumber; // Self-signed, so it's the same serial number. + var serialNumber = GenerateSerialNumber(random); + var issuerSerialNumber = serialNumber; // Self-signed, so it's the same serial number. - const bool isCertificateAuthority = true; - var certificate = GenerateCertificate(random, subjectName, subjectKeyPair, serialNumber, - subjectAlternativeNames, issuerName, issuerKeyPair, - issuerSerialNumber, isCertificateAuthority, - usages); - return ConvertCertificate(certificate, subjectKeyPair, random); - } + const bool isCertificateAuthority = true; + var certificate = GenerateCertificate(random, subjectName, subjectKeyPair, serialNumber, + subjectAlternativeNames, issuerName, issuerKeyPair, + issuerSerialNumber, isCertificateAuthority, + usages); + return ConvertCertificate(certificate, subjectKeyPair, random); + } - public X509Certificate2 CreateSelfSignedCertificate(string subjectName, string[] subjectAlternativeNames, KeyPurposeID[] usages) - { - // It's self-signed, so these are the same. - var issuerName = subjectName; + public X509Certificate2 CreateSelfSignedCertificate(string subjectName, string[] subjectAlternativeNames, KeyPurposeID[] usages) + { + // It's self-signed, so these are the same. + var issuerName = subjectName; - var random = GetSecureRandom(); - var subjectKeyPair = GenerateKeyPair(random, 2048); + var random = GetSecureRandom(); + var subjectKeyPair = GenerateKeyPair(random, 2048); - // It's self-signed, so these are the same. - var issuerKeyPair = subjectKeyPair; + // It's self-signed, so these are the same. + var issuerKeyPair = subjectKeyPair; - var serialNumber = GenerateSerialNumber(random); - var issuerSerialNumber = serialNumber; // Self-signed, so it's the same serial number. + var serialNumber = GenerateSerialNumber(random); + var issuerSerialNumber = serialNumber; // Self-signed, so it's the same serial number. - const bool isCertificateAuthority = false; - var certificate = GenerateCertificate(random, subjectName, subjectKeyPair, serialNumber, - subjectAlternativeNames, issuerName, issuerKeyPair, - issuerSerialNumber, isCertificateAuthority, - usages); - return ConvertCertificate(certificate, subjectKeyPair, random); - } + const bool isCertificateAuthority = false; + var certificate = GenerateCertificate(random, subjectName, subjectKeyPair, serialNumber, + subjectAlternativeNames, issuerName, issuerKeyPair, + issuerSerialNumber, isCertificateAuthority, + usages); + return ConvertCertificate(certificate, subjectKeyPair, random); + } - private SecureRandom GetSecureRandom() - { - // Since we're on Windows, we'll use the CryptoAPI one (on the assumption - // that it might have access to better sources of entropy than the built-in - // Bouncy Castle ones): - var randomGenerator = new CryptoApiRandomGenerator(); - var random = new SecureRandom(randomGenerator); - return random; - } + private SecureRandom GetSecureRandom() + { + // Since we're on Windows, we'll use the CryptoAPI one (on the assumption + // that it might have access to better sources of entropy than the built-in + // Bouncy Castle ones): + var randomGenerator = new CryptoApiRandomGenerator(); + var random = new SecureRandom(randomGenerator); + return random; + } - private X509Certificate GenerateCertificate(SecureRandom random, - string subjectName, - AsymmetricCipherKeyPair subjectKeyPair, - BigInteger subjectSerialNumber, - string[] subjectAlternativeNames, - string issuerName, - AsymmetricCipherKeyPair issuerKeyPair, - BigInteger issuerSerialNumber, - bool isCertificateAuthority, - KeyPurposeID[] usages) - { - var certificateGenerator = new X509V3CertificateGenerator(); + private X509Certificate GenerateCertificate(SecureRandom random, + string subjectName, + AsymmetricCipherKeyPair subjectKeyPair, + BigInteger subjectSerialNumber, + string[] subjectAlternativeNames, + string issuerName, + AsymmetricCipherKeyPair issuerKeyPair, + BigInteger issuerSerialNumber, + bool isCertificateAuthority, + KeyPurposeID[] usages) + { + var certificateGenerator = new X509V3CertificateGenerator(); - certificateGenerator.SetSerialNumber(subjectSerialNumber); + certificateGenerator.SetSerialNumber(subjectSerialNumber); - var issuerDN = new X509Name(issuerName); - certificateGenerator.SetIssuerDN(issuerDN); + var issuerDN = new X509Name(issuerName); + certificateGenerator.SetIssuerDN(issuerDN); - // Note: The subject can be omitted if you specify a subject alternative name (SAN). - var subjectDN = new X509Name(subjectName); - certificateGenerator.SetSubjectDN(subjectDN); + // Note: The subject can be omitted if you specify a subject alternative name (SAN). + var subjectDN = new X509Name(subjectName); + certificateGenerator.SetSubjectDN(subjectDN); - // Our certificate needs valid from/to values. - var notBefore = DateTime.UtcNow.Date; - var notAfter = notBefore.AddYears(2); + // Our certificate needs valid from/to values. + var notBefore = DateTime.UtcNow.Date; + var notAfter = notBefore.AddYears(2); - certificateGenerator.SetNotBefore(notBefore); - certificateGenerator.SetNotAfter(notAfter); + certificateGenerator.SetNotBefore(notBefore); + certificateGenerator.SetNotAfter(notAfter); - // The subject's public key goes in the certificate. - certificateGenerator.SetPublicKey(subjectKeyPair.Public); + // The subject's public key goes in the certificate. + certificateGenerator.SetPublicKey(subjectKeyPair.Public); - AddAuthorityKeyIdentifier(certificateGenerator, issuerDN, issuerKeyPair, issuerSerialNumber); - AddSubjectKeyIdentifier(certificateGenerator, subjectKeyPair); - //AddBasicConstraints(certificateGenerator, isCertificateAuthority); + AddAuthorityKeyIdentifier(certificateGenerator, issuerDN, issuerKeyPair, issuerSerialNumber); + AddSubjectKeyIdentifier(certificateGenerator, subjectKeyPair); + //AddBasicConstraints(certificateGenerator, isCertificateAuthority); - if (usages != null && usages.Any()) - AddExtendedKeyUsage(certificateGenerator, usages); + if (usages != null && usages.Any()) + AddExtendedKeyUsage(certificateGenerator, usages); - if (subjectAlternativeNames != null && subjectAlternativeNames.Any()) - AddSubjectAlternativeNames(certificateGenerator, subjectAlternativeNames); + if (subjectAlternativeNames != null && subjectAlternativeNames.Any()) + AddSubjectAlternativeNames(certificateGenerator, subjectAlternativeNames); - // Set the signature algorithm. This is used to generate the thumbprint which is then signed - // with the issuer's private key. We'll use SHA-256, which is (currently) considered fairly strong. - const string signatureAlgorithm = "SHA256WithRSA"; + // Set the signature algorithm. This is used to generate the thumbprint which is then signed + // with the issuer's private key. We'll use SHA-256, which is (currently) considered fairly strong. + const string signatureAlgorithm = "SHA256WithRSA"; - // The certificate is signed with the issuer's private key. - ISignatureFactory signatureFactory = new Asn1SignatureFactory(signatureAlgorithm, issuerKeyPair.Private, random); - var certificate = certificateGenerator.Generate(signatureFactory); - return certificate; - } + // The certificate is signed with the issuer's private key. + ISignatureFactory signatureFactory = new Asn1SignatureFactory(signatureAlgorithm, issuerKeyPair.Private, random); + var certificate = certificateGenerator.Generate(signatureFactory); + return certificate; + } - /// - /// The certificate needs a serial number. This is used for revocation, - /// and usually should be an incrementing index (which makes it easier to revoke a range of certificates). - /// Since we don't have anywhere to store the incrementing index, we can just use a random number. - /// - /// - /// - private BigInteger GenerateSerialNumber(SecureRandom random) - { - var serialNumber = - BigIntegers.CreateRandomInRange( - BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random); - return serialNumber; - } + /// + /// The certificate needs a serial number. This is used for revocation, + /// and usually should be an incrementing index (which makes it easier to revoke a range of certificates). + /// Since we don't have anywhere to store the incrementing index, we can just use a random number. + /// + /// + /// + private BigInteger GenerateSerialNumber(SecureRandom random) + { + var serialNumber = + BigIntegers.CreateRandomInRange( + BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random); + return serialNumber; + } - /// - /// Generate a key pair. - /// - /// The random number generator. - /// The key length in bits. For RSA, 2048 bits should be considered the minimum acceptable these days. - /// - private AsymmetricCipherKeyPair GenerateKeyPair(SecureRandom random, int strength) - { - var keyGenerationParameters = new KeyGenerationParameters(random, strength); + /// + /// Generate a key pair. + /// + /// The random number generator. + /// The key length in bits. For RSA, 2048 bits should be considered the minimum acceptable these days. + /// + private AsymmetricCipherKeyPair GenerateKeyPair(SecureRandom random, int strength) + { + var keyGenerationParameters = new KeyGenerationParameters(random, strength); - var keyPairGenerator = new RsaKeyPairGenerator(); - keyPairGenerator.Init(keyGenerationParameters); - var subjectKeyPair = keyPairGenerator.GenerateKeyPair(); - return subjectKeyPair; - } + var keyPairGenerator = new RsaKeyPairGenerator(); + keyPairGenerator.Init(keyGenerationParameters); + var subjectKeyPair = keyPairGenerator.GenerateKeyPair(); + return subjectKeyPair; + } - /// - /// Add the Authority Key Identifier. According to http://www.alvestrand.no/objectid/2.5.29.35.html, this - /// identifies the public key to be used to verify the signature on this certificate. - /// In a certificate chain, this corresponds to the "Subject Key Identifier" on the *issuer* certificate. - /// The Bouncy Castle documentation, at http://www.bouncycastle.org/wiki/display/JA1/X.509+Public+Key+Certificate+and+Certification+Request+Generation, - /// shows how to create this from the issuing certificate. Since we're creating a self-signed certificate, we have to do this slightly differently. - /// - /// - /// - /// - /// - private void AddAuthorityKeyIdentifier(X509V3CertificateGenerator certificateGenerator, - X509Name issuerDN, - AsymmetricCipherKeyPair issuerKeyPair, - BigInteger issuerSerialNumber) - { - var authorityKeyIdentifierExtension = - new AuthorityKeyIdentifier( - SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(issuerKeyPair.Public), - new GeneralNames(new GeneralName(issuerDN)), - issuerSerialNumber); - certificateGenerator.AddExtension( - X509Extensions.AuthorityKeyIdentifier.Id, false, authorityKeyIdentifierExtension); - } + /// + /// Add the Authority Key Identifier. According to http://www.alvestrand.no/objectid/2.5.29.35.html, this + /// identifies the public key to be used to verify the signature on this certificate. + /// In a certificate chain, this corresponds to the "Subject Key Identifier" on the *issuer* certificate. + /// The Bouncy Castle documentation, at http://www.bouncycastle.org/wiki/display/JA1/X.509+Public+Key+Certificate+and+Certification+Request+Generation, + /// shows how to create this from the issuing certificate. Since we're creating a self-signed certificate, we have to do this slightly differently. + /// + /// + /// + /// + /// + private void AddAuthorityKeyIdentifier(X509V3CertificateGenerator certificateGenerator, + X509Name issuerDN, + AsymmetricCipherKeyPair issuerKeyPair, + BigInteger issuerSerialNumber) + { + var authorityKeyIdentifierExtension = + new AuthorityKeyIdentifier( + SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(issuerKeyPair.Public), + new GeneralNames(new GeneralName(issuerDN)), + issuerSerialNumber); + certificateGenerator.AddExtension( + X509Extensions.AuthorityKeyIdentifier.Id, false, authorityKeyIdentifierExtension); + } - /// - /// Add the "Subject Alternative Names" extension. Note that you have to repeat - /// the value from the "Subject Name" property. - /// - /// - /// - private void AddSubjectAlternativeNames(X509V3CertificateGenerator certificateGenerator, - IEnumerable subjectAlternativeNames) - { - var subjectAlternativeNamesExtension = - new DerSequence( - subjectAlternativeNames.Select(name => new GeneralName(GeneralName.DnsName, name)) - .ToArray()); - certificateGenerator.AddExtension( - X509Extensions.SubjectAlternativeName.Id, false, subjectAlternativeNamesExtension); - } + /// + /// Add the "Subject Alternative Names" extension. Note that you have to repeat + /// the value from the "Subject Name" property. + /// + /// + /// + private void AddSubjectAlternativeNames(X509V3CertificateGenerator certificateGenerator, + IEnumerable subjectAlternativeNames) + { + var subjectAlternativeNamesExtension = + new DerSequence( + subjectAlternativeNames.Select(name => new GeneralName(GeneralName.DnsName, name)) + .ToArray()); + certificateGenerator.AddExtension( + X509Extensions.SubjectAlternativeName.Id, false, subjectAlternativeNamesExtension); + } - /// - /// Add the "Extended Key Usage" extension, specifying (for example) "server authentication". - /// - /// - /// - private void AddExtendedKeyUsage(X509V3CertificateGenerator certificateGenerator, KeyPurposeID[] usages) - { - certificateGenerator.AddExtension( - X509Extensions.ExtendedKeyUsage.Id, false, new ExtendedKeyUsage(usages)); - } + /// + /// Add the "Extended Key Usage" extension, specifying (for example) "server authentication". + /// + /// + /// + private void AddExtendedKeyUsage(X509V3CertificateGenerator certificateGenerator, KeyPurposeID[] usages) + { + certificateGenerator.AddExtension( + X509Extensions.ExtendedKeyUsage.Id, false, new ExtendedKeyUsage(usages)); + } - /// - /// Add the "Basic Constraints" extension. - /// - /// - /// - private void AddBasicConstraints(X509V3CertificateGenerator certificateGenerator, - bool isCertificateAuthority) - { - certificateGenerator.AddExtension( - X509Extensions.BasicConstraints.Id, true, new BasicConstraints(isCertificateAuthority)); - } + /// + /// Add the "Basic Constraints" extension. + /// + /// + /// + private void AddBasicConstraints(X509V3CertificateGenerator certificateGenerator, + bool isCertificateAuthority) + { + certificateGenerator.AddExtension( + X509Extensions.BasicConstraints.Id, true, new BasicConstraints(isCertificateAuthority)); + } - /// - /// Add the Subject Key Identifier. - /// - /// - /// - private void AddSubjectKeyIdentifier(X509V3CertificateGenerator certificateGenerator, - AsymmetricCipherKeyPair subjectKeyPair) - { - var subjectKeyIdentifierExtension = - new SubjectKeyIdentifier( - SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(subjectKeyPair.Public)); - certificateGenerator.AddExtension( - X509Extensions.SubjectKeyIdentifier.Id, false, subjectKeyIdentifierExtension); - } + /// + /// Add the Subject Key Identifier. + /// + /// + /// + private void AddSubjectKeyIdentifier(X509V3CertificateGenerator certificateGenerator, + AsymmetricCipherKeyPair subjectKeyPair) + { + var subjectKeyIdentifierExtension = + new SubjectKeyIdentifier( + SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(subjectKeyPair.Public)); + certificateGenerator.AddExtension( + X509Extensions.SubjectKeyIdentifier.Id, false, subjectKeyIdentifierExtension); + } - private X509Certificate2 ConvertCertificate(X509Certificate certificate, - AsymmetricCipherKeyPair subjectKeyPair, - SecureRandom random) - { - // Now to convert the Bouncy Castle certificate to a .NET certificate. - // See http://web.archive.org/web/20100504192226/http://www.fkollmann.de/v2/post/Creating-certificates-using-BouncyCastle.aspx - // ...but, basically, we create a PKCS12 store (a .PFX file) in memory, and add the public and private key to that. - var store = new Pkcs12StoreBuilder().Build(); + private X509Certificate2 ConvertCertificate(X509Certificate certificate, + AsymmetricCipherKeyPair subjectKeyPair, + SecureRandom random) + { + // Now to convert the Bouncy Castle certificate to a .NET certificate. + // See http://web.archive.org/web/20100504192226/http://www.fkollmann.de/v2/post/Creating-certificates-using-BouncyCastle.aspx + // ...but, basically, we create a PKCS12 store (a .PFX file) in memory, and add the public and private key to that. + var store = new Pkcs12StoreBuilder().Build(); - // What Bouncy Castle calls "alias" is the same as what Windows terms the "friendly name". - string friendlyName = certificate.SubjectDN.ToString(); + // What Bouncy Castle calls "alias" is the same as what Windows terms the "friendly name". + string friendlyName = certificate.SubjectDN.ToString(); - // Add the certificate. - var certificateEntry = new X509CertificateEntry(certificate); - store.SetCertificateEntry(friendlyName, certificateEntry); + // Add the certificate. + var certificateEntry = new X509CertificateEntry(certificate); + store.SetCertificateEntry(friendlyName, certificateEntry); - // Add the private key. - store.SetKeyEntry(friendlyName, new AsymmetricKeyEntry(subjectKeyPair.Private), new[] { certificateEntry }); + // Add the private key. + store.SetKeyEntry(friendlyName, new AsymmetricKeyEntry(subjectKeyPair.Private), new[] { certificateEntry }); - // Convert it to an X509Certificate2 object by saving/loading it from a MemoryStream. - // It needs a password. Since we'll remove this later, it doesn't particularly matter what we use. + // Convert it to an X509Certificate2 object by saving/loading it from a MemoryStream. + // It needs a password. Since we'll remove this later, it doesn't particularly matter what we use. - var stream = new MemoryStream(); - store.Save(stream, CertificatePassword.ToCharArray(), random); + var stream = new MemoryStream(); + store.Save(stream, CertificatePassword.ToCharArray(), random); - var convertedCertificate = - new X509Certificate2(stream.ToArray(), - CertificatePassword, - X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); - return convertedCertificate; - } + var convertedCertificate = + new X509Certificate2(stream.ToArray(), + CertificatePassword, + X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); + return convertedCertificate; + } - public void WriteCertificate(X509Certificate2 certificate, string outputDirectory, string certName) + public void WriteCertificate(X509Certificate2 certificate, string outputDirectory, string certName) + { + // This password is the one attached to the PFX file. Use 'null' for no password. + // Create PFX (PKCS #12) with private key + try { - // This password is the one attached to the PFX file. Use 'null' for no password. - // Create PFX (PKCS #12) with private key - try - { - var pfx = certificate.Export(X509ContentType.Pfx, CertificatePassword); - File.WriteAllBytes(string.Format("{0}.pfx", Path.Combine(outputDirectory, certName)), pfx); - } - catch (Exception ex) - { - CrestronConsole.PrintLine(string.Format("Failed to write x509 cert pfx\r\n{0}", ex.Message)); - } - // Create Base 64 encoded CER (public key only) - using (var writer = new StreamWriter($"{Path.Combine(outputDirectory, certName)}.cer", false)) - { - try - { - var contents = string.Format("-----BEGIN CERTIFICATE-----\r\n{0}\r\n-----END CERTIFICATE-----", Convert.ToBase64String(certificate.Export(X509ContentType.Cert), Base64FormattingOptions.InsertLineBreaks)); - writer.Write(contents); - } - catch (Exception ex) - { - CrestronConsole.PrintLine(string.Format("Failed to write x509 cert cer\r\n{0}", ex.Message)); - } - } + var pfx = certificate.Export(X509ContentType.Pfx, CertificatePassword); + File.WriteAllBytes(string.Format("{0}.pfx", Path.Combine(outputDirectory, certName)), pfx); } - public bool AddCertToStore(X509Certificate2 cert, System.Security.Cryptography.X509Certificates.StoreName st, System.Security.Cryptography.X509Certificates.StoreLocation sl) + catch (Exception ex) + { + CrestronConsole.PrintLine(string.Format("Failed to write x509 cert pfx\r\n{0}", ex.Message)); + } + // Create Base 64 encoded CER (public key only) + using (var writer = new StreamWriter($"{Path.Combine(outputDirectory, certName)}.cer", false)) { - bool bRet = false; - try { - var store = new System.Security.Cryptography.X509Certificates.X509Store(st, sl); - store.Open(System.Security.Cryptography.X509Certificates.OpenFlags.ReadWrite); - store.Add(cert); - - store.Close(); - bRet = true; + var contents = string.Format("-----BEGIN CERTIFICATE-----\r\n{0}\r\n-----END CERTIFICATE-----", Convert.ToBase64String(certificate.Export(X509ContentType.Cert), Base64FormattingOptions.InsertLineBreaks)); + writer.Write(contents); } catch (Exception ex) { - CrestronConsole.PrintLine(string.Format("AddCertToStore Failed\r\n{0}\r\n{1}", ex.Message, ex.StackTrace)); + CrestronConsole.PrintLine(string.Format("Failed to write x509 cert cer\r\n{0}", ex.Message)); } + } + } + public bool AddCertToStore(X509Certificate2 cert, System.Security.Cryptography.X509Certificates.StoreName st, System.Security.Cryptography.X509Certificates.StoreLocation sl) + { + bool bRet = false; - return bRet; + try + { + var store = new System.Security.Cryptography.X509Certificates.X509Store(st, sl); + store.Open(System.Security.Cryptography.X509Certificates.OpenFlags.ReadWrite); + store.Add(cert); + + store.Close(); + bRet = true; } + catch (Exception ex) + { + CrestronConsole.PrintLine(string.Format("AddCertToStore Failed\r\n{0}\r\n{1}", ex.Message, ex.StackTrace)); + } + + return bRet; } } \ No newline at end of file diff --git a/src/PepperDash.Core/Web/RequestHandlers/DefaultRequestHandler.cs b/src/PepperDash.Core/Web/RequestHandlers/DefaultRequestHandler.cs index ca19cf2fb..2fee0a622 100644 --- a/src/PepperDash.Core/Web/RequestHandlers/DefaultRequestHandler.cs +++ b/src/PepperDash.Core/Web/RequestHandlers/DefaultRequestHandler.cs @@ -1,7 +1,7 @@ using Crestron.SimplSharp.WebScripting; -namespace PepperDash.Core.Web.RequestHandlers -{ +namespace PepperDash.Core.Web.RequestHandlers; + /// /// Web API default request handler /// @@ -13,5 +13,4 @@ public class DefaultRequestHandler : WebApiBaseRequestHandler public DefaultRequestHandler() : base(true) { } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/Web/RequestHandlers/WebApiBaseRequestAsyncHandler.cs b/src/PepperDash.Core/Web/RequestHandlers/WebApiBaseRequestAsyncHandler.cs index b11700319..e8b3e85b5 100644 --- a/src/PepperDash.Core/Web/RequestHandlers/WebApiBaseRequestAsyncHandler.cs +++ b/src/PepperDash.Core/Web/RequestHandlers/WebApiBaseRequestAsyncHandler.cs @@ -3,161 +3,160 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace PepperDash.Core.Web.RequestHandlers +namespace PepperDash.Core.Web.RequestHandlers; + +public abstract class WebApiBaseRequestAsyncHandler:IHttpCwsHandler { - public abstract class WebApiBaseRequestAsyncHandler:IHttpCwsHandler + private readonly Dictionary> _handlers; + protected readonly bool EnableCors; + + /// + /// Constructor + /// + protected WebApiBaseRequestAsyncHandler(bool enableCors) { - private readonly Dictionary> _handlers; - protected readonly bool EnableCors; + EnableCors = enableCors; - /// - /// Constructor - /// - protected WebApiBaseRequestAsyncHandler(bool enableCors) + _handlers = new Dictionary> { - EnableCors = enableCors; - - _handlers = new Dictionary> - { - {"CONNECT", HandleConnect}, - {"DELETE", HandleDelete}, - {"GET", HandleGet}, - {"HEAD", HandleHead}, - {"OPTIONS", HandleOptions}, - {"PATCH", HandlePatch}, - {"POST", HandlePost}, - {"PUT", HandlePut}, - {"TRACE", HandleTrace} - }; - } + {"CONNECT", HandleConnect}, + {"DELETE", HandleDelete}, + {"GET", HandleGet}, + {"HEAD", HandleHead}, + {"OPTIONS", HandleOptions}, + {"PATCH", HandlePatch}, + {"POST", HandlePost}, + {"PUT", HandlePut}, + {"TRACE", HandleTrace} + }; + } - /// - /// Constructor - /// - protected WebApiBaseRequestAsyncHandler() - : this(false) - { - } + /// + /// Constructor + /// + protected WebApiBaseRequestAsyncHandler() + : this(false) + { + } - /// - /// Handles CONNECT method requests - /// - /// - protected virtual async Task HandleConnect(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } + /// + /// Handles CONNECT method requests + /// + /// + protected virtual async Task HandleConnect(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } - /// - /// Handles DELETE method requests - /// - /// - protected virtual async Task HandleDelete(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } + /// + /// Handles DELETE method requests + /// + /// + protected virtual async Task HandleDelete(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } - /// - /// Handles GET method requests - /// - /// - protected virtual async Task HandleGet(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } + /// + /// Handles GET method requests + /// + /// + protected virtual async Task HandleGet(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } - /// - /// Handles HEAD method requests - /// - /// - protected virtual async Task HandleHead(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } + /// + /// Handles HEAD method requests + /// + /// + protected virtual async Task HandleHead(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } - /// - /// Handles OPTIONS method requests - /// - /// - protected virtual async Task HandleOptions(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } + /// + /// Handles OPTIONS method requests + /// + /// + protected virtual async Task HandleOptions(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } - /// - /// Handles PATCH method requests - /// - /// - protected virtual async Task HandlePatch(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } + /// + /// Handles PATCH method requests + /// + /// + protected virtual async Task HandlePatch(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } - /// - /// Handles POST method requests - /// - /// - protected virtual async Task HandlePost(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } + /// + /// Handles POST method requests + /// + /// + protected virtual async Task HandlePost(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } - /// - /// Handles PUT method requests - /// - /// - protected virtual async Task HandlePut(HttpCwsContext context) - { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); - } + /// + /// Handles PUT method requests + /// + /// + protected virtual async Task HandlePut(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } - /// - /// Handles TRACE method requests - /// - /// - protected virtual async Task HandleTrace(HttpCwsContext context) + /// + /// Handles TRACE method requests + /// + /// + protected virtual async Task HandleTrace(HttpCwsContext context) + { + context.Response.StatusCode = 501; + context.Response.StatusDescription = "Not Implemented"; + context.Response.End(); + } + + /// + /// Process request + /// + /// + public void ProcessRequest(HttpCwsContext context) + { + if (!_handlers.TryGetValue(context.Request.HttpMethod, out Func handler)) { - context.Response.StatusCode = 501; - context.Response.StatusDescription = "Not Implemented"; - context.Response.End(); + return; } - /// - /// Process request - /// - /// - public void ProcessRequest(HttpCwsContext context) + if (EnableCors) { - if (!_handlers.TryGetValue(context.Request.HttpMethod, out Func handler)) - { - return; - } - - if (EnableCors) - { - context.Response.Headers.Add("Access-Control-Allow-Origin", "*"); - context.Response.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS"); - } + context.Response.Headers.Add("Access-Control-Allow-Origin", "*"); + context.Response.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS"); + } - var handlerTask = handler(context); + var handlerTask = handler(context); - handlerTask.GetAwaiter().GetResult(); - } + handlerTask.GetAwaiter().GetResult(); } } diff --git a/src/PepperDash.Core/Web/RequestHandlers/WebApiBaseRequestHandler.cs b/src/PepperDash.Core/Web/RequestHandlers/WebApiBaseRequestHandler.cs index 99e4aa93c..22d368a5b 100644 --- a/src/PepperDash.Core/Web/RequestHandlers/WebApiBaseRequestHandler.cs +++ b/src/PepperDash.Core/Web/RequestHandlers/WebApiBaseRequestHandler.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using Crestron.SimplSharp.WebScripting; -namespace PepperDash.Core.Web.RequestHandlers -{ +namespace PepperDash.Core.Web.RequestHandlers; + /// /// CWS Base Handler, implements IHttpCwsHandler /// @@ -161,5 +161,4 @@ public void ProcessRequest(HttpCwsContext context) handler(context); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/Web/WebApiServer.cs b/src/PepperDash.Core/Web/WebApiServer.cs index cf45b361d..dd6ed8d76 100644 --- a/src/PepperDash.Core/Web/WebApiServer.cs +++ b/src/PepperDash.Core/Web/WebApiServer.cs @@ -7,8 +7,8 @@ using Newtonsoft.Json.Linq; using PepperDash.Core.Web.RequestHandlers; -namespace PepperDash.Core.Web -{ +namespace PepperDash.Core.Web; + /// /// Web API server /// @@ -280,5 +280,4 @@ public void ReceivedRequestEventHandler(object sender, HttpCwsRequestEventArgs a Debug.Console(DebugVerbose, this, "ReceivedRequestEventHandler Exception InnerException: {0}", ex.InnerException); } } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/WebApi/Presets/Preset.cs b/src/PepperDash.Core/WebApi/Presets/Preset.cs index bdbc5820f..444d054f0 100644 --- a/src/PepperDash.Core/WebApi/Presets/Preset.cs +++ b/src/PepperDash.Core/WebApi/Presets/Preset.cs @@ -1,45 +1,45 @@ using System; -namespace PepperDash.Core.WebApi.Presets -{ - /// - /// Represents a preset - /// +namespace PepperDash.Core.WebApi.Presets; + +/// +/// Represents a preset +/// public class Preset { - /// - /// ID of preset - /// + /// + /// ID of preset + /// public int Id { get; set; } - /// - /// User ID - /// + /// + /// User ID + /// public int UserId { get; set; } - /// - /// Room Type ID - /// + /// + /// Room Type ID + /// public int RoomTypeId { get; set; } - /// - /// Preset Name - /// + /// + /// Preset Name + /// public string PresetName { get; set; } - /// - /// Preset Number - /// + /// + /// Preset Number + /// public int PresetNumber { get; set; } - /// - /// Preset Data - /// + /// + /// Preset Data + /// public string Data { get; set; } - /// - /// Constructor - /// + /// + /// Constructor + /// public Preset() { PresetName = ""; @@ -53,35 +53,34 @@ public Preset() /// public class PresetReceivedEventArgs : EventArgs { - /// - /// True when the preset is found - /// - public bool LookupSuccess { get; private set; } - - /// - /// S+ helper - /// - public ushort ULookupSuccess { get { return (ushort)(LookupSuccess ? 1 : 0); } } + /// + /// True when the preset is found + /// + public bool LookupSuccess { get; private set; } + + /// + /// S+ helper + /// + public ushort ULookupSuccess { get { return (ushort)(LookupSuccess ? 1 : 0); } } - /// - /// The preset - /// - public Preset Preset { get; private set; } + /// + /// The preset + /// + public Preset Preset { get; private set; } /// /// For Simpl+ /// public PresetReceivedEventArgs() { } - /// - /// Constructor - /// - /// - /// + /// + /// Constructor + /// + /// + /// public PresetReceivedEventArgs(Preset preset, bool success) { - LookupSuccess = success; + LookupSuccess = success; Preset = preset; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/WebApi/Presets/User.cs b/src/PepperDash.Core/WebApi/Presets/User.cs index c82824f60..ccab189e1 100644 --- a/src/PepperDash.Core/WebApi/Presets/User.cs +++ b/src/PepperDash.Core/WebApi/Presets/User.cs @@ -4,31 +4,31 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Core.WebApi.Presets -{ +namespace PepperDash.Core.WebApi.Presets; + /// /// /// public class User { - /// - /// - /// + /// + /// + /// public int Id { get; set; } - /// - /// - /// + /// + /// + /// public string ExternalId { get; set; } - /// - /// - /// + /// + /// + /// public string FirstName { get; set; } - /// - /// - /// + /// + /// + /// public string LastName { get; set; } } @@ -38,19 +38,19 @@ public class User /// public class UserReceivedEventArgs : EventArgs { - /// - /// True when user is found - /// - public bool LookupSuccess { get; private set; } + /// + /// True when user is found + /// + public bool LookupSuccess { get; private set; } - /// - /// For stupid S+ - /// - public ushort ULookupSuccess { get { return (ushort)(LookupSuccess ? 1 : 0); } } + /// + /// For stupid S+ + /// + public ushort ULookupSuccess { get { return (ushort)(LookupSuccess ? 1 : 0); } } - /// - /// - /// + /// + /// + /// public User User { get; private set; } /// @@ -58,14 +58,14 @@ public class UserReceivedEventArgs : EventArgs /// public UserReceivedEventArgs() { } - /// - /// Constructor - /// - /// - /// + /// + /// Constructor + /// + /// + /// public UserReceivedEventArgs(User user, bool success) { - LookupSuccess = success; + LookupSuccess = success; User = user; } } @@ -75,19 +75,18 @@ public UserReceivedEventArgs(User user, bool success) /// public class UserAndRoomMessage { - /// - /// - /// + /// + /// + /// public int UserId { get; set; } - /// - /// - /// + /// + /// + /// public int RoomTypeId { get; set; } - /// - /// - /// + /// + /// + /// public int PresetNumber { get; set; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Core/WebApi/Presets/WebApiPasscodeClient.cs b/src/PepperDash.Core/WebApi/Presets/WebApiPasscodeClient.cs index 0a9317bf7..7525a27f4 100644 --- a/src/PepperDash.Core/WebApi/Presets/WebApiPasscodeClient.cs +++ b/src/PepperDash.Core/WebApi/Presets/WebApiPasscodeClient.cs @@ -8,26 +8,26 @@ using PepperDash.Core.JsonToSimpl; -namespace PepperDash.Core.WebApi.Presets -{ - /// - /// Passcode client for the WebApi - /// +namespace PepperDash.Core.WebApi.Presets; + +/// +/// Passcode client for the WebApi +/// public class WebApiPasscodeClient : IKeyed { - /// - /// Notifies when user received - /// + /// + /// Notifies when user received + /// public event EventHandler UserReceived; - /// - /// Notifies when Preset received - /// + /// + /// Notifies when Preset received + /// public event EventHandler PresetReceived; - /// - /// Unique identifier for this instance - /// + /// + /// Unique identifier for this instance + /// public string Key { get; private set; } //string JsonMasterKey; @@ -54,13 +54,13 @@ public WebApiPasscodeClient() { } - /// - /// Initializes the instance - /// - /// - /// - /// - /// + /// + /// Initializes the instance + /// + /// + /// + /// + /// public void Initialize(string key, string jsonMasterKey, string urlBase, string defaultPresetJsonFilePath) { Key = key; @@ -73,41 +73,41 @@ public void Initialize(string key, string jsonMasterKey, string urlBase, string J2SMaster.Initialize(jsonMasterKey); } - /// - /// Gets the user for a passcode - /// - /// + /// + /// Gets the user for a passcode + /// + /// public void GetUserForPasscode(string passcode) { - // Bullshit duplicate code here... These two cases should be the same - // except for https/http and the certificate ignores - if (!UrlBase.StartsWith("https")) - return; - var req = new HttpsClientRequest(); - req.Url = new UrlParser(UrlBase + "/api/users/dopin"); - req.RequestType = Crestron.SimplSharp.Net.Https.RequestType.Post; - req.Header.AddHeader(new HttpsHeader("Content-Type", "application/json")); - req.Header.AddHeader(new HttpsHeader("Accept", "application/json")); - var jo = new JObject(); - jo.Add("pin", passcode); - req.ContentString = jo.ToString(); + // Bullshit duplicate code here... These two cases should be the same + // except for https/http and the certificate ignores + if (!UrlBase.StartsWith("https")) + return; + var req = new HttpsClientRequest(); + req.Url = new UrlParser(UrlBase + "/api/users/dopin"); + req.RequestType = Crestron.SimplSharp.Net.Https.RequestType.Post; + req.Header.AddHeader(new HttpsHeader("Content-Type", "application/json")); + req.Header.AddHeader(new HttpsHeader("Accept", "application/json")); + var jo = new JObject(); + jo.Add("pin", passcode); + req.ContentString = jo.ToString(); - var client = new HttpsClient(); - client.HostVerification = false; - client.PeerVerification = false; - var resp = client.Dispatch(req); - var handler = UserReceived; - if (resp.Code == 200) - { - //CrestronConsole.PrintLine("Received: {0}", resp.ContentString); - var user = JsonConvert.DeserializeObject(resp.ContentString); - CurrentUser = user; - if (handler != null) - UserReceived(this, new UserReceivedEventArgs(user, true)); - } - else - if (handler != null) - UserReceived(this, new UserReceivedEventArgs(null, false)); + var client = new HttpsClient(); + client.HostVerification = false; + client.PeerVerification = false; + var resp = client.Dispatch(req); + var handler = UserReceived; + if (resp.Code == 200) + { + //CrestronConsole.PrintLine("Received: {0}", resp.ContentString); + var user = JsonConvert.DeserializeObject(resp.ContentString); + CurrentUser = user; + if (handler != null) + UserReceived(this, new UserReceivedEventArgs(user, true)); + } + else + if (handler != null) + UserReceived(this, new UserReceivedEventArgs(null, false)); } /// @@ -130,57 +130,57 @@ public void GetPresetForThisUser(int roomTypeId, int presetNumber) PresetNumber = presetNumber }; - var handler = PresetReceived; + var handler = PresetReceived; try { - if (!UrlBase.StartsWith("https")) - return; - var req = new HttpsClientRequest(); - req.Url = new UrlParser(UrlBase + "/api/presets/userandroom"); - req.RequestType = Crestron.SimplSharp.Net.Https.RequestType.Post; - req.Header.AddHeader(new HttpsHeader("Content-Type", "application/json")); - req.Header.AddHeader(new HttpsHeader("Accept", "application/json")); - req.ContentString = JsonConvert.SerializeObject(msg); - - var client = new HttpsClient(); - client.HostVerification = false; - client.PeerVerification = false; - - // ask for the preset - var resp = client.Dispatch(req); - if (resp.Code == 200) // got it - { - //Debug.Console(1, this, "Received: {0}", resp.ContentString); - var preset = JsonConvert.DeserializeObject(resp.ContentString); - CurrentPreset = preset; - - //if there's no preset data, load the template - if (preset.Data == null || preset.Data.Trim() == string.Empty || JObject.Parse(preset.Data).Count == 0) - { - //Debug.Console(1, this, "Loaded preset has no data. Loading default template."); - LoadDefaultPresetData(); - return; - } - - J2SMaster.LoadWithJson(preset.Data); - if (handler != null) - PresetReceived(this, new PresetReceivedEventArgs(preset, true)); - } - else // no existing preset + if (!UrlBase.StartsWith("https")) + return; + var req = new HttpsClientRequest(); + req.Url = new UrlParser(UrlBase + "/api/presets/userandroom"); + req.RequestType = Crestron.SimplSharp.Net.Https.RequestType.Post; + req.Header.AddHeader(new HttpsHeader("Content-Type", "application/json")); + req.Header.AddHeader(new HttpsHeader("Accept", "application/json")); + req.ContentString = JsonConvert.SerializeObject(msg); + + var client = new HttpsClient(); + client.HostVerification = false; + client.PeerVerification = false; + + // ask for the preset + var resp = client.Dispatch(req); + if (resp.Code == 200) // got it + { + //Debug.Console(1, this, "Received: {0}", resp.ContentString); + var preset = JsonConvert.DeserializeObject(resp.ContentString); + CurrentPreset = preset; + + //if there's no preset data, load the template + if (preset.Data == null || preset.Data.Trim() == string.Empty || JObject.Parse(preset.Data).Count == 0) { - CurrentPreset = new Preset(); + //Debug.Console(1, this, "Loaded preset has no data. Loading default template."); LoadDefaultPresetData(); - if (handler != null) - PresetReceived(this, new PresetReceivedEventArgs(null, false)); + return; } + + J2SMaster.LoadWithJson(preset.Data); + if (handler != null) + PresetReceived(this, new PresetReceivedEventArgs(preset, true)); + } + else // no existing preset + { + CurrentPreset = new Preset(); + LoadDefaultPresetData(); + if (handler != null) + PresetReceived(this, new PresetReceivedEventArgs(null, false)); + } } catch (HttpException e) { var resp = e.Response; Debug.Console(1, this, "No preset received (code {0}). Loading default template", resp.Code); LoadDefaultPresetData(); - if (handler != null) - PresetReceived(this, new PresetReceivedEventArgs(null, false)); + if (handler != null) + PresetReceived(this, new PresetReceivedEventArgs(null, false)); } } @@ -236,8 +236,8 @@ void SaveCallback(string json) { CurrentPreset.Data = json; - if (!UrlBase.StartsWith("https")) - return; + if (!UrlBase.StartsWith("https")) + return; var req = new HttpsClientRequest(); req.RequestType = Crestron.SimplSharp.Net.Https.RequestType.Post; req.Url = new UrlParser(string.Format("{0}/api/presets/addorchange", UrlBase)); @@ -246,8 +246,8 @@ void SaveCallback(string json) req.ContentString = JsonConvert.SerializeObject(CurrentPreset); var client = new HttpsClient(); - client.HostVerification = false; - client.PeerVerification = false; + client.HostVerification = false; + client.PeerVerification = false; try { var resp = client.Dispatch(req); @@ -270,4 +270,3 @@ void SaveCallback(string json) } } } -} diff --git a/src/PepperDash.Core/XSigUtility/Serialization/IXSigSerialization.cs b/src/PepperDash.Core/XSigUtility/Serialization/IXSigSerialization.cs index 8303731e2..b1dcae6b7 100644 --- a/src/PepperDash.Core/XSigUtility/Serialization/IXSigSerialization.cs +++ b/src/PepperDash.Core/XSigUtility/Serialization/IXSigSerialization.cs @@ -1,25 +1,24 @@ using System.Collections.Generic; using PepperDash.Core.Intersystem.Tokens; -namespace PepperDash.Core.Intersystem.Serialization +namespace PepperDash.Core.Intersystem.Serialization; + +/// +/// Interface to determine XSig serialization for an object. +/// +public interface IXSigSerialization { /// - /// Interface to determine XSig serialization for an object. + /// Serialize the sig data /// - public interface IXSigSerialization - { - /// - /// Serialize the sig data - /// - /// - IEnumerable Serialize(); + /// + IEnumerable Serialize(); - /// - /// Deserialize the sig data - /// - /// - /// - /// - T Deserialize(IEnumerable tokens) where T : class, IXSigSerialization; - } + /// + /// Deserialize the sig data + /// + /// + /// + /// + T Deserialize(IEnumerable tokens) where T : class, IXSigSerialization; } \ No newline at end of file diff --git a/src/PepperDash.Core/XSigUtility/Serialization/XSigSerializationException.cs b/src/PepperDash.Core/XSigUtility/Serialization/XSigSerializationException.cs index 8f3fc047d..4db0e9703 100644 --- a/src/PepperDash.Core/XSigUtility/Serialization/XSigSerializationException.cs +++ b/src/PepperDash.Core/XSigUtility/Serialization/XSigSerializationException.cs @@ -1,28 +1,27 @@ using System; -namespace PepperDash.Core.Intersystem.Serialization +namespace PepperDash.Core.Intersystem.Serialization; + +/// +/// Class to handle this specific exception type +/// +public class XSigSerializationException : Exception { /// - /// Class to handle this specific exception type + /// default constructor /// - public class XSigSerializationException : Exception - { - /// - /// default constructor - /// - public XSigSerializationException() { } + public XSigSerializationException() { } - /// - /// constructor with message - /// - /// - public XSigSerializationException(string message) : base(message) { } + /// + /// constructor with message + /// + /// + public XSigSerializationException(string message) : base(message) { } - /// - /// constructor with message and innner exception - /// - /// - /// - public XSigSerializationException(string message, Exception inner) : base(message, inner) { } - } + /// + /// constructor with message and innner exception + /// + /// + /// + public XSigSerializationException(string message, Exception inner) : base(message, inner) { } } \ No newline at end of file diff --git a/src/PepperDash.Core/XSigUtility/Tokens/XSigAnalogToken.cs b/src/PepperDash.Core/XSigUtility/Tokens/XSigAnalogToken.cs index 58473362a..b5cb2e68f 100644 --- a/src/PepperDash.Core/XSigUtility/Tokens/XSigAnalogToken.cs +++ b/src/PepperDash.Core/XSigUtility/Tokens/XSigAnalogToken.cs @@ -1,88 +1,87 @@ using System; -namespace PepperDash.Core.Intersystem.Tokens +namespace PepperDash.Core.Intersystem.Tokens; + +/// +/// Represents an XSigAnalogToken +/// +public sealed class XSigAnalogToken : XSigToken, IFormattable { + private readonly ushort _value; + /// - /// Represents an XSigAnalogToken + /// Constructor /// - public sealed class XSigAnalogToken : XSigToken, IFormattable + /// + /// + public XSigAnalogToken(int index, ushort value) + : base(index) { - private readonly ushort _value; + // 10-bits available for analog encoded data + if (index >= 1024 || index < 0) + throw new ArgumentOutOfRangeException("index"); - /// - /// Constructor - /// - /// - /// - public XSigAnalogToken(int index, ushort value) - : base(index) - { - // 10-bits available for analog encoded data - if (index >= 1024 || index < 0) - throw new ArgumentOutOfRangeException("index"); - - _value = value; - } + _value = value; + } - /// - /// - /// - public ushort Value - { - get { return _value; } - } + /// + /// + /// + public ushort Value + { + get { return _value; } + } - /// - /// - /// - public override XSigTokenType TokenType - { - get { return XSigTokenType.Analog; } - } + /// + /// + /// + public override XSigTokenType TokenType + { + get { return XSigTokenType.Analog; } + } - /// - /// - /// - /// - public override byte[] GetBytes() - { - return new[] { - (byte)(0xC0 | ((Value & 0xC000) >> 10) | (Index - 1 >> 7)), - (byte)((Index - 1) & 0x7F), - (byte)((Value & 0x3F80) >> 7), - (byte)(Value & 0x7F) - }; - } + /// + /// + /// + /// + public override byte[] GetBytes() + { + return new[] { + (byte)(0xC0 | ((Value & 0xC000) >> 10) | (Index - 1 >> 7)), + (byte)((Index - 1) & 0x7F), + (byte)((Value & 0x3F80) >> 7), + (byte)(Value & 0x7F) + }; + } - /// - /// - /// - /// - /// - public override XSigToken GetTokenWithOffset(int offset) - { - if (offset == 0) return this; - return new XSigAnalogToken(Index + offset, Value); - } + /// + /// + /// + /// + /// + public override XSigToken GetTokenWithOffset(int offset) + { + if (offset == 0) return this; + return new XSigAnalogToken(Index + offset, Value); + } - /// - /// - /// - /// - public override string ToString() - { - return Index + " = 0x" + Value.ToString("X4"); - } + /// + /// + /// + /// + public override string ToString() + { + return Index + " = 0x" + Value.ToString("X4"); + } - /// - /// - /// - /// - /// - /// - public string ToString(string format, IFormatProvider formatProvider) - { - return Value.ToString(format, formatProvider); - } + /// + /// + /// + /// + /// + /// + public string ToString(string format, IFormatProvider formatProvider) + { + return Value.ToString(format, formatProvider); } } \ No newline at end of file diff --git a/src/PepperDash.Core/XSigUtility/Tokens/XSigDigitalToken.cs b/src/PepperDash.Core/XSigUtility/Tokens/XSigDigitalToken.cs index 70ccc852e..a82d0eb2d 100644 --- a/src/PepperDash.Core/XSigUtility/Tokens/XSigDigitalToken.cs +++ b/src/PepperDash.Core/XSigUtility/Tokens/XSigDigitalToken.cs @@ -1,85 +1,84 @@ using System; -namespace PepperDash.Core.Intersystem.Tokens +namespace PepperDash.Core.Intersystem.Tokens; + +/// +/// Represents an XSigDigitalToken +/// +public sealed class XSigDigitalToken : XSigToken { + private readonly bool _value; + /// - /// Represents an XSigDigitalToken + /// /// - public sealed class XSigDigitalToken : XSigToken + /// + /// + public XSigDigitalToken(int index, bool value) + : base(index) { - private readonly bool _value; + // 12-bits available for digital encoded data + if (index >= 4096 || index < 0) + throw new ArgumentOutOfRangeException("index"); - /// - /// - /// - /// - /// - public XSigDigitalToken(int index, bool value) - : base(index) - { - // 12-bits available for digital encoded data - if (index >= 4096 || index < 0) - throw new ArgumentOutOfRangeException("index"); - - _value = value; - } + _value = value; + } - /// - /// - /// - public bool Value - { - get { return _value; } - } + /// + /// + /// + public bool Value + { + get { return _value; } + } - /// - /// - /// - public override XSigTokenType TokenType - { - get { return XSigTokenType.Digital; } - } + /// + /// + /// + public override XSigTokenType TokenType + { + get { return XSigTokenType.Digital; } + } - /// - /// - /// - /// - public override byte[] GetBytes() - { - return new[] { - (byte)(0x80 | (Value ? 0 : 0x20) | ((Index - 1) >> 7)), - (byte)((Index - 1) & 0x7F) - }; - } + /// + /// + /// + /// + public override byte[] GetBytes() + { + return new[] { + (byte)(0x80 | (Value ? 0 : 0x20) | ((Index - 1) >> 7)), + (byte)((Index - 1) & 0x7F) + }; + } - /// - /// - /// - /// - /// - public override XSigToken GetTokenWithOffset(int offset) - { - if (offset == 0) return this; - return new XSigDigitalToken(Index + offset, Value); - } + /// + /// + /// + /// + /// + public override XSigToken GetTokenWithOffset(int offset) + { + if (offset == 0) return this; + return new XSigDigitalToken(Index + offset, Value); + } - /// - /// - /// - /// - public override string ToString() - { - return Index + " = " + (Value ? "High" : "Low"); - } + /// + /// + /// + /// + public override string ToString() + { + return Index + " = " + (Value ? "High" : "Low"); + } - /// - /// - /// - /// - /// - public string ToString(IFormatProvider formatProvider) - { - return Value.ToString(formatProvider); - } + /// + /// + /// + /// + /// + public string ToString(IFormatProvider formatProvider) + { + return Value.ToString(formatProvider); } } \ No newline at end of file diff --git a/src/PepperDash.Core/XSigUtility/Tokens/XSigSerialToken.cs b/src/PepperDash.Core/XSigUtility/Tokens/XSigSerialToken.cs index 25ee3fd00..3b6a3f5f3 100644 --- a/src/PepperDash.Core/XSigUtility/Tokens/XSigSerialToken.cs +++ b/src/PepperDash.Core/XSigUtility/Tokens/XSigSerialToken.cs @@ -1,81 +1,80 @@ using System; using System.Text; -namespace PepperDash.Core.Intersystem.Tokens +namespace PepperDash.Core.Intersystem.Tokens; + +/// +/// Represents an XSigSerialToken +/// +public sealed class XSigSerialToken : XSigToken { + private readonly string _value; + /// - /// Represents an XSigSerialToken + /// Constructor /// - public sealed class XSigSerialToken : XSigToken + /// + /// + public XSigSerialToken(int index, string value) + : base(index) { - private readonly string _value; - - /// - /// Constructor - /// - /// - /// - public XSigSerialToken(int index, string value) - : base(index) - { - // 10-bits available for serial encoded data - if (index >= 1024 || index < 0) - throw new ArgumentOutOfRangeException("index"); + // 10-bits available for serial encoded data + if (index >= 1024 || index < 0) + throw new ArgumentOutOfRangeException("index"); - _value = value; - } + _value = value; + } - /// - /// - /// - public string Value - { - get { return _value; } - } + /// + /// + /// + public string Value + { + get { return _value; } + } - /// - /// - /// - public override XSigTokenType TokenType - { - get { return XSigTokenType.Serial; } - } + /// + /// + /// + public override XSigTokenType TokenType + { + get { return XSigTokenType.Serial; } + } - /// - /// - /// - /// - public override byte[] GetBytes() - { - var serialBytes = String.IsNullOrEmpty(Value) ? new byte[0] : Encoding.GetEncoding(28591).GetBytes(Value); - - var xsig = new byte[serialBytes.Length + 3]; - xsig[0] = (byte)(0xC8 | (Index - 1 >> 7)); - xsig[1] = (byte)((Index - 1) & 0x7F); - xsig[xsig.Length - 1] = 0xFF; + /// + /// + /// + /// + public override byte[] GetBytes() + { + var serialBytes = String.IsNullOrEmpty(Value) ? new byte[0] : Encoding.GetEncoding(28591).GetBytes(Value); + + var xsig = new byte[serialBytes.Length + 3]; + xsig[0] = (byte)(0xC8 | (Index - 1 >> 7)); + xsig[1] = (byte)((Index - 1) & 0x7F); + xsig[xsig.Length - 1] = 0xFF; - Buffer.BlockCopy(serialBytes, 0, xsig, 2, serialBytes.Length); - return xsig; - } + Buffer.BlockCopy(serialBytes, 0, xsig, 2, serialBytes.Length); + return xsig; + } - /// - /// - /// - /// - /// - public override XSigToken GetTokenWithOffset(int offset) - { - if (offset == 0) return this; - return new XSigSerialToken(Index + offset, Value); - } + /// + /// + /// + /// + /// + public override XSigToken GetTokenWithOffset(int offset) + { + if (offset == 0) return this; + return new XSigSerialToken(Index + offset, Value); + } - /// - /// - /// - /// - public override string ToString() - { - return Index + " = \"" + Value + "\""; - } + /// + /// + /// + /// + public override string ToString() + { + return Index + " = \"" + Value + "\""; } } \ No newline at end of file diff --git a/src/PepperDash.Core/XSigUtility/Tokens/XSigToken.cs b/src/PepperDash.Core/XSigUtility/Tokens/XSigToken.cs index 4c00a2ed8..cd706bd4d 100644 --- a/src/PepperDash.Core/XSigUtility/Tokens/XSigToken.cs +++ b/src/PepperDash.Core/XSigUtility/Tokens/XSigToken.cs @@ -1,45 +1,44 @@ -namespace PepperDash.Core.Intersystem.Tokens +namespace PepperDash.Core.Intersystem.Tokens; + +/// +/// Represents the base class for all XSig datatypes. +/// +public abstract class XSigToken { + private readonly int _index; + /// - /// Represents the base class for all XSig datatypes. + /// Constructs an XSigToken with the specified index. /// - public abstract class XSigToken + /// Index for the data. + protected XSigToken(int index) { - private readonly int _index; - - /// - /// Constructs an XSigToken with the specified index. - /// - /// Index for the data. - protected XSigToken(int index) - { - _index = index; - } + _index = index; + } - /// - /// XSig 1-based index. - /// - public int Index - { - get { return _index; } - } + /// + /// XSig 1-based index. + /// + public int Index + { + get { return _index; } + } - /// - /// XSigToken type. - /// - public abstract XSigTokenType TokenType { get; } + /// + /// XSigToken type. + /// + public abstract XSigTokenType TokenType { get; } - /// - /// Generates the XSig bytes for the corresponding token. - /// - /// XSig byte array. - public abstract byte[] GetBytes(); + /// + /// Generates the XSig bytes for the corresponding token. + /// + /// XSig byte array. + public abstract byte[] GetBytes(); - /// - /// Returns a new token if necessary with an updated index based on the specified offset. - /// - /// Offset to adjust the index with. - /// XSigToken - public abstract XSigToken GetTokenWithOffset(int offset); - } + /// + /// Returns a new token if necessary with an updated index based on the specified offset. + /// + /// Offset to adjust the index with. + /// XSigToken + public abstract XSigToken GetTokenWithOffset(int offset); } \ No newline at end of file diff --git a/src/PepperDash.Core/XSigUtility/Tokens/XSigTokenType.cs b/src/PepperDash.Core/XSigUtility/Tokens/XSigTokenType.cs index 26d6c1238..60641b4f1 100644 --- a/src/PepperDash.Core/XSigUtility/Tokens/XSigTokenType.cs +++ b/src/PepperDash.Core/XSigUtility/Tokens/XSigTokenType.cs @@ -1,23 +1,22 @@ -namespace PepperDash.Core.Intersystem.Tokens +namespace PepperDash.Core.Intersystem.Tokens; + +/// +/// XSig token types. +/// +public enum XSigTokenType { /// - /// XSig token types. + /// Digital signal datatype. /// - public enum XSigTokenType - { - /// - /// Digital signal datatype. - /// - Digital, + Digital, - /// - /// Analog signal datatype. - /// - Analog, + /// + /// Analog signal datatype. + /// + Analog, - /// - /// Serial signal datatype. - /// - Serial - } + /// + /// Serial signal datatype. + /// + Serial } \ No newline at end of file diff --git a/src/PepperDash.Core/XSigUtility/XSigHelpers.cs b/src/PepperDash.Core/XSigUtility/XSigHelpers.cs index 4ea6f6349..4f970be29 100644 --- a/src/PepperDash.Core/XSigUtility/XSigHelpers.cs +++ b/src/PepperDash.Core/XSigUtility/XSigHelpers.cs @@ -18,222 +18,221 @@ 0aaaaaaa 0aaaaaaa 11111111 <- denotes end of data */ -namespace PepperDash.Core.Intersystem +namespace PepperDash.Core.Intersystem; + +/// +/// Helper methods for creating XSig byte sequences compatible with the Intersystem Communications (ISC) symbol. +/// +/// +/// Indexing is not from the start of each signal type but rather from the beginning of the first defined signal +/// the Intersystem Communications (ISC) symbol. +/// +public static class XSigHelpers { /// - /// Helper methods for creating XSig byte sequences compatible with the Intersystem Communications (ISC) symbol. + /// Forces all outputs to 0. /// - /// - /// Indexing is not from the start of each signal type but rather from the beginning of the first defined signal - /// the Intersystem Communications (ISC) symbol. - /// - public static class XSigHelpers + /// Bytes in XSig format for clear outputs trigger. + public static byte[] ClearOutputs() { - /// - /// Forces all outputs to 0. - /// - /// Bytes in XSig format for clear outputs trigger. - public static byte[] ClearOutputs() - { - return new byte[] { 0xFC }; - } + return new byte[] { 0xFC }; + } - /// - /// Evaluate all inputs and re-transmit any digital, analog, and permanent serail signals not set to 0. - /// - /// Bytes in XSig format for send status trigger. - public static byte[] SendStatus() - { - return new byte[] { 0xFD }; - } + /// + /// Evaluate all inputs and re-transmit any digital, analog, and permanent serail signals not set to 0. + /// + /// Bytes in XSig format for send status trigger. + public static byte[] SendStatus() + { + return new byte[] { 0xFD }; + } - /// - /// Get bytes for an IXSigStateResolver object. - /// - /// XSig state resolver. - /// Bytes in XSig format for each token within the state representation. - public static byte[] GetBytes(IXSigSerialization xSigSerialization) - { - return GetBytes(xSigSerialization, 0); - } + /// + /// Get bytes for an IXSigStateResolver object. + /// + /// XSig state resolver. + /// Bytes in XSig format for each token within the state representation. + public static byte[] GetBytes(IXSigSerialization xSigSerialization) + { + return GetBytes(xSigSerialization, 0); + } - /// - /// Get bytes for an IXSigStateResolver object, with a specified offset. - /// - /// XSig state resolver. - /// Offset to which the data will be aligned. - /// Bytes in XSig format for each token within the state representation. - public static byte[] GetBytes(IXSigSerialization xSigSerialization, int offset) + /// + /// Get bytes for an IXSigStateResolver object, with a specified offset. + /// + /// XSig state resolver. + /// Offset to which the data will be aligned. + /// Bytes in XSig format for each token within the state representation. + public static byte[] GetBytes(IXSigSerialization xSigSerialization, int offset) + { + var tokens = xSigSerialization.Serialize(); + if (tokens == null) return new byte[0]; + using (var memoryStream = new MemoryStream()) { - var tokens = xSigSerialization.Serialize(); - if (tokens == null) return new byte[0]; - using (var memoryStream = new MemoryStream()) - { - using (var tokenWriter = new XSigTokenStreamWriter(memoryStream)) - tokenWriter.WriteXSigData(xSigSerialization, offset); - - return memoryStream.ToArray(); - } - } + using (var tokenWriter = new XSigTokenStreamWriter(memoryStream)) + tokenWriter.WriteXSigData(xSigSerialization, offset); - /// - /// Get bytes for a single digital signal. - /// - /// 1-based digital index - /// Digital data to be encoded - /// Bytes in XSig format for digtial information. - public static byte[] GetBytes(int index, bool value) - { - return GetBytes(index, 0, value); + return memoryStream.ToArray(); } + } - /// - /// Get bytes for a single digital signal. - /// - /// 1-based digital index - /// Index offset. - /// Digital data to be encoded - /// Bytes in XSig format for digtial information. - public static byte[] GetBytes(int index, int offset, bool value) - { - return new XSigDigitalToken(index + offset, value).GetBytes(); - } + /// + /// Get bytes for a single digital signal. + /// + /// 1-based digital index + /// Digital data to be encoded + /// Bytes in XSig format for digtial information. + public static byte[] GetBytes(int index, bool value) + { + return GetBytes(index, 0, value); + } - /// - /// Get byte sequence for multiple digital signals. - /// - /// Starting index of the sequence. - /// Digital signal value array. - /// Byte sequence in XSig format for digital signal information. - public static byte[] GetBytes(int startIndex, bool[] values) - { - return GetBytes(startIndex, 0, values); - } + /// + /// Get bytes for a single digital signal. + /// + /// 1-based digital index + /// Index offset. + /// Digital data to be encoded + /// Bytes in XSig format for digtial information. + public static byte[] GetBytes(int index, int offset, bool value) + { + return new XSigDigitalToken(index + offset, value).GetBytes(); + } - /// - /// Get byte sequence for multiple digital signals. - /// - /// Starting index of the sequence. - /// Index offset. - /// Digital signal value array. - /// Byte sequence in XSig format for digital signal information. - public static byte[] GetBytes(int startIndex, int offset, bool[] values) - { - // Digital XSig data is 2 bytes per value - const int fixedLength = 2; - var bytes = new byte[values.Length * fixedLength]; - for (var i = 0; i < values.Length; i++) - Buffer.BlockCopy(GetBytes(startIndex++, offset, values[i]), 0, bytes, i * fixedLength, fixedLength); + /// + /// Get byte sequence for multiple digital signals. + /// + /// Starting index of the sequence. + /// Digital signal value array. + /// Byte sequence in XSig format for digital signal information. + public static byte[] GetBytes(int startIndex, bool[] values) + { + return GetBytes(startIndex, 0, values); + } - return bytes; - } + /// + /// Get byte sequence for multiple digital signals. + /// + /// Starting index of the sequence. + /// Index offset. + /// Digital signal value array. + /// Byte sequence in XSig format for digital signal information. + public static byte[] GetBytes(int startIndex, int offset, bool[] values) + { + // Digital XSig data is 2 bytes per value + const int fixedLength = 2; + var bytes = new byte[values.Length * fixedLength]; + for (var i = 0; i < values.Length; i++) + Buffer.BlockCopy(GetBytes(startIndex++, offset, values[i]), 0, bytes, i * fixedLength, fixedLength); - /// - /// Get bytes for a single analog signal. - /// - /// 1-based analog index - /// Analog data to be encoded - /// Bytes in XSig format for analog signal information. - public static byte[] GetBytes(int index, ushort value) - { - return GetBytes(index, 0, value); - } + return bytes; + } - /// - /// Get bytes for a single analog signal. - /// - /// 1-based analog index - /// Index offset. - /// Analog data to be encoded - /// Bytes in XSig format for analog signal information. - public static byte[] GetBytes(int index, int offset, ushort value) - { - return new XSigAnalogToken(index + offset, value).GetBytes(); - } + /// + /// Get bytes for a single analog signal. + /// + /// 1-based analog index + /// Analog data to be encoded + /// Bytes in XSig format for analog signal information. + public static byte[] GetBytes(int index, ushort value) + { + return GetBytes(index, 0, value); + } - /// - /// Get byte sequence for multiple analog signals. - /// - /// Starting index of the sequence. - /// Analog signal value array. - /// Byte sequence in XSig format for analog signal information. - public static byte[] GetBytes(int startIndex, ushort[] values) - { - return GetBytes(startIndex, 0, values); - } + /// + /// Get bytes for a single analog signal. + /// + /// 1-based analog index + /// Index offset. + /// Analog data to be encoded + /// Bytes in XSig format for analog signal information. + public static byte[] GetBytes(int index, int offset, ushort value) + { + return new XSigAnalogToken(index + offset, value).GetBytes(); + } - /// - /// Get byte sequence for multiple analog signals. - /// - /// Starting index of the sequence. - /// Index offset. - /// Analog signal value array. - /// Byte sequence in XSig format for analog signal information. - public static byte[] GetBytes(int startIndex, int offset, ushort[] values) - { - // Analog XSig data is 4 bytes per value - const int fixedLength = 4; - var bytes = new byte[values.Length * fixedLength]; - for (var i = 0; i < values.Length; i++) - Buffer.BlockCopy(GetBytes(startIndex++, offset, values[i]), 0, bytes, i * fixedLength, fixedLength); + /// + /// Get byte sequence for multiple analog signals. + /// + /// Starting index of the sequence. + /// Analog signal value array. + /// Byte sequence in XSig format for analog signal information. + public static byte[] GetBytes(int startIndex, ushort[] values) + { + return GetBytes(startIndex, 0, values); + } - return bytes; - } + /// + /// Get byte sequence for multiple analog signals. + /// + /// Starting index of the sequence. + /// Index offset. + /// Analog signal value array. + /// Byte sequence in XSig format for analog signal information. + public static byte[] GetBytes(int startIndex, int offset, ushort[] values) + { + // Analog XSig data is 4 bytes per value + const int fixedLength = 4; + var bytes = new byte[values.Length * fixedLength]; + for (var i = 0; i < values.Length; i++) + Buffer.BlockCopy(GetBytes(startIndex++, offset, values[i]), 0, bytes, i * fixedLength, fixedLength); - /// - /// Get bytes for a single serial signal. - /// - /// 1-based serial index - /// Serial data to be encoded - /// Bytes in XSig format for serial signal information. - public static byte[] GetBytes(int index, string value) - { - return GetBytes(index, 0, value); - } + return bytes; + } - /// - /// Get bytes for a single serial signal. - /// - /// 1-based serial index - /// Index offset. - /// Serial data to be encoded - /// Bytes in XSig format for serial signal information. - public static byte[] GetBytes(int index, int offset, string value) - { - return new XSigSerialToken(index + offset, value).GetBytes(); - } + /// + /// Get bytes for a single serial signal. + /// + /// 1-based serial index + /// Serial data to be encoded + /// Bytes in XSig format for serial signal information. + public static byte[] GetBytes(int index, string value) + { + return GetBytes(index, 0, value); + } - /// - /// Get byte sequence for multiple serial signals. - /// - /// Starting index of the sequence. - /// Serial signal value array. - /// Byte sequence in XSig format for serial signal information. - public static byte[] GetBytes(int startIndex, string[] values) - { - return GetBytes(startIndex, 0, values); - } + /// + /// Get bytes for a single serial signal. + /// + /// 1-based serial index + /// Index offset. + /// Serial data to be encoded + /// Bytes in XSig format for serial signal information. + public static byte[] GetBytes(int index, int offset, string value) + { + return new XSigSerialToken(index + offset, value).GetBytes(); + } - /// - /// Get byte sequence for multiple serial signals. - /// - /// Starting index of the sequence. - /// Index offset. - /// Serial signal value array. - /// Byte sequence in XSig format for serial signal information. - public static byte[] GetBytes(int startIndex, int offset, string[] values) + /// + /// Get byte sequence for multiple serial signals. + /// + /// Starting index of the sequence. + /// Serial signal value array. + /// Byte sequence in XSig format for serial signal information. + public static byte[] GetBytes(int startIndex, string[] values) + { + return GetBytes(startIndex, 0, values); + } + + /// + /// Get byte sequence for multiple serial signals. + /// + /// Starting index of the sequence. + /// Index offset. + /// Serial signal value array. + /// Byte sequence in XSig format for serial signal information. + public static byte[] GetBytes(int startIndex, int offset, string[] values) + { + // Serial XSig data is not fixed-length like the other formats + var dstOffset = 0; + var bytes = new byte[values.Sum(v => v.Length + 3)]; + for (var i = 0; i < values.Length; i++) { - // Serial XSig data is not fixed-length like the other formats - var dstOffset = 0; - var bytes = new byte[values.Sum(v => v.Length + 3)]; - for (var i = 0; i < values.Length; i++) - { - var data = GetBytes(startIndex++, offset, values[i]); - Buffer.BlockCopy(data, 0, bytes, dstOffset, data.Length); - dstOffset += data.Length; - } - - return bytes; + var data = GetBytes(startIndex++, offset, values[i]); + Buffer.BlockCopy(data, 0, bytes, dstOffset, data.Length); + dstOffset += data.Length; } + + return bytes; } } \ No newline at end of file diff --git a/src/PepperDash.Core/XSigUtility/XSigTokenStreamReader.cs b/src/PepperDash.Core/XSigUtility/XSigTokenStreamReader.cs index 9d70d02e4..3c2229601 100644 --- a/src/PepperDash.Core/XSigUtility/XSigTokenStreamReader.cs +++ b/src/PepperDash.Core/XSigUtility/XSigTokenStreamReader.cs @@ -4,144 +4,143 @@ using PepperDash.Core.Intersystem.Serialization; using PepperDash.Core.Intersystem.Tokens; -namespace PepperDash.Core.Intersystem +namespace PepperDash.Core.Intersystem; + +/// +/// XSigToken stream reader. +/// +public sealed class XSigTokenStreamReader : IDisposable { + private readonly Stream _stream; + private readonly bool _leaveOpen; + + /// /// - /// XSigToken stream reader. + /// XSigToken stream reader constructor. /// - public sealed class XSigTokenStreamReader : IDisposable - { - private readonly Stream _stream; - private readonly bool _leaveOpen; - - /// - /// - /// XSigToken stream reader constructor. - /// - /// Input stream to read from. - /// Stream is null. - /// Stream cannot be read from. - public XSigTokenStreamReader(Stream stream) - : this(stream, false) { } - - /// - /// XSigToken stream reader constructor. - /// - /// Input stream to read from. - /// Determines whether to leave the stream open or not. - /// Stream is null. - /// Stream cannot be read from. - public XSigTokenStreamReader(Stream stream, bool leaveOpen) - { - if (stream == null) - throw new ArgumentNullException("stream"); - if (!stream.CanRead) - throw new ArgumentException("The specified stream cannot be read from."); + /// Input stream to read from. + /// Stream is null. + /// Stream cannot be read from. + public XSigTokenStreamReader(Stream stream) + : this(stream, false) { } - _stream = stream; - _leaveOpen = leaveOpen; - } + /// + /// XSigToken stream reader constructor. + /// + /// Input stream to read from. + /// Determines whether to leave the stream open or not. + /// Stream is null. + /// Stream cannot be read from. + public XSigTokenStreamReader(Stream stream, bool leaveOpen) + { + if (stream == null) + throw new ArgumentNullException("stream"); + if (!stream.CanRead) + throw new ArgumentException("The specified stream cannot be read from."); - /// - /// Reads a 16-bit unsigned integer from the specified stream using Big Endian byte order. - /// - /// Input stream - /// Result - /// True if successful, otherwise false. - public static bool TryReadUInt16BE(Stream stream, out ushort value) - { - value = 0; - if (stream.Length < 2) - return false; - - var buffer = new byte[2]; - stream.Read(buffer, 0, 2); - value = (ushort)((buffer[0] << 8) | buffer[1]); - return true; - } + _stream = stream; + _leaveOpen = leaveOpen; + } - /// - /// Read XSig token from the stream. - /// - /// XSigToken - /// Offset is less than 0. - public XSigToken ReadXSigToken() - { - ushort prefix; - if (!TryReadUInt16BE(_stream, out prefix)) - return null; + /// + /// Reads a 16-bit unsigned integer from the specified stream using Big Endian byte order. + /// + /// Input stream + /// Result + /// True if successful, otherwise false. + public static bool TryReadUInt16BE(Stream stream, out ushort value) + { + value = 0; + if (stream.Length < 2) + return false; + + var buffer = new byte[2]; + stream.Read(buffer, 0, 2); + value = (ushort)((buffer[0] << 8) | buffer[1]); + return true; + } - if ((prefix & 0xF880) == 0xC800) // Serial data - { - var index = ((prefix & 0x0700) >> 1) | (prefix & 0x7F); - var n = 0; - const int maxSerialDataLength = 252; - var chars = new char[maxSerialDataLength]; - int ch; - while ((ch = _stream.ReadByte()) != 0xFF) - { - if (ch == -1) // Reached end of stream without end of data marker - return null; - - chars[n++] = (char)ch; - } - - return new XSigSerialToken((ushort)(index + 1), new string(chars, 0, n)); - } + /// + /// Read XSig token from the stream. + /// + /// XSigToken + /// Offset is less than 0. + public XSigToken ReadXSigToken() + { + ushort prefix; + if (!TryReadUInt16BE(_stream, out prefix)) + return null; - if ((prefix & 0xC880) == 0xC000) // Analog data + if ((prefix & 0xF880) == 0xC800) // Serial data + { + var index = ((prefix & 0x0700) >> 1) | (prefix & 0x7F); + var n = 0; + const int maxSerialDataLength = 252; + var chars = new char[maxSerialDataLength]; + int ch; + while ((ch = _stream.ReadByte()) != 0xFF) { - ushort data; - if (!TryReadUInt16BE(_stream, out data)) + if (ch == -1) // Reached end of stream without end of data marker return null; - - var index = ((prefix & 0x0700) >> 1) | (prefix & 0x7F); - var value = ((prefix & 0x3000) << 2) | ((data & 0x7F00) >> 1) | (data & 0x7F); - return new XSigAnalogToken((ushort)(index + 1), (ushort)value); - } - - if ((prefix & 0xC080) == 0x8000) // Digital data - { - var index = ((prefix & 0x1F00) >> 1) | (prefix & 0x7F); - var value = (prefix & 0x2000) == 0; - return new XSigDigitalToken((ushort)(index + 1), value); + + chars[n++] = (char)ch; } - return null; + return new XSigSerialToken((ushort)(index + 1), new string(chars, 0, n)); } - /// - /// Reads all available XSig tokens from the stream. - /// - /// XSigToken collection. - public IEnumerable ReadAllXSigTokens() + if ((prefix & 0xC880) == 0xC000) // Analog data { - var tokens = new List(); - XSigToken token; - while ((token = ReadXSigToken()) != null) - tokens.Add(token); + ushort data; + if (!TryReadUInt16BE(_stream, out data)) + return null; - return tokens; + var index = ((prefix & 0x0700) >> 1) | (prefix & 0x7F); + var value = ((prefix & 0x3000) << 2) | ((data & 0x7F00) >> 1) | (data & 0x7F); + return new XSigAnalogToken((ushort)(index + 1), (ushort)value); } - /// - /// Attempts to deserialize all XSig data within the stream from the current position. - /// - /// Type to deserialize the information to. - /// Deserialized object. - public T DeserializeStream() - where T : class, IXSigSerialization, new() + if ((prefix & 0xC080) == 0x8000) // Digital data { - return new T().Deserialize(ReadAllXSigTokens()); + var index = ((prefix & 0x1F00) >> 1) | (prefix & 0x7F); + var value = (prefix & 0x2000) == 0; + return new XSigDigitalToken((ushort)(index + 1), value); } - /// - /// Disposes of the internal stream if specified to not leave open. - /// - public void Dispose() - { - if (!_leaveOpen) - _stream.Dispose(); - } + return null; + } + + /// + /// Reads all available XSig tokens from the stream. + /// + /// XSigToken collection. + public IEnumerable ReadAllXSigTokens() + { + var tokens = new List(); + XSigToken token; + while ((token = ReadXSigToken()) != null) + tokens.Add(token); + + return tokens; + } + + /// + /// Attempts to deserialize all XSig data within the stream from the current position. + /// + /// Type to deserialize the information to. + /// Deserialized object. + public T DeserializeStream() + where T : class, IXSigSerialization, new() + { + return new T().Deserialize(ReadAllXSigTokens()); + } + + /// + /// Disposes of the internal stream if specified to not leave open. + /// + public void Dispose() + { + if (!_leaveOpen) + _stream.Dispose(); } } \ No newline at end of file diff --git a/src/PepperDash.Core/XSigUtility/XSigTokenStreamWriter.cs b/src/PepperDash.Core/XSigUtility/XSigTokenStreamWriter.cs index 934f2c293..da973acd1 100644 --- a/src/PepperDash.Core/XSigUtility/XSigTokenStreamWriter.cs +++ b/src/PepperDash.Core/XSigUtility/XSigTokenStreamWriter.cs @@ -5,132 +5,131 @@ using PepperDash.Core.Intersystem.Serialization; using PepperDash.Core.Intersystem.Tokens; -namespace PepperDash.Core.Intersystem +namespace PepperDash.Core.Intersystem; + +/// +/// XSigToken stream writer. +/// +public sealed class XSigTokenStreamWriter : IDisposable { + private readonly Stream _stream; + private readonly bool _leaveOpen; + + /// /// - /// XSigToken stream writer. + /// XSigToken stream writer constructor. /// - public sealed class XSigTokenStreamWriter : IDisposable - { - private readonly Stream _stream; - private readonly bool _leaveOpen; + /// Input stream to write to. + /// Stream is null. + /// Stream cannot be written to. + public XSigTokenStreamWriter(Stream stream) + : this(stream, false) { } - /// - /// - /// XSigToken stream writer constructor. - /// - /// Input stream to write to. - /// Stream is null. - /// Stream cannot be written to. - public XSigTokenStreamWriter(Stream stream) - : this(stream, false) { } + /// + /// XSigToken stream writer constructor. + /// + /// Input stream to write to. + /// Determines whether to leave the stream open or not. + /// Stream is null. + /// Stream cannot be written to. + public XSigTokenStreamWriter(Stream stream, bool leaveOpen) + { + if (stream == null) + throw new ArgumentNullException("stream"); + if (!stream.CanWrite) + throw new ArgumentException("The specified stream cannot be written to."); - /// - /// XSigToken stream writer constructor. - /// - /// Input stream to write to. - /// Determines whether to leave the stream open or not. - /// Stream is null. - /// Stream cannot be written to. - public XSigTokenStreamWriter(Stream stream, bool leaveOpen) - { - if (stream == null) - throw new ArgumentNullException("stream"); - if (!stream.CanWrite) - throw new ArgumentException("The specified stream cannot be written to."); + _stream = stream; + _leaveOpen = leaveOpen; + } - _stream = stream; - _leaveOpen = leaveOpen; - } + /// + /// Write XSig data gathered from an IXSigStateResolver to the stream. + /// + /// IXSigStateResolver object. + public void WriteXSigData(IXSigSerialization xSigSerialization) + { + WriteXSigData(xSigSerialization, 0); + } - /// - /// Write XSig data gathered from an IXSigStateResolver to the stream. - /// - /// IXSigStateResolver object. - public void WriteXSigData(IXSigSerialization xSigSerialization) - { - WriteXSigData(xSigSerialization, 0); - } + /// + /// Write XSig data gathered from an IXSigStateResolver to the stream. + /// + /// IXSigStateResolver object. + /// Index offset for each XSigToken. + public void WriteXSigData(IXSigSerialization xSigSerialization, int offset) + { + if (xSigSerialization == null) + throw new ArgumentNullException("xSigSerialization"); - /// - /// Write XSig data gathered from an IXSigStateResolver to the stream. - /// - /// IXSigStateResolver object. - /// Index offset for each XSigToken. - public void WriteXSigData(IXSigSerialization xSigSerialization, int offset) - { - if (xSigSerialization == null) - throw new ArgumentNullException("xSigSerialization"); + var tokens = xSigSerialization.Serialize(); + WriteXSigData(tokens, offset); + } - var tokens = xSigSerialization.Serialize(); - WriteXSigData(tokens, offset); - } + /// + /// Write XSigToken to the stream. + /// + /// XSigToken object. + public void WriteXSigData(XSigToken token) + { + WriteXSigData(token, 0); + } - /// - /// Write XSigToken to the stream. - /// - /// XSigToken object. - public void WriteXSigData(XSigToken token) - { - WriteXSigData(token, 0); - } + /// + /// Write XSigToken to the stream. + /// + /// XSigToken object. + /// Index offset for each XSigToken. + public void WriteXSigData(XSigToken token, int offset) + { + WriteXSigData(new[] { token }, offset); + } - /// - /// Write XSigToken to the stream. - /// - /// XSigToken object. - /// Index offset for each XSigToken. - public void WriteXSigData(XSigToken token, int offset) - { - WriteXSigData(new[] { token }, offset); - } + /// + /// Writes an array of XSigTokens to the stream. + /// + /// XSigToken objects. + public void WriteXSigData(XSigToken[] tokens) + { + WriteXSigData(tokens.AsEnumerable()); + } - /// - /// Writes an array of XSigTokens to the stream. - /// - /// XSigToken objects. - public void WriteXSigData(XSigToken[] tokens) - { - WriteXSigData(tokens.AsEnumerable()); - } + /// + /// Write an enumerable collection of XSigTokens to the stream. + /// + /// XSigToken objects. + public void WriteXSigData(IEnumerable tokens) + { + WriteXSigData(tokens, 0); + } - /// - /// Write an enumerable collection of XSigTokens to the stream. - /// - /// XSigToken objects. - public void WriteXSigData(IEnumerable tokens) - { - WriteXSigData(tokens, 0); - } + /// + /// Write an enumerable collection of XSigTokens to the stream. + /// + /// XSigToken objects. + /// Index offset for each XSigToken. + public void WriteXSigData(IEnumerable tokens, int offset) + { + if (offset < 0) + throw new ArgumentOutOfRangeException("offset", "Offset must be greater than or equal to 0."); - /// - /// Write an enumerable collection of XSigTokens to the stream. - /// - /// XSigToken objects. - /// Index offset for each XSigToken. - public void WriteXSigData(IEnumerable tokens, int offset) + if (tokens != null) { - if (offset < 0) - throw new ArgumentOutOfRangeException("offset", "Offset must be greater than or equal to 0."); - - if (tokens != null) + foreach (var token in tokens) { - foreach (var token in tokens) - { - if (token == null) continue; - var bytes = token.GetTokenWithOffset(offset).GetBytes(); - _stream.Write(bytes, 0, bytes.Length); - } + if (token == null) continue; + var bytes = token.GetTokenWithOffset(offset).GetBytes(); + _stream.Write(bytes, 0, bytes.Length); } } + } - /// - /// Disposes of the internal stream if specified to not leave open. - /// - public void Dispose() - { - if (!_leaveOpen) - _stream.Dispose(); - } + /// + /// Disposes of the internal stream if specified to not leave open. + /// + public void Dispose() + { + if (!_leaveOpen) + _stream.Dispose(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/BridgeBase.cs b/src/PepperDash.Essentials.Core/Bridges/BridgeBase.cs index c1590704a..627ecf205 100644 --- a/src/PepperDash.Essentials.Core/Bridges/BridgeBase.cs +++ b/src/PepperDash.Essentials.Core/Bridges/BridgeBase.cs @@ -16,410 +16,408 @@ //using PepperDash.Essentials.Devices.Common.Cameras; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +/// +/// Base class for bridge API variants +/// +public abstract class BridgeApi : EssentialsDevice { - /// - /// Base class for bridge API variants - /// - public abstract class BridgeApi : EssentialsDevice + protected BridgeApi(string key) : + base(key) { - protected BridgeApi(string key) : - base(key) - { - } } +} - /// - /// Bridge API using EISC - /// - public class EiscApiAdvanced : BridgeApi, ICommunicationMonitor - { - public EiscApiPropertiesConfig PropertiesConfig { get; private set; } +/// +/// Bridge API using EISC +/// +public class EiscApiAdvanced : BridgeApi, ICommunicationMonitor +{ + public EiscApiPropertiesConfig PropertiesConfig { get; private set; } - public Dictionary JoinMaps { get; private set; } + public Dictionary JoinMaps { get; private set; } - public BasicTriList Eisc { get; private set; } + public BasicTriList Eisc { get; private set; } - public EiscApiAdvanced(DeviceConfig dc, BasicTriList eisc) : - base(dc.Key) - { - JoinMaps = new Dictionary(); + public EiscApiAdvanced(DeviceConfig dc, BasicTriList eisc) : + base(dc.Key) + { + JoinMaps = new Dictionary(); - PropertiesConfig = dc.Properties.ToObject(); - //PropertiesConfig = JsonConvert.DeserializeObject(dc.Properties.ToString()); + PropertiesConfig = dc.Properties.ToObject(); + //PropertiesConfig = JsonConvert.DeserializeObject(dc.Properties.ToString()); - Eisc = eisc; + Eisc = eisc; - Eisc.SigChange += Eisc_SigChange; + Eisc.SigChange += Eisc_SigChange; - CommunicationMonitor = new CrestronGenericBaseCommunicationMonitor(this, Eisc, 120000, 300000); + CommunicationMonitor = new CrestronGenericBaseCommunicationMonitor(this, Eisc, 120000, 300000); - AddPostActivationAction(LinkDevices); - AddPostActivationAction(LinkRooms); - AddPostActivationAction(RegisterEisc); - } + AddPostActivationAction(LinkDevices); + AddPostActivationAction(LinkRooms); + AddPostActivationAction(RegisterEisc); + } - public override bool CustomActivate() - { - CommunicationMonitor.Start(); - return base.CustomActivate(); - } + public override bool CustomActivate() + { + CommunicationMonitor.Start(); + return base.CustomActivate(); + } - public override bool Deactivate() + public override bool Deactivate() + { + CommunicationMonitor.Stop(); + return base.Deactivate(); + } + + private void LinkDevices() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Linking Devices..."); + + if (PropertiesConfig.Devices == null) { - CommunicationMonitor.Stop(); - return base.Deactivate(); + Debug.LogMessage(LogEventLevel.Debug, this, "No devices linked to this bridge"); + return; } - private void LinkDevices() + foreach (var d in PropertiesConfig.Devices) { - Debug.LogMessage(LogEventLevel.Debug, this, "Linking Devices..."); + var device = DeviceManager.GetDeviceForKey(d.DeviceKey); - if (PropertiesConfig.Devices == null) + if (device == null) { - Debug.LogMessage(LogEventLevel.Debug, this, "No devices linked to this bridge"); - return; + continue; } - foreach (var d in PropertiesConfig.Devices) - { - var device = DeviceManager.GetDeviceForKey(d.DeviceKey); + Debug.LogMessage(LogEventLevel.Debug, this, "Linking Device: '{0}'", device.Key); - if (device == null) - { - continue; - } - - Debug.LogMessage(LogEventLevel.Debug, this, "Linking Device: '{0}'", device.Key); + if (device is IBridgeAdvanced bridge) + { + bridge.LinkToApi(Eisc, d.JoinStart, d.JoinMapKey, this); + continue; + } - if (device is IBridgeAdvanced bridge) - { - bridge.LinkToApi(Eisc, d.JoinStart, d.JoinMapKey, this); - continue; - } + Debug.LogMessage(LogEventLevel.Information, this, + "{0} is not compatible with this bridge type. Please use 'eiscapi' instead, or updae the device.", + device.Key); + } + } - Debug.LogMessage(LogEventLevel.Information, this, - "{0} is not compatible with this bridge type. Please use 'eiscapi' instead, or updae the device.", - device.Key); - } + private void RegisterEisc() + { + if (Eisc.Registered) + { + return; } - private void RegisterEisc() + var registerResult = Eisc.Register(); + + if (registerResult != eDeviceRegistrationUnRegistrationResponse.Success) { - if (Eisc.Registered) - { - return; - } + Debug.LogMessage(LogEventLevel.Verbose, this, "Registration result: {0}", registerResult); + return; + } - var registerResult = Eisc.Register(); + Debug.LogMessage(LogEventLevel.Debug, this, "EISC registration successful"); + } - if (registerResult != eDeviceRegistrationUnRegistrationResponse.Success) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Registration result: {0}", registerResult); - return; - } + public void LinkRooms() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Linking Rooms..."); - Debug.LogMessage(LogEventLevel.Debug, this, "EISC registration successful"); + if (PropertiesConfig.Rooms == null) + { + Debug.LogMessage(LogEventLevel.Debug, this, "No rooms linked to this bridge."); + return; } - public void LinkRooms() + foreach (var room in PropertiesConfig.Rooms) { - Debug.LogMessage(LogEventLevel.Debug, this, "Linking Rooms..."); + var rm = DeviceManager.GetDeviceForKey(room.RoomKey) as IBridgeAdvanced; - if (PropertiesConfig.Rooms == null) + if (rm == null) { - Debug.LogMessage(LogEventLevel.Debug, this, "No rooms linked to this bridge."); - return; + Debug.LogMessage(LogEventLevel.Debug, this, + "Room {0} does not implement IBridgeAdvanced. Skipping...", room.RoomKey); + continue; } - foreach (var room in PropertiesConfig.Rooms) - { - var rm = DeviceManager.GetDeviceForKey(room.RoomKey) as IBridgeAdvanced; - - if (rm == null) - { - Debug.LogMessage(LogEventLevel.Debug, this, - "Room {0} does not implement IBridgeAdvanced. Skipping...", room.RoomKey); - continue; - } - - rm.LinkToApi(Eisc, room.JoinStart, room.JoinMapKey, this); - } + rm.LinkToApi(Eisc, room.JoinStart, room.JoinMapKey, this); } + } - /// - /// Adds a join map - /// - /// - /// - public void AddJoinMap(string deviceKey, JoinMapBaseAdvanced joinMap) + /// + /// Adds a join map + /// + /// + /// + public void AddJoinMap(string deviceKey, JoinMapBaseAdvanced joinMap) + { + if (!JoinMaps.ContainsKey(deviceKey)) { - if (!JoinMaps.ContainsKey(deviceKey)) - { - JoinMaps.Add(deviceKey, joinMap); - } - else - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Unable to add join map with key '{0}'. Key already exists in JoinMaps dictionary", deviceKey); - } + JoinMaps.Add(deviceKey, joinMap); } - - /// - /// Prints all the join maps on this bridge - /// - public virtual void PrintJoinMaps() + else { - CrestronConsole.ConsoleCommandResponse("Join Maps for EISC IPID: {0}\r\n", Eisc.ID.ToString("X")); - - foreach (var joinMap in JoinMaps) - { - CrestronConsole.ConsoleCommandResponse("Join map for device '{0}':", joinMap.Key); - joinMap.Value.PrintJoinMapInfo(); - } + Debug.LogMessage(LogEventLevel.Verbose, this, "Unable to add join map with key '{0}'. Key already exists in JoinMaps dictionary", deviceKey); } - /// - /// Generates markdown for all join maps on this bridge - /// - public virtual void MarkdownForBridge(string bridgeKey) - { - Debug.LogMessage(LogEventLevel.Information, this, "Writing Joinmaps to files for EISC IPID: {0}", Eisc.ID.ToString("X")); + } - foreach (var joinMap in JoinMaps) - { - Debug.LogMessage(LogEventLevel.Information, "Generating markdown for device '{0}':", joinMap.Key); - joinMap.Value.MarkdownJoinMapInfo(joinMap.Key, bridgeKey); - } + /// + /// Prints all the join maps on this bridge + /// + public virtual void PrintJoinMaps() + { + CrestronConsole.ConsoleCommandResponse("Join Maps for EISC IPID: {0}\r\n", Eisc.ID.ToString("X")); + + foreach (var joinMap in JoinMaps) + { + CrestronConsole.ConsoleCommandResponse("Join map for device '{0}':", joinMap.Key); + joinMap.Value.PrintJoinMapInfo(); } + } + /// + /// Generates markdown for all join maps on this bridge + /// + public virtual void MarkdownForBridge(string bridgeKey) + { + Debug.LogMessage(LogEventLevel.Information, this, "Writing Joinmaps to files for EISC IPID: {0}", Eisc.ID.ToString("X")); - /// - /// Prints the join map for a device by key - /// - /// - public void PrintJoinMapForDevice(string deviceKey) + foreach (var joinMap in JoinMaps) { - var joinMap = JoinMaps[deviceKey]; + Debug.LogMessage(LogEventLevel.Information, "Generating markdown for device '{0}':", joinMap.Key); + joinMap.Value.MarkdownJoinMapInfo(joinMap.Key, bridgeKey); + } + } - if (joinMap == null) - { - Debug.LogMessage(LogEventLevel.Information, this, "Unable to find joinMap for device with key: '{0}'", deviceKey); - return; - } + /// + /// Prints the join map for a device by key + /// + /// + public void PrintJoinMapForDevice(string deviceKey) + { + var joinMap = JoinMaps[deviceKey]; - Debug.LogMessage(LogEventLevel.Information, "Join map for device '{0}' on EISC '{1}':", deviceKey, Key); - joinMap.PrintJoinMapInfo(); - } - /// - /// Prints the join map for a device by key - /// - /// - public void MarkdownJoinMapForDevice(string deviceKey, string bridgeKey) + if (joinMap == null) { - var joinMap = JoinMaps[deviceKey]; + Debug.LogMessage(LogEventLevel.Information, this, "Unable to find joinMap for device with key: '{0}'", deviceKey); + return; + } - if (joinMap == null) - { - Debug.LogMessage(LogEventLevel.Information, this, "Unable to find joinMap for device with key: '{0}'", deviceKey); - return; - } + Debug.LogMessage(LogEventLevel.Information, "Join map for device '{0}' on EISC '{1}':", deviceKey, Key); + joinMap.PrintJoinMapInfo(); + } + /// + /// Prints the join map for a device by key + /// + /// + public void MarkdownJoinMapForDevice(string deviceKey, string bridgeKey) + { + var joinMap = JoinMaps[deviceKey]; - Debug.LogMessage(LogEventLevel.Information, "Join map for device '{0}' on EISC '{1}':", deviceKey, Key); - joinMap.MarkdownJoinMapInfo(deviceKey, bridgeKey); + if (joinMap == null) + { + Debug.LogMessage(LogEventLevel.Information, this, "Unable to find joinMap for device with key: '{0}'", deviceKey); + return; } - /// - /// Used for debugging to trigger an action based on a join number and type - /// - /// - /// - /// - public void ExecuteJoinAction(uint join, string type, object state) + Debug.LogMessage(LogEventLevel.Information, "Join map for device '{0}' on EISC '{1}':", deviceKey, Key); + joinMap.MarkdownJoinMapInfo(deviceKey, bridgeKey); + } + + /// + /// Used for debugging to trigger an action based on a join number and type + /// + /// + /// + /// + public void ExecuteJoinAction(uint join, string type, object state) + { + try { - try + switch (type.ToLower()) { - switch (type.ToLower()) - { - case "digital": - { - var uo = Eisc.BooleanOutput[join].UserObject as Action; - if (uo != null) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Executing Action: {0}", uo.ToString()); - uo(Convert.ToBoolean(state)); - } - else - Debug.LogMessage(LogEventLevel.Verbose, this, "User Action is null. Nothing to Execute"); - break; - } - case "analog": + case "digital": + { + var uo = Eisc.BooleanOutput[join].UserObject as Action; + if (uo != null) { - var uo = Eisc.BooleanOutput[join].UserObject as Action; - if (uo != null) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Executing Action: {0}", uo.ToString()); - uo(Convert.ToUInt16(state)); - } - else - Debug.LogMessage(LogEventLevel.Verbose, this, "User Action is null. Nothing to Execute"); break; + Debug.LogMessage(LogEventLevel.Verbose, this, "Executing Action: {0}", uo.ToString()); + uo(Convert.ToBoolean(state)); } - case "serial": + else + Debug.LogMessage(LogEventLevel.Verbose, this, "User Action is null. Nothing to Execute"); + break; + } + case "analog": + { + var uo = Eisc.BooleanOutput[join].UserObject as Action; + if (uo != null) { - var uo = Eisc.BooleanOutput[join].UserObject as Action; - if (uo != null) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Executing Action: {0}", uo.ToString()); - uo(Convert.ToString(state)); - } - else - Debug.LogMessage(LogEventLevel.Verbose, this, "User Action is null. Nothing to Execute"); - break; + Debug.LogMessage(LogEventLevel.Verbose, this, "Executing Action: {0}", uo.ToString()); + uo(Convert.ToUInt16(state)); } - default: + else + Debug.LogMessage(LogEventLevel.Verbose, this, "User Action is null. Nothing to Execute"); break; + } + case "serial": + { + var uo = Eisc.BooleanOutput[join].UserObject as Action; + if (uo != null) { - Debug.LogMessage(LogEventLevel.Verbose, "Unknown join type. Use digital/serial/analog"); - break; + Debug.LogMessage(LogEventLevel.Verbose, this, "Executing Action: {0}", uo.ToString()); + uo(Convert.ToString(state)); } - } - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e); + else + Debug.LogMessage(LogEventLevel.Verbose, this, "User Action is null. Nothing to Execute"); + break; + } + default: + { + Debug.LogMessage(LogEventLevel.Verbose, "Unknown join type. Use digital/serial/analog"); + break; + } } - } - - /// - /// Handles incoming sig changes - /// - /// - /// - protected void Eisc_SigChange(object currentDevice, SigEventArgs args) + catch (Exception e) { - try - { - Debug.LogMessage(LogEventLevel.Verbose, this, "EiscApiAdvanced change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue); - var uo = args.Sig.UserObject; - - if (uo == null) return; - - Debug.LogMessage(LogEventLevel.Debug, this, "Executing Action: {0}", uo.ToString()); - if (uo is Action) - (uo as Action)(args.Sig.BoolValue); - else if (uo is Action) - (uo as Action)(args.Sig.UShortValue); - else if (uo is Action) - (uo as Action)(args.Sig.StringValue); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Error in Eisc_SigChange handler: {0}", e); - } + Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e); } - #region Implementation of ICommunicationMonitor - - public StatusMonitorBase CommunicationMonitor { get; private set; } - - #endregion } - public class EiscApiPropertiesConfig + /// + /// Handles incoming sig changes + /// + /// + /// + protected void Eisc_SigChange(object currentDevice, SigEventArgs args) { - [JsonProperty("control")] - public EssentialsControlPropertiesConfig Control { get; set; } + try + { + Debug.LogMessage(LogEventLevel.Verbose, this, "EiscApiAdvanced change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue); + var uo = args.Sig.UserObject; + + if (uo == null) return; + + Debug.LogMessage(LogEventLevel.Debug, this, "Executing Action: {0}", uo.ToString()); + if (uo is Action) + (uo as Action)(args.Sig.BoolValue); + else if (uo is Action) + (uo as Action)(args.Sig.UShortValue); + else if (uo is Action) + (uo as Action)(args.Sig.StringValue); + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Error in Eisc_SigChange handler: {0}", e); + } + } - [JsonProperty("devices")] - public List Devices { get; set; } + #region Implementation of ICommunicationMonitor - [JsonProperty("rooms")] - public List Rooms { get; set; } + public StatusMonitorBase CommunicationMonitor { get; private set; } + #endregion +} - public class ApiDevicePropertiesConfig - { - [JsonProperty("deviceKey")] - public string DeviceKey { get; set; } +public class EiscApiPropertiesConfig +{ + [JsonProperty("control")] + public EssentialsControlPropertiesConfig Control { get; set; } - [JsonProperty("joinStart")] - public uint JoinStart { get; set; } + [JsonProperty("devices")] + public List Devices { get; set; } - [JsonProperty("joinMapKey")] - public string JoinMapKey { get; set; } - } + [JsonProperty("rooms")] + public List Rooms { get; set; } - public class ApiRoomPropertiesConfig - { - [JsonProperty("roomKey")] - public string RoomKey { get; set; } - [JsonProperty("joinStart")] - public uint JoinStart { get; set; } + public class ApiDevicePropertiesConfig + { + [JsonProperty("deviceKey")] + public string DeviceKey { get; set; } - [JsonProperty("joinMapKey")] - public string JoinMapKey { get; set; } - } + [JsonProperty("joinStart")] + public uint JoinStart { get; set; } + [JsonProperty("joinMapKey")] + public string JoinMapKey { get; set; } } - public class EiscApiAdvancedFactory : EssentialsDeviceFactory + public class ApiRoomPropertiesConfig { - public EiscApiAdvancedFactory() - { - TypeNames = new List { "eiscapiadv", "eiscapiadvanced", "eiscapiadvancedserver", "eiscapiadvancedclient", "vceiscapiadv", "vceiscapiadvanced" }; - } + [JsonProperty("roomKey")] + public string RoomKey { get; set; } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new EiscApiAdvanced Device"); + [JsonProperty("joinStart")] + public uint JoinStart { get; set; } - var controlProperties = CommFactory.GetControlPropertiesConfig(dc); + [JsonProperty("joinMapKey")] + public string JoinMapKey { get; set; } + } - BasicTriList eisc; +} - switch (dc.Type.ToLower()) - { - case "eiscapiadv": - case "eiscapiadvanced": - { - eisc = new ThreeSeriesTcpIpEthernetIntersystemCommunications(controlProperties.IpIdInt, - controlProperties.TcpSshProperties.Address, Global.ControlSystem); - break; - } - case "eiscapiadvancedserver": - { - eisc = new EISCServer(controlProperties.IpIdInt, Global.ControlSystem); - break; - } - case "eiscapiadvancedclient": - { - eisc = new EISCClient(controlProperties.IpIdInt, controlProperties.TcpSshProperties.Address, Global.ControlSystem); - break; - } - case "vceiscapiadv": - case "vceiscapiadvanced": +public class EiscApiAdvancedFactory : EssentialsDeviceFactory +{ + public EiscApiAdvancedFactory() + { + TypeNames = new List { "eiscapiadv", "eiscapiadvanced", "eiscapiadvancedserver", "eiscapiadvancedclient", "vceiscapiadv", "vceiscapiadvanced" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new EiscApiAdvanced Device"); + + var controlProperties = CommFactory.GetControlPropertiesConfig(dc); + + BasicTriList eisc; + + switch (dc.Type.ToLower()) + { + case "eiscapiadv": + case "eiscapiadvanced": + { + eisc = new ThreeSeriesTcpIpEthernetIntersystemCommunications(controlProperties.IpIdInt, + controlProperties.TcpSshProperties.Address, Global.ControlSystem); + break; + } + case "eiscapiadvancedserver": + { + eisc = new EISCServer(controlProperties.IpIdInt, Global.ControlSystem); + break; + } + case "eiscapiadvancedclient": + { + eisc = new EISCClient(controlProperties.IpIdInt, controlProperties.TcpSshProperties.Address, Global.ControlSystem); + break; + } + case "vceiscapiadv": + case "vceiscapiadvanced": + { + if (string.IsNullOrEmpty(controlProperties.RoomId)) { - if (string.IsNullOrEmpty(controlProperties.RoomId)) - { - Debug.LogMessage(LogEventLevel.Information, "Unable to build VC-4 EISC Client for device {0}. Room ID is missing or empty", dc.Key); - eisc = null; - break; - } - eisc = new VirtualControlEISCClient(controlProperties.IpIdInt, controlProperties.RoomId, - Global.ControlSystem); + Debug.LogMessage(LogEventLevel.Information, "Unable to build VC-4 EISC Client for device {0}. Room ID is missing or empty", dc.Key); + eisc = null; break; } - default: - eisc = null; + eisc = new VirtualControlEISCClient(controlProperties.IpIdInt, controlProperties.RoomId, + Global.ControlSystem); break; - } - - if (eisc == null) - { - return null; - } + } + default: + eisc = null; + break; + } - return new EiscApiAdvanced(dc, eisc); + if (eisc == null) + { + return null; } - } + return new EiscApiAdvanced(dc, eisc); + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/BridgeHelper.cs b/src/PepperDash.Essentials.Core/Bridges/BridgeHelper.cs index 0254cd0d7..3a3ceff20 100644 --- a/src/PepperDash.Essentials.Core/Bridges/BridgeHelper.cs +++ b/src/PepperDash.Essentials.Core/Bridges/BridgeHelper.cs @@ -3,64 +3,62 @@ //using PepperDash.Essentials.Devices.Common.Cameras; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +/// +/// Helper methods for bridges +/// +public static class BridgeHelper { - /// - /// Helper methods for bridges - /// - public static class BridgeHelper + public static void PrintJoinMap(string command) { - public static void PrintJoinMap(string command) - { - var targets = command.Split(' '); + var targets = command.Split(' '); - var bridgeKey = targets[0].Trim(); + var bridgeKey = targets[0].Trim(); - if (!(DeviceManager.GetDeviceForKey(bridgeKey) is EiscApiAdvanced bridge)) - { - Debug.LogMessage(LogEventLevel.Information, "Unable to find advanced bridge with key: '{0}'", bridgeKey); - return; - } + if (!(DeviceManager.GetDeviceForKey(bridgeKey) is EiscApiAdvanced bridge)) + { + Debug.LogMessage(LogEventLevel.Information, "Unable to find advanced bridge with key: '{0}'", bridgeKey); + return; + } - if (targets.Length > 1) - { - var deviceKey = targets[1].Trim(); + if (targets.Length > 1) + { + var deviceKey = targets[1].Trim(); - if (string.IsNullOrEmpty(deviceKey)) return; - bridge.PrintJoinMapForDevice(deviceKey); - } - else - { - bridge.PrintJoinMaps(); - } + if (string.IsNullOrEmpty(deviceKey)) return; + bridge.PrintJoinMapForDevice(deviceKey); } - public static void JoinmapMarkdown(string command) + else { - var targets = command.Split(' '); + bridge.PrintJoinMaps(); + } + } + public static void JoinmapMarkdown(string command) + { + var targets = command.Split(' '); - var bridgeKey = targets[0].Trim(); + var bridgeKey = targets[0].Trim(); - var bridge = DeviceManager.GetDeviceForKey(bridgeKey) as EiscApiAdvanced; + var bridge = DeviceManager.GetDeviceForKey(bridgeKey) as EiscApiAdvanced; - if (bridge == null) - { - Debug.LogMessage(LogEventLevel.Information, "Unable to find advanced bridge with key: '{0}'", bridgeKey); - return; - } + if (bridge == null) + { + Debug.LogMessage(LogEventLevel.Information, "Unable to find advanced bridge with key: '{0}'", bridgeKey); + return; + } - if (targets.Length > 1) - { - var deviceKey = targets[1].Trim(); + if (targets.Length > 1) + { + var deviceKey = targets[1].Trim(); - if (string.IsNullOrEmpty(deviceKey)) return; - bridge.MarkdownJoinMapForDevice(deviceKey, bridgeKey); - } - else - { - bridge.MarkdownForBridge(bridgeKey); + if (string.IsNullOrEmpty(deviceKey)) return; + bridge.MarkdownJoinMapForDevice(deviceKey, bridgeKey); + } + else + { + bridge.MarkdownForBridge(bridgeKey); - } } } - } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/IBridge.cs b/src/PepperDash.Essentials.Core/Bridges/IBridge.cs index 0c6b44ed8..87b4bd351 100644 --- a/src/PepperDash.Essentials.Core/Bridges/IBridge.cs +++ b/src/PepperDash.Essentials.Core/Bridges/IBridge.cs @@ -1,12 +1,11 @@ using Crestron.SimplSharpPro.DeviceSupport; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +/// +/// Defines a device that uses JoinMapBaseAdvanced for its join map +/// +public interface IBridgeAdvanced { - /// - /// Defines a device that uses JoinMapBaseAdvanced for its join map - /// - public interface IBridgeAdvanced - { - void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge); - } + void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/AirMediaControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/AirMediaControllerJoinMap.cs index c46df18cc..33fca20eb 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/AirMediaControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/AirMediaControllerJoinMap.cs @@ -1,71 +1,70 @@ using System; -namespace PepperDash.Essentials.Core.Bridges -{ - public class AirMediaControllerJoinMap : JoinMapBaseAdvanced - { - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Air Media Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); +namespace PepperDash.Essentials.Core.Bridges; - [JoinName("IsInSession")] - public JoinDataComplete IsInSession = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Air Media In Sharing Session", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); +public class AirMediaControllerJoinMap : JoinMapBaseAdvanced +{ + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Air Media Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("HdmiVideoSync")] - public JoinDataComplete HdmiVideoSync = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Air Media Has HDMI Video Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("IsInSession")] + public JoinDataComplete IsInSession = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Air Media In Sharing Session", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("AutomaticInputRoutingEnabled")] - public JoinDataComplete AutomaticInputRoutingEnabled = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Air Media Automatic Input Routing Enable(d)", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("HdmiVideoSync")] + public JoinDataComplete HdmiVideoSync = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Air Media Has HDMI Video Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("VideoOut")] - public JoinDataComplete VideoOut = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Air Media Video Route Select / Feedback", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("AutomaticInputRoutingEnabled")] + public JoinDataComplete AutomaticInputRoutingEnabled = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Air Media Automatic Input Routing Enable(d)", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ErrorFB")] - public JoinDataComplete ErrorFB = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Air Media Error Status", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + [JoinName("VideoOut")] + public JoinDataComplete VideoOut = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Air Media Video Route Select / Feedback", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - [JoinName("NumberOfUsersConnectedFB")] - public JoinDataComplete NumberOfUsersConnectedFB = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Air Media Number of Users Connected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + [JoinName("ErrorFB")] + public JoinDataComplete ErrorFB = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Air Media Error Status", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - [JoinName("LoginCode")] - public JoinDataComplete LoginCode = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Air Media Login Code Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("NumberOfUsersConnectedFB")] + public JoinDataComplete NumberOfUsersConnectedFB = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Air Media Number of Users Connected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - [JoinName("Name")] - public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Air Media Device Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("LoginCode")] + public JoinDataComplete LoginCode = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Air Media Login Code Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - [JoinName("ConnectionAddressFB")] - public JoinDataComplete ConnectionAddressFB = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Air Media IP Address", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Air Media Device Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("HostnameFB")] - public JoinDataComplete HostnameFB = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Air Media Hostname", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("ConnectionAddressFB")] + public JoinDataComplete ConnectionAddressFB = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Air Media IP Address", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("SerialNumberFeedback")] - public JoinDataComplete SerialNumberFeedback = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Air Media Serial Number", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public AirMediaControllerJoinMap(uint joinStart) - : this(joinStart, typeof(AirMediaControllerJoinMap)) - { - } + [JoinName("HostnameFB")] + public JoinDataComplete HostnameFB = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Air Media Hostname", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected AirMediaControllerJoinMap(uint joinStart, Type type) : base(joinStart, type){} + [JoinName("SerialNumberFeedback")] + public JoinDataComplete SerialNumberFeedback = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Air Media Serial Number", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public AirMediaControllerJoinMap(uint joinStart) + : this(joinStart, typeof(AirMediaControllerJoinMap)) + { } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected AirMediaControllerJoinMap(uint joinStart, Type type) : base(joinStart, type){} } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/AppleTvJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/AppleTvJoinMap.cs index 7a9dfa744..3b3eaa062 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/AppleTvJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/AppleTvJoinMap.cs @@ -1,53 +1,52 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class AppleTvJoinMap : JoinMapBaseAdvanced { - public class AppleTvJoinMap : JoinMapBaseAdvanced + [JoinName("UpArrow")] + public JoinDataComplete UpArrow = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "AppleTv Nav Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("DnArrow")] + public JoinDataComplete DnArrow = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "AppleTv Nav Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("LeftArrow")] + public JoinDataComplete LeftArrow = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "AppleTv Nav Left", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("RightArrow")] + public JoinDataComplete RightArrow = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "AppleTv Nav Right", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Menu")] + public JoinDataComplete Menu = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "AppleTv Menu", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Select")] + public JoinDataComplete Select = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata { Description = "AppleTv Select", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("PlayPause")] + public JoinDataComplete PlayPause = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, + new JoinMetadata { Description = "AppleTv Play/Pause", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public AppleTvJoinMap(uint joinStart) + : base(joinStart, typeof(AppleTvJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + public AppleTvJoinMap(uint joinStart, Type type) : base(joinStart, type) { - [JoinName("UpArrow")] - public JoinDataComplete UpArrow = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "AppleTv Nav Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("DnArrow")] - public JoinDataComplete DnArrow = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "AppleTv Nav Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("LeftArrow")] - public JoinDataComplete LeftArrow = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "AppleTv Nav Left", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("RightArrow")] - public JoinDataComplete RightArrow = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "AppleTv Nav Right", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Menu")] - public JoinDataComplete Menu = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "AppleTv Menu", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Select")] - public JoinDataComplete Select = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, - new JoinMetadata { Description = "AppleTv Select", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("PlayPause")] - public JoinDataComplete PlayPause = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, - new JoinMetadata { Description = "AppleTv Play/Pause", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public AppleTvJoinMap(uint joinStart) - : base(joinStart, typeof(AppleTvJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - public AppleTvJoinMap(uint joinStart, Type type) : base(joinStart, type) - { - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/C2nRthsControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/C2nRthsControllerJoinMap.cs index dd141c8e9..17f8f4db7 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/C2nRthsControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/C2nRthsControllerJoinMap.cs @@ -1,45 +1,44 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class C2nRthsControllerJoinMap : JoinMapBaseAdvanced { - public class C2nRthsControllerJoinMap : JoinMapBaseAdvanced + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Temp Sensor Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("TemperatureFormat")] + public JoinDataComplete TemperatureFormat = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Temp Sensor Unit Format", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Temperature")] + public JoinDataComplete Temperature = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Temp Sensor Temperature Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("Humidity")] + public JoinDataComplete Humidity = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Temp Sensor Humidity Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Temp Sensor Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public C2nRthsControllerJoinMap(uint joinStart) + : this(joinStart, typeof(C2nRthsControllerJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected C2nRthsControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) { - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Temp Sensor Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("TemperatureFormat")] - public JoinDataComplete TemperatureFormat = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Temp Sensor Unit Format", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Temperature")] - public JoinDataComplete Temperature = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Temp Sensor Temperature Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("Humidity")] - public JoinDataComplete Humidity = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Temp Sensor Humidity Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("Name")] - public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Temp Sensor Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public C2nRthsControllerJoinMap(uint joinStart) - : this(joinStart, typeof(C2nRthsControllerJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected C2nRthsControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) - { - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/CameraControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/CameraControllerJoinMap.cs index 5c07b4a72..0cb011fa1 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/CameraControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/CameraControllerJoinMap.cs @@ -1,69 +1,68 @@ using System; -namespace PepperDash.Essentials.Core.Bridges -{ - /// - /// Join map for CameraBase devices - /// - public class CameraControllerJoinMap : JoinMapBaseAdvanced - { - [JoinName("TiltUp")] - public JoinDataComplete TiltUp = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, new JoinMetadata { Description = "Tilt Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("TiltDown")] - public JoinDataComplete TiltDown = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, new JoinMetadata { Description = "Tilt Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("PanLeft")] - public JoinDataComplete PanLeft = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, new JoinMetadata { Description = "Pan Left", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("PanRight")] - public JoinDataComplete PanRight = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, new JoinMetadata { Description = "Pan Right", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ZoomIn")] - public JoinDataComplete ZoomIn = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, new JoinMetadata { Description = "Zoom In", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ZoomOut")] - public JoinDataComplete ZoomOut = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, new JoinMetadata { Description = "Zoom Out", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); +namespace PepperDash.Essentials.Core.Bridges; - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 9, JoinSpan = 1 }, new JoinMetadata { Description = "Is Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("PowerOn")] - public JoinDataComplete PowerOn = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, new JoinMetadata { Description = "Power On", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("PowerOff")] - public JoinDataComplete PowerOff = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, new JoinMetadata { Description = "Power Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); +/// +/// Join map for CameraBase devices +/// +public class CameraControllerJoinMap : JoinMapBaseAdvanced +{ + [JoinName("TiltUp")] + public JoinDataComplete TiltUp = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, new JoinMetadata { Description = "Tilt Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("TiltDown")] + public JoinDataComplete TiltDown = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, new JoinMetadata { Description = "Tilt Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("PanLeft")] + public JoinDataComplete PanLeft = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, new JoinMetadata { Description = "Pan Left", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("PanRight")] + public JoinDataComplete PanRight = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, new JoinMetadata { Description = "Pan Right", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("ZoomIn")] + public JoinDataComplete ZoomIn = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, new JoinMetadata { Description = "Zoom In", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("ZoomOut")] + public JoinDataComplete ZoomOut = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, new JoinMetadata { Description = "Zoom Out", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("NumberOfPresets")] - public JoinDataComplete NumberOfPresets = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, new JoinMetadata { Description = "Tells Essentials the number of defined presets", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); - [JoinName("PresetRecallStart")] - public JoinDataComplete PresetRecallStart = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 20 }, new JoinMetadata { Description = "Preset Recall Start", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("PresetLabelStart")] - public JoinDataComplete PresetLabelStart = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 20 }, new JoinMetadata { Description = "Preset Label Start", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Serial }); - [JoinName("PresetSaveStart")] - public JoinDataComplete PresetSaveStart = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 20 }, new JoinMetadata { Description = "Preset Save Start", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 9, JoinSpan = 1 }, new JoinMetadata { Description = "Is Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("PowerOn")] + public JoinDataComplete PowerOn = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, new JoinMetadata { Description = "Power On", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("PowerOff")] + public JoinDataComplete PowerOff = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, new JoinMetadata { Description = "Power Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("CameraModeAuto")] - public JoinDataComplete CameraModeAuto = new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 }, new JoinMetadata { Description = "Camera Mode Auto", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("CameraModeManual")] - public JoinDataComplete CameraModeManual = new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1 }, new JoinMetadata { Description = "Camera Mode Manual", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("CameraModeOff")] - public JoinDataComplete CameraModeOff = new JoinDataComplete(new JoinData { JoinNumber = 53, JoinSpan = 1 }, new JoinMetadata { Description = "Camera Mode Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("NumberOfPresets")] + public JoinDataComplete NumberOfPresets = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, new JoinMetadata { Description = "Tells Essentials the number of defined presets", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("PresetRecallStart")] + public JoinDataComplete PresetRecallStart = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 20 }, new JoinMetadata { Description = "Preset Recall Start", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("PresetLabelStart")] + public JoinDataComplete PresetLabelStart = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 20 }, new JoinMetadata { Description = "Preset Label Start", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Serial }); + [JoinName("PresetSaveStart")] + public JoinDataComplete PresetSaveStart = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 20 }, new JoinMetadata { Description = "Preset Save Start", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("SupportsCameraModeAuto")] - public JoinDataComplete SupportsCameraModeAuto = new JoinDataComplete(new JoinData { JoinNumber = 55, JoinSpan = 1 }, new JoinMetadata { Description = "Supports Camera Mode Auto", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("SupportsCameraModeOff")] - public JoinDataComplete SupportsCameraModeOff = new JoinDataComplete(new JoinData { JoinNumber = 56, JoinSpan = 1 }, new JoinMetadata { Description = "Supports Camera Mode Off", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("SupportsPresets")] - public JoinDataComplete SupportsPresets = new JoinDataComplete(new JoinData { JoinNumber = 57, JoinSpan = 1 }, new JoinMetadata { Description = "Supports Presets", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("CameraModeAuto")] + public JoinDataComplete CameraModeAuto = new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 }, new JoinMetadata { Description = "Camera Mode Auto", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("CameraModeManual")] + public JoinDataComplete CameraModeManual = new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1 }, new JoinMetadata { Description = "Camera Mode Manual", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("CameraModeOff")] + public JoinDataComplete CameraModeOff = new JoinDataComplete(new JoinData { JoinNumber = 53, JoinSpan = 1 }, new JoinMetadata { Description = "Camera Mode Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public CameraControllerJoinMap(uint joinStart) - : this(joinStart, typeof(CameraControllerJoinMap)) - { - } + [JoinName("SupportsCameraModeAuto")] + public JoinDataComplete SupportsCameraModeAuto = new JoinDataComplete(new JoinData { JoinNumber = 55, JoinSpan = 1 }, new JoinMetadata { Description = "Supports Camera Mode Auto", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("SupportsCameraModeOff")] + public JoinDataComplete SupportsCameraModeOff = new JoinDataComplete(new JoinData { JoinNumber = 56, JoinSpan = 1 }, new JoinMetadata { Description = "Supports Camera Mode Off", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("SupportsPresets")] + public JoinDataComplete SupportsPresets = new JoinDataComplete(new JoinData { JoinNumber = 57, JoinSpan = 1 }, new JoinMetadata { Description = "Supports Presets", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected CameraControllerJoinMap(uint joinStart, Type type) : base(joinStart, type){} + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public CameraControllerJoinMap(uint joinStart) + : this(joinStart, typeof(CameraControllerJoinMap)) + { } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected CameraControllerJoinMap(uint joinStart, Type type) : base(joinStart, type){} } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/CenOdtOccupancySensorBaseJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/CenOdtOccupancySensorBaseJoinMap.cs index e306bf85f..b585916bb 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/CenOdtOccupancySensorBaseJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/CenOdtOccupancySensorBaseJoinMap.cs @@ -1,198 +1,196 @@ using System; -namespace PepperDash.Essentials.Core.Bridges -{ - public class CenOdtOccupancySensorBaseJoinMap : JoinMapBaseAdvanced - { - #region Digitals +namespace PepperDash.Essentials.Core.Bridges; - [JoinName("Online")] - public JoinDataComplete Online = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); +public class CenOdtOccupancySensorBaseJoinMap : JoinMapBaseAdvanced +{ + #region Digitals - [JoinName("ForceOccupied")] - public JoinDataComplete ForceOccupied = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Force Occupied", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Online")] + public JoinDataComplete Online = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ForceVacant")] - public JoinDataComplete ForceVacant = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Force Vacant", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("ForceOccupied")] + public JoinDataComplete ForceOccupied = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Force Occupied", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("EnableRawStates")] - public JoinDataComplete EnableRawStates = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Enable Raw States", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("ForceVacant")] + public JoinDataComplete ForceVacant = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Force Vacant", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("RoomOccupiedFeedback")] - public JoinDataComplete RoomOccupiedFeedback = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Room Occupied Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("EnableRawStates")] + public JoinDataComplete EnableRawStates = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Enable Raw States", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("GraceOccupancyDetectedFeedback")] - public JoinDataComplete GraceOccupancyDetectedFeedback = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Grace Occupancy Detected Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("RoomOccupiedFeedback")] + public JoinDataComplete RoomOccupiedFeedback = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Room Occupied Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("RoomVacantFeedback")] - public JoinDataComplete RoomVacantFeedback = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Room Vacant Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("GraceOccupancyDetectedFeedback")] + public JoinDataComplete GraceOccupancyDetectedFeedback = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Grace Occupancy Detected Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("RawOccupancyFeedback")] - public JoinDataComplete RawOccupancyFeedback = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "Raw Occupancy Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("RoomVacantFeedback")] + public JoinDataComplete RoomVacantFeedback = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Room Vacant Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("RawOccupancyPirFeedback")] - public JoinDataComplete RawOccupancyPirFeedback = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, - new JoinMetadata { Description = "Raw Occupancy Pir Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("RawOccupancyFeedback")] + public JoinDataComplete RawOccupancyFeedback = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "Raw Occupancy Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("RawOccupancyUsFeedback")] - public JoinDataComplete RawOccupancyUsFeedback = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, - new JoinMetadata { Description = "Raw Occupancy Us Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("RawOccupancyPirFeedback")] + public JoinDataComplete RawOccupancyPirFeedback = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata { Description = "Raw Occupancy Pir Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("IdentityModeOn")] - public JoinDataComplete IdentityMode = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, - new JoinMetadata { Description = "Enable Identity Mode", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("RawOccupancyUsFeedback")] + public JoinDataComplete RawOccupancyUsFeedback = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, + new JoinMetadata { Description = "Raw Occupancy Us Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("IdentityModeFeedback")] - public JoinDataComplete IdentityModeFeedback = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, - new JoinMetadata { Description = "Identity Mode Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("IdentityModeOn")] + public JoinDataComplete IdentityMode = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, + new JoinMetadata { Description = "Enable Identity Mode", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("EnableLedFlash")] - public JoinDataComplete EnableLedFlash = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata { Description = "Enable Led Flash", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("IdentityModeFeedback")] + public JoinDataComplete IdentityModeFeedback = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, + new JoinMetadata { Description = "Identity Mode Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DisableLedFlash")] - public JoinDataComplete DisableLedFlash = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata { Description = "Disable Led Flash", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("EnableLedFlash")] + public JoinDataComplete EnableLedFlash = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "Enable Led Flash", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("EnableShortTimeout")] - public JoinDataComplete EnableShortTimeout = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, - new JoinMetadata { Description = "Enable Short Timeout", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DisableLedFlash")] + public JoinDataComplete DisableLedFlash = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata { Description = "Disable Led Flash", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DisableShortTimeout")] - public JoinDataComplete DisableShortTimeout = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, - new JoinMetadata { Description = "Disable Short Timeout", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("EnableShortTimeout")] + public JoinDataComplete EnableShortTimeout = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, + new JoinMetadata { Description = "Enable Short Timeout", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("OrWhenVacated")] - public JoinDataComplete OrWhenVacated = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, - new JoinMetadata { Description = "Or When Vacated", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DisableShortTimeout")] + public JoinDataComplete DisableShortTimeout = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, + new JoinMetadata { Description = "Disable Short Timeout", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("AndWhenVacated")] - public JoinDataComplete AndWhenVacated = new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, - new JoinMetadata { Description = "AndWhenVacated", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("OrWhenVacated")] + public JoinDataComplete OrWhenVacated = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, + new JoinMetadata { Description = "Or When Vacated", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("EnableUsA")] - public JoinDataComplete EnableUsA = new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, - new JoinMetadata { Description = "Enable Us A", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("AndWhenVacated")] + public JoinDataComplete AndWhenVacated = new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, + new JoinMetadata { Description = "AndWhenVacated", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DisableUsA")] - public JoinDataComplete DisableUsA = new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, - new JoinMetadata { Description = "Disable Us A", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("EnableUsA")] + public JoinDataComplete EnableUsA = new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, + new JoinMetadata { Description = "Enable Us A", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("EnableUsB")] - public JoinDataComplete EnableUsB = new JoinDataComplete(new JoinData { JoinNumber = 19, JoinSpan = 1 }, - new JoinMetadata { Description = "Enable Us B", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DisableUsA")] + public JoinDataComplete DisableUsA = new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, + new JoinMetadata { Description = "Disable Us A", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DisableUsB")] - public JoinDataComplete DisableUsB = new JoinDataComplete(new JoinData { JoinNumber = 20, JoinSpan = 1 }, - new JoinMetadata { Description = "Disable Us B", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("EnableUsB")] + public JoinDataComplete EnableUsB = new JoinDataComplete(new JoinData { JoinNumber = 19, JoinSpan = 1 }, + new JoinMetadata { Description = "Enable Us B", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("EnablePir")] - public JoinDataComplete EnablePir = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, - new JoinMetadata { Description = "Enable Pir", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DisableUsB")] + public JoinDataComplete DisableUsB = new JoinDataComplete(new JoinData { JoinNumber = 20, JoinSpan = 1 }, + new JoinMetadata { Description = "Disable Us B", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DisablePir")] - public JoinDataComplete DisablePir = new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, - new JoinMetadata { Description = "Disable Pir", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("EnablePir")] + public JoinDataComplete EnablePir = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, + new JoinMetadata { Description = "Enable Pir", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("IncrementUsInOccupiedState")] - public JoinDataComplete IncrementUsInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 23, JoinSpan = 1 }, - new JoinMetadata { Description = "Increment Us In OccupiedState", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DisablePir")] + public JoinDataComplete DisablePir = new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, + new JoinMetadata { Description = "Disable Pir", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DecrementUsInOccupiedState")] - public JoinDataComplete DecrementUsInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, - new JoinMetadata { Description = "Dencrement Us In Occupied State", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("IncrementUsInOccupiedState")] + public JoinDataComplete IncrementUsInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 23, JoinSpan = 1 }, + new JoinMetadata { Description = "Increment Us In OccupiedState", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("IncrementUsInVacantState")] - public JoinDataComplete IncrementUsInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 25, JoinSpan = 1 }, - new JoinMetadata { Description = "Increment Us In VacantState", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DecrementUsInOccupiedState")] + public JoinDataComplete DecrementUsInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, + new JoinMetadata { Description = "Dencrement Us In Occupied State", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DecrementUsInVacantState")] - public JoinDataComplete DecrementUsInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 26, JoinSpan = 1 }, - new JoinMetadata { Description = "Decrement Us In VacantState", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("IncrementUsInVacantState")] + public JoinDataComplete IncrementUsInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 25, JoinSpan = 1 }, + new JoinMetadata { Description = "Increment Us In VacantState", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("IncrementPirInOccupiedState")] - public JoinDataComplete IncrementPirInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 27, JoinSpan = 1 }, - new JoinMetadata { Description = "Increment Pir In Occupied State", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DecrementUsInVacantState")] + public JoinDataComplete DecrementUsInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 26, JoinSpan = 1 }, + new JoinMetadata { Description = "Decrement Us In VacantState", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DecrementPirInOccupiedState")] - public JoinDataComplete DecrementPirInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 28, JoinSpan = 1 }, - new JoinMetadata { Description = "Decrement Pir In OccupiedState", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("IncrementPirInOccupiedState")] + public JoinDataComplete IncrementPirInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 27, JoinSpan = 1 }, + new JoinMetadata { Description = "Increment Pir In Occupied State", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("IncrementPirInVacantState")] - public JoinDataComplete IncrementPirInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 29, JoinSpan = 1 }, - new JoinMetadata { Description = "Increment Pir In Vacant State", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DecrementPirInOccupiedState")] + public JoinDataComplete DecrementPirInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 28, JoinSpan = 1 }, + new JoinMetadata { Description = "Decrement Pir In OccupiedState", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DecrementPirInVacantState")] - public JoinDataComplete DecrementPirInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 30, JoinSpan = 1 }, - new JoinMetadata { Description = "Decrement Pir In Vacant State", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("IncrementPirInVacantState")] + public JoinDataComplete IncrementPirInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 29, JoinSpan = 1 }, + new JoinMetadata { Description = "Increment Pir In Vacant State", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - #endregion + [JoinName("DecrementPirInVacantState")] + public JoinDataComplete DecrementPirInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 30, JoinSpan = 1 }, + new JoinMetadata { Description = "Decrement Pir In Vacant State", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - #region Analog + #endregion - [JoinName("Timeout")] - public JoinDataComplete Timeout = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Timeout", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + #region Analog - [JoinName("TimeoutLocalFeedback")] - public JoinDataComplete TimeoutLocalFeedback = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Timeout Local Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + [JoinName("Timeout")] + public JoinDataComplete Timeout = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Timeout", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - [JoinName("InternalPhotoSensorValue")] - public JoinDataComplete InternalPhotoSensorValue = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Internal PhotoSensor Value", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("TimeoutLocalFeedback")] + public JoinDataComplete TimeoutLocalFeedback = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Timeout Local Feedback", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - [JoinName("UsSensitivityInOccupiedState")] - public JoinDataComplete UsSensitivityInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "Us Sensitivity In Occupied State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + [JoinName("InternalPhotoSensorValue")] + public JoinDataComplete InternalPhotoSensorValue = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Internal PhotoSensor Value", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - [JoinName("UsSensitivityInVacantState")] - public JoinDataComplete UsSensitivityInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, - new JoinMetadata { Description = "Us Sensitivity In Vacant State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + [JoinName("UsSensitivityInOccupiedState")] + public JoinDataComplete UsSensitivityInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "Us Sensitivity In Occupied State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - [JoinName("PirSensitivityInOccupiedState")] - public JoinDataComplete PirSensitivityInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, - new JoinMetadata { Description = "Pir Sensitivity In Occupied State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + [JoinName("UsSensitivityInVacantState")] + public JoinDataComplete UsSensitivityInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata { Description = "Us Sensitivity In Vacant State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - [JoinName("PirSensitivityInVacantState")] - public JoinDataComplete PirSensitivityInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, - new JoinMetadata { Description = "Pir Sensitivity In Vacant State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + [JoinName("PirSensitivityInOccupiedState")] + public JoinDataComplete PirSensitivityInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, + new JoinMetadata { Description = "Pir Sensitivity In Occupied State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - #endregion + [JoinName("PirSensitivityInVacantState")] + public JoinDataComplete PirSensitivityInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, + new JoinMetadata { Description = "Pir Sensitivity In Vacant State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - #region Serial + #endregion - [JoinName("Name")] - public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + #region Serial - #endregion + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public CenOdtOccupancySensorBaseJoinMap(uint joinStart) - : this(joinStart, typeof(CenOdtOccupancySensorBaseJoinMap)) - { - } + #endregion - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected CenOdtOccupancySensorBaseJoinMap(uint joinStart, Type type) : base(joinStart, type) - { - } + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public CenOdtOccupancySensorBaseJoinMap(uint joinStart) + : this(joinStart, typeof(CenOdtOccupancySensorBaseJoinMap)) + { } + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected CenOdtOccupancySensorBaseJoinMap(uint joinStart, Type type) : base(joinStart, type) + { + } } diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DisplayControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DisplayControllerJoinMap.cs index 8e51c952c..2ab95b8e6 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DisplayControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DisplayControllerJoinMap.cs @@ -1,85 +1,84 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class DisplayControllerJoinMap : JoinMapBaseAdvanced { - public class DisplayControllerJoinMap : JoinMapBaseAdvanced + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("PowerOff")] + public JoinDataComplete PowerOff = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Power Off", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("PowerOn")] + public JoinDataComplete PowerOn = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Power On", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("IsTwoWayDisplay")] + public JoinDataComplete IsTwoWayDisplay = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Is Two Way Display", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VolumeUp")] + public JoinDataComplete VolumeUp = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "Volume Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VolumeLevel")] + public JoinDataComplete VolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "Volume Level", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("VolumeDown")] + public JoinDataComplete VolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata { Description = "Volume Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VolumeMute")] + public JoinDataComplete VolumeMute = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, + new JoinMetadata { Description = "Volume Mute", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VolumeMuteOn")] + public JoinDataComplete VolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, + new JoinMetadata { Description = "Volume Mute On", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VolumeMuteOff")] + public JoinDataComplete VolumeMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 9, JoinSpan = 1 }, + new JoinMetadata { Description = "Volume Mute Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("InputSelectOffset")] + public JoinDataComplete InputSelectOffset = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 10 }, + new JoinMetadata { Description = "Input Select", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("InputNamesOffset")] + public JoinDataComplete InputNamesOffset = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 10 }, + new JoinMetadata { Description = "Input Names Offset", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("InputSelect")] + public JoinDataComplete InputSelect = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "Input Select", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("ButtonVisibilityOffset")] + public JoinDataComplete ButtonVisibilityOffset = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 10 }, + new JoinMetadata { Description = "Button Visibility Offset", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.DigitalSerial }); + + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1 }, + new JoinMetadata { Description = "Is Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public DisplayControllerJoinMap(uint joinStart) + : this(joinStart, typeof(DisplayControllerJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected DisplayControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) { - [JoinName("Name")] - public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("PowerOff")] - public JoinDataComplete PowerOff = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Power Off", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("PowerOn")] - public JoinDataComplete PowerOn = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Power On", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("IsTwoWayDisplay")] - public JoinDataComplete IsTwoWayDisplay = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Is Two Way Display", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("VolumeUp")] - public JoinDataComplete VolumeUp = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "Volume Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("VolumeLevel")] - public JoinDataComplete VolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "Volume Level", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("VolumeDown")] - public JoinDataComplete VolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, - new JoinMetadata { Description = "Volume Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("VolumeMute")] - public JoinDataComplete VolumeMute = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, - new JoinMetadata { Description = "Volume Mute", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("VolumeMuteOn")] - public JoinDataComplete VolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, - new JoinMetadata { Description = "Volume Mute On", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("VolumeMuteOff")] - public JoinDataComplete VolumeMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 9, JoinSpan = 1 }, - new JoinMetadata { Description = "Volume Mute Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("InputSelectOffset")] - public JoinDataComplete InputSelectOffset = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 10 }, - new JoinMetadata { Description = "Input Select", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("InputNamesOffset")] - public JoinDataComplete InputNamesOffset = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 10 }, - new JoinMetadata { Description = "Input Names Offset", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("InputSelect")] - public JoinDataComplete InputSelect = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata { Description = "Input Select", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("ButtonVisibilityOffset")] - public JoinDataComplete ButtonVisibilityOffset = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 10 }, - new JoinMetadata { Description = "Button Visibility Offset", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.DigitalSerial }); - - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1 }, - new JoinMetadata { Description = "Is Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public DisplayControllerJoinMap(uint joinStart) - : this(joinStart, typeof(DisplayControllerJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected DisplayControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) - { - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmBladeChassisControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmBladeChassisControllerJoinMap.cs index 3a4c42559..3edd12229 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmBladeChassisControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmBladeChassisControllerJoinMap.cs @@ -1,74 +1,73 @@ using System; -namespace PepperDash.Essentials.Core.Bridges { - public class DmBladeChassisControllerJoinMap : JoinMapBaseAdvanced { - - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata { Description = "DM Blade Chassis Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("VideoSyncStatus")] - public JoinDataComplete VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 128 }, - new JoinMetadata { Description = "DM Blade Input Video Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("InputEndpointOnline")] - public JoinDataComplete InputEndpointOnline = new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 128 }, - new JoinMetadata { Description = "DM Blade Chassis Input Endpoint Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("OutputEndpointOnline")] - public JoinDataComplete OutputEndpointOnline = new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 128 }, - new JoinMetadata { Description = "DM Blade Chassis Output Endpoint Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("TxAdvancedIsPresent")] - public JoinDataComplete TxAdvancedIsPresent = new JoinDataComplete(new JoinData { JoinNumber = 1001, JoinSpan = 128 }, - new JoinMetadata { Description = "DM Blade Chassis Tx Advanced Is Present", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("OutputVideo")] - public JoinDataComplete OutputVideo = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 128 }, - new JoinMetadata { Description = "DM Blade Chassis Output Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("HdcpSupportState")] - public JoinDataComplete HdcpSupportState = new JoinDataComplete(new JoinData { JoinNumber = 1001, JoinSpan = 128 }, - new JoinMetadata { Description = "DM Blade Chassis Input HDCP Support State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("HdcpSupportCapability")] - public JoinDataComplete HdcpSupportCapability = new JoinDataComplete(new JoinData { JoinNumber = 1201, JoinSpan = 128 }, - new JoinMetadata { Description = "DM Blade Chassis Input HDCP Support Capability", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("InputNames")] - public JoinDataComplete InputNames = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 128 }, - new JoinMetadata { Description = "DM Blade Chassis Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("OutputNames")] - public JoinDataComplete OutputNames = new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 128 }, - new JoinMetadata { Description = "DM Blade Chassis Output Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("OutputCurrentVideoInputNames")] - public JoinDataComplete OutputCurrentVideoInputNames = new JoinDataComplete(new JoinData { JoinNumber = 2001, JoinSpan = 128 }, - new JoinMetadata { Description = "DM Blade Chassis Video Output Currently Routed Video Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("InputCurrentResolution")] - public JoinDataComplete InputCurrentResolution = new JoinDataComplete(new JoinData { JoinNumber = 2401, JoinSpan = 128 }, - new JoinMetadata { Description = "DM Blade Chassis Input Current Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public DmBladeChassisControllerJoinMap(uint joinStart) - : this(joinStart, typeof(DmBladeChassisControllerJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected DmBladeChassisControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) - { - } +namespace PepperDash.Essentials.Core.Bridges; +public class DmBladeChassisControllerJoinMap : JoinMapBaseAdvanced { + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "DM Blade Chassis Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VideoSyncStatus")] + public JoinDataComplete VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 128 }, + new JoinMetadata { Description = "DM Blade Input Video Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("InputEndpointOnline")] + public JoinDataComplete InputEndpointOnline = new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 128 }, + new JoinMetadata { Description = "DM Blade Chassis Input Endpoint Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutputEndpointOnline")] + public JoinDataComplete OutputEndpointOnline = new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 128 }, + new JoinMetadata { Description = "DM Blade Chassis Output Endpoint Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("TxAdvancedIsPresent")] + public JoinDataComplete TxAdvancedIsPresent = new JoinDataComplete(new JoinData { JoinNumber = 1001, JoinSpan = 128 }, + new JoinMetadata { Description = "DM Blade Chassis Tx Advanced Is Present", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutputVideo")] + public JoinDataComplete OutputVideo = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 128 }, + new JoinMetadata { Description = "DM Blade Chassis Output Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("HdcpSupportState")] + public JoinDataComplete HdcpSupportState = new JoinDataComplete(new JoinData { JoinNumber = 1001, JoinSpan = 128 }, + new JoinMetadata { Description = "DM Blade Chassis Input HDCP Support State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("HdcpSupportCapability")] + public JoinDataComplete HdcpSupportCapability = new JoinDataComplete(new JoinData { JoinNumber = 1201, JoinSpan = 128 }, + new JoinMetadata { Description = "DM Blade Chassis Input HDCP Support Capability", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("InputNames")] + public JoinDataComplete InputNames = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 128 }, + new JoinMetadata { Description = "DM Blade Chassis Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("OutputNames")] + public JoinDataComplete OutputNames = new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 128 }, + new JoinMetadata { Description = "DM Blade Chassis Output Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("OutputCurrentVideoInputNames")] + public JoinDataComplete OutputCurrentVideoInputNames = new JoinDataComplete(new JoinData { JoinNumber = 2001, JoinSpan = 128 }, + new JoinMetadata { Description = "DM Blade Chassis Video Output Currently Routed Video Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("InputCurrentResolution")] + public JoinDataComplete InputCurrentResolution = new JoinDataComplete(new JoinData { JoinNumber = 2401, JoinSpan = 128 }, + new JoinMetadata { Description = "DM Blade Chassis Input Current Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public DmBladeChassisControllerJoinMap(uint joinStart) + : this(joinStart, typeof(DmBladeChassisControllerJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected DmBladeChassisControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) + { } + } diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmChassisControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmChassisControllerJoinMap.cs index 539e8d29d..db3701b33 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmChassisControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmChassisControllerJoinMap.cs @@ -1,170 +1,169 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class DmChassisControllerJoinMap : JoinMapBaseAdvanced { - public class DmChassisControllerJoinMap : JoinMapBaseAdvanced - { - [JoinName("EnableAudioBreakaway")] - public JoinDataComplete EnableAudioBreakaway = new JoinDataComplete( - new JoinData {JoinNumber = 4, JoinSpan = 1}, - new JoinMetadata - { - Description = "DM Chassis enable audio breakaway routing", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); + [JoinName("EnableAudioBreakaway")] + public JoinDataComplete EnableAudioBreakaway = new JoinDataComplete( + new JoinData {JoinNumber = 4, JoinSpan = 1}, + new JoinMetadata + { + Description = "DM Chassis enable audio breakaway routing", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("EnableUsbBreakaway")] + public JoinDataComplete EnableUsbBreakaway = new JoinDataComplete( + new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata + { + Description = "DM Chassis enable USB breakaway routing", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); - [JoinName("EnableUsbBreakaway")] - public JoinDataComplete EnableUsbBreakaway = new JoinDataComplete( - new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata - { - Description = "DM Chassis enable USB breakaway routing", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "DM Chassis Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("Name")] - public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "DM Chassis Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("SystemId")] - public JoinDataComplete SystemId = new JoinDataComplete(new JoinData { JoinNumber = 10, JoinSpan = 1 }, - new JoinMetadata { Description = "DM Chassis SystemId Get/Set/Trigger/", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.DigitalAnalog }); - - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata { Description = "DM Chassis Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("VideoSyncStatus")] - public JoinDataComplete VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Input Video Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("InputEndpointOnline")] - public JoinDataComplete InputEndpointOnline = new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Input Endpoint Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("OutputEndpointOnline")] - public JoinDataComplete OutputEndpointOnline = new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Output Endpoint Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("TxAdvancedIsPresent")] - public JoinDataComplete TxAdvancedIsPresent = new JoinDataComplete(new JoinData { JoinNumber = 1001, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Tx Advanced Is Present", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("OutputDisabledByHdcp")] - public JoinDataComplete OutputDisabledByHdcp = new JoinDataComplete(new JoinData { JoinNumber = 1201, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Output Disabled by HDCP", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("OutputVideo")] - public JoinDataComplete OutputVideo = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Output Video Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("OutputAudio")] - public JoinDataComplete OutputAudio = new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Output Audio Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("OutputUsb")] - public JoinDataComplete OutputUsb = new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Output USB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("InputUsb")] - public JoinDataComplete InputUsb = new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Input Usb Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("HdcpSupportState")] - public JoinDataComplete HdcpSupportState = new JoinDataComplete(new JoinData { JoinNumber = 1001, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Input HDCP Support State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("HdcpSupportCapability")] - public JoinDataComplete HdcpSupportCapability = new JoinDataComplete(new JoinData { JoinNumber = 1201, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Input HDCP Support Capability", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("InputStreamCardState")] - public JoinDataComplete InputStreamCardState = new JoinDataComplete(new JoinData { JoinNumber = 1501, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Stream Input Start (1), Stop (2), Pause (3) with Feedback", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("OutputStreamCardState")] - public JoinDataComplete OutputStreamCardState = new JoinDataComplete(new JoinData { JoinNumber = 1601, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Stream Output Start (1), Stop (2), Pause (3) with Feedback", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("NoRouteName")] - public JoinDataComplete NoRouteName = new JoinDataComplete(new JoinData { JoinNumber = 100, JoinSpan = 1 }, - new JoinMetadata { Description = "DM Chassis Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("InputNames")] - public JoinDataComplete InputNames = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("OutputNames")] - public JoinDataComplete OutputNames = new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Output Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("InputVideoNames")] public JoinDataComplete InputVideoNames = - new JoinDataComplete(new JoinData {JoinNumber = 501, JoinSpan = 200}, - new JoinMetadata - { - Description = "DM Chassis Video Input Names", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("InputAudioNames")] - public JoinDataComplete InputAudioNames = - new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 200 }, - new JoinMetadata - { - Description = "DM Chassis Audio Input Names", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Serial - }); - [JoinName("OutputVideoNames")] - public JoinDataComplete OutputVideoNames = - new JoinDataComplete(new JoinData { JoinNumber = 901, JoinSpan = 200 }, - new JoinMetadata - { - Description = "DM Chassis Video Output Names", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Serial - }); - [JoinName("OutputAudioNames")] - public JoinDataComplete OutputAudioNames = - new JoinDataComplete(new JoinData { JoinNumber = 1101, JoinSpan = 200 }, + [JoinName("SystemId")] + public JoinDataComplete SystemId = new JoinDataComplete(new JoinData { JoinNumber = 10, JoinSpan = 1 }, + new JoinMetadata { Description = "DM Chassis SystemId Get/Set/Trigger/", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.DigitalAnalog }); + + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "DM Chassis Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VideoSyncStatus")] + public JoinDataComplete VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Input Video Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("InputEndpointOnline")] + public JoinDataComplete InputEndpointOnline = new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Input Endpoint Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutputEndpointOnline")] + public JoinDataComplete OutputEndpointOnline = new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Output Endpoint Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("TxAdvancedIsPresent")] + public JoinDataComplete TxAdvancedIsPresent = new JoinDataComplete(new JoinData { JoinNumber = 1001, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Tx Advanced Is Present", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutputDisabledByHdcp")] + public JoinDataComplete OutputDisabledByHdcp = new JoinDataComplete(new JoinData { JoinNumber = 1201, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Output Disabled by HDCP", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutputVideo")] + public JoinDataComplete OutputVideo = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Output Video Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("OutputAudio")] + public JoinDataComplete OutputAudio = new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Output Audio Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("OutputUsb")] + public JoinDataComplete OutputUsb = new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Output USB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("InputUsb")] + public JoinDataComplete InputUsb = new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Input Usb Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("HdcpSupportState")] + public JoinDataComplete HdcpSupportState = new JoinDataComplete(new JoinData { JoinNumber = 1001, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Input HDCP Support State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("HdcpSupportCapability")] + public JoinDataComplete HdcpSupportCapability = new JoinDataComplete(new JoinData { JoinNumber = 1201, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Input HDCP Support Capability", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("InputStreamCardState")] + public JoinDataComplete InputStreamCardState = new JoinDataComplete(new JoinData { JoinNumber = 1501, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Stream Input Start (1), Stop (2), Pause (3) with Feedback", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("OutputStreamCardState")] + public JoinDataComplete OutputStreamCardState = new JoinDataComplete(new JoinData { JoinNumber = 1601, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Stream Output Start (1), Stop (2), Pause (3) with Feedback", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("NoRouteName")] + public JoinDataComplete NoRouteName = new JoinDataComplete(new JoinData { JoinNumber = 100, JoinSpan = 1 }, + new JoinMetadata { Description = "DM Chassis Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("InputNames")] + public JoinDataComplete InputNames = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("OutputNames")] + public JoinDataComplete OutputNames = new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Output Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("InputVideoNames")] public JoinDataComplete InputVideoNames = + new JoinDataComplete(new JoinData {JoinNumber = 501, JoinSpan = 200}, new JoinMetadata { - Description = "DM Chassis Audio Output Names", + Description = "DM Chassis Video Input Names", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Serial }); - [JoinName("OutputCurrentVideoInputNames")] - public JoinDataComplete OutputCurrentVideoInputNames = new JoinDataComplete(new JoinData { JoinNumber = 2001, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Video Output Currently Routed Video Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("OutputCurrentAudioInputNames")] - public JoinDataComplete OutputCurrentAudioInputNames = new JoinDataComplete(new JoinData { JoinNumber = 2201, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Audio Output Currently Routed Video Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("InputCurrentResolution")] - public JoinDataComplete InputCurrentResolution = new JoinDataComplete(new JoinData { JoinNumber = 2401, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Input Current Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public DmChassisControllerJoinMap(uint joinStart) - : this(joinStart, typeof(DmChassisControllerJoinMap)) + [JoinName("InputAudioNames")] + public JoinDataComplete InputAudioNames = + new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 200 }, + new JoinMetadata { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected DmChassisControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) + Description = "DM Chassis Audio Input Names", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Serial + }); + [JoinName("OutputVideoNames")] + public JoinDataComplete OutputVideoNames = + new JoinDataComplete(new JoinData { JoinNumber = 901, JoinSpan = 200 }, + new JoinMetadata { - } + Description = "DM Chassis Video Output Names", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Serial + }); + [JoinName("OutputAudioNames")] + public JoinDataComplete OutputAudioNames = + new JoinDataComplete(new JoinData { JoinNumber = 1101, JoinSpan = 200 }, + new JoinMetadata + { + Description = "DM Chassis Audio Output Names", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("OutputCurrentVideoInputNames")] + public JoinDataComplete OutputCurrentVideoInputNames = new JoinDataComplete(new JoinData { JoinNumber = 2001, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Video Output Currently Routed Video Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("OutputCurrentAudioInputNames")] + public JoinDataComplete OutputCurrentAudioInputNames = new JoinDataComplete(new JoinData { JoinNumber = 2201, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Audio Output Currently Routed Video Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("InputCurrentResolution")] + public JoinDataComplete InputCurrentResolution = new JoinDataComplete(new JoinData { JoinNumber = 2401, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Input Current Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public DmChassisControllerJoinMap(uint joinStart) + : this(joinStart, typeof(DmChassisControllerJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected DmChassisControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) + { } } diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmRmcControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmRmcControllerJoinMap.cs index bdcc3a696..4ddb9ff41 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmRmcControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmRmcControllerJoinMap.cs @@ -1,92 +1,91 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class DmRmcControllerJoinMap : JoinMapBaseAdvanced { - public class DmRmcControllerJoinMap : JoinMapBaseAdvanced + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VideoMuteOn")] + public JoinDataComplete VideoMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC Mute Video", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VideoMuteOff")] + public JoinDataComplete VideoMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC UnMute Video", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VideoMuteToggle")] + public JoinDataComplete VideoMuteToggle = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC Mute Video Toggle", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("CurrentOutputResolution")] + public JoinDataComplete CurrentOutputResolution = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC Current Output Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("EdidManufacturer")] + public JoinDataComplete EdidManufacturer = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC EDID Manufacturer", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("EdidName")] + public JoinDataComplete EdidName = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC EDID Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("EdidPrefferedTiming")] + public JoinDataComplete EdidPrefferedTiming = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC EDID Preferred Timing", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("EdidSerialNumber")] + public JoinDataComplete EdidSerialNumber = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC EDID Serial Number", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("AudioVideoSource")] + public JoinDataComplete AudioVideoSource = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC Audio Video Source Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("HdcpSupportCapability")] + public JoinDataComplete HdcpSupportCapability = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC HDCP Support Capability", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("Port1HdcpState")] + public JoinDataComplete Port1HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC Port 1 (DM) HDCP State Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("Port2HdcpState")] + public JoinDataComplete Port2HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "DM TX Port 2 (HDMI) HDCP State Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("HdmiInputSync")] + public JoinDataComplete HdmiInputSync = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC HDMI Input Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("HdcpInputPortCount")] + public JoinDataComplete HdcpInputPortCount = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "Number of Input Ports that support HDCP", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public DmRmcControllerJoinMap(uint joinStart) + : this(joinStart, typeof(DmRmcControllerJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected DmRmcControllerJoinMap(uint joinStart, Type type) + : base(joinStart, type) { - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "DM RMC Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("VideoMuteOn")] - public JoinDataComplete VideoMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "DM RMC Mute Video", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("VideoMuteOff")] - public JoinDataComplete VideoMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "DM RMC UnMute Video", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("VideoMuteToggle")] - public JoinDataComplete VideoMuteToggle = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "DM RMC Mute Video Toggle", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("CurrentOutputResolution")] - public JoinDataComplete CurrentOutputResolution = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "DM RMC Current Output Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("EdidManufacturer")] - public JoinDataComplete EdidManufacturer = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "DM RMC EDID Manufacturer", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("EdidName")] - public JoinDataComplete EdidName = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "DM RMC EDID Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("EdidPrefferedTiming")] - public JoinDataComplete EdidPrefferedTiming = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "DM RMC EDID Preferred Timing", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("EdidSerialNumber")] - public JoinDataComplete EdidSerialNumber = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "DM RMC EDID Serial Number", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("Name")] - public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, - new JoinMetadata { Description = "DM RMC Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("AudioVideoSource")] - public JoinDataComplete AudioVideoSource = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "DM RMC Audio Video Source Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("HdcpSupportCapability")] - public JoinDataComplete HdcpSupportCapability = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "DM RMC HDCP Support Capability", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("Port1HdcpState")] - public JoinDataComplete Port1HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "DM RMC Port 1 (DM) HDCP State Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("Port2HdcpState")] - public JoinDataComplete Port2HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "DM TX Port 2 (HDMI) HDCP State Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("HdmiInputSync")] - public JoinDataComplete HdmiInputSync = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "DM RMC HDMI Input Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("HdcpInputPortCount")] - public JoinDataComplete HdcpInputPortCount = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "Number of Input Ports that support HDCP", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public DmRmcControllerJoinMap(uint joinStart) - : this(joinStart, typeof(DmRmcControllerJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected DmRmcControllerJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmTxControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmTxControllerJoinMap.cs index c6f8f89fb..8fb99f330 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmTxControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmTxControllerJoinMap.cs @@ -1,96 +1,95 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class DmTxControllerJoinMap : JoinMapBaseAdvanced { - public class DmTxControllerJoinMap : JoinMapBaseAdvanced + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "DM TX Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VideoSyncStatus")] + public JoinDataComplete VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "DM TX Video Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("FreeRunEnabled")] + public JoinDataComplete FreeRunEnabled = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "DM TX Enable Free Run Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Input1VideoSyncStatus")] + public JoinDataComplete Input1VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Input 1 Video Sync Status", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Input2VideoSyncStatus")] + public JoinDataComplete Input2VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "Input 2 Video Sync Status", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Input3VideoSyncStatus")] + public JoinDataComplete Input3VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata { Description = "Input 3 Video Sync Status", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("CurrentInputResolution")] + public JoinDataComplete CurrentInputResolution = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "DM TX Current Input Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "DM TX Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("VideoInput")] + public JoinDataComplete VideoInput = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "DM TX Video Input Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("AudioInput")] + public JoinDataComplete AudioInput = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "DM TX Audio Input Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("HdcpSupportCapability")] + public JoinDataComplete HdcpSupportCapability = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "DM TX HDCP Support Capability", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("Port1HdcpState")] + public JoinDataComplete Port1HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "DM TX Port 1 HDCP State Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("Port2HdcpState")] + public JoinDataComplete Port2HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "DM TX Port 2 HDCP State Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("VgaBrightness")] + public JoinDataComplete VgaBrightness = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata { Description = "DM TX VGA Brightness", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("VgaContrast")] + public JoinDataComplete VgaContrast = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, + new JoinMetadata { Description = "DM TX Online", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("Port3HdcpState")] + public JoinDataComplete Port3HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, + new JoinMetadata { Description = "DM TX Port 3 HDCP State Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("HdcpInputPortCount")] + public JoinDataComplete HdcpInputPortCount = new JoinDataComplete(new JoinData { JoinNumber = 9, JoinSpan = 1 }, + new JoinMetadata { Description = "Number of Input Ports that support HDCP", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public DmTxControllerJoinMap(uint joinStart) + : this(joinStart, typeof(DmTxControllerJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected DmTxControllerJoinMap(uint joinStart, Type type) + : base(joinStart, type) { - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "DM TX Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("VideoSyncStatus")] - public JoinDataComplete VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "DM TX Video Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("FreeRunEnabled")] - public JoinDataComplete FreeRunEnabled = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "DM TX Enable Free Run Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Input1VideoSyncStatus")] - public JoinDataComplete Input1VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Input 1 Video Sync Status", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Input2VideoSyncStatus")] - public JoinDataComplete Input2VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "Input 2 Video Sync Status", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Input3VideoSyncStatus")] - public JoinDataComplete Input3VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, - new JoinMetadata { Description = "Input 3 Video Sync Status", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("CurrentInputResolution")] - public JoinDataComplete CurrentInputResolution = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "DM TX Current Input Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("Name")] - public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "DM TX Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("VideoInput")] - public JoinDataComplete VideoInput = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "DM TX Video Input Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("AudioInput")] - public JoinDataComplete AudioInput = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "DM TX Audio Input Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("HdcpSupportCapability")] - public JoinDataComplete HdcpSupportCapability = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "DM TX HDCP Support Capability", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("Port1HdcpState")] - public JoinDataComplete Port1HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "DM TX Port 1 HDCP State Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("Port2HdcpState")] - public JoinDataComplete Port2HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "DM TX Port 2 HDCP State Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("VgaBrightness")] - public JoinDataComplete VgaBrightness = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, - new JoinMetadata { Description = "DM TX VGA Brightness", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("VgaContrast")] - public JoinDataComplete VgaContrast = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, - new JoinMetadata { Description = "DM TX Online", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("Port3HdcpState")] - public JoinDataComplete Port3HdcpState = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, - new JoinMetadata { Description = "DM TX Port 3 HDCP State Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("HdcpInputPortCount")] - public JoinDataComplete HdcpInputPortCount = new JoinDataComplete(new JoinData { JoinNumber = 9, JoinSpan = 1 }, - new JoinMetadata { Description = "Number of Input Ports that support HDCP", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public DmTxControllerJoinMap(uint joinStart) - : this(joinStart, typeof(DmTxControllerJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected DmTxControllerJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmpsAudioOutputControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmpsAudioOutputControllerJoinMap.cs index 11509acf4..9ad046912 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmpsAudioOutputControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmpsAudioOutputControllerJoinMap.cs @@ -1,174 +1,173 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class DmpsAudioOutputControllerJoinMap : JoinMapBaseAdvanced { - public class DmpsAudioOutputControllerJoinMap : JoinMapBaseAdvanced - { - [JoinName("MasterVolumeLevel")] - public JoinDataComplete MasterVolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Master Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("MasterVolumeLevel")] + public JoinDataComplete MasterVolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Master Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("MasterVolumeLevelScaled")] + public JoinDataComplete MasterVolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Master Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("MixerPresetRecall")] + public JoinDataComplete MixerPresetRecall = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Mixer Preset Recall Set", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("MixerEqPresetRecall")] + public JoinDataComplete MixerEqPresetRecall = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Mixer Eq Preset Recall Set", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("MasterVolumeMuteOn")] + public JoinDataComplete MasterVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Master Volume Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("MasterVolumeMuteOff")] + public JoinDataComplete MasterVolumeMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Master Volume Mute Off Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("MasterVolumeUp")] + public JoinDataComplete MasterVolumeUp = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Master Volume Level Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("MasterVolumeDown")] + public JoinDataComplete MasterVolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Master Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("MasterVolumeLevelScaledSend")] + public JoinDataComplete MasterVolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "Master Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("SourceVolumeLevel")] + public JoinDataComplete SourceVolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "Source Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("SourceVolumeLevelScaled")] + public JoinDataComplete SourceVolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata { Description = "Source Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("SourceVolumeMuteOn")] + public JoinDataComplete SourceVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "Source Volume Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("SourceVolumeMuteOff")] + public JoinDataComplete SourceVolumeMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata { Description = "Source Volume Mute Off Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("SourceVolumeUp")] + public JoinDataComplete SourceVolumeUp = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, + new JoinMetadata { Description = "Source Volume Level Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("MasterVolumeLevelScaled")] - public JoinDataComplete MasterVolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Master Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("SourceVolumeDown")] + public JoinDataComplete SourceVolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, + new JoinMetadata { Description = "Source Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("MixerPresetRecall")] - public JoinDataComplete MixerPresetRecall = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Mixer Preset Recall Set", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("SourceVolumeLevelScaledSend")] + public JoinDataComplete SourceVolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, + new JoinMetadata { Description = "Source Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("MixerEqPresetRecall")] - public JoinDataComplete MixerEqPresetRecall = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Mixer Eq Preset Recall Set", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("Codec1VolumeLevel")] + public JoinDataComplete Codec1VolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, + new JoinMetadata { Description = "Codec1 Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - [JoinName("MasterVolumeMuteOn")] - public JoinDataComplete MasterVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Master Volume Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Codec1VolumeLevelScaled")] + public JoinDataComplete Codec1VolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, + new JoinMetadata { Description = "Codec1 Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - [JoinName("MasterVolumeMuteOff")] - public JoinDataComplete MasterVolumeMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Master Volume Mute Off Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Codec1VolumeMuteOn")] + public JoinDataComplete Codec1VolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, + new JoinMetadata { Description = "Codec1 Volume Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("MasterVolumeUp")] - public JoinDataComplete MasterVolumeUp = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Master Volume Level Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Codec1VolumeMuteOff")] + public JoinDataComplete Codec1VolumeMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, + new JoinMetadata { Description = "Codec1 Volume Mute Off Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("MasterVolumeDown")] - public JoinDataComplete MasterVolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Master Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Codec1VolumeUp")] + public JoinDataComplete Codec1VolumeUp = new JoinDataComplete(new JoinData { JoinNumber = 23, JoinSpan = 1 }, + new JoinMetadata { Description = "Codec1 Volume Level Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("MasterVolumeLevelScaledSend")] - public JoinDataComplete MasterVolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "Master Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Codec1VolumeDown")] + public JoinDataComplete Codec1VolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, + new JoinMetadata { Description = "Codec1 Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("SourceVolumeLevel")] - public JoinDataComplete SourceVolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata { Description = "Source Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("Codec1VolumeLevelScaledSend")] + public JoinDataComplete Codec1VolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 25, JoinSpan = 1 }, + new JoinMetadata { Description = "Codec1 Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("SourceVolumeLevelScaled")] - public JoinDataComplete SourceVolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata { Description = "Source Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("Codec2VolumeLevel")] + public JoinDataComplete Codec2VolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, + new JoinMetadata { Description = "Codec2 Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - [JoinName("SourceVolumeMuteOn")] - public JoinDataComplete SourceVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata { Description = "Source Volume Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Codec2VolumeLevelScaled")] + public JoinDataComplete Codec2VolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 32, JoinSpan = 1 }, + new JoinMetadata { Description = "Codec2 Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - [JoinName("SourceVolumeMuteOff")] - public JoinDataComplete SourceVolumeMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata { Description = "Source Volume Mute Off Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Codec2VolumeMuteOn")] + public JoinDataComplete Codec2VolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, + new JoinMetadata { Description = "Codec2 Volume Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("SourceVolumeUp")] - public JoinDataComplete SourceVolumeUp = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, - new JoinMetadata { Description = "Source Volume Level Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("SourceVolumeDown")] - public JoinDataComplete SourceVolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, - new JoinMetadata { Description = "Source Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("SourceVolumeLevelScaledSend")] - public JoinDataComplete SourceVolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, - new JoinMetadata { Description = "Source Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Codec1VolumeLevel")] - public JoinDataComplete Codec1VolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, - new JoinMetadata { Description = "Codec1 Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("Codec1VolumeLevelScaled")] - public JoinDataComplete Codec1VolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, - new JoinMetadata { Description = "Codec1 Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("Codec1VolumeMuteOn")] - public JoinDataComplete Codec1VolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, - new JoinMetadata { Description = "Codec1 Volume Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Codec1VolumeMuteOff")] - public JoinDataComplete Codec1VolumeMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, - new JoinMetadata { Description = "Codec1 Volume Mute Off Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Codec1VolumeUp")] - public JoinDataComplete Codec1VolumeUp = new JoinDataComplete(new JoinData { JoinNumber = 23, JoinSpan = 1 }, - new JoinMetadata { Description = "Codec1 Volume Level Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Codec1VolumeDown")] - public JoinDataComplete Codec1VolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, - new JoinMetadata { Description = "Codec1 Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Codec1VolumeLevelScaledSend")] - public JoinDataComplete Codec1VolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 25, JoinSpan = 1 }, - new JoinMetadata { Description = "Codec1 Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Codec2VolumeLevel")] - public JoinDataComplete Codec2VolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, - new JoinMetadata { Description = "Codec2 Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("Codec2VolumeLevelScaled")] - public JoinDataComplete Codec2VolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 32, JoinSpan = 1 }, - new JoinMetadata { Description = "Codec2 Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("Codec2VolumeMuteOn")] - public JoinDataComplete Codec2VolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, - new JoinMetadata { Description = "Codec2 Volume Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Codec2VolumeMuteOff")] - public JoinDataComplete Codec2VolumeMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 32, JoinSpan = 1 }, - new JoinMetadata { Description = "Codec2 Volume Mute Off Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Codec2VolumeUp")] - public JoinDataComplete Codec2VolumeUp = new JoinDataComplete(new JoinData { JoinNumber = 33, JoinSpan = 1 }, - new JoinMetadata { Description = "Codec2 Volume Level Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Codec2VolumeDown")] - public JoinDataComplete Codec2VolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 34, JoinSpan = 1 }, - new JoinMetadata { Description = "Codec2 Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Codec2VolumeLevelScaledSend")] - public JoinDataComplete Codec2VolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 35, JoinSpan = 1 }, - new JoinMetadata { Description = "Codec2 Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("MicsMasterVolumeLevel")] - public JoinDataComplete MicsMasterVolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, - new JoinMetadata { Description = "MicsMaster Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("MicsMasterVolumeLevelScaled")] - public JoinDataComplete MicsMasterVolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 }, - new JoinMetadata { Description = "MicsMaster Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("MicsMasterVolumeMuteOn")] - public JoinDataComplete MicsMasterVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, - new JoinMetadata { Description = "MicsMaster Volume Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("MicsMasterVolumeMuteOff")] - public JoinDataComplete MicsMasterVolumeMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 }, - new JoinMetadata { Description = "MicsMaster Volume Mute Off Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("MicsMasterVolumeUp")] - public JoinDataComplete MicsMasterVolumeUp = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 1 }, - new JoinMetadata { Description = "MicsMaster Volume Level Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("MicsMasterVolumeDown")] - public JoinDataComplete MicsMasterVolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 44, JoinSpan = 1 }, - new JoinMetadata { Description = "MicsMaster Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("MicsMasterVolumeLevelScaledSend")] - public JoinDataComplete MicsMasterVolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 45, JoinSpan = 1 }, - new JoinMetadata { Description = "Mics Master Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public DmpsAudioOutputControllerJoinMap(uint joinStart) - : this(joinStart, typeof(DmpsAudioOutputControllerJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected DmpsAudioOutputControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) - { - } + [JoinName("Codec2VolumeMuteOff")] + public JoinDataComplete Codec2VolumeMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 32, JoinSpan = 1 }, + new JoinMetadata { Description = "Codec2 Volume Mute Off Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Codec2VolumeUp")] + public JoinDataComplete Codec2VolumeUp = new JoinDataComplete(new JoinData { JoinNumber = 33, JoinSpan = 1 }, + new JoinMetadata { Description = "Codec2 Volume Level Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Codec2VolumeDown")] + public JoinDataComplete Codec2VolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 34, JoinSpan = 1 }, + new JoinMetadata { Description = "Codec2 Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Codec2VolumeLevelScaledSend")] + public JoinDataComplete Codec2VolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 35, JoinSpan = 1 }, + new JoinMetadata { Description = "Codec2 Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("MicsMasterVolumeLevel")] + public JoinDataComplete MicsMasterVolumeLevel = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, + new JoinMetadata { Description = "MicsMaster Volume Signed dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("MicsMasterVolumeLevelScaled")] + public JoinDataComplete MicsMasterVolumeLevelScaled = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 }, + new JoinMetadata { Description = "MicsMaster Volume 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("MicsMasterVolumeMuteOn")] + public JoinDataComplete MicsMasterVolumeMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, + new JoinMetadata { Description = "MicsMaster Volume Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("MicsMasterVolumeMuteOff")] + public JoinDataComplete MicsMasterVolumeMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 }, + new JoinMetadata { Description = "MicsMaster Volume Mute Off Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("MicsMasterVolumeUp")] + public JoinDataComplete MicsMasterVolumeUp = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 1 }, + new JoinMetadata { Description = "MicsMaster Volume Level Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("MicsMasterVolumeDown")] + public JoinDataComplete MicsMasterVolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 44, JoinSpan = 1 }, + new JoinMetadata { Description = "MicsMaster Volume Level Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("MicsMasterVolumeLevelScaledSend")] + public JoinDataComplete MicsMasterVolumeLevelScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 45, JoinSpan = 1 }, + new JoinMetadata { Description = "Mics Master Volume Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public DmpsAudioOutputControllerJoinMap(uint joinStart) + : this(joinStart, typeof(DmpsAudioOutputControllerJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected DmpsAudioOutputControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) + { } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmpsMicrophoneControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmpsMicrophoneControllerJoinMap.cs index 6922c569d..90efc9648 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmpsMicrophoneControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmpsMicrophoneControllerJoinMap.cs @@ -1,50 +1,49 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class DmpsMicrophoneControllerJoinMap : JoinMapBaseAdvanced { - public class DmpsMicrophoneControllerJoinMap : JoinMapBaseAdvanced + [JoinName("MicGain")] + public JoinDataComplete MicGain = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Mic Gain dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("MicGainScaled")] + public JoinDataComplete MicGainScaled = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Mic Gain 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("MicMuteOn")] + public JoinDataComplete MicMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Mic Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("MicMuteOff")] + public JoinDataComplete MicMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Mic Mute Off Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("MicGainScaledSend")] + public JoinDataComplete MicGainScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Mic Gain Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("MicName")] + public JoinDataComplete MicName = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Mic Name Get", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public DmpsMicrophoneControllerJoinMap(uint joinStart) + : this(joinStart, typeof(DmpsMicrophoneControllerJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected DmpsMicrophoneControllerJoinMap(uint joinStart, Type type) + : base(joinStart, type) { - [JoinName("MicGain")] - public JoinDataComplete MicGain = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Mic Gain dB Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("MicGainScaled")] - public JoinDataComplete MicGainScaled = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Mic Gain 16bit Scaled Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("MicMuteOn")] - public JoinDataComplete MicMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Mic Mute On Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("MicMuteOff")] - public JoinDataComplete MicMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Mic Mute Off Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("MicGainScaledSend")] - public JoinDataComplete MicGainScaledSend = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Mic Gain Scaled Send Enable/Disable", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("MicName")] - public JoinDataComplete MicName = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Mic Name Get", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public DmpsMicrophoneControllerJoinMap(uint joinStart) - : this(joinStart, typeof(DmpsMicrophoneControllerJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected DmpsMicrophoneControllerJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmpsRoutingControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmpsRoutingControllerJoinMap.cs index a0d8d7b88..e39e38c61 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmpsRoutingControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/DmpsRoutingControllerJoinMap.cs @@ -1,123 +1,122 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class DmpsRoutingControllerJoinMap : JoinMapBaseAdvanced { - public class DmpsRoutingControllerJoinMap : JoinMapBaseAdvanced - { - [JoinName("EnableRouting")] - public JoinDataComplete EnableRouting = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "DMPS Enable Audio and Video Routing", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("SystemPowerOn")] - public JoinDataComplete SystemPowerOn = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata { Description = "DMPS System Power On Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("SystemPowerOff")] - public JoinDataComplete SystemPowerOff = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, - new JoinMetadata { Description = "DMPS System Power Off Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("FrontPanelLockOn")] - public JoinDataComplete FrontPanelLockOn = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, - new JoinMetadata { Description = "DMPS Front Panel Lock On Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("FrontPanelLockOff")] - public JoinDataComplete FrontPanelLockOff = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, - new JoinMetadata { Description = "DMPS Front Panel Lock Off Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("VideoSyncStatus")] - public JoinDataComplete VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Input Video Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("InputEndpointOnline")] - public JoinDataComplete InputEndpointOnline = new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Input Endpoint Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("OutputEndpointOnline")] - public JoinDataComplete OutputEndpointOnline = new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Output Endpoint Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("OutputVideo")] - public JoinDataComplete OutputVideo = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Output Video Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("OutputAudio")] - public JoinDataComplete OutputAudio = new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Output Audio Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("InputNames")] - public JoinDataComplete InputNames = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("OutputNames")] - public JoinDataComplete OutputNames = new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Output Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("InputVideoNames")] - public JoinDataComplete InputVideoNames = - new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 32 }, - new JoinMetadata - { - Description = "Video Input Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("InputAudioNames")] - public JoinDataComplete InputAudioNames = - new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 32 }, - new JoinMetadata - { - Description = "Audio Input Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - [JoinName("OutputVideoNames")] - public JoinDataComplete OutputVideoNames = - new JoinDataComplete(new JoinData { JoinNumber = 901, JoinSpan = 32 }, - new JoinMetadata - { - Description = "Video Output Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - [JoinName("OutputAudioNames")] - public JoinDataComplete OutputAudioNames = - new JoinDataComplete(new JoinData { JoinNumber = 1101, JoinSpan = 32 }, - new JoinMetadata - { - Description = "Audio Output Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("OutputCurrentVideoInputNames")] - public JoinDataComplete OutputCurrentVideoInputNames = new JoinDataComplete(new JoinData { JoinNumber = 2001, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Video Output Currently Routed Video Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("OutputCurrentAudioInputNames")] - public JoinDataComplete OutputCurrentAudioInputNames = new JoinDataComplete(new JoinData { JoinNumber = 2201, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Audio Output Currently Routed Video Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("InputCurrentResolution")] - public JoinDataComplete InputCurrentResolution = new JoinDataComplete(new JoinData { JoinNumber = 2401, JoinSpan = 32 }, - new JoinMetadata { Description = "DM Chassis Input Current Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public DmpsRoutingControllerJoinMap(uint joinStart) - : this(joinStart, typeof(DmpsRoutingControllerJoinMap)) + [JoinName("EnableRouting")] + public JoinDataComplete EnableRouting = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "DMPS Enable Audio and Video Routing", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("SystemPowerOn")] + public JoinDataComplete SystemPowerOn = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata { Description = "DMPS System Power On Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("SystemPowerOff")] + public JoinDataComplete SystemPowerOff = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, + new JoinMetadata { Description = "DMPS System Power Off Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("FrontPanelLockOn")] + public JoinDataComplete FrontPanelLockOn = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, + new JoinMetadata { Description = "DMPS Front Panel Lock On Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("FrontPanelLockOff")] + public JoinDataComplete FrontPanelLockOff = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, + new JoinMetadata { Description = "DMPS Front Panel Lock Off Get/Set", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VideoSyncStatus")] + public JoinDataComplete VideoSyncStatus = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Input Video Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("InputEndpointOnline")] + public JoinDataComplete InputEndpointOnline = new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Input Endpoint Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutputEndpointOnline")] + public JoinDataComplete OutputEndpointOnline = new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Output Endpoint Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutputVideo")] + public JoinDataComplete OutputVideo = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Output Video Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("OutputAudio")] + public JoinDataComplete OutputAudio = new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Output Audio Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("InputNames")] + public JoinDataComplete InputNames = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("OutputNames")] + public JoinDataComplete OutputNames = new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Output Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("InputVideoNames")] + public JoinDataComplete InputVideoNames = + new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 32 }, + new JoinMetadata + { + Description = "Video Input Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("InputAudioNames")] + public JoinDataComplete InputAudioNames = + new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 32 }, + new JoinMetadata + { + Description = "Audio Input Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + [JoinName("OutputVideoNames")] + public JoinDataComplete OutputVideoNames = + new JoinDataComplete(new JoinData { JoinNumber = 901, JoinSpan = 32 }, + new JoinMetadata { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected DmpsRoutingControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) + Description = "Video Output Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + [JoinName("OutputAudioNames")] + public JoinDataComplete OutputAudioNames = + new JoinDataComplete(new JoinData { JoinNumber = 1101, JoinSpan = 32 }, + new JoinMetadata { - } + Description = "Audio Output Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("OutputCurrentVideoInputNames")] + public JoinDataComplete OutputCurrentVideoInputNames = new JoinDataComplete(new JoinData { JoinNumber = 2001, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Video Output Currently Routed Video Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("OutputCurrentAudioInputNames")] + public JoinDataComplete OutputCurrentAudioInputNames = new JoinDataComplete(new JoinData { JoinNumber = 2201, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Audio Output Currently Routed Video Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("InputCurrentResolution")] + public JoinDataComplete InputCurrentResolution = new JoinDataComplete(new JoinData { JoinNumber = 2401, JoinSpan = 32 }, + new JoinMetadata { Description = "DM Chassis Input Current Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public DmpsRoutingControllerJoinMap(uint joinStart) + : this(joinStart, typeof(DmpsRoutingControllerJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected DmpsRoutingControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) + { } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GenericIrControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GenericIrControllerJoinMap.cs index 388e6ac13..50cb4b7dd 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GenericIrControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GenericIrControllerJoinMap.cs @@ -1,7 +1,7 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core.Bridges.JoinMaps -{ +namespace PepperDash.Essentials.Core.Bridges.JoinMaps; + public sealed class GenericIrControllerJoinMap : JoinMapBaseAdvanced { [JoinName("PLAY")] @@ -823,5 +823,4 @@ public GenericIrControllerJoinMap(uint joinStart) : base(joinStart, typeof(GenericIrControllerJoinMap)) { } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GenericLightingJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GenericLightingJoinMap.cs index 2a3015f11..179b4124d 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GenericLightingJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GenericLightingJoinMap.cs @@ -1,49 +1,48 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class GenericLightingJoinMap : JoinMapBaseAdvanced { - public class GenericLightingJoinMap : JoinMapBaseAdvanced + + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Lighting Controller Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("SelectScene")] + public JoinDataComplete SelectScene = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Lighting Controller Select Scene By Index", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("SelectSceneDirect")] + public JoinDataComplete SelectSceneDirect = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 10 }, + new JoinMetadata { Description = "Lighting Controller Select Scene", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.DigitalSerial }); + + [JoinName("ButtonVisibility")] + public JoinDataComplete ButtonVisibility = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 10 }, + new JoinMetadata { Description = "Lighting Controller Button Visibility", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("IntegrationIdSet")] + public JoinDataComplete IntegrationIdSet = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Lighting Controller Set Integration Id", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Serial }); + + + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public GenericLightingJoinMap(uint joinStart) + : this(joinStart, typeof(GenericLightingJoinMap)) { + } - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Lighting Controller Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("SelectScene")] - public JoinDataComplete SelectScene = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Lighting Controller Select Scene By Index", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("SelectSceneDirect")] - public JoinDataComplete SelectSceneDirect = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 10 }, - new JoinMetadata { Description = "Lighting Controller Select Scene", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.DigitalSerial }); - - [JoinName("ButtonVisibility")] - public JoinDataComplete ButtonVisibility = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 10 }, - new JoinMetadata { Description = "Lighting Controller Button Visibility", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("IntegrationIdSet")] - public JoinDataComplete IntegrationIdSet = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Lighting Controller Set Integration Id", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Serial }); - - - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public GenericLightingJoinMap(uint joinStart) - : this(joinStart, typeof(GenericLightingJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected GenericLightingJoinMap(uint joinStart, Type type) : base(joinStart, type) - { - } + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected GenericLightingJoinMap(uint joinStart, Type type) : base(joinStart, type) + { } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GenericRelayControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GenericRelayControllerJoinMap.cs index 688977679..03aaf041f 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GenericRelayControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GenericRelayControllerJoinMap.cs @@ -1,31 +1,30 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class GenericRelayControllerJoinMap : JoinMapBaseAdvanced { - public class GenericRelayControllerJoinMap : JoinMapBaseAdvanced - { - [JoinName("Relay")] - public JoinDataComplete Relay = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Device Relay State Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Relay")] + public JoinDataComplete Relay = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Device Relay State Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public GenericRelayControllerJoinMap(uint joinStart) - : this(joinStart, typeof(GenericRelayControllerJoinMap)) - { - } + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public GenericRelayControllerJoinMap(uint joinStart) + : this(joinStart, typeof(GenericRelayControllerJoinMap)) + { + } - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected GenericRelayControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) - { - - } + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected GenericRelayControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) + { + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GlsOccupancySensorBaseJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GlsOccupancySensorBaseJoinMap.cs index ded7343f6..228cb4f07 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GlsOccupancySensorBaseJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GlsOccupancySensorBaseJoinMap.cs @@ -1,184 +1,184 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class GlsOccupancySensorBaseJoinMap : JoinMapBaseAdvanced { - public class GlsOccupancySensorBaseJoinMap : JoinMapBaseAdvanced - { - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Is Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Is Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("ForceOccupied")] + public JoinDataComplete ForceOccupied = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Set to Occupied", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("ForceVacant")] + public JoinDataComplete ForceVacant = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Set to Vacant", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("EnableRawStates")] + public JoinDataComplete EnableRawStates = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Enable Raw", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("RoomOccupiedFeedback")] + public JoinDataComplete RoomOccupiedFeedback = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Room Is Occupied", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("GraceOccupancyDetectedFeedback")] + public JoinDataComplete GraceOccupancyDetectedFeedback = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Grace Occupancy Detected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("RoomVacantFeedback")] + public JoinDataComplete RoomVacantFeedback = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Room Is Vacant", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("RawOccupancyFeedback")] + public JoinDataComplete RawOccupancyFeedback = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Raw Occupancy Detected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("RawOccupancyPirFeedback")] + public JoinDataComplete RawOccupancyPirFeedback = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Raw PIR Occupancy Detected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("RawOccupancyUsFeedback")] + public JoinDataComplete RawOccupancyUsFeedback = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Raw US Occupancy Detected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("EnableLedFlash")] + public JoinDataComplete EnableLedFlash = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Enable LED Flash", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("DisableLedFlash")] + public JoinDataComplete DisableLedFlash = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Disable LED Flash", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("EnableShortTimeout")] + public JoinDataComplete EnableShortTimeout = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Enable Short Timeout", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("DisableShortTimeout")] + public JoinDataComplete DisableShortTimeout = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Disable Short Timeout", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OrWhenVacated")] + public JoinDataComplete OrWhenVacated = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Set To Vacant when Either Sensor is Vacant", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ForceOccupied")] - public JoinDataComplete ForceOccupied = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Set to Occupied", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("AndWhenVacated")] + public JoinDataComplete AndWhenVacated = new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Set To Vacant when Both Sensors are Vacant", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ForceVacant")] - public JoinDataComplete ForceVacant = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Set to Vacant", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("EnableUsA")] + public JoinDataComplete EnableUsA = new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Enable Ultrasonic Sensor A", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("EnableRawStates")] - public JoinDataComplete EnableRawStates = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Enable Raw", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DisableUsA")] + public JoinDataComplete DisableUsA = new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Disable Ultrasonic Sensor A", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("RoomOccupiedFeedback")] - public JoinDataComplete RoomOccupiedFeedback = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Room Is Occupied", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("EnableUsB")] + public JoinDataComplete EnableUsB = new JoinDataComplete(new JoinData { JoinNumber = 19, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Enable Ultrasonic Sensor B", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("GraceOccupancyDetectedFeedback")] - public JoinDataComplete GraceOccupancyDetectedFeedback = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Grace Occupancy Detected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DisableUsB")] + public JoinDataComplete DisableUsB = new JoinDataComplete(new JoinData { JoinNumber = 20, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Disable Ultrasonic Sensor B", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("RoomVacantFeedback")] - public JoinDataComplete RoomVacantFeedback = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Room Is Vacant", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("EnablePir")] + public JoinDataComplete EnablePir = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Enable IR Sensor", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("RawOccupancyFeedback")] - public JoinDataComplete RawOccupancyFeedback = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Raw Occupancy Detected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DisablePir")] + public JoinDataComplete DisablePir = new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Disable IR Sensor", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("RawOccupancyPirFeedback")] - public JoinDataComplete RawOccupancyPirFeedback = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Raw PIR Occupancy Detected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("IncrementUsInOccupiedState")] + public JoinDataComplete IncrementUsInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 23, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Increment US Occupied State Sensitivity", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("RawOccupancyUsFeedback")] - public JoinDataComplete RawOccupancyUsFeedback = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Raw US Occupancy Detected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DecrementUsInOccupiedState")] + public JoinDataComplete DecrementUsInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Decrement US Occupied State Sensitivity", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("EnableLedFlash")] - public JoinDataComplete EnableLedFlash = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Enable LED Flash", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("IncrementUsInVacantState")] + public JoinDataComplete IncrementUsInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 25, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Increment US Vacant State Sensitivity", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DisableLedFlash")] - public JoinDataComplete DisableLedFlash = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Disable LED Flash", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DecrementUsInVacantState")] + public JoinDataComplete DecrementUsInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 26, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Decrement US Vacant State Sensitivity", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("EnableShortTimeout")] - public JoinDataComplete EnableShortTimeout = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Enable Short Timeout", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("IncrementPirInOccupiedState")] + public JoinDataComplete IncrementPirInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 27, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Increment IR Occupied State Sensitivity", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DisableShortTimeout")] - public JoinDataComplete DisableShortTimeout = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Disable Short Timeout", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DecrementPirInOccupiedState")] + public JoinDataComplete DecrementPirInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 28, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Decrement IR Occupied State Sensitivity", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("OrWhenVacated")] - public JoinDataComplete OrWhenVacated = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Set To Vacant when Either Sensor is Vacant", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("IncrementPirInVacantState")] + public JoinDataComplete IncrementPirInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 29, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Increment IR Vacant State Sensitivity", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("AndWhenVacated")] - public JoinDataComplete AndWhenVacated = new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Set To Vacant when Both Sensors are Vacant", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("EnableUsA")] - public JoinDataComplete EnableUsA = new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Enable Ultrasonic Sensor A", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("DisableUsA")] - public JoinDataComplete DisableUsA = new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Disable Ultrasonic Sensor A", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("EnableUsB")] - public JoinDataComplete EnableUsB = new JoinDataComplete(new JoinData { JoinNumber = 19, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Enable Ultrasonic Sensor B", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("DisableUsB")] - public JoinDataComplete DisableUsB = new JoinDataComplete(new JoinData { JoinNumber = 20, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Disable Ultrasonic Sensor B", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("EnablePir")] - public JoinDataComplete EnablePir = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Enable IR Sensor", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("DisablePir")] - public JoinDataComplete DisablePir = new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Disable IR Sensor", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("IncrementUsInOccupiedState")] - public JoinDataComplete IncrementUsInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 23, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Increment US Occupied State Sensitivity", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("DecrementUsInOccupiedState")] - public JoinDataComplete DecrementUsInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Decrement US Occupied State Sensitivity", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("IncrementUsInVacantState")] - public JoinDataComplete IncrementUsInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 25, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Increment US Vacant State Sensitivity", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("DecrementUsInVacantState")] - public JoinDataComplete DecrementUsInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 26, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Decrement US Vacant State Sensitivity", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("IncrementPirInOccupiedState")] - public JoinDataComplete IncrementPirInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 27, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Increment IR Occupied State Sensitivity", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("DecrementPirInOccupiedState")] - public JoinDataComplete DecrementPirInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 28, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Decrement IR Occupied State Sensitivity", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("IncrementPirInVacantState")] - public JoinDataComplete IncrementPirInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 29, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Increment IR Vacant State Sensitivity", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("DecrementPirInVacantState")] - public JoinDataComplete DecrementPirInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 30, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Decrement IR Vacant State Sensitivity", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Timeout")] - public JoinDataComplete Timeout = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Timeout Value", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("TimeoutLocalFeedback")] - public JoinDataComplete TimeoutLocalFeedback = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Local Timeout Value", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("InternalPhotoSensorValue")] - public JoinDataComplete InternalPhotoSensorValue = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Internal PhotoSensor Value", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("ExternalPhotoSensorValue")] - public JoinDataComplete ExternalPhotoSensorValue = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor External PhotoSensor Value", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("UsSensitivityInOccupiedState")] - public JoinDataComplete UsSensitivityInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Ultrasonic Sensitivity in Occupied State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("UsSensitivityInVacantState")] - public JoinDataComplete UsSensitivityInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Ultrasonic Sensitivity in Vacant State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("PirSensitivityInOccupiedState")] - public JoinDataComplete PirSensitivityInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor PIR Sensitivity in Occupied State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("PirSensitivityInVacantState")] - public JoinDataComplete PirSensitivityInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor PIR Sensitivity in Vacant State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("Name")] - public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Occ Sensor Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public GlsOccupancySensorBaseJoinMap(uint joinStart) - : this(joinStart, typeof(GlsOccupancySensorBaseJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected GlsOccupancySensorBaseJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } + [JoinName("DecrementPirInVacantState")] + public JoinDataComplete DecrementPirInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 30, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Decrement IR Vacant State Sensitivity", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Timeout")] + public JoinDataComplete Timeout = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Timeout Value", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("TimeoutLocalFeedback")] + public JoinDataComplete TimeoutLocalFeedback = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Local Timeout Value", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("InternalPhotoSensorValue")] + public JoinDataComplete InternalPhotoSensorValue = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Internal PhotoSensor Value", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("ExternalPhotoSensorValue")] + public JoinDataComplete ExternalPhotoSensorValue = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor External PhotoSensor Value", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("UsSensitivityInOccupiedState")] + public JoinDataComplete UsSensitivityInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Ultrasonic Sensitivity in Occupied State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("UsSensitivityInVacantState")] + public JoinDataComplete UsSensitivityInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Ultrasonic Sensitivity in Vacant State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("PirSensitivityInOccupiedState")] + public JoinDataComplete PirSensitivityInOccupiedState = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor PIR Sensitivity in Occupied State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("PirSensitivityInVacantState")] + public JoinDataComplete PirSensitivityInVacantState = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor PIR Sensitivity in Vacant State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Occ Sensor Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public GlsOccupancySensorBaseJoinMap(uint joinStart) + : this(joinStart, typeof(GlsOccupancySensorBaseJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected GlsOccupancySensorBaseJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { } -} + +} + diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GlsPartitionSensorJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GlsPartitionSensorJoinMap.cs index cb0f07b2a..7515c8c28 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GlsPartitionSensorJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/GlsPartitionSensorJoinMap.cs @@ -1,157 +1,156 @@ using System; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core.Bridges.JoinMaps +namespace PepperDash.Essentials.Core.Bridges.JoinMaps; + +public class GlsPartitionSensorJoinMap : JoinMapBaseAdvanced { - public class GlsPartitionSensorJoinMap : JoinMapBaseAdvanced + + #region Digital + + [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("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 + }); + + #endregion + + #region Analog + + [JoinName("Sensitivity")] + public JoinDataComplete Sensitivity = new JoinDataComplete( + new JoinData + { + JoinNumber = 2, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Sensor Sensitivity", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + #endregion + + + #region Serial + + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Sensor Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + #endregion + + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public GlsPartitionSensorJoinMap(uint joinStart) + : this(joinStart, typeof(GlsPartitionSensorJoinMap)) + { + + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected GlsPartitionSensorJoinMap(uint joinStart, Type type) + : base(joinStart, type) { - #region Digital - - [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("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 - }); - - #endregion - - #region Analog - - [JoinName("Sensitivity")] - public JoinDataComplete Sensitivity = new JoinDataComplete( - new JoinData - { - JoinNumber = 2, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Sensor Sensitivity", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - #endregion - - - #region Serial - - [JoinName("Name")] - public JoinDataComplete Name = new JoinDataComplete( - new JoinData - { - JoinNumber = 1, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Sensor Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - #endregion - - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public GlsPartitionSensorJoinMap(uint joinStart) - : this(joinStart, typeof(GlsPartitionSensorJoinMap)) - { - - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected GlsPartitionSensorJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - - } } } diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/HdMdNxM4kEControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/HdMdNxM4kEControllerJoinMap.cs index e69946ea5..43ed25c9d 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/HdMdNxM4kEControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/HdMdNxM4kEControllerJoinMap.cs @@ -1,66 +1,65 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class HdMdNxM4kEControllerJoinMap : JoinMapBaseAdvanced { - public class HdMdNxM4kEControllerJoinMap : JoinMapBaseAdvanced - { - [JoinName("Name")] - public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Device Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Device Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("EnableAutoRoute")] - public JoinDataComplete EnableAutoRoute = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Enable Automatic Routing on 4x1 Switchers", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("EnableAutoRoute")] + public JoinDataComplete EnableAutoRoute = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Enable Automatic Routing on 4x1 Switchers", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("InputName")] - public JoinDataComplete InputName = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 8 }, - new JoinMetadata { Description = "Device Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("InputName")] + public JoinDataComplete InputName = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 8 }, + new JoinMetadata { Description = "Device Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("InputSync")] - public JoinDataComplete InputSync = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 8 }, - new JoinMetadata { Description = "Device Input Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("InputSync")] + public JoinDataComplete InputSync = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 8 }, + new JoinMetadata { Description = "Device Input Sync", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("OutputName")] - public JoinDataComplete OutputName = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 2 }, - new JoinMetadata { Description = "Device Output Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("OutputName")] + public JoinDataComplete OutputName = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 2 }, + new JoinMetadata { Description = "Device Output Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("OutputRoute")] - public JoinDataComplete OutputRoute = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 2 }, - new JoinMetadata { Description = "Device Output Route Set/Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("OutputRoute")] + public JoinDataComplete OutputRoute = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 2 }, + new JoinMetadata { Description = "Device Output Route Set/Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - [JoinName("OutputRoutedName")] - public JoinDataComplete OutputRoutedName = new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 2 }, - new JoinMetadata { Description = "Device Output Route Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("OutputRoutedName")] + public JoinDataComplete OutputRoutedName = new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 2 }, + new JoinMetadata { Description = "Device Output Route Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("EnableInputHdcp")] - public JoinDataComplete EnableInputHdcp = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 8 }, - new JoinMetadata { Description = "Device Enable Input Hdcp", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("EnableInputHdcp")] + public JoinDataComplete EnableInputHdcp = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 8 }, + new JoinMetadata { Description = "Device Enable Input Hdcp", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DisableInputHdcp")] - public JoinDataComplete DisableInputHdcp = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 8 }, - new JoinMetadata { Description = "Device Disnable Input Hdcp", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DisableInputHdcp")] + public JoinDataComplete DisableInputHdcp = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 8 }, + new JoinMetadata { Description = "Device Disnable Input Hdcp", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 30, JoinSpan = 1 }, - new JoinMetadata { Description = "Device Onlne", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 30, JoinSpan = 1 }, + new JoinMetadata { Description = "Device Onlne", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public HdMdNxM4kEControllerJoinMap(uint joinStart) - : this(joinStart, typeof(HdMdNxM4kEControllerJoinMap)) - { - } + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public HdMdNxM4kEControllerJoinMap(uint joinStart) + : this(joinStart, typeof(HdMdNxM4kEControllerJoinMap)) + { + } - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected HdMdNxM4kEControllerJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected HdMdNxM4kEControllerJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/HdMdxxxCEControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/HdMdxxxCEControllerJoinMap.cs index 0936f75de..32bc56517 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/HdMdxxxCEControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/HdMdxxxCEControllerJoinMap.cs @@ -1,76 +1,75 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class HdMdxxxCEControllerJoinMap : JoinMapBaseAdvanced { - public class HdMdxxxCEControllerJoinMap : JoinMapBaseAdvanced + + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Device Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("RemoteEndDetected")] + public JoinDataComplete RemoteEndDetected = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Device Remote End Detected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("AutoRouteOn")] + public JoinDataComplete AutoRouteOn = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Device Auto Route On", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("AutoRouteOff")] + public JoinDataComplete AutoRouteOff = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Device Auto Route Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("PriorityRoutingOn")] + public JoinDataComplete PriorityRoutingOn = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "Device Priority Routing On", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("PriorityRoutingOff")] + public JoinDataComplete PriorityRoutingOff = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata { Description = "Device Priority Routing Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("InputOnScreenDisplayEnabled")] + public JoinDataComplete InputOnScreenDisplayEnabled = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, + new JoinMetadata { Description = "Device Input OSD Enabled", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("InputOnScreenDisplayDisabled")] + public JoinDataComplete InputOnScreenDisplayDisabled = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, + new JoinMetadata { Description = "Device Input OSD Disabled", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("SyncDetected")] + public JoinDataComplete SyncDetected = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 5 }, + new JoinMetadata { Description = "Device Sync Detected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VideoSource")] + public JoinDataComplete VideoSource = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 5 }, + new JoinMetadata { Description = "Device Video Source Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("SourceCount")] + public JoinDataComplete SourceCount = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 5 }, + new JoinMetadata { Description = "Device Video Source Count", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("SourceNames")] + public JoinDataComplete SourceNames = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 5 }, + new JoinMetadata { Description = "Device Video Source Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public HdMdxxxCEControllerJoinMap(uint joinStart) + : this(joinStart, typeof(HdMdxxxCEControllerJoinMap)) { + } - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Device Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("RemoteEndDetected")] - public JoinDataComplete RemoteEndDetected = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Device Remote End Detected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("AutoRouteOn")] - public JoinDataComplete AutoRouteOn = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Device Auto Route On", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("AutoRouteOff")] - public JoinDataComplete AutoRouteOff = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Device Auto Route Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("PriorityRoutingOn")] - public JoinDataComplete PriorityRoutingOn = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "Device Priority Routing On", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("PriorityRoutingOff")] - public JoinDataComplete PriorityRoutingOff = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, - new JoinMetadata { Description = "Device Priority Routing Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("InputOnScreenDisplayEnabled")] - public JoinDataComplete InputOnScreenDisplayEnabled = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, - new JoinMetadata { Description = "Device Input OSD Enabled", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("InputOnScreenDisplayDisabled")] - public JoinDataComplete InputOnScreenDisplayDisabled = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, - new JoinMetadata { Description = "Device Input OSD Disabled", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("SyncDetected")] - public JoinDataComplete SyncDetected = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 5 }, - new JoinMetadata { Description = "Device Sync Detected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("VideoSource")] - public JoinDataComplete VideoSource = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 5 }, - new JoinMetadata { Description = "Device Video Source Set / Get", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("SourceCount")] - public JoinDataComplete SourceCount = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 5 }, - new JoinMetadata { Description = "Device Video Source Count", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("SourceNames")] - public JoinDataComplete SourceNames = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 5 }, - new JoinMetadata { Description = "Device Video Source Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public HdMdxxxCEControllerJoinMap(uint joinStart) - : this(joinStart, typeof(HdMdxxxCEControllerJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected HdMdxxxCEControllerJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected HdMdxxxCEControllerJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/HdPsXxxControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/HdPsXxxControllerJoinMap.cs index 04d75d418..56420b24c 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/HdPsXxxControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/HdPsXxxControllerJoinMap.cs @@ -1,8 +1,8 @@ using System; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core.Bridges -{ +namespace PepperDash.Essentials.Core.Bridges; + public class HdPsXxxControllerJoinMap : JoinMapBaseAdvanced { @@ -186,5 +186,4 @@ protected HdPsXxxControllerJoinMap(uint joinStart, Type type) : base(joinStart, type) { } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/Hrxxx0WirelessRemoteControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/Hrxxx0WirelessRemoteControllerJoinMap.cs index 23305b201..ca9ef3c61 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/Hrxxx0WirelessRemoteControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/Hrxxx0WirelessRemoteControllerJoinMap.cs @@ -1,246 +1,245 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class Hrxxx0WirelessRemoteControllerJoinMap : JoinMapBaseAdvanced { - public class Hrxxx0WirelessRemoteControllerJoinMap : JoinMapBaseAdvanced - { - [JoinName("Power")] - public JoinDataComplete Power = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Power", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Power")] + public JoinDataComplete Power = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Power", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Menu")] + public JoinDataComplete Menu = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Menu", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Guide")] + public JoinDataComplete Guide = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Guide", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Info")] + public JoinDataComplete Info = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Info", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VolumeUp")] + public JoinDataComplete VolumeUp = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "VolumeUp", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VolumeDown")] + public JoinDataComplete VolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata { Description = "VolumeDown", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("DialPadUp")] + public JoinDataComplete DialPadUp = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, + new JoinMetadata { Description = "DialPadUp", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("DialPadDown")] + public JoinDataComplete DialPadDown = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, + new JoinMetadata { Description = "DialPadDown", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("DialPadLeft")] + public JoinDataComplete DialPadLeft = new JoinDataComplete(new JoinData { JoinNumber = 9, JoinSpan = 1 }, + new JoinMetadata { Description = "DialPadLeft", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("DialPadRight")] + public JoinDataComplete DialPadRight = new JoinDataComplete(new JoinData { JoinNumber = 10, JoinSpan = 1 }, + new JoinMetadata { Description = "DialPadRight", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("DialPadSelect")] + public JoinDataComplete DialPadSelect = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "DialPadSelect", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("ChannelUp")] + public JoinDataComplete ChannelUp = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata { Description = "ChannelUp", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("ChannelDown")] + public JoinDataComplete ChannelDown = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, + new JoinMetadata { Description = "ChannelDown", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Mute")] + public JoinDataComplete Mute = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, + new JoinMetadata { Description = "Mute", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Menu")] - public JoinDataComplete Menu = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Menu", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Exit")] + public JoinDataComplete Exit = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, + new JoinMetadata { Description = "Exit", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Guide")] - public JoinDataComplete Guide = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Guide", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Last")] + public JoinDataComplete Last = new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, + new JoinMetadata { Description = "Last", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Info")] - public JoinDataComplete Info = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Info", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Play")] + public JoinDataComplete Play = new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, + new JoinMetadata { Description = "Play", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("VolumeUp")] - public JoinDataComplete VolumeUp = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "VolumeUp", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Pause")] + public JoinDataComplete Pause = new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, + new JoinMetadata { Description = "Pause", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("VolumeDown")] - public JoinDataComplete VolumeDown = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, - new JoinMetadata { Description = "VolumeDown", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Rewind")] + public JoinDataComplete Rewind = new JoinDataComplete(new JoinData { JoinNumber = 19, JoinSpan = 1 }, + new JoinMetadata { Description = "Rewind", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DialPadUp")] - public JoinDataComplete DialPadUp = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, - new JoinMetadata { Description = "DialPadUp", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("FastForward")] + public JoinDataComplete FastForward = new JoinDataComplete(new JoinData { JoinNumber = 20, JoinSpan = 1 }, + new JoinMetadata { Description = "FastForward", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DialPadDown")] - public JoinDataComplete DialPadDown = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, - new JoinMetadata { Description = "DialPadDown", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("PreviousTrack")] + public JoinDataComplete PreviousTrack = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, + new JoinMetadata { Description = "PreviousTrack", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DialPadLeft")] - public JoinDataComplete DialPadLeft = new JoinDataComplete(new JoinData { JoinNumber = 9, JoinSpan = 1 }, - new JoinMetadata { Description = "DialPadLeft", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("NextTrack")] + public JoinDataComplete NextTrack = new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, + new JoinMetadata { Description = "NextTrack", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DialPadRight")] - public JoinDataComplete DialPadRight = new JoinDataComplete(new JoinData { JoinNumber = 10, JoinSpan = 1 }, - new JoinMetadata { Description = "DialPadRight", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Stop")] + public JoinDataComplete Stop = new JoinDataComplete(new JoinData { JoinNumber = 23, JoinSpan = 1 }, + new JoinMetadata { Description = "Stop", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("DialPadSelect")] - public JoinDataComplete DialPadSelect = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata { Description = "DialPadSelect", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Record")] + public JoinDataComplete Record = new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, + new JoinMetadata { Description = "Record", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ChannelUp")] - public JoinDataComplete ChannelUp = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata { Description = "ChannelUp", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Dvr")] + public JoinDataComplete Dvr = new JoinDataComplete(new JoinData { JoinNumber = 25, JoinSpan = 1 }, + new JoinMetadata { Description = "Dvr", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ChannelDown")] - public JoinDataComplete ChannelDown = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, - new JoinMetadata { Description = "ChannelDown", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Keypad1")] + public JoinDataComplete Keypad1 = new JoinDataComplete(new JoinData { JoinNumber = 26, JoinSpan = 1 }, + new JoinMetadata { Description = "Keypad1", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Mute")] - public JoinDataComplete Mute = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, - new JoinMetadata { Description = "Mute", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Keypad2Abc")] + public JoinDataComplete Keypad2 = new JoinDataComplete(new JoinData { JoinNumber = 27, JoinSpan = 1 }, + new JoinMetadata { Description = "Keypad2Abc", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Exit")] - public JoinDataComplete Exit = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, - new JoinMetadata { Description = "Exit", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Keypad3Def")] + public JoinDataComplete Keypad3Def = new JoinDataComplete(new JoinData { JoinNumber = 28, JoinSpan = 1 }, + new JoinMetadata { Description = "Keypad3Def", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Last")] - public JoinDataComplete Last = new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, - new JoinMetadata { Description = "Last", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Keypad4Ghi")] + public JoinDataComplete Keypad4Ghi = new JoinDataComplete(new JoinData { JoinNumber = 29, JoinSpan = 1 }, + new JoinMetadata { Description = "Keypad4Ghi", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Play")] - public JoinDataComplete Play = new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, - new JoinMetadata { Description = "Play", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Keypad5Jkl")] + public JoinDataComplete Keypad5Jkl = new JoinDataComplete(new JoinData { JoinNumber = 30, JoinSpan = 1 }, + new JoinMetadata { Description = "Keypad5Jkl", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Pause")] - public JoinDataComplete Pause = new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, - new JoinMetadata { Description = "Pause", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Keypad6Mno")] + public JoinDataComplete Keypad6Mno = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, + new JoinMetadata { Description = "Keypad6Mno", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Rewind")] - public JoinDataComplete Rewind = new JoinDataComplete(new JoinData { JoinNumber = 19, JoinSpan = 1 }, - new JoinMetadata { Description = "Rewind", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Keypad7Pqrs")] + public JoinDataComplete Keypad7Pqrs = new JoinDataComplete(new JoinData { JoinNumber = 32, JoinSpan = 1 }, + new JoinMetadata { Description = "Keypad7Pqrs", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("FastForward")] - public JoinDataComplete FastForward = new JoinDataComplete(new JoinData { JoinNumber = 20, JoinSpan = 1 }, - new JoinMetadata { Description = "FastForward", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Keypad8Tuv")] + public JoinDataComplete Keypad8Tuv = new JoinDataComplete(new JoinData { JoinNumber = 33, JoinSpan = 1 }, + new JoinMetadata { Description = "Keypad8Tuv", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("PreviousTrack")] - public JoinDataComplete PreviousTrack = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, - new JoinMetadata { Description = "PreviousTrack", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Keypad9Wxyz")] + public JoinDataComplete Keypad9Wxyz = new JoinDataComplete(new JoinData { JoinNumber = 34, JoinSpan = 1 }, + new JoinMetadata { Description = "Keypad9Wxyz", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("NextTrack")] - public JoinDataComplete NextTrack = new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, - new JoinMetadata { Description = "NextTrack", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Keypad0")] + public JoinDataComplete Keypad0 = new JoinDataComplete(new JoinData { JoinNumber = 35, JoinSpan = 1 }, + new JoinMetadata { Description = "Keypad0", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Stop")] - public JoinDataComplete Stop = new JoinDataComplete(new JoinData { JoinNumber = 23, JoinSpan = 1 }, - new JoinMetadata { Description = "Stop", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Clear")] + public JoinDataComplete Clear = new JoinDataComplete(new JoinData { JoinNumber = 36, JoinSpan = 1 }, + new JoinMetadata { Description = "Clear", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Record")] - public JoinDataComplete Record = new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, - new JoinMetadata { Description = "Record", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Enter")] + public JoinDataComplete Enter = new JoinDataComplete(new JoinData { JoinNumber = 37, JoinSpan = 1 }, + new JoinMetadata { Description = "Enter", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Dvr")] - public JoinDataComplete Dvr = new JoinDataComplete(new JoinData { JoinNumber = 25, JoinSpan = 1 }, - new JoinMetadata { Description = "Dvr", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Red")] + public JoinDataComplete Red = new JoinDataComplete(new JoinData { JoinNumber = 38, JoinSpan = 1 }, + new JoinMetadata { Description = "Red", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Keypad1")] - public JoinDataComplete Keypad1 = new JoinDataComplete(new JoinData { JoinNumber = 26, JoinSpan = 1 }, - new JoinMetadata { Description = "Keypad1", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Green")] + public JoinDataComplete Green = new JoinDataComplete(new JoinData { JoinNumber = 39, JoinSpan = 1 }, + new JoinMetadata { Description = "Green", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Keypad2Abc")] - public JoinDataComplete Keypad2 = new JoinDataComplete(new JoinData { JoinNumber = 27, JoinSpan = 1 }, - new JoinMetadata { Description = "Keypad2Abc", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Yellow")] + public JoinDataComplete Yellow = new JoinDataComplete(new JoinData { JoinNumber = 40, JoinSpan = 1 }, + new JoinMetadata { Description = "Yellow", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Keypad3Def")] - public JoinDataComplete Keypad3Def = new JoinDataComplete(new JoinData { JoinNumber = 28, JoinSpan = 1 }, - new JoinMetadata { Description = "Keypad3Def", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Blue")] + public JoinDataComplete Blue = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, + new JoinMetadata { Description = "Blue", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Keypad4Ghi")] - public JoinDataComplete Keypad4Ghi = new JoinDataComplete(new JoinData { JoinNumber = 29, JoinSpan = 1 }, - new JoinMetadata { Description = "Keypad4Ghi", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Custom1")] + public JoinDataComplete Custom1 = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 }, + new JoinMetadata { Description = "Custom1", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Keypad5Jkl")] - public JoinDataComplete Keypad5Jkl = new JoinDataComplete(new JoinData { JoinNumber = 30, JoinSpan = 1 }, - new JoinMetadata { Description = "Keypad5Jkl", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Custom2")] + public JoinDataComplete Custom2 = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 1 }, + new JoinMetadata { Description = "Custom2", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Keypad6Mno")] - public JoinDataComplete Keypad6Mno = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, - new JoinMetadata { Description = "Keypad6Mno", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Custom3")] + public JoinDataComplete Custom3 = new JoinDataComplete(new JoinData { JoinNumber = 44, JoinSpan = 1 }, + new JoinMetadata { Description = "Custom3", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Keypad7Pqrs")] - public JoinDataComplete Keypad7Pqrs = new JoinDataComplete(new JoinData { JoinNumber = 32, JoinSpan = 1 }, - new JoinMetadata { Description = "Keypad7Pqrs", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Keypad8Tuv")] - public JoinDataComplete Keypad8Tuv = new JoinDataComplete(new JoinData { JoinNumber = 33, JoinSpan = 1 }, - new JoinMetadata { Description = "Keypad8Tuv", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Keypad9Wxyz")] - public JoinDataComplete Keypad9Wxyz = new JoinDataComplete(new JoinData { JoinNumber = 34, JoinSpan = 1 }, - new JoinMetadata { Description = "Keypad9Wxyz", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Keypad0")] - public JoinDataComplete Keypad0 = new JoinDataComplete(new JoinData { JoinNumber = 35, JoinSpan = 1 }, - new JoinMetadata { Description = "Keypad0", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Clear")] - public JoinDataComplete Clear = new JoinDataComplete(new JoinData { JoinNumber = 36, JoinSpan = 1 }, - new JoinMetadata { Description = "Clear", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Enter")] - public JoinDataComplete Enter = new JoinDataComplete(new JoinData { JoinNumber = 37, JoinSpan = 1 }, - new JoinMetadata { Description = "Enter", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Red")] - public JoinDataComplete Red = new JoinDataComplete(new JoinData { JoinNumber = 38, JoinSpan = 1 }, - new JoinMetadata { Description = "Red", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Green")] - public JoinDataComplete Green = new JoinDataComplete(new JoinData { JoinNumber = 39, JoinSpan = 1 }, - new JoinMetadata { Description = "Green", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Yellow")] - public JoinDataComplete Yellow = new JoinDataComplete(new JoinData { JoinNumber = 40, JoinSpan = 1 }, - new JoinMetadata { Description = "Yellow", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Blue")] - public JoinDataComplete Blue = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, - new JoinMetadata { Description = "Blue", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Custom1")] - public JoinDataComplete Custom1 = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 }, - new JoinMetadata { Description = "Custom1", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Custom2")] - public JoinDataComplete Custom2 = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 1 }, - new JoinMetadata { Description = "Custom2", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Custom3")] - public JoinDataComplete Custom3 = new JoinDataComplete(new JoinData { JoinNumber = 44, JoinSpan = 1 }, - new JoinMetadata { Description = "Custom3", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Custom4")] - public JoinDataComplete Custom4 = new JoinDataComplete(new JoinData { JoinNumber = 45, JoinSpan = 1 }, - new JoinMetadata { Description = "Custom4", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Custom5")] - public JoinDataComplete Custom5 = new JoinDataComplete(new JoinData { JoinNumber = 46, JoinSpan = 1 }, - new JoinMetadata { Description = "Custom5", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Custom6")] - public JoinDataComplete Custom6 = new JoinDataComplete(new JoinData { JoinNumber = 47, JoinSpan = 1 }, - new JoinMetadata { Description = "Custom6", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Custom7")] - public JoinDataComplete Custom7 = new JoinDataComplete(new JoinData { JoinNumber = 48, JoinSpan = 1 }, - new JoinMetadata { Description = "Custom7", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Custom8")] - public JoinDataComplete Custom8 = new JoinDataComplete(new JoinData { JoinNumber = 49, JoinSpan = 1 }, - new JoinMetadata { Description = "Custom8", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Custom9")] - public JoinDataComplete Custom9 = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1 }, - new JoinMetadata { Description = "Custom9", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Fav")] - public JoinDataComplete Fav = new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 }, - new JoinMetadata { Description = "Fav", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Home")] - public JoinDataComplete Home = new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1 }, - new JoinMetadata { Description = "Home", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("BatteryLow")] - public JoinDataComplete BatteryLow = new JoinDataComplete(new JoinData { JoinNumber = 53, JoinSpan = 1 }, - new JoinMetadata { Description = "BatteryLow", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("BatteryCritical")] - public JoinDataComplete BatteryCritical = new JoinDataComplete(new JoinData { JoinNumber = 54, JoinSpan = 1 }, - new JoinMetadata { Description = "BatteryCritical", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("BatteryVoltage")] - public JoinDataComplete BatteryVoltage = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "BatteryVoltage", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public Hrxxx0WirelessRemoteControllerJoinMap(uint joinStart) - : this(joinStart, typeof(Hrxxx0WirelessRemoteControllerJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected Hrxxx0WirelessRemoteControllerJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } + [JoinName("Custom4")] + public JoinDataComplete Custom4 = new JoinDataComplete(new JoinData { JoinNumber = 45, JoinSpan = 1 }, + new JoinMetadata { Description = "Custom4", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Custom5")] + public JoinDataComplete Custom5 = new JoinDataComplete(new JoinData { JoinNumber = 46, JoinSpan = 1 }, + new JoinMetadata { Description = "Custom5", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Custom6")] + public JoinDataComplete Custom6 = new JoinDataComplete(new JoinData { JoinNumber = 47, JoinSpan = 1 }, + new JoinMetadata { Description = "Custom6", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Custom7")] + public JoinDataComplete Custom7 = new JoinDataComplete(new JoinData { JoinNumber = 48, JoinSpan = 1 }, + new JoinMetadata { Description = "Custom7", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Custom8")] + public JoinDataComplete Custom8 = new JoinDataComplete(new JoinData { JoinNumber = 49, JoinSpan = 1 }, + new JoinMetadata { Description = "Custom8", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Custom9")] + public JoinDataComplete Custom9 = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1 }, + new JoinMetadata { Description = "Custom9", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Fav")] + public JoinDataComplete Fav = new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 }, + new JoinMetadata { Description = "Fav", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Home")] + public JoinDataComplete Home = new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1 }, + new JoinMetadata { Description = "Home", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("BatteryLow")] + public JoinDataComplete BatteryLow = new JoinDataComplete(new JoinData { JoinNumber = 53, JoinSpan = 1 }, + new JoinMetadata { Description = "BatteryLow", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("BatteryCritical")] + public JoinDataComplete BatteryCritical = new JoinDataComplete(new JoinData { JoinNumber = 54, JoinSpan = 1 }, + new JoinMetadata { Description = "BatteryCritical", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("BatteryVoltage")] + public JoinDataComplete BatteryVoltage = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "BatteryVoltage", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public Hrxxx0WirelessRemoteControllerJoinMap(uint joinStart) + : this(joinStart, typeof(Hrxxx0WirelessRemoteControllerJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected Hrxxx0WirelessRemoteControllerJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IAnalogInputJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IAnalogInputJoinMap.cs index eaf70f3a0..80509ecc8 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IAnalogInputJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IAnalogInputJoinMap.cs @@ -1,34 +1,33 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class IAnalogInputJoinMap : JoinMapBaseAdvanced { - public class IAnalogInputJoinMap : JoinMapBaseAdvanced - { - [JoinName("InputValue")] - public JoinDataComplete InputValue = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Input Value", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - [JoinName("MinimumChange")] - public JoinDataComplete MinimumChange = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Minimum voltage change required to reflect a change", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + [JoinName("InputValue")] + public JoinDataComplete InputValue = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Input Value", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + [JoinName("MinimumChange")] + public JoinDataComplete MinimumChange = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Minimum voltage change required to reflect a change", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public IAnalogInputJoinMap(uint joinStart) - : this(joinStart, typeof(IAnalogInputJoinMap)) - { - } + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public IAnalogInputJoinMap(uint joinStart) + : this(joinStart, typeof(IAnalogInputJoinMap)) + { + } - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected IAnalogInputJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected IAnalogInputJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IBasicCommunicationJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IBasicCommunicationJoinMap.cs index 0d077284d..1db5b1fff 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IBasicCommunicationJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IBasicCommunicationJoinMap.cs @@ -1,50 +1,49 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class IBasicCommunicationJoinMap : JoinMapBaseAdvanced { - public class IBasicCommunicationJoinMap : JoinMapBaseAdvanced + [JoinName("TextReceived")] + public JoinDataComplete TextReceived = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Text Received From Remote Device", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("SendText")] + public JoinDataComplete SendText = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Text Sent To Remote Device", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("SetPortConfig")] + public JoinDataComplete SetPortConfig = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Set Port Config", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("Connect")] + public JoinDataComplete Connect = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Connect", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Connected")] + public JoinDataComplete Connected = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Connected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Status")] + public JoinDataComplete Status = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Status", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public IBasicCommunicationJoinMap(uint joinStart) + : this(joinStart, typeof(IBasicCommunicationJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected IBasicCommunicationJoinMap(uint joinStart, Type type) + : base(joinStart, type) { - [JoinName("TextReceived")] - public JoinDataComplete TextReceived = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Text Received From Remote Device", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("SendText")] - public JoinDataComplete SendText = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Text Sent To Remote Device", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("SetPortConfig")] - public JoinDataComplete SetPortConfig = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Set Port Config", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("Connect")] - public JoinDataComplete Connect = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Connect", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Connected")] - public JoinDataComplete Connected = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Connected", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Status")] - public JoinDataComplete Status = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Status", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public IBasicCommunicationJoinMap(uint joinStart) - : this(joinStart, typeof(IBasicCommunicationJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected IBasicCommunicationJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IDigitalInputJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IDigitalInputJoinMap.cs index aa31ac764..ceed325de 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IDigitalInputJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IDigitalInputJoinMap.cs @@ -1,31 +1,30 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class IDigitalInputJoinMap : JoinMapBaseAdvanced { - public class IDigitalInputJoinMap : JoinMapBaseAdvanced - { - [JoinName("InputState")] - public JoinDataComplete InputState = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Input State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("InputState")] + public JoinDataComplete InputState = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Input State", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public IDigitalInputJoinMap(uint joinStart) - : this(joinStart, typeof(IDigitalInputJoinMap)) - { - } + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public IDigitalInputJoinMap(uint joinStart) + : this(joinStart, typeof(IDigitalInputJoinMap)) + { + } - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected IDigitalInputJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected IDigitalInputJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IDigitalOutputJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IDigitalOutputJoinMap.cs index cbe623980..8abb2b74e 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IDigitalOutputJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IDigitalOutputJoinMap.cs @@ -1,31 +1,30 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class IDigitalOutputJoinMap : JoinMapBaseAdvanced { - public class IDigitalOutputJoinMap : JoinMapBaseAdvanced - { - [JoinName("OutputState")] - public JoinDataComplete OutputState = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Get / Set state of Digital Input", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("OutputState")] + public JoinDataComplete OutputState = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Get / Set state of Digital Input", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public IDigitalOutputJoinMap(uint joinStart) - : this(joinStart, typeof(IDigitalOutputJoinMap)) - { - } + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public IDigitalOutputJoinMap(uint joinStart) + : this(joinStart, typeof(IDigitalOutputJoinMap)) + { + } - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected IDigitalOutputJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected IDigitalOutputJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IRBlurayBaseJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IRBlurayBaseJoinMap.cs index 991489e9f..d63a1f523 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IRBlurayBaseJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/IRBlurayBaseJoinMap.cs @@ -4,219 +4,218 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +/// +/// Join map for IRBlurayBase devices +/// +public class IRBlurayBaseJoinMap : JoinMapBaseAdvanced { - /// - /// Join map for IRBlurayBase devices - /// - public class IRBlurayBaseJoinMap : JoinMapBaseAdvanced - { - [JoinName("PowerOn")] - public JoinDataComplete PowerOn = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Power On", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("PowerOn")] + public JoinDataComplete PowerOn = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Power On", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("PowerOff")] + public JoinDataComplete PowerOff = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Power Off", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("PowerToggle")] + public JoinDataComplete PowerToggle = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Power Toggle", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Up")] + public JoinDataComplete Up = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Nav Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Down")] + public JoinDataComplete Down = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "Nav Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Left")] + public JoinDataComplete Left = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata { Description = "Nav Left", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Right")] + public JoinDataComplete Right = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, + new JoinMetadata { Description = "Nav Right", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Select")] + public JoinDataComplete Select = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, + new JoinMetadata { Description = "Select", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Menu")] + public JoinDataComplete Menu = new JoinDataComplete(new JoinData { JoinNumber = 9, JoinSpan = 1 }, + new JoinMetadata { Description = "Menu", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Exit")] + public JoinDataComplete Exit = new JoinDataComplete(new JoinData { JoinNumber = 10, JoinSpan = 1 }, + new JoinMetadata { Description = "Exit", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Digit0")] + public JoinDataComplete Digit0 = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "Digit 0", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Digit1")] + public JoinDataComplete Digit1 = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata { Description = "Digit 1", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Digit2")] + public JoinDataComplete Digit2 = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, + new JoinMetadata { Description = "Digit 2", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Digit3")] + public JoinDataComplete Digit3 = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, + new JoinMetadata { Description = "Digit 3", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Digit4")] + public JoinDataComplete Digit4 = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, + new JoinMetadata { Description = "Digit 4", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("PowerOff")] - public JoinDataComplete PowerOff = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Power Off", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Digit5")] + public JoinDataComplete Digit5 = new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, + new JoinMetadata { Description = "Digit 5", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("PowerToggle")] - public JoinDataComplete PowerToggle = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Power Toggle", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Digit6")] + public JoinDataComplete Digit6 = new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, + new JoinMetadata { Description = "Digit 6", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Up")] - public JoinDataComplete Up = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Nav Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Digit7")] + public JoinDataComplete Digit7 = new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, + new JoinMetadata { Description = "Digit 7", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Down")] - public JoinDataComplete Down = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "Nav Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Digit8")] + public JoinDataComplete Digit8 = new JoinDataComplete(new JoinData { JoinNumber = 19, JoinSpan = 1 }, + new JoinMetadata { Description = "Digit 8", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Left")] - public JoinDataComplete Left = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, - new JoinMetadata { Description = "Nav Left", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Digit9")] + public JoinDataComplete Digit9 = new JoinDataComplete(new JoinData { JoinNumber = 20, JoinSpan = 1 }, + new JoinMetadata { Description = "Digit 9", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Right")] - public JoinDataComplete Right = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, - new JoinMetadata { Description = "Nav Right", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("KeypadClear")] + public JoinDataComplete KeypadClear = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, + new JoinMetadata { Description = "Keypad Clear", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Select")] - public JoinDataComplete Select = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, - new JoinMetadata { Description = "Select", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("KeypadEnter")] + public JoinDataComplete KeypadEnter = new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, + new JoinMetadata { Description = "Keypad Enter", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Menu")] - public JoinDataComplete Menu = new JoinDataComplete(new JoinData { JoinNumber = 9, JoinSpan = 1 }, - new JoinMetadata { Description = "Menu", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("ChannelUp")] + public JoinDataComplete ChannelUp = new JoinDataComplete(new JoinData { JoinNumber = 23, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Channel Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Exit")] - public JoinDataComplete Exit = new JoinDataComplete(new JoinData { JoinNumber = 10, JoinSpan = 1 }, - new JoinMetadata { Description = "Exit", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("ChannelDown")] + public JoinDataComplete ChannelDown = new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Channel Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit0")] - public JoinDataComplete Digit0 = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata { Description = "Digit 0", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("LastChannel")] + public JoinDataComplete LastChannel = new JoinDataComplete(new JoinData { JoinNumber = 25, JoinSpan = 1 }, + new JoinMetadata { Description = "Last Channel", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit1")] - public JoinDataComplete Digit1 = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata { Description = "Digit 1", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Guide")] + public JoinDataComplete Guide = new JoinDataComplete(new JoinData { JoinNumber = 26, JoinSpan = 1 }, + new JoinMetadata { Description = "Guide", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit2")] - public JoinDataComplete Digit2 = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, - new JoinMetadata { Description = "Digit 2", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Info")] + public JoinDataComplete Info = new JoinDataComplete(new JoinData { JoinNumber = 27, JoinSpan = 1 }, + new JoinMetadata { Description = "Info", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit3")] - public JoinDataComplete Digit3 = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, - new JoinMetadata { Description = "Digit 3", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Red")] + public JoinDataComplete Red = new JoinDataComplete(new JoinData { JoinNumber = 28, JoinSpan = 1 }, + new JoinMetadata { Description = "Red", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit4")] - public JoinDataComplete Digit4 = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, - new JoinMetadata { Description = "Digit 4", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Green")] + public JoinDataComplete Green = new JoinDataComplete(new JoinData { JoinNumber = 29, JoinSpan = 1 }, + new JoinMetadata { Description = "Green", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit5")] - public JoinDataComplete Digit5 = new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, - new JoinMetadata { Description = "Digit 5", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Yellow")] + public JoinDataComplete Yellow = new JoinDataComplete(new JoinData { JoinNumber = 30, JoinSpan = 1 }, + new JoinMetadata { Description = "Yellow", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit6")] - public JoinDataComplete Digit6 = new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, - new JoinMetadata { Description = "Digit 6", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Blue")] + public JoinDataComplete Blue = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, + new JoinMetadata { Description = "Blue", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit7")] - public JoinDataComplete Digit7 = new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, - new JoinMetadata { Description = "Digit 7", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit8")] - public JoinDataComplete Digit8 = new JoinDataComplete(new JoinData { JoinNumber = 19, JoinSpan = 1 }, - new JoinMetadata { Description = "Digit 8", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Play")] + public JoinDataComplete Play = new JoinDataComplete(new JoinData { JoinNumber = 33, JoinSpan = 1 }, + new JoinMetadata { Description = "Play", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit9")] - public JoinDataComplete Digit9 = new JoinDataComplete(new JoinData { JoinNumber = 20, JoinSpan = 1 }, - new JoinMetadata { Description = "Digit 9", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Pause")] + public JoinDataComplete Pause = new JoinDataComplete(new JoinData { JoinNumber = 34, JoinSpan = 1 }, + new JoinMetadata { Description = "Pause", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("KeypadClear")] - public JoinDataComplete KeypadClear = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, - new JoinMetadata { Description = "Keypad Clear", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Stop")] + public JoinDataComplete Stop = new JoinDataComplete(new JoinData { JoinNumber = 35, JoinSpan = 1 }, + new JoinMetadata { Description = "Stop", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("KeypadEnter")] - public JoinDataComplete KeypadEnter = new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, - new JoinMetadata { Description = "Keypad Enter", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("FFwd")] + public JoinDataComplete FFwd = new JoinDataComplete(new JoinData { JoinNumber = 36, JoinSpan = 1 }, + new JoinMetadata { Description = "FFwd", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ChannelUp")] - public JoinDataComplete ChannelUp = new JoinDataComplete(new JoinData { JoinNumber = 23, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Channel Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Rewind")] + public JoinDataComplete Rewind = new JoinDataComplete(new JoinData { JoinNumber = 37, JoinSpan = 1 }, + new JoinMetadata { Description = "Rewind", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ChannelDown")] - public JoinDataComplete ChannelDown = new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Channel Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("LastChannel")] - public JoinDataComplete LastChannel = new JoinDataComplete(new JoinData { JoinNumber = 25, JoinSpan = 1 }, - new JoinMetadata { Description = "Last Channel", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Guide")] - public JoinDataComplete Guide = new JoinDataComplete(new JoinData { JoinNumber = 26, JoinSpan = 1 }, - new JoinMetadata { Description = "Guide", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Info")] - public JoinDataComplete Info = new JoinDataComplete(new JoinData { JoinNumber = 27, JoinSpan = 1 }, - new JoinMetadata { Description = "Info", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Red")] - public JoinDataComplete Red = new JoinDataComplete(new JoinData { JoinNumber = 28, JoinSpan = 1 }, - new JoinMetadata { Description = "Red", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Green")] - public JoinDataComplete Green = new JoinDataComplete(new JoinData { JoinNumber = 29, JoinSpan = 1 }, - new JoinMetadata { Description = "Green", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Yellow")] - public JoinDataComplete Yellow = new JoinDataComplete(new JoinData { JoinNumber = 30, JoinSpan = 1 }, - new JoinMetadata { Description = "Yellow", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Blue")] - public JoinDataComplete Blue = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, - new JoinMetadata { Description = "Blue", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - - [JoinName("Play")] - public JoinDataComplete Play = new JoinDataComplete(new JoinData { JoinNumber = 33, JoinSpan = 1 }, - new JoinMetadata { Description = "Play", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Pause")] - public JoinDataComplete Pause = new JoinDataComplete(new JoinData { JoinNumber = 34, JoinSpan = 1 }, - new JoinMetadata { Description = "Pause", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Stop")] - public JoinDataComplete Stop = new JoinDataComplete(new JoinData { JoinNumber = 35, JoinSpan = 1 }, - new JoinMetadata { Description = "Stop", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("FFwd")] - public JoinDataComplete FFwd = new JoinDataComplete(new JoinData { JoinNumber = 36, JoinSpan = 1 }, - new JoinMetadata { Description = "FFwd", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Rewind")] - public JoinDataComplete Rewind = new JoinDataComplete(new JoinData { JoinNumber = 37, JoinSpan = 1 }, - new JoinMetadata { Description = "Rewind", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("ChapPlus")] - public JoinDataComplete ChapPlus = new JoinDataComplete(new JoinData { JoinNumber = 38, JoinSpan = 1 }, - new JoinMetadata { Description = "Chapter Plus", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("ChapMinus")] - public JoinDataComplete ChapMinus = new JoinDataComplete(new JoinData { JoinNumber = 39, JoinSpan = 1 }, - new JoinMetadata { Description = "Chapter Minus", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Replay")] - public JoinDataComplete Replay = new JoinDataComplete(new JoinData { JoinNumber = 40, JoinSpan = 1 }, - new JoinMetadata { Description = "Replay", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Record")] - public JoinDataComplete Record = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, - new JoinMetadata { Description = "Record", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("HasKeypadAccessoryButton1")] - public JoinDataComplete HasKeypadAccessoryButton1 = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 }, - new JoinMetadata { Description = "Has Keypad Accessory Button 1", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("HasKeypadAccessoryButton2")] - public JoinDataComplete HasKeypadAccessoryButton2 = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 1 }, - new JoinMetadata { Description = "Has Keypad Accessory Button 2", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("KeypadAccessoryButton1Press")] - public JoinDataComplete KeypadAccessoryButton1Press = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 2 }, - new JoinMetadata { Description = "Keypad Accessory Button 1 Press", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("KeypadAccessoryButton2Press")] - public JoinDataComplete KeypadAccessoryButton2Press = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 2 }, - new JoinMetadata { Description = "Keypad Accessory Button 2 Press", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Name")] - public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("KeypadAccessoryButton1Label")] - public JoinDataComplete KeypadAccessoryButton1Label = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 }, - new JoinMetadata { Description = "Keypad Accessory Button 1 Label", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("KeypadAccessoryButton2Label")] - public JoinDataComplete KeypadAccessoryButton2Label = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 1 }, - new JoinMetadata { Description = "Keypad Accessory Button 1 Label", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public IRBlurayBaseJoinMap(uint joinStart) - : this(joinStart, typeof(IRBlurayBaseJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected IRBlurayBaseJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } + [JoinName("ChapPlus")] + public JoinDataComplete ChapPlus = new JoinDataComplete(new JoinData { JoinNumber = 38, JoinSpan = 1 }, + new JoinMetadata { Description = "Chapter Plus", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("ChapMinus")] + public JoinDataComplete ChapMinus = new JoinDataComplete(new JoinData { JoinNumber = 39, JoinSpan = 1 }, + new JoinMetadata { Description = "Chapter Minus", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Replay")] + public JoinDataComplete Replay = new JoinDataComplete(new JoinData { JoinNumber = 40, JoinSpan = 1 }, + new JoinMetadata { Description = "Replay", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Record")] + public JoinDataComplete Record = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, + new JoinMetadata { Description = "Record", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("HasKeypadAccessoryButton1")] + public JoinDataComplete HasKeypadAccessoryButton1 = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 }, + new JoinMetadata { Description = "Has Keypad Accessory Button 1", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("HasKeypadAccessoryButton2")] + public JoinDataComplete HasKeypadAccessoryButton2 = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 1 }, + new JoinMetadata { Description = "Has Keypad Accessory Button 2", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("KeypadAccessoryButton1Press")] + public JoinDataComplete KeypadAccessoryButton1Press = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 2 }, + new JoinMetadata { Description = "Keypad Accessory Button 1 Press", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("KeypadAccessoryButton2Press")] + public JoinDataComplete KeypadAccessoryButton2Press = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 2 }, + new JoinMetadata { Description = "Keypad Accessory Button 2 Press", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("KeypadAccessoryButton1Label")] + public JoinDataComplete KeypadAccessoryButton1Label = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 }, + new JoinMetadata { Description = "Keypad Accessory Button 1 Label", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("KeypadAccessoryButton2Label")] + public JoinDataComplete KeypadAccessoryButton2Label = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 1 }, + new JoinMetadata { Description = "Keypad Accessory Button 1 Label", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public IRBlurayBaseJoinMap(uint joinStart) + : this(joinStart, typeof(IRBlurayBaseJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected IRBlurayBaseJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/PduJoinMapBase.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/PduJoinMapBase.cs index 0c2e9ed9b..10bf590d7 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/PduJoinMapBase.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/PduJoinMapBase.cs @@ -1,60 +1,59 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class PduJoinMapBase : JoinMapBaseAdvanced { - public class PduJoinMapBase : JoinMapBaseAdvanced - { - [JoinName("Name")] - public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "PDU Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("Online")] - public JoinDataComplete Online = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("OutletCount")] - public JoinDataComplete OutletCount = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Number of COntrolled Outlets", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("OutletName")] - public JoinDataComplete OutletName = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata { Description = "Outlet Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("OutletEnabled")] - public JoinDataComplete OutletEnabled = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata { Description = "Outlet Enabled", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("OutletPowerCycle")] - public JoinDataComplete OutletPowerCycle = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata { Description = "Outlet Power Cycle", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("OutletPowerOn")] - public JoinDataComplete OutletPowerOn = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, - new JoinMetadata { Description = "Outlet Power On", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("OutletPowerOff")] - public JoinDataComplete OutletPowerOff = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, - new JoinMetadata { Description = "Outlet Power Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public PduJoinMapBase(uint joinStart) - :base(joinStart, typeof(PduJoinMapBase)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - public PduJoinMapBase(uint joinStart, Type type) - : base(joinStart, type) - { - } + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "PDU Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("Online")] + public JoinDataComplete Online = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutletCount")] + public JoinDataComplete OutletCount = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Number of COntrolled Outlets", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("OutletName")] + public JoinDataComplete OutletName = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "Outlet Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("OutletEnabled")] + public JoinDataComplete OutletEnabled = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "Outlet Enabled", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutletPowerCycle")] + public JoinDataComplete OutletPowerCycle = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata { Description = "Outlet Power Cycle", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutletPowerOn")] + public JoinDataComplete OutletPowerOn = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, + new JoinMetadata { Description = "Outlet Power On", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("OutletPowerOff")] + public JoinDataComplete OutletPowerOff = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, + new JoinMetadata { Description = "Outlet Power Off", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public PduJoinMapBase(uint joinStart) + :base(joinStart, typeof(PduJoinMapBase)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + public PduJoinMapBase(uint joinStart, Type type) + : base(joinStart, type) + { } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/SetTopBoxControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/SetTopBoxControllerJoinMap.cs index ec0ff8d25..0705eb93b 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/SetTopBoxControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/SetTopBoxControllerJoinMap.cs @@ -1,240 +1,239 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class SetTopBoxControllerJoinMap : JoinMapBaseAdvanced { - public class SetTopBoxControllerJoinMap : JoinMapBaseAdvanced - { - [JoinName("PowerOn")] - public JoinDataComplete PowerOn = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Power On", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("PowerOn")] + public JoinDataComplete PowerOn = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Power On", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("PowerOff")] + public JoinDataComplete PowerOff = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Power Off", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("PowerToggle")] + public JoinDataComplete PowerToggle = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Power Toggle", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("HasDpad")] + public JoinDataComplete HasDpad = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Has DPad", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Up")] + public JoinDataComplete Up = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Nav Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Down")] + public JoinDataComplete Down = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Nav Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Left")] + public JoinDataComplete Left = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Nav Left", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Right")] + public JoinDataComplete Right = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Nav Right", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Select")] + public JoinDataComplete Select = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Select", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Menu")] + public JoinDataComplete Menu = new JoinDataComplete(new JoinData { JoinNumber = 9, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Menu", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Exit")] + public JoinDataComplete Exit = new JoinDataComplete(new JoinData { JoinNumber = 10, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Exit", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("HasNumeric")] + public JoinDataComplete HasNumeric = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Has Numeric", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Digit0")] + public JoinDataComplete Digit0 = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Digit 0", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Digit1")] + public JoinDataComplete Digit1 = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Digit 1", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("PowerOff")] - public JoinDataComplete PowerOff = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Power Off", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Digit2")] + public JoinDataComplete Digit2 = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Digit 2", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("PowerToggle")] - public JoinDataComplete PowerToggle = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Power Toggle", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Digit3")] + public JoinDataComplete Digit3 = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Digit 3", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("HasDpad")] - public JoinDataComplete HasDpad = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Has DPad", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Digit4")] + public JoinDataComplete Digit4 = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Digit 4", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Up")] - public JoinDataComplete Up = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Nav Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Digit5")] + public JoinDataComplete Digit5 = new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Digit 5", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Down")] - public JoinDataComplete Down = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Nav Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Digit6")] + public JoinDataComplete Digit6 = new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Digit 6", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Left")] - public JoinDataComplete Left = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Nav Left", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Digit7")] + public JoinDataComplete Digit7 = new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Digit 7", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Right")] - public JoinDataComplete Right = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Nav Right", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Digit8")] + public JoinDataComplete Digit8 = new JoinDataComplete(new JoinData { JoinNumber = 19, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Digit 8", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Select")] - public JoinDataComplete Select = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Select", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Digit9")] + public JoinDataComplete Digit9 = new JoinDataComplete(new JoinData { JoinNumber = 20, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Digit 9", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Menu")] - public JoinDataComplete Menu = new JoinDataComplete(new JoinData { JoinNumber = 9, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Menu", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Dash")] + public JoinDataComplete Dash = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Dash", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Exit")] - public JoinDataComplete Exit = new JoinDataComplete(new JoinData { JoinNumber = 10, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Exit", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("KeypadEnter")] + public JoinDataComplete KeypadEnter = new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Keypad Enter", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("HasNumeric")] - public JoinDataComplete HasNumeric = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Has Numeric", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("ChannelUp")] + public JoinDataComplete ChannelUp = new JoinDataComplete(new JoinData { JoinNumber = 23, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Channel Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit0")] - public JoinDataComplete Digit0 = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Digit 0", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("ChannelDown")] + public JoinDataComplete ChannelDown = new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Channel Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit1")] - public JoinDataComplete Digit1 = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Digit 1", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("LastChannel")] + public JoinDataComplete LastChannel = new JoinDataComplete(new JoinData { JoinNumber = 25, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Last Channel", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit2")] - public JoinDataComplete Digit2 = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Digit 2", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Guide")] + public JoinDataComplete Guide = new JoinDataComplete(new JoinData { JoinNumber = 26, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Guide", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit3")] - public JoinDataComplete Digit3 = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Digit 3", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Info")] + public JoinDataComplete Info = new JoinDataComplete(new JoinData { JoinNumber = 27, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Info", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit4")] - public JoinDataComplete Digit4 = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Digit 4", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Red")] + public JoinDataComplete Red = new JoinDataComplete(new JoinData { JoinNumber = 28, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Red", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit5")] - public JoinDataComplete Digit5 = new JoinDataComplete(new JoinData { JoinNumber = 16, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Digit 5", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Green")] + public JoinDataComplete Green = new JoinDataComplete(new JoinData { JoinNumber = 29, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Green", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit6")] - public JoinDataComplete Digit6 = new JoinDataComplete(new JoinData { JoinNumber = 17, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Digit 6", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Yellow")] + public JoinDataComplete Yellow = new JoinDataComplete(new JoinData { JoinNumber = 30, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Yellow", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit7")] - public JoinDataComplete Digit7 = new JoinDataComplete(new JoinData { JoinNumber = 18, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Digit 7", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Blue")] + public JoinDataComplete Blue = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Blue", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit8")] - public JoinDataComplete Digit8 = new JoinDataComplete(new JoinData { JoinNumber = 19, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Digit 8", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("HasDvr")] + public JoinDataComplete HasDvr = new JoinDataComplete(new JoinData { JoinNumber = 32, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Has DVR", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Digit9")] - public JoinDataComplete Digit9 = new JoinDataComplete(new JoinData { JoinNumber = 20, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Digit 9", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("DvrList")] + public JoinDataComplete DvrList = new JoinDataComplete(new JoinData { JoinNumber = 32, JoinSpan = 1 }, + new JoinMetadata { Description = "STB DvrList", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Dash")] - public JoinDataComplete Dash = new JoinDataComplete(new JoinData { JoinNumber = 21, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Dash", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Play")] + public JoinDataComplete Play = new JoinDataComplete(new JoinData { JoinNumber = 33, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Play", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("KeypadEnter")] - public JoinDataComplete KeypadEnter = new JoinDataComplete(new JoinData { JoinNumber = 22, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Keypad Enter", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Pause")] + public JoinDataComplete Pause = new JoinDataComplete(new JoinData { JoinNumber = 34, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Pause", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ChannelUp")] - public JoinDataComplete ChannelUp = new JoinDataComplete(new JoinData { JoinNumber = 23, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Channel Up", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Stop")] + public JoinDataComplete Stop = new JoinDataComplete(new JoinData { JoinNumber = 35, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Stop", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ChannelDown")] - public JoinDataComplete ChannelDown = new JoinDataComplete(new JoinData { JoinNumber = 24, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Channel Down", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("FFwd")] + public JoinDataComplete FFwd = new JoinDataComplete(new JoinData { JoinNumber = 36, JoinSpan = 1 }, + new JoinMetadata { Description = "STB FFwd", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("LastChannel")] - public JoinDataComplete LastChannel = new JoinDataComplete(new JoinData { JoinNumber = 25, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Last Channel", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Rewind")] + public JoinDataComplete Rewind = new JoinDataComplete(new JoinData { JoinNumber = 37, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Rewind", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Guide")] - public JoinDataComplete Guide = new JoinDataComplete(new JoinData { JoinNumber = 26, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Guide", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("ChapPlus")] + public JoinDataComplete ChapPlus = new JoinDataComplete(new JoinData { JoinNumber = 38, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Chapter Plus", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Info")] - public JoinDataComplete Info = new JoinDataComplete(new JoinData { JoinNumber = 27, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Info", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("ChapMinus")] + public JoinDataComplete ChapMinus = new JoinDataComplete(new JoinData { JoinNumber = 39, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Chapter Minus", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Red")] - public JoinDataComplete Red = new JoinDataComplete(new JoinData { JoinNumber = 28, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Red", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Replay")] + public JoinDataComplete Replay = new JoinDataComplete(new JoinData { JoinNumber = 40, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Replay", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Green")] - public JoinDataComplete Green = new JoinDataComplete(new JoinData { JoinNumber = 29, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Green", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("Record")] + public JoinDataComplete Record = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Record", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("Yellow")] - public JoinDataComplete Yellow = new JoinDataComplete(new JoinData { JoinNumber = 30, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Yellow", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Blue")] - public JoinDataComplete Blue = new JoinDataComplete(new JoinData { JoinNumber = 31, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Blue", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("HasDvr")] - public JoinDataComplete HasDvr = new JoinDataComplete(new JoinData { JoinNumber = 32, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Has DVR", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("DvrList")] - public JoinDataComplete DvrList = new JoinDataComplete(new JoinData { JoinNumber = 32, JoinSpan = 1 }, - new JoinMetadata { Description = "STB DvrList", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Play")] - public JoinDataComplete Play = new JoinDataComplete(new JoinData { JoinNumber = 33, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Play", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Pause")] - public JoinDataComplete Pause = new JoinDataComplete(new JoinData { JoinNumber = 34, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Pause", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Stop")] - public JoinDataComplete Stop = new JoinDataComplete(new JoinData { JoinNumber = 35, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Stop", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("FFwd")] - public JoinDataComplete FFwd = new JoinDataComplete(new JoinData { JoinNumber = 36, JoinSpan = 1 }, - new JoinMetadata { Description = "STB FFwd", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Rewind")] - public JoinDataComplete Rewind = new JoinDataComplete(new JoinData { JoinNumber = 37, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Rewind", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("ChapPlus")] - public JoinDataComplete ChapPlus = new JoinDataComplete(new JoinData { JoinNumber = 38, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Chapter Plus", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("ChapMinus")] - public JoinDataComplete ChapMinus = new JoinDataComplete(new JoinData { JoinNumber = 39, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Chapter Minus", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Replay")] - public JoinDataComplete Replay = new JoinDataComplete(new JoinData { JoinNumber = 40, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Replay", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Record")] - public JoinDataComplete Record = new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Record", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("HasKeypadAccessoryButton1")] - public JoinDataComplete HasKeypadAccessoryButton1 = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Has Keypad Accessory Button 1", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("HasKeypadAccessoryButton2")] - public JoinDataComplete HasKeypadAccessoryButton2 = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Has Keypad Accessory Button 2", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("KeypadAccessoryButton1Press")] - public JoinDataComplete KeypadAccessoryButton1Press = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 2 }, - new JoinMetadata { Description = "STB Keypad Accessory Button 1 Press", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("KeypadAccessoryButton2Press")] - public JoinDataComplete KeypadAccessoryButton2Press = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 2 }, - new JoinMetadata { Description = "STB Keypad Accessory Button 2 Press", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Name")] - public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("KeypadAccessoryButton1Label")] - public JoinDataComplete KeypadAccessoryButton1Label = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Keypad Accessory Button 1 Label", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("KeypadAccessoryButton2Label")] - public JoinDataComplete KeypadAccessoryButton2Label = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Keypad Accessory Button 1 Label", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("LoadPresets")] - public JoinDataComplete LoadPresets = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Load Presets", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("HasPresets")] - public JoinDataComplete HasPresets = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1 }, - new JoinMetadata { Description = "STB Load Presets", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public SetTopBoxControllerJoinMap(uint joinStart) - : this(joinStart, typeof(SetTopBoxControllerJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected SetTopBoxControllerJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } + [JoinName("HasKeypadAccessoryButton1")] + public JoinDataComplete HasKeypadAccessoryButton1 = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Has Keypad Accessory Button 1", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("HasKeypadAccessoryButton2")] + public JoinDataComplete HasKeypadAccessoryButton2 = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Has Keypad Accessory Button 2", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("KeypadAccessoryButton1Press")] + public JoinDataComplete KeypadAccessoryButton1Press = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 2 }, + new JoinMetadata { Description = "STB Keypad Accessory Button 1 Press", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("KeypadAccessoryButton2Press")] + public JoinDataComplete KeypadAccessoryButton2Press = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 2 }, + new JoinMetadata { Description = "STB Keypad Accessory Button 2 Press", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("KeypadAccessoryButton1Label")] + public JoinDataComplete KeypadAccessoryButton1Label = new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Keypad Accessory Button 1 Label", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("KeypadAccessoryButton2Label")] + public JoinDataComplete KeypadAccessoryButton2Label = new JoinDataComplete(new JoinData { JoinNumber = 43, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Keypad Accessory Button 1 Label", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("LoadPresets")] + public JoinDataComplete LoadPresets = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Load Presets", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("HasPresets")] + public JoinDataComplete HasPresets = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1 }, + new JoinMetadata { Description = "STB Load Presets", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public SetTopBoxControllerJoinMap(uint joinStart) + : this(joinStart, typeof(SetTopBoxControllerJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected SetTopBoxControllerJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/StatusSignControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/StatusSignControllerJoinMap.cs index ba441ef00..98cd92180 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/StatusSignControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/StatusSignControllerJoinMap.cs @@ -1,59 +1,58 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class StatusSignControllerJoinMap : JoinMapBaseAdvanced { - public class StatusSignControllerJoinMap : JoinMapBaseAdvanced + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Status Sign Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Status Sign Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + + [JoinName("RedControl")] + public JoinDataComplete RedControl = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Status Red LED Enable / Disable", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("RedLed")] + public JoinDataComplete RedLed = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Status Red LED Intensity", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("GreenControl")] + public JoinDataComplete GreenControl = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Status Green LED Enable / Disable", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("GreenLed")] + public JoinDataComplete GreenLed = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Status Green LED Intensity", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + [JoinName("BlueControl")] + public JoinDataComplete BlueControl = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Status Blue LED Enable / Disable", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("BlueLed")] + public JoinDataComplete BlueLed = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Status Blue LED Intensity", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public StatusSignControllerJoinMap(uint joinStart) + : this(joinStart, typeof(StatusSignControllerJoinMap)) { - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Status Sign Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("Name")] - public JoinDataComplete Name = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Status Sign Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - - [JoinName("RedControl")] - public JoinDataComplete RedControl = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Status Red LED Enable / Disable", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("RedLed")] - public JoinDataComplete RedLed = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Status Red LED Intensity", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("GreenControl")] - public JoinDataComplete GreenControl = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Status Green LED Enable / Disable", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("GreenLed")] - public JoinDataComplete GreenLed = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Status Green LED Intensity", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - [JoinName("BlueControl")] - public JoinDataComplete BlueControl = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Status Blue LED Enable / Disable", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - - [JoinName("BlueLed")] - public JoinDataComplete BlueLed = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Status Blue LED Intensity", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Analog }); - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public StatusSignControllerJoinMap(uint joinStart) - : this(joinStart, typeof(StatusSignControllerJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected StatusSignControllerJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } + } + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected StatusSignControllerJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/SystemMonitorJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/SystemMonitorJoinMap.cs index 9adabfce9..6cd482afa 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/SystemMonitorJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/SystemMonitorJoinMap.cs @@ -1,136 +1,136 @@ using System; -namespace PepperDash.Essentials.Core.Bridges +namespace PepperDash.Essentials.Core.Bridges; + +public class SystemMonitorJoinMap : JoinMapBaseAdvanced { - public class SystemMonitorJoinMap : JoinMapBaseAdvanced - { - [JoinName("TimeZone")] - public JoinDataComplete TimeZone = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Timezone", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); + [JoinName("TimeZone")] + public JoinDataComplete TimeZone = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Timezone", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Analog }); - [JoinName("TimeZoneName")] - public JoinDataComplete TimeZoneName = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Timezone Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("TimeZoneName")] + public JoinDataComplete TimeZoneName = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Timezone Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("IOControllerVersion")] - public JoinDataComplete IOControllerVersion = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor IO Controller Version", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("IOControllerVersion")] + public JoinDataComplete IOControllerVersion = new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor IO Controller Version", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("SnmpAppVersion")] - public JoinDataComplete SnmpAppVersion = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor SNMP App Version", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("SnmpAppVersion")] + public JoinDataComplete SnmpAppVersion = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor SNMP App Version", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("BACnetAppVersion")] - public JoinDataComplete BACnetAppVersion = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor BACNet App Version", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("BACnetAppVersion")] + public JoinDataComplete BACnetAppVersion = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor BACNet App Version", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("ControllerVersion")] - public JoinDataComplete ControllerVersion = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Controller Version", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("ControllerVersion")] + public JoinDataComplete ControllerVersion = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Controller Version", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("SerialNumber")] - public JoinDataComplete SerialNumber = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Serial Number", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("SerialNumber")] + public JoinDataComplete SerialNumber = new JoinDataComplete(new JoinData { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Serial Number", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("Model")] - public JoinDataComplete Model = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Model", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("Model")] + public JoinDataComplete Model = new JoinDataComplete(new JoinData { JoinNumber = 7, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Model", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("Uptime")] - public JoinDataComplete Uptime = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Uptime", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("Uptime")] + public JoinDataComplete Uptime = new JoinDataComplete(new JoinData { JoinNumber = 8, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Uptime", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("LastBoot")] - public JoinDataComplete LastBoot = new JoinDataComplete(new JoinData { JoinNumber = 9, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Last Boot", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("LastBoot")] + public JoinDataComplete LastBoot = new JoinDataComplete(new JoinData { JoinNumber = 9, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Last Boot", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("ProgramOffsetJoin")] - public JoinDataComplete ProgramOffsetJoin = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 5 }, - new JoinMetadata { Description = "All Program Data is offset between slots by 5 - First Joins Start at 11", JoinCapabilities = eJoinCapabilities.None, JoinType = eJoinType.None }); + [JoinName("ProgramOffsetJoin")] + public JoinDataComplete ProgramOffsetJoin = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 5 }, + new JoinMetadata { Description = "All Program Data is offset between slots by 5 - First Joins Start at 11", JoinCapabilities = eJoinCapabilities.None, JoinType = eJoinType.None }); - [JoinName("ProgramStart")] - public JoinDataComplete ProgramStart = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Program Start / Fb", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("ProgramStart")] + public JoinDataComplete ProgramStart = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Program Start / Fb", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ProgramStop")] - public JoinDataComplete ProgramStop = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Program Stop / Fb", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("ProgramStop")] + public JoinDataComplete ProgramStop = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Program Stop / Fb", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ProgramRegister")] - public JoinDataComplete ProgramRegister = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Program Register / Fb", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("ProgramRegister")] + public JoinDataComplete ProgramRegister = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Program Register / Fb", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ProgramUnregister")] - public JoinDataComplete ProgramUnregister = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Program UnRegister / Fb", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("ProgramUnregister")] + public JoinDataComplete ProgramUnregister = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Program UnRegister / Fb", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ProgramName")] - public JoinDataComplete ProgramName = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Program Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("ProgramName")] + public JoinDataComplete ProgramName = new JoinDataComplete(new JoinData { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Program Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("ProgramCompiledTime")] - public JoinDataComplete ProgramCompiledTime = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Program Compile Time", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("ProgramCompiledTime")] + public JoinDataComplete ProgramCompiledTime = new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Program Compile Time", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("ProgramCrestronDatabaseVersion")] - public JoinDataComplete ProgramCrestronDatabaseVersion = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Program Database Version", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("ProgramCrestronDatabaseVersion")] + public JoinDataComplete ProgramCrestronDatabaseVersion = new JoinDataComplete(new JoinData { JoinNumber = 13, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Program Database Version", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("ProgramEnvironmentVersion")] - public JoinDataComplete ProgramEnvironmentVersion = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Program Environment Version", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("ProgramEnvironmentVersion")] + public JoinDataComplete ProgramEnvironmentVersion = new JoinDataComplete(new JoinData { JoinNumber = 14, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Program Environment Version", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("AggregatedProgramInfo")] - public JoinDataComplete AggregatedProgramInfo = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Program Aggregate Info Json", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("AggregatedProgramInfo")] + public JoinDataComplete AggregatedProgramInfo = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Program Aggregate Info Json", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("EthernetOffsetJoin")] - public JoinDataComplete EthernetOffsetJoin = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, - new JoinMetadata { Description = "All Ethernet Data is offset between Nics by 5 - First Joins Start at 76", JoinCapabilities = eJoinCapabilities.None, JoinType = eJoinType.None }); + [JoinName("EthernetOffsetJoin")] + public JoinDataComplete EthernetOffsetJoin = new JoinDataComplete(new JoinData { JoinNumber = 15, JoinSpan = 1 }, + new JoinMetadata { Description = "All Ethernet Data is offset between Nics by 5 - First Joins Start at 76", JoinCapabilities = eJoinCapabilities.None, JoinType = eJoinType.None }); - [JoinName("HostName")] - public JoinDataComplete HostName = new JoinDataComplete(new JoinData { JoinNumber = 76, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Ethernet Hostname", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("HostName")] + public JoinDataComplete HostName = new JoinDataComplete(new JoinData { JoinNumber = 76, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Ethernet Hostname", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("CurrentIpAddress")] - public JoinDataComplete CurrentIpAddress = new JoinDataComplete(new JoinData { JoinNumber = 77, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Ethernet Current Ip Address", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("CurrentIpAddress")] + public JoinDataComplete CurrentIpAddress = new JoinDataComplete(new JoinData { JoinNumber = 77, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Ethernet Current Ip Address", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("CurrentSubnetMask")] - public JoinDataComplete CurrentSubnetMask = new JoinDataComplete(new JoinData { JoinNumber = 78, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Ethernet Current Subnet Mask", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("CurrentSubnetMask")] + public JoinDataComplete CurrentSubnetMask = new JoinDataComplete(new JoinData { JoinNumber = 78, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Ethernet Current Subnet Mask", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("CurrentDefaultGateway")] - public JoinDataComplete CurrentDefaultGateway = new JoinDataComplete(new JoinData { JoinNumber = 79, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Ethernet Current Default Gateway", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("CurrentDefaultGateway")] + public JoinDataComplete CurrentDefaultGateway = new JoinDataComplete(new JoinData { JoinNumber = 79, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Ethernet Current Default Gateway", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("StaticIpAddress")] - public JoinDataComplete StaticIpAddress = new JoinDataComplete(new JoinData { JoinNumber = 80, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Ethernet Static Ip Address", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("StaticIpAddress")] + public JoinDataComplete StaticIpAddress = new JoinDataComplete(new JoinData { JoinNumber = 80, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Ethernet Static Ip Address", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("StaticSubnetMask")] - public JoinDataComplete StaticSubnetMask = new JoinDataComplete(new JoinData { JoinNumber = 81, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Ethernet Static Subnet Mask", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("StaticSubnetMask")] + public JoinDataComplete StaticSubnetMask = new JoinDataComplete(new JoinData { JoinNumber = 81, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Ethernet Static Subnet Mask", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("StaticDefaultGateway")] - public JoinDataComplete StaticDefaultGateway = new JoinDataComplete(new JoinData { JoinNumber = 82, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Ethernet Static Default Gateway", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("StaticDefaultGateway")] + public JoinDataComplete StaticDefaultGateway = new JoinDataComplete(new JoinData { JoinNumber = 82, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Ethernet Static Default Gateway", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("Domain")] - public JoinDataComplete Domain = new JoinDataComplete(new JoinData { JoinNumber = 83, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Ethernet Domain", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("Domain")] + public JoinDataComplete Domain = new JoinDataComplete(new JoinData { JoinNumber = 83, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Ethernet Domain", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("DnsServer")] - public JoinDataComplete DnsServer = new JoinDataComplete(new JoinData { JoinNumber = 84, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Ethernet Dns Server", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("DnsServer")] + public JoinDataComplete DnsServer = new JoinDataComplete(new JoinData { JoinNumber = 84, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Ethernet Dns Server", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("MacAddress")] - public JoinDataComplete MacAddress = new JoinDataComplete(new JoinData { JoinNumber = 85, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Ethernet Mac Address", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("MacAddress")] + public JoinDataComplete MacAddress = new JoinDataComplete(new JoinData { JoinNumber = 85, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Ethernet Mac Address", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("DhcpStatus")] - public JoinDataComplete DhcpStatus = new JoinDataComplete(new JoinData { JoinNumber = 86, JoinSpan = 1 }, - new JoinMetadata { Description = "Processor Ethernet Dhcp Status", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); + [JoinName("DhcpStatus")] + public JoinDataComplete DhcpStatus = new JoinDataComplete(new JoinData { JoinNumber = 86, JoinSpan = 1 }, + new JoinMetadata { Description = "Processor Ethernet Dhcp Status", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); [JoinName("ProcessorRebot")] public JoinDataComplete ProcessorReboot = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, @@ -149,23 +149,22 @@ public class SystemMonitorJoinMap : JoinMapBaseAdvanced new JoinMetadata { Description = "Resets the program", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public SystemMonitorJoinMap(uint joinStart) - : this(joinStart, typeof(SystemMonitorJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected SystemMonitorJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public SystemMonitorJoinMap(uint joinStart) + : this(joinStart, typeof(SystemMonitorJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected SystemMonitorJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs index 755a586eb..c4526e474 100644 --- a/src/PepperDash.Essentials.Core/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Bridges/JoinMaps/VideoCodecControllerJoinMap.cs @@ -1,7 +1,7 @@ using System; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core.Bridges.JoinMaps -{ +namespace PepperDash.Essentials.Core.Bridges.JoinMaps; + public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced { #region Digital @@ -20,21 +20,21 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("SendDtmfToSpecificCallIndex")] - public JoinDataComplete SendDtmfToSpecificCallIndex = new JoinDataComplete( - new JoinData - { - JoinNumber = 10, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "If High, will send DTMF tones to the call set by SelectCall analog. If low sends DTMF tones to last connected call.", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("Dtmf1")] + [JoinName("SendDtmfToSpecificCallIndex")] + public JoinDataComplete SendDtmfToSpecificCallIndex = new JoinDataComplete( + new JoinData + { + JoinNumber = 10, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "If High, will send DTMF tones to the call set by SelectCall analog. If low sends DTMF tones to last connected call.", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("Dtmf1")] public JoinDataComplete Dtmf1 = new JoinDataComplete( new JoinData { @@ -48,7 +48,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("Dtmf2")] + [JoinName("Dtmf2")] public JoinDataComplete Dtmf2 = new JoinDataComplete( new JoinData { @@ -62,7 +62,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("Dtmf3")] + [JoinName("Dtmf3")] public JoinDataComplete Dtmf3 = new JoinDataComplete( new JoinData { @@ -76,7 +76,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("Dtmf4")] + [JoinName("Dtmf4")] public JoinDataComplete Dtmf4 = new JoinDataComplete( new JoinData { @@ -90,7 +90,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("Dtmf5")] + [JoinName("Dtmf5")] public JoinDataComplete Dtmf5 = new JoinDataComplete( new JoinData { @@ -104,7 +104,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("Dtmf6")] + [JoinName("Dtmf6")] public JoinDataComplete Dtmf6 = new JoinDataComplete( new JoinData { @@ -118,7 +118,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("Dtmf7")] + [JoinName("Dtmf7")] public JoinDataComplete Dtmf7 = new JoinDataComplete( new JoinData { @@ -132,7 +132,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("Dtmf8")] + [JoinName("Dtmf8")] public JoinDataComplete Dtmf8 = new JoinDataComplete( new JoinData { @@ -146,7 +146,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("Dtmf9")] + [JoinName("Dtmf9")] public JoinDataComplete Dtmf9 = new JoinDataComplete( new JoinData { @@ -160,7 +160,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("Dtmf0")] + [JoinName("Dtmf0")] public JoinDataComplete Dtmf0 = new JoinDataComplete( new JoinData { @@ -174,7 +174,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("DtmfStar")] + [JoinName("DtmfStar")] public JoinDataComplete DtmfStar = new JoinDataComplete( new JoinData { @@ -188,7 +188,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("DtmfPound")] + [JoinName("DtmfPound")] public JoinDataComplete DtmfPound = new JoinDataComplete( new JoinData { @@ -202,7 +202,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("EndAllCalls")] + [JoinName("EndAllCalls")] public JoinDataComplete EndAllCalls = new JoinDataComplete( new JoinData { @@ -300,7 +300,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("DialPhone")] + [JoinName("DialPhone")] public JoinDataComplete DialPhone = new JoinDataComplete( new JoinData { @@ -328,7 +328,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("HangUpPhone")] + [JoinName("HangUpPhone")] public JoinDataComplete HangUpPhone = new JoinDataComplete( new JoinData { @@ -342,47 +342,47 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("EndCallStart")] - public JoinDataComplete EndCallStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 81, - JoinSpan = 8 - }, - new JoinMetadata - { - Description = "End a specific call by call index. ", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("JoinAllCalls")] - public JoinDataComplete JoinAllCalls = new JoinDataComplete( - new JoinData - { - JoinNumber = 90, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Join all calls", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("JoinCallStart")] - public JoinDataComplete JoinCallStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 91, - JoinSpan = 8 - }, - new JoinMetadata - { - Description = "Join a specific call by call index. ", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); + [JoinName("EndCallStart")] + public JoinDataComplete EndCallStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 81, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "End a specific call by call index. ", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("JoinAllCalls")] + public JoinDataComplete JoinAllCalls = new JoinDataComplete( + new JoinData + { + JoinNumber = 90, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Join all calls", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("JoinCallStart")] + public JoinDataComplete JoinCallStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 91, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "Join a specific call by call index. ", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); [JoinName("DirectorySearchBusy")] public JoinDataComplete DirectorySearchBusy = new JoinDataComplete( @@ -497,47 +497,47 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("DirectoryDisableAutoDialSelectedLine")] - public JoinDataComplete DirectoryDisableAutoDialSelectedLine = new JoinDataComplete( - new JoinData - { - JoinNumber = 107, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Set high to disable automatic dialing of a contact when selected", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryDialSelectedContactMethod")] - public JoinDataComplete DirectoryDialSelectedContactMethod = new JoinDataComplete( - new JoinData - { - JoinNumber = 108, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Pulse to dial the selected contact method", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryClearSelected")] - public JoinDataComplete DirectoryClearSelected = new JoinDataComplete( - new JoinData - { - JoinNumber = 110, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Clear Selected Entry and String from Search", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); + [JoinName("DirectoryDisableAutoDialSelectedLine")] + public JoinDataComplete DirectoryDisableAutoDialSelectedLine = new JoinDataComplete( + new JoinData + { + JoinNumber = 107, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Set high to disable automatic dialing of a contact when selected", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryDialSelectedContactMethod")] + public JoinDataComplete DirectoryDialSelectedContactMethod = new JoinDataComplete( + new JoinData + { + JoinNumber = 108, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Pulse to dial the selected contact method", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryClearSelected")] + public JoinDataComplete DirectoryClearSelected = new JoinDataComplete( + new JoinData + { + JoinNumber = 110, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Clear Selected Entry and String from Search", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); [JoinName("CameraTiltUp")] @@ -624,47 +624,47 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("CameraFocusNear")] - public JoinDataComplete CameraFocusNear = new JoinDataComplete( - new JoinData - { - JoinNumber = 117, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Focus Near", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraFocusFar")] - public JoinDataComplete CameraFocusFar = new JoinDataComplete( - new JoinData - { - JoinNumber = 118, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Focus Far", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraFocusAuto")] - public JoinDataComplete CameraFocusAuto = new JoinDataComplete( - new JoinData - { - JoinNumber = 119, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Camera Auto Focus Trigger", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); + [JoinName("CameraFocusNear")] + public JoinDataComplete CameraFocusNear = new JoinDataComplete( + new JoinData + { + JoinNumber = 117, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Focus Near", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraFocusFar")] + public JoinDataComplete CameraFocusFar = new JoinDataComplete( + new JoinData + { + JoinNumber = 118, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Focus Far", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraFocusAuto")] + public JoinDataComplete CameraFocusAuto = new JoinDataComplete( + new JoinData + { + JoinNumber = 119, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Camera Auto Focus Trigger", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); [JoinName("CameraPresetSave")] public JoinDataComplete CameraPresetSave = new JoinDataComplete( @@ -792,7 +792,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("DialMeetingStart")] + [JoinName("DialMeetingStart")] public JoinDataComplete DialMeetingStart = new JoinDataComplete( new JoinData { @@ -918,33 +918,33 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("RemoveSelectedRecentCallItem")] - public JoinDataComplete RemoveSelectedRecentCallItem = new JoinDataComplete( - new JoinData - { - JoinNumber = 181, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Pulse to remove the selected recent call item specified by the SelectRecentCallItem analog join", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DialSelectedRecentCallItem")] - public JoinDataComplete DialSelectedRecentCallItem = new JoinDataComplete( - new JoinData - { - JoinNumber = 182, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Pulse to dial the selected recent call item specified by the SelectRecentCallItem analog join", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); + [JoinName("RemoveSelectedRecentCallItem")] + public JoinDataComplete RemoveSelectedRecentCallItem = new JoinDataComplete( + new JoinData + { + JoinNumber = 181, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Pulse to remove the selected recent call item specified by the SelectRecentCallItem analog join", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DialSelectedRecentCallItem")] + public JoinDataComplete DialSelectedRecentCallItem = new JoinDataComplete( + new JoinData + { + JoinNumber = 182, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Pulse to dial the selected recent call item specified by the SelectRecentCallItem analog join", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); [JoinName("SourceShareStart")] public JoinDataComplete SourceShareStart = new JoinDataComplete( @@ -1016,117 +1016,117 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Digital }); - [JoinName("HoldAllCalls")] - public JoinDataComplete HoldAllCalls = new JoinDataComplete( - new JoinData - { - JoinNumber = 220, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Holds all calls", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("HoldCallsStart")] - public JoinDataComplete HoldCallsStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 221, - JoinSpan = 8 - }, - new JoinMetadata - { - Description = "Holds Call at specified index. FB reported on Call Status XSIG", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ResumeCallsStart")] - public JoinDataComplete ResumeCallsStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 231, - JoinSpan = 8 - }, - new JoinMetadata - { - Description = "Resume Call at specified index", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("MultiSiteOptionIsEnabled")] - public JoinDataComplete MultiSiteOptionIsEnabled = new JoinDataComplete( - new JoinData - { - JoinNumber = 301, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Multi site option is enabled FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("AutoAnswerEnabled")] - public JoinDataComplete AutoAnswerEnabled = new JoinDataComplete( - new JoinData - { - JoinNumber = 302, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Auto Answer is enabled FB", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ParticipantAudioMuteToggleStart")] - public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( + [JoinName("HoldAllCalls")] + public JoinDataComplete HoldAllCalls = new JoinDataComplete( + new JoinData + { + JoinNumber = 220, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Holds all calls", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("HoldCallsStart")] + public JoinDataComplete HoldCallsStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 221, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "Holds Call at specified index. FB reported on Call Status XSIG", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ResumeCallsStart")] + public JoinDataComplete ResumeCallsStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 231, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "Resume Call at specified index", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("MultiSiteOptionIsEnabled")] + public JoinDataComplete MultiSiteOptionIsEnabled = new JoinDataComplete( + new JoinData + { + JoinNumber = 301, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Multi site option is enabled FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("AutoAnswerEnabled")] + public JoinDataComplete AutoAnswerEnabled = new JoinDataComplete( + new JoinData + { + JoinNumber = 302, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Auto Answer is enabled FB", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ParticipantAudioMuteToggleStart")] + public JoinDataComplete ParticipantAudioMuteToggleStart = new JoinDataComplete( new JoinData { JoinNumber = 501, JoinSpan = 50 }, - new JoinMetadata - { - Description = "Toggles the participant's audio mute status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); + new JoinMetadata + { + Description = "Toggles the participant's audio mute status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); - [JoinName("ParticipantVideoMuteToggleStart")] - public JoinDataComplete ParticipantVideoMuteToggleStart = new JoinDataComplete( + [JoinName("ParticipantVideoMuteToggleStart")] + public JoinDataComplete ParticipantVideoMuteToggleStart = new JoinDataComplete( new JoinData { JoinNumber = 801, JoinSpan = 50 }, - new JoinMetadata - { - Description = "Toggles the participant's video mute status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); + new JoinMetadata + { + Description = "Toggles the participant's video mute status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); - [JoinName("ParticipantPinToggleStart")] - public JoinDataComplete ParticipantPinToggleStart = new JoinDataComplete( + [JoinName("ParticipantPinToggleStart")] + public JoinDataComplete ParticipantPinToggleStart = new JoinDataComplete( new JoinData { JoinNumber = 1101, JoinSpan = 50 }, - new JoinMetadata - { - Description = "Toggles the participant's pin status", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); + new JoinMetadata + { + Description = "Toggles the participant's pin status", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); #endregion @@ -1135,49 +1135,49 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced #region Analog - // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set - [JoinName("MeetingsToDisplay")] - public JoinDataComplete MeetingsToDisplay = new JoinDataComplete( - new JoinData - { - JoinNumber = 40, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Set/FB the number of meetings to display via the bridge xsig; default: 3 meetings.", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("SelectCall")] - public JoinDataComplete SelectCall = new JoinDataComplete( - new JoinData - { - JoinNumber = 24, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Sets the selected Call for DTMF commands. Valid values 1-8", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - - [JoinName("ConnectedCallCount")] - public JoinDataComplete ConnectedCallCount = new JoinDataComplete( - new JoinData - { - JoinNumber = 25, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Reports the number of currently connected calls", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); + // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set + [JoinName("MeetingsToDisplay")] + public JoinDataComplete MeetingsToDisplay = new JoinDataComplete( + new JoinData + { + JoinNumber = 40, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Set/FB the number of meetings to display via the bridge xsig; default: 3 meetings.", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("SelectCall")] + public JoinDataComplete SelectCall = new JoinDataComplete( + new JoinData + { + JoinNumber = 24, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Sets the selected Call for DTMF commands. Valid values 1-8", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + + [JoinName("ConnectedCallCount")] + public JoinDataComplete ConnectedCallCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 25, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reports the number of currently connected calls", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); [JoinName("MinutesBeforeMeetingStart")] public JoinDataComplete MinutesBeforeMeetingStart = new JoinDataComplete( @@ -1207,19 +1207,19 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Analog }); - [JoinName("CameraCount")] - public JoinDataComplete CameraCount = new JoinDataComplete( - new JoinData - { - JoinNumber = 61, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Reports the number of cameras", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); + [JoinName("CameraCount")] + public JoinDataComplete CameraCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 61, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reports the number of cameras", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); [JoinName("DirectoryRowCount")] public JoinDataComplete DirectoryRowCount = new JoinDataComplete( @@ -1250,47 +1250,47 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced }); - [JoinName("SelectedContactMethodCount")] - public JoinDataComplete SelectedContactMethodCount = new JoinDataComplete( - new JoinData - { - JoinNumber = 102, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Reports the number of contact methods for the selected contact", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("SelectContactMethod")] - public JoinDataComplete SelectContactMethod = new JoinDataComplete( - new JoinData - { - JoinNumber = 103, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Selects a contact method by index", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("DirectorySelectRowFeedback")] - public JoinDataComplete DirectorySelectRowFeedback = new JoinDataComplete( - new JoinData - { - JoinNumber = 104, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Directory Select Row and Feedback", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); + [JoinName("SelectedContactMethodCount")] + public JoinDataComplete SelectedContactMethodCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 102, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Reports the number of contact methods for the selected contact", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("SelectContactMethod")] + public JoinDataComplete SelectContactMethod = new JoinDataComplete( + new JoinData + { + JoinNumber = 103, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selects a contact method by index", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("DirectorySelectRowFeedback")] + public JoinDataComplete DirectorySelectRowFeedback = new JoinDataComplete( + new JoinData + { + JoinNumber = 104, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Directory Select Row and Feedback", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); @@ -1308,19 +1308,19 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Analog }); - [JoinName("FarEndPresetSelect")] - public JoinDataComplete FarEndPresetSelect = new JoinDataComplete( - new JoinData - { - JoinNumber = 122, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Far End Preset Preset Select", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); + [JoinName("FarEndPresetSelect")] + public JoinDataComplete FarEndPresetSelect = new JoinDataComplete( + new JoinData + { + JoinNumber = 122, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Far End Preset Preset Select", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); [JoinName("ParticipantCount")] public JoinDataComplete ParticipantCount = new JoinDataComplete( @@ -1364,47 +1364,47 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Analog }); - [JoinName("SelectRecentCallItem")] - public JoinDataComplete SelectRecentCallItem = new JoinDataComplete( - new JoinData - { - JoinNumber = 180, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Select/FB for Recent Call Item. Valid values 1 - 10", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("RecentCallOccurrenceType")] - public JoinDataComplete RecentCallOccurrenceType = new JoinDataComplete( - new JoinData - { - JoinNumber = 181, - JoinSpan = 10 - }, - new JoinMetadata - { - Description = "Recent Call Occurrence Type. [0-3] 0 = Unknown, 1 = Placed, 2 = Received, 3 = NoAnswer", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("RecentCallCount")] - public JoinDataComplete RecentCallCount = new JoinDataComplete( - new JoinData - { - JoinNumber = 191, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Recent Call Count", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); + [JoinName("SelectRecentCallItem")] + public JoinDataComplete SelectRecentCallItem = new JoinDataComplete( + new JoinData + { + JoinNumber = 180, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Select/FB for Recent Call Item. Valid values 1 - 10", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("RecentCallOccurrenceType")] + public JoinDataComplete RecentCallOccurrenceType = new JoinDataComplete( + new JoinData + { + JoinNumber = 181, + JoinSpan = 10 + }, + new JoinMetadata + { + Description = "Recent Call Occurrence Type. [0-3] 0 = Unknown, 1 = Placed, 2 = Received, 3 = NoAnswer", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("RecentCallCount")] + public JoinDataComplete RecentCallCount = new JoinDataComplete( + new JoinData + { + JoinNumber = 191, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Recent Call Count", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); #endregion @@ -1426,7 +1426,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Serial }); - [JoinName("PhoneDialString")] + [JoinName("PhoneDialString")] public JoinDataComplete PhoneDialString = new JoinDataComplete( new JoinData { @@ -1440,7 +1440,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Serial }); - [JoinName("CurrentCallData")] + [JoinName("CurrentCallData")] public JoinDataComplete CurrentCallData = new JoinDataComplete( new JoinData { @@ -1539,19 +1539,19 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Serial }); - [JoinName("ContactMethods")] - public JoinDataComplete ContactMethods = new JoinDataComplete( - new JoinData - { - JoinNumber = 103, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Contact Methods - XSig, 10 entries", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); + [JoinName("ContactMethods")] + public JoinDataComplete ContactMethods = new JoinDataComplete( + new JoinData + { + JoinNumber = 103, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Contact Methods - XSig, 10 entries", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); [JoinName("CameraPresetNames")] public JoinDataComplete CameraPresetNames = new JoinDataComplete( @@ -1567,7 +1567,7 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Serial }); - [JoinName("CurrentLayoutStringFb")] + [JoinName("CurrentLayoutStringFb")] public JoinDataComplete CurrentLayoutStringFb = new JoinDataComplete( new JoinData { @@ -1581,33 +1581,33 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Serial }); - [JoinName("AvailableLayoutsFb")] - public JoinDataComplete AvailableLayoutsFb = new JoinDataComplete( - new JoinData - { - JoinNumber = 142, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "xSig of all available layouts", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SelectLayout")] - public JoinDataComplete SelectLayout = new JoinDataComplete( - new JoinData - { - JoinNumber = 142, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Select Layout by string", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); + [JoinName("AvailableLayoutsFb")] + public JoinDataComplete AvailableLayoutsFb = new JoinDataComplete( + new JoinData + { + JoinNumber = 142, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "xSig of all available layouts", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SelectLayout")] + public JoinDataComplete SelectLayout = new JoinDataComplete( + new JoinData + { + JoinNumber = 142, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Select Layout by string", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); @@ -1625,75 +1625,75 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Serial }); - [JoinName("CameraNamesFb")] - public JoinDataComplete CameraNamesFb = new JoinDataComplete( - new JoinData - { - JoinNumber = 161, - JoinSpan = 10 - }, - new JoinMetadata - { - Description = "Camera Name Fb", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SelectedRecentCallName")] - public JoinDataComplete SelectedRecentCallName = new JoinDataComplete( - new JoinData - { - JoinNumber = 171, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Selected Recent Call Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SelectedRecentCallNumber")] - public JoinDataComplete SelectedRecentCallNumber = new JoinDataComplete( - new JoinData - { - JoinNumber = 172, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Selected Recent Call Number", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("RecentCallNamesStart")] - public JoinDataComplete RecentCallNamesStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 181, - JoinSpan = 10 - }, - new JoinMetadata - { - Description = "Recent Call Names", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("RecentCallTimesStart")] - public JoinDataComplete RecentCallTimesStart = new JoinDataComplete( - new JoinData - { - JoinNumber = 191, - JoinSpan = 10 - }, - new JoinMetadata - { - Description = "Recent Calls Times", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); + [JoinName("CameraNamesFb")] + public JoinDataComplete CameraNamesFb = new JoinDataComplete( + new JoinData + { + JoinNumber = 161, + JoinSpan = 10 + }, + new JoinMetadata + { + Description = "Camera Name Fb", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SelectedRecentCallName")] + public JoinDataComplete SelectedRecentCallName = new JoinDataComplete( + new JoinData + { + JoinNumber = 171, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Recent Call Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SelectedRecentCallNumber")] + public JoinDataComplete SelectedRecentCallNumber = new JoinDataComplete( + new JoinData + { + JoinNumber = 172, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Selected Recent Call Number", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("RecentCallNamesStart")] + public JoinDataComplete RecentCallNamesStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 181, + JoinSpan = 10 + }, + new JoinMetadata + { + Description = "Recent Call Names", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("RecentCallTimesStart")] + public JoinDataComplete RecentCallTimesStart = new JoinDataComplete( + new JoinData + { + JoinNumber = 191, + JoinSpan = 10 + }, + new JoinMetadata + { + Description = "Recent Calls Times", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); [JoinName("CurrentSource")] public JoinDataComplete CurrentSource = new JoinDataComplete( @@ -1723,75 +1723,75 @@ public class VideoCodecControllerJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Serial }); - [JoinName("DeviceIpAddresss")] - public JoinDataComplete DeviceIpAddresss = new JoinDataComplete( - new JoinData - { - JoinNumber = 301, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "IP Address of device", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SipPhoneNumber")] - public JoinDataComplete SipPhoneNumber = new JoinDataComplete( - new JoinData - { - JoinNumber = 302, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "SIP phone number of device", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("E164Alias")] - public JoinDataComplete E164Alias = new JoinDataComplete( - new JoinData - { - JoinNumber = 303, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "E164 alias of device", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("H323Id")] - public JoinDataComplete H323Id = new JoinDataComplete( - new JoinData - { - JoinNumber = 304, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "H323 ID of device", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SipUri")] - public JoinDataComplete SipUri = new JoinDataComplete( - new JoinData - { - JoinNumber = 305, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "SIP URI of device", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); + [JoinName("DeviceIpAddresss")] + public JoinDataComplete DeviceIpAddresss = new JoinDataComplete( + new JoinData + { + JoinNumber = 301, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "IP Address of device", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SipPhoneNumber")] + public JoinDataComplete SipPhoneNumber = new JoinDataComplete( + new JoinData + { + JoinNumber = 302, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "SIP phone number of device", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("E164Alias")] + public JoinDataComplete E164Alias = new JoinDataComplete( + new JoinData + { + JoinNumber = 303, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "E164 alias of device", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("H323Id")] + public JoinDataComplete H323Id = new JoinDataComplete( + new JoinData + { + JoinNumber = 304, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "H323 ID of device", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SipUri")] + public JoinDataComplete SipUri = new JoinDataComplete( + new JoinData + { + JoinNumber = 305, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "SIP URI of device", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); [JoinName("DirectoryEntrySelectedName")] public JoinDataComplete DirectoryEntrySelectedName = new JoinDataComplete( @@ -1848,4 +1848,3 @@ public VideoCodecControllerJoinMap(uint joinStart, Type type) { } } -} diff --git a/src/PepperDash.Essentials.Core/Comm and IR/CecPortController.cs b/src/PepperDash.Essentials.Core/Comm and IR/CecPortController.cs index 544a682f9..0c053d6b5 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/CecPortController.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/CecPortController.cs @@ -10,117 +10,116 @@ using PepperDash.Core; using Serilog.Events; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public class CecPortController : Device, IBasicCommunicationWithStreamDebugging - { +{ public CommunicationStreamDebugging StreamDebugging { get; private set; } - public event EventHandler BytesReceived; - public event EventHandler TextReceived; + public event EventHandler BytesReceived; + public event EventHandler TextReceived; - public bool IsConnected { get { return true; } } + public bool IsConnected { get { return true; } } - ICec Port; + ICec Port; - public CecPortController(string key, Func postActivationFunc, - EssentialsControlPropertiesConfig config):base(key) - { + public CecPortController(string key, Func postActivationFunc, + EssentialsControlPropertiesConfig config):base(key) + { StreamDebugging = new CommunicationStreamDebugging(key); - AddPostActivationAction(() => - { - Port = postActivationFunc(config); + AddPostActivationAction(() => + { + Port = postActivationFunc(config); - Port.StreamCec.CecChange += StreamCec_CecChange; - }); - } + Port.StreamCec.CecChange += StreamCec_CecChange; + }); + } - public CecPortController(string key, ICec port) - : base(key) - { - Port = port; + public CecPortController(string key, ICec port) + : base(key) + { + Port = port; - Port.StreamCec.CecChange += new CecChangeEventHandler(StreamCec_CecChange); - } + Port.StreamCec.CecChange += new CecChangeEventHandler(StreamCec_CecChange); + } - void StreamCec_CecChange(Cec cecDevice, CecEventArgs args) - { - if (args.EventId == CecEventIds.CecMessageReceivedEventId) - OnDataReceived(cecDevice.Received.StringValue); - else if (args.EventId == CecEventIds.ErrorFeedbackEventId) - if(cecDevice.ErrorFeedback.BoolValue) - Debug.LogMessage(LogEventLevel.Verbose, this, "CEC NAK Error"); - } + void StreamCec_CecChange(Cec cecDevice, CecEventArgs args) + { + if (args.EventId == CecEventIds.CecMessageReceivedEventId) + OnDataReceived(cecDevice.Received.StringValue); + else if (args.EventId == CecEventIds.ErrorFeedbackEventId) + if(cecDevice.ErrorFeedback.BoolValue) + Debug.LogMessage(LogEventLevel.Verbose, this, "CEC NAK Error"); + } - void OnDataReceived(string s) - { + void OnDataReceived(string s) + { var bytesHandler = BytesReceived; - if (bytesHandler != null) - { - var bytes = Encoding.GetEncoding(28591).GetBytes(s); + if (bytesHandler != null) + { + var bytes = Encoding.GetEncoding(28591).GetBytes(s); if (StreamDebugging.RxStreamDebuggingIsEnabled) Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", ComTextHelper.GetEscapedText(bytes)); - bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); - } - var textHandler = TextReceived; + bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); + } + var textHandler = TextReceived; if (textHandler != null) { if (StreamDebugging.RxStreamDebuggingIsEnabled) Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", s); textHandler(this, new GenericCommMethodReceiveTextArgs(s)); } - } + } - #region IBasicCommunication Members + #region IBasicCommunication Members - public void SendText(string text) - { - if (Port == null) - return; + public void SendText(string text) + { + if (Port == null) + return; if (StreamDebugging.TxStreamDebuggingIsEnabled) Debug.LogMessage(LogEventLevel.Information, this, "Sending {0} characters of text: '{1}'", text.Length, text); - Port.StreamCec.Send.StringValue = text; - } + Port.StreamCec.Send.StringValue = text; + } - public void SendBytes(byte[] bytes) - { - if (Port == null) - return; - var text = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); + public void SendBytes(byte[] bytes) + { + if (Port == null) + return; + var text = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); if (StreamDebugging.TxStreamDebuggingIsEnabled) Debug.LogMessage(LogEventLevel.Information, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); - Port.StreamCec.Send.StringValue = text; - } + Port.StreamCec.Send.StringValue = text; + } - public void Connect() - { - } + public void Connect() + { + } - public void Disconnect() - { - } + public void Disconnect() + { + } - #endregion + #endregion - /// - /// - /// - /// - public void SimulateReceive(string s) + /// + /// + /// + /// + public void SimulateReceive(string s) + { + // split out hex chars and build string + var split = Regex.Split(s, @"(\\[Xx][0-9a-fA-F][0-9a-fA-F])"); + StringBuilder b = new StringBuilder(); + foreach (var t in split) { - // split out hex chars and build string - var split = Regex.Split(s, @"(\\[Xx][0-9a-fA-F][0-9a-fA-F])"); - StringBuilder b = new StringBuilder(); - foreach (var t in split) - { - if (t.StartsWith(@"\") && t.Length == 4) - b.Append((char)(Convert.ToByte(t.Substring(2, 2), 16))); - else - b.Append(t); - } - - OnDataReceived(b.ToString()); + if (t.StartsWith(@"\") && t.Length == 4) + b.Append((char)(Convert.ToByte(t.Substring(2, 2), 16))); + else + b.Append(t); } + + OnDataReceived(b.ToString()); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs b/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs index 41420b7ca..a011e29cd 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs @@ -10,11 +10,11 @@ using Serilog.Events; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public class ComPortController : Device, IBasicCommunicationWithStreamDebugging { - public CommunicationStreamDebugging StreamDebugging { get; private set; } + public CommunicationStreamDebugging StreamDebugging { get; private set; } public event EventHandler BytesReceived; public event EventHandler TextReceived; @@ -27,16 +27,16 @@ public class ComPortController : Device, IBasicCommunicationWithStreamDebugging public ComPortController(string key, Func postActivationFunc, ComPort.ComPortSpec spec, EssentialsControlPropertiesConfig config) : base(key) { - StreamDebugging = new CommunicationStreamDebugging(key); + StreamDebugging = new CommunicationStreamDebugging(key); Spec = spec; - AddPostActivationAction(() => - { - Port = postActivationFunc(config); + AddPostActivationAction(() => + { + Port = postActivationFunc(config); - RegisterAndConfigureComPort(); - }); + RegisterAndConfigureComPort(); + }); } public ComPortController(string key, ComPort port, ComPort.ComPortSpec spec) @@ -62,15 +62,15 @@ private void RegisterAndConfigureComPort() Debug.LogMessage(LogEventLevel.Information, this, "Configured com Port for this device does not exist."); return; } - if (Port.Parent is CrestronControlSystem) + if (Port.Parent is CrestronControlSystem) + { + var result = Port.Register(); + if (result != eDeviceRegistrationUnRegistrationResponse.Success) { - var result = Port.Register(); - if (result != eDeviceRegistrationUnRegistrationResponse.Success) - { - Debug.LogMessage(LogEventLevel.Information, this, "ERROR: Cannot register Com port: {0}", result); - return; // false - } + Debug.LogMessage(LogEventLevel.Information, this, "ERROR: Cannot register Com port: {0}", result); + return; // false } + } var specResult = Port.SetComPortSpec(Spec); if (specResult != 0) @@ -88,33 +88,33 @@ private void RegisterAndConfigureComPort() void Port_SerialDataReceived(ComPort ReceivingComPort, ComPortSerialDataEventArgs args) { - OnDataReceived(args.SerialData); + OnDataReceived(args.SerialData); } - void OnDataReceived(string s) - { + void OnDataReceived(string s) + { var eventSubscribed = false; - var bytesHandler = BytesReceived; - if (bytesHandler != null) - { - var bytes = Encoding.GetEncoding(28591).GetBytes(s); + var bytesHandler = BytesReceived; + if (bytesHandler != null) + { + var bytes = Encoding.GetEncoding(28591).GetBytes(s); if (StreamDebugging.RxStreamDebuggingIsEnabled) Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", ComTextHelper.GetEscapedText(bytes)); - bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); + bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); eventSubscribed = true; - } - var textHandler = TextReceived; - if (textHandler != null) - { + } + var textHandler = TextReceived; + if (textHandler != null) + { if (StreamDebugging.RxStreamDebuggingIsEnabled) Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", s); - textHandler(this, new GenericCommMethodReceiveTextArgs(s)); + textHandler(this, new GenericCommMethodReceiveTextArgs(s)); eventSubscribed = true; - } + } if(!eventSubscribed) Debug.LogMessage(LogEventLevel.Warning, this, "Received data but no handler is registered"); - } + } public override bool Deactivate() { @@ -128,9 +128,9 @@ public void SendText(string text) if (Port == null) return; - if (StreamDebugging.TxStreamDebuggingIsEnabled) - Debug.LogMessage(LogEventLevel.Information, this, "Sending {0} characters of text: '{1}'", text.Length, text); - Port.Send(text); + if (StreamDebugging.TxStreamDebuggingIsEnabled) + Debug.LogMessage(LogEventLevel.Information, this, "Sending {0} characters of text: '{1}'", text.Length, text); + Port.Send(text); } public void SendBytes(byte[] bytes) @@ -138,8 +138,8 @@ public void SendBytes(byte[] bytes) if (Port == null) return; var text = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); - if (StreamDebugging.TxStreamDebuggingIsEnabled) - Debug.LogMessage(LogEventLevel.Information, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); + if (StreamDebugging.TxStreamDebuggingIsEnabled) + Debug.LogMessage(LogEventLevel.Information, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); Port.Send(text); } @@ -154,24 +154,23 @@ public void Disconnect() #endregion - /// - /// - /// - /// - public void SimulateReceive(string s) + /// + /// + /// + /// + public void SimulateReceive(string s) + { + // split out hex chars and build string + var split = Regex.Split(s, @"(\\[Xx][0-9a-fA-F][0-9a-fA-F])"); + StringBuilder b = new StringBuilder(); + foreach (var t in split) { - // split out hex chars and build string - var split = Regex.Split(s, @"(\\[Xx][0-9a-fA-F][0-9a-fA-F])"); - StringBuilder b = new StringBuilder(); - foreach (var t in split) - { - if (t.StartsWith(@"\") && t.Length == 4) - b.Append((char)(Convert.ToByte(t.Substring(2, 2), 16))); - else - b.Append(t); - } - - OnDataReceived(b.ToString()); + if (t.StartsWith(@"\") && t.Length == 4) + b.Append((char)(Convert.ToByte(t.Substring(2, 2), 16))); + else + b.Append(t); } - } -} \ No newline at end of file + + OnDataReceived(b.ToString()); + } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Comm and IR/ComSpecJsonConverter.cs b/src/PepperDash.Essentials.Core/Comm and IR/ComSpecJsonConverter.cs index bfdccb65d..6ef2f916b 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/ComSpecJsonConverter.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/ComSpecJsonConverter.cs @@ -13,92 +13,89 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// This converter creates a proper ComPort.ComPortSpec struct from more-friendly JSON values. It uses +/// ComSpecPropsJsonConverter to finish the individual properties. +/// +public class ComSpecJsonConverter : JsonConverter { - /// - /// This converter creates a proper ComPort.ComPortSpec struct from more-friendly JSON values. It uses - /// ComSpecPropsJsonConverter to finish the individual properties. - /// - public class ComSpecJsonConverter : JsonConverter + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - if (objectType == typeof(ComPort.ComPortSpec?)) - { - var newSer = new JsonSerializer(); - newSer.Converters.Add(new ComSpecPropsJsonConverter()); - newSer.ObjectCreationHandling = ObjectCreationHandling.Replace; - return newSer.Deserialize(reader); - } - return null; - } - - /// - /// - /// - public override bool CanConvert(Type objectType) + if (objectType == typeof(ComPort.ComPortSpec?)) { - return objectType == typeof(ComPort.ComPortSpec?); - } - - public override bool CanRead { get { return true; } } - - /// - /// This converter will not be used for writing - /// - public override bool CanWrite { get { return false; } } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - throw new NotImplementedException(); + var newSer = new JsonSerializer(); + newSer.Converters.Add(new ComSpecPropsJsonConverter()); + newSer.ObjectCreationHandling = ObjectCreationHandling.Replace; + return newSer.Deserialize(reader); } + return null; } /// - /// The gist of this converter: The comspec JSON comes in with normal values that need to be converted - /// into enum names. This converter takes the value and applies the appropriate enum's name prefix to the value - /// and then returns the enum value using Enum.Parse. NOTE: Does not write + /// /// - public class ComSpecPropsJsonConverter : JsonConverter + public override bool CanConvert(Type objectType) { - public override bool CanConvert(Type objectType) - { - return objectType == typeof(ComPort.eComBaudRates) - || objectType == typeof(ComPort.eComDataBits) - || objectType == typeof(ComPort.eComParityType) - || objectType == typeof(ComPort.eComHardwareHandshakeType) - || objectType == typeof(ComPort.eComSoftwareHandshakeType) - || objectType == typeof(ComPort.eComProtocolType) - || objectType == typeof(ComPort.eComStopBits); - } + return objectType == typeof(ComPort.ComPortSpec?); + } - public override bool CanRead { get { return true; } } + public override bool CanRead { get { return true; } } - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - //Debug.LogMessage(LogEventLevel.Verbose, "ReadJson type: " + objectType.Name); - if (objectType == typeof(ComPort.eComBaudRates)) - return Enum.Parse(typeof(ComPort.eComBaudRates), "ComspecBaudRate" + reader.Value, false); - else if (objectType == typeof(ComPort.eComDataBits)) - return Enum.Parse(typeof(ComPort.eComDataBits), "ComspecDataBits" + reader.Value, true); - else if (objectType == typeof(ComPort.eComHardwareHandshakeType)) - return Enum.Parse(typeof(ComPort.eComHardwareHandshakeType), "ComspecHardwareHandshake" + reader.Value, true); - else if (objectType == typeof(ComPort.eComParityType)) - return Enum.Parse(typeof(ComPort.eComParityType), "ComspecParity" + reader.Value, true); - else if (objectType == typeof(ComPort.eComProtocolType)) - return Enum.Parse(typeof(ComPort.eComProtocolType), "ComspecProtocol" + reader.Value, true); - else if (objectType == typeof(ComPort.eComSoftwareHandshakeType)) - return Enum.Parse(typeof(ComPort.eComSoftwareHandshakeType), "ComspecSoftwareHandshake" + reader.Value, true); - else if (objectType == typeof(ComPort.eComStopBits)) - return Enum.Parse(typeof(ComPort.eComStopBits), "ComspecStopBits" + reader.Value, true); - return null; - } + /// + /// This converter will not be used for writing + /// + public override bool CanWrite { get { return false; } } - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - throw new NotImplementedException(); - } + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException(); } +} +/// +/// The gist of this converter: The comspec JSON comes in with normal values that need to be converted +/// into enum names. This converter takes the value and applies the appropriate enum's name prefix to the value +/// and then returns the enum value using Enum.Parse. NOTE: Does not write +/// +public class ComSpecPropsJsonConverter : JsonConverter +{ + public override bool CanConvert(Type objectType) + { + return objectType == typeof(ComPort.eComBaudRates) + || objectType == typeof(ComPort.eComDataBits) + || objectType == typeof(ComPort.eComParityType) + || objectType == typeof(ComPort.eComHardwareHandshakeType) + || objectType == typeof(ComPort.eComSoftwareHandshakeType) + || objectType == typeof(ComPort.eComProtocolType) + || objectType == typeof(ComPort.eComStopBits); + } + + public override bool CanRead { get { return true; } } + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + //Debug.LogMessage(LogEventLevel.Verbose, "ReadJson type: " + objectType.Name); + if (objectType == typeof(ComPort.eComBaudRates)) + return Enum.Parse(typeof(ComPort.eComBaudRates), "ComspecBaudRate" + reader.Value, false); + else if (objectType == typeof(ComPort.eComDataBits)) + return Enum.Parse(typeof(ComPort.eComDataBits), "ComspecDataBits" + reader.Value, true); + else if (objectType == typeof(ComPort.eComHardwareHandshakeType)) + return Enum.Parse(typeof(ComPort.eComHardwareHandshakeType), "ComspecHardwareHandshake" + reader.Value, true); + else if (objectType == typeof(ComPort.eComParityType)) + return Enum.Parse(typeof(ComPort.eComParityType), "ComspecParity" + reader.Value, true); + else if (objectType == typeof(ComPort.eComProtocolType)) + return Enum.Parse(typeof(ComPort.eComProtocolType), "ComspecProtocol" + reader.Value, true); + else if (objectType == typeof(ComPort.eComSoftwareHandshakeType)) + return Enum.Parse(typeof(ComPort.eComSoftwareHandshakeType), "ComspecSoftwareHandshake" + reader.Value, true); + else if (objectType == typeof(ComPort.eComStopBits)) + return Enum.Parse(typeof(ComPort.eComStopBits), "ComspecStopBits" + reader.Value, true); + return null; + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Comm and IR/CommFactory.cs b/src/PepperDash.Essentials.Core/Comm and IR/CommFactory.cs index 8fa4076a9..7a41ed8ee 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/CommFactory.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/CommFactory.cs @@ -10,8 +10,8 @@ using PepperDash.Essentials.Core.Config; using Serilog.Events; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// /// @@ -53,35 +53,35 @@ public static IBasicCommunication CreateCommForDevice(DeviceConfig deviceConfig) case eControlMethod.Com: comm = new ComPortController(deviceConfig.Key + "-com", GetComPort, controlConfig.ComParams.Value, controlConfig); break; - case eControlMethod.Cec: - comm = new CecPortController(deviceConfig.Key + "-cec", GetCecPort, controlConfig); - break; + case eControlMethod.Cec: + comm = new CecPortController(deviceConfig.Key + "-cec", GetCecPort, controlConfig); + break; case eControlMethod.IR: break; - case eControlMethod.Ssh: - { - var ssh = new GenericSshClient(deviceConfig.Key + "-ssh", c.Address, c.Port, c.Username, c.Password); - ssh.AutoReconnect = c.AutoReconnect; - if(ssh.AutoReconnect) - ssh.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs; - comm = ssh; - break; - } - case eControlMethod.Tcpip: - { - var tcp = new GenericTcpIpClient(deviceConfig.Key + "-tcp", c.Address, c.Port, c.BufferSize); - tcp.AutoReconnect = c.AutoReconnect; - if (tcp.AutoReconnect) - tcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs; - comm = tcp; - break; - } - case eControlMethod.Udp: - { - var udp = new GenericUdpServer(deviceConfig.Key + "-udp", c.Address, c.Port, c.BufferSize); - comm = udp; - break; - } + case eControlMethod.Ssh: + { + var ssh = new GenericSshClient(deviceConfig.Key + "-ssh", c.Address, c.Port, c.Username, c.Password); + ssh.AutoReconnect = c.AutoReconnect; + if(ssh.AutoReconnect) + ssh.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs; + comm = ssh; + break; + } + case eControlMethod.Tcpip: + { + var tcp = new GenericTcpIpClient(deviceConfig.Key + "-tcp", c.Address, c.Port, c.BufferSize); + tcp.AutoReconnect = c.AutoReconnect; + if (tcp.AutoReconnect) + tcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs; + comm = tcp; + break; + } + case eControlMethod.Udp: + { + var udp = new GenericUdpServer(deviceConfig.Key + "-udp", c.Address, c.Port, c.BufferSize); + comm = udp; + break; + } case eControlMethod.Telnet: break; case eControlMethod.SecureTcpIp: @@ -120,13 +120,13 @@ public static ComPort GetComPort(EssentialsControlPropertiesConfig config) return null; } - /// - /// Gets an ICec port from a RoutingInput or RoutingOutput on a device - /// - /// - /// - public static ICec GetCecPort(ControlPropertiesConfig config) - { + /// + /// Gets an ICec port from a RoutingInput or RoutingOutput on a device + /// + /// + /// + public static ICec GetCecPort(ControlPropertiesConfig config) + { try { var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey); @@ -175,7 +175,7 @@ public static ICec GetCecPort(ControlPropertiesConfig config) config.ControlPortDevKey, config.ControlPortName); return null; - } + } /// /// Helper to grab the IComPorts device for this PortDeviceKey. Key "controlSystem" will @@ -198,66 +198,65 @@ public static IComPorts GetIComPortsDeviceFromManagedDevice(string ComPortDevKey } } - /// - /// - /// - public class EssentialsControlPropertiesConfig : - ControlPropertiesConfig - { +/// +/// +/// +public class EssentialsControlPropertiesConfig : + ControlPropertiesConfig +{ - [JsonProperty("comParams", NullValueHandling = NullValueHandling.Ignore)] - [JsonConverter(typeof(ComSpecJsonConverter))] - public ComPort.ComPortSpec? ComParams { get; set; } + [JsonProperty("comParams", NullValueHandling = NullValueHandling.Ignore)] + [JsonConverter(typeof(ComSpecJsonConverter))] + public ComPort.ComPortSpec? ComParams { get; set; } - [JsonProperty("cresnetId", NullValueHandling = NullValueHandling.Ignore)] - public string CresnetId { get; set; } + [JsonProperty("cresnetId", NullValueHandling = NullValueHandling.Ignore)] + public string CresnetId { get; set; } - /// - /// Attempts to provide uint conversion of string CresnetId - /// - [JsonIgnore] - public uint CresnetIdInt + /// + /// Attempts to provide uint conversion of string CresnetId + /// + [JsonIgnore] + public uint CresnetIdInt + { + get { - get + try { - try - { - return Convert.ToUInt32(CresnetId, 16); - } - catch (Exception) - { - throw new FormatException(string.Format("ERROR:Unable to convert Cresnet ID: {0} to hex. Error:\n{1}", CresnetId)); - } + return Convert.ToUInt32(CresnetId, 16); + } + catch (Exception) + { + throw new FormatException(string.Format("ERROR:Unable to convert Cresnet ID: {0} to hex. Error:\n{1}", CresnetId)); } } + } - [JsonProperty("infinetId", NullValueHandling = NullValueHandling.Ignore)] - public string InfinetId { get; set; } + [JsonProperty("infinetId", NullValueHandling = NullValueHandling.Ignore)] + public string InfinetId { get; set; } - /// - /// Attepmts to provide uiont conversion of string InifinetId - /// - [JsonIgnore] - public uint InfinetIdInt + /// + /// Attepmts to provide uiont conversion of string InifinetId + /// + [JsonIgnore] + public uint InfinetIdInt + { + get { - get + try + { + return Convert.ToUInt32(InfinetId, 16); + } + catch (Exception) { - try - { - return Convert.ToUInt32(InfinetId, 16); - } - catch (Exception) - { - throw new FormatException(string.Format("ERROR:Unable to conver Infinet ID: {0} to hex. Error:\n{1}", InfinetId)); - } + throw new FormatException(string.Format("ERROR:Unable to conver Infinet ID: {0} to hex. Error:\n{1}", InfinetId)); } } } +} - public class IrControlSpec - { - public string PortDeviceKey { get; set; } - public uint PortNumber { get; set; } - public string File { get; set; } - } +public class IrControlSpec +{ + public string PortDeviceKey { get; set; } + public uint PortNumber { get; set; } + public string File { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Comm and IR/CommunicationExtras.cs b/src/PepperDash.Essentials.Core/Comm and IR/CommunicationExtras.cs index 995004b96..e335157fa 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/CommunicationExtras.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/CommunicationExtras.cs @@ -13,13 +13,12 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// /// public interface IComPortsDevice { IComPorts Device { get; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Comm and IR/ConsoleCommMockDevice.cs b/src/PepperDash.Essentials.Core/Comm and IR/ConsoleCommMockDevice.cs index fd7184aa5..3960d38b3 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/ConsoleCommMockDevice.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/ConsoleCommMockDevice.cs @@ -9,8 +9,8 @@ using Serilog.Events; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public class ConsoleCommMockDevice : EssentialsDevice, ICommunicationMonitor { public IBasicCommunication Communication { get; private set; } @@ -67,21 +67,19 @@ public ConsoleCommMockDevicePropertiesConfig() } } - public class ConsoleCommMockDeviceFactory : EssentialsDeviceFactory +public class ConsoleCommMockDeviceFactory : EssentialsDeviceFactory +{ + public ConsoleCommMockDeviceFactory() { - public ConsoleCommMockDeviceFactory() - { - TypeNames = new List() { "commmock" }; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Comm Mock Device"); - var comm = CommFactory.CreateCommForDevice(dc); - var props = Newtonsoft.Json.JsonConvert.DeserializeObject( - dc.Properties.ToString()); - return new ConsoleCommMockDevice(dc.Key, dc.Name, props, comm); - } + TypeNames = new List() { "commmock" }; } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Comm Mock Device"); + var comm = CommFactory.CreateCommForDevice(dc); + var props = Newtonsoft.Json.JsonConvert.DeserializeObject( + dc.Properties.ToString()); + return new ConsoleCommMockDevice(dc.Key, dc.Name, props, comm); + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Comm and IR/GenericComm.cs b/src/PepperDash.Essentials.Core/Comm and IR/GenericComm.cs index ddd7ec5df..6e913968a 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/GenericComm.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/GenericComm.cs @@ -13,133 +13,132 @@ using Serilog.Events; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Serves as a generic wrapper class for all styles of IBasicCommuncation ports +/// +[Description("Generic communication wrapper class for any IBasicCommunication type")] +public class GenericComm : ReconfigurableBridgableDevice { - /// - /// Serves as a generic wrapper class for all styles of IBasicCommuncation ports - /// - [Description("Generic communication wrapper class for any IBasicCommunication type")] - public class GenericComm : ReconfigurableBridgableDevice + EssentialsControlPropertiesConfig PropertiesConfig; + + public IBasicCommunication CommPort { get; private set; } + + public GenericComm(DeviceConfig config) + : base(config) { - EssentialsControlPropertiesConfig PropertiesConfig; - public IBasicCommunication CommPort { get; private set; } + PropertiesConfig = CommFactory.GetControlPropertiesConfig(config); - public GenericComm(DeviceConfig config) - : base(config) - { + var commPort = CommFactory.CreateCommForDevice(config); - PropertiesConfig = CommFactory.GetControlPropertiesConfig(config); + //Fixing decision to require '-comPorts' in delcaration for DGE in order to get a device with comports included + if (commPort == null) + { + config.Key = config.Key + "-comPorts"; + commPort = CommFactory.CreateCommForDevice(config); + } - var commPort = CommFactory.CreateCommForDevice(config); + CommPort = commPort; - //Fixing decision to require '-comPorts' in delcaration for DGE in order to get a device with comports included - if (commPort == null) - { - config.Key = config.Key + "-comPorts"; - commPort = CommFactory.CreateCommForDevice(config); - } + } - CommPort = commPort; + public static IKeyed BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Comm Device"); + return new GenericComm(dc); + } + public void SetPortConfig(string portConfig) + { + // TODO: Deserialize new EssentialsControlPropertiesConfig and handle as necessary + try + { + PropertiesConfig = JsonConvert.DeserializeObject + (portConfig); } - - public static IKeyed BuildDevice(DeviceConfig dc) + catch (Exception e) { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Comm Device"); - return new GenericComm(dc); + Debug.LogMessage(LogEventLevel.Verbose, this, "Error deserializing port config: {0}", e); } + } + + protected override void CustomSetConfig(DeviceConfig config) + { + PropertiesConfig = CommFactory.GetControlPropertiesConfig(config); - public void SetPortConfig(string portConfig) + ConfigWriter.UpdateDeviceConfig(config); + } + + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new IBasicCommunicationJoinMap(joinStart); + + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + if (bridge != null) { - // TODO: Deserialize new EssentialsControlPropertiesConfig and handle as necessary - try - { - PropertiesConfig = JsonConvert.DeserializeObject - (portConfig); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Error deserializing port config: {0}", e); - } + bridge.AddJoinMap(Key, joinMap); } - - protected override void CustomSetConfig(DeviceConfig config) + else { - PropertiesConfig = CommFactory.GetControlPropertiesConfig(config); + Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } - ConfigWriter.UpdateDeviceConfig(config); + if (CommPort == null) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. CommPort is null", Key); + return; } - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + + // this is a permanent event handler. This cannot be -= from event + CommPort.TextReceived += (s, a) => { - var joinMap = new IBasicCommunicationJoinMap(joinStart); + trilist.SetString(joinMap.TextReceived.JoinNumber, a.Text); + }; + trilist.SetStringSigAction(joinMap.SendText.JoinNumber, s => CommPort.SendText(s)); + trilist.SetStringSigAction(joinMap.SetPortConfig.JoinNumber, SetPortConfig); - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - if (!string.IsNullOrEmpty(joinMapSerialized)) - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + var sComm = CommPort as ISocketStatus; + if (sComm == null) return; + sComm.ConnectionChange += (s, a) => + { + trilist.SetUshort(joinMap.Status.JoinNumber, (ushort)(a.Client.ClientStatus)); + trilist.SetBool(joinMap.Connected.JoinNumber, a.Client.ClientStatus == + SocketStatus.SOCKET_STATUS_CONNECTED); + }; - if (bridge != null) + trilist.SetBoolSigAction(joinMap.Connect.JoinNumber, b => + { + if (b) { - bridge.AddJoinMap(Key, joinMap); + sComm.Connect(); } else { - Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + sComm.Disconnect(); } - - if (CommPort == null) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. CommPort is null", Key); - return; - } - - Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - - // this is a permanent event handler. This cannot be -= from event - CommPort.TextReceived += (s, a) => - { - trilist.SetString(joinMap.TextReceived.JoinNumber, a.Text); - }; - trilist.SetStringSigAction(joinMap.SendText.JoinNumber, s => CommPort.SendText(s)); - trilist.SetStringSigAction(joinMap.SetPortConfig.JoinNumber, SetPortConfig); - - - var sComm = CommPort as ISocketStatus; - if (sComm == null) return; - sComm.ConnectionChange += (s, a) => - { - trilist.SetUshort(joinMap.Status.JoinNumber, (ushort)(a.Client.ClientStatus)); - trilist.SetBool(joinMap.Connected.JoinNumber, a.Client.ClientStatus == - SocketStatus.SOCKET_STATUS_CONNECTED); - }; - - trilist.SetBoolSigAction(joinMap.Connect.JoinNumber, b => - { - if (b) - { - sComm.Connect(); - } - else - { - sComm.Disconnect(); - } - }); - } + }); } +} - public class GenericCommFactory : EssentialsDeviceFactory +public class GenericCommFactory : EssentialsDeviceFactory +{ + public GenericCommFactory() { - public GenericCommFactory() - { - TypeNames = new List() { "genericComm" }; - } + TypeNames = new List() { "genericComm" }; + } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Comm Device"); - return new GenericComm(dc); - } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Comm Device"); + return new GenericComm(dc); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Comm and IR/GenericHttpClient.cs b/src/PepperDash.Essentials.Core/Comm and IR/GenericHttpClient.cs index d88e9728e..3fa521625 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/GenericHttpClient.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/GenericHttpClient.cs @@ -2,9 +2,9 @@ using PepperDash.Core; using System; -namespace PepperDash.Essentials.Core -{ - [Obsolete("Please use the builtin HttpClient class instead: https://learn.microsoft.com/en-us/dotnet/fundamentals/networking/http/httpclient-guidelines")] +namespace PepperDash.Essentials.Core; + +[Obsolete("Please use the builtin HttpClient class instead: https://learn.microsoft.com/en-us/dotnet/fundamentals/networking/http/httpclient-guidelines")] public class GenericHttpClient : Device, IBasicCommunication { private readonly HttpClient Client; @@ -13,13 +13,13 @@ public class GenericHttpClient : Device, IBasicCommunication public GenericHttpClient(string key, string name, string hostname) : base(key, name) { - Client = new HttpClient - { - HostName = hostname - }; + Client = new HttpClient + { + HostName = hostname + }; - } + } /// /// @@ -56,8 +56,8 @@ private void Response(HttpClientResponse response, HTTP_CALLBACK_ERROR error, ob if (responseReceived.ContentString.Length > 0) { - ResponseRecived?.Invoke(this, new GenericHttpClientEventArgs(responseReceived.ContentString, (request as HttpClientRequest).Url.ToString(), error)); - } + ResponseRecived?.Invoke(this, new GenericHttpClientEventArgs(responseReceived.ContentString, (request as HttpClientRequest).Url.ToString(), error)); + } } } @@ -108,5 +108,4 @@ public GenericHttpClientEventArgs(string response, string request, HTTP_CALLBACK RequestPath = request; Error = error; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Comm and IR/IRPortHelper.cs b/src/PepperDash.Essentials.Core/Comm and IR/IRPortHelper.cs index 498df9d25..52474d420 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/IRPortHelper.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/IRPortHelper.cs @@ -12,8 +12,8 @@ using PepperDash.Essentials.Core.Config; using Serilog.Events; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// /// @@ -137,89 +137,89 @@ public static IROutputPort GetIrOutputPort(DeviceConfig dc) var port = irDev.IROutputPorts[portNum]; - + return port; } public static IrOutputPortController GetIrOutputPortController(DeviceConfig config) { - Debug.LogMessage(LogEventLevel.Debug, "Attempting to create new Ir Port Controller"); + Debug.LogMessage(LogEventLevel.Debug, "Attempting to create new Ir Port Controller"); if (config == null) { return null; } - var postActivationFunc = new Func (GetIrOutputPort); + var postActivationFunc = new Func (GetIrOutputPort); var irDevice = new IrOutputPortController(config.Key + "-ir", postActivationFunc, config); return irDevice; } /* - /// - /// Returns a ready-to-go IrOutputPortController from a DeviceConfig object. - /// - public static IrOutputPortController GetIrOutputPortController(DeviceConfig devConf) + /// + /// Returns a ready-to-go IrOutputPortController from a DeviceConfig object. + /// + public static IrOutputPortController GetIrOutputPortController(DeviceConfig devConf) + { + var irControllerKey = devConf.Key + "-ir"; + if (devConf.Properties == null) + { + Debug.LogMessage(LogEventLevel.Information, "[{0}] WARNING: Device config does not include properties. IR will not function.", devConf.Key); + return new IrOutputPortController(irControllerKey, null, ""); + } + + var control = devConf.Properties["control"]; + if (control == null) + { + var c = new IrOutputPortController(irControllerKey, null, ""); + Debug.LogMessage(LogEventLevel.Information, c, "WARNING: Device config does not include control properties. IR will not function"); + return c; + } + + var portDevKey = control.Value("controlPortDevKey"); + var portNum = control.Value("controlPortNumber"); + IIROutputPorts irDev = null; + + if (portDevKey == null) { - var irControllerKey = devConf.Key + "-ir"; - if (devConf.Properties == null) - { - Debug.LogMessage(LogEventLevel.Information, "[{0}] WARNING: Device config does not include properties. IR will not function.", devConf.Key); - return new IrOutputPortController(irControllerKey, null, ""); - } - - var control = devConf.Properties["control"]; - if (control == null) - { - var c = new IrOutputPortController(irControllerKey, null, ""); - Debug.LogMessage(LogEventLevel.Information, c, "WARNING: Device config does not include control properties. IR will not function"); - return c; - } - - var portDevKey = control.Value("controlPortDevKey"); - var portNum = control.Value("controlPortNumber"); - IIROutputPorts irDev = null; - - if (portDevKey == null) - { - var c = new IrOutputPortController(irControllerKey, null, ""); - Debug.LogMessage(LogEventLevel.Information, c, "WARNING: control properties is missing ir device"); - return c; - } - - if (portNum == 0) - { - var c = new IrOutputPortController(irControllerKey, null, ""); - Debug.LogMessage(LogEventLevel.Information, c, "WARNING: control properties is missing ir port number"); - return c; - } - - if (portDevKey.Equals("controlSystem", StringComparison.OrdinalIgnoreCase) - || portDevKey.Equals("processor", StringComparison.OrdinalIgnoreCase)) - irDev = Global.ControlSystem; - else - irDev = DeviceManager.GetDeviceForKey(portDevKey) as IIROutputPorts; - - if (irDev == null) - { - var c = new IrOutputPortController(irControllerKey, null, ""); - Debug.LogMessage(LogEventLevel.Information, c, "WARNING: device with IR ports '{0}' not found", portDevKey); - return c; - } - - if (portNum <= irDev.NumberOfIROutputPorts) // success! - return new IrOutputPortController(irControllerKey, irDev.IROutputPorts[portNum], - IrDriverPathPrefix + control["irFile"].Value()); - else - { - var c = new IrOutputPortController(irControllerKey, null, ""); - Debug.LogMessage(LogEventLevel.Information, c, "WARNING: device '{0}' IR port {1} out of range", - portDevKey, portNum); - return c; - } - }*/ + var c = new IrOutputPortController(irControllerKey, null, ""); + Debug.LogMessage(LogEventLevel.Information, c, "WARNING: control properties is missing ir device"); + return c; + } + + if (portNum == 0) + { + var c = new IrOutputPortController(irControllerKey, null, ""); + Debug.LogMessage(LogEventLevel.Information, c, "WARNING: control properties is missing ir port number"); + return c; + } + + if (portDevKey.Equals("controlSystem", StringComparison.OrdinalIgnoreCase) + || portDevKey.Equals("processor", StringComparison.OrdinalIgnoreCase)) + irDev = Global.ControlSystem; + else + irDev = DeviceManager.GetDeviceForKey(portDevKey) as IIROutputPorts; + + if (irDev == null) + { + var c = new IrOutputPortController(irControllerKey, null, ""); + Debug.LogMessage(LogEventLevel.Information, c, "WARNING: device with IR ports '{0}' not found", portDevKey); + return c; + } + + if (portNum <= irDev.NumberOfIROutputPorts) // success! + return new IrOutputPortController(irControllerKey, irDev.IROutputPorts[portNum], + IrDriverPathPrefix + control["irFile"].Value()); + else + { + var c = new IrOutputPortController(irControllerKey, null, ""); + Debug.LogMessage(LogEventLevel.Information, c, "WARNING: device '{0}' IR port {1} out of range", + portDevKey, portNum); + return c; + } + }*/ } /// @@ -240,5 +240,4 @@ public IrOutPortConfig() { FileName = ""; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Config/AudioControlPointListItem.cs b/src/PepperDash.Essentials.Core/Config/AudioControlPointListItem.cs index 3552c2b25..3a3e2fc80 100644 --- a/src/PepperDash.Essentials.Core/Config/AudioControlPointListItem.cs +++ b/src/PepperDash.Essentials.Core/Config/AudioControlPointListItem.cs @@ -6,15 +6,14 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core.Config +namespace PepperDash.Essentials.Core.Config; + +public class AudioControlPointListItem { - public class AudioControlPointListItem - { - [JsonProperty("levelControls")] - public Dictionary LevelControls { get; set; } = new Dictionary(); + [JsonProperty("levelControls")] + public Dictionary LevelControls { get; set; } = new Dictionary(); - [JsonProperty("presets")] - public Dictionary Presets { get; set; } = new Dictionary(); + [JsonProperty("presets")] + public Dictionary Presets { get; set; } = new Dictionary(); - } } diff --git a/src/PepperDash.Essentials.Core/Config/BasicConfig.cs b/src/PepperDash.Essentials.Core/Config/BasicConfig.cs index 0e3e1e35c..c210dd025 100644 --- a/src/PepperDash.Essentials.Core/Config/BasicConfig.cs +++ b/src/PepperDash.Essentials.Core/Config/BasicConfig.cs @@ -7,8 +7,8 @@ using Newtonsoft.Json.Linq; using PepperDash.Essentials.Core.Devices; -namespace PepperDash.Essentials.Core.Config -{ +namespace PepperDash.Essentials.Core.Config; + /// /// Override this and splice on specific room type behavior, as well as other properties /// @@ -23,32 +23,32 @@ public class BasicConfig [JsonProperty("sourceLists")] public Dictionary> SourceLists { get; set; } - [JsonProperty("destinationLists")] - public Dictionary> DestinationLists { get; set; } + [JsonProperty("destinationLists")] + public Dictionary> DestinationLists { get; set; } - [JsonProperty("audioControlPointLists")] - public Dictionary AudioControlPointLists { get; set; } + [JsonProperty("audioControlPointLists")] + public Dictionary AudioControlPointLists { get; set; } - [JsonProperty("cameraLists")] - public Dictionary> CameraLists { get; set; } + [JsonProperty("cameraLists")] + public Dictionary> CameraLists { get; set; } - [JsonProperty("tieLines")] + [JsonProperty("tieLines")] public List TieLines { get; set; } - [JsonProperty("joinMaps")] - public Dictionary JoinMaps { get; set; } - - public BasicConfig() - { - Info = new InfoConfig(); - Devices = new List(); - SourceLists = new Dictionary>(); - DestinationLists = new Dictionary>(); - AudioControlPointLists = new Dictionary(); - CameraLists = new Dictionary>(); - TieLines = new List(); - JoinMaps = new Dictionary(); - } + [JsonProperty("joinMaps")] + public Dictionary JoinMaps { get; set; } + + public BasicConfig() + { + Info = new InfoConfig(); + Devices = new List(); + SourceLists = new Dictionary>(); + DestinationLists = new Dictionary>(); + AudioControlPointLists = new Dictionary(); + CameraLists = new Dictionary>(); + TieLines = new List(); + JoinMaps = new Dictionary(); + } /// /// Checks SourceLists for a given list and returns it if found. Otherwise, returns null @@ -61,11 +61,11 @@ public Dictionary GetSourceListForKey(string key) return SourceLists[key]; } - /// - /// Retrieves a DestinationListItem based on the key - /// - /// key of the list to retrieve - /// DestinationList if the key exists, null otherwise + /// + /// Retrieves a DestinationListItem based on the key + /// + /// key of the list to retrieve + /// DestinationList if the key exists, null otherwise public Dictionary GetDestinationListForKey(string key) { if (DestinationLists == null || string.IsNullOrEmpty(key) || !DestinationLists.ContainsKey(key)) @@ -76,48 +76,47 @@ public Dictionary GetDestinationListForKey(string k return DestinationLists[key]; } - /// - /// Retrieves a AudioControlPointList based on the key - /// - /// key of the list to retrieve - /// AudioControlPointList if the key exists, null otherwise - public AudioControlPointListItem GetAudioControlPointListForKey(string key) - { - if (AudioControlPointLists == null || string.IsNullOrEmpty(key) || !AudioControlPointLists.ContainsKey(key)) - return null; - - return AudioControlPointLists[key]; - } - - /// - /// Checks CameraLists for a given list and returns it if found. Otherwise, returns null - /// - public Dictionary GetCameraListForKey(string key) + /// + /// Retrieves a AudioControlPointList based on the key + /// + /// key of the list to retrieve + /// AudioControlPointList if the key exists, null otherwise + public AudioControlPointListItem GetAudioControlPointListForKey(string key) + { + if (AudioControlPointLists == null || string.IsNullOrEmpty(key) || !AudioControlPointLists.ContainsKey(key)) + return null; + + return AudioControlPointLists[key]; + } + + /// + /// Checks CameraLists for a given list and returns it if found. Otherwise, returns null + /// + public Dictionary GetCameraListForKey(string key) + { + if (CameraLists == null || string.IsNullOrEmpty(key) || !CameraLists.ContainsKey(key)) + return null; + + return CameraLists[key]; + } + + /// + /// Checks Devices for an item with a Key that matches and returns it if found. Otherwise, retunes null + /// + /// Key of desired device + /// + public DeviceConfig GetDeviceForKey(string key) + { + if (string.IsNullOrEmpty(key)) + return null; + + var deviceConfig = Devices.FirstOrDefault(d => d.Key.Equals(key)); + + if (deviceConfig != null) + return deviceConfig; + else { - if (CameraLists == null || string.IsNullOrEmpty(key) || !CameraLists.ContainsKey(key)) - return null; - - return CameraLists[key]; - } - - /// - /// Checks Devices for an item with a Key that matches and returns it if found. Otherwise, retunes null - /// - /// Key of desired device - /// - public DeviceConfig GetDeviceForKey(string key) - { - if (string.IsNullOrEmpty(key)) - return null; - - var deviceConfig = Devices.FirstOrDefault(d => d.Key.Equals(key)); - - if (deviceConfig != null) - return deviceConfig; - else - { - return null; - } + return null; } - } -} \ No newline at end of file + } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Config/ConfigPropertiesHelpers.cs b/src/PepperDash.Essentials.Core/Config/ConfigPropertiesHelpers.cs index 0950d62e3..9eb8e61df 100644 --- a/src/PepperDash.Essentials.Core/Config/ConfigPropertiesHelpers.cs +++ b/src/PepperDash.Essentials.Core/Config/ConfigPropertiesHelpers.cs @@ -9,24 +9,23 @@ using PepperDash.Core; using Newtonsoft.Json.Linq; -namespace PepperDash.Essentials.Core.Config +namespace PepperDash.Essentials.Core.Config; + +public class ConfigPropertiesHelpers { - public class ConfigPropertiesHelpers + /// + /// Returns the value of properties.hasAudio, or false if not defined + /// + public static bool GetHasAudio(DeviceConfig deviceConfig) { - /// - /// Returns the value of properties.hasAudio, or false if not defined - /// - public static bool GetHasAudio(DeviceConfig deviceConfig) - { - return deviceConfig.Properties.Value("hasAudio"); - } + return deviceConfig.Properties.Value("hasAudio"); + } - /// - /// Returns the value of properties.hasControls, or false if not defined - /// - public static bool GetHasControls(DeviceConfig deviceConfig) - { - return deviceConfig.Properties.Value("hasControls"); - } + /// + /// Returns the value of properties.hasControls, or false if not defined + /// + public static bool GetHasControls(DeviceConfig deviceConfig) + { + return deviceConfig.Properties.Value("hasControls"); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Config/DeviceConfig.cs b/src/PepperDash.Essentials.Core/Config/DeviceConfig.cs index 3eac80d9d..49994abc5 100644 --- a/src/PepperDash.Essentials.Core/Config/DeviceConfig.cs +++ b/src/PepperDash.Essentials.Core/Config/DeviceConfig.cs @@ -11,72 +11,71 @@ using PepperDash.Core; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core.Config -{ - public class DeviceConfig - { - [JsonProperty("key")] - public string Key { get; set; } +namespace PepperDash.Essentials.Core.Config; - [JsonProperty("uid")] - public int Uid { get; set; } +public class DeviceConfig +{ + [JsonProperty("key")] + public string Key { get; set; } - [JsonProperty("name")] - public string Name { get; set; } + [JsonProperty("uid")] + public int Uid { get; set; } - [JsonProperty("group")] - public string Group { get; set; } + [JsonProperty("name")] + public string Name { get; set; } - [JsonProperty("type")] - public string Type { get; set; } + [JsonProperty("group")] + public string Group { get; set; } - [JsonProperty("properties")] - [JsonConverter(typeof(DevicePropertiesConverter))] - public JToken Properties { get; set; } + [JsonProperty("type")] + public string Type { get; set; } - public DeviceConfig(DeviceConfig dc) - { - Key = dc.Key; - Uid = dc.Uid; - Name = dc.Name; - Group = dc.Group; - Type = dc.Type; + [JsonProperty("properties")] + [JsonConverter(typeof(DevicePropertiesConverter))] + public JToken Properties { get; set; } - Properties = JToken.Parse(dc.Properties.ToString()); + public DeviceConfig(DeviceConfig dc) + { + Key = dc.Key; + Uid = dc.Uid; + Name = dc.Name; + Group = dc.Group; + Type = dc.Type; - //Properties = JToken.FromObject(dc.Properties); - } + Properties = JToken.Parse(dc.Properties.ToString()); - public DeviceConfig() {} + //Properties = JToken.FromObject(dc.Properties); } - /// - /// - /// - public class DevicePropertiesConverter : JsonConverter - { + public DeviceConfig() {} +} - public override bool CanConvert(Type objectType) - { - return objectType == typeof(JToken); - } +/// +/// +/// +public class DevicePropertiesConverter : JsonConverter +{ - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - return JToken.ReadFrom(reader); - } + public override bool CanConvert(Type objectType) + { + return objectType == typeof(JToken); + } - public override bool CanWrite - { - get - { - return false; - } - } + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + return JToken.ReadFrom(reader); + } - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + public override bool CanWrite + { + get { - throw new NotImplementedException("SOD OFF HOSER"); + return false; } } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException("SOD OFF HOSER"); + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Config/Essentials/ConfigReader.cs b/src/PepperDash.Essentials.Core/Config/Essentials/ConfigReader.cs index 8549ecd83..d81223e39 100644 --- a/src/PepperDash.Essentials.Core/Config/Essentials/ConfigReader.cs +++ b/src/PepperDash.Essentials.Core/Config/Essentials/ConfigReader.cs @@ -11,15 +11,15 @@ using PepperDash.Core.Config; using Serilog.Events; -namespace PepperDash.Essentials.Core.Config -{ +namespace PepperDash.Essentials.Core.Config; + /// /// Loads the ConfigObject from the file /// public class ConfigReader { public const string LocalConfigPresent = - @" + @" *************************************************** ************* Using Local config file ************* ***************************************************"; @@ -31,227 +31,226 @@ public static bool LoadConfig2() Debug.LogMessage(LogEventLevel.Information, "Loading unmerged system/template portal configuration file."); try { - // Check for local config file first - var filePath = Global.FilePathPrefix + ConfigWriter.LocalConfigFolder + Global.DirectorySeparator + Global.ConfigFileName; + // Check for local config file first + var filePath = Global.FilePathPrefix + ConfigWriter.LocalConfigFolder + Global.DirectorySeparator + Global.ConfigFileName; - bool localConfigFound = false; + bool localConfigFound = false; - Debug.LogMessage(LogEventLevel.Information, "Attempting to load Local config file: '{0}'", filePath); + Debug.LogMessage(LogEventLevel.Information, "Attempting to load Local config file: '{0}'", filePath); - // Check for local config directory first + // Check for local config directory first - var configFiles = GetConfigFiles(filePath); + var configFiles = GetConfigFiles(filePath); - if (configFiles != null) + if (configFiles != null) + { + if (configFiles.Length > 1) { - if (configFiles.Length > 1) - { - Debug.LogMessage(LogEventLevel.Information, - "****Error: Multiple Local Configuration files present. Please ensure only a single file exists and reset program.****"); - return false; - } - if(configFiles.Length == 1) - { - localConfigFound = true; - - } + Debug.LogMessage(LogEventLevel.Information, + "****Error: Multiple Local Configuration files present. Please ensure only a single file exists and reset program.****"); + return false; } - else + if(configFiles.Length == 1) { - Debug.LogMessage(LogEventLevel.Information, - "Local Configuration file not present.", filePath); - + localConfigFound = true; + } + } + else + { + Debug.LogMessage(LogEventLevel.Information, + "Local Configuration file not present.", filePath); - // Check for Portal Config - if(!localConfigFound) - { - filePath = Global.FilePathPrefix + Global.ConfigFileName; + } - Debug.LogMessage(LogEventLevel.Information, "Attempting to load Portal config file: '{0}'", filePath); + // Check for Portal Config + if(!localConfigFound) + { + filePath = Global.FilePathPrefix + Global.ConfigFileName; - configFiles = GetConfigFiles(filePath); + Debug.LogMessage(LogEventLevel.Information, "Attempting to load Portal config file: '{0}'", filePath); - if (configFiles != null) + configFiles = GetConfigFiles(filePath); + + if (configFiles != null) + { + Debug.LogMessage(LogEventLevel.Verbose, "{0} config files found matching pattern", configFiles.Length); + + if (configFiles.Length > 1) { - Debug.LogMessage(LogEventLevel.Verbose, "{0} config files found matching pattern", configFiles.Length); - - if (configFiles.Length > 1) - { - Debug.LogMessage(LogEventLevel.Information, - "****Error: Multiple Portal Configuration files present. Please ensure only a single file exists and reset program.****"); - return false; - } - else if (configFiles.Length == 1) - { - Debug.LogMessage(LogEventLevel.Information, "Found Portal config file: '{0}'", filePath); - } - else - { - Debug.LogMessage(LogEventLevel.Information, "No config file found."); - return false; - } + Debug.LogMessage(LogEventLevel.Information, + "****Error: Multiple Portal Configuration files present. Please ensure only a single file exists and reset program.****"); + return false; + } + else if (configFiles.Length == 1) + { + Debug.LogMessage(LogEventLevel.Information, "Found Portal config file: '{0}'", filePath); } else { - Debug.LogMessage(LogEventLevel.Information, - "ERROR: Portal Configuration file not present. Please load file and reset program."); + Debug.LogMessage(LogEventLevel.Information, "No config file found."); return false; } } + else + { + Debug.LogMessage(LogEventLevel.Information, + "ERROR: Portal Configuration file not present. Please load file and reset program."); + return false; + } + } - // Get the actual file path - filePath = configFiles[0].FullName; + // Get the actual file path + filePath = configFiles[0].FullName; - // Generate debug statement if using a local file. + // Generate debug statement if using a local file. if (localConfigFound) { - GetLocalFileMessage(filePath); + GetLocalFileMessage(filePath); } - // Read the file - using (StreamReader fs = new StreamReader(filePath)) - { - Debug.LogMessage(LogEventLevel.Information, "Loading config file: '{0}'", filePath); + // Read the file + using (StreamReader fs = new StreamReader(filePath)) + { + Debug.LogMessage(LogEventLevel.Information, "Loading config file: '{0}'", filePath); - if (localConfigFound) - { - ConfigObject = JObject.Parse(fs.ReadToEnd()).ToObject(); + if (localConfigFound) + { + ConfigObject = JObject.Parse(fs.ReadToEnd()).ToObject(); - Debug.LogMessage(LogEventLevel.Information, "Successfully Loaded Local Config"); + Debug.LogMessage(LogEventLevel.Information, "Successfully Loaded Local Config"); - return true; - } - else - { - var doubleObj = JObject.Parse(fs.ReadToEnd()); - ConfigObject = PortalConfigReader.MergeConfigs(doubleObj).ToObject(); + return true; + } + else + { + var doubleObj = JObject.Parse(fs.ReadToEnd()); + ConfigObject = PortalConfigReader.MergeConfigs(doubleObj).ToObject(); - // Extract SystemUrl and TemplateUrl into final config output + // Extract SystemUrl and TemplateUrl into final config output - if (doubleObj["system_url"] != null) - { - ConfigObject.SystemUrl = doubleObj["system_url"].Value(); - } + if (doubleObj["system_url"] != null) + { + ConfigObject.SystemUrl = doubleObj["system_url"].Value(); + } - if (doubleObj["template_url"] != null) - { - ConfigObject.TemplateUrl = doubleObj["template_url"].Value(); - } + if (doubleObj["template_url"] != null) + { + ConfigObject.TemplateUrl = doubleObj["template_url"].Value(); } + } - Debug.LogMessage(LogEventLevel.Information, "Successfully Loaded Merged Config"); + Debug.LogMessage(LogEventLevel.Information, "Successfully Loaded Merged Config"); - return true; - } + return true; + } } catch (Exception e) { - Debug.LogMessage(LogEventLevel.Information, "ERROR: Config load failed: \r{0}", e); + Debug.LogMessage(LogEventLevel.Information, "ERROR: Config load failed: \r{0}", e); return false; } } - /// - /// Returns all the files from the directory specified. - /// - /// - /// - public static FileInfo[] GetConfigFiles(string filePath) + /// + /// Returns all the files from the directory specified. + /// + /// + /// + public static FileInfo[] GetConfigFiles(string filePath) + { + // Get the directory + var dir = Path.GetDirectoryName(filePath); + + if (Directory.Exists(dir)) { - // Get the directory - var dir = Path.GetDirectoryName(filePath); + Debug.LogMessage(LogEventLevel.Debug, "Searching in Directory '{0}'", dir); + // Get the directory info + var dirInfo = new DirectoryInfo(dir); - if (Directory.Exists(dir)) - { - Debug.LogMessage(LogEventLevel.Debug, "Searching in Directory '{0}'", dir); - // Get the directory info - var dirInfo = new DirectoryInfo(dir); + // Get the file name + var fileName = Path.GetFileName(filePath); + Debug.LogMessage(LogEventLevel.Debug, "For Config Files matching: '{0}'", fileName); - // Get the file name - var fileName = Path.GetFileName(filePath); - Debug.LogMessage(LogEventLevel.Debug, "For Config Files matching: '{0}'", fileName); - - // Get the files that match from the directory - return dirInfo.GetFiles(fileName); - } - else - { - Debug.LogMessage(LogEventLevel.Information, - "Directory not found: ", dir); + // Get the files that match from the directory + return dirInfo.GetFiles(fileName); + } + else + { + Debug.LogMessage(LogEventLevel.Information, + "Directory not found: ", dir); - return null; - } + return null; } + } /// /// Returns the group for a given device key in config /// /// /// - public static string GetGroupForDeviceKey(string key) - { - var dev = ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); - return dev == null ? null : dev.Group; - } + public static string GetGroupForDeviceKey(string key) + { + var dev = ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); + return dev == null ? null : dev.Group; + } private static void GetLocalFileMessage(string filePath) { - var filePathLength = filePath.Length + 2; - var debugStringWidth = filePathLength + 12; + var filePathLength = filePath.Length + 2; + var debugStringWidth = filePathLength + 12; - if (debugStringWidth < 51) - { - debugStringWidth = 51; - } - var qualifier = (filePathLength % 2 != 0) - ? " Using Local Config File " - : " Using Local Config File "; - var bookend1 = (debugStringWidth - qualifier.Length) / 2; - var bookend2 = (debugStringWidth - filePathLength) / 2; + if (debugStringWidth < 51) + { + debugStringWidth = 51; + } + var qualifier = (filePathLength % 2 != 0) + ? " Using Local Config File " + : " Using Local Config File "; + var bookend1 = (debugStringWidth - qualifier.Length) / 2; + var bookend2 = (debugStringWidth - filePathLength) / 2; var newDebugString = new StringBuilder() .Append(CrestronEnvironment.NewLine) - // Line 1 + // Line 1 .Append(new string('*', debugStringWidth)) .Append(CrestronEnvironment.NewLine) - // Line 2 + // Line 2 .Append(new string('*', debugStringWidth)) .Append(CrestronEnvironment.NewLine) - // Line 3 + // Line 3 .Append(new string('*', 2)) .Append(new string(' ', debugStringWidth - 4)) .Append(new string('*', 2)) .Append(CrestronEnvironment.NewLine) - // Line 4 + // Line 4 .Append(new string('*', 2)) .Append(new string(' ', bookend1 - 2)) .Append(qualifier) .Append(new string(' ', bookend1 - 2)) .Append(new string('*', 2)) .Append(CrestronEnvironment.NewLine) - // Line 5 + // Line 5 .Append(new string('*', 2)) .Append(new string(' ', bookend2 - 2)) .Append(" " + filePath + " ") .Append(new string(' ', bookend2 - 2)) .Append(new string('*', 2)) .Append(CrestronEnvironment.NewLine) - // Line 6 + // Line 6 .Append(new string('*', 2)) .Append(new string(' ', debugStringWidth - 4)) .Append(new string('*', 2)) .Append(CrestronEnvironment.NewLine) - // Line 7 + // Line 7 .Append(new string('*', debugStringWidth)) .Append(CrestronEnvironment.NewLine) - // Line 8 + // Line 8 .Append(new string('*', debugStringWidth)); - Debug.LogMessage(LogEventLevel.Verbose, "Found Local config file: '{0}'", filePath); - Debug.LogMessage(LogEventLevel.Information, newDebugString.ToString()); + Debug.LogMessage(LogEventLevel.Verbose, "Found Local config file: '{0}'", filePath); + Debug.LogMessage(LogEventLevel.Information, newDebugString.ToString()); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Config/Essentials/ConfigUpdater.cs b/src/PepperDash.Essentials.Core/Config/Essentials/ConfigUpdater.cs index 141ffc25b..0f14e4557 100644 --- a/src/PepperDash.Essentials.Core/Config/Essentials/ConfigUpdater.cs +++ b/src/PepperDash.Essentials.Core/Config/Essentials/ConfigUpdater.cs @@ -14,213 +14,212 @@ using PepperDash.Core; using Serilog.Events; -namespace PepperDash.Essentials.Core.Config +namespace PepperDash.Essentials.Core.Config; + +public static class ConfigUpdater { - public static class ConfigUpdater - { - public static event EventHandler ConfigStatusChanged; + public static event EventHandler ConfigStatusChanged; - public static void GetConfigFromServer(string url) - { - Debug.LogMessage(LogEventLevel.Information, "Attempting to get new config from '{0}'", url); + public static void GetConfigFromServer(string url) + { + Debug.LogMessage(LogEventLevel.Information, "Attempting to get new config from '{0}'", url); - // HTTP GET - var req = new HttpClientRequest(); + // HTTP GET + var req = new HttpClientRequest(); - try - { - req.RequestType = RequestType.Get; - req.Url.Parse(url); + try + { + req.RequestType = RequestType.Get; + req.Url.Parse(url); - new HttpClient().DispatchAsync(req, (r, e) => + new HttpClient().DispatchAsync(req, (r, e) => + { + if (e == HTTP_CALLBACK_ERROR.COMPLETED) { - if (e == HTTP_CALLBACK_ERROR.COMPLETED) + if (r.Code == 200) { - if (r.Code == 200) - { - var newConfig = r.ContentString; + var newConfig = r.ContentString; - OnStatusUpdate(eUpdateStatus.ConfigFileReceived); + OnStatusUpdate(eUpdateStatus.ConfigFileReceived); - ArchiveExistingPortalConfigs(); + ArchiveExistingPortalConfigs(); - CheckForLocalConfigAndDelete(); + CheckForLocalConfigAndDelete(); - WriteConfigToFile(newConfig); + WriteConfigToFile(newConfig); - RestartProgram(); - } - else - { - Debug.LogMessage(LogEventLevel.Information, "Config Update Process Stopped. Failed to get config file from server: {0}", r.Code); - OnStatusUpdate(eUpdateStatus.UpdateFailed); - } + RestartProgram(); } else - Debug.LogMessage(LogEventLevel.Information, "Request for config from Server Failed: {0}", e); - }); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Debug, "Error Getting Config from Server: {0}", e); - } - + { + Debug.LogMessage(LogEventLevel.Information, "Config Update Process Stopped. Failed to get config file from server: {0}", r.Code); + OnStatusUpdate(eUpdateStatus.UpdateFailed); + } + } + else + Debug.LogMessage(LogEventLevel.Information, "Request for config from Server Failed: {0}", e); + }); } - - static void OnStatusUpdate(eUpdateStatus status) + catch (Exception e) { - var handler = ConfigStatusChanged; - - if(handler != null) - { - handler(typeof(ConfigUpdater), new ConfigStatusEventArgs(status)); - } + Debug.LogMessage(LogEventLevel.Debug, "Error Getting Config from Server: {0}", e); } - static void WriteConfigToFile(string configData) + } + + static void OnStatusUpdate(eUpdateStatus status) + { + var handler = ConfigStatusChanged; + + if(handler != null) { - var filePath = Global.FilePathPrefix+ "configurationFile-updated.json"; + handler(typeof(ConfigUpdater), new ConfigStatusEventArgs(status)); + } + } - try - { - var config = JObject.Parse(configData).ToObject(); + static void WriteConfigToFile(string configData) + { + var filePath = Global.FilePathPrefix+ "configurationFile-updated.json"; - ConfigWriter.WriteFile(filePath, configData); + try + { + var config = JObject.Parse(configData).ToObject(); - OnStatusUpdate(eUpdateStatus.WritingConfigFile); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Debug, "Error parsing new config: {0}", e); + ConfigWriter.WriteFile(filePath, configData); - OnStatusUpdate(eUpdateStatus.UpdateFailed); - } + OnStatusUpdate(eUpdateStatus.WritingConfigFile); } - - /// - /// Checks for any existing portal config files and archives them - /// - static void ArchiveExistingPortalConfigs() + catch (Exception e) { - var filePath = Global.FilePathPrefix + Global.ConfigFileName; + Debug.LogMessage(LogEventLevel.Debug, "Error parsing new config: {0}", e); - var configFiles = ConfigReader.GetConfigFiles(filePath); + OnStatusUpdate(eUpdateStatus.UpdateFailed); + } + } - if (configFiles != null) - { - Debug.LogMessage(LogEventLevel.Information, "Existing config files found. Moving to Archive folder."); + /// + /// Checks for any existing portal config files and archives them + /// + static void ArchiveExistingPortalConfigs() + { + var filePath = Global.FilePathPrefix + Global.ConfigFileName; - OnStatusUpdate(eUpdateStatus.ArchivingConfigs); + var configFiles = ConfigReader.GetConfigFiles(filePath); - MoveFilesToArchiveFolder(configFiles); - } - else - { - Debug.LogMessage(LogEventLevel.Information, "No Existing config files found in '{0}'. Nothing to archive", filePath); - } - } - - /// - /// Checks for presence of archive folder and if found deletes contents. - /// Moves any config files to the archive folder and adds a .bak suffix - /// - /// - static void MoveFilesToArchiveFolder(FileInfo[] files) + if (configFiles != null) { - string archiveDirectoryPath = Global.FilePathPrefix + "archive"; + Debug.LogMessage(LogEventLevel.Information, "Existing config files found. Moving to Archive folder."); - if (!Directory.Exists(archiveDirectoryPath)) - { - // Directory does not exist, create it - Directory.Create(archiveDirectoryPath); - } - else - { - // Directory exists, first clear any contents - var archivedConfigFiles = ConfigReader.GetConfigFiles(archiveDirectoryPath + Global.DirectorySeparator + Global.ConfigFileName + ".bak"); + OnStatusUpdate(eUpdateStatus.ArchivingConfigs); - if(archivedConfigFiles != null || archivedConfigFiles.Length > 0) - { - Debug.LogMessage(LogEventLevel.Information, "{0} Existing files found in archive folder. Deleting.", archivedConfigFiles.Length); + MoveFilesToArchiveFolder(configFiles); + } + else + { + Debug.LogMessage(LogEventLevel.Information, "No Existing config files found in '{0}'. Nothing to archive", filePath); + } + } - for (int i = 0; i < archivedConfigFiles.Length; i++ ) - { - var file = archivedConfigFiles[i]; - Debug.LogMessage(LogEventLevel.Information, "Deleting archived file: '{0}'", file.FullName); - file.Delete(); - } - } + /// + /// Checks for presence of archive folder and if found deletes contents. + /// Moves any config files to the archive folder and adds a .bak suffix + /// + /// + static void MoveFilesToArchiveFolder(FileInfo[] files) + { + string archiveDirectoryPath = Global.FilePathPrefix + "archive"; - } + if (!Directory.Exists(archiveDirectoryPath)) + { + // Directory does not exist, create it + Directory.Create(archiveDirectoryPath); + } + else + { + // Directory exists, first clear any contents + var archivedConfigFiles = ConfigReader.GetConfigFiles(archiveDirectoryPath + Global.DirectorySeparator + Global.ConfigFileName + ".bak"); - // Move any files from the program folder to the archive folder - foreach (var file in files) + if(archivedConfigFiles != null || archivedConfigFiles.Length > 0) { - Debug.LogMessage(LogEventLevel.Information, "Moving config file '{0}' to archive folder", file.FullName); + Debug.LogMessage(LogEventLevel.Information, "{0} Existing files found in archive folder. Deleting.", archivedConfigFiles.Length); - // Moves the file and appends the .bak extension - var fileDest = archiveDirectoryPath + "/" + file.Name + ".bak"; - if(!File.Exists(fileDest)) + for (int i = 0; i < archivedConfigFiles.Length; i++ ) { - file.MoveTo(fileDest); + var file = archivedConfigFiles[i]; + Debug.LogMessage(LogEventLevel.Information, "Deleting archived file: '{0}'", file.FullName); + file.Delete(); } - else - Debug.LogMessage(LogEventLevel.Information, "Cannot move file to archive folder. Existing file already exists with same name: '{0}'", fileDest); } + } - /// - /// Checks for LocalConfig folder in file system and deletes if found - /// - static void CheckForLocalConfigAndDelete() + // Move any files from the program folder to the archive folder + foreach (var file in files) { - var folderPath = Global.FilePathPrefix + ConfigWriter.LocalConfigFolder; + Debug.LogMessage(LogEventLevel.Information, "Moving config file '{0}' to archive folder", file.FullName); - if (Directory.Exists(folderPath)) + // Moves the file and appends the .bak extension + var fileDest = archiveDirectoryPath + "/" + file.Name + ".bak"; + if(!File.Exists(fileDest)) { - OnStatusUpdate(eUpdateStatus.DeletingLocalConfig); - Directory.Delete(folderPath); - Debug.LogMessage(LogEventLevel.Information, "Local Config Found in '{0}'. Deleting.", folderPath); + file.MoveTo(fileDest); } + else + Debug.LogMessage(LogEventLevel.Information, "Cannot move file to archive folder. Existing file already exists with same name: '{0}'", fileDest); } + } - /// - /// Connects to the processor via SSH and restarts the program - /// - static void RestartProgram() + /// + /// Checks for LocalConfig folder in file system and deletes if found + /// + static void CheckForLocalConfigAndDelete() + { + var folderPath = Global.FilePathPrefix + ConfigWriter.LocalConfigFolder; + + if (Directory.Exists(folderPath)) { - Debug.LogMessage(LogEventLevel.Information, "Attempting to Reset Program"); + OnStatusUpdate(eUpdateStatus.DeletingLocalConfig); + Directory.Delete(folderPath); + Debug.LogMessage(LogEventLevel.Information, "Local Config Found in '{0}'. Deleting.", folderPath); + } + } - OnStatusUpdate(eUpdateStatus.RestartingProgram); + /// + /// Connects to the processor via SSH and restarts the program + /// + static void RestartProgram() + { + Debug.LogMessage(LogEventLevel.Information, "Attempting to Reset Program"); - string response = string.Empty; + OnStatusUpdate(eUpdateStatus.RestartingProgram); - CrestronConsole.SendControlSystemCommand(string.Format("progreset -p:{0}", InitialParametersClass.ApplicationNumber), ref response); + string response = string.Empty; - Debug.LogMessage(LogEventLevel.Debug, "Console Response: {0}", response); - } + CrestronConsole.SendControlSystemCommand(string.Format("progreset -p:{0}", InitialParametersClass.ApplicationNumber), ref response); + Debug.LogMessage(LogEventLevel.Debug, "Console Response: {0}", response); } - public enum eUpdateStatus - { - UpdateStarted, - ConfigFileReceived, - ArchivingConfigs, - DeletingLocalConfig, - WritingConfigFile, - RestartingProgram, - UpdateSucceeded, - UpdateFailed - } +} - public class ConfigStatusEventArgs : EventArgs - { - public eUpdateStatus UpdateStatus { get; private set; } + public enum eUpdateStatus +{ + UpdateStarted, + ConfigFileReceived, + ArchivingConfigs, + DeletingLocalConfig, + WritingConfigFile, + RestartingProgram, + UpdateSucceeded, + UpdateFailed +} + +public class ConfigStatusEventArgs : EventArgs +{ + public eUpdateStatus UpdateStatus { get; private set; } - public ConfigStatusEventArgs(eUpdateStatus status) - { - UpdateStatus = status; - } + public ConfigStatusEventArgs(eUpdateStatus status) + { + UpdateStatus = status; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Config/Essentials/ConfigWriter.cs b/src/PepperDash.Essentials.Core/Config/Essentials/ConfigWriter.cs index 58ced97ee..a688b3783 100644 --- a/src/PepperDash.Essentials.Core/Config/Essentials/ConfigWriter.cs +++ b/src/PepperDash.Essentials.Core/Config/Essentials/ConfigWriter.cs @@ -11,155 +11,154 @@ using PepperDash.Core; using Serilog.Events; -namespace PepperDash.Essentials.Core.Config +namespace PepperDash.Essentials.Core.Config; + +/// +/// Responsible for updating config at runtime, and writing the updates out to a local file +/// +public class ConfigWriter { + public const string LocalConfigFolder = "LocalConfig"; + + public const long WriteTimeout = 30000; + + public static CTimer WriteTimer; + static CCriticalSection fileLock = new CCriticalSection(); + /// - /// Responsible for updating config at runtime, and writing the updates out to a local file + /// Updates the config properties of a device /// - public class ConfigWriter + /// + /// + /// + public static bool UpdateDeviceProperties(string deviceKey, JToken properties) { - public const string LocalConfigFolder = "LocalConfig"; - - public const long WriteTimeout = 30000; + bool success = false; - public static CTimer WriteTimer; - static CCriticalSection fileLock = new CCriticalSection(); + // Get the current device config + var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(deviceKey)); - /// - /// Updates the config properties of a device - /// - /// - /// - /// - public static bool UpdateDeviceProperties(string deviceKey, JToken properties) + if (deviceConfig != null) { - bool success = false; + // Replace the current properties JToken with the new one passed into this method + deviceConfig.Properties = properties; - // Get the current device config - var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(deviceKey)); + Debug.LogMessage(LogEventLevel.Debug, "Updated properties of device: '{0}'", deviceKey); - if (deviceConfig != null) - { - // Replace the current properties JToken with the new one passed into this method - deviceConfig.Properties = properties; + success = true; + } - Debug.LogMessage(LogEventLevel.Debug, "Updated properties of device: '{0}'", deviceKey); + ResetTimer(); - success = true; - } + return success; + } - ResetTimer(); + public static bool UpdateDeviceConfig(DeviceConfig config) + { + bool success = false; - return success; - } + var deviceConfigIndex = ConfigReader.ConfigObject.Devices.FindIndex(d => d.Key.Equals(config.Key)); - public static bool UpdateDeviceConfig(DeviceConfig config) + if (deviceConfigIndex >= 0) { - bool success = false; - - var deviceConfigIndex = ConfigReader.ConfigObject.Devices.FindIndex(d => d.Key.Equals(config.Key)); + ConfigReader.ConfigObject.Devices[deviceConfigIndex] = config; - if (deviceConfigIndex >= 0) - { - ConfigReader.ConfigObject.Devices[deviceConfigIndex] = config; - - Debug.LogMessage(LogEventLevel.Debug, "Updated config of device: '{0}'", config.Key); + Debug.LogMessage(LogEventLevel.Debug, "Updated config of device: '{0}'", config.Key); - success = true; - } + success = true; + } - ResetTimer(); + ResetTimer(); - return success; - } + return success; + } - public static bool UpdateRoomConfig(DeviceConfig config) - { - bool success = false; + public static bool UpdateRoomConfig(DeviceConfig config) + { + bool success = false; var roomConfigIndex = ConfigReader.ConfigObject.Rooms.FindIndex(d => d.Key.Equals(config.Key)); if (roomConfigIndex >= 0) - { - ConfigReader.ConfigObject.Rooms[roomConfigIndex] = config; + { + ConfigReader.ConfigObject.Rooms[roomConfigIndex] = config; - Debug.LogMessage(LogEventLevel.Debug, "Updated room of device: '{0}'", config.Key); + Debug.LogMessage(LogEventLevel.Debug, "Updated room of device: '{0}'", config.Key); - success = true; - } + success = true; + } - ResetTimer(); + ResetTimer(); - return success; - } + return success; + } - /// - /// Resets (or starts) the write timer - /// - static void ResetTimer() - { - if (WriteTimer == null) - WriteTimer = new CTimer(WriteConfigFile, WriteTimeout); + /// + /// Resets (or starts) the write timer + /// + static void ResetTimer() + { + if (WriteTimer == null) + WriteTimer = new CTimer(WriteConfigFile, WriteTimeout); - WriteTimer.Reset(WriteTimeout); + WriteTimer.Reset(WriteTimeout); - Debug.LogMessage(LogEventLevel.Debug, "Config File write timer has been reset."); - } + Debug.LogMessage(LogEventLevel.Debug, "Config File write timer has been reset."); + } - /// - /// Writes the current config to a file in the LocalConfig subfolder - /// - /// - private static void WriteConfigFile(object o) - { - var filePath = Global.FilePathPrefix + LocalConfigFolder + Global.DirectorySeparator + "configurationFile.json"; + /// + /// Writes the current config to a file in the LocalConfig subfolder + /// + /// + private static void WriteConfigFile(object o) + { + var filePath = Global.FilePathPrefix + LocalConfigFolder + Global.DirectorySeparator + "configurationFile.json"; - var configData = JsonConvert.SerializeObject(ConfigReader.ConfigObject); + var configData = JsonConvert.SerializeObject(ConfigReader.ConfigObject); - WriteFile(filePath, configData); - } + WriteFile(filePath, configData); + } - /// - /// Writes - /// - /// - /// - public static void WriteFile(string filePath, string configData) - { - if (WriteTimer != null) - WriteTimer.Stop(); + /// + /// Writes + /// + /// + /// + public static void WriteFile(string filePath, string configData) + { + if (WriteTimer != null) + WriteTimer.Stop(); - Debug.LogMessage(LogEventLevel.Information, "Writing Configuration to file"); + Debug.LogMessage(LogEventLevel.Information, "Writing Configuration to file"); - Debug.LogMessage(LogEventLevel.Information, "Attempting to write config file: '{0}'", filePath); + Debug.LogMessage(LogEventLevel.Information, "Attempting to write config file: '{0}'", filePath); - try + try + { + if (fileLock.TryEnter()) { - if (fileLock.TryEnter()) + using (StreamWriter sw = new StreamWriter(filePath)) { - using (StreamWriter sw = new StreamWriter(filePath)) - { - sw.Write(configData); - sw.Flush(); - } - } - else - { - Debug.LogMessage(LogEventLevel.Information, "Unable to enter FileLock"); + sw.Write(configData); + sw.Flush(); } } - catch (Exception e) + else { - Debug.LogMessage(LogEventLevel.Information, "Error: Config write failed: \r{0}", e); + Debug.LogMessage(LogEventLevel.Information, "Unable to enter FileLock"); } - finally - { - if (fileLock != null && !fileLock.Disposed) - fileLock.Leave(); + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Information, "Error: Config write failed: \r{0}", e); + } + finally + { + if (fileLock != null && !fileLock.Disposed) + fileLock.Leave(); - } } + } - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Config/Essentials/EssentialsConfig.cs b/src/PepperDash.Essentials.Core/Config/Essentials/EssentialsConfig.cs index b42ec94cd..bab6ae1dc 100644 --- a/src/PepperDash.Essentials.Core/Config/Essentials/EssentialsConfig.cs +++ b/src/PepperDash.Essentials.Core/Config/Essentials/EssentialsConfig.cs @@ -9,25 +9,25 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core.Config -{ +namespace PepperDash.Essentials.Core.Config; + /// /// Loads the ConfigObject from the file /// public class EssentialsConfig : BasicConfig { [JsonProperty("system_url")] - public string SystemUrl { get; set; } + public string SystemUrl { get; set; } [JsonProperty("template_url")] - public string TemplateUrl { get; set; } + public string TemplateUrl { get; set; } [JsonProperty("systemUuid")] public string SystemUuid + { + get { - get - { if (string.IsNullOrEmpty(SystemUrl)) return "missing url"; @@ -38,18 +38,18 @@ public string SystemUuid return uuid; } else { - var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/.*"); - string uuid = result.Groups[1].Value; - return uuid; - } + var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/.*"); + string uuid = result.Groups[1].Value; + return uuid; } } + } [JsonProperty("templateUuid")] public string TemplateUuid + { + get { - get - { if (string.IsNullOrEmpty(TemplateUrl)) return "missing template url"; @@ -60,22 +60,22 @@ public string TemplateUuid return uuid; } else { - var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/system-templates\/(.*)\/system-template-versions\/(.*)\/.*"); - string uuid = result.Groups[2].Value; - return uuid; - } + var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/system-templates\/(.*)\/system-template-versions\/(.*)\/.*"); + string uuid = result.Groups[2].Value; + return uuid; } } + } [JsonProperty("rooms")] - public List Rooms { get; set; } + public List Rooms { get; set; } - public EssentialsConfig() - : base() - { - Rooms = new List(); - } + public EssentialsConfig() + : base() + { + Rooms = new List(); + } } /// @@ -86,5 +86,4 @@ public class SystemTemplateConfigs public EssentialsConfig System { get; set; } public EssentialsConfig Template { get; set; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Config/ILoadConfig.cs b/src/PepperDash.Essentials.Core/Config/ILoadConfig.cs index 00bbf5f65..a02baa8cd 100644 --- a/src/PepperDash.Essentials.Core/Config/ILoadConfig.cs +++ b/src/PepperDash.Essentials.Core/Config/ILoadConfig.cs @@ -4,10 +4,9 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public interface ILoadConfig { - public interface ILoadConfig - { - void GoWithLoad(); - } + void GoWithLoad(); } diff --git a/src/PepperDash.Essentials.Core/Config/InfoConfig.cs b/src/PepperDash.Essentials.Core/Config/InfoConfig.cs index 12ca49f4e..95b7860ec 100644 --- a/src/PepperDash.Essentials.Core/Config/InfoConfig.cs +++ b/src/PepperDash.Essentials.Core/Config/InfoConfig.cs @@ -5,12 +5,12 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.Core.Config -{ - /// - /// Represents the info section of a Config file - /// - public class InfoConfig +namespace PepperDash.Essentials.Core.Config; + +/// +/// Represents the info section of a Config file +/// +public class InfoConfig { [JsonProperty("name")] public string Name { get; set; } @@ -24,17 +24,17 @@ public class InfoConfig [JsonProperty("version")] public string Version { get; set; } - [JsonProperty("runtimeInfo")] - public RuntimeInfo RuntimeInfo { get; set; } + [JsonProperty("runtimeInfo")] + public RuntimeInfo RuntimeInfo { get; set; } [JsonProperty("comment")] public string Comment { get; set; } - [JsonProperty("hostname")] - public string HostName { get; set; } + [JsonProperty("hostname")] + public string HostName { get; set; } - [JsonProperty("appNumber")] - public uint AppNumber { get; set; } + [JsonProperty("appNumber")] + public uint AppNumber { get; set; } public InfoConfig() { @@ -43,49 +43,49 @@ public InfoConfig() Type = ""; Version = ""; Comment = ""; - HostName = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0); - AppNumber = InitialParametersClass.ApplicationNumber; + HostName = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0); + AppNumber = InitialParametersClass.ApplicationNumber; - RuntimeInfo = new RuntimeInfo(); + RuntimeInfo = new RuntimeInfo(); } } - + +/// +/// Represents runtime information about the program/processor +/// +public class RuntimeInfo +{ /// - /// Represents runtime information about the program/processor + /// The name of the running application /// - public class RuntimeInfo - { - /// - /// The name of the running application - /// - [JsonProperty("appName")] - public string AppName {get; set;} - //{ - // get - // { - // return Assembly.GetExecutingAssembly().GetName().Name; - // } - //} + [JsonProperty("appName")] + public string AppName {get; set;} + //{ + // get + // { + // return Assembly.GetExecutingAssembly().GetName().Name; + // } + //} - /// - /// The Assembly version of the running application - /// - [JsonProperty("assemblyVersion")] - public string AssemblyVersion {get; set;} - //{ - // get - // { - // var version = Assembly.GetExecutingAssembly().GetName().Version; - // return string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build); - // } - //} + /// + /// The Assembly version of the running application + /// + [JsonProperty("assemblyVersion")] + public string AssemblyVersion {get; set;} + //{ + // get + // { + // var version = Assembly.GetExecutingAssembly().GetName().Version; + // return string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build); + // } + //} - /// , - /// The OS Version of the processor (Firmware Version) - /// - [JsonProperty("osVersion")] - public string OsVersion {get; set;} + /// , + /// The OS Version of the processor (Firmware Version) + /// + [JsonProperty("osVersion")] + public string OsVersion {get; set;} //{ // get // { @@ -93,17 +93,15 @@ public class RuntimeInfo // } //} - /// - /// The information gathered by the processor at runtime about it's NICs and their IP addresses. - /// - [JsonProperty("ipInfo")] - public Dictionary IpInfo + /// + /// The information gathered by the processor at runtime about it's NICs and their IP addresses. + /// + [JsonProperty("ipInfo")] + public Dictionary IpInfo + { + get { - get - { - return Global.EthernetAdapterInfoCollection; - } + return Global.EthernetAdapterInfoCollection; } } - } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Config/SourceDevicePropertiesConfigBase.cs b/src/PepperDash.Essentials.Core/Config/SourceDevicePropertiesConfigBase.cs index e6d133398..cc02289cf 100644 --- a/src/PepperDash.Essentials.Core/Config/SourceDevicePropertiesConfigBase.cs +++ b/src/PepperDash.Essentials.Core/Config/SourceDevicePropertiesConfigBase.cs @@ -4,10 +4,9 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core.Config -{ +namespace PepperDash.Essentials.Core.Config; + public class SourceDevicePropertiesConfigBase { public bool DisableSharing { get; set; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Crestron/CrestronGenericBaseDevice.cs b/src/PepperDash.Essentials.Core/Crestron/CrestronGenericBaseDevice.cs index ce5438859..8ad90b14f 100644 --- a/src/PepperDash.Essentials.Core/Crestron/CrestronGenericBaseDevice.cs +++ b/src/PepperDash.Essentials.Core/Crestron/CrestronGenericBaseDevice.cs @@ -7,16 +7,16 @@ using PepperDash.Essentials.Core.Bridges; using Serilog.Events; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public abstract class CrestronGenericBaseDevice : EssentialsDevice, IOnline, IHasFeedback, ICommunicationMonitor, IUsageTracking { protected GenericBase Hardware; - /// - /// Returns a list containing the Outputs that we want to expose. - /// - public FeedbackCollection Feedbacks { get; private set; } + /// + /// Returns a list containing the Outputs that we want to expose. + /// + public FeedbackCollection Feedbacks { get; private set; } public BoolFeedback IsOnline { get; private set; } public BoolFeedback IsRegistered { get; private set; } @@ -29,35 +29,35 @@ public abstract class CrestronGenericBaseDevice : EssentialsDevice, IOnline, IHa public bool PreventRegistration { get; protected set; } protected CrestronGenericBaseDevice(string key, string name, GenericBase hardware) - : base(key, name) - { - Feedbacks = new FeedbackCollection(); + : base(key, name) + { + Feedbacks = new FeedbackCollection(); - Hardware = hardware; - IsOnline = new BoolFeedback("IsOnlineFeedback", () => Hardware.IsOnline); - IsRegistered = new BoolFeedback("IsRegistered", () => Hardware.Registered); - IpConnectionsText = new StringFeedback("IpConnectionsText", () => Hardware.ConnectedIpList != null ? string.Join(",", Hardware.ConnectedIpList.Select(cip => cip.DeviceIpAddress).ToArray()) : string.Empty); - AddToFeedbackList(IsOnline, IpConnectionsText); + Hardware = hardware; + IsOnline = new BoolFeedback("IsOnlineFeedback", () => Hardware.IsOnline); + IsRegistered = new BoolFeedback("IsRegistered", () => Hardware.Registered); + IpConnectionsText = new StringFeedback("IpConnectionsText", () => Hardware.ConnectedIpList != null ? string.Join(",", Hardware.ConnectedIpList.Select(cip => cip.DeviceIpAddress).ToArray()) : string.Empty); + AddToFeedbackList(IsOnline, IpConnectionsText); - CommunicationMonitor = new CrestronGenericBaseCommunicationMonitor(this, hardware, 120000, 300000); - } + CommunicationMonitor = new CrestronGenericBaseCommunicationMonitor(this, hardware, 120000, 300000); + } - protected CrestronGenericBaseDevice(string key, string name) - : base(key, name) - { - Feedbacks = new FeedbackCollection(); + protected CrestronGenericBaseDevice(string key, string name) + : base(key, name) + { + Feedbacks = new FeedbackCollection(); - } + } protected void RegisterCrestronGenericBase(GenericBase hardware) { - Hardware = hardware; - IsOnline = new BoolFeedback("IsOnlineFeedback", () => Hardware.IsOnline); - IsRegistered = new BoolFeedback("IsRegistered", () => Hardware.Registered); - IpConnectionsText = new StringFeedback("IpConnectionsText", () => Hardware.ConnectedIpList != null ? string.Join(",", Hardware.ConnectedIpList.Select(cip => cip.DeviceIpAddress).ToArray()) : string.Empty); - AddToFeedbackList(IsOnline, IpConnectionsText); + Hardware = hardware; + IsOnline = new BoolFeedback("IsOnlineFeedback", () => Hardware.IsOnline); + IsRegistered = new BoolFeedback("IsRegistered", () => Hardware.Registered); + IpConnectionsText = new StringFeedback("IpConnectionsText", () => Hardware.ConnectedIpList != null ? string.Join(",", Hardware.ConnectedIpList.Select(cip => cip.DeviceIpAddress).ToArray()) : string.Empty); + AddToFeedbackList(IsOnline, IpConnectionsText); - CommunicationMonitor = new CrestronGenericBaseCommunicationMonitor(this, hardware, 120000, 300000); + CommunicationMonitor = new CrestronGenericBaseCommunicationMonitor(this, hardware, 120000, 300000); } /// @@ -66,43 +66,43 @@ protected void RegisterCrestronGenericBase(GenericBase hardware) /// public override bool CustomActivate() { - Debug.LogMessage(LogEventLevel.Information, this, "Activating"); - if (!PreventRegistration) - { - //Debug.LogMessage(LogEventLevel.Debug, this, " Does not require registration. Skipping"); + Debug.LogMessage(LogEventLevel.Information, this, "Activating"); + if (!PreventRegistration) + { + //Debug.LogMessage(LogEventLevel.Debug, this, " Does not require registration. Skipping"); - if (Hardware.Registerable && !Hardware.Registered) + if (Hardware.Registerable && !Hardware.Registered) + { + var response = Hardware.RegisterWithLogging(Key); + if (response != eDeviceRegistrationUnRegistrationResponse.Success) { - var response = Hardware.RegisterWithLogging(Key); - if (response != eDeviceRegistrationUnRegistrationResponse.Success) - { - //Debug.LogMessage(LogEventLevel.Information, this, "ERROR: Cannot register Crestron device: {0}", response); - return false; - } + //Debug.LogMessage(LogEventLevel.Information, this, "ERROR: Cannot register Crestron device: {0}", response); + return false; } - - IsRegistered.FireUpdate(); } - else - { - AddPostActivationAction(() => + + IsRegistered.FireUpdate(); + } + else + { + AddPostActivationAction(() => + { + if (Hardware.Registerable && !Hardware.Registered) { - if (Hardware.Registerable && !Hardware.Registered) - { - var response = Hardware.RegisterWithLogging(Key); - } + var response = Hardware.RegisterWithLogging(Key); + } - IsRegistered.FireUpdate(); - }); - } + IsRegistered.FireUpdate(); + }); + } - foreach (var f in Feedbacks) - { - f.FireUpdate(); - } + foreach (var f in Feedbacks) + { + f.FireUpdate(); + } - Hardware.OnlineStatusChange += Hardware_OnlineStatusChange; - CommunicationMonitor.Start(); + Hardware.OnlineStatusChange += Hardware_OnlineStatusChange; + CommunicationMonitor.Start(); return base.CustomActivate(); } @@ -118,42 +118,42 @@ public override bool Deactivate() var success = Hardware.UnRegister() == eDeviceRegistrationUnRegistrationResponse.Success; - IsRegistered.FireUpdate(); + IsRegistered.FireUpdate(); - return success; + return success; } /// - /// Adds feedback(s) to the list - /// - /// - public void AddToFeedbackList(params Feedback[] newFbs) + /// Adds feedback(s) to the list + /// + /// + public void AddToFeedbackList(params Feedback[] newFbs) + { + foreach (var f in newFbs) { - foreach (var f in newFbs) - { - if (f == null) continue; + if (f == null) continue; - if (!Feedbacks.Contains(f)) - { - Feedbacks.Add(f); - } + if (!Feedbacks.Contains(f)) + { + Feedbacks.Add(f); } } + } void Hardware_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args) { - Debug.LogMessage(LogEventLevel.Verbose, this, "OnlineStatusChange Event. Online = {0}", args.DeviceOnLine); + Debug.LogMessage(LogEventLevel.Verbose, this, "OnlineStatusChange Event. Online = {0}", args.DeviceOnLine); - if (!Hardware.Registered) - { - return; // protects in cases where device has been unregistered and feedbacks would attempt to access null sigs. - } + if (!Hardware.Registered) + { + return; // protects in cases where device has been unregistered and feedbacks would attempt to access null sigs. + } - foreach (var feedback in Feedbacks) - { - if (feedback != null) - feedback.FireUpdate(); - } + foreach (var feedback in Feedbacks) + { + if (feedback != null) + feedback.FireUpdate(); + } } #region IStatusMonitor Members @@ -161,27 +161,27 @@ void Hardware_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventAr public StatusMonitorBase CommunicationMonitor { get; private set; } #endregion - #region IUsageTracking Members + #region IUsageTracking Members - public UsageTracking UsageTracker { get; set; } + public UsageTracking UsageTracker { get; set; } - #endregion + #endregion } - public abstract class CrestronGenericBridgeableBaseDevice : CrestronGenericBaseDevice, IBridgeAdvanced +public abstract class CrestronGenericBridgeableBaseDevice : CrestronGenericBaseDevice, IBridgeAdvanced +{ + protected CrestronGenericBridgeableBaseDevice(string key, string name, GenericBase hardware) : base(key, name, hardware) { - protected CrestronGenericBridgeableBaseDevice(string key, string name, GenericBase hardware) : base(key, name, hardware) - { - } + } - protected CrestronGenericBridgeableBaseDevice(string key, string name) - : base(key, name) - { - } + protected CrestronGenericBridgeableBaseDevice(string key, string name) + : base(key, name) + { + } - public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge); - } + public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge); +} //*********************************************************************************** @@ -208,5 +208,4 @@ public static eDeviceRegistrationUnRegistrationResponse RegisterWithLogging(this return result; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/CrestronIO/GenericDigitalInputDevice.cs b/src/PepperDash.Essentials.Core/CrestronIO/GenericDigitalInputDevice.cs index a5923011d..34b363717 100644 --- a/src/PepperDash.Essentials.Core/CrestronIO/GenericDigitalInputDevice.cs +++ b/src/PepperDash.Essentials.Core/CrestronIO/GenericDigitalInputDevice.cs @@ -14,155 +14,152 @@ using Serilog.Events; -namespace PepperDash.Essentials.Core.CrestronIO +namespace PepperDash.Essentials.Core.CrestronIO; + +[Description("Wrapper class for Digital Input")] +public class GenericDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput { - [Description("Wrapper class for Digital Input")] - public class GenericDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput - { - public DigitalInput InputPort { get; private set; } + public DigitalInput InputPort { get; private set; } - public BoolFeedback InputStateFeedback { get; private set; } + public BoolFeedback InputStateFeedback { get; private set; } - Func InputStateFeedbackFunc + Func InputStateFeedbackFunc + { + get { - get - { - return () => InputPort.State; - } + return () => InputPort.State; } + } - public GenericDigitalInputDevice(string key, string name, Func postActivationFunc, - IOPortConfig config) - : base(key, name) + public GenericDigitalInputDevice(string key, string name, Func postActivationFunc, + IOPortConfig config) + : base(key, name) + { + InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc); + + AddPostActivationAction(() => { - InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc); + InputPort = postActivationFunc(config); - AddPostActivationAction(() => - { - InputPort = postActivationFunc(config); + InputPort.Register(); - InputPort.Register(); + InputPort.StateChange += InputPort_StateChange; - InputPort.StateChange += InputPort_StateChange; + }); + } - }); - } + #region Events - #region Events + void InputPort_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args) + { + InputStateFeedback.FireUpdate(); + } - void InputPort_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args) - { - InputStateFeedback.FireUpdate(); - } + #endregion - #endregion + #region PreActivate - #region PreActivate + private static DigitalInput GetDigitalInput(IOPortConfig dc) + { + IDigitalInputPorts ioPortDevice; - private static DigitalInput GetDigitalInput(IOPortConfig dc) + if (dc.PortDeviceKey.Equals("processor")) { - IDigitalInputPorts ioPortDevice; - - if (dc.PortDeviceKey.Equals("processor")) - { - if (!Global.ControlSystem.SupportsDigitalInput) - { - Debug.LogMessage(LogEventLevel.Information, "GetDigitalInput: Processor does not support Digital Inputs"); - return null; - } - ioPortDevice = Global.ControlSystem; - } - else + if (!Global.ControlSystem.SupportsDigitalInput) { - var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IDigitalInputPorts; - if (ioPortDev == null) - { - Debug.LogMessage(LogEventLevel.Information, "GetDigitalInput: Device {0} is not a valid device", dc.PortDeviceKey); - return null; - } - ioPortDevice = ioPortDev; + Debug.LogMessage(LogEventLevel.Information, "GetDigitalInput: Processor does not support Digital Inputs"); + return null; } - if (ioPortDevice == null) + ioPortDevice = Global.ControlSystem; + } + else + { + var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IDigitalInputPorts; + if (ioPortDev == null) { - Debug.LogMessage(LogEventLevel.Information, "GetDigitalInput: Device '0' is not a valid IDigitalInputPorts Device", dc.PortDeviceKey); + Debug.LogMessage(LogEventLevel.Information, "GetDigitalInput: Device {0} is not a valid device", dc.PortDeviceKey); return null; } + ioPortDevice = ioPortDev; + } + if (ioPortDevice == null) + { + Debug.LogMessage(LogEventLevel.Information, "GetDigitalInput: Device '0' is not a valid IDigitalInputPorts Device", dc.PortDeviceKey); + return null; + } - if (dc.PortNumber > ioPortDevice.NumberOfDigitalInputPorts) - { - Debug.LogMessage(LogEventLevel.Information, "GetDigitalInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber); - } + if (dc.PortNumber > ioPortDevice.NumberOfDigitalInputPorts) + { + Debug.LogMessage(LogEventLevel.Information, "GetDigitalInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber); + } - return ioPortDevice.DigitalInputPorts[dc.PortNumber]; + return ioPortDevice.DigitalInputPorts[dc.PortNumber]; - } + } - #endregion + #endregion - #region Bridge Linking + #region Bridge Linking - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = new IDigitalInputJoinMap(joinStart); + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new IDigitalInputJoinMap(joinStart); - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - if (!string.IsNullOrEmpty(joinMapSerialized)) - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } - try - { - Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + try + { + Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - // Link feedback for input state - InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Input is null", Key); - Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e); - } + // Link feedback for input state + InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]); + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Input is null", Key); + Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e); } + } - #endregion + #endregion - #region Factory + #region Factory - public class GenericDigitalInputDeviceFactory : EssentialsDeviceFactory + public class GenericDigitalInputDeviceFactory : EssentialsDeviceFactory + { + public GenericDigitalInputDeviceFactory() { - public GenericDigitalInputDeviceFactory() - { - TypeNames = new List() { "digitalinput" }; - } + TypeNames = new List() { "digitalinput" }; + } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Digital Input Device"); + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Digital Input Device"); - var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); - if (props == null) return null; + if (props == null) return null; - var portDevice = new GenericDigitalInputDevice(dc.Key, dc.Name, GetDigitalInput, props); + var portDevice = new GenericDigitalInputDevice(dc.Key, dc.Name, GetDigitalInput, props); - return portDevice; - } + return portDevice; } - - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/CrestronIO/GenericRelayDevice.cs b/src/PepperDash.Essentials.Core/CrestronIO/GenericRelayDevice.cs index 2bc2c50bc..15dfcd365 100644 --- a/src/PepperDash.Essentials.Core/CrestronIO/GenericRelayDevice.cs +++ b/src/PepperDash.Essentials.Core/CrestronIO/GenericRelayDevice.cs @@ -13,212 +13,209 @@ using PepperDash.Essentials.Core.Config; using Serilog.Events; -namespace PepperDash.Essentials.Core.CrestronIO +namespace PepperDash.Essentials.Core.CrestronIO; + +/// +/// Represents a generic device controlled by relays +/// +[Description("Wrapper class for a Relay")] +public class GenericRelayDevice : EssentialsBridgeableDevice, ISwitchedOutput { - /// - /// Represents a generic device controlled by relays - /// - [Description("Wrapper class for a Relay")] - public class GenericRelayDevice : EssentialsBridgeableDevice, ISwitchedOutput - { - public Relay RelayOutput { get; private set; } + public Relay RelayOutput { get; private set; } - public BoolFeedback OutputIsOnFeedback { get; private set; } + public BoolFeedback OutputIsOnFeedback { get; private set; } - //Maintained for compatibility with PepperDash.Essentials.Core.Devices.CrestronProcessor - public GenericRelayDevice(string key, Relay relay) : - base(key) - { - OutputIsOnFeedback = new BoolFeedback(new Func(() => RelayOutput.State)); + //Maintained for compatibility with PepperDash.Essentials.Core.Devices.CrestronProcessor + public GenericRelayDevice(string key, Relay relay) : + base(key) + { + OutputIsOnFeedback = new BoolFeedback(new Func(() => RelayOutput.State)); - RelayOutput = relay; - RelayOutput.Register(); + RelayOutput = relay; + RelayOutput.Register(); - RelayOutput.StateChange += RelayOutput_StateChange; - } + RelayOutput.StateChange += RelayOutput_StateChange; + } + + public GenericRelayDevice(string key, string name, Func postActivationFunc, + IOPortConfig config) + : base(key, name) + { + OutputIsOnFeedback = new BoolFeedback(() => RelayOutput.State); - public GenericRelayDevice(string key, string name, Func postActivationFunc, - IOPortConfig config) - : base(key, name) + AddPostActivationAction(() => { - OutputIsOnFeedback = new BoolFeedback(() => RelayOutput.State); + RelayOutput = postActivationFunc(config); - AddPostActivationAction(() => + if (RelayOutput == null) { - RelayOutput = postActivationFunc(config); - - if (RelayOutput == null) - { - Debug.LogMessage(LogEventLevel.Information, this, "Unable to get parent relay device for device key {0} and port {1}", config.PortDeviceKey, config.PortNumber); - return; - } + Debug.LogMessage(LogEventLevel.Information, this, "Unable to get parent relay device for device key {0} and port {1}", config.PortDeviceKey, config.PortNumber); + return; + } - RelayOutput.Register(); + RelayOutput.Register(); - RelayOutput.StateChange += RelayOutput_StateChange; - }); - } + RelayOutput.StateChange += RelayOutput_StateChange; + }); + } - #region PreActivate + #region PreActivate - private static Relay GetRelay(IOPortConfig dc) - { + private static Relay GetRelay(IOPortConfig dc) + { - IRelayPorts relayDevice; + IRelayPorts relayDevice; - if(dc.PortDeviceKey.Equals("processor")) - { - if (!Global.ControlSystem.SupportsRelay) - { - Debug.LogMessage(LogEventLevel.Information, "Processor does not support relays"); - return null; - } - relayDevice = Global.ControlSystem; - - return relayDevice.RelayPorts[dc.PortNumber]; - } - - var essentialsDevice = DeviceManager.GetDeviceForKey(dc.PortDeviceKey); - if (essentialsDevice == null) - { - Debug.LogMessage(LogEventLevel.Information, "Device {0} was not found in Device Manager. Check configuration or for errors with device.", dc.PortDeviceKey); - return null; - } - - relayDevice = essentialsDevice as IRelayPorts; - - if (relayDevice == null) + if(dc.PortDeviceKey.Equals("processor")) + { + if (!Global.ControlSystem.SupportsRelay) { - Debug.LogMessage(LogEventLevel.Information, "Device {0} is not a valid relay parent. Please check configuration.", dc.PortDeviceKey); + Debug.LogMessage(LogEventLevel.Information, "Processor does not support relays"); return null; } + relayDevice = Global.ControlSystem; - if (dc.PortNumber <= relayDevice.NumberOfRelayPorts) - { - return relayDevice.RelayPorts[dc.PortNumber]; - } - - Debug.LogMessage(LogEventLevel.Information, "Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber); + return relayDevice.RelayPorts[dc.PortNumber]; + } + + var essentialsDevice = DeviceManager.GetDeviceForKey(dc.PortDeviceKey); + if (essentialsDevice == null) + { + Debug.LogMessage(LogEventLevel.Information, "Device {0} was not found in Device Manager. Check configuration or for errors with device.", dc.PortDeviceKey); return null; } - #endregion - - #region Events + relayDevice = essentialsDevice as IRelayPorts; + + if (relayDevice == null) + { + Debug.LogMessage(LogEventLevel.Information, "Device {0} is not a valid relay parent. Please check configuration.", dc.PortDeviceKey); + return null; + } - void RelayOutput_StateChange(Relay relay, RelayEventArgs args) + if (dc.PortNumber <= relayDevice.NumberOfRelayPorts) { - OutputIsOnFeedback.FireUpdate(); + return relayDevice.RelayPorts[dc.PortNumber]; } - #endregion + Debug.LogMessage(LogEventLevel.Information, "Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber); + return null; + } - #region Methods + #endregion - public void OpenRelay() - { - RelayOutput.State = false; - } + #region Events - public void CloseRelay() - { - RelayOutput.State = true; - } + void RelayOutput_StateChange(Relay relay, RelayEventArgs args) + { + OutputIsOnFeedback.FireUpdate(); + } - public void ToggleRelayState() - { - if (RelayOutput.State == true) - OpenRelay(); - else - CloseRelay(); - } + #endregion - #endregion + #region Methods - #region ISwitchedOutput Members + public void OpenRelay() + { + RelayOutput.State = false; + } - void ISwitchedOutput.On() - { - CloseRelay(); - } + public void CloseRelay() + { + RelayOutput.State = true; + } - void ISwitchedOutput.Off() - { + public void ToggleRelayState() + { + if (RelayOutput.State == true) OpenRelay(); - } - - #endregion + else + CloseRelay(); + } - #region Bridge Linking + #endregion - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = new GenericRelayControllerJoinMap(joinStart); + #region ISwitchedOutput Members - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + void ISwitchedOutput.On() + { + CloseRelay(); + } - if (!string.IsNullOrEmpty(joinMapSerialized)) - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + void ISwitchedOutput.Off() + { + OpenRelay(); + } - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } + #endregion - if (RelayOutput == null) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Relay is null", Key); - return; - } + #region Bridge Linking - Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new GenericRelayControllerJoinMap(joinStart); - trilist.SetBoolSigAction(joinMap.Relay.JoinNumber, b => - { - if (b) - CloseRelay(); - else - OpenRelay(); - }); + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - // feedback for relay state + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); - OutputIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Relay.JoinNumber]); + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); } - #endregion + if (RelayOutput == null) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Relay is null", Key); + return; + } - #region Factory + Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - public class GenericRelayDeviceFactory : EssentialsDeviceFactory + trilist.SetBoolSigAction(joinMap.Relay.JoinNumber, b => { - public GenericRelayDeviceFactory() - { - TypeNames = new List() { "relayoutput" }; - } + if (b) + CloseRelay(); + else + OpenRelay(); + }); - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Relay Device"); + // feedback for relay state - var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + OutputIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Relay.JoinNumber]); + } - if (props == null) return null; + #endregion - var portDevice = new GenericRelayDevice(dc.Key, dc.Name, GetRelay, props); + #region Factory - return portDevice; - } + public class GenericRelayDeviceFactory : EssentialsDeviceFactory + { + public GenericRelayDeviceFactory() + { + TypeNames = new List() { "relayoutput" }; } - #endregion + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Relay Device"); + + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + if (props == null) return null; + var portDevice = new GenericRelayDevice(dc.Key, dc.Name, GetRelay, props); + + return portDevice; + } } + #endregion + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/CrestronIO/GenericVersiportAnalogInputDevice.cs b/src/PepperDash.Essentials.Core/CrestronIO/GenericVersiportAnalogInputDevice.cs index af83b3d6f..42b83dfdf 100644 --- a/src/PepperDash.Essentials.Core/CrestronIO/GenericVersiportAnalogInputDevice.cs +++ b/src/PepperDash.Essentials.Core/CrestronIO/GenericVersiportAnalogInputDevice.cs @@ -16,196 +16,195 @@ using Newtonsoft.Json; using Serilog.Events; -namespace PepperDash.Essentials.Core.CrestronIO +namespace PepperDash.Essentials.Core.CrestronIO; + +/// +/// Represents a generic digital input deviced tied to a versiport +/// +public class GenericVersiportAnalogInputDevice : EssentialsBridgeableDevice, IAnalogInput { - /// - /// Represents a generic digital input deviced tied to a versiport - /// - public class GenericVersiportAnalogInputDevice : EssentialsBridgeableDevice, IAnalogInput - { - public Versiport InputPort { get; private set; } + public Versiport InputPort { get; private set; } - public IntFeedback InputValueFeedback { get; private set; } - public IntFeedback InputMinimumChangeFeedback { get; private set; } + public IntFeedback InputValueFeedback { get; private set; } + public IntFeedback InputMinimumChangeFeedback { get; private set; } - Func InputValueFeedbackFunc + Func InputValueFeedbackFunc + { + get { - get - { - return () => InputPort.AnalogIn; - } + return () => InputPort.AnalogIn; } + } - Func InputMinimumChangeFeedbackFunc - { - get { return () => InputPort.AnalogMinChange; } - } + Func InputMinimumChangeFeedbackFunc + { + get { return () => InputPort.AnalogMinChange; } + } - public GenericVersiportAnalogInputDevice(string key, string name, Func postActivationFunc, IOPortConfig config) : - base(key, name) - { - InputValueFeedback = new IntFeedback(InputValueFeedbackFunc); - InputMinimumChangeFeedback = new IntFeedback(InputMinimumChangeFeedbackFunc); + public GenericVersiportAnalogInputDevice(string key, string name, Func postActivationFunc, IOPortConfig config) : + base(key, name) + { + InputValueFeedback = new IntFeedback(InputValueFeedbackFunc); + InputMinimumChangeFeedback = new IntFeedback(InputMinimumChangeFeedbackFunc); - AddPostActivationAction(() => - { - InputPort = postActivationFunc(config); + AddPostActivationAction(() => + { + InputPort = postActivationFunc(config); - InputPort.Register(); + InputPort.Register(); - InputPort.SetVersiportConfiguration(eVersiportConfiguration.AnalogInput); - InputPort.AnalogMinChange = (ushort)(config.MinimumChange > 0 ? config.MinimumChange : 655); - if (config.DisablePullUpResistor) - InputPort.DisablePullUpResistor = true; + InputPort.SetVersiportConfiguration(eVersiportConfiguration.AnalogInput); + InputPort.AnalogMinChange = (ushort)(config.MinimumChange > 0 ? config.MinimumChange : 655); + if (config.DisablePullUpResistor) + InputPort.DisablePullUpResistor = true; - InputPort.VersiportChange += InputPort_VersiportChange; + InputPort.VersiportChange += InputPort_VersiportChange; - Debug.LogMessage(LogEventLevel.Debug, this, "Created GenericVersiportAnalogInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, InputPort.DisablePullUpResistor); + Debug.LogMessage(LogEventLevel.Debug, this, "Created GenericVersiportAnalogInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, InputPort.DisablePullUpResistor); - }); + }); - } + } - /// - /// Set minimum voltage change for device to update voltage changed method - /// - /// valid values range from 0 - 65535, representing the full 100% range of the processor voltage source. Check processor documentation for details - public void SetMinimumChange(ushort value) - { - InputPort.AnalogMinChange = value; - } + /// + /// Set minimum voltage change for device to update voltage changed method + /// + /// valid values range from 0 - 65535, representing the full 100% range of the processor voltage source. Check processor documentation for details + public void SetMinimumChange(ushort value) + { + InputPort.AnalogMinChange = value; + } - void InputPort_VersiportChange(Versiport port, VersiportEventArgs args) - { + void InputPort_VersiportChange(Versiport port, VersiportEventArgs args) + { Debug.LogMessage(LogEventLevel.Debug, this, "Versiport change: {0}", args.Event); - if(args.Event == eVersiportEvent.AnalogInChange) - InputValueFeedback.FireUpdate(); - if (args.Event == eVersiportEvent.AnalogMinChangeChange) - InputMinimumChangeFeedback.FireUpdate(); - } - + if(args.Event == eVersiportEvent.AnalogInChange) + InputValueFeedback.FireUpdate(); + if (args.Event == eVersiportEvent.AnalogMinChangeChange) + InputMinimumChangeFeedback.FireUpdate(); + } - #region Bridge Linking - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = new IAnalogInputJoinMap(joinStart); + #region Bridge Linking - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - - if (!string.IsNullOrEmpty(joinMapSerialized)) - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new IAnalogInputJoinMap(joinStart); - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - try - { - Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); - // Link feedback for input state - InputValueFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputValue.JoinNumber]); - InputMinimumChangeFeedback.LinkInputSig(trilist.UShortInput[joinMap.MinimumChange.JoinNumber]); - trilist.SetUShortSigAction(joinMap.MinimumChange.JoinNumber, SetMinimumChange); + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Input is null", Key); - Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e); - } + try + { + Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - trilist.OnlineStatusChange += (d, args) => - { - if (!args.DeviceOnLine) return; - InputValueFeedback.FireUpdate(); - InputMinimumChangeFeedback.FireUpdate(); - }; + // Link feedback for input state + InputValueFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputValue.JoinNumber]); + InputMinimumChangeFeedback.LinkInputSig(trilist.UShortInput[joinMap.MinimumChange.JoinNumber]); + trilist.SetUShortSigAction(joinMap.MinimumChange.JoinNumber, SetMinimumChange); } - - void trilist_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args) + catch (Exception e) { - throw new NotImplementedException(); + Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Input is null", Key); + Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e); } - #endregion + trilist.OnlineStatusChange += (d, args) => + { + if (!args.DeviceOnLine) return; + InputValueFeedback.FireUpdate(); + InputMinimumChangeFeedback.FireUpdate(); + }; + } - public static Versiport GetVersiportDigitalInput(IOPortConfig dc) - { - - IIOPorts ioPortDevice; + void trilist_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args) + { + throw new NotImplementedException(); + } - if (dc.PortDeviceKey.Equals("processor")) - { - if (!Global.ControlSystem.SupportsVersiport) - { - Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Processor does not support Versiports"); - return null; - } - ioPortDevice = Global.ControlSystem; - } - else - { - var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts; - if (ioPortDev == null) - { - Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Device {0} is not a valid device", dc.PortDeviceKey); - return null; - } - ioPortDevice = ioPortDev; - } - if (ioPortDevice == null) - { - Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Device '0' is not a valid IIOPorts Device", dc.PortDeviceKey); - return null; - } + #endregion + + + public static Versiport GetVersiportDigitalInput(IOPortConfig dc) + { + + IIOPorts ioPortDevice; - if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts) + if (dc.PortDeviceKey.Equals("processor")) + { + if (!Global.ControlSystem.SupportsVersiport) { - Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber); + Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Processor does not support Versiports"); return null; } - if(!ioPortDevice.VersiPorts[dc.PortNumber].SupportsAnalogInput) + ioPortDevice = Global.ControlSystem; + } + else + { + var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts; + if (ioPortDev == null) { - Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Device {0} does not support AnalogInput on port {1}", dc.PortDeviceKey, dc.PortNumber); + Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Device {0} is not a valid device", dc.PortDeviceKey); return null; } + ioPortDevice = ioPortDev; + } + if (ioPortDevice == null) + { + Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Device '0' is not a valid IIOPorts Device", dc.PortDeviceKey); + return null; + } + if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts) + { + Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber); + return null; + } + if(!ioPortDevice.VersiPorts[dc.PortNumber].SupportsAnalogInput) + { + Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Device {0} does not support AnalogInput on port {1}", dc.PortDeviceKey, dc.PortNumber); + return null; + } - return ioPortDevice.VersiPorts[dc.PortNumber]; + + return ioPortDevice.VersiPorts[dc.PortNumber]; - } } +} - public class GenericVersiportAbalogInputDeviceFactory : EssentialsDeviceFactory +public class GenericVersiportAbalogInputDeviceFactory : EssentialsDeviceFactory +{ + public GenericVersiportAbalogInputDeviceFactory() { - public GenericVersiportAbalogInputDeviceFactory() - { - TypeNames = new List() { "versiportanaloginput" }; - } + TypeNames = new List() { "versiportanaloginput" }; + } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Versiport Device"); + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Versiport Device"); - var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); - if (props == null) return null; + if (props == null) return null; - var portDevice = new GenericVersiportAnalogInputDevice(dc.Key, dc.Name, GenericVersiportAnalogInputDevice.GetVersiportDigitalInput, props); + var portDevice = new GenericVersiportAnalogInputDevice(dc.Key, dc.Name, GenericVersiportAnalogInputDevice.GetVersiportDigitalInput, props); - return portDevice; - } + return portDevice; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/CrestronIO/GenericVersiportInputDevice.cs b/src/PepperDash.Essentials.Core/CrestronIO/GenericVersiportInputDevice.cs index c9133a607..c71ffc50e 100644 --- a/src/PepperDash.Essentials.Core/CrestronIO/GenericVersiportInputDevice.cs +++ b/src/PepperDash.Essentials.Core/CrestronIO/GenericVersiportInputDevice.cs @@ -16,165 +16,164 @@ using Newtonsoft.Json; using Serilog.Events; -namespace PepperDash.Essentials.Core.CrestronIO +namespace PepperDash.Essentials.Core.CrestronIO; + +/// +/// Represents a generic digital input deviced tied to a versiport +/// +public class GenericVersiportDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput, IPartitionStateProvider { - /// - /// Represents a generic digital input deviced tied to a versiport - /// - public class GenericVersiportDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput, IPartitionStateProvider - { - public Versiport InputPort { get; private set; } + public Versiport InputPort { get; private set; } - public BoolFeedback InputStateFeedback { get; private set; } + public BoolFeedback InputStateFeedback { get; private set; } - Func InputStateFeedbackFunc + Func InputStateFeedbackFunc + { + get { - get - { - return () => InputPort.DigitalIn; - } + return () => InputPort.DigitalIn; } + } - public BoolFeedback PartitionPresentFeedback { get; } + public BoolFeedback PartitionPresentFeedback { get; } - public bool PartitionPresent => !InputStateFeedbackFunc(); + public bool PartitionPresent => !InputStateFeedbackFunc(); - public GenericVersiportDigitalInputDevice(string key, string name, Func postActivationFunc, IOPortConfig config) : - base(key, name) - { - InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc); - PartitionPresentFeedback = new BoolFeedback(() => !InputStateFeedbackFunc()); + public GenericVersiportDigitalInputDevice(string key, string name, Func postActivationFunc, IOPortConfig config) : + base(key, name) + { + InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc); + PartitionPresentFeedback = new BoolFeedback(() => !InputStateFeedbackFunc()); - AddPostActivationAction(() => - { - InputPort = postActivationFunc(config); + AddPostActivationAction(() => + { + InputPort = postActivationFunc(config); - InputPort.Register(); + InputPort.Register(); - InputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput); - if (config.DisablePullUpResistor) - InputPort.DisablePullUpResistor = true; + InputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput); + if (config.DisablePullUpResistor) + InputPort.DisablePullUpResistor = true; - InputPort.VersiportChange += InputPort_VersiportChange; + InputPort.VersiportChange += InputPort_VersiportChange; - InputStateFeedback.FireUpdate(); - PartitionPresentFeedback.FireUpdate(); + InputStateFeedback.FireUpdate(); + PartitionPresentFeedback.FireUpdate(); - Debug.LogMessage(LogEventLevel.Debug, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, InputPort.DisablePullUpResistor); + Debug.LogMessage(LogEventLevel.Debug, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, InputPort.DisablePullUpResistor); - }); + }); - } + } - void InputPort_VersiportChange(Versiport port, VersiportEventArgs args) - { + void InputPort_VersiportChange(Versiport port, VersiportEventArgs args) + { Debug.LogMessage(LogEventLevel.Debug, this, "Versiport change: {0}", args.Event); - if(args.Event == eVersiportEvent.DigitalInChange) - { - InputStateFeedback.FireUpdate(); - PartitionPresentFeedback.FireUpdate(); - } + if(args.Event == eVersiportEvent.DigitalInChange) + { + InputStateFeedback.FireUpdate(); + PartitionPresentFeedback.FireUpdate(); } + } - #region Bridge Linking + #region Bridge Linking - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = new IDigitalInputJoinMap(joinStart); + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new IDigitalInputJoinMap(joinStart); - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - if (!string.IsNullOrEmpty(joinMapSerialized)) - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } - try - { - Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + try + { + Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - // Link feedback for input state - InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Input is null", Key); - Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e); - } + // Link feedback for input state + InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]); + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Input is null", Key); + Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e); } + } - #endregion + #endregion - public static Versiport GetVersiportDigitalInput(IOPortConfig dc) - { - - IIOPorts ioPortDevice; + public static Versiport GetVersiportDigitalInput(IOPortConfig dc) + { + + IIOPorts ioPortDevice; - if (dc.PortDeviceKey.Equals("processor")) - { - if (!Global.ControlSystem.SupportsVersiport) - { - Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalInput: Processor does not support Versiports"); - return null; - } - ioPortDevice = Global.ControlSystem; - } - else + if (dc.PortDeviceKey.Equals("processor")) + { + if (!Global.ControlSystem.SupportsVersiport) { - var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts; - if (ioPortDev == null) - { - Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalInput: Device {0} is not a valid device", dc.PortDeviceKey); - return null; - } - ioPortDevice = ioPortDev; + Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalInput: Processor does not support Versiports"); + return null; } - if (ioPortDevice == null) + ioPortDevice = Global.ControlSystem; + } + else + { + var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts; + if (ioPortDev == null) { - Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalInput: Device '0' is not a valid IIOPorts Device", dc.PortDeviceKey); + Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalInput: Device {0} is not a valid device", dc.PortDeviceKey); return null; } + ioPortDevice = ioPortDev; + } + if (ioPortDevice == null) + { + Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalInput: Device '0' is not a valid IIOPorts Device", dc.PortDeviceKey); + return null; + } - if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts) - { - Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber); - } + if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts) + { + Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber); + } - return ioPortDevice.VersiPorts[dc.PortNumber]; + return ioPortDevice.VersiPorts[dc.PortNumber]; - } } +} - public class GenericVersiportDigitalInputDeviceFactory : EssentialsDeviceFactory +public class GenericVersiportDigitalInputDeviceFactory : EssentialsDeviceFactory +{ + public GenericVersiportDigitalInputDeviceFactory() { - public GenericVersiportDigitalInputDeviceFactory() - { - TypeNames = new List() { "versiportinput" }; - } + TypeNames = new List() { "versiportinput" }; + } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Versiport Device"); + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Versiport Device"); - var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); - if (props == null) return null; + if (props == null) return null; - var portDevice = new GenericVersiportDigitalInputDevice(dc.Key, dc.Name, GenericVersiportDigitalInputDevice.GetVersiportDigitalInput, props); + var portDevice = new GenericVersiportDigitalInputDevice(dc.Key, dc.Name, GenericVersiportDigitalInputDevice.GetVersiportDigitalInput, props); - return portDevice; - } + return portDevice; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/CrestronIO/GenericVersiportOutputDevice.cs b/src/PepperDash.Essentials.Core/CrestronIO/GenericVersiportOutputDevice.cs index 030dc6136..e2304baf9 100644 --- a/src/PepperDash.Essentials.Core/CrestronIO/GenericVersiportOutputDevice.cs +++ b/src/PepperDash.Essentials.Core/CrestronIO/GenericVersiportOutputDevice.cs @@ -16,177 +16,176 @@ using Newtonsoft.Json; using Serilog.Events; -namespace PepperDash.Essentials.Core.CrestronIO +namespace PepperDash.Essentials.Core.CrestronIO; + +/// +/// Represents a generic digital input deviced tied to a versiport +/// +public class GenericVersiportDigitalOutputDevice : EssentialsBridgeableDevice, IDigitalOutput { - /// - /// Represents a generic digital input deviced tied to a versiport - /// - public class GenericVersiportDigitalOutputDevice : EssentialsBridgeableDevice, IDigitalOutput - { - public Versiport OutputPort { get; private set; } + public Versiport OutputPort { get; private set; } - public BoolFeedback OutputStateFeedback { get; private set; } + public BoolFeedback OutputStateFeedback { get; private set; } - Func OutputStateFeedbackFunc + Func OutputStateFeedbackFunc + { + get { - get - { - return () => OutputPort.DigitalOut; - } + return () => OutputPort.DigitalOut; } + } - public GenericVersiportDigitalOutputDevice(string key, string name, Func postActivationFunc, IOPortConfig config) : - base(key, name) - { - OutputStateFeedback = new BoolFeedback(OutputStateFeedbackFunc); + public GenericVersiportDigitalOutputDevice(string key, string name, Func postActivationFunc, IOPortConfig config) : + base(key, name) + { + OutputStateFeedback = new BoolFeedback(OutputStateFeedbackFunc); - AddPostActivationAction(() => - { - OutputPort = postActivationFunc(config); + AddPostActivationAction(() => + { + OutputPort = postActivationFunc(config); - OutputPort.Register(); + OutputPort.Register(); - if (!OutputPort.SupportsDigitalOutput) - { - Debug.LogMessage(LogEventLevel.Information, this, "Device does not support configuration as a Digital Output"); - return; - } + if (!OutputPort.SupportsDigitalOutput) + { + Debug.LogMessage(LogEventLevel.Information, this, "Device does not support configuration as a Digital Output"); + return; + } - OutputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalOutput); + OutputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalOutput); - OutputPort.VersiportChange += OutputPort_VersiportChange; + OutputPort.VersiportChange += OutputPort_VersiportChange; - }); + }); - } + } - void OutputPort_VersiportChange(Versiport port, VersiportEventArgs args) - { + void OutputPort_VersiportChange(Versiport port, VersiportEventArgs args) + { Debug.LogMessage(LogEventLevel.Debug, this, "Versiport change: {0}", args.Event); - if(args.Event == eVersiportEvent.DigitalOutChange) - OutputStateFeedback.FireUpdate(); - } + if(args.Event == eVersiportEvent.DigitalOutChange) + OutputStateFeedback.FireUpdate(); + } - /// - /// Set value of the versiport digital output - /// - /// value to set the output to - public void SetOutput(bool state) - { - if (OutputPort.SupportsDigitalOutput) - { - Debug.LogMessage(LogEventLevel.Information, this, "Passed the Check"); + /// + /// Set value of the versiport digital output + /// + /// value to set the output to + public void SetOutput(bool state) + { + if (OutputPort.SupportsDigitalOutput) + { + Debug.LogMessage(LogEventLevel.Information, this, "Passed the Check"); - OutputPort.DigitalOut = state; + OutputPort.DigitalOut = state; - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Versiport does not support Digital Output Mode"); - } + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "Versiport does not support Digital Output Mode"); + } - } + } - #region Bridge Linking + #region Bridge Linking - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = new IDigitalOutputJoinMap(joinStart); + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new IDigitalOutputJoinMap(joinStart); - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - if (!string.IsNullOrEmpty(joinMapSerialized)) - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } - try - { - Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + try + { + Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - // Link feedback for input state - OutputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.OutputState.JoinNumber]); - trilist.SetBoolSigAction(joinMap.OutputState.JoinNumber, SetOutput); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Input is null", Key); - Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e); - } + // Link feedback for input state + OutputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.OutputState.JoinNumber]); + trilist.SetBoolSigAction(joinMap.OutputState.JoinNumber, SetOutput); + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Input is null", Key); + Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e); } + } - #endregion + #endregion - public static Versiport GetVersiportDigitalOutput(IOPortConfig dc) - { + public static Versiport GetVersiportDigitalOutput(IOPortConfig dc) + { - IIOPorts ioPortDevice; + IIOPorts ioPortDevice; - if (dc.PortDeviceKey.Equals("processor")) - { - if (!Global.ControlSystem.SupportsVersiport) - { - Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOuptut: Processor does not support Versiports"); - return null; - } - ioPortDevice = Global.ControlSystem; - } - else + if (dc.PortDeviceKey.Equals("processor")) + { + if (!Global.ControlSystem.SupportsVersiport) { - var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts; - if (ioPortDev == null) - { - Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOuptut: Device {0} is not a valid device", dc.PortDeviceKey); - return null; - } - ioPortDevice = ioPortDev; + Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOuptut: Processor does not support Versiports"); + return null; } - if (ioPortDevice == null) + ioPortDevice = Global.ControlSystem; + } + else + { + var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts; + if (ioPortDev == null) { - Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOuptut: Device '0' is not a valid IOPorts Device", dc.PortDeviceKey); + Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOuptut: Device {0} is not a valid device", dc.PortDeviceKey); return null; } + ioPortDevice = ioPortDev; + } + if (ioPortDevice == null) + { + Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOuptut: Device '0' is not a valid IOPorts Device", dc.PortDeviceKey); + return null; + } - if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts) - { - Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOuptut: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber); - } - var port = ioPortDevice.VersiPorts[dc.PortNumber]; - return port; + if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts) + { + Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOuptut: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber); + } + var port = ioPortDevice.VersiPorts[dc.PortNumber]; + return port; - } } +} - public class GenericVersiportDigitalOutputDeviceFactory : EssentialsDeviceFactory +public class GenericVersiportDigitalOutputDeviceFactory : EssentialsDeviceFactory +{ + public GenericVersiportDigitalOutputDeviceFactory() { - public GenericVersiportDigitalOutputDeviceFactory() - { - TypeNames = new List() { "versiportoutput" }; - } + TypeNames = new List() { "versiportoutput" }; + } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Versiport Device"); + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Versiport Device"); - var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); - if (props == null) return null; + if (props == null) return null; - var portDevice = new GenericVersiportDigitalOutputDevice(dc.Key, dc.Name, GenericVersiportDigitalOutputDevice.GetVersiportDigitalOutput, props); + var portDevice = new GenericVersiportDigitalOutputDevice(dc.Key, dc.Name, GenericVersiportDigitalOutputDevice.GetVersiportDigitalOutput, props); - return portDevice; - } + return portDevice; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/CrestronIO/IAnalogInput.cs b/src/PepperDash.Essentials.Core/CrestronIO/IAnalogInput.cs index 44af99547..a202be397 100644 --- a/src/PepperDash.Essentials.Core/CrestronIO/IAnalogInput.cs +++ b/src/PepperDash.Essentials.Core/CrestronIO/IAnalogInput.cs @@ -5,10 +5,9 @@ using Crestron.SimplSharp; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core.CrestronIO +namespace PepperDash.Essentials.Core.CrestronIO; + +public interface IAnalogInput { - public interface IAnalogInput - { - IntFeedback InputValueFeedback { get; } - } + IntFeedback InputValueFeedback { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/CrestronIO/IDigitalInput.cs b/src/PepperDash.Essentials.Core/CrestronIO/IDigitalInput.cs index 7c63b92c9..be41769b1 100644 --- a/src/PepperDash.Essentials.Core/CrestronIO/IDigitalInput.cs +++ b/src/PepperDash.Essentials.Core/CrestronIO/IDigitalInput.cs @@ -4,13 +4,12 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core.CrestronIO +namespace PepperDash.Essentials.Core.CrestronIO; + +/// +/// Represents a device that provides digital input +/// +public interface IDigitalInput { - /// - /// Represents a device that provides digital input - /// - public interface IDigitalInput - { - BoolFeedback InputStateFeedback { get; } - } + BoolFeedback InputStateFeedback { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/CrestronIO/IDigitalOutput.cs b/src/PepperDash.Essentials.Core/CrestronIO/IDigitalOutput.cs index b41519415..a99a29e43 100644 --- a/src/PepperDash.Essentials.Core/CrestronIO/IDigitalOutput.cs +++ b/src/PepperDash.Essentials.Core/CrestronIO/IDigitalOutput.cs @@ -4,14 +4,13 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core.CrestronIO +namespace PepperDash.Essentials.Core.CrestronIO; + +/// +/// Represents a device that provides digital input +/// +public interface IDigitalOutput { - /// - /// Represents a device that provides digital input - /// - public interface IDigitalOutput - { - BoolFeedback OutputStateFeedback { get; } - void SetOutput(bool state); - } + BoolFeedback OutputStateFeedback { get; } + void SetOutput(bool state); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/CrestronIO/IHasCresnetBranches.cs b/src/PepperDash.Essentials.Core/CrestronIO/IHasCresnetBranches.cs index a13aca1a5..90b144cc1 100644 --- a/src/PepperDash.Essentials.Core/CrestronIO/IHasCresnetBranches.cs +++ b/src/PepperDash.Essentials.Core/CrestronIO/IHasCresnetBranches.cs @@ -6,10 +6,9 @@ using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public interface IHasCresnetBranches { - public interface IHasCresnetBranches - { - CrestronCollection CresnetBranches { get; } - } + CrestronCollection CresnetBranches { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/CrestronIO/IOPortConfig.cs b/src/PepperDash.Essentials.Core/CrestronIO/IOPortConfig.cs index ab269f080..06561f61e 100644 --- a/src/PepperDash.Essentials.Core/CrestronIO/IOPortConfig.cs +++ b/src/PepperDash.Essentials.Core/CrestronIO/IOPortConfig.cs @@ -7,17 +7,16 @@ using Crestron.SimplSharp; using Newtonsoft.Json; -namespace PepperDash.Essentials.Core.CrestronIO +namespace PepperDash.Essentials.Core.CrestronIO; + +public class IOPortConfig { - public class IOPortConfig - { - [JsonProperty("portDeviceKey")] - public string PortDeviceKey { get; set; } - [JsonProperty("portNumber")] - public uint PortNumber { get; set; } - [JsonProperty("disablePullUpResistor")] - public bool DisablePullUpResistor { get; set; } - [JsonProperty("minimumChange")] - public int MinimumChange { get; set; } - } + [JsonProperty("portDeviceKey")] + public string PortDeviceKey { get; set; } + [JsonProperty("portNumber")] + public uint PortNumber { get; set; } + [JsonProperty("disablePullUpResistor")] + public bool DisablePullUpResistor { get; set; } + [JsonProperty("minimumChange")] + public int MinimumChange { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/CrestronIO/ISwitchedOutput.cs b/src/PepperDash.Essentials.Core/CrestronIO/ISwitchedOutput.cs index 19f8e0df6..63ed96a21 100644 --- a/src/PepperDash.Essentials.Core/CrestronIO/ISwitchedOutput.cs +++ b/src/PepperDash.Essentials.Core/CrestronIO/ISwitchedOutput.cs @@ -6,21 +6,20 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core.CrestronIO +namespace PepperDash.Essentials.Core.CrestronIO; + +/// +/// Describes an output capable of switching on and off +/// +public interface ISwitchedOutput { - /// - /// Describes an output capable of switching on and off - /// - public interface ISwitchedOutput - { - BoolFeedback OutputIsOnFeedback {get;} + BoolFeedback OutputIsOnFeedback {get;} - void On(); - void Off(); - } + void On(); + void Off(); +} - public interface ISwitchedOutputCollection - { - Dictionary SwitchedOutputs { get; } - } +public interface ISwitchedOutputCollection +{ + Dictionary SwitchedOutputs { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Device Info/DeviceInfo.cs b/src/PepperDash.Essentials.Core/Device Info/DeviceInfo.cs index 9b03ec112..429579385 100644 --- a/src/PepperDash.Essentials.Core/Device Info/DeviceInfo.cs +++ b/src/PepperDash.Essentials.Core/Device Info/DeviceInfo.cs @@ -1,11 +1,10 @@ -namespace PepperDash.Essentials.Core.DeviceInfo +namespace PepperDash.Essentials.Core.DeviceInfo; + +public class DeviceInfo { - public class DeviceInfo - { - public string HostName { get; set; } - public string IpAddress { get; set; } - public string MacAddress { get; set; } - public string SerialNumber { get; set; } - public string FirmwareVersion { get; set; } - } + public string HostName { get; set; } + public string IpAddress { get; set; } + public string MacAddress { get; set; } + public string SerialNumber { get; set; } + public string FirmwareVersion { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Device Info/DeviceInfoEventArgs.cs b/src/PepperDash.Essentials.Core/Device Info/DeviceInfoEventArgs.cs index 6727bce66..1095051ce 100644 --- a/src/PepperDash.Essentials.Core/Device Info/DeviceInfoEventArgs.cs +++ b/src/PepperDash.Essentials.Core/Device Info/DeviceInfoEventArgs.cs @@ -1,19 +1,18 @@ using System; -namespace PepperDash.Essentials.Core.DeviceInfo +namespace PepperDash.Essentials.Core.DeviceInfo; + +public class DeviceInfoEventArgs:EventArgs { - public class DeviceInfoEventArgs:EventArgs - { - public DeviceInfo DeviceInfo { get; set; } + public DeviceInfo DeviceInfo { get; set; } - public DeviceInfoEventArgs() - { - - } + public DeviceInfoEventArgs() + { + + } - public DeviceInfoEventArgs(DeviceInfo devInfo) - { - DeviceInfo = devInfo; - } + public DeviceInfoEventArgs(DeviceInfo devInfo) + { + DeviceInfo = devInfo; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Device Info/IDeviceInfoProvider.cs b/src/PepperDash.Essentials.Core/Device Info/IDeviceInfoProvider.cs index ea9c16e68..b949dcea6 100644 --- a/src/PepperDash.Essentials.Core/Device Info/IDeviceInfoProvider.cs +++ b/src/PepperDash.Essentials.Core/Device Info/IDeviceInfoProvider.cs @@ -1,16 +1,15 @@ using System; using PepperDash.Core; -namespace PepperDash.Essentials.Core.DeviceInfo +namespace PepperDash.Essentials.Core.DeviceInfo; + +public interface IDeviceInfoProvider:IKeyed { - public interface IDeviceInfoProvider:IKeyed - { - DeviceInfo DeviceInfo { get; } + DeviceInfo DeviceInfo { get; } - event DeviceInfoChangeHandler DeviceInfoChanged; + event DeviceInfoChangeHandler DeviceInfoChanged; - void UpdateDeviceInfo(); - } + void UpdateDeviceInfo(); +} - public delegate void DeviceInfoChangeHandler(IKeyed device, DeviceInfoEventArgs args); -} \ No newline at end of file +public delegate void DeviceInfoChangeHandler(IKeyed device, DeviceInfoEventArgs args); \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Device Info/NetworkDeviceHelpers.cs b/src/PepperDash.Essentials.Core/Device Info/NetworkDeviceHelpers.cs index a1cc1e2f7..143907546 100644 --- a/src/PepperDash.Essentials.Core/Device Info/NetworkDeviceHelpers.cs +++ b/src/PepperDash.Essentials.Core/Device Info/NetworkDeviceHelpers.cs @@ -6,214 +6,213 @@ using PepperDash.Essentials.Core; using Serilog.Events; -namespace PepperDash.Essentials.Core.DeviceInfo +namespace PepperDash.Essentials.Core.DeviceInfo; + +public static class NetworkDeviceHelpers { - public static class NetworkDeviceHelpers + /// + /// Event raised when ArpTable changes + /// + public static event ArpTableEventHandler ArpTableUpdated; + + /// + /// Delegate called by ArpTableUpdated + /// + /// contains the entire ARP table and a bool to note if there was an error in retrieving the data + public delegate void ArpTableEventHandler(ArpTableEventArgs args); + + private static readonly char NewLineSplitter = CrestronEnvironment.NewLine.ToCharArray().First(); + private static readonly string NewLine = CrestronEnvironment.NewLine; + + private static readonly CCriticalSection Lock = new CCriticalSection(); + + /// + /// Last resolved ARP table - it is recommended to refresh the arp before using this. + /// + public static List ArpTable { get; private set; } + + /// + /// Force recheck of ARP table + /// + public static void RefreshArp() { - /// - /// Event raised when ArpTable changes - /// - public static event ArpTableEventHandler ArpTableUpdated; - - /// - /// Delegate called by ArpTableUpdated - /// - /// contains the entire ARP table and a bool to note if there was an error in retrieving the data - public delegate void ArpTableEventHandler(ArpTableEventArgs args); - - private static readonly char NewLineSplitter = CrestronEnvironment.NewLine.ToCharArray().First(); - private static readonly string NewLine = CrestronEnvironment.NewLine; - - private static readonly CCriticalSection Lock = new CCriticalSection(); - - /// - /// Last resolved ARP table - it is recommended to refresh the arp before using this. - /// - public static List ArpTable { get; private set; } - - /// - /// Force recheck of ARP table - /// - public static void RefreshArp() + var error = false; + try { - var error = false; - try - { - Lock.Enter(); - var consoleResponse = string.Empty; - if (!CrestronConsole.SendControlSystemCommand("showarptable", ref consoleResponse)) return; - if (string.IsNullOrEmpty(consoleResponse)) - { - error = true; - return; - } - ArpTable.Clear(); - - Debug.LogMessage(LogEventLevel.Verbose, "ConsoleResponse of 'showarptable' : {0}{1}", NewLine, consoleResponse); - - var myLines = - consoleResponse.Split(NewLineSplitter) - .ToList() - .Where(o => (o.Contains(':') && !o.Contains("Type", StringComparison.OrdinalIgnoreCase))) - .ToList(); - foreach (var line in myLines) - { - var item = line; - var seperator = item.Contains('\t') ? '\t' : ' '; - var dataPoints = item.Split(seperator); - if (dataPoints == null || dataPoints.Length < 2) continue; - var ipAddress = SanitizeIpAddress(dataPoints.First().TrimAll()); - var macAddress = dataPoints.Last(); - ArpTable.Add(new ArpEntry(ipAddress, macAddress)); - } - } - catch (Exception ex) + Lock.Enter(); + var consoleResponse = string.Empty; + if (!CrestronConsole.SendControlSystemCommand("showarptable", ref consoleResponse)) return; + if (string.IsNullOrEmpty(consoleResponse)) { - Debug.LogMessage(LogEventLevel.Information, "Exception in \"RefreshArp\" : {0}", ex.Message); error = true; + return; } - finally + ArpTable.Clear(); + + Debug.LogMessage(LogEventLevel.Verbose, "ConsoleResponse of 'showarptable' : {0}{1}", NewLine, consoleResponse); + + var myLines = + consoleResponse.Split(NewLineSplitter) + .ToList() + .Where(o => (o.Contains(':') && !o.Contains("Type", StringComparison.OrdinalIgnoreCase))) + .ToList(); + foreach (var line in myLines) { - Lock.Leave(); - OnArpTableUpdated(new ArpTableEventArgs(ArpTable, error)); + var item = line; + var seperator = item.Contains('\t') ? '\t' : ' '; + var dataPoints = item.Split(seperator); + if (dataPoints == null || dataPoints.Length < 2) continue; + var ipAddress = SanitizeIpAddress(dataPoints.First().TrimAll()); + var macAddress = dataPoints.Last(); + ArpTable.Add(new ArpEntry(ipAddress, macAddress)); } } - - - private static void OnArpTableUpdated(ArpTableEventArgs args) + catch (Exception ex) { - if (args == null) return; - var handler = ArpTableUpdated; - if (handler == null) return; - handler.Invoke(args); + Debug.LogMessage(LogEventLevel.Information, "Exception in \"RefreshArp\" : {0}", ex.Message); + error = true; } - - static NetworkDeviceHelpers() + finally { - ArpTable = new List(); + Lock.Leave(); + OnArpTableUpdated(new ArpTableEventArgs(ArpTable, error)); } + } + + + private static void OnArpTableUpdated(ArpTableEventArgs args) + { + if (args == null) return; + var handler = ArpTableUpdated; + if (handler == null) return; + handler.Invoke(args); + } - /// - /// Removes leading zeros, leading whitespace, and trailing whitespace from an IPAddress string - /// - /// Ip Address to Santitize - /// Sanitized Ip Address - public static string SanitizeIpAddress(string ipAddressIn) + static NetworkDeviceHelpers() + { + ArpTable = new List(); + } + + /// + /// Removes leading zeros, leading whitespace, and trailing whitespace from an IPAddress string + /// + /// Ip Address to Santitize + /// Sanitized Ip Address + public static string SanitizeIpAddress(string ipAddressIn) + { + try { - try - { - var ipAddress = IPAddress.Parse(ipAddressIn.TrimStart('0')); - return ipAddress.ToString(); - } - catch (Exception ex) - { - Debug.LogMessage(LogEventLevel.Information, "Unable to Santize Ip : {0}", ex.Message); - return ipAddressIn; - } + var ipAddress = IPAddress.Parse(ipAddressIn.TrimStart('0')); + return ipAddress.ToString(); } - - /// - /// Resolves a hostname by IP Address using DNS - /// - /// IP Address to resolve from - /// Resolved Hostname - on failure to determine hostname, will return IP Address - public static string ResolveHostnameFromIp(string ipAddress) + catch (Exception ex) { - try - { - var santitizedIp = SanitizeIpAddress(ipAddress); - var hostEntry = Dns.GetHostEntry(santitizedIp); - return hostEntry == null ? ipAddress : hostEntry.HostName; - } - catch (Exception ex) - { - Debug.LogMessage(LogEventLevel.Information, "Exception Resolving Hostname from IP Address : {0}", ex.Message); - return ipAddress; - } + Debug.LogMessage(LogEventLevel.Information, "Unable to Santize Ip : {0}", ex.Message); + return ipAddressIn; } + } - /// - /// Resolves an IP Address by hostname using DNS - /// - /// Hostname to resolve from - /// Resolved IP Address - on a failure to determine IP Address, will return hostname - public static string ResolveIpFromHostname(string hostName) + /// + /// Resolves a hostname by IP Address using DNS + /// + /// IP Address to resolve from + /// Resolved Hostname - on failure to determine hostname, will return IP Address + public static string ResolveHostnameFromIp(string ipAddress) + { + try { - try - { - var hostEntry = Dns.GetHostEntry(hostName); - return hostEntry == null ? hostName : hostEntry.AddressList.First().ToString(); - } - catch (Exception ex) - { - Debug.LogMessage(LogEventLevel.Information, "Exception Resolving IP Address from Hostname : {0}", ex.Message); - return hostName; - } + var santitizedIp = SanitizeIpAddress(ipAddress); + var hostEntry = Dns.GetHostEntry(santitizedIp); + return hostEntry == null ? ipAddress : hostEntry.HostName; + } + catch (Exception ex) + { + Debug.LogMessage(LogEventLevel.Information, "Exception Resolving Hostname from IP Address : {0}", ex.Message); + return ipAddress; } - } /// - /// Object to hold data about an arp entry + /// Resolves an IP Address by hostname using DNS /// - public class ArpEntry + /// Hostname to resolve from + /// Resolved IP Address - on a failure to determine IP Address, will return hostname + public static string ResolveIpFromHostname(string hostName) { - public readonly IPAddress IpAddress; - public readonly string MacAddress; - - /// - /// Constructs new ArpEntry object - /// - /// string formatted as ipv4 address - /// mac address string - format is unimportant - public ArpEntry(string ipAddress, string macAddress) + try { - if (string.IsNullOrEmpty(ipAddress)) - { - throw new ArgumentException("\"ipAddress\" cannot be null or empty"); - } - if (string.IsNullOrEmpty(macAddress)) - { - throw new ArgumentException("\"macAddress\" cannot be null or empty"); - } - IpAddress = IPAddress.Parse(ipAddress.TrimStart().TrimStart('0').TrimEnd()); - MacAddress = macAddress; + var hostEntry = Dns.GetHostEntry(hostName); + return hostEntry == null ? hostName : hostEntry.AddressList.First().ToString(); + } + catch (Exception ex) + { + Debug.LogMessage(LogEventLevel.Information, "Exception Resolving IP Address from Hostname : {0}", ex.Message); + return hostName; } } +} + +/// +/// Object to hold data about an arp entry +/// +public class ArpEntry +{ + public readonly IPAddress IpAddress; + public readonly string MacAddress; + /// - /// Arguments passed by the ArpTableUpdated event + /// Constructs new ArpEntry object /// - public class ArpTableEventArgs : EventArgs + /// string formatted as ipv4 address + /// mac address string - format is unimportant + public ArpEntry(string ipAddress, string macAddress) { - /// - /// The retrieved ARP Table - /// - public readonly List ArpTable; - /// - /// True if there was a problem retrieving the ARP Table - /// - public readonly bool Error; - - /// - /// Constructor for ArpTableEventArgs - /// - /// The entirety of the retrieved ARP table - /// True of an error was encountered updating the ARP table - public ArpTableEventArgs(List arpTable, bool error) + if (string.IsNullOrEmpty(ipAddress)) { - ArpTable = arpTable; - Error = error; + throw new ArgumentException("\"ipAddress\" cannot be null or empty"); } - - /// - /// Constructor for ArpTableEventArgs - assumes no error encountered in retrieving ARP Table - /// - /// The entirety of the retrieved ARP table - public ArpTableEventArgs(List arpTable) + if (string.IsNullOrEmpty(macAddress)) { - ArpTable = arpTable; - Error = false; + throw new ArgumentException("\"macAddress\" cannot be null or empty"); } + IpAddress = IPAddress.Parse(ipAddress.TrimStart().TrimStart('0').TrimEnd()); + MacAddress = macAddress; + } +} + +/// +/// Arguments passed by the ArpTableUpdated event +/// +public class ArpTableEventArgs : EventArgs +{ + /// + /// The retrieved ARP Table + /// + public readonly List ArpTable; + /// + /// True if there was a problem retrieving the ARP Table + /// + public readonly bool Error; + + /// + /// Constructor for ArpTableEventArgs + /// + /// The entirety of the retrieved ARP table + /// True of an error was encountered updating the ARP table + public ArpTableEventArgs(List arpTable, bool error) + { + ArpTable = arpTable; + Error = error; + } + + /// + /// Constructor for ArpTableEventArgs - assumes no error encountered in retrieving ARP Table + /// + /// The entirety of the retrieved ARP table + public ArpTableEventArgs(List arpTable) + { + ArpTable = arpTable; + Error = false; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IChannel.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IChannel.cs index 5a38c703d..5242b4968 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IChannel.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IChannel.cs @@ -4,8 +4,8 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.SmartObjects; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// /// @@ -43,5 +43,4 @@ public static void UnlinkButtons(this IChannel dev, BasicTriList triList) triList.ClearBoolSigAction(129); triList.ClearBoolSigAction(134); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IColorFunctions.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IColorFunctions.cs index 232362e98..8997da6cd 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IColorFunctions.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IColorFunctions.cs @@ -4,8 +4,8 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.SmartObjects; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// /// @@ -37,5 +37,4 @@ public static void UnlinkButtons(this IColor dev, BasicTriList triList) triList.ClearBoolSigAction(157); triList.ClearBoolSigAction(158); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDPad.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDPad.cs index a69cfe3bf..287d7f778 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDPad.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDPad.cs @@ -4,8 +4,8 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.SmartObjects; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// /// @@ -46,5 +46,4 @@ public static void UnlinkButtons(this IDPad dev, BasicTriList triList) triList.ClearBoolSigAction(130); triList.ClearBoolSigAction(134); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDiscPlayerControls.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDiscPlayerControls.cs index 024bac273..0c7fe5eff 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDiscPlayerControls.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDiscPlayerControls.cs @@ -3,11 +3,9 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.SmartObjects; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; - public interface IDiscPlayerControls : IColor, IDPad, INumericKeypad, IHasPowerControl, ITransport, IUiDisplayInfo - { - } -} \ No newline at end of file +public interface IDiscPlayerControls : IColor, IDPad, INumericKeypad, IHasPowerControl, ITransport, IUiDisplayInfo + { + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDisplay.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDisplay.cs index 9b82cacdd..049d08780 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDisplay.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDisplay.cs @@ -1,8 +1,7 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +public interface IDisplay: IHasFeedback, IRoutingSinkWithSwitching, IHasPowerControl, IWarmingCooling, IUsageTracking, IKeyName { - public interface IDisplay: IHasFeedback, IRoutingSinkWithSwitching, IHasPowerControl, IWarmingCooling, IUsageTracking, IKeyName - { - } } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDisplayBasic.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDisplayBasic.cs index 5624f77ce..5a825cc9a 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDisplayBasic.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDisplayBasic.cs @@ -4,8 +4,8 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core.Devices.DeviceTypeInterfaces -{ +namespace PepperDash.Essentials.Core.Devices.DeviceTypeInterfaces; + public interface IDisplayBasic { void InputHdmi1(); @@ -18,5 +18,4 @@ public interface IDisplayBasic void InputVga1(); void InputVga2(); void InputRgb1(); - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDumbSource.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDumbSource.cs index 1d4829cd3..c00638219 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDumbSource.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDumbSource.cs @@ -4,9 +4,8 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public interface IDumbSource { - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDvr.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDvr.cs index 9e55702ca..4d9276af9 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDvr.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IDvr.cs @@ -9,8 +9,8 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.SmartObjects; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// /// @@ -36,5 +36,4 @@ public static void UnlinkButtons(this IDvr dev, BasicTriList triList) triList.ClearBoolSigAction(136); triList.ClearBoolSigAction(152); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IEmergencyOSD.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IEmergencyOSD.cs index 7d1580272..593fe7eb4 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IEmergencyOSD.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IEmergencyOSD.cs @@ -4,11 +4,10 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +public interface IEmergencyOSD { - public interface IEmergencyOSD - { - void ShowEmergencyMessage(string url); - void HideEmergencyMessage(); - } + void ShowEmergencyMessage(string url); + void HideEmergencyMessage(); } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasBranding.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasBranding.cs index 10db107f5..414082a99 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasBranding.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasBranding.cs @@ -1,10 +1,9 @@ using System; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +public interface IHasBranding { - public interface IHasBranding - { - bool BrandingEnabled { get; } - void InitializeBranding(string roomKey); - } + bool BrandingEnabled { get; } + void InitializeBranding(string roomKey); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasFarEndContentStatus.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasFarEndContentStatus.cs index 21bde91fa..071ac71f8 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasFarEndContentStatus.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasFarEndContentStatus.cs @@ -1,7 +1,6 @@ -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +public interface IHasFarEndContentStatus { - public interface IHasFarEndContentStatus - { - BoolFeedback ReceivingContent { get; } - } + BoolFeedback ReceivingContent { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs index ff9511fa8..5851c7bae 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasInputs.cs @@ -1,16 +1,15 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +/// +/// Describes a device that has selectable inputs +/// +/// the type to use as the key for each input item. Most likely an enum or string\ +/// +/// See MockDisplay for example implemntation +/// +public interface IHasInputs : IKeyName { - /// - /// Describes a device that has selectable inputs - /// - /// the type to use as the key for each input item. Most likely an enum or string\ - /// - /// See MockDisplay for example implemntation - /// - public interface IHasInputs : IKeyName - { - ISelectableItems Inputs { get; } - } + ISelectableItems Inputs { get; } } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasPhoneDialing.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasPhoneDialing.cs index cd208d4bf..417d69637 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasPhoneDialing.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasPhoneDialing.cs @@ -1,15 +1,14 @@ using System; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +public interface IHasPhoneDialing { - public interface IHasPhoneDialing - { - BoolFeedback PhoneOffHookFeedback { get; } - StringFeedback CallerIdNameFeedback { get; } - StringFeedback CallerIdNumberFeedback { get; } - void DialPhoneCall(string number); - void EndPhoneCall(); - void SendDtmfToPhone(string digit); - } + BoolFeedback PhoneOffHookFeedback { get; } + StringFeedback CallerIdNameFeedback { get; } + StringFeedback CallerIdNumberFeedback { get; } + void DialPhoneCall(string number); + void EndPhoneCall(); + void SendDtmfToPhone(string digit); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasScreensWithLayouts.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasScreensWithLayouts.cs index 439462c6f..2a67e39b7 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasScreensWithLayouts.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasScreensWithLayouts.cs @@ -5,103 +5,102 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +/// +/// This defines a device that has screens with layouts +/// Simply decorative +/// +public interface IHasScreensWithLayouts { /// - /// This defines a device that has screens with layouts - /// Simply decorative + /// A dictionary of screens, keyed by screen ID, that contains information about each screen and its layouts. /// - public interface IHasScreensWithLayouts - { - /// - /// A dictionary of screens, keyed by screen ID, that contains information about each screen and its layouts. - /// - Dictionary Screens { get; } - - /// - /// Applies a specific layout to a screen based on the provided screen ID and layout index. - /// - /// - /// - void ApplyLayout(uint screenId, uint layoutIndex); - } + Dictionary Screens { get; } /// - /// Represents information about a screen and its layouts. + /// Applies a specific layout to a screen based on the provided screen ID and layout index. /// - public class ScreenInfo - { + /// + /// + void ApplyLayout(uint screenId, uint layoutIndex); +} - /// - /// Indicates whether the screen is enabled or not. - /// - [JsonProperty("enabled")] - public bool Enabled { get; set; } +/// +/// Represents information about a screen and its layouts. +/// +public class ScreenInfo +{ - /// - /// The name of the screen. - /// - [JsonProperty("name")] - public string Name { get; set; } + /// + /// Indicates whether the screen is enabled or not. + /// + [JsonProperty("enabled")] + public bool Enabled { get; set; } - /// - /// The index of the screen. - /// - [JsonProperty("screenIndex")] - public int ScreenIndex { get; set; } + /// + /// The name of the screen. + /// + [JsonProperty("name")] + public string Name { get; set; } - /// - /// A dictionary of layout information for the screen, keyed by layout ID. - /// - [JsonProperty("layouts")] - public Dictionary Layouts { get; set; } - } + /// + /// The index of the screen. + /// + [JsonProperty("screenIndex")] + public int ScreenIndex { get; set; } /// - /// Represents information about a layout on a screen. + /// A dictionary of layout information for the screen, keyed by layout ID. /// - public class LayoutInfo - { - /// - /// The name of the layout. - /// - [JsonProperty("layoutName")] - public string LayoutName { get; set; } + [JsonProperty("layouts")] + public Dictionary Layouts { get; set; } +} - /// - /// The index of the layout. - /// - [JsonProperty("layoutIndex")] - public int LayoutIndex { get; set; } +/// +/// Represents information about a layout on a screen. +/// +public class LayoutInfo +{ + /// + /// The name of the layout. + /// + [JsonProperty("layoutName")] + public string LayoutName { get; set; } + + /// + /// The index of the layout. + /// + [JsonProperty("layoutIndex")] + public int LayoutIndex { get; set; } - /// - /// The type of the layout, which can be "single", "double", "triple", or "quad". - /// - [JsonProperty("layoutType")] - public string LayoutType { get; set; } + /// + /// The type of the layout, which can be "single", "double", "triple", or "quad". + /// + [JsonProperty("layoutType")] + public string LayoutType { get; set; } - /// - /// A dictionary of window configurations for the layout, keyed by window ID. - /// - [JsonProperty("windows")] - public Dictionary Windows { get; set; } - } + /// + /// A dictionary of window configurations for the layout, keyed by window ID. + /// + [JsonProperty("windows")] + public Dictionary Windows { get; set; } +} +/// +/// Represents the configuration of a window within a layout on a screen. +/// +public class WindowConfig +{ /// - /// Represents the configuration of a window within a layout on a screen. + /// The display label for the window /// - public class WindowConfig - { - /// - /// The display label for the window - /// - [JsonProperty("label")] - public string Label { get; set; } + [JsonProperty("label")] + public string Label { get; set; } - /// - /// The input for the window - /// - [JsonProperty("input")] - public string Input { get; set; } - } + /// + /// The input for the window + /// + [JsonProperty("input")] + public string Input { get; set; } } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasSurroundSoundModes.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasSurroundSoundModes.cs index c1c4ec86d..bd6e42894 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasSurroundSoundModes.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasSurroundSoundModes.cs @@ -5,16 +5,15 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +/// +/// Describes a device that has selectable surround sound modes +/// +/// the type to use as the key for each input item. Most likely an enum or string +public interface IHasSurroundSoundModes: IKeyName { - /// - /// Describes a device that has selectable surround sound modes - /// - /// the type to use as the key for each input item. Most likely an enum or string - public interface IHasSurroundSoundModes: IKeyName - { - ISelectableItems SurroundSoundModes { get; } + ISelectableItems SurroundSoundModes { get; } - void SetSurroundSoundMode(TSelector selector); - } + void SetSurroundSoundMode(TSelector selector); } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasWebView.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasWebView.cs index 84177a898..ebb3f0e50 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasWebView.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHasWebView.cs @@ -4,23 +4,22 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +public interface IHasWebView { - public interface IHasWebView - { - bool WebviewIsVisible { get; } - void ShowWebView(string url, string mode, string title, string target); - void HideWebView(); - event EventHandler WebViewStatusChanged; - } + bool WebviewIsVisible { get; } + void ShowWebView(string url, string mode, string title, string target); + void HideWebView(); + event EventHandler WebViewStatusChanged; +} - public class WebViewStatusChangedEventArgs : EventArgs - { - public string Status { get; } +public class WebViewStatusChangedEventArgs : EventArgs +{ + public string Status { get; } - public WebViewStatusChangedEventArgs(string status) - { - Status = status; - } + public WebViewStatusChangedEventArgs(string status) + { + Status = status; } } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHumiditySensor.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHumiditySensor.cs index 8e9a369bc..e8a614948 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHumiditySensor.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IHumiditySensor.cs @@ -4,15 +4,14 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +public interface IHumiditySensor { - public interface IHumiditySensor - { - /// - /// Reports the relative humidity level. Level ranging from 0 to 100 (for 0% to 100% - /// RH). EventIds: HumidityFeedbackFeedbackEventId will trigger to indicate change. - /// - IntFeedback HumidityFeedback { get; } + /// + /// Reports the relative humidity level. Level ranging from 0 to 100 (for 0% to 100% + /// RH). EventIds: HumidityFeedbackFeedbackEventId will trigger to indicate change. + /// + IntFeedback HumidityFeedback { get; } - } } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ILanguageDefinition.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ILanguageDefinition.cs index 181cac350..ff17353ed 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ILanguageDefinition.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ILanguageDefinition.cs @@ -1,18 +1,17 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +public interface ILanguageDefinition { - public interface ILanguageDefinition - { - string LocaleName { get; set; } - string FriendlyName { get; set; } - bool Enable { get; set; } - List UiLabels { get; set; } - List Sources { get; set; } - List Destinations { get; set; } - List SourceGroupNames { get; set; } - List DestinationGroupNames { get; set; } - List RoomNames { get; set; } - } + string LocaleName { get; set; } + string FriendlyName { get; set; } + bool Enable { get; set; } + List UiLabels { get; set; } + List Sources { get; set; } + List Destinations { get; set; } + List SourceGroupNames { get; set; } + List DestinationGroupNames { get; set; } + List RoomNames { get; set; } } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ILanguageProvider.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ILanguageProvider.cs index 428f78c3d..8112b4be8 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ILanguageProvider.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ILanguageProvider.cs @@ -1,13 +1,11 @@ using System; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces -{ - - public interface ILanguageProvider - { - ILanguageDefinition CurrentLanguage { get; set; } +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + - event EventHandler CurrentLanguageChanged; - } +public interface ILanguageProvider +{ + ILanguageDefinition CurrentLanguage { get; set; } + event EventHandler CurrentLanguageChanged; } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ILevelControls.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ILevelControls.cs index f4cb4b71c..736d122ae 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ILevelControls.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ILevelControls.cs @@ -4,10 +4,9 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +public interface ILevelControls { - public interface ILevelControls - { - Dictionary LevelControlPoints { get; } - } + Dictionary LevelControlPoints { get; } } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMobileControl.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMobileControl.cs index c30edebd1..0d2541d53 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMobileControl.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMobileControl.cs @@ -3,117 +3,116 @@ using Newtonsoft.Json.Linq; using PepperDash.Core; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +/// +/// Use this interface on a device or room if it uses custom Mobile Control messengers +/// +public interface ICustomMobileControl : IKeyed { - /// - /// Use this interface on a device or room if it uses custom Mobile Control messengers - /// - public interface ICustomMobileControl : IKeyed - { - } +} - /*/// - /// Describes a MobileControlSystemController - /// - public interface IMobileControl : IKeyed - { - void CreateMobileControlRoomBridge(IEssentialsRoom room, IMobileControl parent); +/*/// +/// Describes a MobileControlSystemController +/// +public interface IMobileControl : IKeyed +{ + void CreateMobileControlRoomBridge(IEssentialsRoom room, IMobileControl parent); - void LinkSystemMonitorToAppServer(); - }*/ + void LinkSystemMonitorToAppServer(); +}*/ - /// - /// Describes a MobileSystemController that accepts IEssentialsRoom - /// - public interface IMobileControl : IKeyed - { - string Host { get; } +/// +/// Describes a MobileSystemController that accepts IEssentialsRoom +/// +public interface IMobileControl : IKeyed +{ + string Host { get; } - string ClientAppUrl { get; } + string ClientAppUrl { get; } - string SystemUuid { get; } + string SystemUuid { get; } - BoolFeedback ApiOnlineAndAuthorized { get;} + BoolFeedback ApiOnlineAndAuthorized { get;} - void SendMessageObject(IMobileControlMessage o); + void SendMessageObject(IMobileControlMessage o); - void AddAction(T messenger, Action action) where T:IMobileControlMessenger; + void AddAction(T messenger, Action action) where T:IMobileControlMessenger; - void RemoveAction(string key); + void RemoveAction(string key); - void AddDeviceMessenger(IMobileControlMessenger messenger); + void AddDeviceMessenger(IMobileControlMessenger messenger); - bool CheckForDeviceMessenger(string key); + bool CheckForDeviceMessenger(string key); IMobileControlRoomMessenger GetRoomMessenger(string key); } - /// - /// Describes a mobile control messenger - /// - public interface IMobileControlMessenger: IKeyed - { - IMobileControl AppServerController { get; } - string MessagePath { get; } +/// +/// Describes a mobile control messenger +/// +public interface IMobileControlMessenger: IKeyed +{ + IMobileControl AppServerController { get; } + string MessagePath { get; } - string DeviceKey { get; } - void RegisterWithAppServer(IMobileControl appServerController); - } + string DeviceKey { get; } + void RegisterWithAppServer(IMobileControl appServerController); +} - public interface IMobileControlMessage - { - [JsonProperty("type")] - string Type { get; } +public interface IMobileControlMessage +{ + [JsonProperty("type")] + string Type { get; } - [JsonProperty("clientId", NullValueHandling = NullValueHandling.Ignore)] - string ClientId { get; } + [JsonProperty("clientId", NullValueHandling = NullValueHandling.Ignore)] + string ClientId { get; } - [JsonProperty("content", NullValueHandling = NullValueHandling.Ignore)] - JToken Content { get; } + [JsonProperty("content", NullValueHandling = NullValueHandling.Ignore)] + JToken Content { get; } - } +} - /// - /// Describes a MobileControl Room Bridge - /// - public interface IMobileControlRoomMessenger : IKeyed - { - event EventHandler UserCodeChanged; +/// +/// Describes a MobileControl Room Bridge +/// +public interface IMobileControlRoomMessenger : IKeyed +{ + event EventHandler UserCodeChanged; - event EventHandler UserPromptedForCode; + event EventHandler UserPromptedForCode; - event EventHandler ClientJoined; + event EventHandler ClientJoined; - event EventHandler AppUrlChanged; + event EventHandler AppUrlChanged; - string UserCode { get; } + string UserCode { get; } - string QrCodeUrl { get; } + string QrCodeUrl { get; } - string QrCodeChecksum { get; } + string QrCodeChecksum { get; } - string McServerUrl { get; } + string McServerUrl { get; } - string RoomName { get; } + string RoomName { get; } - string AppUrl { get; } + string AppUrl { get; } - void UpdateAppUrl(string url); - } + void UpdateAppUrl(string url); +} - public interface IMobileControlAction - { - IMobileControlMessenger Messenger { get; } +public interface IMobileControlAction +{ + IMobileControlMessenger Messenger { get; } - Action Action { get; } - } + Action Action { get; } +} - public interface IMobileControlTouchpanelController : IKeyed - { - string DefaultRoomKey { get; } - void SetAppUrl(string url); - bool UseDirectServer { get; } - bool ZoomRoomController { get; } - } +public interface IMobileControlTouchpanelController : IKeyed +{ + string DefaultRoomKey { get; } + void SetAppUrl(string url); + bool UseDirectServer { get; } + bool ZoomRoomController { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/INumeric.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/INumeric.cs index 62ea8b3f3..e308fe598 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/INumeric.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/INumeric.cs @@ -3,8 +3,8 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.SmartObjects; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// /// @@ -80,5 +80,4 @@ public static void UnlinkButtons(this INumericKeypad dev, BasicTriList trilist) trilist.ClearBoolSigAction(120); trilist.ClearBoolSigAction(121); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IPasswordPrompt.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IPasswordPrompt.cs index 6ecdd7751..cfdcf0cee 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IPasswordPrompt.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IPasswordPrompt.cs @@ -4,53 +4,52 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Describes the functionality required to prompt a user to enter a password +/// +public interface IPasswordPrompt { /// - /// Describes the functionality required to prompt a user to enter a password + /// Notifies when a password is required or is entered incorrectly /// - public interface IPasswordPrompt - { - /// - /// Notifies when a password is required or is entered incorrectly - /// - event EventHandler PasswordRequired; - - /// - /// Submits the password - /// - /// - void SubmitPassword(string password); - } + event EventHandler PasswordRequired; + + /// + /// Submits the password + /// + /// + void SubmitPassword(string password); +} + +public class PasswordPromptEventArgs : EventArgs +{ + /// + /// Indicates if the last submitted password was incorrect + /// + public bool LastAttemptWasIncorrect { get; private set; } + + /// + /// Indicates that the login attempt has failed + /// + public bool LoginAttemptFailed { get; private set; } + + /// + /// Indicates that the process was cancelled and the prompt should be dismissed + /// + public bool LoginAttemptCancelled { get; private set; } + + /// + /// A message to be displayed to the user + /// + public string Message { get; private set; } - public class PasswordPromptEventArgs : EventArgs + public PasswordPromptEventArgs(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message) { - /// - /// Indicates if the last submitted password was incorrect - /// - public bool LastAttemptWasIncorrect { get; private set; } - - /// - /// Indicates that the login attempt has failed - /// - public bool LoginAttemptFailed { get; private set; } - - /// - /// Indicates that the process was cancelled and the prompt should be dismissed - /// - public bool LoginAttemptCancelled { get; private set; } - - /// - /// A message to be displayed to the user - /// - public string Message { get; private set; } - - public PasswordPromptEventArgs(bool lastAttemptIncorrect, bool loginFailed, bool loginCancelled, string message) - { - LastAttemptWasIncorrect = lastAttemptIncorrect; - LoginAttemptFailed = loginFailed; - LoginAttemptCancelled = loginCancelled; - Message = message; - } + LastAttemptWasIncorrect = lastAttemptIncorrect; + LoginAttemptFailed = loginFailed; + LoginAttemptCancelled = loginCancelled; + Message = message; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IPower.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IPower.cs index b7c3345e9..b88abafe3 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IPower.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IPower.cs @@ -11,56 +11,55 @@ using PepperDash.Essentials.Core.SmartObjects; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + - /// - /// Adds feedback for current power state - /// - public interface IHasPowerControlWithFeedback : IHasPowerControl - { - BoolFeedback PowerIsOnFeedback { get; } - } +/// +/// Adds feedback for current power state +/// +public interface IHasPowerControlWithFeedback : IHasPowerControl +{ + BoolFeedback PowerIsOnFeedback { get; } +} - /// - /// Defines the ability to power a device on and off - /// - public interface IHasPowerControl - { - void PowerOn(); - void PowerOff(); - void PowerToggle(); - } +/// +/// Defines the ability to power a device on and off +/// +public interface IHasPowerControl +{ + void PowerOn(); + void PowerOff(); + void PowerToggle(); +} /// /// /// public static class IHasPowerControlExtensions { - public static void LinkButtons(this IHasPowerControl dev, BasicTriList triList) + public static void LinkButtons(this IHasPowerControl dev, BasicTriList triList) { triList.SetSigFalseAction(101, dev.PowerOn); triList.SetSigFalseAction(102, dev.PowerOff); triList.SetSigFalseAction(103, dev.PowerToggle); - var fbdev = dev as IHasPowerControlWithFeedback; - if (fbdev != null) - { - fbdev.PowerIsOnFeedback.LinkInputSig(triList.BooleanInput[101]); - } + var fbdev = dev as IHasPowerControlWithFeedback; + if (fbdev != null) + { + fbdev.PowerIsOnFeedback.LinkInputSig(triList.BooleanInput[101]); + } } - public static void UnlinkButtons(this IHasPowerControl dev, BasicTriList triList) + public static void UnlinkButtons(this IHasPowerControl dev, BasicTriList triList) { triList.ClearBoolSigAction(101); triList.ClearBoolSigAction(102); triList.ClearBoolSigAction(103); - var fbdev = dev as IHasPowerControlWithFeedback; - if (fbdev != null) - { - fbdev.PowerIsOnFeedback.UnlinkInputSig(triList.BooleanInput[101]); - } + var fbdev = dev as IHasPowerControlWithFeedback; + if (fbdev != null) + { + fbdev.PowerIsOnFeedback.UnlinkInputSig(triList.BooleanInput[101]); + } } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IProjectorScreenLiftControl.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IProjectorScreenLiftControl.cs index 268951145..5d77aa1f7 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IProjectorScreenLiftControl.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IProjectorScreenLiftControl.cs @@ -3,8 +3,8 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces -{ +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + /// /// Defines a class that has warm up and cool down /// @@ -23,5 +23,4 @@ public enum eScreenLiftControlType { lift, screen - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItem.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItem.cs index 0f7408f60..a3c23f410 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItem.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItem.cs @@ -2,18 +2,17 @@ using Newtonsoft.Json; using PepperDash.Core; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces -{ +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + - /// - /// Describes an item that can be selected - /// - public interface ISelectableItem : IKeyName - { - event EventHandler ItemUpdated; +/// +/// Describes an item that can be selected +/// +public interface ISelectableItem : IKeyName +{ + event EventHandler ItemUpdated; - [JsonProperty("isSelected")] - bool IsSelected { get; set; } - void Select(); - } + [JsonProperty("isSelected")] + bool IsSelected { get; set; } + void Select(); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs index 9479099ca..195283ea3 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISelectableItems.cs @@ -2,26 +2,25 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +public interface ISelectableItems where TValue : ISelectableItem { - public interface ISelectableItems where TValue : ISelectableItem - { - event EventHandler ItemsUpdated; - event EventHandler CurrentItemChanged; + event EventHandler ItemsUpdated; + event EventHandler CurrentItemChanged; - [JsonProperty("items")] - Dictionary Items { get; set; } + [JsonProperty("items")] + Dictionary Items { get; set; } - [JsonProperty("currentItem")] - TKey CurrentItem { get; set; } + [JsonProperty("currentItem")] + TKey CurrentItem { get; set; } - } +} - /// - /// Describes a collection of items that can be selected - /// - /// type for the keys in the collection. Probably a string or enum - public interface ISelectableItems : ISelectableItems - { - } +/// +/// Describes a collection of items that can be selected +/// +/// type for the keys in the collection. Probably a string or enum +public interface ISelectableItems : ISelectableItems +{ } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISetTopBoxControls.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISetTopBoxControls.cs index a9a921269..0d7018d48 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISetTopBoxControls.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ISetTopBoxControls.cs @@ -3,8 +3,8 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.SmartObjects; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// /// @@ -51,5 +51,4 @@ public static void UnlinkButtons(this ISetTopBoxControls dev, BasicTriList triLi triList.ClearBoolSigAction(136); triList.ClearBoolSigAction(152); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ITemperatureSensor.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ITemperatureSensor.cs index fe1c560c6..cc0f2a266 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ITemperatureSensor.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ITemperatureSensor.cs @@ -4,19 +4,18 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +public interface ITemperatureSensor { - public interface ITemperatureSensor - { - /// - /// The values will range from -400 to +1760 (for -40° to +176° F) or -400 to +800 - /// (for -40° to +80° C)in tenths of a degree. - /// - IntFeedback TemperatureFeedback { get; } + /// + /// The values will range from -400 to +1760 (for -40° to +176° F) or -400 to +800 + /// (for -40° to +80° C)in tenths of a degree. + /// + IntFeedback TemperatureFeedback { get; } - BoolFeedback TemperatureInCFeedback { get; } + BoolFeedback TemperatureInCFeedback { get; } - void SetTemperatureFormat(bool setToC); - } + void SetTemperatureFormat(bool setToC); } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ITransport.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ITransport.cs index 1189c10b6..6e9ba7245 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ITransport.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ITransport.cs @@ -1,7 +1,7 @@ using Crestron.SimplSharpPro.DeviceSupport; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// /// @@ -49,5 +49,4 @@ public static void UnlinkButtons(this ITransport dev, BasicTriList triList) triList.ClearBoolSigAction(151); triList.ClearBoolSigAction(154); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ITvPresetsProvider.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ITvPresetsProvider.cs index 61b8ec099..199c62350 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ITvPresetsProvider.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/ITvPresetsProvider.cs @@ -1,9 +1,8 @@ using PepperDash.Essentials.Core.Presets; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +public interface ITvPresetsProvider { - public interface ITvPresetsProvider - { - DevicePresetsModel TvPresets { get; } - } + DevicePresetsModel TvPresets { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IUiDisplayInfo.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IUiDisplayInfo.cs index fb51f7e21..6a607b1e2 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IUiDisplayInfo.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IUiDisplayInfo.cs @@ -1,12 +1,11 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// Describes things needed to show on UI /// public interface IUiDisplayInfo : IKeyed { uint DisplayUiType { get; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IWarmingCooling.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IWarmingCooling.cs index 2baf15480..829848591 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IWarmingCooling.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IWarmingCooling.cs @@ -4,8 +4,8 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// Defines a class that has warm up and cool down /// @@ -13,5 +13,4 @@ public interface IWarmingCooling { BoolFeedback IsWarmingUpFeedback { get; } BoolFeedback IsCoolingDownFeedback { get; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/LanguageLabel.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/LanguageLabel.cs index 890d1416a..a7150706d 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/LanguageLabel.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/LanguageLabel.cs @@ -1,13 +1,12 @@ using System; using PepperDash.Core; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +public class LanguageLabel { - public class LanguageLabel - { - public string Key { get; set; } - public string Description { get; set; } - public string DisplayText { get; set; } - public uint JoinNumber { get; set; } - } + public string Key { get; set; } + public string Description { get; set; } + public string DisplayText { get; set; } + public uint JoinNumber { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/Template.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/Template.cs index 31f71df92..bf8dedd66 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/Template.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/Template.cs @@ -3,7 +3,6 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.SmartObjects; -namespace PepperDash.Essentials.Core -{ - -} \ No newline at end of file +namespace PepperDash.Essentials.Core; + + \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/AudioControlListItemBase.cs b/src/PepperDash.Essentials.Core/Devices/AudioControlListItemBase.cs index 295fd25c0..4294374a0 100644 --- a/src/PepperDash.Essentials.Core/Devices/AudioControlListItemBase.cs +++ b/src/PepperDash.Essentials.Core/Devices/AudioControlListItemBase.cs @@ -5,38 +5,37 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public abstract class AudioControlListItemBase { - public abstract class AudioControlListItemBase - { - /// - /// Key of the parent device in the DeviceManager - /// - [JsonProperty("parentDeviceKey")] - public string ParentDeviceKey { get; set; } + /// + /// Key of the parent device in the DeviceManager + /// + [JsonProperty("parentDeviceKey")] + public string ParentDeviceKey { get; set; } - /// - /// Optional key of the item in the parent device - /// - [JsonProperty("itemKey")] - public string ItemKey { get; set; } + /// + /// Optional key of the item in the parent device + /// + [JsonProperty("itemKey")] + public string ItemKey { get; set; } - /// - /// A name that will override the items's name on the UI - /// - [JsonProperty("name")] - public string Name { get; set; } + /// + /// A name that will override the items's name on the UI + /// + [JsonProperty("name")] + public string Name { get; set; } - /// - /// Indicates if the item should be included in the user accessible list - /// - [JsonProperty("includeInUserList")] - public bool IncludeInUserList { get; set; } + /// + /// Indicates if the item should be included in the user accessible list + /// + [JsonProperty("includeInUserList")] + public bool IncludeInUserList { get; set; } - /// - /// Used to specify the order of the items in the source list when displayed - /// - [JsonProperty("order")] - public int Order { get; set; } - } + /// + /// Used to specify the order of the items in the source list when displayed + /// + [JsonProperty("order")] + public int Order { get; set; } } diff --git a/src/PepperDash.Essentials.Core/Devices/AudioInterfaces.cs b/src/PepperDash.Essentials.Core/Devices/AudioInterfaces.cs index 90aa4909e..2eb93d3bc 100644 --- a/src/PepperDash.Essentials.Core/Devices/AudioInterfaces.cs +++ b/src/PepperDash.Essentials.Core/Devices/AudioInterfaces.cs @@ -6,8 +6,8 @@ using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public enum AudioChangeType { @@ -24,5 +24,4 @@ public AudioChangeEventArgs(IBasicVolumeControls device, AudioChangeType changeT ChangeType = changeType; AudioDevice = device; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/CameraListItem.cs b/src/PepperDash.Essentials.Core/Devices/CameraListItem.cs index d519feb45..f0707c9a3 100644 --- a/src/PepperDash.Essentials.Core/Devices/CameraListItem.cs +++ b/src/PepperDash.Essentials.Core/Devices/CameraListItem.cs @@ -1,76 +1,75 @@ using Newtonsoft.Json; using PepperDash.Core; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public class CameraListItem { - public class CameraListItem - { - [JsonProperty("deviceKey")] - public string DeviceKey { get; set; } + [JsonProperty("deviceKey")] + public string DeviceKey { get; set; } - /// - /// Returns the source Device for this, if it exists in DeviceManager - /// - [JsonIgnore] - public Device CameraDevice + /// + /// Returns the source Device for this, if it exists in DeviceManager + /// + [JsonIgnore] + public Device CameraDevice + { + get { - get - { - if (_cameraDevice == null) - _cameraDevice = DeviceManager.GetDeviceForKey(DeviceKey) as Device; - return _cameraDevice; - } + if (_cameraDevice == null) + _cameraDevice = DeviceManager.GetDeviceForKey(DeviceKey) as Device; + return _cameraDevice; } - Device _cameraDevice; + } + Device _cameraDevice; - /// - /// Gets either the source's Name or this AlternateName property, if - /// defined. If source doesn't exist, returns "Missing source" - /// - [JsonProperty("preferredName")] - public string PreferredName + /// + /// Gets either the source's Name or this AlternateName property, if + /// defined. If source doesn't exist, returns "Missing source" + /// + [JsonProperty("preferredName")] + public string PreferredName + { + get { - get + if (string.IsNullOrEmpty(Name)) { - if (string.IsNullOrEmpty(Name)) - { - if (CameraDevice == null) - return "---"; - return CameraDevice.Name; - } - return Name; + if (CameraDevice == null) + return "---"; + return CameraDevice.Name; } + return Name; } + } - /// - /// A name that will override the source's name on the UI - /// - [JsonProperty("name")] - public string Name { get; set; } + /// + /// A name that will override the source's name on the UI + /// + [JsonProperty("name")] + public string Name { get; set; } - /// - /// Specifies and icon for the source list item - /// - [JsonProperty("icon")] - public string Icon { get; set; } + /// + /// Specifies and icon for the source list item + /// + [JsonProperty("icon")] + public string Icon { get; set; } - /// - /// Alternate icon - /// + /// + /// Alternate icon + /// [JsonProperty("altIcon", NullValueHandling = NullValueHandling.Ignore)] - public string AltIcon { get; set; } + public string AltIcon { get; set; } - /// - /// Indicates if the item should be included in the user facing list - /// + /// + /// Indicates if the item should be included in the user facing list + /// [JsonProperty("includeInUserList")] - public bool IncludeInUserList { get; set; } + public bool IncludeInUserList { get; set; } - /// - /// Used to specify the order of the items in the source list when displayed - /// + /// + /// Used to specify the order of the items in the source list when displayed + /// [JsonProperty("order")] - public int Order { get; set; } - } + public int Order { get; set; } } diff --git a/src/PepperDash.Essentials.Core/Devices/CodecInterfaces.cs b/src/PepperDash.Essentials.Core/Devices/CodecInterfaces.cs index afb1da178..0d3e1c990 100644 --- a/src/PepperDash.Essentials.Core/Devices/CodecInterfaces.cs +++ b/src/PepperDash.Essentials.Core/Devices/CodecInterfaces.cs @@ -4,43 +4,42 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Adds control of codec receive volume +/// +public interface IReceiveVolume { - /// - /// Adds control of codec receive volume - /// - public interface IReceiveVolume - { - // Break this out into 3 interfaces - void SetReceiveVolume(ushort level); - void ReceiveMuteOn(); - void ReceiveMuteOff(); - void ReceiveMuteToggle(); - IntFeedback ReceiveLevelFeedback { get; } - BoolFeedback ReceiveMuteIsOnFeedback { get; } - } + // Break this out into 3 interfaces + void SetReceiveVolume(ushort level); + void ReceiveMuteOn(); + void ReceiveMuteOff(); + void ReceiveMuteToggle(); + IntFeedback ReceiveLevelFeedback { get; } + BoolFeedback ReceiveMuteIsOnFeedback { get; } +} - /// - /// Adds control of codec transmit volume - /// - public interface ITransmitVolume - { - void SetTransmitVolume(ushort level); - void TransmitMuteOn(); - void TransmitMuteOff(); - void TransmitMuteToggle(); - IntFeedback TransmitLevelFeedback { get; } - BoolFeedback TransmitMuteIsOnFeedback { get; } - } +/// +/// Adds control of codec transmit volume +/// +public interface ITransmitVolume +{ + void SetTransmitVolume(ushort level); + void TransmitMuteOn(); + void TransmitMuteOff(); + void TransmitMuteToggle(); + IntFeedback TransmitLevelFeedback { get; } + BoolFeedback TransmitMuteIsOnFeedback { get; } +} - /// - /// Adds control of codec privacy function (microphone mute) - /// - public interface IPrivacy - { - void PrivacyModeOn(); - void PrivacyModeOff(); - void PrivacyModeToggle(); - BoolFeedback PrivacyModeIsOnFeedback { get; } - } +/// +/// Adds control of codec privacy function (microphone mute) +/// +public interface IPrivacy +{ + void PrivacyModeOn(); + void PrivacyModeOff(); + void PrivacyModeToggle(); + BoolFeedback PrivacyModeIsOnFeedback { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/CrestronProcessor.cs b/src/PepperDash.Essentials.Core/Devices/CrestronProcessor.cs index 57d99df83..29481b342 100644 --- a/src/PepperDash.Essentials.Core/Devices/CrestronProcessor.cs +++ b/src/PepperDash.Essentials.Core/Devices/CrestronProcessor.cs @@ -8,46 +8,45 @@ using PepperDash.Essentials.Core.CrestronIO; using Serilog.Events; -namespace PepperDash.Essentials.Core.Devices +namespace PepperDash.Essentials.Core.Devices; + +/// +/// This wrapper class is meant to allow interfaces to be applied to any Crestron processor +/// +public class CrestronProcessor : Device, ISwitchedOutputCollection { - /// - /// This wrapper class is meant to allow interfaces to be applied to any Crestron processor - /// - public class CrestronProcessor : Device, ISwitchedOutputCollection - { - public Dictionary SwitchedOutputs { get; private set; } + public Dictionary SwitchedOutputs { get; private set; } - public Crestron.SimplSharpPro.CrestronControlSystem Processor { get; private set; } + public Crestron.SimplSharpPro.CrestronControlSystem Processor { get; private set; } - public CrestronProcessor(string key) - : base(key) - { - SwitchedOutputs = new Dictionary(); - Processor = Global.ControlSystem; + public CrestronProcessor(string key) + : base(key) + { + SwitchedOutputs = new Dictionary(); + Processor = Global.ControlSystem; - GetRelays(); - } + GetRelays(); + } - /// - /// Creates a GenericRelayDevice for each relay on the processor and adds them to the SwitchedOutputs collection - /// - void GetRelays() + /// + /// Creates a GenericRelayDevice for each relay on the processor and adds them to the SwitchedOutputs collection + /// + void GetRelays() + { + try { - try + if (Processor.SupportsRelay) { - if (Processor.SupportsRelay) + for (uint i = 1; i <= Processor.NumberOfRelayPorts; i++) { - for (uint i = 1; i <= Processor.NumberOfRelayPorts; i++) - { - var relay = new GenericRelayDevice(string.Format("{0}-relay-{1}", this.Key, i), Processor.RelayPorts[i]); - SwitchedOutputs.Add(i, relay); - } + var relay = new GenericRelayDevice(string.Format("{0}-relay-{1}", this.Key, i), Processor.RelayPorts[i]); + SwitchedOutputs.Add(i, relay); } } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Error Getting Relays from processor:\n '{0}'", e); - } + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Error Getting Relays from processor:\n '{0}'", e); } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/DestinationListItem.cs b/src/PepperDash.Essentials.Core/Devices/DestinationListItem.cs index 0c21216ab..525a89291 100644 --- a/src/PepperDash.Essentials.Core/Devices/DestinationListItem.cs +++ b/src/PepperDash.Essentials.Core/Devices/DestinationListItem.cs @@ -3,60 +3,59 @@ using Newtonsoft.Json; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public class DestinationListItem { - public class DestinationListItem - { - [JsonProperty("sinkKey")] - public string SinkKey { get; set; } + [JsonProperty("sinkKey")] + public string SinkKey { get; set; } - private EssentialsDevice _sinkDevice; + private EssentialsDevice _sinkDevice; - [JsonIgnore] - public EssentialsDevice SinkDevice - { - get { return _sinkDevice ?? (_sinkDevice = DeviceManager.GetDeviceForKey(SinkKey) as EssentialsDevice); } - } + [JsonIgnore] + public EssentialsDevice SinkDevice + { + get { return _sinkDevice ?? (_sinkDevice = DeviceManager.GetDeviceForKey(SinkKey) as EssentialsDevice); } + } - [JsonProperty("preferredName")] - public string PreferredName + [JsonProperty("preferredName")] + public string PreferredName + { + get { - get + if (!string.IsNullOrEmpty(Name)) { - if (!string.IsNullOrEmpty(Name)) - { - return Name; - } - - return SinkDevice == null ? "---" : SinkDevice.Name; + return Name; } + + return SinkDevice == null ? "---" : SinkDevice.Name; } + } - [JsonProperty("name")] - public string Name { get; set; } + [JsonProperty("name")] + public string Name { get; set; } - [JsonProperty("includeInDestinationList")] - public bool IncludeInDestinationList { get; set; } + [JsonProperty("includeInDestinationList")] + public bool IncludeInDestinationList { get; set; } - [JsonProperty("order")] - public int Order { get; set; } + [JsonProperty("order")] + public int Order { get; set; } - [JsonProperty("surfaceLocation")] - public int SurfaceLocation { get; set; } + [JsonProperty("surfaceLocation")] + public int SurfaceLocation { get; set; } - [JsonProperty("verticalLocation")] - public int VerticalLocation { get; set; } - - [JsonProperty("horizontalLocation")] - public int HorizontalLocation { get; set; } + [JsonProperty("verticalLocation")] + public int VerticalLocation { get; set; } + + [JsonProperty("horizontalLocation")] + public int HorizontalLocation { get; set; } - [JsonProperty("sinkType")] - public eRoutingSignalType SinkType { get; set; } + [JsonProperty("sinkType")] + public eRoutingSignalType SinkType { get; set; } - [JsonProperty("isCodecContentDestination")] - public bool isCodecContentDestination { get; set; } + [JsonProperty("isCodecContentDestination")] + public bool isCodecContentDestination { get; set; } - [JsonProperty("isProgramAudioDestination")] - public bool isProgramAudioDestination { get; set; } - } + [JsonProperty("isProgramAudioDestination")] + public bool isProgramAudioDestination { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/DeviceApiBase.cs b/src/PepperDash.Essentials.Core/Devices/DeviceApiBase.cs index 34669ff5e..79f3ea864 100644 --- a/src/PepperDash.Essentials.Core/Devices/DeviceApiBase.cs +++ b/src/PepperDash.Essentials.Core/Devices/DeviceApiBase.cs @@ -4,14 +4,13 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core.Devices +namespace PepperDash.Essentials.Core.Devices; + +/// +/// Base class for all Device APIs +/// +public abstract class DeviceApiBase { - /// - /// Base class for all Device APIs - /// - public abstract class DeviceApiBase - { - public Dictionary ActionApi { get; protected set; } - public Dictionary FeedbackApi { get; protected set; } - } + public Dictionary ActionApi { get; protected set; } + public Dictionary FeedbackApi { get; protected set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/DeviceFeedbackExtensions.cs b/src/PepperDash.Essentials.Core/Devices/DeviceFeedbackExtensions.cs index 1ef59b0f9..e732e9f4a 100644 --- a/src/PepperDash.Essentials.Core/Devices/DeviceFeedbackExtensions.cs +++ b/src/PepperDash.Essentials.Core/Devices/DeviceFeedbackExtensions.cs @@ -6,27 +6,26 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public static class DeviceFeedbackExtensions { - public static class DeviceFeedbackExtensions + /// + /// Attempts to get and return a feedback property from a device by name. + /// If unsuccessful, returns null. + /// + /// + /// + /// + public static Feedback GetFeedbackProperty(this Device device, string propertyName) { - /// - /// Attempts to get and return a feedback property from a device by name. - /// If unsuccessful, returns null. - /// - /// - /// - /// - public static Feedback GetFeedbackProperty(this Device device, string propertyName) - { - var feedback = DeviceJsonApi.GetPropertyByName(device.Key, propertyName) as Feedback; - - if (feedback != null) - { - return feedback; - } + var feedback = DeviceJsonApi.GetPropertyByName(device.Key, propertyName) as Feedback; - return null; + if (feedback != null) + { + return feedback; } + + return null; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs b/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs index 816251ba0..3422376a9 100644 --- a/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs +++ b/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs @@ -9,443 +9,442 @@ using System.Reflection; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public class DeviceJsonApi { - public class DeviceJsonApi + /// + /// + /// + /// + public static void DoDeviceActionWithJson(string json) { - /// - /// - /// - /// - public static void DoDeviceActionWithJson(string json) + if (String.IsNullOrEmpty(json)) { - if (String.IsNullOrEmpty(json)) - { - CrestronConsole.ConsoleCommandResponse( - "Please provide a JSON object matching the format {\"deviceKey\":\"myDevice\", \"methodName\":\"someMethod\", \"params\": [\"param1\", true]}.\r\nIf the method has no parameters, the \"params\" object may be omitted."); - return; - } - try - { - var action = JsonConvert.DeserializeObject(json); + CrestronConsole.ConsoleCommandResponse( + "Please provide a JSON object matching the format {\"deviceKey\":\"myDevice\", \"methodName\":\"someMethod\", \"params\": [\"param1\", true]}.\r\nIf the method has no parameters, the \"params\" object may be omitted."); + return; + } + try + { + var action = JsonConvert.DeserializeObject(json); + + DoDeviceAction(action); + } + catch (Exception) + { + CrestronConsole.ConsoleCommandResponse("Incorrect format for JSON. Please check that the format matches {\"deviceKey\":\"myDevice\", \"methodName\":\"someMethod\", \"params\": [\"param1\", true]}"); + } + + } - DoDeviceAction(action); - } - catch (Exception) - { - CrestronConsole.ConsoleCommandResponse("Incorrect format for JSON. Please check that the format matches {\"deviceKey\":\"myDevice\", \"methodName\":\"someMethod\", \"params\": [\"param1\", true]}"); - } + /// + /// + /// + /// + public static void DoDeviceAction(DeviceActionWrapper action) + { + var key = action.DeviceKey; + var obj = FindObjectOnPath(key); + if (obj == null) + { + CrestronConsole.ConsoleCommandResponse("Unable to find object at path {0}", key); + return; } + if (action.Params == null) + { + //no params, so setting action.Params to empty array + action.Params = new object[0]; + } - /// - /// - /// - /// - public static void DoDeviceAction(DeviceActionWrapper action) + Type t = obj.GetType(); + try { - var key = action.DeviceKey; - var obj = FindObjectOnPath(key); - if (obj == null) - { - CrestronConsole.ConsoleCommandResponse("Unable to find object at path {0}", key); - return; - } + var methods = t.GetMethods().Where(m => m.Name == action.MethodName).ToList(); - if (action.Params == null) - { - //no params, so setting action.Params to empty array - action.Params = new object[0]; - } + var method = methods.Count == 1 ? methods[0] : methods.FirstOrDefault(m => m.GetParameters().Length == action.Params.Length); - Type t = obj.GetType(); - try + if (method == null) { - var methods = t.GetMethods().Where(m => m.Name == action.MethodName).ToList(); + CrestronConsole.ConsoleCommandResponse( + "Unable to find method with name {0} and that matches parameters {1}", action.MethodName, + action.Params); + return; + } + var mParams = method.GetParameters(); - var method = methods.Count == 1 ? methods[0] : methods.FirstOrDefault(m => m.GetParameters().Length == action.Params.Length); + var convertedParams = mParams + .Select((p, i) => ConvertType(action.Params[i], p.ParameterType)) + .ToArray(); - if (method == null) + Task.Run(() => { - CrestronConsole.ConsoleCommandResponse( - "Unable to find method with name {0} and that matches parameters {1}", action.MethodName, - action.Params); - return; - } - var mParams = method.GetParameters(); + try + { + Debug.LogMessage(LogEventLevel.Verbose, "Calling method {methodName} on device {deviceKey}", null, method.Name, action.DeviceKey); + method.Invoke(obj, convertedParams); + } + catch (Exception e) + { + Debug.LogMessage(e, "Error invoking method {methodName} on device {deviceKey}", null, method.Name, action.DeviceKey); + } + }); - var convertedParams = mParams - .Select((p, i) => ConvertType(action.Params[i], p.ParameterType)) - .ToArray(); + CrestronConsole.ConsoleCommandResponse("Method {0} successfully called on device {1}", method.Name, + action.DeviceKey); + } + catch (Exception ex) + { + CrestronConsole.ConsoleCommandResponse("Unable to call method with name {0}. {1}", action.MethodName, + ex.Message); + } + } - Task.Run(() => - { - try - { - Debug.LogMessage(LogEventLevel.Verbose, "Calling method {methodName} on device {deviceKey}", null, method.Name, action.DeviceKey); - method.Invoke(obj, convertedParams); - } - catch (Exception e) - { - Debug.LogMessage(e, "Error invoking method {methodName} on device {deviceKey}", null, method.Name, action.DeviceKey); - } - }); + public static async Task DoDeviceActionAsync(DeviceActionWrapper action) + { + var key = action.DeviceKey; + var obj = FindObjectOnPath(key); + if (obj == null) + { + Debug.LogMessage(LogEventLevel.Warning, "Unable to find object at path {deviceKey}", null, key); + return; + } - CrestronConsole.ConsoleCommandResponse("Method {0} successfully called on device {1}", method.Name, - action.DeviceKey); - } - catch (Exception ex) - { - CrestronConsole.ConsoleCommandResponse("Unable to call method with name {0}. {1}", action.MethodName, - ex.Message); - } + if (action.Params == null) + { + //no params, so setting action.Params to empty array + action.Params = new object[0]; } - public static async Task DoDeviceActionAsync(DeviceActionWrapper action) + Type t = obj.GetType(); + try { - var key = action.DeviceKey; - var obj = FindObjectOnPath(key); - if (obj == null) + var methods = t.GetMethods().Where(m => m.Name == action.MethodName).ToList(); + + var method = methods.Count == 1 ? methods[0] : methods.FirstOrDefault(m => m.GetParameters().Length == action.Params.Length); + + if (method == null) { - Debug.LogMessage(LogEventLevel.Warning, "Unable to find object at path {deviceKey}", null, key); + Debug.LogMessage(LogEventLevel.Warning, + "Unable to find method with name {methodName} and that matches parameters {@parameters}", null, action.MethodName, + action.Params); return; } + var mParams = method.GetParameters(); - if (action.Params == null) - { - //no params, so setting action.Params to empty array - action.Params = new object[0]; - } + var convertedParams = mParams + .Select((p, i) => ConvertType(action.Params[i], p.ParameterType)) + .ToArray(); - Type t = obj.GetType(); try { - var methods = t.GetMethods().Where(m => m.Name == action.MethodName).ToList(); - - var method = methods.Count == 1 ? methods[0] : methods.FirstOrDefault(m => m.GetParameters().Length == action.Params.Length); - - if (method == null) + Debug.LogMessage(LogEventLevel.Verbose, "Calling method {methodName} on device {deviceKey} with {@params}", null, method.Name, action.DeviceKey, action.Params); + var result = method.Invoke(obj, convertedParams); + + // If the method returns a Task, await it + if (result is Task task) { - Debug.LogMessage(LogEventLevel.Warning, - "Unable to find method with name {methodName} and that matches parameters {@parameters}", null, action.MethodName, - action.Params); - return; + await task; } - var mParams = method.GetParameters(); - - var convertedParams = mParams - .Select((p, i) => ConvertType(action.Params[i], p.ParameterType)) - .ToArray(); - - try - { - Debug.LogMessage(LogEventLevel.Verbose, "Calling method {methodName} on device {deviceKey} with {@params}", null, method.Name, action.DeviceKey, action.Params); - var result = method.Invoke(obj, convertedParams); - - // If the method returns a Task, await it - if (result is Task task) - { - await task; - } - // If the method returns a Task, await it - else if (result != null && result.GetType().IsGenericType && result.GetType().GetGenericTypeDefinition() == typeof(Task<>)) - { - await (Task)result; - } - } - catch (Exception e) + // If the method returns a Task, await it + else if (result != null && result.GetType().IsGenericType && result.GetType().GetGenericTypeDefinition() == typeof(Task<>)) { - Debug.LogMessage(e, "Error invoking method {methodName} on device {deviceKey}", null, method.Name, action.DeviceKey); + await (Task)result; } } - catch (Exception ex) + catch (Exception e) { - Debug.LogMessage(ex, "Unable to call method with name {methodName} with {@parameters}", null, action.MethodName, action.Params); + Debug.LogMessage(e, "Error invoking method {methodName} on device {deviceKey}", null, method.Name, action.DeviceKey); } } - - private static object ConvertType(object value, Type conversionType) + catch (Exception ex) { - if (!conversionType.IsEnum) - { - return Convert.ChangeType(value, conversionType, System.Globalization.CultureInfo.InvariantCulture); - } - - var stringValue = Convert.ToString(value); - - if (String.IsNullOrEmpty(stringValue)) - { - throw new InvalidCastException( - String.Format("{0} cannot be converted to a string prior to conversion to enum")); - } - return Enum.Parse(conversionType, stringValue, true); + Debug.LogMessage(ex, "Unable to call method with name {methodName} with {@parameters}", null, action.MethodName, action.Params); } + } - /// - /// Gets the properties on a device - /// - /// - /// - public static string GetProperties(string deviceObjectPath) + private static object ConvertType(object value, Type conversionType) + { + if (!conversionType.IsEnum) { - var obj = FindObjectOnPath(deviceObjectPath); - if (obj == null) - return "{ \"error\":\"No Device\"}"; - - Type t = obj.GetType(); - // get the properties and set them into a new collection of NameType wrappers - var props = t.GetProperties().Select(p => new PropertyNameType(p, obj)); - return JsonConvert.SerializeObject(props, Formatting.Indented); + return Convert.ChangeType(value, conversionType, System.Globalization.CultureInfo.InvariantCulture); } - /// - /// Gets a property from a device path by name - /// - /// - /// - /// - public static object GetPropertyByName(string deviceObjectPath, string propertyName) + var stringValue = Convert.ToString(value); + + if (String.IsNullOrEmpty(stringValue)) { - var dev = FindObjectOnPath(deviceObjectPath); - if (dev == null) - return "{ \"error\":\"No Device\"}"; + throw new InvalidCastException( + String.Format("{0} cannot be converted to a string prior to conversion to enum")); + } + return Enum.Parse(conversionType, stringValue, true); + } + + /// + /// Gets the properties on a device + /// + /// + /// + public static string GetProperties(string deviceObjectPath) + { + var obj = FindObjectOnPath(deviceObjectPath); + if (obj == null) + return "{ \"error\":\"No Device\"}"; + + Type t = obj.GetType(); + // get the properties and set them into a new collection of NameType wrappers + var props = t.GetProperties().Select(p => new PropertyNameType(p, obj)); + return JsonConvert.SerializeObject(props, Formatting.Indented); + } - object prop = dev.GetType().GetProperty(propertyName).GetValue(dev, null); + /// + /// Gets a property from a device path by name + /// + /// + /// + /// + public static object GetPropertyByName(string deviceObjectPath, string propertyName) + { + var dev = FindObjectOnPath(deviceObjectPath); + if (dev == null) + return "{ \"error\":\"No Device\"}"; - // var prop = t.GetProperty(propertyName); - if (prop != null) - { - return prop; - } - else - { - Debug.LogMessage(LogEventLevel.Debug, "Unable to find Property: {0} on Device with path: {1}", propertyName, deviceObjectPath); - return null; - } - } + object prop = dev.GetType().GetProperty(propertyName).GetValue(dev, null); - /// - /// Gets the methods on a device - /// - /// - /// - public static string GetMethods(string deviceObjectPath) + // var prop = t.GetProperty(propertyName); + if (prop != null) { - var obj = FindObjectOnPath(deviceObjectPath); - if (obj == null) - return "{ \"error\":\"No Device\"}"; - - // Package up method names using helper objects - Type t = obj.GetType(); - var methods = t.GetMethods() - .Where(m => !m.IsSpecialName) - .Select(p => new MethodNameParams(p)); - return JsonConvert.SerializeObject(methods, Formatting.Indented); + return prop; } - - public static string GetApiMethods(string deviceObjectPath) + else { - var obj = FindObjectOnPath(deviceObjectPath); - if (obj == null) - return "{ \"error\":\"No Device\"}"; - - // Package up method names using helper objects - Type t = obj.GetType(); - var methods = t.GetMethods() - .Where(m => !m.IsSpecialName) - .Where(m => m.GetCustomAttributes(typeof(ApiAttribute), true).Any()) - .Select(p => new MethodNameParams(p)); - return JsonConvert.SerializeObject(methods, Formatting.Indented); + Debug.LogMessage(LogEventLevel.Debug, "Unable to find Property: {0} on Device with path: {1}", propertyName, deviceObjectPath); + return null; } + } + /// + /// Gets the methods on a device + /// + /// + /// + public static string GetMethods(string deviceObjectPath) + { + var obj = FindObjectOnPath(deviceObjectPath); + if (obj == null) + return "{ \"error\":\"No Device\"}"; + + // Package up method names using helper objects + Type t = obj.GetType(); + var methods = t.GetMethods() + .Where(m => !m.IsSpecialName) + .Select(p => new MethodNameParams(p)); + return JsonConvert.SerializeObject(methods, Formatting.Indented); + } - /// - /// Walks down a dotted object path, starting with a Device, and returns the object - /// at the end of the path - /// - public static object FindObjectOnPath(string deviceObjectPath) - { - var path = deviceObjectPath.Split('.'); + public static string GetApiMethods(string deviceObjectPath) + { + var obj = FindObjectOnPath(deviceObjectPath); + if (obj == null) + return "{ \"error\":\"No Device\"}"; + + // Package up method names using helper objects + Type t = obj.GetType(); + var methods = t.GetMethods() + .Where(m => !m.IsSpecialName) + .Where(m => m.GetCustomAttributes(typeof(ApiAttribute), true).Any()) + .Select(p => new MethodNameParams(p)); + return JsonConvert.SerializeObject(methods, Formatting.Indented); + } - var dev = DeviceManager.GetDeviceForKey(path[0]); - if (dev == null) - { - Debug.LogMessage(LogEventLevel.Information, "Device {0} not found", path[0]); - return null; - } - // loop through any dotted properties - object obj = dev; - if (path.Length > 1) + /// + /// Walks down a dotted object path, starting with a Device, and returns the object + /// at the end of the path + /// + public static object FindObjectOnPath(string deviceObjectPath) + { + var path = deviceObjectPath.Split('.'); + + var dev = DeviceManager.GetDeviceForKey(path[0]); + if (dev == null) + { + Debug.LogMessage(LogEventLevel.Information, "Device {0} not found", path[0]); + return null; + } + + // loop through any dotted properties + object obj = dev; + if (path.Length > 1) + { + for (int i = 1; i < path.Length; i++) { - for (int i = 1; i < path.Length; i++) + var objName = path[i]; + string indexStr = null; + var indexOpen = objName.IndexOf('['); + if (indexOpen != -1) { - var objName = path[i]; - string indexStr = null; - var indexOpen = objName.IndexOf('['); - if (indexOpen != -1) + var indexClose = objName.IndexOf(']'); + if (indexClose == -1) { - var indexClose = objName.IndexOf(']'); - if (indexClose == -1) - { - Debug.LogMessage(LogEventLevel.Information, dev, "ERROR Unmatched index brackets"); - return null; - } - // Get the index and strip quotes if any - indexStr = objName.Substring(indexOpen + 1, indexClose - indexOpen - 1).Replace("\"", ""); - objName = objName.Substring(0, indexOpen); - Debug.LogMessage(LogEventLevel.Information, dev, " Checking for collection '{0}', index '{1}'", objName, indexStr); + Debug.LogMessage(LogEventLevel.Information, dev, "ERROR Unmatched index brackets"); + return null; } + // Get the index and strip quotes if any + indexStr = objName.Substring(indexOpen + 1, indexClose - indexOpen - 1).Replace("\"", ""); + objName = objName.Substring(0, indexOpen); + Debug.LogMessage(LogEventLevel.Information, dev, " Checking for collection '{0}', index '{1}'", objName, indexStr); + } - Type oType = obj.GetType(); - var prop = oType.GetProperty(objName); - if (prop == null) + Type oType = obj.GetType(); + var prop = oType.GetProperty(objName); + if (prop == null) + { + Debug.LogMessage(LogEventLevel.Information, dev, "Property {0} not found on {1}", objName, path[i - 1]); + return null; + } + // if there's an index, try to get the property + if (indexStr != null) + { + if (!typeof(ICollection).IsAssignableFrom(prop.PropertyType)) { - Debug.LogMessage(LogEventLevel.Information, dev, "Property {0} not found on {1}", objName, path[i - 1]); + Debug.LogMessage(LogEventLevel.Information, dev, "Property {0} is not collection", objName); return null; } - // if there's an index, try to get the property - if (indexStr != null) + var collection = prop.GetValue(obj, null) as ICollection; + // Get the indexed items "property" + var indexedPropInfo = prop.PropertyType.GetProperty("Item"); + // These are the parameters for the indexing. Only care about one + var indexParams = indexedPropInfo.GetIndexParameters(); + if (indexParams.Length > 0) { - if (!typeof(ICollection).IsAssignableFrom(prop.PropertyType)) + Debug.LogMessage(LogEventLevel.Information, " Indexed, param type: {0}", indexParams[0].ParameterType.Name); + var properParam = Convert.ChangeType(indexStr, indexParams[0].ParameterType, + System.Globalization.CultureInfo.InvariantCulture); + try { - Debug.LogMessage(LogEventLevel.Information, dev, "Property {0} is not collection", objName); - return null; + obj = indexedPropInfo.GetValue(collection, new object[] { properParam }); } - var collection = prop.GetValue(obj, null) as ICollection; - // Get the indexed items "property" - var indexedPropInfo = prop.PropertyType.GetProperty("Item"); - // These are the parameters for the indexing. Only care about one - var indexParams = indexedPropInfo.GetIndexParameters(); - if (indexParams.Length > 0) + // if the index is bad, catch it here. + catch (TargetInvocationException e) { - Debug.LogMessage(LogEventLevel.Information, " Indexed, param type: {0}", indexParams[0].ParameterType.Name); - var properParam = Convert.ChangeType(indexStr, indexParams[0].ParameterType, - System.Globalization.CultureInfo.InvariantCulture); - try - { - obj = indexedPropInfo.GetValue(collection, new object[] { properParam }); - } - // if the index is bad, catch it here. - catch (TargetInvocationException e) - { - if (e.InnerException is ArgumentOutOfRangeException) - Debug.LogMessage(LogEventLevel.Information, " Index Out of range"); - else if (e.InnerException is KeyNotFoundException) - Debug.LogMessage(LogEventLevel.Information, " Key not found"); - return null; - } + if (e.InnerException is ArgumentOutOfRangeException) + Debug.LogMessage(LogEventLevel.Information, " Index Out of range"); + else if (e.InnerException is KeyNotFoundException) + Debug.LogMessage(LogEventLevel.Information, " Key not found"); + return null; } - } - else - obj = prop.GetValue(obj, null); + } + else + obj = prop.GetValue(obj, null); } - return obj; } + return obj; + } - /// - /// Sets a property on an object. - /// - /// - /// - public static string SetProperty(string deviceObjectPath) - { - throw new NotImplementedException("This could be really useful. Finish it please"); + /// + /// Sets a property on an object. + /// + /// + /// + public static string SetProperty(string deviceObjectPath) + { + throw new NotImplementedException("This could be really useful. Finish it please"); - //var obj = FindObjectOnPath(deviceObjectPath); - //if (obj == null) - // return "{\"error\":\"No object found\"}"; + //var obj = FindObjectOnPath(deviceObjectPath); + //if (obj == null) + // return "{\"error\":\"No object found\"}"; - //Type t = obj.GetType(); + //Type t = obj.GetType(); - //// get the properties and set them into a new collection of NameType wrappers - //var props = t.GetProperties().Select(p => new PropertyNameType(p, obj)); - //return JsonConvert.SerializeObject(props, Formatting.Indented); - } + //// get the properties and set them into a new collection of NameType wrappers + //var props = t.GetProperties().Select(p => new PropertyNameType(p, obj)); + //return JsonConvert.SerializeObject(props, Formatting.Indented); + } - } +} - public class DeviceActionWrapper - { - public string DeviceKey { get; set; } - public string MethodName { get; set; } - public object[] Params { get; set; } - } +public class DeviceActionWrapper +{ + public string DeviceKey { get; set; } + public string MethodName { get; set; } + public object[] Params { get; set; } +} - public class PropertyNameType - { - private object Parent; +public class PropertyNameType +{ + private object Parent; - [JsonIgnore] - public PropertyInfo PropInfo { get; private set; } - public string Name { get { return PropInfo.Name; } } - public string Type { get { return PropInfo.PropertyType.Name; } } - public string Value + [JsonIgnore] + public PropertyInfo PropInfo { get; private set; } + public string Name { get { return PropInfo.Name; } } + public string Type { get { return PropInfo.PropertyType.Name; } } + public string Value + { + get { - get + if (PropInfo.CanRead) { - if (PropInfo.CanRead) + try { - try - { - return PropInfo.GetValue(Parent, null).ToString(); - } - catch (Exception) - { - return null; - } + return PropInfo.GetValue(Parent, null).ToString(); } - else + catch (Exception) + { return null; + } } + else + return null; } + } - public bool CanRead { get { return PropInfo.CanRead; } } - public bool CanWrite { get { return PropInfo.CanWrite; } } - + public bool CanRead { get { return PropInfo.CanRead; } } + public bool CanWrite { get { return PropInfo.CanWrite; } } - public PropertyNameType(PropertyInfo info, object parent) - { - PropInfo = info; - Parent = parent; - } - } - public class MethodNameParams + public PropertyNameType(PropertyInfo info, object parent) { - [JsonIgnore] - public MethodInfo MethodInfo { get; private set; } + PropInfo = info; + Parent = parent; + } +} - public string Name { get { return MethodInfo.Name; } } - public IEnumerable Params - { - get - { - return MethodInfo.GetParameters().Select(p => - new NameType { Name = p.Name, Type = p.ParameterType.Name }); - } - } +public class MethodNameParams +{ + [JsonIgnore] + public MethodInfo MethodInfo { get; private set; } - public MethodNameParams(MethodInfo info) + public string Name { get { return MethodInfo.Name; } } + public IEnumerable Params + { + get { - MethodInfo = info; + return MethodInfo.GetParameters().Select(p => + new NameType { Name = p.Name, Type = p.ParameterType.Name }); } } - public class NameType + public MethodNameParams(MethodInfo info) { - public string Name { get; set; } - public string Type { get; set; } + MethodInfo = info; } +} - [AttributeUsage(AttributeTargets.All)] - public class ApiAttribute : Attribute - { +public class NameType +{ + public string Name { get; set; } + public string Type { get; set; } +} + +[AttributeUsage(AttributeTargets.All)] +public class ApiAttribute : Attribute +{ - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/DeviceManager.cs b/src/PepperDash.Essentials.Core/Devices/DeviceManager.cs index 5cd921b89..ad003c466 100644 --- a/src/PepperDash.Essentials.Core/Devices/DeviceManager.cs +++ b/src/PepperDash.Essentials.Core/Devices/DeviceManager.cs @@ -1,507 +1,514 @@ -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; -using PepperDash.Core; -using Serilog.Events; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using PepperDash.Core; +using Serilog.Events; + +namespace PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core +public static class DeviceManager { - public static class DeviceManager - { - public static event EventHandler AllDevicesActivated; - public static event EventHandler AllDevicesRegistered; - public static event EventHandler AllDevicesInitialized; + public static event EventHandler AllDevicesActivated; + public static event EventHandler AllDevicesRegistered; + public static event EventHandler AllDevicesInitialized; - private static readonly CCriticalSection DeviceCriticalSection = new CCriticalSection(); - private static readonly CEvent AllowAddDevicesCEvent = new CEvent(false, true); + private static readonly CCriticalSection DeviceCriticalSection = new CCriticalSection(); - //public static List Devices { get { return _Devices; } } - //static List _Devices = new List(); + //public static List Devices { get { return _Devices; } } + //static List _Devices = new List(); - private static readonly Dictionary Devices = new Dictionary(StringComparer.OrdinalIgnoreCase); + private static readonly Dictionary Devices = new Dictionary(StringComparer.OrdinalIgnoreCase); - /// - /// Returns a copy of all the devices in a list - /// - public static List AllDevices { get { return new List(Devices.Values); } } + /// + /// Returns a copy of all the devices in a list + /// + public static List AllDevices => [.. Devices.Values]; - public static bool AddDeviceEnabled; + public static bool AddDeviceEnabled; - public static void Initialize(CrestronControlSystem cs) - { - AddDeviceEnabled = true; - CrestronConsole.AddNewConsoleCommand(ListDeviceCommStatuses, "devcommstatus", "Lists the communication status of all devices", - ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(ListDeviceFeedbacks, "devfb", "Lists current feedbacks", - ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(ListDevices, "devlist", "Lists current managed devices", - ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(DeviceJsonApi.DoDeviceActionWithJson, "devjson", "", - ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetProperties(s)), "devprops", "", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetMethods(s)), "devmethods", "", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s)), "apimethods", "", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(SimulateComReceiveOnDevice, "devsimreceive", - "Simulates incoming data on a com device", ConsoleAccessLevelEnum.AccessOperator); - - CrestronConsole.AddNewConsoleCommand(SetDeviceStreamDebugging, "setdevicestreamdebug", "set comm debug [deviceKey] [off/rx/tx/both] ([minutes])", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => DisableAllDeviceStreamDebugging(), "disableallstreamdebug", "disables stream debugging on all devices", ConsoleAccessLevelEnum.AccessOperator); - } + /// + /// Initializes the control system by enabling device management and registering console commands. + /// + /// This method sets up the control system for device management by enabling the addition of + /// devices and registering a series of console commands for interacting with devices. These commands allow + /// operators to list device statuses, feedbacks, and managed devices, as well as perform actions such as + /// simulating communication, debugging device streams, and accessing device properties and methods. + /// The instance representing the control system to initialize. + public static void Initialize(CrestronControlSystem cs) + { + AddDeviceEnabled = true; + + CrestronConsole.AddNewConsoleCommand(ListDeviceCommStatuses, "devcommstatus", "Lists the communication status of all devices", + ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(ListDeviceFeedbacks, "devfb", "Lists current feedbacks", + ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(ListDevices, "devlist", "Lists current managed devices", + ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(DeviceJsonApi.DoDeviceActionWithJson, "devjson", "", + ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetProperties(s)), "devprops", "", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetMethods(s)), "devmethods", "", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s)), "apimethods", "", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(SimulateComReceiveOnDevice, "devsimreceive", + "Simulates incoming data on a com device", ConsoleAccessLevelEnum.AccessOperator); + + CrestronConsole.AddNewConsoleCommand(SetDeviceStreamDebugging, "setdevicestreamdebug", "set comm debug [deviceKey] [off/rx/tx/both] ([minutes])", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => DisableAllDeviceStreamDebugging(), "disableallstreamdebug", "disables stream debugging on all devices", ConsoleAccessLevelEnum.AccessOperator); + } - /// - /// Calls activate steps on all Device class items - /// - public static void ActivateAll() + /// + /// Calls activate steps on all Device class items + /// + public static void ActivateAll() + { + try { - try - { - OnAllDevicesRegistered(); + OnAllDevicesRegistered(); - DeviceCriticalSection.Enter(); - AddDeviceEnabled = false; - // PreActivate all devices - Debug.LogMessage(LogEventLevel.Information, "****PreActivation starting...****"); - foreach (var d in Devices.Values) + DeviceCriticalSection.Enter(); + AddDeviceEnabled = false; + // PreActivate all devices + Debug.LogMessage(LogEventLevel.Information, "****PreActivation starting...****"); + foreach (var d in Devices.Values) + { + try { - try - { - if (d is Device) - (d as Device).PreActivate(); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Information, d, "ERROR: Device {1} PreActivation failure: {0}", e.Message, d.Key); - Debug.LogMessage(LogEventLevel.Debug, d, "Stack Trace: {0}", e.StackTrace); - } + if (d is Device) + (d as Device).PreActivate(); } - Debug.LogMessage(LogEventLevel.Information, "****PreActivation complete****"); - Debug.LogMessage(LogEventLevel.Information, "****Activation starting...****"); - - // Activate all devices - foreach (var d in Devices.Values) + catch (Exception e) { - try - { - if (d is Device) - (d as Device).Activate(); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Information, d, "ERROR: Device {1} Activation failure: {0}", e.Message, d.Key); - Debug.LogMessage(LogEventLevel.Debug, d, "Stack Trace: {0}", e.StackTrace); - } + Debug.LogMessage(LogEventLevel.Information, d, "ERROR: Device {1} PreActivation failure: {0}", e.Message, d.Key); + Debug.LogMessage(LogEventLevel.Debug, d, "Stack Trace: {0}", e.StackTrace); } + } + Debug.LogMessage(LogEventLevel.Information, "****PreActivation complete****"); + Debug.LogMessage(LogEventLevel.Information, "****Activation starting...****"); - Debug.LogMessage(LogEventLevel.Information, "****Activation complete****"); - Debug.LogMessage(LogEventLevel.Information, "****PostActivation starting...****"); - - // PostActivate all devices - foreach (var d in Devices.Values) + // Activate all devices + foreach (var d in Devices.Values) + { + try + { + if (d is Device) + (d as Device).Activate(); + } + catch (Exception e) { - try - { - if (d is Device) - (d as Device).PostActivate(); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Information, d, "ERROR: Device {1} PostActivation failure: {0}", e.Message, d.Key); - Debug.LogMessage(LogEventLevel.Debug, d, "Stack Trace: {0}", e.StackTrace); - } + Debug.LogMessage(LogEventLevel.Information, d, "ERROR: Device {1} Activation failure: {0}", e.Message, d.Key); + Debug.LogMessage(LogEventLevel.Debug, d, "Stack Trace: {0}", e.StackTrace); } + } - Debug.LogMessage(LogEventLevel.Information, "****PostActivation complete****"); + Debug.LogMessage(LogEventLevel.Information, "****Activation complete****"); + Debug.LogMessage(LogEventLevel.Information, "****PostActivation starting...****"); - OnAllDevicesActivated(); - } - finally + // PostActivate all devices + foreach (var d in Devices.Values) { - DeviceCriticalSection.Leave(); + try + { + if (d is Device) + (d as Device).PostActivate(); + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Information, d, "ERROR: Device {1} PostActivation failure: {0}", e.Message, d.Key); + Debug.LogMessage(LogEventLevel.Debug, d, "Stack Trace: {0}", e.StackTrace); + } } + + Debug.LogMessage(LogEventLevel.Information, "****PostActivation complete****"); + + OnAllDevicesActivated(); + } + finally + { + DeviceCriticalSection.Leave(); } + } + + private static void DeviceManager_Initialized(object sender, EventArgs e) + { + var allInitialized = Devices.Values.OfType().All(d => d.IsInitialized); - private static void DeviceManager_Initialized(object sender, EventArgs e) + if (allInitialized) { - var allInitialized = Devices.Values.OfType().All(d => d.IsInitialized); + Debug.LogMessage(LogEventLevel.Information, "****All Devices Initalized****"); - if (allInitialized) - { - Debug.LogMessage(LogEventLevel.Information, "****All Devices Initalized****"); + OnAllDevicesInitialized(); + } + } - OnAllDevicesInitialized(); - } + private static void OnAllDevicesActivated() + { + var handler = AllDevicesActivated; + if (handler != null) + { + handler(null, new EventArgs()); } + } - private static void OnAllDevicesActivated() + private static void OnAllDevicesRegistered() + { + var handler = AllDevicesRegistered; + if (handler != null) { - var handler = AllDevicesActivated; - if (handler != null) - { - handler(null, new EventArgs()); - } + handler(null, new EventArgs()); } + } - private static void OnAllDevicesRegistered() + private static void OnAllDevicesInitialized() + { + var handler = AllDevicesInitialized; + if (handler != null) { - var handler = AllDevicesRegistered; - if (handler != null) - { - handler(null, new EventArgs()); - } + handler(null, new EventArgs()); } + } - private static void OnAllDevicesInitialized() + /// + /// Calls activate on all Device class items + /// + public static void DeactivateAll() + { + try { - var handler = AllDevicesInitialized; - if (handler != null) + DeviceCriticalSection.Enter(); + foreach (var d in Devices.Values.OfType()) { - handler(null, new EventArgs()); + d.Deactivate(); } } + finally + { + DeviceCriticalSection.Leave(); + } + } - /// - /// Calls activate on all Device class items - /// - public static void DeactivateAll() + //static void ListMethods(string devKey) + //{ + // var dev = GetDeviceForKey(devKey); + // if(dev != null) + // { + // var type = dev.GetType().GetType(); + // var methods = type.GetMethods(BindingFlags.Public|BindingFlags.Instance); + // var sb = new StringBuilder(); + // sb.AppendLine(string.Format("{2} methods on [{0}] ({1}):", dev.Key, type.Name, methods.Length)); + // foreach (var m in methods) + // { + // sb.Append(string.Format("{0}(", m.Name)); + // var pars = m.GetParameters(); + // foreach (var p in pars) + // sb.Append(string.Format("({1}){0} ", p.Name, p.ParameterType.Name)); + // sb.AppendLine(")"); + // } + // CrestronConsole.ConsoleCommandResponse(sb.ToString()); + // } + //} + + private static void ListDevices(string s) + { + Debug.LogMessage(LogEventLevel.Information, "{0} Devices registered with Device Manager:", Devices.Count); + var sorted = Devices.Values.ToList(); + sorted.Sort((a, b) => a.Key.CompareTo(b.Key)); + + foreach (var d in sorted) { - try - { - DeviceCriticalSection.Enter(); - foreach (var d in Devices.Values.OfType()) - { - d.Deactivate(); - } - } - finally - { - DeviceCriticalSection.Leave(); - } + var name = d is IKeyName ? (d as IKeyName).Name : "---"; + Debug.LogMessage(LogEventLevel.Information, " [{0}] {1}", d.Key, name); } + } - //static void ListMethods(string devKey) - //{ - // var dev = GetDeviceForKey(devKey); - // if(dev != null) - // { - // var type = dev.GetType().GetType(); - // var methods = type.GetMethods(BindingFlags.Public|BindingFlags.Instance); - // var sb = new StringBuilder(); - // sb.AppendLine(string.Format("{2} methods on [{0}] ({1}):", dev.Key, type.Name, methods.Length)); - // foreach (var m in methods) - // { - // sb.Append(string.Format("{0}(", m.Name)); - // var pars = m.GetParameters(); - // foreach (var p in pars) - // sb.Append(string.Format("({1}){0} ", p.Name, p.ParameterType.Name)); - // sb.AppendLine(")"); - // } - // CrestronConsole.ConsoleCommandResponse(sb.ToString()); - // } - //} - - private static void ListDevices(string s) + private static void ListDeviceFeedbacks(string devKey) + { + var dev = GetDeviceForKey(devKey); + if (dev == null) + { + Debug.LogMessage(LogEventLevel.Information, "Device '{0}' not found", devKey); + return; + } + if (!(dev is IHasFeedback statusDev)) { - Debug.LogMessage(LogEventLevel.Information, "{0} Devices registered with Device Manager:", Devices.Count); - var sorted = Devices.Values.ToList(); - sorted.Sort((a, b) => a.Key.CompareTo(b.Key)); + Debug.LogMessage(LogEventLevel.Information, "Device '{0}' does not have visible feedbacks", devKey); + return; + } + statusDev.DumpFeedbacksToConsole(true); + } - foreach (var d in sorted) - { - var name = d is IKeyName ? (d as IKeyName).Name : "---"; - Debug.LogMessage(LogEventLevel.Information, " [{0}] {1}", d.Key, name); - } + //static void ListDeviceCommands(string devKey) + //{ + // var dev = GetDeviceForKey(devKey); + // if (dev == null) + // { + // Debug.LogMessage(LogEventLevel.Information, "Device '{0}' not found", devKey); + // return; + // } + // Debug.LogMessage(LogEventLevel.Information, "This needs to be reworked. Stay tuned.", devKey); + //} + + private static void ListDeviceCommStatuses(string input) + { + + foreach (var dev in Devices.Values.OfType()) + { + CrestronConsole.ConsoleCommandResponse($"{dev}: {dev.CommunicationMonitor.Status}\r\n"); } + } - private static void ListDeviceFeedbacks(string devKey) + + //static void DoDeviceCommand(string command) + //{ + // Debug.LogMessage(LogEventLevel.Information, "Not yet implemented. Stay tuned"); + //} + + public static void AddDevice(IKeyed newDev) + { + try { - var dev = GetDeviceForKey(devKey); - if (dev == null) + if (!DeviceCriticalSection.TryEnter()) { - Debug.LogMessage(LogEventLevel.Information, "Device '{0}' not found", devKey); + Debug.LogMessage(LogEventLevel.Information, "Currently unable to add devices to Device Manager. Please try again"); return; } - if (!(dev is IHasFeedback statusDev)) + // Check for device with same key + //var existingDevice = _Devices.FirstOrDefault(d => d.Key.Equals(newDev.Key, StringComparison.OrdinalIgnoreCase)); + ////// If it exists, remove or warn?? + //if (existingDevice != null) + + if (!AddDeviceEnabled) { - Debug.LogMessage(LogEventLevel.Information, "Device '{0}' does not have visible feedbacks", devKey); + Debug.LogMessage(LogEventLevel.Information, "All devices have been activated. Adding new devices is not allowed."); return; } - statusDev.DumpFeedbacksToConsole(true); - } - - //static void ListDeviceCommands(string devKey) - //{ - // var dev = GetDeviceForKey(devKey); - // if (dev == null) - // { - // Debug.LogMessage(LogEventLevel.Information, "Device '{0}' not found", devKey); - // return; - // } - // Debug.LogMessage(LogEventLevel.Information, "This needs to be reworked. Stay tuned.", devKey); - //} - - private static void ListDeviceCommStatuses(string input) - { - foreach (var dev in Devices.Values.OfType()) + if (Devices.ContainsKey(newDev.Key)) { - CrestronConsole.ConsoleCommandResponse($"{dev}: {dev.CommunicationMonitor.Status}\r\n"); + Debug.LogMessage(LogEventLevel.Information, newDev, "WARNING: A device with this key already exists. Not added to manager"); + return; } - } + Devices.Add(newDev.Key, newDev); + //if (!(_Devices.Contains(newDev))) + // _Devices.Add(newDev); + if (newDev is EssentialsDevice essentialsDev) + essentialsDev.Initialized += DeviceManager_Initialized; + } + finally + { + DeviceCriticalSection.Leave(); + } + } - //static void DoDeviceCommand(string command) - //{ - // Debug.LogMessage(LogEventLevel.Information, "Not yet implemented. Stay tuned"); - //} - - public static void AddDevice(IKeyed newDev) + public static void AddDevice(IEnumerable devicesToAdd) + { + try { - try + if (!DeviceCriticalSection.TryEnter()) { - if (!DeviceCriticalSection.TryEnter()) - { - Debug.LogMessage(LogEventLevel.Information, "Currently unable to add devices to Device Manager. Please try again"); - return; - } - // Check for device with same key - //var existingDevice = _Devices.FirstOrDefault(d => d.Key.Equals(newDev.Key, StringComparison.OrdinalIgnoreCase)); - ////// If it exists, remove or warn?? - //if (existingDevice != null) - - if (!AddDeviceEnabled) - { - Debug.LogMessage(LogEventLevel.Information, "All devices have been activated. Adding new devices is not allowed."); - return; - } - - if (Devices.ContainsKey(newDev.Key)) - { - Debug.LogMessage(LogEventLevel.Information, newDev, "WARNING: A device with this key already exists. Not added to manager"); - return; - } - Devices.Add(newDev.Key, newDev); - //if (!(_Devices.Contains(newDev))) - // _Devices.Add(newDev); - - if (newDev is EssentialsDevice essentialsDev) - essentialsDev.Initialized += DeviceManager_Initialized; + Debug.LogMessage(LogEventLevel.Information, + "Currently unable to add devices to Device Manager. Please try again"); + return; } - finally + if (!AddDeviceEnabled) { - DeviceCriticalSection.Leave(); + Debug.LogMessage(LogEventLevel.Information, + "All devices have been activated. Adding new devices is not allowed."); + return; } - } - public static void AddDevice(IEnumerable devicesToAdd) - { - try + foreach (var dev in devicesToAdd) { - if (!DeviceCriticalSection.TryEnter()) - { - Debug.LogMessage(LogEventLevel.Information, - "Currently unable to add devices to Device Manager. Please try again"); - return; - } - if (!AddDeviceEnabled) + try { - Debug.LogMessage(LogEventLevel.Information, - "All devices have been activated. Adding new devices is not allowed."); - return; + Devices.Add(dev.Key, dev); } - - foreach (var dev in devicesToAdd) + catch (ArgumentException ex) { - try - { - Devices.Add(dev.Key, dev); - } - catch (ArgumentException ex) - { - Debug.LogMessage(LogEventLevel.Information, "Error adding device with key {0} to Device Manager: {1}\r\nStack Trace: {2}", - dev.Key, ex.Message, ex.StackTrace); - } + Debug.LogMessage(LogEventLevel.Information, "Error adding device with key {0} to Device Manager: {1}\r\nStack Trace: {2}", + dev.Key, ex.Message, ex.StackTrace); } } - finally - { - DeviceCriticalSection.Leave(); - } } - - public static void RemoveDevice(IKeyed newDev) + finally { - try - { - DeviceCriticalSection.Enter(); - if (newDev == null) - return; - if (Devices.ContainsKey(newDev.Key)) - Devices.Remove(newDev.Key); - //if (_Devices.Contains(newDev)) - // _Devices.Remove(newDev); - else - Debug.LogMessage(LogEventLevel.Information, "Device manager: Device '{0}' does not exist in manager. Cannot remove", newDev.Key); - } - finally - { - DeviceCriticalSection.Leave(); - } + DeviceCriticalSection.Leave(); } + } - public static IEnumerable GetDeviceKeys() + public static void RemoveDevice(IKeyed newDev) + { + try { - //return _Devices.Select(d => d.Key).ToList(); - return Devices.Keys; + DeviceCriticalSection.Enter(); + if (newDev == null) + return; + if (Devices.ContainsKey(newDev.Key)) + Devices.Remove(newDev.Key); + //if (_Devices.Contains(newDev)) + // _Devices.Remove(newDev); + else + Debug.LogMessage(LogEventLevel.Information, "Device manager: Device '{0}' does not exist in manager. Cannot remove", newDev.Key); } - - public static IEnumerable GetDevices() + finally { - //return _Devices.Select(d => d.Key).ToList(); - return Devices.Values; + DeviceCriticalSection.Leave(); } + } - public static IKeyed GetDeviceForKey(string key) - { - //return _Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); - if (key != null && Devices.ContainsKey(key)) - return Devices[key]; + public static IEnumerable GetDeviceKeys() + { + //return _Devices.Select(d => d.Key).ToList(); + return Devices.Keys; + } - return null; - } + public static IEnumerable GetDevices() + { + //return _Devices.Select(d => d.Key).ToList(); + return Devices.Values; + } - /// - /// Console handler that simulates com port data receive - /// - /// - public static void SimulateComReceiveOnDevice(string s) - { - // devcomsim:1 xyzabc - var match = Regex.Match(s, @"(\S*)\s*(.*)"); - if (match.Groups.Count < 3) - { - CrestronConsole.ConsoleCommandResponse(" Format: devsimreceive:P "); - return; - } - //Debug.LogMessage(LogEventLevel.Verbose, "**** {0} - {1} ****", match.Groups[1].Value, match.Groups[2].Value); + public static IKeyed GetDeviceForKey(string key) + { + //return _Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); + if (key != null && Devices.ContainsKey(key)) + return Devices[key]; - if (!(GetDeviceForKey(match.Groups[1].Value) is ComPortController com)) - { - CrestronConsole.ConsoleCommandResponse("'{0}' is not a comm port device", match.Groups[1].Value); - return; - } - com.SimulateReceive(match.Groups[2].Value); + return null; + } + + /// + /// Console handler that simulates com port data receive + /// + /// + public static void SimulateComReceiveOnDevice(string s) + { + // devcomsim:1 xyzabc + var match = Regex.Match(s, @"(\S*)\s*(.*)"); + if (match.Groups.Count < 3) + { + CrestronConsole.ConsoleCommandResponse(" Format: devsimreceive:P "); + return; } + //Debug.LogMessage(LogEventLevel.Verbose, "**** {0} - {1} ****", match.Groups[1].Value, match.Groups[2].Value); - /// - /// Prints a list of routing inputs and outputs by device key. - /// - /// Device key from which to report data - public static void GetRoutingPorts(string s) + if (!(GetDeviceForKey(match.Groups[1].Value) is ComPortController com)) { - var device = GetDeviceForKey(s); + CrestronConsole.ConsoleCommandResponse("'{0}' is not a comm port device", match.Groups[1].Value); + return; + } + com.SimulateReceive(match.Groups[2].Value); + } - if (device == null) return; - var inputPorts = ((device as IRoutingInputs) != null) ? (device as IRoutingInputs).InputPorts : null; - var outputPorts = ((device as IRoutingOutputs) != null) ? (device as IRoutingOutputs).OutputPorts : null; - if (inputPorts != null) - { - CrestronConsole.ConsoleCommandResponse("Device {0} has {1} Input Ports:{2}", s, inputPorts.Count, CrestronEnvironment.NewLine); - foreach (var routingInputPort in inputPorts) - { - CrestronConsole.ConsoleCommandResponse("{0}{1}", routingInputPort.Key, CrestronEnvironment.NewLine); - } - } - if (outputPorts == null) return; - CrestronConsole.ConsoleCommandResponse("Device {0} has {1} Output Ports:{2}", s, outputPorts.Count, CrestronEnvironment.NewLine); - foreach (var routingOutputPort in outputPorts) + /// + /// Prints a list of routing inputs and outputs by device key. + /// + /// Device key from which to report data + public static void GetRoutingPorts(string s) + { + var device = GetDeviceForKey(s); + + if (device == null) return; + var inputPorts = ((device as IRoutingInputs) != null) ? (device as IRoutingInputs).InputPorts : null; + var outputPorts = ((device as IRoutingOutputs) != null) ? (device as IRoutingOutputs).OutputPorts : null; + if (inputPorts != null) + { + CrestronConsole.ConsoleCommandResponse("Device {0} has {1} Input Ports:{2}", s, inputPorts.Count, CrestronEnvironment.NewLine); + foreach (var routingInputPort in inputPorts) { - CrestronConsole.ConsoleCommandResponse("{0}{1}", routingOutputPort.Key, CrestronEnvironment.NewLine); + CrestronConsole.ConsoleCommandResponse("{0}{1}", routingInputPort.Key, CrestronEnvironment.NewLine); } } + if (outputPorts == null) return; + CrestronConsole.ConsoleCommandResponse("Device {0} has {1} Output Ports:{2}", s, outputPorts.Count, CrestronEnvironment.NewLine); + foreach (var routingOutputPort in outputPorts) + { + CrestronConsole.ConsoleCommandResponse("{0}{1}", routingOutputPort.Key, CrestronEnvironment.NewLine); + } + } - /// - /// Attempts to set the debug level of a device - /// - /// - public static void SetDeviceStreamDebugging(string s) + /// + /// Attempts to set the debug level of a device + /// + /// + public static void SetDeviceStreamDebugging(string s) + { + if (String.IsNullOrEmpty(s) || s.Contains("?")) { - if (String.IsNullOrEmpty(s) || s.Contains("?")) - { - CrestronConsole.ConsoleCommandResponse( - @"SETDEVICESTREAMDEBUG [{deviceKey}] [OFF |TX | RX | BOTH] [timeOutInMinutes] - {deviceKey} [OFF | TX | RX | BOTH] - Device to set stream debugging on, and which setting to use - timeOutInMinutes - Set timeout for stream debugging. Default is 30 minutes"); - return; - } + CrestronConsole.ConsoleCommandResponse( + "SETDEVICESTREAMDEBUG [{deviceKey}] [OFF |TX | RX | BOTH] [timeOutInMinutes]\r\n" + + " {deviceKey} [OFF | TX | RX | BOTH] - Device to set stream debugging on, and which setting to use\r\n" + + " timeOutInMinutes - Set timeout for stream debugging. Default is 30 minutes"); + return; + } - var args = s.Split(' '); + var args = s.Split(' '); - var deviceKey = args[0]; - var setting = args[1]; + var deviceKey = args[0]; + var setting = args[1]; - var timeout = String.Empty; + var timeout = String.Empty; - if (args.Length >= 3) - { - timeout = args[2]; - } + if (args.Length >= 3) + { + timeout = args[2]; + } - if (!(GetDeviceForKey(deviceKey) is IStreamDebugging device)) - { - CrestronConsole.ConsoleCommandResponse("Unable to get device with key: {0}", deviceKey); - return; - } + if (!(GetDeviceForKey(deviceKey) is IStreamDebugging device)) + { + CrestronConsole.ConsoleCommandResponse("Unable to get device with key: {0}", deviceKey); + return; + } - eStreamDebuggingSetting debugSetting; + eStreamDebuggingSetting debugSetting; - try - { - debugSetting = (eStreamDebuggingSetting)Enum.Parse(typeof(eStreamDebuggingSetting), setting, true); - } - catch - { - CrestronConsole.ConsoleCommandResponse("Unable to convert setting value. Please use off/rx/tx/both"); - return; - } + try + { + debugSetting = (eStreamDebuggingSetting)Enum.Parse(typeof(eStreamDebuggingSetting), setting, true); + } + catch + { + CrestronConsole.ConsoleCommandResponse("Unable to convert setting value. Please use off/rx/tx/both"); + return; + } - if (!string.IsNullOrEmpty(timeout)) + if (!string.IsNullOrEmpty(timeout)) + { + try { - try - { - var min = Convert.ToUInt32(timeout); + var min = Convert.ToUInt32(timeout); - device.StreamDebugging.SetDebuggingWithSpecificTimeout(debugSetting, min); - CrestronConsole.ConsoleCommandResponse("Device: '{0}' debug level set to {1} for {2} minutes", deviceKey, debugSetting, min); + device.StreamDebugging.SetDebuggingWithSpecificTimeout(debugSetting, min); + CrestronConsole.ConsoleCommandResponse("Device: '{0}' debug level set to {1} for {2} minutes", deviceKey, debugSetting, min); - } - catch (Exception e) - { - CrestronConsole.ConsoleCommandResponse("Unable to convert minutes or settings value. Please use an integer value for minutes. Error: {0}", e); - } } - else + catch (Exception e) { - device.StreamDebugging.SetDebuggingWithDefaultTimeout(debugSetting); - CrestronConsole.ConsoleCommandResponse("Device: '{0}' debug level set to {1} for default time (30 minutes)", deviceKey, debugSetting); + CrestronConsole.ConsoleCommandResponse("Unable to convert minutes or settings value. Please use an integer value for minutes. Error: {0}", e); } } + else + { + device.StreamDebugging.SetDebuggingWithDefaultTimeout(debugSetting); + CrestronConsole.ConsoleCommandResponse("Device: '{0}' debug level set to {1} for default time (30 minutes)", deviceKey, debugSetting); + } + } - /// - /// Sets stream debugging settings to off for all devices - /// - public static void DisableAllDeviceStreamDebugging() + /// + /// Sets stream debugging settings to off for all devices + /// + public static void DisableAllDeviceStreamDebugging() + { + foreach (var device in AllDevices) { - foreach (var device in AllDevices) + if (device is IStreamDebugging streamDevice) { - if (device is IStreamDebugging streamDevice) - { - streamDevice.StreamDebugging.SetDebuggingWithDefaultTimeout(eStreamDebuggingSetting.Off); - } + streamDevice.StreamDebugging.SetDebuggingWithDefaultTimeout(eStreamDebuggingSetting.Off); } } } diff --git a/src/PepperDash.Essentials.Core/Devices/DisplayUiConstants.cs b/src/PepperDash.Essentials.Core/Devices/DisplayUiConstants.cs index a42239fc4..90a2f516c 100644 --- a/src/PepperDash.Essentials.Core/Devices/DisplayUiConstants.cs +++ b/src/PepperDash.Essentials.Core/Devices/DisplayUiConstants.cs @@ -4,8 +4,8 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// Integers that represent the "source type number" for given sources. /// Primarily used by the UI to calculate subpage join offsets @@ -24,5 +24,4 @@ public class DisplayUiConstants public const uint TypePc = 32; public const uint TypeNoControls = 49; - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/EssentialsBridgeableDevice.cs b/src/PepperDash.Essentials.Core/Devices/EssentialsBridgeableDevice.cs index 0812ca4e4..23b06e9ac 100644 --- a/src/PepperDash.Essentials.Core/Devices/EssentialsBridgeableDevice.cs +++ b/src/PepperDash.Essentials.Core/Devices/EssentialsBridgeableDevice.cs @@ -1,18 +1,17 @@ using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Essentials.Core.Bridges; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public abstract class EssentialsBridgeableDevice:EssentialsDevice, IBridgeAdvanced { - public abstract class EssentialsBridgeableDevice:EssentialsDevice, IBridgeAdvanced + protected EssentialsBridgeableDevice(string key) : base(key) { - protected EssentialsBridgeableDevice(string key) : base(key) - { - } - - protected EssentialsBridgeableDevice(string key, string name) : base(key, name) - { - } + } - public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge); + protected EssentialsBridgeableDevice(string key, string name) : base(key, name) + { } + + public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs b/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs index 778f92260..34484a087 100644 --- a/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs +++ b/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs @@ -9,209 +9,178 @@ using PepperDash.Essentials.Core.Config; using Serilog.Events; -namespace PepperDash.Essentials.Core -{ - /// - /// Defines the basic needs for an EssentialsDevice to enable it to be build by an IDeviceFactory class - /// - [Description("The base Essentials Device Class")] - public abstract class EssentialsDevice : Device - { - public event EventHandler Initialized; - - private bool _isInitialized; - public bool IsInitialized - { - get { return _isInitialized; } - private set - { - if (_isInitialized == value) return; - - _isInitialized = value; - - if (_isInitialized) - { - Initialized?.Invoke(this, new EventArgs()); - } - } - } +namespace PepperDash.Essentials.Core; - protected EssentialsDevice(string key) - : base(key) - { - SubscribeToActivateComplete(); - } +/// +/// Defines the basic needs for an EssentialsDevice to enable it to be build by an IDeviceFactory class +/// +[Description("The base Essentials Device Class")] +public abstract class EssentialsDevice : Device +{ + public event EventHandler Initialized; - protected EssentialsDevice(string key, string name) - : base(key, name) + private bool _isInitialized; + public bool IsInitialized + { + get { return _isInitialized; } + private set { - SubscribeToActivateComplete(); - } + if (_isInitialized == value) return; - private void SubscribeToActivateComplete() - { - DeviceManager.AllDevicesActivated += DeviceManagerOnAllDevicesActivated; - } + _isInitialized = value; - private void DeviceManagerOnAllDevicesActivated(object sender, EventArgs eventArgs) - { - CrestronInvoke.BeginInvoke((o) => + if (_isInitialized) { - try - { - Initialize(); - - IsInitialized = true; - } - catch (Exception ex) - { - Debug.LogMessage(LogEventLevel.Error, this, "Exception initializing device: {0}", ex.Message); - Debug.LogMessage(LogEventLevel.Debug, this, "Stack Trace: {0}", ex.StackTrace); - } - }); - } - - public override bool CustomActivate() - { - CreateMobileControlMessengers(); - - return base.CustomActivate(); + Initialized?.Invoke(this, new EventArgs()); + } } + } - /// - /// Override this method to build and create custom Mobile Control Messengers during the Activation phase - /// - protected virtual void CreateMobileControlMessengers() - { + protected EssentialsDevice(string key) + : base(key) + { + SubscribeToActivateComplete(); + } - } + protected EssentialsDevice(string key, string name) + : base(key, name) + { + SubscribeToActivateComplete(); } - [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)] - public class DescriptionAttribute : Attribute + private void SubscribeToActivateComplete() { - private string _Description; + DeviceManager.AllDevicesActivated += DeviceManagerOnAllDevicesActivated; + } - public DescriptionAttribute(string description) + private void DeviceManagerOnAllDevicesActivated(object sender, EventArgs eventArgs) + { + CrestronInvoke.BeginInvoke((o) => { - //Debug.LogMessage(LogEventLevel.Verbose, "Setting Description: {0}", description); - _Description = description; - } + try + { + Initialize(); - public string Description - { - get { return _Description; } - } + IsInitialized = true; + } + catch (Exception ex) + { + Debug.LogMessage(LogEventLevel.Error, this, "Exception initializing device: {0}", ex.Message); + Debug.LogMessage(LogEventLevel.Debug, this, "Stack Trace: {0}", ex.StackTrace); + } + }); } - [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)] - public class ConfigSnippetAttribute : Attribute + public override bool CustomActivate() { - private string _ConfigSnippet; + CreateMobileControlMessengers(); - public ConfigSnippetAttribute(string configSnippet) - { - //Debug.LogMessage(LogEventLevel.Verbose, "Setting Config Snippet {0}", configSnippet); - _ConfigSnippet = configSnippet; - } - - public string ConfigSnippet - { - get { return _ConfigSnippet; } - } + return base.CustomActivate(); } /// - /// Devices the basic needs for a Device Factory + /// Override this method to build and create custom Mobile Control Messengers during the Activation phase /// - public abstract class EssentialsDeviceFactory : IDeviceFactory where T:EssentialsDevice + protected virtual void CreateMobileControlMessengers() { - #region IDeviceFactory Members - /// - /// A list of strings that can be used in the type property of a DeviceConfig object to build an instance of this device - /// - public List TypeNames { get; protected set; } - - /// - /// Loads an item to the DeviceFactory.FactoryMethods dictionary for each entry in the TypeNames list - /// - public void LoadTypeFactories() - { - foreach (var typeName in TypeNames) - { - //Debug.LogMessage(LogEventLevel.Verbose, "Getting Description Attribute from class: '{0}'", typeof(T).FullName); - var descriptionAttribute = typeof(T).GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[]; - string description = descriptionAttribute[0].Description; - var snippetAttribute = typeof(T).GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[]; - DeviceFactory.AddFactoryForType(typeName.ToLower(), description, typeof(T), BuildDevice); - } - } + } +} - /// - /// The method that will build the device - /// - /// The device config - /// An instance of the device - public abstract EssentialsDevice BuildDevice(DeviceConfig dc); +[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)] +public class DescriptionAttribute : Attribute +{ + private string _Description; - #endregion + public DescriptionAttribute(string description) + { + //Debug.LogMessage(LogEventLevel.Verbose, "Setting Description: {0}", description); + _Description = description; } - public abstract class ProcessorExtensionDeviceFactory : IProcessorExtensionDeviceFactory where T: EssentialsDevice + public string Description { - #region IProcessorExtensionDeviceFactory Members + get { return _Description; } + } +} - /// - /// A list of strings that can be used in the type property of a DeviceConfig object to build an instance of this device - /// - public List TypeNames { get; protected set; } +[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)] +public class ConfigSnippetAttribute : Attribute +{ + private string _ConfigSnippet; - /// - /// Loads an item to the ProcessorExtensionDeviceFactory.ProcessorExtensionFactoryMethods dictionary for each entry in the TypeNames list - /// - public void LoadFactories() - { - foreach (var typeName in TypeNames) - { - //Debug.LogMessage(LogEventLevel.Verbose, "Getting Description Attribute from class: '{0}'", typeof(T).FullName); - var descriptionAttribute = typeof(T).GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[]; - string description = descriptionAttribute[0].Description; - var snippetAttribute = typeof(T).GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[]; - ProcessorExtensionDeviceFactory.AddFactoryForType(typeName.ToLower(), description, typeof(T), BuildDevice); - } - } + public ConfigSnippetAttribute(string configSnippet) + { + //Debug.LogMessage(LogEventLevel.Verbose, "Setting Config Snippet {0}", configSnippet); + _ConfigSnippet = configSnippet; + } - /// - /// The method that will build the device - /// - /// The device config - /// An instance of the device - public abstract EssentialsDevice BuildDevice(DeviceConfig dc); + public string ConfigSnippet + { + get { return _ConfigSnippet; } + } +} - #endregion +public abstract class ProcessorExtensionDeviceFactory : IProcessorExtensionDeviceFactory where T: EssentialsDevice +{ + #region IProcessorExtensionDeviceFactory Members - } + /// + /// A list of strings that can be used in the type property of a DeviceConfig object to build an instance of this device + /// + public List TypeNames { get; protected set; } /// - /// Devices the basic needs for a Device Factory + /// Loads an item to the ProcessorExtensionDeviceFactory.ProcessorExtensionFactoryMethods dictionary for each entry in the TypeNames list /// - public abstract class EssentialsPluginDeviceFactory : EssentialsDeviceFactory, IPluginDeviceFactory where T : EssentialsDevice + public void LoadFactories() { - /// - /// Specifies the minimum version of Essentials required for a plugin to run. Must use the format Major.Minor.Build (ex. "1.4.33") - /// - public string MinimumEssentialsFrameworkVersion { get; protected set; } + foreach (var typeName in TypeNames) + { + //Debug.LogMessage(LogEventLevel.Verbose, "Getting Description Attribute from class: '{0}'", typeof(T).FullName); + var descriptionAttribute = typeof(T).GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[]; + string description = descriptionAttribute[0].Description; + var snippetAttribute = typeof(T).GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[]; + ProcessorExtensionDeviceFactory.AddFactoryForType(typeName.ToLower(), description, typeof(T), BuildDevice); + } } - public abstract class EssentialsPluginDevelopmentDeviceFactory : EssentialsDeviceFactory, IPluginDevelopmentDeviceFactory where T : EssentialsDevice - { - /// - /// Specifies the minimum version of Essentials required for a plugin to run. Must use the format Major.Minor.Build (ex. "1.4.33") - /// - public string MinimumEssentialsFrameworkVersion { get; protected set; } + /// + /// The method that will build the device + /// + /// The device config + /// An instance of the device + public abstract EssentialsDevice BuildDevice(DeviceConfig dc); - public List DevelopmentEssentialsFrameworkVersions { get; protected set; } - } + #endregion +} + +/// +/// Devices the basic needs for a Device Factory +/// +public abstract class EssentialsPluginDeviceFactory : EssentialsDeviceFactory, IPluginDeviceFactory where T : EssentialsDevice +{ + /// + /// Specifies the minimum version of Essentials required for a plugin to run. Must use the format Major.Minor.Build (ex. "1.4.33") + /// + public string MinimumEssentialsFrameworkVersion { get; protected set; } +} + +/// +/// Provides a base class for creating device factories specifically designed for plugin development in the Essentials +/// framework. +/// +/// This class is intended to be used by developers creating plugins for the Essentials framework. It +/// includes properties to specify the minimum required Essentials framework version and to track framework versions +/// used during development. +/// The type of device that this factory creates. Must derive from . +public abstract class EssentialsPluginDevelopmentDeviceFactory : EssentialsDeviceFactory, IPluginDevelopmentDeviceFactory where T : EssentialsDevice +{ + /// + /// Specifies the minimum version of Essentials required for a plugin to run. Must use the format Major.Minor.Build (ex. "1.4.33") + /// + public string MinimumEssentialsFrameworkVersion { get; protected set; } + + public List DevelopmentEssentialsFrameworkVersions { get; protected set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/EssentialsDeviceFactory.cs b/src/PepperDash.Essentials.Core/Devices/EssentialsDeviceFactory.cs new file mode 100644 index 000000000..35651377f --- /dev/null +++ b/src/PepperDash.Essentials.Core/Devices/EssentialsDeviceFactory.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using PepperDash.Essentials.Core.Config; + +namespace PepperDash.Essentials.Core; + +/// +/// Devices the basic needs for a Device Factory +/// +public abstract class EssentialsDeviceFactory : IDeviceFactory where T:EssentialsDevice +{ + #region IDeviceFactory Members + + /// + public Type FactoryType => typeof(T); + + /// + /// A list of strings that can be used in the type property of a DeviceConfig object to build an instance of this device + /// + public List TypeNames { get; protected set; } + + /// + /// The method that will build the device + /// + /// The device config + /// An instance of the device + public abstract EssentialsDevice BuildDevice(DeviceConfig dc); + + #endregion +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/FIND HOMES Interfaces.cs b/src/PepperDash.Essentials.Core/Devices/FIND HOMES Interfaces.cs index d4b097796..901304cb1 100644 --- a/src/PepperDash.Essentials.Core/Devices/FIND HOMES Interfaces.cs +++ b/src/PepperDash.Essentials.Core/Devices/FIND HOMES Interfaces.cs @@ -1,8 +1,8 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public interface IOnline { BoolFeedback IsOnline { get; } @@ -28,5 +28,4 @@ public interface IMakeModel : IKeyed { string DeviceMake { get; } string DeviceModel { get; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/GenericIRController.cs b/src/PepperDash.Essentials.Core/Devices/GenericIRController.cs index 26718ebf9..e4265fc2a 100644 --- a/src/PepperDash.Essentials.Core/Devices/GenericIRController.cs +++ b/src/PepperDash.Essentials.Core/Devices/GenericIRController.cs @@ -11,68 +11,68 @@ using PepperDash.Essentials.Core.Bridges.JoinMaps; using Serilog.Events; -namespace PepperDash.Essentials.Core.Devices +namespace PepperDash.Essentials.Core.Devices; + +public class GenericIrController: EssentialsBridgeableDevice { - public class GenericIrController: EssentialsBridgeableDevice - { - //data storage for bridging - private BasicTriList _trilist; - private uint _joinStart; - private string _joinMapKey; - private EiscApiAdvanced _bridge; + //data storage for bridging + private BasicTriList _trilist; + private uint _joinStart; + private string _joinMapKey; + private EiscApiAdvanced _bridge; - private readonly IrOutputPortController _port; + private readonly IrOutputPortController _port; - public string[] IrCommands {get { return _port.IrFileCommands; }} + public string[] IrCommands {get { return _port.IrFileCommands; }} - public GenericIrController(string key, string name, IrOutputPortController irPort) : base(key, name) + public GenericIrController(string key, string name, IrOutputPortController irPort) : base(key, name) + { + _port = irPort; + if (_port == null) { - _port = irPort; - if (_port == null) - { - Debug.LogMessage(LogEventLevel.Information, this, "IR Port is null, device will not function"); - return; - } - DeviceManager.AddDevice(_port); - - _port.DriverLoaded.OutputChange += DriverLoadedOnOutputChange; + Debug.LogMessage(LogEventLevel.Information, this, "IR Port is null, device will not function"); + return; } + DeviceManager.AddDevice(_port); - private void DriverLoadedOnOutputChange(object sender, FeedbackEventArgs args) - { - if (!args.BoolValue) - { - return; - } + _port.DriverLoaded.OutputChange += DriverLoadedOnOutputChange; + } - if (_trilist == null || _bridge == null) - { - return; - } + private void DriverLoadedOnOutputChange(object sender, FeedbackEventArgs args) + { + if (!args.BoolValue) + { + return; + } - LinkToApi(_trilist, _joinStart, _joinMapKey, _bridge); + if (_trilist == null || _bridge == null) + { + return; } - #region Overrides of EssentialsBridgeableDevice + LinkToApi(_trilist, _joinStart, _joinMapKey, _bridge); + } + + #region Overrides of EssentialsBridgeableDevice - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + //if driver isn't loaded yet, store the variables until it is loaded, then call the LinkToApi method again + if (!_port.DriverIsLoaded) { - //if driver isn't loaded yet, store the variables until it is loaded, then call the LinkToApi method again - if (!_port.DriverIsLoaded) - { - _trilist = trilist; - _joinStart = joinStart; - _joinMapKey = joinMapKey; - _bridge = bridge; - return; - } + _trilist = trilist; + _joinStart = joinStart; + _joinMapKey = joinMapKey; + _bridge = bridge; + return; + } - var joinMap = new GenericIrControllerJoinMap(joinStart); + var joinMap = new GenericIrControllerJoinMap(joinStart); - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - if (!string.IsNullOrEmpty(joinMapSerialized)) - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); if (_port.UseBridgeJoinMap) { @@ -134,43 +134,42 @@ public override void LinkToApi(BasicTriList trilist, uint joinStart, string join } } - joinMap.PrintJoinMapInfo(); + joinMap.PrintJoinMapInfo(); - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); } - - #endregion - - public void Press(string command, bool pressRelease) + else { - _port.PressRelease(command, pressRelease); + Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); } } - public class GenericIrControllerFactory : EssentialsDeviceFactory + #endregion + + public void Press(string command, bool pressRelease) { - public GenericIrControllerFactory() - { - TypeNames = new List {"genericIrController"}; - } - #region Overrides of EssentialsDeviceFactory + _port.PressRelease(command, pressRelease); + } +} - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic IR Controller Device"); +public class GenericIrControllerFactory : EssentialsDeviceFactory +{ + public GenericIrControllerFactory() + { + TypeNames = new List {"genericIrController"}; + } + #region Overrides of EssentialsDeviceFactory - var irPort = IRPortHelper.GetIrOutputPortController(dc); + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic IR Controller Device"); - return new GenericIrController(dc.Key, dc.Name, irPort); - } + var irPort = IRPortHelper.GetIrOutputPortController(dc); - #endregion + return new GenericIrController(dc.Key, dc.Name, irPort); } + + #endregion } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/GenericMonitoredTcpDevice.cs b/src/PepperDash.Essentials.Core/Devices/GenericMonitoredTcpDevice.cs index 8929edebf..08cfb47cb 100644 --- a/src/PepperDash.Essentials.Core/Devices/GenericMonitoredTcpDevice.cs +++ b/src/PepperDash.Essentials.Core/Devices/GenericMonitoredTcpDevice.cs @@ -8,8 +8,8 @@ using Serilog.Events; -namespace PepperDash.Essentials.Core.Devices -{ +namespace PepperDash.Essentials.Core.Devices; + public class GenericCommunicationMonitoredDevice : Device, ICommunicationMonitor { IBasicCommunication Client; @@ -47,5 +47,4 @@ public override bool Deactivate() CommunicationMonitor.Stop(); return true; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/IAttachVideoStatusExtensions.cs b/src/PepperDash.Essentials.Core/Devices/IAttachVideoStatusExtensions.cs index e5218ee01..15f2068c7 100644 --- a/src/PepperDash.Essentials.Core/Devices/IAttachVideoStatusExtensions.cs +++ b/src/PepperDash.Essentials.Core/Devices/IAttachVideoStatusExtensions.cs @@ -4,8 +4,8 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public static class IAttachVideoStatusExtensions { /// @@ -35,5 +35,4 @@ public static bool HasVideoStatuses(this IAttachVideoStatus attachedDev) t.SourcePort.ParentDevice == attachedDev && t.DestinationPort is RoutingInputPortWithVideoStatuses) != null; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/IDspPresets.cs b/src/PepperDash.Essentials.Core/Devices/IDspPresets.cs index 94bc39297..d6aad26ba 100644 --- a/src/PepperDash.Essentials.Core/Devices/IDspPresets.cs +++ b/src/PepperDash.Essentials.Core/Devices/IDspPresets.cs @@ -1,12 +1,11 @@ using PepperDash.Core; using System.Collections.Generic; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public interface IDspPresets { - public interface IDspPresets - { - Dictionary Presets { get; } + Dictionary Presets { get; } - void RecallPreset(string key); - } + void RecallPreset(string key); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/IHasFeedbacks.cs b/src/PepperDash.Essentials.Core/Devices/IHasFeedbacks.cs index 9943c7383..e4bcd84a6 100644 --- a/src/PepperDash.Essentials.Core/Devices/IHasFeedbacks.cs +++ b/src/PepperDash.Essentials.Core/Devices/IHasFeedbacks.cs @@ -4,8 +4,8 @@ using PepperDash.Core; using Serilog.Events; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public interface IHasFeedback : IKeyed { /// @@ -21,9 +21,9 @@ public static class IHasFeedbackExtensions { public static void DumpFeedbacksToConsole(this IHasFeedback source, bool getCurrentStates) { - Type t = source.GetType(); - // get the properties and set them into a new collection of NameType wrappers - var props = t.GetProperties().Select(p => new PropertyNameType(p, t)); + Type t = source.GetType(); + // get the properties and set them into a new collection of NameType wrappers + var props = t.GetProperties().Select(p => new PropertyNameType(p, t)); var feedbacks = source.Feedbacks; if (feedbacks != null) @@ -32,24 +32,24 @@ public static void DumpFeedbacksToConsole(this IHasFeedback source, bool getCurr foreach (var f in feedbacks) { string val = ""; - string type = ""; + string type = ""; if (getCurrentStates) { - if (f is BoolFeedback) - { - val = f.BoolValue.ToString(); - type = "boolean"; - } - else if (f is IntFeedback) - { - val = f.IntValue.ToString(); - type = "integer"; - } - else if (f is StringFeedback) - { - val = f.StringValue; - type = "string"; - } + if (f is BoolFeedback) + { + val = f.BoolValue.ToString(); + type = "boolean"; + } + else if (f is IntFeedback) + { + val = f.IntValue.ToString(); + type = "integer"; + } + else if (f is StringFeedback) + { + val = f.StringValue; + type = "string"; + } } Debug.LogMessage(LogEventLevel.Information, "{0,-12} {1, -25} {2}", type, (string.IsNullOrEmpty(f.Key) ? "-no key-" : f.Key), val); @@ -58,5 +58,4 @@ public static void DumpFeedbacksToConsole(this IHasFeedback source, bool getCurr else Debug.LogMessage(LogEventLevel.Information, source, "No available outputs:"); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/IProjectorInterfaces.cs b/src/PepperDash.Essentials.Core/Devices/IProjectorInterfaces.cs index c0cb33ede..97af2a39c 100644 --- a/src/PepperDash.Essentials.Core/Devices/IProjectorInterfaces.cs +++ b/src/PepperDash.Essentials.Core/Devices/IProjectorInterfaces.cs @@ -4,19 +4,18 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public interface IBasicVideoMute +{ + void VideoMuteToggle(); +} + +public interface IBasicVideoMuteWithFeedback : IBasicVideoMute { - public interface IBasicVideoMute - { - void VideoMuteToggle(); - } + BoolFeedback VideoMuteIsOn { get; } - public interface IBasicVideoMuteWithFeedback : IBasicVideoMute - { - BoolFeedback VideoMuteIsOn { get; } + void VideoMuteOn(); + void VideoMuteOff(); - void VideoMuteOn(); - void VideoMuteOff(); - - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/IReconfigurableDevice.cs b/src/PepperDash.Essentials.Core/Devices/IReconfigurableDevice.cs index ab0e37c36..433d96286 100644 --- a/src/PepperDash.Essentials.Core/Devices/IReconfigurableDevice.cs +++ b/src/PepperDash.Essentials.Core/Devices/IReconfigurableDevice.cs @@ -6,14 +6,13 @@ using PepperDash.Essentials.Core.Config; -namespace PepperDash.Essentials.Core.Devices +namespace PepperDash.Essentials.Core.Devices; + +public interface IReconfigurableDevice { - public interface IReconfigurableDevice - { - event EventHandler ConfigChanged; + event EventHandler ConfigChanged; - DeviceConfig Config { get; } + DeviceConfig Config { get; } - void SetConfig(DeviceConfig config); - } + void SetConfig(DeviceConfig config); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/IUsageTracking.cs b/src/PepperDash.Essentials.Core/Devices/IUsageTracking.cs index 968fa127f..4a45f0cc6 100644 --- a/src/PepperDash.Essentials.Core/Devices/IUsageTracking.cs +++ b/src/PepperDash.Essentials.Core/Devices/IUsageTracking.cs @@ -6,100 +6,99 @@ using PepperDash.Core; using Serilog.Events; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public interface IUsageTracking { - public interface IUsageTracking - { - UsageTracking UsageTracker { get; set; } - } + UsageTracking UsageTracker { get; set; } +} + +//public static class IUsageTrackingExtensions +//{ +// public static void EnableUsageTracker(this IUsageTracking device) +// { +// device.UsageTracker = new UsageTracking(); +// } +//} + +public class UsageTracking +{ + public event EventHandler DeviceUsageEnded; - //public static class IUsageTrackingExtensions - //{ - // public static void EnableUsageTracker(this IUsageTracking device) - // { - // device.UsageTracker = new UsageTracking(); - // } - //} + public InUseTracking InUseTracker { get; protected set; } - public class UsageTracking - { - public event EventHandler DeviceUsageEnded; + public bool UsageIsTracked { get; set; } - public InUseTracking InUseTracker { get; protected set; } + public bool UsageTrackingStarted { get; protected set; } + public DateTime UsageStartTime { get; protected set; } + public DateTime UsageEndTime { get; protected set; } - public bool UsageIsTracked { get; set; } + public Device Parent { get; private set; } - public bool UsageTrackingStarted { get; protected set; } - public DateTime UsageStartTime { get; protected set; } - public DateTime UsageEndTime { get; protected set; } + public UsageTracking(Device parent) + { + Parent = parent; - public Device Parent { get; private set; } + InUseTracker = new InUseTracking(); - public UsageTracking(Device parent) - { - Parent = parent; - - InUseTracker = new InUseTracking(); + InUseTracker.InUseFeedback.OutputChange += InUseFeedback_OutputChange; //new EventHandler(); + } - InUseTracker.InUseFeedback.OutputChange += InUseFeedback_OutputChange; //new EventHandler(); + void InUseFeedback_OutputChange(object sender, EventArgs e) + { + if(InUseTracker.InUseFeedback.BoolValue) + { + StartDeviceUsage(); } - - void InUseFeedback_OutputChange(object sender, EventArgs e) + else { - if(InUseTracker.InUseFeedback.BoolValue) - { - StartDeviceUsage(); - } - else - { - EndDeviceUsage(); - } + EndDeviceUsage(); } + } - /// - /// Stores the usage start time - /// - public void StartDeviceUsage() - { - UsageTrackingStarted = true; - UsageStartTime = DateTime.Now; - } + /// + /// Stores the usage start time + /// + public void StartDeviceUsage() + { + UsageTrackingStarted = true; + UsageStartTime = DateTime.Now; + } - /// - /// Calculates the difference between the usage start and end times, gets the total minutes used and fires an event to pass that info to a consumer - /// - public void EndDeviceUsage() + /// + /// Calculates the difference between the usage start and end times, gets the total minutes used and fires an event to pass that info to a consumer + /// + public void EndDeviceUsage() + { + try { - try - { - UsageTrackingStarted = false; + UsageTrackingStarted = false; - UsageEndTime = DateTime.Now; + UsageEndTime = DateTime.Now; - if (UsageStartTime != null) - { - var timeUsed = UsageEndTime - UsageStartTime; + if (UsageStartTime != null) + { + var timeUsed = UsageEndTime - UsageStartTime; - var handler = DeviceUsageEnded; + var handler = DeviceUsageEnded; - if (handler != null) - { - Debug.LogMessage(LogEventLevel.Debug, "Device Usage Ended for: {0} at {1}. In use for {2} minutes.", Parent.Name, UsageEndTime, timeUsed.Minutes); - handler(this, new DeviceUsageEventArgs() { UsageEndTime = UsageEndTime, MinutesUsed = timeUsed.Minutes }); - } + if (handler != null) + { + Debug.LogMessage(LogEventLevel.Debug, "Device Usage Ended for: {0} at {1}. In use for {2} minutes.", Parent.Name, UsageEndTime, timeUsed.Minutes); + handler(this, new DeviceUsageEventArgs() { UsageEndTime = UsageEndTime, MinutesUsed = timeUsed.Minutes }); } } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Debug, "Error ending device usage: {0}", e); - } + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Debug, "Error ending device usage: {0}", e); } } +} - public class DeviceUsageEventArgs : EventArgs - { - public DateTime UsageEndTime { get; set; } - public int MinutesUsed { get; set; } - } +public class DeviceUsageEventArgs : EventArgs +{ + public DateTime UsageEndTime { get; set; } + public int MinutesUsed { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/IVolumeAndAudioInterfaces.cs b/src/PepperDash.Essentials.Core/Devices/IVolumeAndAudioInterfaces.cs index 5d8e07241..b0cd33c39 100644 --- a/src/PepperDash.Essentials.Core/Devices/IVolumeAndAudioInterfaces.cs +++ b/src/PepperDash.Essentials.Core/Devices/IVolumeAndAudioInterfaces.cs @@ -4,62 +4,62 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// Defines minimal volume and mute control methods /// - public interface IBasicVolumeControls +public interface IBasicVolumeControls { void VolumeUp(bool pressRelease); void VolumeDown(bool pressRelease); void MuteToggle(); } - /// - /// Defines basic volume control methods - /// - public interface IHasVolumeControl - { - void VolumeUp(bool pressRelease); - void VolumeDown(bool pressRelease); - } - - /// - /// Defines volume control methods and properties with feedback - /// - public interface IHasVolumeControlWithFeedback : IHasVolumeControl - { - void SetVolume(ushort level); - IntFeedback VolumeLevelFeedback { get; } - } - - /// - /// Defines basic mute control methods - /// - public interface IHasMuteControl - { - void MuteToggle(); - } - - /// - /// Defines mute control methods and properties with feedback - /// - public interface IHasMuteControlWithFeedback : IHasMuteControl - { - BoolFeedback MuteFeedback { get; } - void MuteOn(); - void MuteOff(); - } +/// +/// Defines basic volume control methods +/// +public interface IHasVolumeControl +{ + void VolumeUp(bool pressRelease); + void VolumeDown(bool pressRelease); +} + +/// +/// Defines volume control methods and properties with feedback +/// +public interface IHasVolumeControlWithFeedback : IHasVolumeControl +{ + void SetVolume(ushort level); + IntFeedback VolumeLevelFeedback { get; } +} + +/// +/// Defines basic mute control methods +/// +public interface IHasMuteControl +{ + void MuteToggle(); +} + +/// +/// Defines mute control methods and properties with feedback +/// +public interface IHasMuteControlWithFeedback : IHasMuteControl +{ + BoolFeedback MuteFeedback { get; } + void MuteOn(); + void MuteOff(); +} /// /// Adds feedback and direct volume level set to IBasicVolumeControls /// - public interface IBasicVolumeWithFeedback : IBasicVolumeControls +public interface IBasicVolumeWithFeedback : IBasicVolumeControls { BoolFeedback MuteFeedback { get; } - void MuteOn(); - void MuteOff(); + void MuteOn(); + void MuteOff(); void SetVolume(ushort level); IntFeedback VolumeLevelFeedback { get; } } @@ -74,26 +74,26 @@ public interface IBasicVolumeWithFeedbackAdvanced : IBasicVolumeWithFeedback eVolumeLevelUnits Units { get; } } - public enum eVolumeLevelUnits - { - Decibels, - Percent, - Relative, - Absolute - } - - /// - /// A class that implements this contains a reference to a current IBasicVolumeControls device. - /// The class may have multiple IBasicVolumeControls. - /// - public interface IHasCurrentVolumeControls - { - IBasicVolumeControls CurrentVolumeControls { get; } +public enum eVolumeLevelUnits +{ + Decibels, + Percent, + Relative, + Absolute +} + +/// +/// A class that implements this contains a reference to a current IBasicVolumeControls device. +/// The class may have multiple IBasicVolumeControls. +/// +public interface IHasCurrentVolumeControls +{ + IBasicVolumeControls CurrentVolumeControls { get; } event EventHandler CurrentVolumeDeviceChange; - void SetDefaultLevels(); + void SetDefaultLevels(); - bool ZeroVolumeWhenSwtichingVolumeDevices { get; } + bool ZeroVolumeWhenSwtichingVolumeDevices { get; } } @@ -160,5 +160,4 @@ public interface IAudioZones : IRouting public interface IAudioZone : IBasicVolumeWithFeedback { void SelectInput(ushort input); - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/IrOutputPortController.cs b/src/PepperDash.Essentials.Core/Devices/IrOutputPortController.cs index edcedfbbf..ba639ceb6 100644 --- a/src/PepperDash.Essentials.Core/Devices/IrOutputPortController.cs +++ b/src/PepperDash.Essentials.Core/Devices/IrOutputPortController.cs @@ -15,8 +15,8 @@ using System.IO; using PepperDash.Core.Logging; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// IR port wrapper. May act standalone @@ -26,13 +26,13 @@ public class IrOutputPortController : Device uint IrPortUid; IROutputPort IrPort; - public BoolFeedback DriverLoaded { get; private set; } + public BoolFeedback DriverLoaded { get; private set; } public ushort StandardIrPulseTime { get; set; } public string DriverFilepath { get; private set; } public bool DriverIsLoaded { get; private set; } - public string[] IrFileCommands { get { return IrPort.AvailableStandardIRCmds(IrPortUid); } } + public string[] IrFileCommands { get { return IrPort.AvailableStandardIRCmds(IrPortUid); } } public bool UseBridgeJoinMap { get; private set; } @@ -59,53 +59,53 @@ public IrOutputPortController(string key, Func postA DeviceConfig config) : base(key) { - DriverLoaded = new BoolFeedback(() => DriverIsLoaded); + DriverLoaded = new BoolFeedback(() => DriverIsLoaded); UseBridgeJoinMap = config.Properties["control"].Value("useBridgeJoinMap"); - AddPostActivationAction(() => - { + AddPostActivationAction(() => + { IrPort = postActivationFunc(config); - if (IrPort == null) - { - Debug.LogMessage(LogEventLevel.Information, this, "WARNING No valid IR Port assigned to controller. IR will not function"); - return; - } - - // var filePath = Global.FilePathPrefix + "ir" + Global.DirectorySeparator + config.Properties["control"]["irFile"].Value(); + if (IrPort == null) + { + Debug.LogMessage(LogEventLevel.Information, this, "WARNING No valid IR Port assigned to controller. IR will not function"); + return; + } + + // var filePath = Global.FilePathPrefix + "ir" + Global.DirectorySeparator + config.Properties["control"]["irFile"].Value(); - var fileName = config.Properties["control"]["irFile"].Value(); + var fileName = config.Properties["control"]["irFile"].Value(); - var files = Directory.GetFiles(Global.FilePathPrefix, fileName, SearchOption.AllDirectories); + var files = Directory.GetFiles(Global.FilePathPrefix, fileName, SearchOption.AllDirectories); - if(files.Length == 0) - { - this.LogError("IR file {fileName} not found in {path}", fileName, Global.FilePathPrefix); - return; - } + if(files.Length == 0) + { + this.LogError("IR file {fileName} not found in {path}", fileName, Global.FilePathPrefix); + return; + } - if(files.Length > 1) - { - this.LogError("IR file {fileName} found in multiple locations: {files}", fileName, files); - return; - } + if(files.Length > 1) + { + this.LogError("IR file {fileName} found in multiple locations: {files}", fileName, files); + return; + } - var filePath = files[0]; + var filePath = files[0]; - Debug.LogMessage(LogEventLevel.Debug, "*************Attempting to load IR file: {0}***************", filePath); + Debug.LogMessage(LogEventLevel.Debug, "*************Attempting to load IR file: {0}***************", filePath); - LoadDriver(filePath); - + LoadDriver(filePath); + PrintAvailableCommands(); - }); + }); } public void PrintAvailableCommands() { - Debug.LogMessage(LogEventLevel.Verbose, this, "Available IR Commands in IR File {0}", IrPortUid); - foreach (var cmd in IrPort.AvailableIRCmds()) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "{0}", cmd); - } + Debug.LogMessage(LogEventLevel.Verbose, this, "Available IR Commands in IR File {0}", IrPortUid); + foreach (var cmd in IrPort.AvailableIRCmds()) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "{0}", cmd); + } } @@ -115,7 +115,7 @@ public void PrintAvailableCommands() /// public void LoadDriver(string path) { - Debug.LogMessage(LogEventLevel.Verbose, this, "***Loading IR File***"); + Debug.LogMessage(LogEventLevel.Verbose, this, "***Loading IR File***"); if (string.IsNullOrEmpty(path)) path = DriverFilepath; try { @@ -124,14 +124,14 @@ public void LoadDriver(string path) StandardIrPulseTime = 200; DriverIsLoaded = true; - DriverLoaded.FireUpdate(); + DriverLoaded.FireUpdate(); } catch { DriverIsLoaded = false; var message = string.Format("WARNING IR Driver '{0}' failed to load", path); Debug.LogMessage(LogEventLevel.Information, this, message); - DriverLoaded.FireUpdate(); + DriverLoaded.FireUpdate(); } } @@ -192,5 +192,4 @@ protected void NoIrCommandError(string command) Debug.LogMessage(LogEventLevel.Verbose, this, "Device {0}: IR Driver {1} does not contain command {2}", Key, IrPort.IRDriverFileNameByIRDriverId(IrPortUid), command); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs index 4c2e83e48..02769e28f 100644 --- a/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs +++ b/src/PepperDash.Essentials.Core/Devices/LevelControlListItem.cs @@ -7,76 +7,75 @@ using PepperDash.Core; using PepperDash.Essentials.Core.Devices; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public class LevelControlListItem : AudioControlListItemBase { - public class LevelControlListItem : AudioControlListItemBase - { - [JsonIgnore] - public IBasicVolumeWithFeedback LevelControl + [JsonIgnore] + public IBasicVolumeWithFeedback LevelControl + { + get { - get - { - if (_levelControl == null) - _levelControl = DeviceManager.GetDeviceForKey(ParentDeviceKey) as IBasicVolumeWithFeedback; - return _levelControl; - } + if (_levelControl == null) + _levelControl = DeviceManager.GetDeviceForKey(ParentDeviceKey) as IBasicVolumeWithFeedback; + return _levelControl; } - IBasicVolumeWithFeedback _levelControl; + } + IBasicVolumeWithFeedback _levelControl; - /// - /// Gets the name from the device if it implements IKeyName or else returns the Name property - /// - [JsonProperty("preferredName")] - public string PreferredName + /// + /// Gets the name from the device if it implements IKeyName or else returns the Name property + /// + [JsonProperty("preferredName")] + public string PreferredName + { + get { - get + if (!string.IsNullOrEmpty(Name)) return Name; + else { - if (!string.IsNullOrEmpty(Name)) return Name; - else + if (LevelControl is IKeyName namedLevelControl) { - if (LevelControl is IKeyName namedLevelControl) - { - if (namedLevelControl == null) - return "---"; - return namedLevelControl.Name; - } - else return "---"; + if (namedLevelControl == null) + return "---"; + return namedLevelControl.Name; } + else return "---"; } } + } - /// - /// The key of the device in the DeviceManager for control - /// - [JsonProperty("deviceKey")] - public string DeviceKey + /// + /// The key of the device in the DeviceManager for control + /// + [JsonProperty("deviceKey")] + public string DeviceKey + { + get { - get + if(string.IsNullOrEmpty(ItemKey)) return ParentDeviceKey; + else { - if(string.IsNullOrEmpty(ItemKey)) return ParentDeviceKey; - else - { - return DeviceManager.AllDevices. - Where(d => d.Key.Contains(ParentDeviceKey) && d.Key.Contains(ItemKey)).FirstOrDefault()?.Key ?? $"{ParentDeviceKey}--{ItemKey}"; - } + return DeviceManager.AllDevices. + Where(d => d.Key.Contains(ParentDeviceKey) && d.Key.Contains(ItemKey)).FirstOrDefault()?.Key ?? $"{ParentDeviceKey}--{ItemKey}"; } } - - /// - /// Indicates if the item is a level, mute , or both - /// - [JsonProperty("type")] - [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] - public eLevelControlType Type { get; set; } } - [Flags] - public enum eLevelControlType - { - Level = 1, - Mute = 2, - LevelAndMute = Level | Mute, - } + /// + /// Indicates if the item is a level, mute , or both + /// + [JsonProperty("type")] + [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + public eLevelControlType Type { get; set; } +} + +[Flags] +public enum eLevelControlType +{ + Level = 1, + Mute = 2, + LevelAndMute = Level | Mute, } diff --git a/src/PepperDash.Essentials.Core/Devices/PduInterfaces.cs b/src/PepperDash.Essentials.Core/Devices/PduInterfaces.cs index 1c0431b5e..5283907d8 100644 --- a/src/PepperDash.Essentials.Core/Devices/PduInterfaces.cs +++ b/src/PepperDash.Essentials.Core/Devices/PduInterfaces.cs @@ -4,33 +4,32 @@ using PepperDash.Core; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core.Devices +namespace PepperDash.Essentials.Core.Devices; + +/// +/// Interface for any device that is able to control it'spower and has a configurable reboot time +/// +public interface IHasPowerCycle : IKeyName, IHasPowerControlWithFeedback { /// - /// Interface for any device that is able to control it'spower and has a configurable reboot time - /// - public interface IHasPowerCycle : IKeyName, IHasPowerControlWithFeedback - { - /// - /// Delay between power off and power on for reboot - /// - int PowerCycleTimeMs { get;} + /// Delay between power off and power on for reboot + /// + int PowerCycleTimeMs { get;} - /// - /// Reboot outlet - /// - void PowerCycle(); - } + /// + /// Reboot outlet + /// + void PowerCycle(); +} +/// +/// Interface for any device that contains a collection of IHasPowerReboot Devices +/// +public interface IHasControlledPowerOutlets : IKeyName +{ /// - /// Interface for any device that contains a collection of IHasPowerReboot Devices - /// - public interface IHasControlledPowerOutlets : IKeyName - { - /// - /// Collection of IPduOutlets - /// - ReadOnlyDictionary PduOutlets { get; } + /// Collection of IPduOutlets + /// + ReadOnlyDictionary PduOutlets { get; } - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/PowerInterfaces.cs b/src/PepperDash.Essentials.Core/Devices/PowerInterfaces.cs index 1fc6672ab..443123dcc 100644 --- a/src/PepperDash.Essentials.Core/Devices/PowerInterfaces.cs +++ b/src/PepperDash.Essentials.Core/Devices/PowerInterfaces.cs @@ -1,87 +1,83 @@ using Crestron.SimplSharp; using PepperDash.Core; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Interface for any device that has a battery that can be monitored +/// +public interface IHasBatteryStats : IKeyName { - /// - /// Interface for any device that has a battery that can be monitored - /// - public interface IHasBatteryStats : IKeyName - { - int BatteryPercentage { get; } - int BatteryCautionThresholdPercentage { get; } - int BatteryWarningThresholdPercentage { get; } - BoolFeedback BatteryIsWarningFeedback { get; } - BoolFeedback BatteryIsCautionFeedback { get; } - BoolFeedback BatteryIsOkFeedback { get; } - IntFeedback BatteryPercentageFeedback { get; } - } + int BatteryPercentage { get; } + int BatteryCautionThresholdPercentage { get; } + int BatteryWarningThresholdPercentage { get; } + BoolFeedback BatteryIsWarningFeedback { get; } + BoolFeedback BatteryIsCautionFeedback { get; } + BoolFeedback BatteryIsOkFeedback { get; } + IntFeedback BatteryPercentageFeedback { get; } +} - /// - /// Interface for any device that has a battery that can be monitored and the ability to charge and discharge - /// - public interface IHasBatteryCharging : IHasBatteryStats - { - BoolFeedback BatteryIsCharging { get; } - } +/// +/// Interface for any device that has a battery that can be monitored and the ability to charge and discharge +/// +public interface IHasBatteryCharging : IHasBatteryStats +{ + BoolFeedback BatteryIsCharging { get; } +} - /// - /// Interface for any device that has multiple batteries that can be monitored - /// - public interface IHasBatteries : IKeyName - { - ReadOnlyDictionary Batteries { get; } - } +/// +/// Interface for any device that has multiple batteries that can be monitored +/// +public interface IHasBatteries : IKeyName +{ + ReadOnlyDictionary Batteries { get; } +} - public interface IHasBatteryStatsExtended : IHasBatteryStats - { - int InputVoltage { get; } - int OutputVoltage { get; } - int InptuCurrent { get; } - int OutputCurrent { get; } +public interface IHasBatteryStatsExtended : IHasBatteryStats +{ + int InputVoltage { get; } + int OutputVoltage { get; } + int InptuCurrent { get; } + int OutputCurrent { get; } + + IntFeedback InputVoltageFeedback { get; } + IntFeedback OutputVoltageFeedback { get; } + IntFeedback InputCurrentFeedback { get; } + IntFeedback OutputCurrentFeedback { get; } +} - IntFeedback InputVoltageFeedback { get; } - IntFeedback OutputVoltageFeedback { get; } - IntFeedback InputCurrentFeedback { get; } - IntFeedback OutputCurrentFeedback { get; } - } +/// +/// Interface for any device that is able to control its power, has a configurable reboot time, and has batteries that can be monitored +/// +public interface IHasPowerCycleWithBattery : IHasPowerCycle, IHasBatteryStats +{ + +} +/// +/// Interface for any device that is able to control it's power and has a configurable reboot time +/// +public interface IHasPowerCycle : IKeyName, IHasPowerControlWithFeedback +{ /// - /// Interface for any device that is able to control its power, has a configurable reboot time, and has batteries that can be monitored + /// Delay between power off and power on for reboot /// - public interface IHasPowerCycleWithBattery : IHasPowerCycle, IHasBatteryStats - { - - } + int PowerCycleTimeMs { get; } /// - /// Interface for any device that is able to control it's power and has a configurable reboot time + /// Reboot outlet /// - public interface IHasPowerCycle : IKeyName, IHasPowerControlWithFeedback - { - /// - /// Delay between power off and power on for reboot - /// - int PowerCycleTimeMs { get; } - - /// - /// Reboot outlet - /// - void PowerCycle(); - } + void PowerCycle(); +} +/// +/// Interface for any device that contains a collection of IHasPowerReboot Devices +/// +public interface IHasControlledPowerOutlets : IKeyName +{ /// - /// Interface for any device that contains a collection of IHasPowerReboot Devices + /// Collection of IPduOutlets /// - public interface IHasControlledPowerOutlets : IKeyName - { - /// - /// Collection of IPduOutlets - /// - ReadOnlyDictionary PduOutlets { get; } - - } - - + ReadOnlyDictionary PduOutlets { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/PresentationDeviceType.cs b/src/PepperDash.Essentials.Core/Devices/PresentationDeviceType.cs index 41555ae8e..f2db91593 100644 --- a/src/PepperDash.Essentials.Core/Devices/PresentationDeviceType.cs +++ b/src/PepperDash.Essentials.Core/Devices/PresentationDeviceType.cs @@ -7,10 +7,9 @@ using Crestron.SimplSharpPro.EthernetCommunication; using Crestron.SimplSharpPro.UI; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public enum PresentationSourceType { None, Dvd, Laptop, PC, SetTopBox, VCR - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/PresetListItem.cs b/src/PepperDash.Essentials.Core/Devices/PresetListItem.cs index f539d7186..5865fc759 100644 --- a/src/PepperDash.Essentials.Core/Devices/PresetListItem.cs +++ b/src/PepperDash.Essentials.Core/Devices/PresetListItem.cs @@ -7,39 +7,38 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public class PresetListItem : AudioControlListItemBase { - public class PresetListItem : AudioControlListItemBase + [JsonIgnore] + public IKeyName Preset { - [JsonIgnore] - public IKeyName Preset + get { - get + if (_preset == null) { - if (_preset == null) - { - var parent = DeviceManager.GetDeviceForKey(ParentDeviceKey) as IDspPresets; - if (parent == null || !parent.Presets.ContainsKey(ItemKey)) - return null; - _preset = parent.Presets[ItemKey]; - } - return _preset; + var parent = DeviceManager.GetDeviceForKey(ParentDeviceKey) as IDspPresets; + if (parent == null || !parent.Presets.ContainsKey(ItemKey)) + return null; + _preset = parent.Presets[ItemKey]; } + return _preset; } - private IKeyName _preset; + } + private IKeyName _preset; - /// - /// Gets the name from the device if it implements IKeyName or else returns the Name property - /// - [JsonProperty("preferredName")] - public string PreferredName + /// + /// Gets the name from the device if it implements IKeyName or else returns the Name property + /// + [JsonProperty("preferredName")] + public string PreferredName + { + get { - get - { - if (!string.IsNullOrEmpty(Name)) return Name; + if (!string.IsNullOrEmpty(Name)) return Name; - else return Preset.Name; - } + else return Preset.Name; } } } diff --git a/src/PepperDash.Essentials.Core/Devices/ReconfigurableDevice.cs b/src/PepperDash.Essentials.Core/Devices/ReconfigurableDevice.cs index 1da908a96..a7dc2af2f 100644 --- a/src/PepperDash.Essentials.Core/Devices/ReconfigurableDevice.cs +++ b/src/PepperDash.Essentials.Core/Devices/ReconfigurableDevice.cs @@ -12,68 +12,67 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; -namespace PepperDash.Essentials.Core.Devices -{ - /// - /// - /// - public abstract class ReconfigurableDevice : EssentialsDevice, IReconfigurableDevice - { - public event EventHandler ConfigChanged; +namespace PepperDash.Essentials.Core.Devices; - public DeviceConfig Config { get; private set; } +/// +/// +/// +public abstract class ReconfigurableDevice : EssentialsDevice, IReconfigurableDevice +{ + public event EventHandler ConfigChanged; - protected ReconfigurableDevice(DeviceConfig config) - : base(config.Key) - { - SetNameHelper(config); + public DeviceConfig Config { get; private set; } - Config = config; - } + protected ReconfigurableDevice(DeviceConfig config) + : base(config.Key) + { + SetNameHelper(config); - /// - /// Sets the Config, calls CustomSetConfig and fires the ConfigChanged event - /// - /// - public void SetConfig(DeviceConfig config) - { - Config = config; + Config = config; + } - SetNameHelper(config); + /// + /// Sets the Config, calls CustomSetConfig and fires the ConfigChanged event + /// + /// + public void SetConfig(DeviceConfig config) + { + Config = config; - CustomSetConfig(config); + SetNameHelper(config); - var handler = ConfigChanged; - if (handler != null) - { - handler(this, new EventArgs()); - } - } + CustomSetConfig(config); - void SetNameHelper(DeviceConfig config) + var handler = ConfigChanged; + if (handler != null) { - if (!string.IsNullOrEmpty(config.Name)) - Name = config.Name; + handler(this, new EventArgs()); } + } + void SetNameHelper(DeviceConfig config) + { + if (!string.IsNullOrEmpty(config.Name)) + Name = config.Name; + } - /// - /// Used by the extending class to allow for any custom actions to be taken (tell the ConfigWriter to write config, etc) - /// - /// - protected virtual void CustomSetConfig(DeviceConfig config) - { - ConfigWriter.UpdateDeviceConfig(config); - } - } - public abstract class ReconfigurableBridgableDevice : ReconfigurableDevice, IBridgeAdvanced + /// + /// Used by the extending class to allow for any custom actions to be taken (tell the ConfigWriter to write config, etc) + /// + /// + protected virtual void CustomSetConfig(DeviceConfig config) { - protected ReconfigurableBridgableDevice(DeviceConfig config) : base(config) - { - } + ConfigWriter.UpdateDeviceConfig(config); + } +} - public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge); +public abstract class ReconfigurableBridgableDevice : ReconfigurableDevice, IBridgeAdvanced +{ + protected ReconfigurableBridgableDevice(DeviceConfig config) : base(config) + { } + + public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/SmartObjectBaseTypes.cs b/src/PepperDash.Essentials.Core/Devices/SmartObjectBaseTypes.cs index 37e62036a..95ef8e869 100644 --- a/src/PepperDash.Essentials.Core/Devices/SmartObjectBaseTypes.cs +++ b/src/PepperDash.Essentials.Core/Devices/SmartObjectBaseTypes.cs @@ -1,11 +1,10 @@  -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public class SmartObjectJoinOffsets { public const ushort Dpad = 1; public const ushort Numpad = 2; public const ushort PresetList = 6; - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/SourceListItem.cs b/src/PepperDash.Essentials.Core/Devices/SourceListItem.cs index 6de2f35d5..ed3f171a4 100644 --- a/src/PepperDash.Essentials.Core/Devices/SourceListItem.cs +++ b/src/PepperDash.Essentials.Core/Devices/SourceListItem.cs @@ -3,195 +3,194 @@ using PepperDash.Core; using System.Collections.Generic; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// +/// +public enum eSourceListItemType { - /// - /// - /// - public enum eSourceListItemType - { - Route, Off, Other, SomethingAwesomerThanThese - } + Route, Off, Other, SomethingAwesomerThanThese +} + +/// +/// Represents an item in a source list - can be deserialized into. +/// +public class SourceListItem +{ + [JsonProperty("sourceKey")] + public string SourceKey { get; set; } /// - /// Represents an item in a source list - can be deserialized into. + /// Returns the source Device for this, if it exists in DeviceManager /// - public class SourceListItem + [JsonIgnore] + public Device SourceDevice { - [JsonProperty("sourceKey")] - public string SourceKey { get; set; } - - /// - /// Returns the source Device for this, if it exists in DeviceManager - /// - [JsonIgnore] - public Device SourceDevice + get { - get - { - if (_SourceDevice == null) - _SourceDevice = DeviceManager.GetDeviceForKey(SourceKey) as Device; - return _SourceDevice; - } + if (_SourceDevice == null) + _SourceDevice = DeviceManager.GetDeviceForKey(SourceKey) as Device; + return _SourceDevice; } + } - private Device _SourceDevice; + private Device _SourceDevice; - /// - /// Gets either the source's Name or this AlternateName property, if - /// defined. If source doesn't exist, returns "Missing source" - /// - [JsonProperty("preferredName")] - public string PreferredName + /// + /// Gets either the source's Name or this AlternateName property, if + /// defined. If source doesn't exist, returns "Missing source" + /// + [JsonProperty("preferredName")] + public string PreferredName + { + get { - get + if (string.IsNullOrEmpty(Name)) { - if (string.IsNullOrEmpty(Name)) - { - if (SourceDevice == null) - return "---"; - return SourceDevice.Name; - } - return Name; + if (SourceDevice == null) + return "---"; + return SourceDevice.Name; } + return Name; } + } - /// - /// A name that will override the source's name on the UI - /// - [JsonProperty("name")] - public string Name { get; set; } + /// + /// A name that will override the source's name on the UI + /// + [JsonProperty("name")] + public string Name { get; set; } - /// - /// Specifies and icon for the source list item - /// + /// + /// Specifies and icon for the source list item + /// [JsonProperty("icon")] - public string Icon { get; set; } + public string Icon { get; set; } - /// - /// Alternate icon - /// + /// + /// Alternate icon + /// [JsonProperty("altIcon")] - public string AltIcon { get; set; } + public string AltIcon { get; set; } - /// - /// Indicates if the item should be included in the source list - /// + /// + /// Indicates if the item should be included in the source list + /// [JsonProperty("includeInSourceList")] - public bool IncludeInSourceList { get; set; } + public bool IncludeInSourceList { get; set; } - /// - /// Used to specify the order of the items in the source list when displayed - /// + /// + /// Used to specify the order of the items in the source list when displayed + /// [JsonProperty("order")] - public int Order { get; set; } + public int Order { get; set; } - /// - /// The key of the device for volume control - /// + /// + /// The key of the device for volume control + /// [JsonProperty("volumeControlKey")] - public string VolumeControlKey { get; set; } + public string VolumeControlKey { get; set; } - /// - /// The type of source list item - /// + /// + /// The type of source list item + /// [JsonProperty("type")] - [JsonConverter(typeof(StringEnumConverter))] - public eSourceListItemType Type { get; set; } + [JsonConverter(typeof(StringEnumConverter))] + public eSourceListItemType Type { get; set; } - /// - /// The list of routes to execute for this source list item - /// + /// + /// The list of routes to execute for this source list item + /// [JsonProperty("routeList")] - public List RouteList { get; set; } + public List RouteList { get; set; } - /// - /// Indicates if this source should be disabled for sharing to the far end call participants via codec content - /// + /// + /// Indicates if this source should be disabled for sharing to the far end call participants via codec content + /// [JsonProperty("disableCodecSharing")] - public bool DisableCodecSharing { get; set; } + public bool DisableCodecSharing { get; set; } - /// - /// Indicates if this source should be disabled for routing to a shared output - /// + /// + /// Indicates if this source should be disabled for routing to a shared output + /// [JsonProperty("disableRoutedSharing")] - public bool DisableRoutedSharing { get; set; } - - [JsonProperty("destinations")] - public List Destinations { get; set; } - /// - /// A means to reference a source list for this source item, in the event that this source has an input that can have sources routed to it - /// - [JsonProperty("sourceListKey")] - public string SourceListKey { get; set; } - - /// - /// Indicates if the device associated with this source is controllable - /// - [JsonProperty("isControllable")] - public bool IsControllable { get; set; } - - /// - /// Indicates that the device associated with this source has audio available - /// - [JsonProperty("isAudioSource")] - public bool IsAudioSource { get; set; } - - /// - /// Hide source on UI when Avanced Sharing is enabled - /// - [JsonProperty("disableAdvancedRouting")] - public bool DisableAdvancedRouting { get; set; } - - /// - /// Hide source on UI when Simpl Sharing is enabled - /// - [JsonProperty("disableSimpleRouting")] - public bool DisableSimpleRouting { get; set; } - - public SourceListItem() - { - Icon = "Blank"; - } + public bool DisableRoutedSharing { get; set; } - public override string ToString() - { - return $"{SourceKey}:{Name}"; - } - } + [JsonProperty("destinations")] + public List Destinations { get; set; } + /// + /// A means to reference a source list for this source item, in the event that this source has an input that can have sources routed to it + /// + [JsonProperty("sourceListKey")] + public string SourceListKey { get; set; } - public class SourceRouteListItem - { - [JsonProperty("sourceKey")] - public string SourceKey { get; set; } + /// + /// Indicates if the device associated with this source is controllable + /// + [JsonProperty("isControllable")] + public bool IsControllable { get; set; } - [JsonProperty("sourcePortKey")] - public string SourcePortKey { get; set; } + /// + /// Indicates that the device associated with this source has audio available + /// + [JsonProperty("isAudioSource")] + public bool IsAudioSource { get; set; } - [JsonProperty("destinationKey")] - public string DestinationKey { get; set; } + /// + /// Hide source on UI when Avanced Sharing is enabled + /// + [JsonProperty("disableAdvancedRouting")] + public bool DisableAdvancedRouting { get; set; } - [JsonProperty("destinationPortKey")] - public string DestinationPortKey { get; set; } + /// + /// Hide source on UI when Simpl Sharing is enabled + /// + [JsonProperty("disableSimpleRouting")] + public bool DisableSimpleRouting { get; set; } - [JsonProperty("type")] - public eRoutingSignalType Type { get; set; } + public SourceListItem() + { + Icon = "Blank"; } - /// - /// Defines the valid destination types for SourceListItems in a room - /// - public enum eSourceListItemDestinationTypes + public override string ToString() { - defaultDisplay, - leftDisplay, - rightDisplay, - centerDisplay, - programAudio, - codecContent, - frontLeftDisplay, - frontRightDisplay, - rearLeftDisplay, - rearRightDisplay, + return $"{SourceKey}:{Name}"; } +} + +public class SourceRouteListItem +{ + [JsonProperty("sourceKey")] + public string SourceKey { get; set; } + + [JsonProperty("sourcePortKey")] + public string SourcePortKey { get; set; } + + [JsonProperty("destinationKey")] + public string DestinationKey { get; set; } + + [JsonProperty("destinationPortKey")] + public string DestinationPortKey { get; set; } + + [JsonProperty("type")] + public eRoutingSignalType Type { get; set; } +} + +/// +/// Defines the valid destination types for SourceListItems in a room +/// +public enum eSourceListItemDestinationTypes +{ + defaultDisplay, + leftDisplay, + rightDisplay, + centerDisplay, + programAudio, + codecContent, + frontLeftDisplay, + frontRightDisplay, + rearLeftDisplay, + rearRightDisplay, } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Devices/VolumeDeviceChangeEventArgs.cs b/src/PepperDash.Essentials.Core/Devices/VolumeDeviceChangeEventArgs.cs index 2171cb73a..931dc462d 100644 --- a/src/PepperDash.Essentials.Core/Devices/VolumeDeviceChangeEventArgs.cs +++ b/src/PepperDash.Essentials.Core/Devices/VolumeDeviceChangeEventArgs.cs @@ -7,8 +7,8 @@ using PepperDash.Core; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// /// @@ -32,5 +32,4 @@ public VolumeDeviceChangeEventArgs(IBasicVolumeControls oldDev, IBasicVolumeCont public enum ChangeType { WillChange, DidChange - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Ethernet/EthernetStatistics.cs b/src/PepperDash.Essentials.Core/Ethernet/EthernetStatistics.cs index cbdd06170..eb308cc50 100644 --- a/src/PepperDash.Essentials.Core/Ethernet/EthernetStatistics.cs +++ b/src/PepperDash.Essentials.Core/Ethernet/EthernetStatistics.cs @@ -6,8 +6,8 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core.Ethernet -{ +namespace PepperDash.Essentials.Core.Ethernet; + public static class EthernetSettings { public static readonly BoolFeedback LinkActive = new BoolFeedback("LinkActive", @@ -29,5 +29,4 @@ public static class EthernetSettings public static readonly StringFeedback DefaultGateway0 = new StringFeedback("DefaultGateway0", () => CrestronEthernetHelper.GetEthernetParameter( CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, 0)); - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Extensions/IpAddressExtensions.cs b/src/PepperDash.Essentials.Core/Extensions/IpAddressExtensions.cs index 35ec1b8a8..6da2211ab 100644 --- a/src/PepperDash.Essentials.Core/Extensions/IpAddressExtensions.cs +++ b/src/PepperDash.Essentials.Core/Extensions/IpAddressExtensions.cs @@ -5,82 +5,81 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Extensions for IPAddress to provide additional functionality such as getting broadcast address, network address, and checking if two addresses are in the same subnet. +/// +public static class IPAddressExtensions { /// - /// Extensions for IPAddress to provide additional functionality such as getting broadcast address, network address, and checking if two addresses are in the same subnet. + /// Get the broadcast address for a given IP address and subnet mask. /// - public static class IPAddressExtensions + /// Address to check + /// Subnet mask in a.b.c.d format + /// Broadcast address + /// + /// If the input IP address is 192.168.1.100 and the subnet mask is 255.255.255.0, the broadcast address will be 192.168.1.255 + /// + /// + public static IPAddress GetBroadcastAddress(this IPAddress address, IPAddress subnetMask) { - /// - /// Get the broadcast address for a given IP address and subnet mask. - /// - /// Address to check - /// Subnet mask in a.b.c.d format - /// Broadcast address - /// - /// If the input IP address is 192.168.1.100 and the subnet mask is 255.255.255.0, the broadcast address will be 192.168.1.255 - /// - /// - public static IPAddress GetBroadcastAddress(this IPAddress address, IPAddress subnetMask) - { - byte[] ipAdressBytes = address.GetAddressBytes(); - byte[] subnetMaskBytes = subnetMask.GetAddressBytes(); + byte[] ipAdressBytes = address.GetAddressBytes(); + byte[] subnetMaskBytes = subnetMask.GetAddressBytes(); - if (ipAdressBytes.Length != subnetMaskBytes.Length) - throw new ArgumentException("Lengths of IP address and subnet mask do not match."); + if (ipAdressBytes.Length != subnetMaskBytes.Length) + throw new ArgumentException("Lengths of IP address and subnet mask do not match."); - byte[] broadcastAddress = new byte[ipAdressBytes.Length]; - for (int i = 0; i < broadcastAddress.Length; i++) - { - broadcastAddress[i] = (byte)(ipAdressBytes[i] | (subnetMaskBytes[i] ^ 255)); - } - return new IPAddress(broadcastAddress); + byte[] broadcastAddress = new byte[ipAdressBytes.Length]; + for (int i = 0; i < broadcastAddress.Length; i++) + { + broadcastAddress[i] = (byte)(ipAdressBytes[i] | (subnetMaskBytes[i] ^ 255)); } + return new IPAddress(broadcastAddress); + } - /// - /// Get the network address for a given IP address and subnet mask. - /// - /// Address to check - /// Subnet mask in a.b.c.d - /// Network Address - /// /// - /// If the input IP address is 192.168.1.100 and the subnet mask is 255.255.255.0, the network address will be 192.168.1.0 - /// - /// - public static IPAddress GetNetworkAddress(this IPAddress address, IPAddress subnetMask) - { - byte[] ipAdressBytes = address.GetAddressBytes(); - byte[] subnetMaskBytes = subnetMask.GetAddressBytes(); + /// + /// Get the network address for a given IP address and subnet mask. + /// + /// Address to check + /// Subnet mask in a.b.c.d + /// Network Address + /// /// + /// If the input IP address is 192.168.1.100 and the subnet mask is 255.255.255.0, the network address will be 192.168.1.0 + /// + /// + public static IPAddress GetNetworkAddress(this IPAddress address, IPAddress subnetMask) + { + byte[] ipAdressBytes = address.GetAddressBytes(); + byte[] subnetMaskBytes = subnetMask.GetAddressBytes(); - if (ipAdressBytes.Length != subnetMaskBytes.Length) - throw new ArgumentException("Lengths of IP address and subnet mask do not match."); + if (ipAdressBytes.Length != subnetMaskBytes.Length) + throw new ArgumentException("Lengths of IP address and subnet mask do not match."); - byte[] broadcastAddress = new byte[ipAdressBytes.Length]; - for (int i = 0; i < broadcastAddress.Length; i++) - { - broadcastAddress[i] = (byte)(ipAdressBytes[i] & (subnetMaskBytes[i])); - } - return new IPAddress(broadcastAddress); + byte[] broadcastAddress = new byte[ipAdressBytes.Length]; + for (int i = 0; i < broadcastAddress.Length; i++) + { + broadcastAddress[i] = (byte)(ipAdressBytes[i] & (subnetMaskBytes[i])); } + return new IPAddress(broadcastAddress); + } - /// - /// Determine if two IP addresses are in the same subnet. - /// - /// Address to check - /// Second address to check - /// Subnet mask to use to compare the 2 IP Address - /// True if addresses are in the same subnet - /// - /// If the input IP addresses are 192.168.1.100 and 192.168.1.200, and the subnet mask is 255.255.255.0, this will return true. - /// If the input IP addresses are 10.1.1.100 and 192.168.1.100, and the subnet mask is 255.255.255.0, this will return false. - /// - public static bool IsInSameSubnet(this IPAddress address2, IPAddress address, IPAddress subnetMask) - { - IPAddress network1 = address.GetNetworkAddress(subnetMask); - IPAddress network2 = address2.GetNetworkAddress(subnetMask); + /// + /// Determine if two IP addresses are in the same subnet. + /// + /// Address to check + /// Second address to check + /// Subnet mask to use to compare the 2 IP Address + /// True if addresses are in the same subnet + /// + /// If the input IP addresses are 192.168.1.100 and 192.168.1.200, and the subnet mask is 255.255.255.0, this will return true. + /// If the input IP addresses are 10.1.1.100 and 192.168.1.100, and the subnet mask is 255.255.255.0, this will return false. + /// + public static bool IsInSameSubnet(this IPAddress address2, IPAddress address, IPAddress subnetMask) + { + IPAddress network1 = address.GetNetworkAddress(subnetMask); + IPAddress network2 = address2.GetNetworkAddress(subnetMask); - return network1.Equals(network2); - } + return network1.Equals(network2); } } diff --git a/src/PepperDash.Essentials.Core/Extensions/JsonExtensions.cs b/src/PepperDash.Essentials.Core/Extensions/JsonExtensions.cs index 2d71c6bcc..a25d9c89c 100644 --- a/src/PepperDash.Essentials.Core/Extensions/JsonExtensions.cs +++ b/src/PepperDash.Essentials.Core/Extensions/JsonExtensions.cs @@ -8,36 +8,35 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public static class JsonExtensions { - public static class JsonExtensions + public static List FindTokens(this JToken containerToken, string name) { - public static List FindTokens(this JToken containerToken, string name) - { - List matches = new List(); - FindTokens(containerToken, name, matches); - return matches; - } + List matches = new List(); + FindTokens(containerToken, name, matches); + return matches; + } - private static void FindTokens(JToken containerToken, string name, List matches) + private static void FindTokens(JToken containerToken, string name, List matches) + { + if (containerToken.Type == JTokenType.Object) { - if (containerToken.Type == JTokenType.Object) + foreach (JProperty child in containerToken.Children()) { - foreach (JProperty child in containerToken.Children()) + if (child.Name == name) { - if (child.Name == name) - { - matches.Add(child.Value); - } - FindTokens(child.Value, name, matches); + matches.Add(child.Value); } + FindTokens(child.Value, name, matches); } - else if (containerToken.Type == JTokenType.Array) + } + else if (containerToken.Type == JTokenType.Array) + { + foreach (JToken child in containerToken.Children()) { - foreach (JToken child in containerToken.Children()) - { - FindTokens(child, name, matches); - } + FindTokens(child, name, matches); } } } diff --git a/src/PepperDash.Essentials.Core/Extensions/StringExtensions.cs b/src/PepperDash.Essentials.Core/Extensions/StringExtensions.cs index 7bf8d5a55..3a863b152 100644 --- a/src/PepperDash.Essentials.Core/Extensions/StringExtensions.cs +++ b/src/PepperDash.Essentials.Core/Extensions/StringExtensions.cs @@ -5,74 +5,73 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public static class StringExtensions { - public static class StringExtensions + /// + /// Returns null if a string is empty, otherwise returns the string + /// + /// string input + /// null if the string is emtpy, otherwise returns the string + public static string NullIfEmpty(this string s) { - /// - /// Returns null if a string is empty, otherwise returns the string - /// - /// string input - /// null if the string is emtpy, otherwise returns the string - public static string NullIfEmpty(this string s) - { - return string.IsNullOrEmpty(s) ? null : s; - } - - /// - /// Returns null if a string is empty or made of only whitespace characters, otherwise returns the string - /// - /// string input - /// null if the string is wempty or made of only whitespace characters, otherwise returns the string - public static string NullIfWhiteSpace(this string s) - { - return string.IsNullOrEmpty(s.Trim()) ? null : s; - } + return string.IsNullOrEmpty(s) ? null : s; + } - /// - /// Returns a replacement string if the input string is empty or made of only whitespace characters, otherwise returns the input string - /// - /// input string - /// string to replace with if input string is empty or whitespace - /// returns newString if s is null, emtpy, or made of whitespace characters, otherwise returns s - public static string ReplaceIfNullOrEmpty(this string s, string newString) - { - return string.IsNullOrEmpty(s) ? newString : s; - } + /// + /// Returns null if a string is empty or made of only whitespace characters, otherwise returns the string + /// + /// string input + /// null if the string is wempty or made of only whitespace characters, otherwise returns the string + public static string NullIfWhiteSpace(this string s) + { + return string.IsNullOrEmpty(s.Trim()) ? null : s; + } - /// - /// Overload for Contains that allows setting an explicit String Comparison - /// - /// Source String - /// String to check in Source String - /// Comparison parameters - /// true of string contains "toCheck" - public static bool Contains(this string source, string toCheck, StringComparison comp) - { - if (string.IsNullOrEmpty(source)) return false; - return source.IndexOf(toCheck, comp) >= 0; - } + /// + /// Returns a replacement string if the input string is empty or made of only whitespace characters, otherwise returns the input string + /// + /// input string + /// string to replace with if input string is empty or whitespace + /// returns newString if s is null, emtpy, or made of whitespace characters, otherwise returns s + public static string ReplaceIfNullOrEmpty(this string s, string newString) + { + return string.IsNullOrEmpty(s) ? newString : s; + } - /// - /// Performs TrimStart() and TrimEnd() on source string - /// - /// String to Trim - /// Trimmed String - public static string TrimAll(this string source) - { - return string.IsNullOrEmpty(source) ? string.Empty : source.TrimStart().TrimEnd(); - } + /// + /// Overload for Contains that allows setting an explicit String Comparison + /// + /// Source String + /// String to check in Source String + /// Comparison parameters + /// true of string contains "toCheck" + public static bool Contains(this string source, string toCheck, StringComparison comp) + { + if (string.IsNullOrEmpty(source)) return false; + return source.IndexOf(toCheck, comp) >= 0; + } - /// - /// Performs TrimStart(chars char[]) and TrimEnd(chars char[]) on source string. - /// - /// String to Trim - /// Char Array to trim from string - /// Trimmed String - public static string TrimAll(this string source, char[] chars) - { - return string.IsNullOrEmpty(source) ? string.Empty : source.TrimStart(chars).TrimEnd(chars); - } + /// + /// Performs TrimStart() and TrimEnd() on source string + /// + /// String to Trim + /// Trimmed String + public static string TrimAll(this string source) + { + return string.IsNullOrEmpty(source) ? string.Empty : source.TrimStart().TrimEnd(); + } + /// + /// Performs TrimStart(chars char[]) and TrimEnd(chars char[]) on source string. + /// + /// String to Trim + /// Char Array to trim from string + /// Trimmed String + public static string TrimAll(this string source, char[] chars) + { + return string.IsNullOrEmpty(source) ? string.Empty : source.TrimStart(chars).TrimEnd(chars); } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Factory/DeviceFactory.cs b/src/PepperDash.Essentials.Core/Factory/DeviceFactory.cs index 07bcc56a1..dca09cb99 100644 --- a/src/PepperDash.Essentials.Core/Factory/DeviceFactory.cs +++ b/src/PepperDash.Essentials.Core/Factory/DeviceFactory.cs @@ -1,198 +1,308 @@  -using Crestron.SimplSharp; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.IO; +using System.Linq; using System.Reflection; +using Crestron.SimplSharp; using Newtonsoft.Json.Linq; using PepperDash.Core; using PepperDash.Essentials.Core.Config; using Serilog.Events; -using System; -using System.Collections.Generic; -using System.Linq; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Represents a wrapper for a device factory, encapsulating the type of device, a description, and a factory method +/// for creating device instances. +/// +/// This class is designed to provide a convenient way to store and manage metadata and factory methods +/// for creating devices based on a given configuration. +public class DeviceFactoryWrapper { - public class DeviceFactoryWrapper - { - public Type Type { get; set; } - public string Description { get; set; } - public Func FactoryMethod { get; set; } + /// + /// Gets or sets the type associated with the current instance. + /// + public Type Type { get; set; } - public DeviceFactoryWrapper() - { - Type = null; - Description = "Not Available"; - } - } + /// + /// Gets or sets the description associated with the object. + /// + public string Description { get; set; } - public class DeviceFactory + /// + /// Gets or sets the factory method used to create an instance based on the provided . + /// + /// The factory method allows customization of how instances are created for + /// specific inputs. Ensure the delegate is not null before invoking it. + public Func FactoryMethod { get; set; } + + /// + /// Initializes a new instance of the class with default values. + /// + /// The property is initialized to , and the property is set to "Not Available". + public DeviceFactoryWrapper() { - public DeviceFactory() - { - var assy = Assembly.GetExecutingAssembly(); - PluginLoader.SetEssentialsAssembly(assy.GetName().Name, assy); + Type = null; + Description = "Not Available"; + } +} - var types = assy.GetTypes().Where(ct => typeof(IDeviceFactory).IsAssignableFrom(ct) && !ct.IsInterface && !ct.IsAbstract); +/// +/// Provides functionality for managing and registering device factories, including loading plugin-based factories and +/// retrieving devices based on their configuration. +/// +/// The class is responsible for discovering and registering device factories +/// from plugins, as well as providing methods to retrieve devices based on their configuration. It maintains a +/// collection of factory methods that are keyed by device type names, allowing for extensibility through plugins. This +/// class also handles metadata retrieval and secret management for device configurations. +public class DeviceFactory +{ + /// + /// Initializes a new instance of the class and loads all available device factories + /// from the current assembly. + /// + /// This constructor scans the executing assembly for types that implement the interface and are not abstract or interfaces. For each valid type, an instance is + /// created and passed to the LoadDeviceFactories method for further processing. If a type cannot be + /// instantiated, an informational log message is generated, and the process continues with the remaining + /// types. + public DeviceFactory() + { + var programAssemblies = Directory.GetFiles(InitialParametersClass.ProgramDirectory.ToString(), "*.dll"); - if (types != null) + foreach (var assembly in programAssemblies) + { + try { - foreach (var type in types) - { - try - { - var factory = (IDeviceFactory)Activator.CreateInstance(type); - factory.LoadTypeFactories(); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Information, "Unable to load type: '{1}' DeviceFactory: {0}", e, type.Name); - } - } + Assembly.LoadFrom(assembly); + } + catch (Exception e) + { + Debug.LogError("Unable to load assembly: {assemblyName} - {message}", assembly, e.Message); } } - /// - /// A dictionary of factory methods, keyed by config types, added by plugins. - /// These methods are looked up and called by GetDevice in this class. - /// - static Dictionary FactoryMethods = - new Dictionary(StringComparer.OrdinalIgnoreCase); - - /// - /// Adds a plugin factory method - /// - /// - /// - public static void AddFactoryForType(string typeName, Func method) - { - //Debug.LogMessage(LogEventLevel.Debug, "Adding factory method for type '{0}'", typeName); - DeviceFactory.FactoryMethods.Add(typeName, new DeviceFactoryWrapper() { FactoryMethod = method}); - } - - public static void AddFactoryForType(string typeName, string description, Type Type, Func method) + var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); + + // Loop through all loaded assemblies that contain at least 1 type that implements IDeviceFactory + foreach (var assembly in loadedAssemblies) { - //Debug.LogMessage(LogEventLevel.Debug, "Adding factory method for type '{0}'", typeName); + Debug.LogDebug("loaded assembly: {assemblyName}", assembly.GetName().Name); + + PluginLoader.AddLoadedAssembly(assembly.GetName().Name, assembly); - if(FactoryMethods.ContainsKey(typeName)) + var types = assembly.GetTypes().Where(ct => typeof(IDeviceFactory).IsAssignableFrom(ct) && !ct.IsInterface && !ct.IsAbstract); + + if (types == null || !types.Any()) { - Debug.LogMessage(LogEventLevel.Information, "Unable to add type: '{0}'. Already exists in DeviceFactory", typeName); - return; + Debug.LogDebug("No DeviceFactory types found in assembly: {assemblyName}", assembly.GetName().Name); + continue; } - var wrapper = new DeviceFactoryWrapper() { Type = Type, Description = description, FactoryMethod = method }; - DeviceFactory.FactoryMethods.Add(typeName, wrapper); - } - - private static void CheckForSecrets(IEnumerable obj) - { - foreach (var prop in obj.Where(prop => prop.Value as JObject != null)) + foreach (var type in types) { - if (prop.Name.ToLower() == "secret") + try { - var secret = GetSecret(prop.Children().First().ToObject()); - //var secret = GetSecret(JsonConvert.DeserializeObject(prop.Children().First().ToString())); - prop.Parent.Replace(secret); + var factory = (IDeviceFactory)Activator.CreateInstance(type); + LoadDeviceFactories(factory); + } + catch (Exception e) + { + Debug.LogError("Unable to load type: '{message}' DeviceFactory: {type}", e.Message, type.Name); } - var recurseProp = prop.Value as JObject; - if (recurseProp == null) return; - CheckForSecrets(recurseProp.Properties()); } + + } + } + + /// + /// Loads device factories from the specified plugin device factory and registers them for use. + /// + /// This method retrieves metadata from the provided , including + /// type names, descriptions, and configuration snippets, and registers the factory for each device type. The type + /// names are converted to lowercase for registration. + /// The plugin device factory that provides the device types, descriptions, and factory methods to be registered. + private static void LoadDeviceFactories(IDeviceFactory deviceFactory) + { + foreach (var typeName in deviceFactory.TypeNames) + { + //Debug.LogMessage(LogEventLevel.Verbose, "Getting Description Attribute from class: '{0}'", typeof(T).FullName); + var descriptionAttribute = deviceFactory.FactoryType.GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[]; + string description = descriptionAttribute[0].Description; + var snippetAttribute = deviceFactory.FactoryType.GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[]; + AddFactoryForType(typeName.ToLower(), description, deviceFactory.FactoryType, deviceFactory.BuildDevice); } + } + + /// + /// A dictionary of factory methods, keyed by config types, added by plugins. + /// These methods are looked up and called by GetDevice in this class. + /// + private static readonly Dictionary FactoryMethods = + new(StringComparer.OrdinalIgnoreCase); + + /// + /// Registers a factory method for creating instances of a specific type. + /// + /// This method associates a type name with a factory method, allowing instances of the type to + /// be created dynamically. The factory method is stored internally and can be retrieved or invoked as + /// needed. + /// The name of the type for which the factory method is being registered. This value cannot be null or empty. + /// A delegate that defines the factory method. The delegate takes a parameter and + /// returns an instance of . + public static void AddFactoryForType(string typeName, Func method) + { + FactoryMethods.Add(typeName, new DeviceFactoryWrapper() { FactoryMethod = method }); + } - private static string GetSecret(SecretsPropertiesConfig data) + /// + /// Registers a factory method for creating instances of a specific device type. + /// + /// If a factory method for the specified already exists, the method + /// will not overwrite it and will log an informational message instead. + /// The unique name of the device type. This serves as the key for identifying the factory method. + /// A brief description of the device type. This is used for informational purposes. + /// The of the device being registered. This represents the runtime type of the device. + /// A factory method that takes a as input and returns an instance of . + public static void AddFactoryForType(string typeName, string description, Type Type, Func method) + { + if (FactoryMethods.ContainsKey(typeName)) { - var secretProvider = SecretsManager.GetSecretProviderByKey(data.Provider); - if (secretProvider == null) return null; - var secret = secretProvider.GetSecret(data.Key); - if (secret != null) return (string) secret.Value; - Debug.LogMessage(LogEventLevel.Debug, - "Unable to retrieve secret {0}{1} - Make sure you've added it to the secrets provider", - data.Provider, data.Key); - return String.Empty; + Debug.LogInformation("Unable to add type: '{typeName}'. Already exists in DeviceFactory", typeName); + return; } + var wrapper = new DeviceFactoryWrapper() { Type = Type, Description = description, FactoryMethod = method }; - /// - /// The factory method for Core "things". Also iterates the Factory methods that have - /// been loaded from plugins - /// - /// - /// - public static IKeyed GetDevice(DeviceConfig dc) + FactoryMethods.Add(typeName, wrapper); + } + + private static void CheckForSecrets(IEnumerable obj) + { + foreach (var prop in obj.Where(prop => prop.Value as JObject != null)) { - try + if (prop.Name.Equals("secret", StringComparison.CurrentCultureIgnoreCase)) { - Debug.LogMessage(LogEventLevel.Information, "Loading '{0}' from Essentials Core", dc.Type); + var secret = GetSecret(prop.Children().First().ToObject()); - var localDc = new DeviceConfig(dc); + prop.Parent.Replace(secret); + } + if (prop.Value is not JObject recurseProp) return; + CheckForSecrets(recurseProp.Properties()); + } + } - var key = localDc.Key; - var name = localDc.Name; - var type = localDc.Type; - var properties = localDc.Properties; - //var propRecurse = properties; + private static string GetSecret(SecretsPropertiesConfig data) + { + var secretProvider = SecretsManager.GetSecretProviderByKey(data.Provider); + if (secretProvider == null) return null; + var secret = secretProvider.GetSecret(data.Key); + if (secret != null) return (string)secret.Value; + Debug.LogMessage(LogEventLevel.Debug, + "Unable to retrieve secret {0}{1} - Make sure you've added it to the secrets provider", + data.Provider, data.Key); + return string.Empty; + } - var typeName = localDc.Type.ToLower(); + /// + /// Creates and returns a device instance based on the provided . + /// + /// This method attempts to create a device using the type specified in the + /// parameter. If the type corresponds to a registered factory method, the device is created and returned. If the + /// type is unrecognized or an exception occurs, the method logs the error and returns . + /// The configuration object containing the key, name, type, and properties required to create the device. + /// An instance of a device that implements , or if the device type is + /// not recognized or an error occurs during creation. + public static IKeyed GetDevice(DeviceConfig dc) + { + try + { + var localDc = new DeviceConfig(dc); - var jObject = properties as JObject; - if (jObject != null) - { - var jProp = jObject.Properties(); + var key = localDc.Key; + var name = localDc.Name; + var type = localDc.Type; + var properties = localDc.Properties; - CheckForSecrets(jProp); - } + var typeName = localDc.Type.ToLower(); + + if (properties is JObject jObject) + { + var jProp = jObject.Properties(); - Debug.LogMessage(LogEventLevel.Verbose, "typeName = {0}", typeName); - // Check for types that have been added by plugin dlls. - return !FactoryMethods.ContainsKey(typeName) ? null : FactoryMethods[typeName].FactoryMethod(localDc); + CheckForSecrets(jProp); } - catch (Exception ex) + + if (!FactoryMethods.TryGetValue(typeName, out var wrapper)) { - Debug.LogMessage(ex, "Exception occurred while creating device {0}: {1}", null, dc.Key, ex.Message); + Debug.LogWarning("Device type '{typeName}' not found in DeviceFactory", typeName); return null; } - } - /// - /// Prints the type names and associated metadata from the FactoryMethods collection. - /// - /// - public static void GetDeviceFactoryTypes(string filter) + Debug.LogInformation("Loading '{type}' from {assemblyName}", typeName, wrapper.Type.Assembly.FullName); + + // Check for types that have been added by plugin dlls. + return wrapper.FactoryMethod(localDc); + } + catch (Exception ex) { - var types = !string.IsNullOrEmpty(filter) - ? FactoryMethods.Where(k => k.Key.Contains(filter)).ToDictionary(k => k.Key, k => k.Value) - : FactoryMethods; + Debug.LogError(ex, "Exception occurred while creating device {0}: {1}", null, dc.Key, ex.Message); + return null; + } + } - CrestronConsole.ConsoleCommandResponse("Device Types:"); + /// + /// Displays a list of device factory types that match the specified filter. + /// + /// The method outputs the filtered list of device factory types to the console, including their + /// key, type, and description. If a type is not specified by the plugin, it will be displayed as "Not Specified by + /// Plugin." + /// A string used to filter the device factory types by their keys. If the filter is null or empty, all device + /// factory types are displayed. + public static void GetDeviceFactoryTypes(string filter) + { + var types = !string.IsNullOrEmpty(filter) + ? FactoryMethods.Where(k => k.Key.Contains(filter)).ToDictionary(k => k.Key, k => k.Value) + : FactoryMethods; - foreach (var type in types.OrderBy(t => t.Key)) - { - var description = type.Value.Description; - var Type = "Not Specified by Plugin"; + CrestronConsole.ConsoleCommandResponse("Device Types:"); - if (type.Value.Type != null) - { - Type = type.Value.Type.FullName; - } + foreach (var type in types.OrderBy(t => t.Key)) + { + var description = type.Value.Description; + var Type = "Not Specified by Plugin"; - CrestronConsole.ConsoleCommandResponse( - @"Type: '{0}' - Type: '{1}' - Description: {2}{3}", type.Key, Type, description, CrestronEnvironment.NewLine); + if (type.Value.Type != null) + { + Type = type.Value.Type.FullName; } + + CrestronConsole.ConsoleCommandResponse( + "Type: '{0}'\r\n" + + " Type: '{1}'\r\n" + + " Description: {2}{3}", type.Key, Type, description, CrestronEnvironment.NewLine); } + } - /// - /// Returns the device factory dictionary - /// - /// - /// - public static Dictionary GetDeviceFactoryDictionary(string filter) - { - return string.IsNullOrEmpty(filter) - ? FactoryMethods - : FactoryMethods.Where(k => k.Key.Contains(filter)).ToDictionary(k => k.Key, k => k.Value); - } + /// + /// Retrieves a dictionary of device factory wrappers, optionally filtered by a specified string. + /// + /// A string used to filter the dictionary keys. Only entries with keys containing the specified filter will be + /// included. If or empty, all entries are returned. + /// A dictionary where the keys are strings representing device identifiers and the values are instances. The dictionary may be empty if no entries match the filter. + public static Dictionary GetDeviceFactoryDictionary(string filter) + { + return string.IsNullOrEmpty(filter) + ? FactoryMethods + : FactoryMethods.Where(k => k.Key.Contains(filter)).ToDictionary(k => k.Key, k => k.Value); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Factory/IDeviceFactory.cs b/src/PepperDash.Essentials.Core/Factory/IDeviceFactory.cs index 9f7eec584..affbc4f1c 100644 --- a/src/PepperDash.Essentials.Core/Factory/IDeviceFactory.cs +++ b/src/PepperDash.Essentials.Core/Factory/IDeviceFactory.cs @@ -1,13 +1,29 @@ -namespace PepperDash.Essentials.Core +using PepperDash.Essentials.Core.Config; +using System; +using System.Collections.Generic; + +namespace PepperDash.Essentials.Core; + +/// +/// Defines a class that is capable of loading device types +/// +public interface IDeviceFactory { - /// - /// Defines a class that is capable of loading device types + /// + /// Gets the type of the factory associated with the current instance. /// - public interface IDeviceFactory - { - /// - /// Loads all the types to the DeviceFactory - /// - void LoadTypeFactories(); - } + Type FactoryType { get; } + + /// + /// Gets a list of type names associated with the current plugin. + /// + List TypeNames { get; } + + /// + /// Builds and returns an instance based on the provided configuration. + /// + /// The configuration settings used to initialize the device. This parameter cannot be null. + /// An instance configured according to the specified . + EssentialsDevice BuildDevice(DeviceConfig deviceConfig); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Factory/IProcessorExtensionDeviceFactory.cs b/src/PepperDash.Essentials.Core/Factory/IProcessorExtensionDeviceFactory.cs index a50ab16d9..5d016011e 100644 --- a/src/PepperDash.Essentials.Core/Factory/IProcessorExtensionDeviceFactory.cs +++ b/src/PepperDash.Essentials.Core/Factory/IProcessorExtensionDeviceFactory.cs @@ -4,13 +4,12 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public interface IProcessorExtensionDeviceFactory { - public interface IProcessorExtensionDeviceFactory - { - /// - /// Loads all the extension factories to the ProcessorExtensionDeviceFactory - /// - void LoadFactories(); - } + /// + /// Loads all the extension factories to the ProcessorExtensionDeviceFactory + /// + void LoadFactories(); } diff --git a/src/PepperDash.Essentials.Core/Factory/ProcessorExtensionDeviceFactory.cs b/src/PepperDash.Essentials.Core/Factory/ProcessorExtensionDeviceFactory.cs index b67dcf5b0..5a0822094 100644 --- a/src/PepperDash.Essentials.Core/Factory/ProcessorExtensionDeviceFactory.cs +++ b/src/PepperDash.Essentials.Core/Factory/ProcessorExtensionDeviceFactory.cs @@ -7,148 +7,146 @@ using System.Collections.Generic; using System.Linq; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; - public class ProcessorExtensionDeviceFactory - { - public ProcessorExtensionDeviceFactory() { - var assy = Assembly.GetExecutingAssembly(); - PluginLoader.SetEssentialsAssembly(assy.GetName().Name, assy); - var extensions = assy.GetTypes().Where(ct => typeof(IProcessorExtensionDeviceFactory) - .IsAssignableFrom(ct) && !ct.IsInterface && !ct.IsAbstract); +public class ProcessorExtensionDeviceFactory +{ + public ProcessorExtensionDeviceFactory() { + var assy = Assembly.GetExecutingAssembly(); + PluginLoader.AddLoadedAssembly(assy.GetName().Name, assy); + + var extensions = assy.GetTypes().Where(ct => typeof(IProcessorExtensionDeviceFactory) + .IsAssignableFrom(ct) && !ct.IsInterface && !ct.IsAbstract); - if (extensions != null ) + if (extensions != null ) + { + foreach ( var extension in extensions ) { - foreach ( var extension in extensions ) + try { - try - { - var factory = (IProcessorExtensionDeviceFactory)Activator.CreateInstance(extension); - factory.LoadFactories(); - } - catch( Exception e ) - { - Debug.LogMessage(LogEventLevel.Information, "Unable to load extension device: '{1}' ProcessorExtensionDeviceFactory: {0}", e, extension.Name); - } + var factory = (IProcessorExtensionDeviceFactory)Activator.CreateInstance(extension); + factory.LoadFactories(); + } + catch( Exception e ) + { + Debug.LogMessage(LogEventLevel.Information, "Unable to load extension device: '{1}' ProcessorExtensionDeviceFactory: {0}", e, extension.Name); } } } + } - /// - /// A dictionary of factory methods, keyed by config types, added by plugins. - /// These methods are looked up and called by GetDevice in this class. - /// - static Dictionary ProcessorExtensionFactoryMethods = - new Dictionary(StringComparer.OrdinalIgnoreCase); - + /// + /// A dictionary of factory methods, keyed by config types, added by plugins. + /// These methods are looked up and called by GetDevice in this class. + /// + static Dictionary ProcessorExtensionFactoryMethods = + new Dictionary(StringComparer.OrdinalIgnoreCase); - /// - /// Adds a plugin factory method - /// - /// - /// - public static void AddFactoryForType(string extensionName, Func method) - { - //Debug.LogMessage(LogEventLevel.Debug, "Adding factory method for type '{0}'", typeName); - ProcessorExtensionDeviceFactory.ProcessorExtensionFactoryMethods.Add(extensionName, new DeviceFactoryWrapper() { FactoryMethod = method }); - } - public static void AddFactoryForType(string extensionName, string description, Type Type, Func method) - { - //Debug.LogMessage(LogEventLevel.Debug, "Adding factory method for type '{0}'", typeName); + /// + /// Adds a plugin factory method + /// + /// + /// + public static void AddFactoryForType(string extensionName, Func method) + { + //Debug.LogMessage(LogEventLevel.Debug, "Adding factory method for type '{0}'", typeName); + ProcessorExtensionDeviceFactory.ProcessorExtensionFactoryMethods.Add(extensionName, new DeviceFactoryWrapper() { FactoryMethod = method }); + } - if (ProcessorExtensionFactoryMethods.ContainsKey(extensionName)) - { - Debug.LogMessage(LogEventLevel.Information, "Unable to add extension device: '{0}'. Already exists in ProcessorExtensionDeviceFactory", extensionName); - return; - } + public static void AddFactoryForType(string extensionName, string description, Type Type, Func method) + { + //Debug.LogMessage(LogEventLevel.Debug, "Adding factory method for type '{0}'", typeName); - var wrapper = new DeviceFactoryWrapper() { Type = Type, Description = description, FactoryMethod = method }; - ProcessorExtensionDeviceFactory.ProcessorExtensionFactoryMethods.Add(extensionName, wrapper); + if (ProcessorExtensionFactoryMethods.ContainsKey(extensionName)) + { + Debug.LogMessage(LogEventLevel.Information, "Unable to add extension device: '{0}'. Already exists in ProcessorExtensionDeviceFactory", extensionName); + return; } - private static void CheckForSecrets(IEnumerable obj) + var wrapper = new DeviceFactoryWrapper() { Type = Type, Description = description, FactoryMethod = method }; + ProcessorExtensionDeviceFactory.ProcessorExtensionFactoryMethods.Add(extensionName, wrapper); + } + + private static void CheckForSecrets(IEnumerable obj) + { + foreach (var prop in obj.Where(prop => prop.Value as Newtonsoft.Json.Linq.JObject != null)) { - foreach (var prop in obj.Where(prop => prop.Value as Newtonsoft.Json.Linq.JObject != null)) + if (prop.Name.ToLower() == "secret") { - if (prop.Name.ToLower() == "secret") - { - var secret = GetSecret(prop.Children().First().ToObject()); - //var secret = GetSecret(JsonConvert.DeserializeObject(prop.Children().First().ToString())); - prop.Parent.Replace(secret); - } - var recurseProp = prop.Value as Newtonsoft.Json.Linq.JObject; - if (recurseProp == null) return; - CheckForSecrets(recurseProp.Properties()); + var secret = GetSecret(prop.Children().First().ToObject()); + //var secret = GetSecret(JsonConvert.DeserializeObject(prop.Children().First().ToString())); + prop.Parent.Replace(secret); } + var recurseProp = prop.Value as Newtonsoft.Json.Linq.JObject; + if (recurseProp == null) return; + CheckForSecrets(recurseProp.Properties()); } + } - private static string GetSecret(SecretsPropertiesConfig data) - { - var secretProvider = SecretsManager.GetSecretProviderByKey(data.Provider); - if (secretProvider == null) return null; - var secret = secretProvider.GetSecret(data.Key); - if (secret != null) return (string)secret.Value; - Debug.LogMessage(LogEventLevel.Debug, - "Unable to retrieve secret {0}{1} - Make sure you've added it to the secrets provider", - data.Provider, data.Key); - return String.Empty; - } + private static string GetSecret(SecretsPropertiesConfig data) + { + var secretProvider = SecretsManager.GetSecretProviderByKey(data.Provider); + if (secretProvider == null) return null; + var secret = secretProvider.GetSecret(data.Key); + if (secret != null) return (string)secret.Value; + Debug.LogMessage(LogEventLevel.Debug, + "Unable to retrieve secret {0}{1} - Make sure you've added it to the secrets provider", + data.Provider, data.Key); + return String.Empty; + } - /// - /// The factory method for processor extension devices. Also iterates the Factory methods that have - /// been loaded from plugins - /// - /// - /// - public static IKeyed GetExtensionDevice(DeviceConfig dc) + /// + /// The factory method for processor extension devices. Also iterates the Factory methods that have + /// been loaded from plugins + /// + /// + /// + public static IKeyed GetExtensionDevice(DeviceConfig dc) + { + try { - try - { - Debug.LogMessage(LogEventLevel.Information, "Loading '{0}' from Essentials Core", dc.Type); + Debug.LogMessage(LogEventLevel.Information, "Loading '{0}' from Essentials Core", dc.Type); - var localDc = new DeviceConfig(dc); + var localDc = new DeviceConfig(dc); - var key = localDc.Key; - var name = localDc.Name; - var type = localDc.Type; - var properties = localDc.Properties; - //var propRecurse = properties; + var key = localDc.Key; + var name = localDc.Name; + var type = localDc.Type; + var properties = localDc.Properties; + //var propRecurse = properties; - var typeName = localDc.Type.ToLower(); - - var jObject = properties as Newtonsoft.Json.Linq.JObject; - if (jObject != null) - { - var jProp = jObject.Properties(); + var typeName = localDc.Type.ToLower(); - CheckForSecrets(jProp); - } + var jObject = properties as Newtonsoft.Json.Linq.JObject; + if (jObject != null) + { + var jProp = jObject.Properties(); - Debug.LogMessage(LogEventLevel.Verbose, "typeName = {0}", typeName); - // Check for types that have been added by plugin dlls. - return !ProcessorExtensionFactoryMethods.ContainsKey(typeName) ? null : ProcessorExtensionFactoryMethods[typeName].FactoryMethod(localDc); + CheckForSecrets(jProp); } - catch (Exception ex) - { - Debug.LogMessage(LogEventLevel.Information, "Exception occurred while creating device {0}: {1}", dc.Key, ex.Message); - Debug.LogMessage(LogEventLevel.Verbose, "{0}", ex.StackTrace); + Debug.LogMessage(LogEventLevel.Verbose, "typeName = {0}", typeName); + // Check for types that have been added by plugin dlls. + return !ProcessorExtensionFactoryMethods.ContainsKey(typeName) ? null : ProcessorExtensionFactoryMethods[typeName].FactoryMethod(localDc); + } + catch (Exception ex) + { + Debug.LogMessage(LogEventLevel.Information, "Exception occurred while creating device {0}: {1}", dc.Key, ex.Message); - if (ex.InnerException == null) - { - return null; - } + Debug.LogMessage(LogEventLevel.Verbose, "{0}", ex.StackTrace); - Debug.LogMessage(LogEventLevel.Information, "Inner exception while creating device {0}: {1}", dc.Key, - ex.InnerException.Message); - Debug.LogMessage(LogEventLevel.Verbose, "{0}", ex.InnerException.StackTrace); + if (ex.InnerException == null) + { return null; } - } + Debug.LogMessage(LogEventLevel.Information, "Inner exception while creating device {0}: {1}", dc.Key, + ex.InnerException.Message); + Debug.LogMessage(LogEventLevel.Verbose, "{0}", ex.InnerException.StackTrace); + return null; + } } } diff --git a/src/PepperDash.Essentials.Core/Factory/ReadyEventArgs.cs b/src/PepperDash.Essentials.Core/Factory/ReadyEventArgs.cs index 6ccc0600d..f432734bc 100644 --- a/src/PepperDash.Essentials.Core/Factory/ReadyEventArgs.cs +++ b/src/PepperDash.Essentials.Core/Factory/ReadyEventArgs.cs @@ -5,21 +5,20 @@ using Crestron.SimplSharp; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core -{ - public class IsReadyEventArgs : EventArgs - { - public bool IsReady { get; set; } +namespace PepperDash.Essentials.Core; - public IsReadyEventArgs(bool data) - { - IsReady = data; - } - } +public class IsReadyEventArgs : EventArgs +{ + public bool IsReady { get; set; } - public interface IHasReady + public IsReadyEventArgs(bool data) { - event EventHandler IsReadyEvent; - bool IsReady { get; } + IsReady = data; } } + +public interface IHasReady +{ + event EventHandler IsReadyEvent; + bool IsReady { get; } +} diff --git a/src/PepperDash.Essentials.Core/Feedbacks/BoolFeedback.cs b/src/PepperDash.Essentials.Core/Feedbacks/BoolFeedback.cs index 055ed5b6a..3aa75e22c 100644 --- a/src/PepperDash.Essentials.Core/Feedbacks/BoolFeedback.cs +++ b/src/PepperDash.Essentials.Core/Feedbacks/BoolFeedback.cs @@ -5,167 +5,165 @@ using Crestron.SimplSharp; using Crestron.SimplSharpPro; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// A Feedback whose output is derived from the return value of a provided Func. +/// +public class BoolFeedback : Feedback { /// - /// A Feedback whose output is derived from the return value of a provided Func. + /// Returns the current value of the feedback, derived from the ValueFunc. The ValueFunc is + /// evaluated whenever FireUpdate() is called /// - public class BoolFeedback : Feedback - { - /// - /// Returns the current value of the feedback, derived from the ValueFunc. The ValueFunc is - /// evaluated whenever FireUpdate() is called - /// - public override bool BoolValue { get { return _BoolValue; } } - bool _BoolValue; - - /// - /// Fake value to be used in test mode - /// - public bool TestValue { get; private set; } - - /// - /// Func that evaluates on FireUpdate - /// - public Func ValueFunc { get; private set; } - - List LinkedInputSigs = new List(); - List LinkedComplementInputSigs = new List(); - - List LinkedCrestronFeedbacks = new List(); - - /// - /// Creates the feedback with the Func as described. - /// - /// - /// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge, - /// it will NOT reflect an actual value from a device until has been called - /// - /// Delegate to invoke when this feedback needs to be updated - public BoolFeedback(Func valueFunc) - : this(null, valueFunc) - { - } + public override bool BoolValue { get { return _BoolValue; } } + bool _BoolValue; - /// - /// Creates the feedback with the Func as described. - /// - /// - /// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge, - /// it will NOT reflect an actual value from a device until has been called - /// - /// Key to find this Feedback - /// Delegate to invoke when this feedback needs to be updated - public BoolFeedback(string key, Func valueFunc) - : base(key) - { - ValueFunc = valueFunc; - } + /// + /// Fake value to be used in test mode + /// + public bool TestValue { get; private set; } - public void SetValueFunc(Func newFunc) - { - ValueFunc = newFunc; - } + /// + /// Func that evaluates on FireUpdate + /// + public Func ValueFunc { get; private set; } - public override void FireUpdate() - { - bool newValue = InTestMode ? TestValue : ValueFunc.Invoke(); - if (newValue != _BoolValue) - { - _BoolValue = newValue; - LinkedInputSigs.ForEach(s => UpdateSig(s)); - LinkedComplementInputSigs.ForEach(s => UpdateComplementSig(s)); - OnOutputChange(newValue); - } - } + List LinkedInputSigs = new List(); + List LinkedComplementInputSigs = new List(); - /// - /// Links an input sig - /// - /// - public void LinkInputSig(BoolInputSig sig) - { - LinkedInputSigs.Add(sig); - UpdateSig(sig); - } + List LinkedCrestronFeedbacks = new List(); - /// - /// Unlinks an inputs sig - /// - /// - public void UnlinkInputSig(BoolInputSig sig) - { - LinkedInputSigs.Remove(sig); - } + /// + /// Creates the feedback with the Func as described. + /// + /// + /// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge, + /// it will NOT reflect an actual value from a device until has been called + /// + /// Delegate to invoke when this feedback needs to be updated + public BoolFeedback(Func valueFunc) + : this(null, valueFunc) + { + } - /// - /// Links an input sig to the complement value - /// - /// - public void LinkComplementInputSig(BoolInputSig sig) - { - LinkedComplementInputSigs.Add(sig); - UpdateComplementSig(sig); - } + /// + /// Creates the feedback with the Func as described. + /// + /// + /// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge, + /// it will NOT reflect an actual value from a device until has been called + /// + /// Key to find this Feedback + /// Delegate to invoke when this feedback needs to be updated + public BoolFeedback(string key, Func valueFunc) + : base(key) + { + ValueFunc = valueFunc; + } - /// - /// Unlinks an input sig to the complement value - /// - /// - public void UnlinkComplementInputSig(BoolInputSig sig) - { - LinkedComplementInputSigs.Remove(sig); - } + public void SetValueFunc(Func newFunc) + { + ValueFunc = newFunc; + } - /// - /// Links a Crestron Feedback object - /// - /// - public void LinkCrestronFeedback(Crestron.SimplSharpPro.DeviceSupport.Feedback feedback) + public override void FireUpdate() + { + bool newValue = InTestMode ? TestValue : ValueFunc.Invoke(); + if (newValue != _BoolValue) { - LinkedCrestronFeedbacks.Add(feedback); - UpdateCrestronFeedback(feedback); + _BoolValue = newValue; + LinkedInputSigs.ForEach(s => UpdateSig(s)); + LinkedComplementInputSigs.ForEach(s => UpdateComplementSig(s)); + OnOutputChange(newValue); } + } - /// - /// - /// - /// - public void UnlinkCrestronFeedback(Crestron.SimplSharpPro.DeviceSupport.Feedback feedback) - { - LinkedCrestronFeedbacks.Remove(feedback); - } + /// + /// Links an input sig + /// + /// + public void LinkInputSig(BoolInputSig sig) + { + LinkedInputSigs.Add(sig); + UpdateSig(sig); + } - public override string ToString() - { - return (InTestMode ? "TEST -- " : "") + BoolValue.ToString(); - } + /// + /// Unlinks an inputs sig + /// + /// + public void UnlinkInputSig(BoolInputSig sig) + { + LinkedInputSigs.Remove(sig); + } - /// - /// Puts this in test mode, sets the test value and fires an update. - /// - /// - public void SetTestValue(bool value) - { - TestValue = value; - InTestMode = true; - FireUpdate(); - } + /// + /// Links an input sig to the complement value + /// + /// + public void LinkComplementInputSig(BoolInputSig sig) + { + LinkedComplementInputSigs.Add(sig); + UpdateComplementSig(sig); + } - void UpdateSig(BoolInputSig sig) - { - sig.BoolValue = _BoolValue; - } + /// + /// Unlinks an input sig to the complement value + /// + /// + public void UnlinkComplementInputSig(BoolInputSig sig) + { + LinkedComplementInputSigs.Remove(sig); + } - void UpdateComplementSig(BoolInputSig sig) - { - sig.BoolValue = !_BoolValue; - } + /// + /// Links a Crestron Feedback object + /// + /// + public void LinkCrestronFeedback(Crestron.SimplSharpPro.DeviceSupport.Feedback feedback) + { + LinkedCrestronFeedbacks.Add(feedback); + UpdateCrestronFeedback(feedback); + } - void UpdateCrestronFeedback(Crestron.SimplSharpPro.DeviceSupport.Feedback feedback) - { - feedback.State = _BoolValue; - } + /// + /// + /// + /// + public void UnlinkCrestronFeedback(Crestron.SimplSharpPro.DeviceSupport.Feedback feedback) + { + LinkedCrestronFeedbacks.Remove(feedback); } + public override string ToString() + { + return (InTestMode ? "TEST -- " : "") + BoolValue.ToString(); + } + + /// + /// Puts this in test mode, sets the test value and fires an update. + /// + /// + public void SetTestValue(bool value) + { + TestValue = value; + InTestMode = true; + FireUpdate(); + } + + void UpdateSig(BoolInputSig sig) + { + sig.BoolValue = _BoolValue; + } + + void UpdateComplementSig(BoolInputSig sig) + { + sig.BoolValue = !_BoolValue; + } + + void UpdateCrestronFeedback(Crestron.SimplSharpPro.DeviceSupport.Feedback feedback) + { + feedback.State = _BoolValue; + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Feedbacks/BoolFeedbackOneShot.cs b/src/PepperDash.Essentials.Core/Feedbacks/BoolFeedbackOneShot.cs index cc1835690..05d50a380 100644 --- a/src/PepperDash.Essentials.Core/Feedbacks/BoolFeedbackOneShot.cs +++ b/src/PepperDash.Essentials.Core/Feedbacks/BoolFeedbackOneShot.cs @@ -4,8 +4,8 @@ using System.Text; using Crestron.SimplSharp; using Crestron.SimplSharpPro; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public class BoolFeedbackPulse { public uint TimeoutMs { get; set; } @@ -65,5 +65,4 @@ public void Cancel() if(Timer != null) Timer.Reset(0); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Feedbacks/BoolFeedbackPulseExtender.cs b/src/PepperDash.Essentials.Core/Feedbacks/BoolFeedbackPulseExtender.cs index 53a5e559d..f4467411a 100644 --- a/src/PepperDash.Essentials.Core/Feedbacks/BoolFeedbackPulseExtender.cs +++ b/src/PepperDash.Essentials.Core/Feedbacks/BoolFeedbackPulseExtender.cs @@ -4,8 +4,8 @@ using System.Text; using Crestron.SimplSharp; using Crestron.SimplSharpPro; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// A class that wraps a BoolFeedback with logic that extends it's true state for /// a time period after the value goes false. @@ -74,5 +74,4 @@ void ClearFeedback() Feedback.FireUpdate(); Timer = null; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Feedbacks/BoolOutputLogicals.cs b/src/PepperDash.Essentials.Core/Feedbacks/BoolOutputLogicals.cs index a8dae7b88..67ba435a8 100644 --- a/src/PepperDash.Essentials.Core/Feedbacks/BoolOutputLogicals.cs +++ b/src/PepperDash.Essentials.Core/Feedbacks/BoolOutputLogicals.cs @@ -5,8 +5,8 @@ using Crestron.SimplSharp; using Crestron.SimplSharpPro; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public abstract class BoolFeedbackLogic @@ -71,7 +71,7 @@ public void RemoveOutputsIn(List outputs) public void ClearOutputs() { OutputsIn.Clear(); - Evaluate(); + Evaluate(); } void AnyInput_OutputChange(object sender, EventArgs e) @@ -133,5 +133,4 @@ protected override void Evaluate() ComputedValue = newValue; Output.FireUpdate(); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Feedbacks/FeedbackBase.cs b/src/PepperDash.Essentials.Core/Feedbacks/FeedbackBase.cs index c3aac50b1..90d9e0142 100644 --- a/src/PepperDash.Essentials.Core/Feedbacks/FeedbackBase.cs +++ b/src/PepperDash.Essentials.Core/Feedbacks/FeedbackBase.cs @@ -7,18 +7,18 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public abstract class Feedback : IKeyed { public event EventHandler OutputChange; - public string Key { get; private set; } + public string Key { get; private set; } public virtual bool BoolValue { get { return false; } } public virtual int IntValue { get { return 0; } } public virtual string StringValue { get { return ""; } } - public virtual string SerialValue { get { return ""; } } + public virtual string SerialValue { get { return ""; } } /// /// Feedbacks can be put into test mode for simulation of events without real data. @@ -34,13 +34,13 @@ protected Feedback() { } - protected Feedback(string key) - { - if (key == null) - Key = ""; - else - Key = key; - } + protected Feedback(string key) + { + if (key == null) + Key = ""; + else + Key = key; + } @@ -66,28 +66,27 @@ public void InvokeFireUpdate() CrestronInvoke.BeginInvoke(o => FireUpdate()); } - ///// - ///// Helper method that fires event. Use this intstead of calling OutputChange - ///// - //protected void OnOutputChange() - //{ - // if (OutputChange != null) OutputChange(this, EventArgs.Empty); - //} - - protected void OnOutputChange(bool value) - { - if (OutputChange != null) OutputChange(this, new FeedbackEventArgs(value)); - } - - protected void OnOutputChange(int value) - { - if (OutputChange != null) OutputChange(this, new FeedbackEventArgs(value)); - } - - - protected void OnOutputChange(string value) - { - if (OutputChange != null) OutputChange(this, new FeedbackEventArgs(value)); - } - } -} \ No newline at end of file + ///// + ///// Helper method that fires event. Use this intstead of calling OutputChange + ///// + //protected void OnOutputChange() + //{ + // if (OutputChange != null) OutputChange(this, EventArgs.Empty); + //} + + protected void OnOutputChange(bool value) + { + if (OutputChange != null) OutputChange(this, new FeedbackEventArgs(value)); + } + + protected void OnOutputChange(int value) + { + if (OutputChange != null) OutputChange(this, new FeedbackEventArgs(value)); + } + + + protected void OnOutputChange(string value) + { + if (OutputChange != null) OutputChange(this, new FeedbackEventArgs(value)); + } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Feedbacks/FeedbackCollection.cs b/src/PepperDash.Essentials.Core/Feedbacks/FeedbackCollection.cs index ed7517da4..32b1abfb8 100644 --- a/src/PepperDash.Essentials.Core/Feedbacks/FeedbackCollection.cs +++ b/src/PepperDash.Essentials.Core/Feedbacks/FeedbackCollection.cs @@ -4,22 +4,21 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Basically a List , with an indexer to find feedbacks by key name +/// +public class FeedbackCollection : List where T : Feedback { /// - /// Basically a List , with an indexer to find feedbacks by key name + /// Case-insensitive port lookup linked to feedbacks' keys /// - public class FeedbackCollection : List where T : Feedback + public T this[string key] { - /// - /// Case-insensitive port lookup linked to feedbacks' keys - /// - public T this[string key] + get { - get - { - return this.FirstOrDefault(i => i.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); - } + return this.FirstOrDefault(i => i.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Feedbacks/FeedbackEventArgs.cs b/src/PepperDash.Essentials.Core/Feedbacks/FeedbackEventArgs.cs index 9a7f5c29d..8f8a5170b 100644 --- a/src/PepperDash.Essentials.Core/Feedbacks/FeedbackEventArgs.cs +++ b/src/PepperDash.Essentials.Core/Feedbacks/FeedbackEventArgs.cs @@ -4,45 +4,44 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public class FeedbackEventArgs : EventArgs { - public class FeedbackEventArgs : EventArgs + public bool BoolValue { get; private set; } + public int IntValue { get; private set; } + public ushort UShortValue { - public bool BoolValue { get; private set; } - public int IntValue { get; private set; } - public ushort UShortValue - { - get - { - return (ushort)IntValue; - } - } - public string StringValue { get; private set; } - public eFeedbackEventType Type { get; private set; } - - public FeedbackEventArgs(bool value) + get { - BoolValue = value; - Type = eFeedbackEventType.TypeBool; + return (ushort)IntValue; } + } + public string StringValue { get; private set; } + public eFeedbackEventType Type { get; private set; } - public FeedbackEventArgs(int value) - { - IntValue = value; - Type = eFeedbackEventType.TypeInt; - } + public FeedbackEventArgs(bool value) + { + BoolValue = value; + Type = eFeedbackEventType.TypeBool; + } - public FeedbackEventArgs(string value) - { - StringValue = value; - Type = eFeedbackEventType.TypeString; - } + public FeedbackEventArgs(int value) + { + IntValue = value; + Type = eFeedbackEventType.TypeInt; } - public enum eFeedbackEventType + public FeedbackEventArgs(string value) { - TypeBool, - TypeInt, - TypeString + StringValue = value; + Type = eFeedbackEventType.TypeString; } +} + +public enum eFeedbackEventType +{ + TypeBool, + TypeInt, + TypeString } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Feedbacks/IntFeedback.cs b/src/PepperDash.Essentials.Core/Feedbacks/IntFeedback.cs index 53bae09aa..1cf7a3bd0 100644 --- a/src/PepperDash.Essentials.Core/Feedbacks/IntFeedback.cs +++ b/src/PepperDash.Essentials.Core/Feedbacks/IntFeedback.cs @@ -5,99 +5,98 @@ using Crestron.SimplSharp; using Crestron.SimplSharpPro; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public class IntFeedback : Feedback { - public class IntFeedback : Feedback - { - public override int IntValue { get { return _IntValue; } } // ValueFunc.Invoke(); } } - int _IntValue; - public ushort UShortValue { get { return (ushort)_IntValue; } } + public override int IntValue { get { return _IntValue; } } // ValueFunc.Invoke(); } } + int _IntValue; + public ushort UShortValue { get { return (ushort)_IntValue; } } - //public override eCueType Type { get { return eCueType.Int; } } + //public override eCueType Type { get { return eCueType.Int; } } - public int TestValue { get; private set; } + public int TestValue { get; private set; } - /// - /// Func evaluated on FireUpdate - /// - Func ValueFunc; - List LinkedInputSigs = new List(); + /// + /// Func evaluated on FireUpdate + /// + Func ValueFunc; + List LinkedInputSigs = new List(); - /// - /// Creates the feedback with the Func as described. - /// - /// - /// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge, - /// it will NOT reflect an actual value from a device until has been called - /// - /// Delegate to invoke when this feedback needs to be updated - public IntFeedback(Func valueFunc) - : this(null, valueFunc) - { - } + /// + /// Creates the feedback with the Func as described. + /// + /// + /// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge, + /// it will NOT reflect an actual value from a device until has been called + /// + /// Delegate to invoke when this feedback needs to be updated + public IntFeedback(Func valueFunc) + : this(null, valueFunc) + { + } - /// - /// Creates the feedback with the Func as described. - /// - /// - /// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge, - /// it will NOT reflect an actual value from a device until has been called - /// - /// Key to find this Feedback - /// Delegate to invoke when this feedback needs to be updated - public IntFeedback(string key, Func valueFunc) - : base(key) - { - ValueFunc = valueFunc; - } + /// + /// Creates the feedback with the Func as described. + /// + /// + /// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge, + /// it will NOT reflect an actual value from a device until has been called + /// + /// Key to find this Feedback + /// Delegate to invoke when this feedback needs to be updated + public IntFeedback(string key, Func valueFunc) + : base(key) + { + ValueFunc = valueFunc; + } - public void SetValueFunc(Func newFunc) - { - ValueFunc = newFunc; - } + public void SetValueFunc(Func newFunc) + { + ValueFunc = newFunc; + } - public override void FireUpdate() + public override void FireUpdate() + { + var newValue = InTestMode ? TestValue : ValueFunc.Invoke(); + if (newValue != _IntValue) { - var newValue = InTestMode ? TestValue : ValueFunc.Invoke(); - if (newValue != _IntValue) - { - _IntValue = newValue; - LinkedInputSigs.ForEach(s => UpdateSig(s)); - OnOutputChange(newValue); - } + _IntValue = newValue; + LinkedInputSigs.ForEach(s => UpdateSig(s)); + OnOutputChange(newValue); } + } - public void LinkInputSig(UShortInputSig sig) - { - LinkedInputSigs.Add(sig); - UpdateSig(sig); - } + public void LinkInputSig(UShortInputSig sig) + { + LinkedInputSigs.Add(sig); + UpdateSig(sig); + } - public void UnlinkInputSig(UShortInputSig sig) - { - LinkedInputSigs.Remove(sig); - } + public void UnlinkInputSig(UShortInputSig sig) + { + LinkedInputSigs.Remove(sig); + } - public override string ToString() - { - return (InTestMode ? "TEST -- " : "") + IntValue.ToString(); - } + public override string ToString() + { + return (InTestMode ? "TEST -- " : "") + IntValue.ToString(); + } - /// - /// Puts this in test mode, sets the test value and fires an update. - /// - /// - public void SetTestValue(int value) - { - TestValue = value; - InTestMode = true; - FireUpdate(); - } + /// + /// Puts this in test mode, sets the test value and fires an update. + /// + /// + public void SetTestValue(int value) + { + TestValue = value; + InTestMode = true; + FireUpdate(); + } - void UpdateSig(UShortInputSig sig) - { - sig.UShortValue = UShortValue; - } + void UpdateSig(UShortInputSig sig) + { + sig.UShortValue = UShortValue; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Feedbacks/SerialFeedback.cs b/src/PepperDash.Essentials.Core/Feedbacks/SerialFeedback.cs index bbf135dcc..6fe0be62b 100644 --- a/src/PepperDash.Essentials.Core/Feedbacks/SerialFeedback.cs +++ b/src/PepperDash.Essentials.Core/Feedbacks/SerialFeedback.cs @@ -5,82 +5,81 @@ using Crestron.SimplSharp; using Crestron.SimplSharpPro; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// To be used for serial data feedback where the event chain / asynchronicity must be maintained +/// and calculating the value based on a Func when it is needed will not suffice. +/// +public class SerialFeedback : Feedback { - /// - /// To be used for serial data feedback where the event chain / asynchronicity must be maintained - /// and calculating the value based on a Func when it is needed will not suffice. - /// - public class SerialFeedback : Feedback - { - public override string SerialValue { get { return _SerialValue; } } - string _SerialValue; + public override string SerialValue { get { return _SerialValue; } } + string _SerialValue; - //public override eCueType Type { get { return eCueType.Serial; } } + //public override eCueType Type { get { return eCueType.Serial; } } - /// - /// Used in testing. Set/Clear functions - /// - public string TestValue { get; private set; } + /// + /// Used in testing. Set/Clear functions + /// + public string TestValue { get; private set; } - List LinkedInputSigs = new List(); + List LinkedInputSigs = new List(); - public SerialFeedback() - { - } + public SerialFeedback() + { + } - public SerialFeedback(string key) - : base(key) - { - } + public SerialFeedback(string key) + : base(key) + { + } - public override void FireUpdate() - { - throw new NotImplementedException("This feedback type does not use Funcs"); - } + public override void FireUpdate() + { + throw new NotImplementedException("This feedback type does not use Funcs"); + } - public void FireUpdate(string newValue) - { - _SerialValue = newValue; - LinkedInputSigs.ForEach(s => UpdateSig(s, newValue)); - OnOutputChange(newValue); - } + public void FireUpdate(string newValue) + { + _SerialValue = newValue; + LinkedInputSigs.ForEach(s => UpdateSig(s, newValue)); + OnOutputChange(newValue); + } - public void LinkInputSig(StringInputSig sig) - { - LinkedInputSigs.Add(sig); - UpdateSig(sig); - } + public void LinkInputSig(StringInputSig sig) + { + LinkedInputSigs.Add(sig); + UpdateSig(sig); + } - public void UnlinkInputSig(StringInputSig sig) - { - LinkedInputSigs.Remove(sig); - } + public void UnlinkInputSig(StringInputSig sig) + { + LinkedInputSigs.Remove(sig); + } - public override string ToString() - { - return (InTestMode ? "TEST -- " : "") + SerialValue; - } + public override string ToString() + { + return (InTestMode ? "TEST -- " : "") + SerialValue; + } - /// - /// Puts this in test mode, sets the test value and fires an update. - /// - /// - public void SetTestValue(string value) - { - TestValue = value; - InTestMode = true; - FireUpdate(TestValue); - } + /// + /// Puts this in test mode, sets the test value and fires an update. + /// + /// + public void SetTestValue(string value) + { + TestValue = value; + InTestMode = true; + FireUpdate(TestValue); + } - void UpdateSig(StringInputSig sig) - { - sig.StringValue = _SerialValue; - } + void UpdateSig(StringInputSig sig) + { + sig.StringValue = _SerialValue; + } - void UpdateSig(StringInputSig sig, string value) - { - sig.StringValue = value; - } + void UpdateSig(StringInputSig sig, string value) + { + sig.StringValue = value; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Feedbacks/StringFeedback.cs b/src/PepperDash.Essentials.Core/Feedbacks/StringFeedback.cs index fb5cccb55..2eb184147 100644 --- a/src/PepperDash.Essentials.Core/Feedbacks/StringFeedback.cs +++ b/src/PepperDash.Essentials.Core/Feedbacks/StringFeedback.cs @@ -5,99 +5,98 @@ using Crestron.SimplSharp; using Crestron.SimplSharpPro; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; - public class StringFeedback : Feedback - { - public override string StringValue { get { return _StringValue; } } // ValueFunc.Invoke(); } } - string _StringValue; - /// - /// Used in testing. Set/Clear functions - /// - public string TestValue { get; private set; } +public class StringFeedback : Feedback +{ + public override string StringValue { get { return _StringValue; } } // ValueFunc.Invoke(); } } + string _StringValue; - /// - /// Evaluated on FireUpdate - /// - public Func ValueFunc { get; private set; } - List LinkedInputSigs = new List(); + /// + /// Used in testing. Set/Clear functions + /// + public string TestValue { get; private set; } - /// - /// Creates the feedback with the Func as described. - /// - /// - /// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge, - /// it will NOT reflect an actual value from a device until has been called - /// - /// Delegate to invoke when this feedback needs to be updated - public StringFeedback(Func valueFunc) - : this(null, valueFunc) - { - } + /// + /// Evaluated on FireUpdate + /// + public Func ValueFunc { get; private set; } + List LinkedInputSigs = new List(); - /// - /// Creates the feedback with the Func as described. - /// - /// - /// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge, - /// it will NOT reflect an actual value from a device until has been called - /// - /// Key to find this Feedback - /// Delegate to invoke when this feedback needs to be updated - public StringFeedback(string key, Func valueFunc) - : base(key) - { - ValueFunc = valueFunc; - } + /// + /// Creates the feedback with the Func as described. + /// + /// + /// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge, + /// it will NOT reflect an actual value from a device until has been called + /// + /// Delegate to invoke when this feedback needs to be updated + public StringFeedback(Func valueFunc) + : this(null, valueFunc) + { + } - public void SetValueFunc(Func newFunc) - { - ValueFunc = newFunc; - } + /// + /// Creates the feedback with the Func as described. + /// + /// + /// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge, + /// it will NOT reflect an actual value from a device until has been called + /// + /// Key to find this Feedback + /// Delegate to invoke when this feedback needs to be updated + public StringFeedback(string key, Func valueFunc) + : base(key) + { + ValueFunc = valueFunc; + } - public override void FireUpdate() - { - var newValue = InTestMode ? TestValue : ValueFunc.Invoke(); - if (newValue != _StringValue) - { - _StringValue = newValue; - LinkedInputSigs.ForEach(s => UpdateSig(s)); - OnOutputChange(newValue); - } - } + public void SetValueFunc(Func newFunc) + { + ValueFunc = newFunc; + } - public void LinkInputSig(StringInputSig sig) + public override void FireUpdate() + { + var newValue = InTestMode ? TestValue : ValueFunc.Invoke(); + if (newValue != _StringValue) { - LinkedInputSigs.Add(sig); - UpdateSig(sig); + _StringValue = newValue; + LinkedInputSigs.ForEach(s => UpdateSig(s)); + OnOutputChange(newValue); } + } - public void UnlinkInputSig(StringInputSig sig) - { - LinkedInputSigs.Remove(sig); - } + public void LinkInputSig(StringInputSig sig) + { + LinkedInputSigs.Add(sig); + UpdateSig(sig); + } - public override string ToString() - { - return (InTestMode ? "TEST -- " : "") + StringValue; - } + public void UnlinkInputSig(StringInputSig sig) + { + LinkedInputSigs.Remove(sig); + } - /// - /// Puts this in test mode, sets the test value and fires an update. - /// - /// - public void SetTestValue(string value) - { - TestValue = value; - InTestMode = true; - FireUpdate(); - } + public override string ToString() + { + return (InTestMode ? "TEST -- " : "") + StringValue; + } - void UpdateSig(StringInputSig sig) - { - sig.StringValue = _StringValue; - } + /// + /// Puts this in test mode, sets the test value and fires an update. + /// + /// + public void SetTestValue(string value) + { + TestValue = value; + InTestMode = true; + FireUpdate(); + } + + void UpdateSig(StringInputSig sig) + { + sig.StringValue = _StringValue; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/File/FileIO.cs b/src/PepperDash.Essentials.Core/File/FileIO.cs index 24bdf8d12..98ad787f8 100644 --- a/src/PepperDash.Essentials.Core/File/FileIO.cs +++ b/src/PepperDash.Essentials.Core/File/FileIO.cs @@ -8,8 +8,8 @@ using Crestron.SimplSharpPro.CrestronThread; using Serilog.Events; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public static class FileIO { @@ -22,37 +22,37 @@ public static class FileIO /// /// /// - public static FileInfo[] GetFiles(string fileName) + public static FileInfo[] GetFiles(string fileName) + { + string fullFilePath = Global.FilePathPrefix + fileName; + DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(fullFilePath)); + var files = dirInfo.GetFiles(Path.GetFileName(fullFilePath)); + Debug.LogMessage(LogEventLevel.Information, "FileIO found: {0}, {1}", files.Count(), fullFilePath); + if (files.Count() > 0) { - string fullFilePath = Global.FilePathPrefix + fileName; - DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(fullFilePath)); - var files = dirInfo.GetFiles(Path.GetFileName(fullFilePath)); - Debug.LogMessage(LogEventLevel.Information, "FileIO found: {0}, {1}", files.Count(), fullFilePath); - if (files.Count() > 0) - { - return files; - } - else - { - return null; - } + return files; } - - public static FileInfo GetFile(string fileName) + else + { + return null; + } + } + + public static FileInfo GetFile(string fileName) + { + string fullFilePath = Global.FilePathPrefix + fileName; + DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(fullFilePath)); + var files = dirInfo.GetFiles(Path.GetFileName(fullFilePath)); + Debug.LogMessage(LogEventLevel.Information, "FileIO found: {0}, {1}", files.Count(), fullFilePath); + if (files.Count() > 0) { - string fullFilePath = Global.FilePathPrefix + fileName; - DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(fullFilePath)); - var files = dirInfo.GetFiles(Path.GetFileName(fullFilePath)); - Debug.LogMessage(LogEventLevel.Information, "FileIO found: {0}, {1}", files.Count(), fullFilePath); - if (files.Count() > 0) - { - return files.FirstOrDefault(); - } - else - { - return null; - } + return files.FirstOrDefault(); } + else + { + return null; + } + } /// @@ -73,12 +73,12 @@ public static string ReadDataFromFile(string fileName) } } - /// - /// Get the data with fileInfo object - /// - /// - /// - public static string ReadDataFromFile(FileInfo file) + /// + /// Get the data with fileInfo object + /// + /// + /// + public static string ReadDataFromFile(FileInfo file) { try { @@ -200,7 +200,7 @@ private static void _ReadDataFromFileASync(FileInfo file) public static void WriteDataToFile(string data, string filePath) { Thread _WriteFileThread; - _WriteFileThread = new Thread((O) => _WriteFileMethod(data, Global.FilePathPrefix + "/" + filePath), null, Thread.eThreadStartOptions.CreateSuspended); + _WriteFileThread = new Thread((O) => _WriteFileMethod(data, Global.FilePathPrefix + "/" + filePath), null, Thread.eThreadStartOptions.CreateSuspended); _WriteFileThread.Priority = Thread.eThreadPriority.LowestPriority; _WriteFileThread.Start(); Debug.LogMessage(LogEventLevel.Information, "New WriteFile Thread"); @@ -216,7 +216,7 @@ static object _WriteFileMethod(string data, string filePath) if (fileLock.TryEnter()) { - using (StreamWriter sw = new StreamWriter(filePath)) + using (StreamWriter sw = new StreamWriter(filePath)) { sw.Write(data); sw.Flush(); @@ -273,5 +273,4 @@ public class FileEventArgs public FileEventArgs(string data) { Data = data; } public string Data { get; private set; } // readonly - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs b/src/PepperDash.Essentials.Core/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs index 9a2667f0e..2f0df0b64 100644 --- a/src/PepperDash.Essentials.Core/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs +++ b/src/PepperDash.Essentials.Core/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs @@ -16,1591 +16,1570 @@ using System.Linq; using System.Text; -namespace PepperDash.Essentials.Core.Fusion +namespace PepperDash.Essentials.Core.Fusion; + +public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupancyStatusProvider { - public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupancyStatusProvider - { - private readonly EssentialsHuddleSpaceRoomFusionRoomJoinMap JoinMap; + private readonly EssentialsHuddleSpaceRoomFusionRoomJoinMap JoinMap; - private const string RemoteOccupancyXml = "Local{0}"; - private readonly bool _guidFileExists; + private const string RemoteOccupancyXml = "Local{0}"; + private readonly bool _guidFileExists; - private readonly Dictionary _sourceToFeedbackSigs = - new Dictionary(); + private readonly Dictionary _sourceToFeedbackSigs = + new Dictionary(); - protected StringSigData CurrentRoomSourceNameSig; + protected StringSigData CurrentRoomSourceNameSig; - private readonly FusionCustomPropertiesBridge CustomPropertiesBridge = new FusionCustomPropertiesBridge(); - protected FusionOccupancySensorAsset FusionOccSensor; - private readonly FusionRemoteOccupancySensor FusionRemoteOccSensor; + private readonly FusionCustomPropertiesBridge CustomPropertiesBridge = new FusionCustomPropertiesBridge(); + protected FusionOccupancySensorAsset FusionOccSensor; + private readonly FusionRemoteOccupancySensor FusionRemoteOccSensor; - protected FusionRoom FusionRoom; - protected Dictionary FusionStaticAssets; - private readonly long PushNotificationTimeout = 5000; - private readonly IEssentialsRoom Room; - private readonly long SchedulePollInterval = 300000; + protected FusionRoom FusionRoom; + protected Dictionary FusionStaticAssets; + private readonly long PushNotificationTimeout = 5000; + private readonly IEssentialsRoom Room; + private readonly long SchedulePollInterval = 300000; - private Event _currentMeeting; - private RoomSchedule _currentSchedule; - private CTimer _dailyTimeRequestTimer; - private StatusMonitorCollection _errorMessageRollUp; + private Event _currentMeeting; + private RoomSchedule _currentSchedule; + private CTimer _dailyTimeRequestTimer; + private StatusMonitorCollection _errorMessageRollUp; - private FusionRoomGuids _guiDs; - private uint _ipId; + private FusionRoomGuids _guiDs; + private uint _ipId; - private bool _isRegisteredForSchedulePushNotifications; - private Event _nextMeeting; + private bool _isRegisteredForSchedulePushNotifications; + private Event _nextMeeting; - private CTimer _pollTimer; + private CTimer _pollTimer; - private CTimer _pushNotificationTimer; + private CTimer _pushNotificationTimer; - private string _roomOccupancyRemoteString; + private string _roomOccupancyRemoteString; - #region System Info Sigs + #region System Info Sigs - //StringSigData SystemName; - //StringSigData Model; - //StringSigData SerialNumber; - //StringSigData Uptime; + //StringSigData SystemName; + //StringSigData Model; + //StringSigData SerialNumber; + //StringSigData Uptime; - #endregion + #endregion - #region Processor Info Sigs + #region Processor Info Sigs - private readonly StringSigData[] _program = new StringSigData[10]; - private StringSigData _dns1; - private StringSigData _dns2; - private StringSigData _domain; - private StringSigData _firmware; - private StringSigData _gateway; - private StringSigData _hostname; - private StringSigData _ip1; - private StringSigData _ip2; - private StringSigData _mac1; - private StringSigData _mac2; - private StringSigData _netMask1; - private StringSigData _netMask2; + private readonly StringSigData[] _program = new StringSigData[10]; + private StringSigData _dns1; + private StringSigData _dns2; + private StringSigData _domain; + private StringSigData _firmware; + private StringSigData _gateway; + private StringSigData _hostname; + private StringSigData _ip1; + private StringSigData _ip2; + private StringSigData _mac1; + private StringSigData _mac2; + private StringSigData _netMask1; + private StringSigData _netMask2; - #endregion + #endregion - #region Default Display Source Sigs + #region Default Display Source Sigs - private readonly BooleanSigData[] _source = new BooleanSigData[10]; + private readonly BooleanSigData[] _source = new BooleanSigData[10]; - #endregion + #endregion - public EssentialsHuddleSpaceFusionSystemControllerBase(IEssentialsRoom room, uint ipId, string joinMapKey) - : base(room.Key + "-fusion") + public EssentialsHuddleSpaceFusionSystemControllerBase(IEssentialsRoom room, uint ipId, string joinMapKey) + : base(room.Key + "-fusion") + { + try { - try - { - JoinMap = new EssentialsHuddleSpaceRoomFusionRoomJoinMap(1); + JoinMap = new EssentialsHuddleSpaceRoomFusionRoomJoinMap(1); - CrestronConsole.AddNewConsoleCommand((o) => JoinMap.PrintJoinMapInfo(), string.Format("ptjnmp-{0}", Key), "Prints Attribute Join Map", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand((o) => JoinMap.PrintJoinMapInfo(), string.Format("ptjnmp-{0}", Key), "Prints Attribute Join Map", ConsoleAccessLevelEnum.AccessOperator); - if (!string.IsNullOrEmpty(joinMapKey)) + if (!string.IsNullOrEmpty(joinMapKey)) + { + var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); + if (customJoins != null) { - var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); - if (customJoins != null) - { - JoinMap.SetCustomJoinData(customJoins); - } + JoinMap.SetCustomJoinData(customJoins); } - - Room = room; + } + + Room = room; - _ipId = ipId; + _ipId = ipId; - FusionStaticAssets = new Dictionary(); + FusionStaticAssets = new Dictionary(); - _guiDs = new FusionRoomGuids(); + _guiDs = new FusionRoomGuids(); - var mac = - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0); + var mac = + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0); - var slot = Global.ControlSystem.ProgramNumber; + var slot = Global.ControlSystem.ProgramNumber; - var guidFilePath = Global.FilePathPrefix + - string.Format(@"{0}-FusionGuids-{1:X2}.json", InitialParametersClass.ProgramIDTag, _ipId); + var guidFilePath = Global.FilePathPrefix + + string.Format(@"{0}-FusionGuids-{1:X2}.json", InitialParametersClass.ProgramIDTag, _ipId); - var oldGuidFilePath = Global.FilePathPrefix + - string.Format(@"{0}-FusionGuids.json", InitialParametersClass.ProgramIDTag); + var oldGuidFilePath = Global.FilePathPrefix + + string.Format(@"{0}-FusionGuids.json", InitialParametersClass.ProgramIDTag); - if (File.Exists(oldGuidFilePath)) - { - Debug.LogMessage(LogEventLevel.Information, this, "Migrating from old Fusion GUID file to new Fusion GUID File"); + if (File.Exists(oldGuidFilePath)) + { + Debug.LogMessage(LogEventLevel.Information, this, "Migrating from old Fusion GUID file to new Fusion GUID File"); - File.Copy(oldGuidFilePath, guidFilePath); + File.Copy(oldGuidFilePath, guidFilePath); - File.Delete(oldGuidFilePath); - } + File.Delete(oldGuidFilePath); + } - _guidFileExists = File.Exists(guidFilePath); + _guidFileExists = File.Exists(guidFilePath); - // Check if file exists - if (!_guidFileExists) - { - // Does not exist. Create GUIDs - _guiDs = new FusionRoomGuids(Room.Name, ipId, _guiDs.GenerateNewRoomGuid(slot, mac), - FusionStaticAssets); - } - else - { - // Exists. Read GUIDs - ReadGuidFile(guidFilePath); - } + // Check if file exists + if (!_guidFileExists) + { + // Does not exist. Create GUIDs + _guiDs = new FusionRoomGuids(Room.Name, ipId, _guiDs.GenerateNewRoomGuid(slot, mac), + FusionStaticAssets); + } + else + { + // Exists. Read GUIDs + ReadGuidFile(guidFilePath); + } - if (Room is IRoomOccupancy occupancyRoom) + if (Room is IRoomOccupancy occupancyRoom) + { + if (occupancyRoom.RoomOccupancy != null) { - if (occupancyRoom.RoomOccupancy != null) + if (occupancyRoom.OccupancyStatusProviderIsRemote) { - if (occupancyRoom.OccupancyStatusProviderIsRemote) - { - SetUpRemoteOccupancy(); - } - else - { - SetUpLocalOccupancy(); - } + SetUpRemoteOccupancy(); + } + else + { + SetUpLocalOccupancy(); } } + } - AddPostActivationAction(() => PostActivate(guidFilePath)); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Information, this, "Error Building Fusion System Controller: {0}", e); - } + AddPostActivationAction(() => PostActivate(guidFilePath)); } - - private void PostActivate(string guidFilePath) + catch (Exception e) { - CreateSymbolAndBasicSigs(_ipId); - SetUpSources(); - SetUpCommunitcationMonitors(); - SetUpDisplay(); - SetUpError(); - ExecuteCustomSteps(); + Debug.LogMessage(LogEventLevel.Information, this, "Error Building Fusion System Controller: {0}", e); + } + } - FusionRVI.GenerateFileForAllFusionDevices(); + private void PostActivate(string guidFilePath) + { + CreateSymbolAndBasicSigs(_ipId); + SetUpSources(); + SetUpCommunitcationMonitors(); + SetUpDisplay(); + SetUpError(); + ExecuteCustomSteps(); - GenerateGuidFile(guidFilePath); - } + FusionRVI.GenerateFileForAllFusionDevices(); - protected string RoomGuid - { - get { return _guiDs.RoomGuid; } - } + GenerateGuidFile(guidFilePath); + } + + protected string RoomGuid + { + get { return _guiDs.RoomGuid; } + } - public StringFeedback RoomOccupancyRemoteStringFeedback { get; private set; } + public StringFeedback RoomOccupancyRemoteStringFeedback { get; private set; } - protected Func RoomIsOccupiedFeedbackFunc - { - get { return () => FusionRemoteOccSensor.RoomOccupied.OutputSig.BoolValue; } - } + protected Func RoomIsOccupiedFeedbackFunc + { + get { return () => FusionRemoteOccSensor.RoomOccupied.OutputSig.BoolValue; } + } + + #region IOccupancyStatusProvider Members - #region IOccupancyStatusProvider Members + public BoolFeedback RoomIsOccupiedFeedback { get; private set; } - public BoolFeedback RoomIsOccupiedFeedback { get; private set; } + #endregion - #endregion + public event EventHandler ScheduleChange; + //public event EventHandler MeetingEndWarning; + //public event EventHandler NextMeetingBeginWarning; - public event EventHandler ScheduleChange; - //public event EventHandler MeetingEndWarning; - //public event EventHandler NextMeetingBeginWarning; + public event EventHandler RoomInfoChange; - public event EventHandler RoomInfoChange; + //ScheduleResponseEvent NextMeeting; - //ScheduleResponseEvent NextMeeting; + /// + /// Used for extension classes to execute whatever steps are necessary before generating the RVI and GUID files + /// + protected virtual void ExecuteCustomSteps() + { + } - /// - /// Used for extension classes to execute whatever steps are necessary before generating the RVI and GUID files - /// - protected virtual void ExecuteCustomSteps() + /// + /// Generates the guid file in NVRAM. If the file already exists it will be overwritten. + /// + /// path for the file + private void GenerateGuidFile(string filePath) + { + if (string.IsNullOrEmpty(filePath)) { + Debug.LogMessage(LogEventLevel.Information, this, "Error writing guid file. No path specified."); + return; } - /// - /// Generates the guid file in NVRAM. If the file already exists it will be overwritten. - /// - /// path for the file - private void GenerateGuidFile(string filePath) + var fileLock = new CCriticalSection(); + + try { - if (string.IsNullOrEmpty(filePath)) + if (fileLock.Disposed) { - Debug.LogMessage(LogEventLevel.Information, this, "Error writing guid file. No path specified."); return; } - var fileLock = new CCriticalSection(); - - try - { - if (fileLock.Disposed) - { - return; - } - - fileLock.Enter(); - - Debug.LogMessage(LogEventLevel.Debug, this, "Writing GUIDs to file"); + fileLock.Enter(); - _guiDs = FusionOccSensor == null - ? new FusionRoomGuids(Room.Name, _ipId, RoomGuid, FusionStaticAssets) - : new FusionRoomGuids(Room.Name, _ipId, RoomGuid, FusionStaticAssets, FusionOccSensor); + Debug.LogMessage(LogEventLevel.Debug, this, "Writing GUIDs to file"); - var json = JsonConvert.SerializeObject(_guiDs, Newtonsoft.Json.Formatting.Indented); + _guiDs = FusionOccSensor == null + ? new FusionRoomGuids(Room.Name, _ipId, RoomGuid, FusionStaticAssets) + : new FusionRoomGuids(Room.Name, _ipId, RoomGuid, FusionStaticAssets, FusionOccSensor); - using (var sw = new StreamWriter(filePath)) - { - sw.Write(json); - sw.Flush(); - } + var json = JsonConvert.SerializeObject(_guiDs, Newtonsoft.Json.Formatting.Indented); - Debug.LogMessage(LogEventLevel.Debug, this, "Guids successfully written to file '{0}'", filePath); - } - catch (Exception e) + using (var sw = new StreamWriter(filePath)) { - Debug.LogMessage(LogEventLevel.Information, this, "Error writing guid file: {0}", e); + sw.Write(json); + sw.Flush(); } - finally + + Debug.LogMessage(LogEventLevel.Debug, this, "Guids successfully written to file '{0}'", filePath); + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Information, this, "Error writing guid file: {0}", e); + } + finally + { + if (!fileLock.Disposed) { - if (!fileLock.Disposed) - { - fileLock.Leave(); - } + fileLock.Leave(); } } + } + + /// + /// Reads the guid file from NVRAM + /// + /// path for te file + private void ReadGuidFile(string filePath) + { + if (string.IsNullOrEmpty(filePath)) + { + Debug.LogMessage(LogEventLevel.Information, this, "Error reading guid file. No path specified."); + return; + } - /// - /// Reads the guid file from NVRAM - /// - /// path for te file - private void ReadGuidFile(string filePath) + var fileLock = new CCriticalSection(); + + try { - if (string.IsNullOrEmpty(filePath)) + if (fileLock.Disposed) { - Debug.LogMessage(LogEventLevel.Information, this, "Error reading guid file. No path specified."); return; } - var fileLock = new CCriticalSection(); + fileLock.Enter(); - try + if (File.Exists(filePath)) { - if (fileLock.Disposed) - { - return; - } - - fileLock.Enter(); - - if (File.Exists(filePath)) - { - var json = File.ReadToEnd(filePath, Encoding.ASCII); + var json = File.ReadToEnd(filePath, Encoding.ASCII); - _guiDs = JsonConvert.DeserializeObject(json); + _guiDs = JsonConvert.DeserializeObject(json); - _ipId = _guiDs.IpId; + _ipId = _guiDs.IpId; - FusionStaticAssets = _guiDs.StaticAssets; - } + FusionStaticAssets = _guiDs.StaticAssets; + } - Debug.LogMessage(LogEventLevel.Information, this, "Fusion Guids successfully read from file: {0}", - filePath); + Debug.LogMessage(LogEventLevel.Information, this, "Fusion Guids successfully read from file: {0}", + filePath); - Debug.LogMessage(LogEventLevel.Debug, this, "\r\n********************\r\n\tRoom Name: {0}\r\n\tIPID: {1:X}\r\n\tRoomGuid: {2}\r\n*******************", Room.Name, _ipId, RoomGuid); + Debug.LogMessage(LogEventLevel.Debug, this, "\r\n********************\r\n\tRoom Name: {0}\r\n\tIPID: {1:X}\r\n\tRoomGuid: {2}\r\n*******************", Room.Name, _ipId, RoomGuid); - foreach (var item in FusionStaticAssets) - { - Debug.LogMessage(LogEventLevel.Debug, this, "\nAsset Name: {0}\nAsset No: {1}\n Guid: {2}", item.Value.Name, - item.Value.SlotNumber, item.Value.InstanceId); - } - } - catch (Exception e) + foreach (var item in FusionStaticAssets) { - Debug.LogMessage(LogEventLevel.Information, this, "Error reading guid file: {0}", e); + Debug.LogMessage(LogEventLevel.Debug, this, "\nAsset Name: {0}\nAsset No: {1}\n Guid: {2}", item.Value.Name, + item.Value.SlotNumber, item.Value.InstanceId); } - finally + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Information, this, "Error reading guid file: {0}", e); + } + finally + { + if (!fileLock.Disposed) { - if (!fileLock.Disposed) - { - fileLock.Leave(); - } + fileLock.Leave(); } } + } - protected virtual void CreateSymbolAndBasicSigs(uint ipId) + protected virtual void CreateSymbolAndBasicSigs(uint ipId) + { + Debug.LogMessage(LogEventLevel.Information, this, "Creating Fusion Room symbol with GUID: {0} and IP-ID {1:X2}", RoomGuid, ipId); + + FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid); + FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use(); + FusionRoom.ExtenderFusionRoomDataReservedSigs.Use(); + + FusionRoom.Register(); + + FusionRoom.FusionStateChange += FusionRoom_FusionStateChange; + + FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.DeviceExtenderSigChange += + FusionRoomSchedule_DeviceExtenderSigChange; + FusionRoom.ExtenderFusionRoomDataReservedSigs.DeviceExtenderSigChange += + ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange; + FusionRoom.OnlineStatusChange += FusionRoom_OnlineStatusChange; + + CrestronConsole.AddNewConsoleCommand(RequestFullRoomSchedule, "FusReqRoomSchedule", + "Requests schedule of the room for the next 24 hours", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(ModifyMeetingEndTimeConsoleHelper, "FusReqRoomSchMod", + "Ends or extends a meeting by the specified time", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(CreateAdHocMeeting, "FusCreateMeeting", + "Creates and Ad Hoc meeting for on hour or until the next meeting", + ConsoleAccessLevelEnum.AccessOperator); + + // Room to fusion room + Room.OnFeedback.LinkInputSig(FusionRoom.SystemPowerOn.InputSig); + + // Moved to + CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(JoinMap.Display1CurrentSourceName.JoinNumber, JoinMap.Display1CurrentSourceName.AttributeName, + eSigIoMask.InputSigOnly); + // Don't think we need to get current status of this as nothing should be alive yet. + if (Room is IHasCurrentSourceInfoChange hasCurrentSourceInfoChange) { - Debug.LogMessage(LogEventLevel.Information, this, "Creating Fusion Room symbol with GUID: {0} and IP-ID {1:X2}", RoomGuid, ipId); - - FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid); - FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use(); - FusionRoom.ExtenderFusionRoomDataReservedSigs.Use(); - - FusionRoom.Register(); - - FusionRoom.FusionStateChange += FusionRoom_FusionStateChange; - - FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.DeviceExtenderSigChange += - FusionRoomSchedule_DeviceExtenderSigChange; - FusionRoom.ExtenderFusionRoomDataReservedSigs.DeviceExtenderSigChange += - ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange; - FusionRoom.OnlineStatusChange += FusionRoom_OnlineStatusChange; - - CrestronConsole.AddNewConsoleCommand(RequestFullRoomSchedule, "FusReqRoomSchedule", - "Requests schedule of the room for the next 24 hours", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(ModifyMeetingEndTimeConsoleHelper, "FusReqRoomSchMod", - "Ends or extends a meeting by the specified time", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(CreateAdHocMeeting, "FusCreateMeeting", - "Creates and Ad Hoc meeting for on hour or until the next meeting", - ConsoleAccessLevelEnum.AccessOperator); + hasCurrentSourceInfoChange.CurrentSourceChange += Room_CurrentSourceInfoChange; + } - // Room to fusion room - Room.OnFeedback.LinkInputSig(FusionRoom.SystemPowerOn.InputSig); - // Moved to - CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(JoinMap.Display1CurrentSourceName.JoinNumber, JoinMap.Display1CurrentSourceName.AttributeName, - eSigIoMask.InputSigOnly); - // Don't think we need to get current status of this as nothing should be alive yet. - if (Room is IHasCurrentSourceInfoChange hasCurrentSourceInfoChange) + FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction(Room.PowerOnToDefaultOrLastSource); + FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => + { + if (Room is IRunRouteAction runRouteAction) { - hasCurrentSourceInfoChange.CurrentSourceChange += Room_CurrentSourceInfoChange; + runRouteAction.RunRouteAction("roomOff", Room.SourceListKey); } + }); + // NO!! room.RoomIsOn.LinkComplementInputSig(FusionRoom.SystemPowerOff.InputSig); + FusionRoom.ErrorMessage.InputSig.StringValue = + "3: 7 Errors: This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;"; + SetUpEthernetValues(); - FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction(Room.PowerOnToDefaultOrLastSource); - FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => - { - if (Room is IRunRouteAction runRouteAction) - { - runRouteAction.RunRouteAction("roomOff", Room.SourceListKey); - } - }); - // NO!! room.RoomIsOn.LinkComplementInputSig(FusionRoom.SystemPowerOff.InputSig); - FusionRoom.ErrorMessage.InputSig.StringValue = - "3: 7 Errors: This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;"; - - SetUpEthernetValues(); - - GetProcessorEthernetValues(); + GetProcessorEthernetValues(); - GetSystemInfo(); + GetSystemInfo(); - GetProcessorInfo(); + GetProcessorInfo(); - CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler; - } + CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler; + } - protected void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs ethernetEventArgs) + protected void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs ethernetEventArgs) + { + if (ethernetEventArgs.EthernetEventType == eEthernetEventType.LinkUp) { - if (ethernetEventArgs.EthernetEventType == eEthernetEventType.LinkUp) - { - GetProcessorEthernetValues(); - } + GetProcessorEthernetValues(); } + } - protected void GetSystemInfo() - { - //SystemName.InputSig.StringValue = Room.Name; - //Model.InputSig.StringValue = InitialParametersClass.ControllerPromptName; - //SerialNumber.InputSig.StringValue = InitialParametersClass. + protected void GetSystemInfo() + { + //SystemName.InputSig.StringValue = Room.Name; + //Model.InputSig.StringValue = InitialParametersClass.ControllerPromptName; + //SerialNumber.InputSig.StringValue = InitialParametersClass. - var response = string.Empty; + var response = string.Empty; - var systemReboot = FusionRoom.CreateOffsetBoolSig(JoinMap.ProcessorReboot.JoinNumber, JoinMap.ProcessorReboot.AttributeName, eSigIoMask.OutputSigOnly); - systemReboot.OutputSig.SetSigFalseAction( - () => CrestronConsole.SendControlSystemCommand("reboot", ref response)); - } + var systemReboot = FusionRoom.CreateOffsetBoolSig(JoinMap.ProcessorReboot.JoinNumber, JoinMap.ProcessorReboot.AttributeName, eSigIoMask.OutputSigOnly); + systemReboot.OutputSig.SetSigFalseAction( + () => CrestronConsole.SendControlSystemCommand("reboot", ref response)); + } + + protected void SetUpEthernetValues() + { + _ip1 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorIp1.JoinNumber, JoinMap.ProcessorIp1.AttributeName, eSigIoMask.InputSigOnly); + _ip2 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorIp2.JoinNumber, JoinMap.ProcessorIp2.AttributeName, eSigIoMask.InputSigOnly); + _gateway = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorGateway.JoinNumber, JoinMap.ProcessorGateway.AttributeName, eSigIoMask.InputSigOnly); + _hostname = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorHostname.JoinNumber, JoinMap.ProcessorHostname.AttributeName, eSigIoMask.InputSigOnly); + _domain = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorDomain.JoinNumber, JoinMap.ProcessorDomain.AttributeName, eSigIoMask.InputSigOnly); + _dns1 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorDns1.JoinNumber, JoinMap.ProcessorDns1.AttributeName, eSigIoMask.InputSigOnly); + _dns2 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorDns2.JoinNumber, JoinMap.ProcessorDns2.AttributeName, eSigIoMask.InputSigOnly); + _mac1 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorMac1.JoinNumber, JoinMap.ProcessorMac1.AttributeName, eSigIoMask.InputSigOnly); + _mac2 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorMac2.JoinNumber, JoinMap.ProcessorMac2.AttributeName, eSigIoMask.InputSigOnly); + _netMask1 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorNetMask1.JoinNumber, JoinMap.ProcessorNetMask1.AttributeName, eSigIoMask.InputSigOnly); + _netMask2 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorNetMask2.JoinNumber, JoinMap.ProcessorNetMask2.AttributeName, eSigIoMask.InputSigOnly); + } - protected void SetUpEthernetValues() + protected void GetProcessorEthernetValues() + { + _ip1.InputSig.StringValue = + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0); + _gateway.InputSig.StringValue = + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, 0); + _hostname.InputSig.StringValue = + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0); + _domain.InputSig.StringValue = + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DOMAIN_NAME, 0); + + var dnsServers = + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DNS_SERVER, 0).Split(','); + _dns1.InputSig.StringValue = dnsServers[0]; + if (dnsServers.Length > 1) { - _ip1 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorIp1.JoinNumber, JoinMap.ProcessorIp1.AttributeName, eSigIoMask.InputSigOnly); - _ip2 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorIp2.JoinNumber, JoinMap.ProcessorIp2.AttributeName, eSigIoMask.InputSigOnly); - _gateway = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorGateway.JoinNumber, JoinMap.ProcessorGateway.AttributeName, eSigIoMask.InputSigOnly); - _hostname = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorHostname.JoinNumber, JoinMap.ProcessorHostname.AttributeName, eSigIoMask.InputSigOnly); - _domain = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorDomain.JoinNumber, JoinMap.ProcessorDomain.AttributeName, eSigIoMask.InputSigOnly); - _dns1 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorDns1.JoinNumber, JoinMap.ProcessorDns1.AttributeName, eSigIoMask.InputSigOnly); - _dns2 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorDns2.JoinNumber, JoinMap.ProcessorDns2.AttributeName, eSigIoMask.InputSigOnly); - _mac1 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorMac1.JoinNumber, JoinMap.ProcessorMac1.AttributeName, eSigIoMask.InputSigOnly); - _mac2 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorMac2.JoinNumber, JoinMap.ProcessorMac2.AttributeName, eSigIoMask.InputSigOnly); - _netMask1 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorNetMask1.JoinNumber, JoinMap.ProcessorNetMask1.AttributeName, eSigIoMask.InputSigOnly); - _netMask2 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorNetMask2.JoinNumber, JoinMap.ProcessorNetMask2.AttributeName, eSigIoMask.InputSigOnly); + _dns2.InputSig.StringValue = dnsServers[1]; } - protected void GetProcessorEthernetValues() + _mac1.InputSig.StringValue = + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0); + _netMask1.InputSig.StringValue = + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, 0); + + // Interface 1 + + if (InitialParametersClass.NumberOfEthernetInterfaces > 1) + // Only get these values if the processor has more than 1 NIC { - _ip1.InputSig.StringValue = - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0); - _gateway.InputSig.StringValue = + _ip2.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, 0); - _hostname.InputSig.StringValue = + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 1); + _mac2.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0); - _domain.InputSig.StringValue = + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 1); + _netMask2.InputSig.StringValue = CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DOMAIN_NAME, 0); + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, 1); + } + } - var dnsServers = - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DNS_SERVER, 0).Split(','); - _dns1.InputSig.StringValue = dnsServers[0]; - if (dnsServers.Length > 1) + protected void GetProcessorInfo() + { + _firmware = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorFirmware.JoinNumber, JoinMap.ProcessorFirmware.AttributeName, eSigIoMask.InputSigOnly); + + if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server) + { + for (var i = 0; i < Global.ControlSystem.NumProgramsSupported; i++) { - _dns2.InputSig.StringValue = dnsServers[1]; + var join = JoinMap.ProgramNameStart.JoinNumber + i; + var progNum = i + 1; + _program[i] = FusionRoom.CreateOffsetStringSig((uint) join, + string.Format("{0} {1}", JoinMap.ProgramNameStart.AttributeName, progNum), eSigIoMask.InputSigOnly); } + } - _mac1.InputSig.StringValue = - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0); - _netMask1.InputSig.StringValue = - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, 0); + _firmware.InputSig.StringValue = InitialParametersClass.FirmwareVersion; + } - // Interface 1 + protected void GetCustomProperties() + { + if (FusionRoom.IsOnline) + { + const string fusionRoomCustomPropertiesRequest = + @"RoomConfigurationRequest"; - if (InitialParametersClass.NumberOfEthernetInterfaces > 1) - // Only get these values if the processor has more than 1 NIC - { - _ip2.InputSig.StringValue = - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 1); - _mac2.InputSig.StringValue = - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 1); - _netMask2.InputSig.StringValue = - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, 1); - } + FusionRoom.ExtenderFusionRoomDataReservedSigs.RoomConfigQuery.StringValue = + fusionRoomCustomPropertiesRequest; } + } - protected void GetProcessorInfo() - { - _firmware = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorFirmware.JoinNumber, JoinMap.ProcessorFirmware.AttributeName, eSigIoMask.InputSigOnly); + private void GetTouchpanelInfo() + { + // TODO: Get IP and Project Name from TP + } - if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server) - { - for (var i = 0; i < Global.ControlSystem.NumProgramsSupported; i++) + protected void FusionRoom_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args) + { + if (args.DeviceOnLine) + { + CrestronInvoke.BeginInvoke( (o) => + { + CrestronEnvironment.Sleep(200); + + // Send Push Notification Action request: + + const string requestId = "InitialPushRequest"; + + + var actionRequest = + string.Format("\n{0}\n", requestId) + + "RegisterPushModel\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n"; + + Debug.LogMessage(LogEventLevel.Verbose, this, "Sending Fusion ActionRequest: \n{0}", actionRequest); + + FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = actionRequest; + + GetCustomProperties(); + + // Request current Fusion Server Time + RequestLocalDateTime(null); + + // Setup timer to request time daily + if (_dailyTimeRequestTimer != null && !_dailyTimeRequestTimer.Disposed) { - var join = JoinMap.ProgramNameStart.JoinNumber + i; - var progNum = i + 1; - _program[i] = FusionRoom.CreateOffsetStringSig((uint) join, - string.Format("{0} {1}", JoinMap.ProgramNameStart.AttributeName, progNum), eSigIoMask.InputSigOnly); + _dailyTimeRequestTimer.Stop(); + _dailyTimeRequestTimer.Dispose(); } - } - _firmware.InputSig.StringValue = InitialParametersClass.FirmwareVersion; + _dailyTimeRequestTimer = new CTimer(RequestLocalDateTime, null, 86400000, 86400000); + + _dailyTimeRequestTimer.Reset(86400000, 86400000); + }); } + } - protected void GetCustomProperties() - { - if (FusionRoom.IsOnline) - { - const string fusionRoomCustomPropertiesRequest = - @"RoomConfigurationRequest"; + /// + /// Requests the local date and time from the Fusion Server + /// + /// + public void RequestLocalDateTime(object callbackObject) + { + const string timeRequestId = "TimeRequest"; - FusionRoom.ExtenderFusionRoomDataReservedSigs.RoomConfigQuery.StringValue = - fusionRoomCustomPropertiesRequest; - } - } + var timeRequest = string.Format("{0}", + timeRequestId); - private void GetTouchpanelInfo() - { - // TODO: Get IP and Project Name from TP - } + FusionRoom.ExtenderFusionRoomDataReservedSigs.LocalDateTimeQuery.StringValue = timeRequest; + } - protected void FusionRoom_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args) - { - if (args.DeviceOnLine) - { - CrestronInvoke.BeginInvoke( (o) => - { - CrestronEnvironment.Sleep(200); - - // Send Push Notification Action request: - - const string requestId = "InitialPushRequest"; - - - var actionRequest = - string.Format("\n{0}\n", requestId) + - "RegisterPushModel\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "\n"; - - Debug.LogMessage(LogEventLevel.Verbose, this, "Sending Fusion ActionRequest: \n{0}", actionRequest); - - FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = actionRequest; - - GetCustomProperties(); - - // Request current Fusion Server Time - RequestLocalDateTime(null); - - // Setup timer to request time daily - if (_dailyTimeRequestTimer != null && !_dailyTimeRequestTimer.Disposed) - { - _dailyTimeRequestTimer.Stop(); - _dailyTimeRequestTimer.Dispose(); - } + /// + /// Generates a room schedule request for this room for the next 24 hours. + /// + public void RequestFullRoomSchedule(object callbackObject) + { + var now = DateTime.Today; - _dailyTimeRequestTimer = new CTimer(RequestLocalDateTime, null, 86400000, 86400000); + var currentTime = now.ToString("s"); - _dailyTimeRequestTimer.Reset(86400000, 86400000); - }); - } - } + var requestTest = + string.Format( + "FullSchedleRequest{0}{1}24", + RoomGuid, currentTime); - /// - /// Requests the local date and time from the Fusion Server - /// - /// - public void RequestLocalDateTime(object callbackObject) - { - const string timeRequestId = "TimeRequest"; + Debug.LogMessage(LogEventLevel.Verbose, this, "Sending Fusion ScheduleQuery: \n{0}", requestTest); - var timeRequest = string.Format("{0}", - timeRequestId); + FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleQuery.StringValue = requestTest; - FusionRoom.ExtenderFusionRoomDataReservedSigs.LocalDateTimeQuery.StringValue = timeRequest; + if (_isRegisteredForSchedulePushNotifications) + { + _pushNotificationTimer.Stop(); } + } - /// - /// Generates a room schedule request for this room for the next 24 hours. - /// - public void RequestFullRoomSchedule(object callbackObject) - { - var now = DateTime.Today; + /// + /// Wrapper method to allow console commands to modify the current meeting end time + /// + /// meetingID extendTime + public void ModifyMeetingEndTimeConsoleHelper(string command) + { + var extendMinutes = -1; - var currentTime = now.ToString("s"); + const string requestId = "ModifyMeetingTest12345"; - var requestTest = - string.Format( - "FullSchedleRequest{0}{1}24", - RoomGuid, currentTime); + try + { + var tokens = command.Split(' '); - Debug.LogMessage(LogEventLevel.Verbose, this, "Sending Fusion ScheduleQuery: \n{0}", requestTest); + extendMinutes = Int32.Parse(tokens[1]); + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Error parsing console command: {0}", e); + } - FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleQuery.StringValue = requestTest; + ModifyMeetingEndTime(requestId, extendMinutes); + } - if (_isRegisteredForSchedulePushNotifications) - { - _pushNotificationTimer.Stop(); - } + /// + /// Ends or Extends the current meeting by the specified number of minutes. + /// + /// + /// Number of minutes to extend the meeting. A value of 0 will end the meeting. + public void ModifyMeetingEndTime(string requestId, int extendMinutes) + { + if (_currentMeeting == null) + { + Debug.LogMessage(LogEventLevel.Debug, this, "No meeting in progress. Unable to modify end time."); + return; } - /// - /// Wrapper method to allow console commands to modify the current meeting end time - /// - /// meetingID extendTime - public void ModifyMeetingEndTimeConsoleHelper(string command) + if (extendMinutes > -1) { - var extendMinutes = -1; - - const string requestId = "ModifyMeetingTest12345"; - - try + if (extendMinutes > 0) { - var tokens = command.Split(' '); + var extendTime = _currentMeeting.dtEnd - DateTime.Now; + var extendMinutesRaw = extendTime.TotalMinutes; - extendMinutes = Int32.Parse(tokens[1]); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Error parsing console command: {0}", e); + extendMinutes += (int) Math.Round(extendMinutesRaw); } - ModifyMeetingEndTime(requestId, extendMinutes); - } - /// - /// Ends or Extends the current meeting by the specified number of minutes. - /// - /// - /// Number of minutes to extend the meeting. A value of 0 will end the meeting. - public void ModifyMeetingEndTime(string requestId, int extendMinutes) + var requestTest = string.Format( + "{0}{1}MeetingChange" + , requestId, RoomGuid, _currentMeeting.MeetingID, extendMinutes); + + Debug.LogMessage(LogEventLevel.Debug, this, "Sending MeetingChange Request: \n{0}", requestTest); + + FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = requestTest; + } + else { - if (_currentMeeting == null) - { - Debug.LogMessage(LogEventLevel.Debug, this, "No meeting in progress. Unable to modify end time."); - return; - } + Debug.LogMessage(LogEventLevel.Debug, this, "Invalid time specified"); + } + } - if (extendMinutes > -1) - { - if (extendMinutes > 0) - { - var extendTime = _currentMeeting.dtEnd - DateTime.Now; - var extendMinutesRaw = extendTime.TotalMinutes; + /// + /// Creates and Ad Hoc meeting with a duration of 1 hour, or until the next meeting if in less than 1 hour. + /// + public void CreateAdHocMeeting(string command) + { + const string requestId = "CreateAdHocMeeting"; - extendMinutes += (int) Math.Round(extendMinutesRaw); - } + var now = DateTime.Now.AddMinutes(1); + now.AddSeconds(-now.Second); - var requestTest = string.Format( - "{0}{1}MeetingChange" - , requestId, RoomGuid, _currentMeeting.MeetingID, extendMinutes); + // Assume 1 hour meeting if possible + var dtEnd = now.AddHours(1); - Debug.LogMessage(LogEventLevel.Debug, this, "Sending MeetingChange Request: \n{0}", requestTest); + // Check if room is available for 1 hour before next meeting + if (_nextMeeting != null) + { + var roomAvailable = _nextMeeting.dtEnd.Subtract(dtEnd); - FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = requestTest; - } - else + if (roomAvailable.TotalMinutes < 60) { - Debug.LogMessage(LogEventLevel.Debug, this, "Invalid time specified"); + // Room not available for full hour, book until next meeting starts + dtEnd = _nextMeeting.dtEnd; } } - /// - /// Creates and Ad Hoc meeting with a duration of 1 hour, or until the next meeting if in less than 1 hour. - /// - public void CreateAdHocMeeting(string command) - { - const string requestId = "CreateAdHocMeeting"; - - var now = DateTime.Now.AddMinutes(1); + var createMeetingRequest = + "" + + string.Format("{0}", requestId) + + string.Format("{0}", RoomGuid) + + "" + + string.Format("{0}", now.ToString("s")) + + string.Format("{0}", dtEnd.ToString("s")) + + "AdHoc Meeting" + + "Room User" + + "Example Message" + + "" + + ""; - now.AddSeconds(-now.Second); + Debug.LogMessage(LogEventLevel.Verbose, this, "Sending CreateMeeting Request: \n{0}", createMeetingRequest); - // Assume 1 hour meeting if possible - var dtEnd = now.AddHours(1); + FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateMeeting.StringValue = createMeetingRequest; - // Check if room is available for 1 hour before next meeting - if (_nextMeeting != null) - { - var roomAvailable = _nextMeeting.dtEnd.Subtract(dtEnd); + //Debug.LogMessage(LogEventLevel.Debug, this, "Sending CreateMeeting Request: \n{0}", command); - if (roomAvailable.TotalMinutes < 60) - { - // Room not available for full hour, book until next meeting starts - dtEnd = _nextMeeting.dtEnd; - } - } + //FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateMeeting.StringValue = command; + } - var createMeetingRequest = - "" + - string.Format("{0}", requestId) + - string.Format("{0}", RoomGuid) + - "" + - string.Format("{0}", now.ToString("s")) + - string.Format("{0}", dtEnd.ToString("s")) + - "AdHoc Meeting" + - "Room User" + - "Example Message" + - "" + - ""; + /// + /// Event handler method for Device Extender sig changes + /// + /// + /// + protected void ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, + SigEventArgs args) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, args.Sig.Name, + args.Sig.StringValue); - Debug.LogMessage(LogEventLevel.Verbose, this, "Sending CreateMeeting Request: \n{0}", createMeetingRequest); - FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateMeeting.StringValue = createMeetingRequest; + if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQueryResponse) + { + try + { + var message = new XmlDocument(); - //Debug.LogMessage(LogEventLevel.Debug, this, "Sending CreateMeeting Request: \n{0}", command); + message.LoadXml(args.Sig.StringValue); - //FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateMeeting.StringValue = command; - } + var actionResponse = message["ActionResponse"]; - /// - /// Event handler method for Device Extender sig changes - /// - /// - /// - protected void ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, - SigEventArgs args) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, args.Sig.Name, - args.Sig.StringValue); + if (actionResponse == null) + { + return; + } + var requestId = actionResponse["RequestID"]; - if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQueryResponse) - { - try + if (requestId.InnerText != "InitialPushRequest") { - var message = new XmlDocument(); + return; + } - message.LoadXml(args.Sig.StringValue); + if (actionResponse["ActionID"].InnerText != "RegisterPushModel") + { + return; + } - var actionResponse = message["ActionResponse"]; + var parameters = actionResponse["Parameters"]; - if (actionResponse == null) - { - return; - } - - var requestId = actionResponse["RequestID"]; - - if (requestId.InnerText != "InitialPushRequest") - { - return; - } - - if (actionResponse["ActionID"].InnerText != "RegisterPushModel") - { - return; - } - - var parameters = actionResponse["Parameters"]; - - foreach (var isRegistered in from XmlElement parameter in parameters - where parameter.HasAttributes - select parameter.Attributes - into attributes - where attributes["ID"].Value == "Registered" - select Int32.Parse(attributes["Value"].Value)) + foreach (var isRegistered in from XmlElement parameter in parameters + where parameter.HasAttributes + select parameter.Attributes + into attributes + where attributes["ID"].Value == "Registered" + select Int32.Parse(attributes["Value"].Value)) + { + switch (isRegistered) { - switch (isRegistered) - { - case 1: - _isRegisteredForSchedulePushNotifications = true; - if (_pollTimer != null && !_pollTimer.Disposed) - { - _pollTimer.Stop(); - _pollTimer.Dispose(); - } - _pushNotificationTimer = new CTimer(RequestFullRoomSchedule, null, - PushNotificationTimeout, PushNotificationTimeout); - _pushNotificationTimer.Reset(PushNotificationTimeout, PushNotificationTimeout); - break; - case 0: - _isRegisteredForSchedulePushNotifications = false; - if (_pushNotificationTimer != null && !_pushNotificationTimer.Disposed) - { - _pushNotificationTimer.Stop(); - _pushNotificationTimer.Dispose(); - } - _pollTimer = new CTimer(RequestFullRoomSchedule, null, SchedulePollInterval, - SchedulePollInterval); - _pollTimer.Reset(SchedulePollInterval, SchedulePollInterval); - break; - } + case 1: + _isRegisteredForSchedulePushNotifications = true; + if (_pollTimer != null && !_pollTimer.Disposed) + { + _pollTimer.Stop(); + _pollTimer.Dispose(); + } + _pushNotificationTimer = new CTimer(RequestFullRoomSchedule, null, + PushNotificationTimeout, PushNotificationTimeout); + _pushNotificationTimer.Reset(PushNotificationTimeout, PushNotificationTimeout); + break; + case 0: + _isRegisteredForSchedulePushNotifications = false; + if (_pushNotificationTimer != null && !_pushNotificationTimer.Disposed) + { + _pushNotificationTimer.Stop(); + _pushNotificationTimer.Dispose(); + } + _pollTimer = new CTimer(RequestFullRoomSchedule, null, SchedulePollInterval, + SchedulePollInterval); + _pollTimer.Reset(SchedulePollInterval, SchedulePollInterval); + break; } } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Error parsing ActionQueryResponse: {0}", e); - } } - else if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.LocalDateTimeQueryResponse) + catch (Exception e) { - try - { - var message = new XmlDocument(); + Debug.LogMessage(LogEventLevel.Debug, this, "Error parsing ActionQueryResponse: {0}", e); + } + } + else if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.LocalDateTimeQueryResponse) + { + try + { + var message = new XmlDocument(); - message.LoadXml(args.Sig.StringValue); + message.LoadXml(args.Sig.StringValue); - var localDateTimeResponse = message["LocalTimeResponse"]; + var localDateTimeResponse = message["LocalTimeResponse"]; - if (localDateTimeResponse != null) - { - var localDateTime = localDateTimeResponse["LocalDateTime"]; + if (localDateTimeResponse != null) + { + var localDateTime = localDateTimeResponse["LocalDateTime"]; - if (localDateTime != null) - { - var tempLocalDateTime = localDateTime.InnerText; + if (localDateTime != null) + { + var tempLocalDateTime = localDateTime.InnerText; - var currentTime = DateTime.Parse(tempLocalDateTime); + var currentTime = DateTime.Parse(tempLocalDateTime); - Debug.LogMessage(LogEventLevel.Debug, this, "DateTime from Fusion Server: {0}", currentTime); + Debug.LogMessage(LogEventLevel.Debug, this, "DateTime from Fusion Server: {0}", currentTime); - // Parse time and date from response and insert values - CrestronEnvironment.SetTimeAndDate((ushort) currentTime.Hour, (ushort) currentTime.Minute, - (ushort) currentTime.Second, (ushort) currentTime.Month, (ushort) currentTime.Day, - (ushort) currentTime.Year); + // Parse time and date from response and insert values + CrestronEnvironment.SetTimeAndDate((ushort) currentTime.Hour, (ushort) currentTime.Minute, + (ushort) currentTime.Second, (ushort) currentTime.Month, (ushort) currentTime.Day, + (ushort) currentTime.Year); - Debug.LogMessage(LogEventLevel.Debug, this, "Processor time set to {0}", CrestronEnvironment.GetLocalTime()); - } + Debug.LogMessage(LogEventLevel.Debug, this, "Processor time set to {0}", CrestronEnvironment.GetLocalTime()); } } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Error parsing LocalDateTimeQueryResponse: {0}", e); - } } - else if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.RoomConfigResponse) + catch (Exception e) { - // Room info response with custom properties + Debug.LogMessage(LogEventLevel.Debug, this, "Error parsing LocalDateTimeQueryResponse: {0}", e); + } + } + else if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.RoomConfigResponse) + { + // Room info response with custom properties - var roomConfigResponseArgs = args.Sig.StringValue.Replace("&", "and"); + var roomConfigResponseArgs = args.Sig.StringValue.Replace("&", "and"); - Debug.LogMessage(LogEventLevel.Verbose, this, "Fusion Response: \n {0}", roomConfigResponseArgs); + Debug.LogMessage(LogEventLevel.Verbose, this, "Fusion Response: \n {0}", roomConfigResponseArgs); - try - { - var roomConfigResponse = new XmlDocument(); + try + { + var roomConfigResponse = new XmlDocument(); - roomConfigResponse.LoadXml(roomConfigResponseArgs); + roomConfigResponse.LoadXml(roomConfigResponseArgs); - var requestRoomConfiguration = roomConfigResponse["RoomConfigurationResponse"]; + var requestRoomConfiguration = roomConfigResponse["RoomConfigurationResponse"]; + + if (requestRoomConfiguration != null) + { + var roomInformation = new RoomInformation(); - if (requestRoomConfiguration != null) + foreach (XmlElement e in roomConfigResponse.FirstChild.ChildNodes) { - var roomInformation = new RoomInformation(); + if (e.Name == "RoomInformation") + { + var roomInfo = new XmlReader(e.OuterXml); - foreach (XmlElement e in roomConfigResponse.FirstChild.ChildNodes) + roomInformation = CrestronXMLSerialization.DeSerializeObject(roomInfo); + } + else if (e.Name == "CustomFields") { - if (e.Name == "RoomInformation") + foreach (XmlElement el in e) { - var roomInfo = new XmlReader(e.OuterXml); + var customProperty = new FusionCustomProperty(); - roomInformation = CrestronXMLSerialization.DeSerializeObject(roomInfo); - } - else if (e.Name == "CustomFields") - { - foreach (XmlElement el in e) + if (el.Name == "CustomField") { - var customProperty = new FusionCustomProperty(); + customProperty.ID = el.Attributes["ID"].Value; + } - if (el.Name == "CustomField") + foreach (XmlElement elm in el) + { + if (elm.Name == "CustomFieldName") { - customProperty.ID = el.Attributes["ID"].Value; + customProperty.CustomFieldName = elm.InnerText; } - - foreach (XmlElement elm in el) + if (elm.Name == "CustomFieldType") { - if (elm.Name == "CustomFieldName") - { - customProperty.CustomFieldName = elm.InnerText; - } - if (elm.Name == "CustomFieldType") - { - customProperty.CustomFieldType = elm.InnerText; - } - if (elm.Name == "CustomFieldValue") - { - customProperty.CustomFieldValue = elm.InnerText; - } + customProperty.CustomFieldType = elm.InnerText; + } + if (elm.Name == "CustomFieldValue") + { + customProperty.CustomFieldValue = elm.InnerText; } - - roomInformation.FusionCustomProperties.Add(customProperty); } + + roomInformation.FusionCustomProperties.Add(customProperty); } } - RoomInfoChange?.Invoke(this, new EventArgs()); - - CustomPropertiesBridge.EvaluateRoomInfo(Room.Key, roomInformation); } + RoomInfoChange?.Invoke(this, new EventArgs()); + + CustomPropertiesBridge.EvaluateRoomInfo(Room.Key, roomInformation); } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Error parsing Custom Properties response: {0}", e); - } - //PrintRoomInfo(); - //getRoomInfoBusy = false; - //_DynFusion.API.EISC.BooleanInput[Constants.GetRoomInfo].BoolValue = getRoomInfoBusy; } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Error parsing Custom Properties response: {0}", e); + } + //PrintRoomInfo(); + //getRoomInfoBusy = false; + //_DynFusion.API.EISC.BooleanInput[Constants.GetRoomInfo].BoolValue = getRoomInfoBusy; } + } - /// - /// Event handler method for Device Extender sig changes - /// - /// - /// - protected void FusionRoomSchedule_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, - SigEventArgs args) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Scehdule Response Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, - args.Sig.Name, args.Sig.StringValue); + /// + /// Event handler method for Device Extender sig changes + /// + /// + /// + protected void FusionRoomSchedule_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, + SigEventArgs args) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Scehdule Response Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, + args.Sig.Name, args.Sig.StringValue); - if (args.Sig == FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleResponse) + if (args.Sig == FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleResponse) + { + try { - try - { - var scheduleResponse = new ScheduleResponse(); + var scheduleResponse = new ScheduleResponse(); - var message = new XmlDocument(); + var message = new XmlDocument(); - message.LoadXml(args.Sig.StringValue); + message.LoadXml(args.Sig.StringValue); - var response = message["ScheduleResponse"]; + var response = message["ScheduleResponse"]; - if (response != null) + if (response != null) + { + // Check for push notification + if (response["RequestID"].InnerText == "RVRequest") { - // Check for push notification - if (response["RequestID"].InnerText == "RVRequest") - { - var action = response["Action"]; + var action = response["Action"]; - if (action.OuterXml.IndexOf("RequestSchedule", StringComparison.Ordinal) > -1) - { - _pushNotificationTimer.Reset(PushNotificationTimeout, PushNotificationTimeout); - } - } - else // Not a push notification + if (action.OuterXml.IndexOf("RequestSchedule", StringComparison.Ordinal) > -1) { - _currentSchedule = new RoomSchedule(); // Clear Current Schedule - _currentMeeting = null; // Clear Current Meeting - _nextMeeting = null; // Clear Next Meeting + _pushNotificationTimer.Reset(PushNotificationTimeout, PushNotificationTimeout); + } + } + else // Not a push notification + { + _currentSchedule = new RoomSchedule(); // Clear Current Schedule + _currentMeeting = null; // Clear Current Meeting + _nextMeeting = null; // Clear Next Meeting - var isNextMeeting = false; + var isNextMeeting = false; - foreach (XmlElement element in message.FirstChild.ChildNodes) + foreach (XmlElement element in message.FirstChild.ChildNodes) + { + if (element.Name == "RequestID") { - if (element.Name == "RequestID") - { - scheduleResponse.RequestID = element.InnerText; - } - else if (element.Name == "RoomID") - { - scheduleResponse.RoomID = element.InnerText; - } - else if (element.Name == "RoomName") - { - scheduleResponse.RoomName = element.InnerText; - } - else if (element.Name == "Event") - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Event Found:\n{0}", element.OuterXml); - - var reader = new XmlReader(element.OuterXml); - - var tempEvent = CrestronXMLSerialization.DeSerializeObject(reader); + scheduleResponse.RequestID = element.InnerText; + } + else if (element.Name == "RoomID") + { + scheduleResponse.RoomID = element.InnerText; + } + else if (element.Name == "RoomName") + { + scheduleResponse.RoomName = element.InnerText; + } + else if (element.Name == "Event") + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Event Found:\n{0}", element.OuterXml); - scheduleResponse.Events.Add(tempEvent); + var reader = new XmlReader(element.OuterXml); - // Check is this is the current event - if (tempEvent.dtStart <= DateTime.Now && tempEvent.dtEnd >= DateTime.Now) - { - _currentMeeting = tempEvent; // Set Current Meeting - isNextMeeting = true; // Flag that next element is next meeting - } + var tempEvent = CrestronXMLSerialization.DeSerializeObject(reader); - if (isNextMeeting) - { - _nextMeeting = tempEvent; // Set Next Meeting - isNextMeeting = false; - } + scheduleResponse.Events.Add(tempEvent); - _currentSchedule.Meetings.Add(tempEvent); + // Check is this is the current event + if (tempEvent.dtStart <= DateTime.Now && tempEvent.dtEnd >= DateTime.Now) + { + _currentMeeting = tempEvent; // Set Current Meeting + isNextMeeting = true; // Flag that next element is next meeting } - } - PrintTodaysSchedule(); + if (isNextMeeting) + { + _nextMeeting = tempEvent; // Set Next Meeting + isNextMeeting = false; + } - if (!_isRegisteredForSchedulePushNotifications) - { - _pollTimer.Reset(SchedulePollInterval, SchedulePollInterval); + _currentSchedule.Meetings.Add(tempEvent); } + } - // Fire Schedule Change Event - ScheduleChange?.Invoke(this, new ScheduleChangeEventArgs { Schedule = _currentSchedule }); + PrintTodaysSchedule(); + + if (!_isRegisteredForSchedulePushNotifications) + { + _pollTimer.Reset(SchedulePollInterval, SchedulePollInterval); } + + // Fire Schedule Change Event + ScheduleChange?.Invoke(this, new ScheduleChangeEventArgs { Schedule = _currentSchedule }); } } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Error parsing ScheduleResponse: {0}", e); - } } - else if (args.Sig == FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateResponse) + catch (Exception e) { - Debug.LogMessage(LogEventLevel.Verbose, this, "Create Meeting Response Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, - args.Sig.Name, args.Sig.StringValue); + Debug.LogMessage(LogEventLevel.Debug, this, "Error parsing ScheduleResponse: {0}", e); } } + else if (args.Sig == FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.CreateResponse) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Create Meeting Response Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, + args.Sig.Name, args.Sig.StringValue); + } + } - /// - /// Prints today's schedule to console for debugging - /// - private void PrintTodaysSchedule() + /// + /// Prints today's schedule to console for debugging + /// + private void PrintTodaysSchedule() + { + if (Debug.Level > 1) { - if (Debug.Level > 1) + if (_currentSchedule.Meetings.Count > 0) { - if (_currentSchedule.Meetings.Count > 0) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Today's Schedule for '{0}'\n", Room.Name); + Debug.LogMessage(LogEventLevel.Debug, this, "Today's Schedule for '{0}'\n", Room.Name); - foreach (var e in _currentSchedule.Meetings) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Subject: {0}", e.Subject); - Debug.LogMessage(LogEventLevel.Debug, this, "Organizer: {0}", e.Organizer); - Debug.LogMessage(LogEventLevel.Debug, this, "MeetingID: {0}", e.MeetingID); - Debug.LogMessage(LogEventLevel.Debug, this, "Start Time: {0}", e.dtStart); - Debug.LogMessage(LogEventLevel.Debug, this, "End Time: {0}", e.dtEnd); - Debug.LogMessage(LogEventLevel.Debug, this, "Duration: {0}\n", e.DurationInMinutes); - } + foreach (var e in _currentSchedule.Meetings) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Subject: {0}", e.Subject); + Debug.LogMessage(LogEventLevel.Debug, this, "Organizer: {0}", e.Organizer); + Debug.LogMessage(LogEventLevel.Debug, this, "MeetingID: {0}", e.MeetingID); + Debug.LogMessage(LogEventLevel.Debug, this, "Start Time: {0}", e.dtStart); + Debug.LogMessage(LogEventLevel.Debug, this, "End Time: {0}", e.dtEnd); + Debug.LogMessage(LogEventLevel.Debug, this, "Duration: {0}\n", e.DurationInMinutes); } } } + } - protected virtual void SetUpSources() + protected virtual void SetUpSources() + { + // Sources + var dict = ConfigReader.ConfigObject.GetSourceListForKey(Room.SourceListKey); + if (dict != null) { - // Sources - var dict = ConfigReader.ConfigObject.GetSourceListForKey(Room.SourceListKey); - if (dict != null) - { - // NEW PROCESS: - // Make these lists and insert the fusion attributes by iterating these - var setTopBoxes = dict.Where(d => d.Value.SourceDevice is ISetTopBoxControls); - uint i = 1; - foreach (var kvp in setTopBoxes) + // NEW PROCESS: + // Make these lists and insert the fusion attributes by iterating these + var setTopBoxes = dict.Where(d => d.Value.SourceDevice is ISetTopBoxControls); + uint i = 1; + foreach (var kvp in setTopBoxes) + { + TryAddRouteActionSigs(JoinMap.Display1SetTopBoxSourceStart.AttributeName + " " + i, JoinMap.Display1SetTopBoxSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice); + i++; + if (i > JoinMap.Display1SetTopBoxSourceStart.JoinSpan) // We only have five spots { - TryAddRouteActionSigs(JoinMap.Display1SetTopBoxSourceStart.AttributeName + " " + i, JoinMap.Display1SetTopBoxSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice); - i++; - if (i > JoinMap.Display1SetTopBoxSourceStart.JoinSpan) // We only have five spots - { - break; - } - } - - var discPlayers = dict.Where(d => d.Value.SourceDevice is IDiscPlayerControls); - i = 1; - foreach (var kvp in discPlayers) - { - TryAddRouteActionSigs(JoinMap.Display1DiscPlayerSourceStart.AttributeName + " " + i, JoinMap.Display1DiscPlayerSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice); - i++; - if (i > JoinMap.Display1DiscPlayerSourceStart.JoinSpan) // We only have five spots - { - break; - } + break; } + } - var laptops = dict.Where(d => d.Value.SourceDevice is IRoutingSource); - i = 1; - foreach (var kvp in laptops) + var discPlayers = dict.Where(d => d.Value.SourceDevice is IDiscPlayerControls); + i = 1; + foreach (var kvp in discPlayers) + { + TryAddRouteActionSigs(JoinMap.Display1DiscPlayerSourceStart.AttributeName + " " + i, JoinMap.Display1DiscPlayerSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice); + i++; + if (i > JoinMap.Display1DiscPlayerSourceStart.JoinSpan) // We only have five spots { - TryAddRouteActionSigs(JoinMap.Display1LaptopSourceStart.AttributeName + " " + i, JoinMap.Display1LaptopSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice); - i++; - if (i > JoinMap.Display1LaptopSourceStart.JoinSpan) // We only have ten spots??? - { - break; - } + break; } + } - foreach (var usageDevice in dict.Select(kvp => kvp.Value.SourceDevice).OfType()) + var laptops = dict.Where(d => d.Value.SourceDevice is IRoutingSource); + i = 1; + foreach (var kvp in laptops) + { + TryAddRouteActionSigs(JoinMap.Display1LaptopSourceStart.AttributeName + " " + i, JoinMap.Display1LaptopSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice); + i++; + if (i > JoinMap.Display1LaptopSourceStart.JoinSpan) // We only have ten spots??? { - usageDevice.UsageTracker = new UsageTracking(usageDevice as Device) {UsageIsTracked = true}; - usageDevice.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded; + break; } } - else + + foreach (var usageDevice in dict.Select(kvp => kvp.Value.SourceDevice).OfType()) { - Debug.LogMessage(LogEventLevel.Debug, this, "WARNING: Config source list '{0}' not found for room '{1}'", - Room.SourceListKey, Room.Key); + usageDevice.UsageTracker = new UsageTracking(usageDevice as Device) {UsageIsTracked = true}; + usageDevice.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded; } } + else + { + Debug.LogMessage(LogEventLevel.Debug, this, "WARNING: Config source list '{0}' not found for room '{1}'", + Room.SourceListKey, Room.Key); + } + } - /// - /// Collects usage data from source and sends to Fusion - /// - /// - /// - protected void UsageTracker_DeviceUsageEnded(object sender, DeviceUsageEventArgs e) + /// + /// Collects usage data from source and sends to Fusion + /// + /// + /// + protected void UsageTracker_DeviceUsageEnded(object sender, DeviceUsageEventArgs e) + { + if (!(sender is UsageTracking deviceTracker)) { - if (!(sender is UsageTracking deviceTracker)) - { - return; - } + return; + } - var group = ConfigReader.GetGroupForDeviceKey(deviceTracker.Parent.Key); + var group = ConfigReader.GetGroupForDeviceKey(deviceTracker.Parent.Key); - var currentMeetingId = "-"; + var currentMeetingId = "-"; - if (_currentMeeting != null) - { - currentMeetingId = _currentMeeting.MeetingID; - } + if (_currentMeeting != null) + { + currentMeetingId = _currentMeeting.MeetingID; + } - //String Format: "USAGE||[Date YYYY-MM-DD]||[Time HH-mm-ss]||TIME||[Asset_Type]||[Asset_Name]||[Minutes_used]||[Asset_ID]||[Meeting_ID]" - // [Asset_ID] property does not appear to be used in Crestron SSI examples. They are sending "-" instead so that's what is replicated here - var deviceUsage = string.Format("USAGE||{0}||{1}||TIME||{2}||{3}||-||{4}||-||{5}||{6}||\r\n", - e.UsageEndTime.ToString("yyyy-MM-dd"), e.UsageEndTime.ToString("HH:mm:ss"), - @group, deviceTracker.Parent.Name, e.MinutesUsed, "-", currentMeetingId); + //String Format: "USAGE||[Date YYYY-MM-DD]||[Time HH-mm-ss]||TIME||[Asset_Type]||[Asset_Name]||[Minutes_used]||[Asset_ID]||[Meeting_ID]" + // [Asset_ID] property does not appear to be used in Crestron SSI examples. They are sending "-" instead so that's what is replicated here + var deviceUsage = string.Format("USAGE||{0}||{1}||TIME||{2}||{3}||-||{4}||-||{5}||{6}||\r\n", + e.UsageEndTime.ToString("yyyy-MM-dd"), e.UsageEndTime.ToString("HH:mm:ss"), + @group, deviceTracker.Parent.Name, e.MinutesUsed, "-", currentMeetingId); - Debug.LogMessage(LogEventLevel.Debug, this, "Device usage for: {0} ended at {1}. In use for {2} minutes", - deviceTracker.Parent.Name, e.UsageEndTime, e.MinutesUsed); + Debug.LogMessage(LogEventLevel.Debug, this, "Device usage for: {0} ended at {1}. In use for {2} minutes", + deviceTracker.Parent.Name, e.UsageEndTime, e.MinutesUsed); - FusionRoom.DeviceUsage.InputSig.StringValue = deviceUsage; + FusionRoom.DeviceUsage.InputSig.StringValue = deviceUsage; - Debug.LogMessage(LogEventLevel.Debug, this, "Device usage string: {0}", deviceUsage); - } + Debug.LogMessage(LogEventLevel.Debug, this, "Device usage string: {0}", deviceUsage); + } - protected void TryAddRouteActionSigs(string attrName, uint attrNum, string routeKey, Device pSrc) + protected void TryAddRouteActionSigs(string attrName, uint attrNum, string routeKey, Device pSrc) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Creating attribute '{0}' with join {1} for source {2}", + attrName, attrNum, pSrc.Key); + try { - Debug.LogMessage(LogEventLevel.Verbose, this, "Creating attribute '{0}' with join {1} for source {2}", - attrName, attrNum, pSrc.Key); - try - { - var sigD = FusionRoom.CreateOffsetBoolSig(attrNum, attrName, eSigIoMask.InputOutputSig); - // Need feedback when this source is selected - // Event handler, added below, will compare source changes with this sig dict - _sourceToFeedbackSigs.Add(pSrc, sigD.InputSig); + var sigD = FusionRoom.CreateOffsetBoolSig(attrNum, attrName, eSigIoMask.InputOutputSig); + // Need feedback when this source is selected + // Event handler, added below, will compare source changes with this sig dict + _sourceToFeedbackSigs.Add(pSrc, sigD.InputSig); - // And respond to selection in Fusion - sigD.OutputSig.SetSigFalseAction(() => - { - if (Room is IRunRouteAction runRouteAction) - { - runRouteAction.RunRouteAction(routeKey, Room.SourceListKey); - } - }); - } - catch (Exception) + // And respond to selection in Fusion + sigD.OutputSig.SetSigFalseAction(() => { - Debug.LogMessage(LogEventLevel.Verbose, this, "Error creating Fusion signal {0} {1} for device '{2}'. THIS NEEDS REWORKING", - attrNum, attrName, pSrc.Key); - } + if (Room is IRunRouteAction runRouteAction) + { + runRouteAction.RunRouteAction(routeKey, Room.SourceListKey); + } + }); } - - /// - /// - /// - private void SetUpCommunitcationMonitors() + catch (Exception) { - uint displayNum = 0; - uint touchpanelNum = 0; - uint xpanelNum = 0; + Debug.LogMessage(LogEventLevel.Verbose, this, "Error creating Fusion signal {0} {1} for device '{2}'. THIS NEEDS REWORKING", + attrNum, attrName, pSrc.Key); + } + } + + /// + /// + /// + private void SetUpCommunitcationMonitors() + { + uint displayNum = 0; + uint touchpanelNum = 0; + uint xpanelNum = 0; - // Attach to all room's devices with monitors. - //foreach (var dev in DeviceManager.Devices) - foreach (var dev in DeviceManager.GetDevices()) + // Attach to all room's devices with monitors. + //foreach (var dev in DeviceManager.Devices) + foreach (var dev in DeviceManager.GetDevices()) + { + if (!(dev is ICommunicationMonitor)) { - if (!(dev is ICommunicationMonitor)) - { - continue; - } + continue; + } - string attrName = null; - uint attrNum = 1; + string attrName = null; + uint attrNum = 1; - //var keyNum = ExtractNumberFromKey(dev.Key); - //if (keyNum == -1) - //{ - // Debug.LogMessage(LogEventLevel.Debug, this, "WARNING: Cannot link device '{0}' to numbered Fusion monitoring attributes", - // dev.Key); - // continue; - //} - //uint attrNum = Convert.ToUInt32(keyNum); + //var keyNum = ExtractNumberFromKey(dev.Key); + //if (keyNum == -1) + //{ + // Debug.LogMessage(LogEventLevel.Debug, this, "WARNING: Cannot link device '{0}' to numbered Fusion monitoring attributes", + // dev.Key); + // continue; + //} + //uint attrNum = Convert.ToUInt32(keyNum); - // Check for UI devices - if (dev is IHasBasicTriListWithSmartObject uiDev) + // Check for UI devices + if (dev is IHasBasicTriListWithSmartObject uiDev) + { + if (uiDev.Panel is Crestron.SimplSharpPro.UI.XpanelForSmartGraphics) { - if (uiDev.Panel is Crestron.SimplSharpPro.UI.XpanelForSmartGraphics) - { - attrNum += touchpanelNum; + attrNum += touchpanelNum; - if (attrNum > JoinMap.XpanelOnlineStart.JoinSpan) - { - continue; - } - attrName = JoinMap.XpanelOnlineStart.AttributeName + " " + attrNum; - attrNum += JoinMap.XpanelOnlineStart.JoinNumber; - - touchpanelNum++; - } - else + if (attrNum > JoinMap.XpanelOnlineStart.JoinSpan) { - attrNum += xpanelNum; - - if (attrNum > JoinMap.TouchpanelOnlineStart.JoinSpan) - { - continue; - } - attrName = JoinMap.TouchpanelOnlineStart.AttributeName + " " + attrNum; - attrNum += JoinMap.TouchpanelOnlineStart.JoinNumber; - - xpanelNum++; + continue; } - } + attrName = JoinMap.XpanelOnlineStart.AttributeName + " " + attrNum; + attrNum += JoinMap.XpanelOnlineStart.JoinNumber; - //else - if (dev is IDisplay) + touchpanelNum++; + } + else { - attrNum += displayNum; - if (attrNum > JoinMap.DisplayOnlineStart.JoinSpan) + attrNum += xpanelNum; + + if (attrNum > JoinMap.TouchpanelOnlineStart.JoinSpan) { continue; } - attrName = JoinMap.DisplayOnlineStart.AttributeName + " " + attrNum; - attrNum += JoinMap.DisplayOnlineStart.JoinNumber; + attrName = JoinMap.TouchpanelOnlineStart.AttributeName + " " + attrNum; + attrNum += JoinMap.TouchpanelOnlineStart.JoinNumber; - displayNum++; + xpanelNum++; } - //else if (dev is DvdDeviceBase) - //{ - // if (attrNum > 5) - // continue; - // attrName = "Device Ok - DVD " + attrNum; - // attrNum += 260; - //} - // add set top box - - // add Cresnet roll-up - - // add DM-devices roll-up + } - if (attrName != null) + //else + if (dev is IDisplay) + { + attrNum += displayNum; + if (attrNum > JoinMap.DisplayOnlineStart.JoinSpan) { - // Link comm status to sig and update - var sigD = FusionRoom.CreateOffsetBoolSig(attrNum, attrName, eSigIoMask.InputSigOnly); - var smd = dev as ICommunicationMonitor; - sigD.InputSig.BoolValue = smd.CommunicationMonitor.Status == MonitorStatus.IsOk; - smd.CommunicationMonitor.StatusChange += - (o, a) => { sigD.InputSig.BoolValue = a.Status == MonitorStatus.IsOk; }; - Debug.LogMessage(LogEventLevel.Information, this, "Linking '{0}' communication monitor to Fusion '{1}'", dev.Key, attrName); + continue; } + attrName = JoinMap.DisplayOnlineStart.AttributeName + " " + attrNum; + attrNum += JoinMap.DisplayOnlineStart.JoinNumber; + + displayNum++; + } + //else if (dev is DvdDeviceBase) + //{ + // if (attrNum > 5) + // continue; + // attrName = "Device Ok - DVD " + attrNum; + // attrNum += 260; + //} + // add set top box + + // add Cresnet roll-up + + // add DM-devices roll-up + + if (attrName != null) + { + // Link comm status to sig and update + var sigD = FusionRoom.CreateOffsetBoolSig(attrNum, attrName, eSigIoMask.InputSigOnly); + var smd = dev as ICommunicationMonitor; + sigD.InputSig.BoolValue = smd.CommunicationMonitor.Status == MonitorStatus.IsOk; + smd.CommunicationMonitor.StatusChange += + (o, a) => { sigD.InputSig.BoolValue = a.Status == MonitorStatus.IsOk; }; + Debug.LogMessage(LogEventLevel.Information, this, "Linking '{0}' communication monitor to Fusion '{1}'", dev.Key, attrName); } } + } - protected virtual void SetUpDisplay() + protected virtual void SetUpDisplay() + { + try { - try - { - //Setup Display Usage Monitoring + //Setup Display Usage Monitoring - var displays = DeviceManager.AllDevices.Where(d => d is IDisplay); + var displays = DeviceManager.AllDevices.Where(d => d is IDisplay); - // Consider updating this in multiple display systems + // Consider updating this in multiple display systems - foreach (var display in displays.Cast()) - { - display.UsageTracker = new UsageTracking(display as Device) {UsageIsTracked = true}; - display.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded; - } + foreach (var display in displays.Cast()) + { + display.UsageTracker = new UsageTracking(display as Device) {UsageIsTracked = true}; + display.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded; + } - if (!(Room is IHasDefaultDisplay hasDefaultDisplay)) + if (!(Room is IHasDefaultDisplay hasDefaultDisplay)) + { + return; + } + if (!(hasDefaultDisplay.DefaultDisplay is IDisplay defaultDisplay)) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Cannot link null display to Fusion because default display is null"); + return; + } + + var dispPowerOnAction = new Action(b => + { + if (!b) { - return; + defaultDisplay.PowerOn(); } - if (!(hasDefaultDisplay.DefaultDisplay is IDisplay defaultDisplay)) + }); + var dispPowerOffAction = new Action(b => + { + if (!b) { - Debug.LogMessage(LogEventLevel.Debug, this, "Cannot link null display to Fusion because default display is null"); - return; + defaultDisplay.PowerOff(); } + }); - var dispPowerOnAction = new Action(b => - { - if (!b) - { - defaultDisplay.PowerOn(); - } - }); - var dispPowerOffAction = new Action(b => - { - if (!b) - { - defaultDisplay.PowerOff(); - } - }); - - // Display to fusion room sigs - FusionRoom.DisplayPowerOn.OutputSig.UserObject = dispPowerOnAction; - FusionRoom.DisplayPowerOff.OutputSig.UserObject = dispPowerOffAction; + // Display to fusion room sigs + FusionRoom.DisplayPowerOn.OutputSig.UserObject = dispPowerOnAction; + FusionRoom.DisplayPowerOff.OutputSig.UserObject = dispPowerOffAction; - MapDisplayToRoomJoins(1, JoinMap.Display1Start.JoinNumber, defaultDisplay); + MapDisplayToRoomJoins(1, JoinMap.Display1Start.JoinNumber, defaultDisplay); - var deviceConfig = - ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key)); + var deviceConfig = + ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key)); - //Check for existing asset in GUIDs collection + //Check for existing asset in GUIDs collection - FusionAsset tempAsset; + FusionAsset tempAsset; - if (FusionStaticAssets.ContainsKey(deviceConfig.Uid)) - { - tempAsset = FusionStaticAssets[deviceConfig.Uid]; - } - else - { - // Create a new asset - tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), - defaultDisplay.Name, "Display", ""); - FusionStaticAssets.Add(deviceConfig.Uid, tempAsset); - } + if (FusionStaticAssets.ContainsKey(deviceConfig.Uid)) + { + tempAsset = FusionStaticAssets[deviceConfig.Uid]; + } + else + { + // Create a new asset + tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), + defaultDisplay.Name, "Display", ""); + FusionStaticAssets.Add(deviceConfig.Uid, tempAsset); + } - var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", - tempAsset.InstanceId); - dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction; - dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction; + var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", + tempAsset.InstanceId); + dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction; + dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction; - if (defaultDisplay is IHasPowerControlWithFeedback defaultTwoWayDisplay) + if (defaultDisplay is IHasPowerControlWithFeedback defaultTwoWayDisplay) + { + defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig); + if (defaultDisplay is IDisplayUsage) { - defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig); - if (defaultDisplay is IDisplayUsage) - { - (defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig); - } - - defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig); + (defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig); } - // Use extension methods - dispAsset.TrySetMakeModel(defaultDisplay as Device); - dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay as Device); + defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig); } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Error setting up display in Fusion: {0}", e); - } - } - /// - /// Maps room attributes to a display at a specified index - /// - /// - /// - /// - /// a - protected virtual void MapDisplayToRoomJoins(int displayIndex, uint joinOffset, IDisplay display) + // Use extension methods + dispAsset.TrySetMakeModel(defaultDisplay as Device); + dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay as Device); + } + catch (Exception e) { - var displayName = string.Format("Display {0} - ", displayIndex); + Debug.LogMessage(LogEventLevel.Debug, this, "Error setting up display in Fusion: {0}", e); + } + } + + /// + /// Maps room attributes to a display at a specified index + /// + /// + /// + /// + /// a + protected virtual void MapDisplayToRoomJoins(int displayIndex, uint joinOffset, IDisplay display) + { + var displayName = string.Format("Display {0} - ", displayIndex); - if (!(Room is IHasDefaultDisplay hasDefaultDisplay) || display != hasDefaultDisplay.DefaultDisplay) + if (!(Room is IHasDefaultDisplay hasDefaultDisplay) || display != hasDefaultDisplay.DefaultDisplay) + { + return; + } + // Display volume + var defaultDisplayVolume = FusionRoom.CreateOffsetUshortSig(JoinMap.VolumeFader1.JoinNumber, JoinMap.VolumeFader1.AttributeName, + eSigIoMask.InputOutputSig); + defaultDisplayVolume.OutputSig.UserObject = new Action(b => + { + if (!(display is IBasicVolumeWithFeedback basicVolumeWithFeedback)) { return; } - // Display volume - var defaultDisplayVolume = FusionRoom.CreateOffsetUshortSig(JoinMap.VolumeFader1.JoinNumber, JoinMap.VolumeFader1.AttributeName, - eSigIoMask.InputOutputSig); - defaultDisplayVolume.OutputSig.UserObject = new Action(b => - { - if (!(display is IBasicVolumeWithFeedback basicVolumeWithFeedback)) - { - return; - } - basicVolumeWithFeedback.SetVolume(b); - basicVolumeWithFeedback.VolumeLevelFeedback.LinkInputSig(defaultDisplayVolume.InputSig); - }); + basicVolumeWithFeedback.SetVolume(b); + basicVolumeWithFeedback.VolumeLevelFeedback.LinkInputSig(defaultDisplayVolume.InputSig); + }); - // Power on - var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint) joinOffset, displayName + "Power On", - eSigIoMask.InputOutputSig); - defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => + // Power on + var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint) joinOffset, displayName + "Power On", + eSigIoMask.InputOutputSig); + defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => + { + if (!b) { - if (!b) - { - display.PowerOn(); - } - }); + display.PowerOn(); + } + }); - // Power Off - var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint) joinOffset + 1, displayName + "Power Off", - eSigIoMask.InputOutputSig); - defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => + // Power Off + var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint) joinOffset + 1, displayName + "Power Off", + eSigIoMask.InputOutputSig); + defaultDisplayPowerOn.OutputSig.UserObject = new Action(b => + { + if (!b) { - if (!b) - { - display.PowerOff(); - } - }); + display.PowerOff(); + } + }); - if (display is IHasPowerControlWithFeedback defaultTwoWayDisplay) - { - defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig); - defaultTwoWayDisplay.PowerIsOnFeedback.LinkComplementInputSig(defaultDisplayPowerOff.InputSig); - } + if (display is IHasPowerControlWithFeedback defaultTwoWayDisplay) + { + defaultTwoWayDisplay.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig); + defaultTwoWayDisplay.PowerIsOnFeedback.LinkComplementInputSig(defaultDisplayPowerOff.InputSig); + } - // Current Source - var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint) joinOffset + 8, - displayName + "Source None", eSigIoMask.InputOutputSig); - defaultDisplaySourceNone.OutputSig.UserObject = new Action(b => + // Current Source + var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint) joinOffset + 8, + displayName + "Source None", eSigIoMask.InputOutputSig); + defaultDisplaySourceNone.OutputSig.UserObject = new Action(b => + { + if (!b) { - if (!b) + if (Room is IRunRouteAction runRouteAction) { - if (Room is IRunRouteAction runRouteAction) - { - runRouteAction.RunRouteAction("roomOff", Room.SourceListKey); - } + runRouteAction.RunRouteAction("roomOff", Room.SourceListKey); } - }); - } + } + }); + } - private void SetUpError() + private void SetUpError() + { + // Roll up ALL device errors + _errorMessageRollUp = new StatusMonitorCollection(this); + foreach (var dev in DeviceManager.GetDevices()) { - // Roll up ALL device errors - _errorMessageRollUp = new StatusMonitorCollection(this); - foreach (var dev in DeviceManager.GetDevices()) + if (dev is ICommunicationMonitor md) { - if (dev is ICommunicationMonitor md) - { - _errorMessageRollUp.AddMonitor(md.CommunicationMonitor); - Debug.LogMessage(LogEventLevel.Verbose, this, "Adding '{0}' to room's overall error monitor", - md.CommunicationMonitor.Parent.Key); - } + _errorMessageRollUp.AddMonitor(md.CommunicationMonitor); + Debug.LogMessage(LogEventLevel.Verbose, this, "Adding '{0}' to room's overall error monitor", + md.CommunicationMonitor.Parent.Key); } - _errorMessageRollUp.Start(); - FusionRoom.ErrorMessage.InputSig.StringValue = _errorMessageRollUp.Message; - _errorMessageRollUp.StatusChange += - (o, a) => { FusionRoom.ErrorMessage.InputSig.StringValue = _errorMessageRollUp.Message; }; } + _errorMessageRollUp.Start(); + FusionRoom.ErrorMessage.InputSig.StringValue = _errorMessageRollUp.Message; + _errorMessageRollUp.StatusChange += + (o, a) => { FusionRoom.ErrorMessage.InputSig.StringValue = _errorMessageRollUp.Message; }; + } - /// - /// Sets up a local occupancy sensor, such as one attached to a Fusion Scheduling panel. The occupancy status of the room will be read from Fusion - /// - private void SetUpLocalOccupancy() - { - RoomIsOccupiedFeedback = new BoolFeedback(RoomIsOccupiedFeedbackFunc); + /// + /// Sets up a local occupancy sensor, such as one attached to a Fusion Scheduling panel. The occupancy status of the room will be read from Fusion + /// + private void SetUpLocalOccupancy() + { + RoomIsOccupiedFeedback = new BoolFeedback(RoomIsOccupiedFeedbackFunc); - FusionRoom.FusionAssetStateChange += FusionRoom_FusionAssetStateChange; + FusionRoom.FusionAssetStateChange += FusionRoom_FusionAssetStateChange; - // Build Occupancy Asset? - // Link sigs? + // Build Occupancy Asset? + // Link sigs? - //Room.SetRoomOccupancy(this as IOccupancyStatusProvider, 0); - } + //Room.SetRoomOccupancy(this as IOccupancyStatusProvider, 0); + } - private void FusionRoom_FusionAssetStateChange(FusionBase device, FusionAssetStateEventArgs args) + private void FusionRoom_FusionAssetStateChange(FusionBase device, FusionAssetStateEventArgs args) + { + if (args.EventId == FusionAssetEventId.RoomOccupiedReceivedEventId || + args.EventId == FusionAssetEventId.RoomUnoccupiedReceivedEventId) { - if (args.EventId == FusionAssetEventId.RoomOccupiedReceivedEventId || - args.EventId == FusionAssetEventId.RoomUnoccupiedReceivedEventId) - { - RoomIsOccupiedFeedback.FireUpdate(); - } + RoomIsOccupiedFeedback.FireUpdate(); } + } - /// - /// Sets up remote occupancy that will relay the occupancy status determined by local system devices to Fusion - /// - private void SetUpRemoteOccupancy() - { - // Need to have the room occupancy object first and somehow determine the slot number of the Occupancy asset but will not be able to use the UID from config likely. - // Consider defining an object just for Room Occupancy (either eAssetType.Occupancy Sensor (local) or eAssetType.RemoteOccupancySensor (from Fusion sched. panel)) and reserving slot 4 for that asset (statics would start at 5) - - //if (Room.OccupancyObj != null) - //{ + /// + /// Sets up remote occupancy that will relay the occupancy status determined by local system devices to Fusion + /// + private void SetUpRemoteOccupancy() + { + // Need to have the room occupancy object first and somehow determine the slot number of the Occupancy asset but will not be able to use the UID from config likely. + // Consider defining an object just for Room Occupancy (either eAssetType.Occupancy Sensor (local) or eAssetType.RemoteOccupancySensor (from Fusion sched. panel)) and reserving slot 4 for that asset (statics would start at 5) - var tempOccAsset = _guiDs.OccupancyAsset; + //if (Room.OccupancyObj != null) + //{ - if (tempOccAsset == null) - { - FusionOccSensor = new FusionOccupancySensorAsset(eAssetType.OccupancySensor); - tempOccAsset = FusionOccSensor; - } + var tempOccAsset = _guiDs.OccupancyAsset; - var occSensorAsset = FusionRoom.CreateOccupancySensorAsset(tempOccAsset.SlotNumber, tempOccAsset.Name, - "Occupancy Sensor", tempOccAsset.InstanceId); + if (tempOccAsset == null) + { + FusionOccSensor = new FusionOccupancySensorAsset(eAssetType.OccupancySensor); + tempOccAsset = FusionOccSensor; + } - occSensorAsset.RoomOccupied.AddSigToRVIFile = true; + var occSensorAsset = FusionRoom.CreateOccupancySensorAsset(tempOccAsset.SlotNumber, tempOccAsset.Name, + "Occupancy Sensor", tempOccAsset.InstanceId); - //var occSensorShutdownMinutes = FusionRoom.CreateOffsetUshortSig(70, "Occ Shutdown - Minutes", eSigIoMask.InputOutputSig); + occSensorAsset.RoomOccupied.AddSigToRVIFile = true; - // Tie to method on occupancy object - //occSensorShutdownMinutes.OutputSig.UserObject(new Action(ushort)(b => Room.OccupancyObj.SetShutdownMinutes(b)); + //var occSensorShutdownMinutes = FusionRoom.CreateOffsetUshortSig(70, "Occ Shutdown - Minutes", eSigIoMask.InputOutputSig); + // Tie to method on occupancy object + //occSensorShutdownMinutes.OutputSig.UserObject(new Action(ushort)(b => Room.OccupancyObj.SetShutdownMinutes(b)); - if (Room is IRoomOccupancy occRoom) - { - occRoom.RoomOccupancy.RoomIsOccupiedFeedback.LinkInputSig(occSensorAsset.RoomOccupied.InputSig); - occRoom.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange; - } - RoomOccupancyRemoteStringFeedback = new StringFeedback(() => _roomOccupancyRemoteString); - - RoomOccupancyRemoteStringFeedback.LinkInputSig(occSensorAsset.RoomOccupancyInfo.InputSig); - //} + if (Room is IRoomOccupancy occRoom) + { + occRoom.RoomOccupancy.RoomIsOccupiedFeedback.LinkInputSig(occSensorAsset.RoomOccupied.InputSig); + occRoom.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange; } + RoomOccupancyRemoteStringFeedback = new StringFeedback(() => _roomOccupancyRemoteString); + + RoomOccupancyRemoteStringFeedback.LinkInputSig(occSensorAsset.RoomOccupancyInfo.InputSig); + + //} + } - private void RoomIsOccupiedFeedback_OutputChange(object sender, FeedbackEventArgs e) + private void RoomIsOccupiedFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + _roomOccupancyRemoteString = String.Format(RemoteOccupancyXml, e.BoolValue ? "Occupied" : "Unoccupied"); + RoomOccupancyRemoteStringFeedback.FireUpdate(); + } + + /// + /// Helper to get the number from the end of a device's key string + /// + /// -1 if no number matched + private int ExtractNumberFromKey(string key) + { + var capture = System.Text.RegularExpressions.Regex.Match(key, @"\b(\d+)"); + if (!capture.Success) { - _roomOccupancyRemoteString = String.Format(RemoteOccupancyXml, e.BoolValue ? "Occupied" : "Unoccupied"); - RoomOccupancyRemoteStringFeedback.FireUpdate(); + return -1; } + return Convert.ToInt32(capture.Groups[1].Value); + } - /// - /// Helper to get the number from the end of a device's key string - /// - /// -1 if no number matched - private int ExtractNumberFromKey(string key) + /// + /// Event handler for when room source changes + /// + protected void Room_CurrentSourceInfoChange(SourceListItem info, ChangeType type) + { + // Handle null. Nothing to do when switching from or to null + if (info == null || info.SourceDevice == null) { - var capture = System.Text.RegularExpressions.Regex.Match(key, @"\b(\d+)"); - if (!capture.Success) - { - return -1; - } - return Convert.ToInt32(capture.Groups[1].Value); + return; } - /// - /// Event handler for when room source changes - /// - protected void Room_CurrentSourceInfoChange(SourceListItem info, ChangeType type) + var dev = info.SourceDevice; + if (type == ChangeType.WillChange) { - // Handle null. Nothing to do when switching from or to null - if (info == null || info.SourceDevice == null) - { - return; - } - - var dev = info.SourceDevice; - if (type == ChangeType.WillChange) + if (_sourceToFeedbackSigs.ContainsKey(dev)) { - if (_sourceToFeedbackSigs.ContainsKey(dev)) - { - _sourceToFeedbackSigs[dev].BoolValue = false; - } + _sourceToFeedbackSigs[dev].BoolValue = false; } - else + } + else + { + if (_sourceToFeedbackSigs.ContainsKey(dev)) { - if (_sourceToFeedbackSigs.ContainsKey(dev)) - { - _sourceToFeedbackSigs[dev].BoolValue = true; - } - //var name = (room == null ? "" : room.Name); - CurrentRoomSourceNameSig.InputSig.StringValue = info.SourceDevice.Name; + _sourceToFeedbackSigs[dev].BoolValue = true; } + //var name = (room == null ? "" : room.Name); + CurrentRoomSourceNameSig.InputSig.StringValue = info.SourceDevice.Name; } + } - protected void FusionRoom_FusionStateChange(FusionBase device, FusionStateEventArgs args) - { - // The sig/UO method: Need separate handlers for fixed and user sigs, all flavors, - // even though they all contain sigs. - + protected void FusionRoom_FusionStateChange(FusionBase device, FusionStateEventArgs args) + { + // The sig/UO method: Need separate handlers for fixed and user sigs, all flavors, + // even though they all contain sigs. - BoolOutputSig outSig; - if (args.UserConfiguredSigDetail is BooleanSigDataFixedName sigData) - { - outSig = sigData.OutputSig; - if (outSig.UserObject is Action) - { - (outSig.UserObject as Action).Invoke(outSig.BoolValue); - } - else if (outSig.UserObject is Action) - { - (outSig.UserObject as Action).Invoke(outSig.UShortValue); - } - else if (outSig.UserObject is Action) - { - (outSig.UserObject as Action).Invoke(outSig.StringValue); - } - return; - } - var attrData = (args.UserConfiguredSigDetail as BooleanSigData); - if (attrData == null) - { - return; - } - outSig = attrData.OutputSig; + BoolOutputSig outSig; + if (args.UserConfiguredSigDetail is BooleanSigDataFixedName sigData) + { + outSig = sigData.OutputSig; if (outSig.UserObject is Action) { (outSig.UserObject as Action).Invoke(outSig.BoolValue); @@ -1613,191 +1592,211 @@ protected void FusionRoom_FusionStateChange(FusionBase device, FusionStateEventA { (outSig.UserObject as Action).Invoke(outSig.StringValue); } + return; + } + + var attrData = (args.UserConfiguredSigDetail as BooleanSigData); + if (attrData == null) + { + return; + } + outSig = attrData.OutputSig; + if (outSig.UserObject is Action) + { + (outSig.UserObject as Action).Invoke(outSig.BoolValue); + } + else if (outSig.UserObject is Action) + { + (outSig.UserObject as Action).Invoke(outSig.UShortValue); + } + else if (outSig.UserObject is Action) + { + (outSig.UserObject as Action).Invoke(outSig.StringValue); } } +} - public static class FusionRoomExtensions +public static class FusionRoomExtensions +{ + /// + /// Creates and returns a fusion attribute. The join number will match the established Simpl + /// standard of 50+, and will generate a 50+ join in the RVI. It calls + /// FusionRoom.AddSig with join number - 49 + /// + /// The new attribute + public static BooleanSigData CreateOffsetBoolSig(this FusionRoom fr, uint number, string name, eSigIoMask mask) { - /// - /// Creates and returns a fusion attribute. The join number will match the established Simpl - /// standard of 50+, and will generate a 50+ join in the RVI. It calls - /// FusionRoom.AddSig with join number - 49 - /// - /// The new attribute - public static BooleanSigData CreateOffsetBoolSig(this FusionRoom fr, uint number, string name, eSigIoMask mask) - { - if (number < 50) - { - throw new ArgumentOutOfRangeException("number", "Cannot be less than 50"); - } - number -= 49; - fr.AddSig(eSigType.Bool, number, name, mask); - return fr.UserDefinedBooleanSigDetails[number]; + if (number < 50) + { + throw new ArgumentOutOfRangeException("number", "Cannot be less than 50"); } + number -= 49; + fr.AddSig(eSigType.Bool, number, name, mask); + return fr.UserDefinedBooleanSigDetails[number]; + } - /// - /// Creates and returns a fusion attribute. The join number will match the established Simpl - /// standard of 50+, and will generate a 50+ join in the RVI. It calls - /// FusionRoom.AddSig with join number - 49 - /// - /// The new attribute - public static UShortSigData CreateOffsetUshortSig(this FusionRoom fr, uint number, string name, eSigIoMask mask) + /// + /// Creates and returns a fusion attribute. The join number will match the established Simpl + /// standard of 50+, and will generate a 50+ join in the RVI. It calls + /// FusionRoom.AddSig with join number - 49 + /// + /// The new attribute + public static UShortSigData CreateOffsetUshortSig(this FusionRoom fr, uint number, string name, eSigIoMask mask) + { + if (number < 50) { - if (number < 50) - { - throw new ArgumentOutOfRangeException("number", "Cannot be less than 50"); - } - number -= 49; - fr.AddSig(eSigType.UShort, number, name, mask); - return fr.UserDefinedUShortSigDetails[number]; + throw new ArgumentOutOfRangeException("number", "Cannot be less than 50"); } + number -= 49; + fr.AddSig(eSigType.UShort, number, name, mask); + return fr.UserDefinedUShortSigDetails[number]; + } - /// - /// Creates and returns a fusion attribute. The join number will match the established Simpl - /// standard of 50+, and will generate a 50+ join in the RVI. It calls - /// FusionRoom.AddSig with join number - 49 - /// - /// The new attribute - public static StringSigData CreateOffsetStringSig(this FusionRoom fr, uint number, string name, eSigIoMask mask) + /// + /// Creates and returns a fusion attribute. The join number will match the established Simpl + /// standard of 50+, and will generate a 50+ join in the RVI. It calls + /// FusionRoom.AddSig with join number - 49 + /// + /// The new attribute + public static StringSigData CreateOffsetStringSig(this FusionRoom fr, uint number, string name, eSigIoMask mask) + { + if (number < 50) { - if (number < 50) - { - throw new ArgumentOutOfRangeException("number", "Cannot be less than 50"); - } - number -= 49; - fr.AddSig(eSigType.String, number, name, mask); - return fr.UserDefinedStringSigDetails[number]; + throw new ArgumentOutOfRangeException("number", "Cannot be less than 50"); } + number -= 49; + fr.AddSig(eSigType.String, number, name, mask); + return fr.UserDefinedStringSigDetails[number]; + } - /// - /// Creates and returns a static asset - /// - /// the new asset - public static FusionStaticAsset CreateStaticAsset(this FusionRoom fr, uint number, string name, string type, - string instanceId) + /// + /// Creates and returns a static asset + /// + /// the new asset + public static FusionStaticAsset CreateStaticAsset(this FusionRoom fr, uint number, string name, string type, + string instanceId) + { + try { - try - { - Debug.LogMessage(LogEventLevel.Information, "Adding Fusion Static Asset '{0}' to slot {1} with GUID: '{2}'", name, number, instanceId); + Debug.LogMessage(LogEventLevel.Information, "Adding Fusion Static Asset '{0}' to slot {1} with GUID: '{2}'", name, number, instanceId); - fr.AddAsset(eAssetType.StaticAsset, number, name, type, instanceId); - return fr.UserConfigurableAssetDetails[number].Asset as FusionStaticAsset; - } - catch (InvalidOperationException ex) - { - Debug.LogMessage(LogEventLevel.Information, "Error creating Static Asset for device: '{0}'. Check that multiple devices don't have missing or duplicate uid properties in configuration. /r/nError: {1}", name, ex); - return null; - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Verbose, "Error creating Static Asset: {0}", e); - return null; - } + fr.AddAsset(eAssetType.StaticAsset, number, name, type, instanceId); + return fr.UserConfigurableAssetDetails[number].Asset as FusionStaticAsset; + } + catch (InvalidOperationException ex) + { + Debug.LogMessage(LogEventLevel.Information, "Error creating Static Asset for device: '{0}'. Check that multiple devices don't have missing or duplicate uid properties in configuration. /r/nError: {1}", name, ex); + return null; } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Verbose, "Error creating Static Asset: {0}", e); + return null; + } + } - public static FusionOccupancySensor CreateOccupancySensorAsset(this FusionRoom fr, uint number, string name, - string type, string instanceId) + public static FusionOccupancySensor CreateOccupancySensorAsset(this FusionRoom fr, uint number, string name, + string type, string instanceId) + { + try { - try - { - Debug.LogMessage(LogEventLevel.Information, "Adding Fusion Occupancy Sensor Asset '{0}' to slot {1} with GUID: '{2}'", name, number, - instanceId); + Debug.LogMessage(LogEventLevel.Information, "Adding Fusion Occupancy Sensor Asset '{0}' to slot {1} with GUID: '{2}'", name, number, + instanceId); - fr.AddAsset(eAssetType.OccupancySensor, number, name, type, instanceId); - return fr.UserConfigurableAssetDetails[number].Asset as FusionOccupancySensor; - } - catch (InvalidOperationException ex) - { - Debug.LogMessage(LogEventLevel.Information, "Error creating Static Asset for device: '{0}'. Check that multiple devices don't have missing or duplicate uid properties in configuration. Error: {1}", name, ex); - return null; - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Error, "Error creating Static Asset: {0}", e); - return null; - } + fr.AddAsset(eAssetType.OccupancySensor, number, name, type, instanceId); + return fr.UserConfigurableAssetDetails[number].Asset as FusionOccupancySensor; + } + catch (InvalidOperationException ex) + { + Debug.LogMessage(LogEventLevel.Information, "Error creating Static Asset for device: '{0}'. Check that multiple devices don't have missing or duplicate uid properties in configuration. Error: {1}", name, ex); + return null; + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Error, "Error creating Static Asset: {0}", e); + return null; } } +} - //************************************************************************************************ +//************************************************************************************************ +/// +/// Extensions to enhance Fusion room, asset and signal creation. +/// +public static class FusionStaticAssetExtensions +{ /// - /// Extensions to enhance Fusion room, asset and signal creation. + /// Tries to set a Fusion asset with the make and model of a device. + /// If the provided Device is IMakeModel, will set the corresponding parameters on the fusion static asset. + /// Otherwise, does nothing. /// - public static class FusionStaticAssetExtensions + public static void TrySetMakeModel(this FusionStaticAsset asset, Device device) { - /// - /// Tries to set a Fusion asset with the make and model of a device. - /// If the provided Device is IMakeModel, will set the corresponding parameters on the fusion static asset. - /// Otherwise, does nothing. - /// - public static void TrySetMakeModel(this FusionStaticAsset asset, Device device) - { - if (device is IMakeModel mm) - { - asset.ParamMake.Value = mm.DeviceMake; - asset.ParamModel.Value = mm.DeviceModel; - } - } - - /// - /// Tries to attach the AssetError input on a Fusion asset to a Device's - /// CommunicationMonitor.StatusChange event. Does nothing if the device is not - /// IStatusMonitor - /// - /// - /// - public static void TryLinkAssetErrorToCommunication(this FusionStaticAsset asset, Device device) + if (device is IMakeModel mm) { - if (device is ICommunicationMonitor) - { - var monitor = (device as ICommunicationMonitor).CommunicationMonitor; - monitor.StatusChange += (o, a) => - { - // Link connected and error inputs on asset - asset.Connected.InputSig.BoolValue = a.Status == MonitorStatus.IsOk; - asset.AssetError.InputSig.StringValue = a.Status.ToString(); - }; - // set current value - asset.Connected.InputSig.BoolValue = monitor.Status == MonitorStatus.IsOk; - asset.AssetError.InputSig.StringValue = monitor.Status.ToString(); - } + asset.ParamMake.Value = mm.DeviceMake; + asset.ParamModel.Value = mm.DeviceModel; } } - public class RoomInformation + /// + /// Tries to attach the AssetError input on a Fusion asset to a Device's + /// CommunicationMonitor.StatusChange event. Does nothing if the device is not + /// IStatusMonitor + /// + /// + /// + public static void TryLinkAssetErrorToCommunication(this FusionStaticAsset asset, Device device) { - public RoomInformation() + if (device is ICommunicationMonitor) { - FusionCustomProperties = new List(); + var monitor = (device as ICommunicationMonitor).CommunicationMonitor; + monitor.StatusChange += (o, a) => + { + // Link connected and error inputs on asset + asset.Connected.InputSig.BoolValue = a.Status == MonitorStatus.IsOk; + asset.AssetError.InputSig.StringValue = a.Status.ToString(); + }; + // set current value + asset.Connected.InputSig.BoolValue = monitor.Status == MonitorStatus.IsOk; + asset.AssetError.InputSig.StringValue = monitor.Status.ToString(); } - - public string ID { get; set; } - public string Name { get; set; } - public string Location { get; set; } - public string Description { get; set; } - public string TimeZone { get; set; } - public string WebcamURL { get; set; } - public string BacklogMsg { get; set; } - public string SubErrorMsg { get; set; } - public string EmailInfo { get; set; } - public List FusionCustomProperties { get; set; } } +} - public class FusionCustomProperty +public class RoomInformation +{ + public RoomInformation() { - public FusionCustomProperty() - { - } + FusionCustomProperties = new List(); + } - public FusionCustomProperty(string id) - { - ID = id; - } + public string ID { get; set; } + public string Name { get; set; } + public string Location { get; set; } + public string Description { get; set; } + public string TimeZone { get; set; } + public string WebcamURL { get; set; } + public string BacklogMsg { get; set; } + public string SubErrorMsg { get; set; } + public string EmailInfo { get; set; } + public List FusionCustomProperties { get; set; } +} + +public class FusionCustomProperty +{ + public FusionCustomProperty() + { + } - public string ID { get; set; } - public string CustomFieldName { get; set; } - public string CustomFieldType { get; set; } - public string CustomFieldValue { get; set; } + public FusionCustomProperty(string id) + { + ID = id; } + + public string ID { get; set; } + public string CustomFieldName { get; set; } + public string CustomFieldType { get; set; } + public string CustomFieldValue { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Fusion/EssentialsHuddleSpaceRoomFusionRoomJoinMap.cs b/src/PepperDash.Essentials.Core/Fusion/EssentialsHuddleSpaceRoomFusionRoomJoinMap.cs index 33f2fe1bc..37d1e6a57 100644 --- a/src/PepperDash.Essentials.Core/Fusion/EssentialsHuddleSpaceRoomFusionRoomJoinMap.cs +++ b/src/PepperDash.Essentials.Core/Fusion/EssentialsHuddleSpaceRoomFusionRoomJoinMap.cs @@ -7,144 +7,143 @@ using PepperDash.Essentials.Core.Bridges; -namespace PepperDash.Essentials.Core.Fusion +namespace PepperDash.Essentials.Core.Fusion; + +public class EssentialsHuddleSpaceRoomFusionRoomJoinMap : JoinMapBaseAdvanced { - public class EssentialsHuddleSpaceRoomFusionRoomJoinMap : JoinMapBaseAdvanced + + // Processor Attributes + [JoinName("ProcessorIp1")] + public JoinDataComplete ProcessorIp1 = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1, AttributeName = "Info - Processor - IP 1" }, + new JoinMetadata { Description = "Info - Processor - IP 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + + [JoinName("ProcessorIp2")] + public JoinDataComplete ProcessorIp2 = new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1, AttributeName = "Info - Processor - IP 2" }, + new JoinMetadata { Description = "Info - Processor - IP 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + + [JoinName("ProcessorGateway")] + public JoinDataComplete ProcessorGateway = new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1, AttributeName = "Info - Processor - Gateway" }, + new JoinMetadata { Description = "Info - Processor - Gateway", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + + [JoinName("ProcessorHostname")] + public JoinDataComplete ProcessorHostname = new JoinDataComplete(new JoinData { JoinNumber = 53, JoinSpan = 1, AttributeName = "Info - Processor - Hostname" }, + new JoinMetadata { Description = "Info - Processor - Hostname", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + + [JoinName("ProcessorDomain")] + public JoinDataComplete ProcessorDomain = new JoinDataComplete(new JoinData { JoinNumber = 54, JoinSpan = 1, AttributeName = "Info - Processor - Domain" }, + new JoinMetadata { Description = "Info - Processor - Domain", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + + [JoinName("ProcessorDns1")] + public JoinDataComplete ProcessorDns1 = new JoinDataComplete(new JoinData { JoinNumber = 55, JoinSpan = 1, AttributeName = "Info - Processor - DNS 1" }, + new JoinMetadata { Description = "Info - Processor - DNS 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + + [JoinName("ProcessorDns2")] + public JoinDataComplete ProcessorDns2 = new JoinDataComplete(new JoinData { JoinNumber = 56, JoinSpan = 1, AttributeName = "Info - Processor - DNS 2" }, + new JoinMetadata { Description = "Info - Processor - DNS 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + + [JoinName("ProcessorMac1")] + public JoinDataComplete ProcessorMac1 = new JoinDataComplete(new JoinData { JoinNumber = 57, JoinSpan = 1, AttributeName = "Info - Processor - MAC 1" }, + new JoinMetadata { Description = "Info - Processor - MAC 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + + [JoinName("ProcessorMac2")] + public JoinDataComplete ProcessorMac2 = new JoinDataComplete(new JoinData { JoinNumber = 58, JoinSpan = 1, AttributeName = "Info - Processor - MAC 2" }, + new JoinMetadata { Description = "Info - Processor - MAC 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + + [JoinName("ProcessorNetMask1")] + public JoinDataComplete ProcessorNetMask1 = new JoinDataComplete(new JoinData { JoinNumber = 59, JoinSpan = 1, AttributeName = "Info - Processor - Net Mask 1" }, + new JoinMetadata { Description = "Info - Processor - Net Mask 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + + [JoinName("ProcessorNetMask2")] + public JoinDataComplete ProcessorNetMask2 = new JoinDataComplete(new JoinData { JoinNumber = 60, JoinSpan = 1, AttributeName = "Info - Processor - Net Mask 2" }, + new JoinMetadata { Description = "Info - Processor - Net Mask 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + + [JoinName("ProcessorFirmware")] + public JoinDataComplete ProcessorFirmware = new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1, AttributeName = "Info - Processor - Firmware" }, + new JoinMetadata { Description = "Info - Processor - Firmware", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + + [JoinName("ProgramNameStart")] + public JoinDataComplete ProgramNameStart = new JoinDataComplete(new JoinData { JoinNumber = 62, JoinSpan = 10, AttributeName = "Info - Processor - Program" }, + new JoinMetadata { Description = "Info - Processor - Program", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + + [JoinName("ProcessorReboot")] + public JoinDataComplete ProcessorReboot = new JoinDataComplete(new JoinData { JoinNumber = 74, JoinSpan = 1, AttributeName = "Processor - Reboot" }, + new JoinMetadata { Description = "Processor - Reboot", JoinCapabilities = eJoinCapabilities.FromFusion, JoinType = eJoinType.Digital }); + + // Volume Controls + [JoinName("VolumeFader1")] + public JoinDataComplete VolumeFader1 = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1, AttributeName = "Volume - Fader01" }, + new JoinMetadata { Description = "Volume - Fader01", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Analog }); + + // Codec Info + [JoinName("VcCodecInCall")] + public JoinDataComplete VcCodecInCall = new JoinDataComplete(new JoinData { JoinNumber = 69, JoinSpan = 1, AttributeName = "Conf - VC 1 In Call" }, + new JoinMetadata { Description = "Conf - VC 1 In Call", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital }); + + [JoinName("VcCodecOnline")] + public JoinDataComplete VcCodecOnline = new JoinDataComplete(new JoinData { JoinNumber = 122, JoinSpan = 1, AttributeName = "Online - VC 1" }, + new JoinMetadata { Description = "Online - VC 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital }); + + [JoinName("VcCodecIpAddress")] + public JoinDataComplete VcCodecIpAddress = new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1, AttributeName = "IP Address - VC" }, + new JoinMetadata { Description = "IP Address - VC", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + + [JoinName("VcCodecIpPort")] + public JoinDataComplete VcCodecIpPort = new JoinDataComplete(new JoinData { JoinNumber = 150, JoinSpan = 1, AttributeName = "IP Port - VC" }, + new JoinMetadata { Description = "IP Port - VC", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + + // Source Attributes + [JoinName("Display1CurrentSourceName")] + public JoinDataComplete Display1CurrentSourceName = new JoinDataComplete(new JoinData { JoinNumber = 84, JoinSpan = 1, AttributeName = "Display 1 - Current Source" }, + new JoinMetadata { Description = "Display 1 - Current Source", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + + + // Device Online Status + [JoinName("TouchpanelOnlineStart")] + public JoinDataComplete TouchpanelOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 150, JoinSpan = 10, AttributeName = "Online - Touch Panel" }, + new JoinMetadata { Description = "Online - Touch Panel", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital }); + + [JoinName("XpanelOnlineStart")] + public JoinDataComplete XpanelOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 160, JoinSpan = 5, AttributeName = "Online - XPanel" }, + new JoinMetadata { Description = "Online - XPanel", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital }); + + [JoinName("DisplayOnlineStart")] + public JoinDataComplete DisplayOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 170, JoinSpan = 10, AttributeName = "Online - Display" }, + new JoinMetadata { Description = "Online - Display", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital }); + + [JoinName("Display1LaptopSourceStart")] + public JoinDataComplete Display1LaptopSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 166, JoinSpan = 5, AttributeName = "Display 1 - Source Laptop" }, + new JoinMetadata { Description = "Display 1 - Source Laptop", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital }); + + [JoinName("Display1DiscPlayerSourceStart")] + public JoinDataComplete Display1DiscPlayerSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 181, JoinSpan = 5, AttributeName = "Display 1 - Source Disc Player" }, + new JoinMetadata { Description = "Display 1 - Source Disc Player", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital }); + + [JoinName("Display1SetTopBoxSourceStart")] + public JoinDataComplete Display1SetTopBoxSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 188, JoinSpan = 5, AttributeName = "Display 1 - Source TV" }, + new JoinMetadata { Description = "Display 1 - Source TV", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital }); + + // Display 1 + [JoinName("Display1Start")] + public JoinDataComplete Display1Start = new JoinDataComplete(new JoinData { JoinNumber = 158, JoinSpan = 1 }, + new JoinMetadata { Description = "Display 1 Start", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital }); + + + /// + /// Constructor to use when instantiating this Join Map without inheriting from it + /// + /// Join this join map will start at + public EssentialsHuddleSpaceRoomFusionRoomJoinMap(uint joinStart) + : base(joinStart, typeof(EssentialsHuddleSpaceRoomFusionRoomJoinMap)) { - // Processor Attributes - [JoinName("ProcessorIp1")] - public JoinDataComplete ProcessorIp1 = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1, AttributeName = "Info - Processor - IP 1" }, - new JoinMetadata { Description = "Info - Processor - IP 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); - - [JoinName("ProcessorIp2")] - public JoinDataComplete ProcessorIp2 = new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1, AttributeName = "Info - Processor - IP 2" }, - new JoinMetadata { Description = "Info - Processor - IP 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); - - [JoinName("ProcessorGateway")] - public JoinDataComplete ProcessorGateway = new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1, AttributeName = "Info - Processor - Gateway" }, - new JoinMetadata { Description = "Info - Processor - Gateway", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); - - [JoinName("ProcessorHostname")] - public JoinDataComplete ProcessorHostname = new JoinDataComplete(new JoinData { JoinNumber = 53, JoinSpan = 1, AttributeName = "Info - Processor - Hostname" }, - new JoinMetadata { Description = "Info - Processor - Hostname", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); + } - [JoinName("ProcessorDomain")] - public JoinDataComplete ProcessorDomain = new JoinDataComplete(new JoinData { JoinNumber = 54, JoinSpan = 1, AttributeName = "Info - Processor - Domain" }, - new JoinMetadata { Description = "Info - Processor - Domain", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); - - [JoinName("ProcessorDns1")] - public JoinDataComplete ProcessorDns1 = new JoinDataComplete(new JoinData { JoinNumber = 55, JoinSpan = 1, AttributeName = "Info - Processor - DNS 1" }, - new JoinMetadata { Description = "Info - Processor - DNS 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); - - [JoinName("ProcessorDns2")] - public JoinDataComplete ProcessorDns2 = new JoinDataComplete(new JoinData { JoinNumber = 56, JoinSpan = 1, AttributeName = "Info - Processor - DNS 2" }, - new JoinMetadata { Description = "Info - Processor - DNS 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); - - [JoinName("ProcessorMac1")] - public JoinDataComplete ProcessorMac1 = new JoinDataComplete(new JoinData { JoinNumber = 57, JoinSpan = 1, AttributeName = "Info - Processor - MAC 1" }, - new JoinMetadata { Description = "Info - Processor - MAC 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); - - [JoinName("ProcessorMac2")] - public JoinDataComplete ProcessorMac2 = new JoinDataComplete(new JoinData { JoinNumber = 58, JoinSpan = 1, AttributeName = "Info - Processor - MAC 2" }, - new JoinMetadata { Description = "Info - Processor - MAC 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); - - [JoinName("ProcessorNetMask1")] - public JoinDataComplete ProcessorNetMask1 = new JoinDataComplete(new JoinData { JoinNumber = 59, JoinSpan = 1, AttributeName = "Info - Processor - Net Mask 1" }, - new JoinMetadata { Description = "Info - Processor - Net Mask 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); - - [JoinName("ProcessorNetMask2")] - public JoinDataComplete ProcessorNetMask2 = new JoinDataComplete(new JoinData { JoinNumber = 60, JoinSpan = 1, AttributeName = "Info - Processor - Net Mask 2" }, - new JoinMetadata { Description = "Info - Processor - Net Mask 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); - - [JoinName("ProcessorFirmware")] - public JoinDataComplete ProcessorFirmware = new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1, AttributeName = "Info - Processor - Firmware" }, - new JoinMetadata { Description = "Info - Processor - Firmware", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); - - [JoinName("ProgramNameStart")] - public JoinDataComplete ProgramNameStart = new JoinDataComplete(new JoinData { JoinNumber = 62, JoinSpan = 10, AttributeName = "Info - Processor - Program" }, - new JoinMetadata { Description = "Info - Processor - Program", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); - - [JoinName("ProcessorReboot")] - public JoinDataComplete ProcessorReboot = new JoinDataComplete(new JoinData { JoinNumber = 74, JoinSpan = 1, AttributeName = "Processor - Reboot" }, - new JoinMetadata { Description = "Processor - Reboot", JoinCapabilities = eJoinCapabilities.FromFusion, JoinType = eJoinType.Digital }); - - // Volume Controls - [JoinName("VolumeFader1")] - public JoinDataComplete VolumeFader1 = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1, AttributeName = "Volume - Fader01" }, - new JoinMetadata { Description = "Volume - Fader01", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Analog }); - - // Codec Info - [JoinName("VcCodecInCall")] - public JoinDataComplete VcCodecInCall = new JoinDataComplete(new JoinData { JoinNumber = 69, JoinSpan = 1, AttributeName = "Conf - VC 1 In Call" }, - new JoinMetadata { Description = "Conf - VC 1 In Call", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital }); - - [JoinName("VcCodecOnline")] - public JoinDataComplete VcCodecOnline = new JoinDataComplete(new JoinData { JoinNumber = 122, JoinSpan = 1, AttributeName = "Online - VC 1" }, - new JoinMetadata { Description = "Online - VC 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital }); - - [JoinName("VcCodecIpAddress")] - public JoinDataComplete VcCodecIpAddress = new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1, AttributeName = "IP Address - VC" }, - new JoinMetadata { Description = "IP Address - VC", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); - - [JoinName("VcCodecIpPort")] - public JoinDataComplete VcCodecIpPort = new JoinDataComplete(new JoinData { JoinNumber = 150, JoinSpan = 1, AttributeName = "IP Port - VC" }, - new JoinMetadata { Description = "IP Port - VC", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); - - // Source Attributes - [JoinName("Display1CurrentSourceName")] - public JoinDataComplete Display1CurrentSourceName = new JoinDataComplete(new JoinData { JoinNumber = 84, JoinSpan = 1, AttributeName = "Display 1 - Current Source" }, - new JoinMetadata { Description = "Display 1 - Current Source", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial }); - - - // Device Online Status - [JoinName("TouchpanelOnlineStart")] - public JoinDataComplete TouchpanelOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 150, JoinSpan = 10, AttributeName = "Online - Touch Panel" }, - new JoinMetadata { Description = "Online - Touch Panel", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital }); - - [JoinName("XpanelOnlineStart")] - public JoinDataComplete XpanelOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 160, JoinSpan = 5, AttributeName = "Online - XPanel" }, - new JoinMetadata { Description = "Online - XPanel", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital }); - - [JoinName("DisplayOnlineStart")] - public JoinDataComplete DisplayOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 170, JoinSpan = 10, AttributeName = "Online - Display" }, - new JoinMetadata { Description = "Online - Display", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital }); - - [JoinName("Display1LaptopSourceStart")] - public JoinDataComplete Display1LaptopSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 166, JoinSpan = 5, AttributeName = "Display 1 - Source Laptop" }, - new JoinMetadata { Description = "Display 1 - Source Laptop", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital }); - - [JoinName("Display1DiscPlayerSourceStart")] - public JoinDataComplete Display1DiscPlayerSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 181, JoinSpan = 5, AttributeName = "Display 1 - Source Disc Player" }, - new JoinMetadata { Description = "Display 1 - Source Disc Player", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital }); - - [JoinName("Display1SetTopBoxSourceStart")] - public JoinDataComplete Display1SetTopBoxSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 188, JoinSpan = 5, AttributeName = "Display 1 - Source TV" }, - new JoinMetadata { Description = "Display 1 - Source TV", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital }); - - // Display 1 - [JoinName("Display1Start")] - public JoinDataComplete Display1Start = new JoinDataComplete(new JoinData { JoinNumber = 158, JoinSpan = 1 }, - new JoinMetadata { Description = "Display 1 Start", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital }); - - - /// - /// Constructor to use when instantiating this Join Map without inheriting from it - /// - /// Join this join map will start at - public EssentialsHuddleSpaceRoomFusionRoomJoinMap(uint joinStart) - : base(joinStart, typeof(EssentialsHuddleSpaceRoomFusionRoomJoinMap)) - { - - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - public EssentialsHuddleSpaceRoomFusionRoomJoinMap(uint joinStart, Type type) : base(joinStart, type) - { - } - } -} \ No newline at end of file + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + public EssentialsHuddleSpaceRoomFusionRoomJoinMap(uint joinStart, Type type) : base(joinStart, type) + { + } +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Fusion/FusionCustomPropertiesBridge.cs b/src/PepperDash.Essentials.Core/Fusion/FusionCustomPropertiesBridge.cs index a0cd8e6e8..c7864f121 100644 --- a/src/PepperDash.Essentials.Core/Fusion/FusionCustomPropertiesBridge.cs +++ b/src/PepperDash.Essentials.Core/Fusion/FusionCustomPropertiesBridge.cs @@ -14,108 +14,107 @@ using PepperDash.Essentials.Core.Devices; using Serilog.Events; -namespace PepperDash.Essentials.Core.Fusion +namespace PepperDash.Essentials.Core.Fusion; + +/// +/// Handles mapping Fusion Custom Property values to system properties +/// +public class FusionCustomPropertiesBridge { + /// - /// Handles mapping Fusion Custom Property values to system properties + /// Evaluates the room info and custom properties from Fusion and updates the system properties aa needed /// - public class FusionCustomPropertiesBridge + /// + public void EvaluateRoomInfo(string roomKey, RoomInformation roomInfo) { - - /// - /// Evaluates the room info and custom properties from Fusion and updates the system properties aa needed - /// - /// - public void EvaluateRoomInfo(string roomKey, RoomInformation roomInfo) + try { - try + var reconfigurableDevices = DeviceManager.AllDevices.Where(d => d is ReconfigurableDevice); + + foreach (var device in reconfigurableDevices) { - var reconfigurableDevices = DeviceManager.AllDevices.Where(d => d is ReconfigurableDevice); + // Get the current device config so new values can be overwritten over existing + var deviceConfig = (device as ReconfigurableDevice).Config; - foreach (var device in reconfigurableDevices) + if (device is RoomOnToDefaultSourceWhenOccupied) { - // Get the current device config so new values can be overwritten over existing - var deviceConfig = (device as ReconfigurableDevice).Config; + Debug.LogMessage(LogEventLevel.Debug, "Mapping Room on via Occupancy values from Fusion"); - if (device is RoomOnToDefaultSourceWhenOccupied) - { - Debug.LogMessage(LogEventLevel.Debug, "Mapping Room on via Occupancy values from Fusion"); + var devProps = JsonConvert.DeserializeObject(deviceConfig.Properties.ToString()); - var devProps = JsonConvert.DeserializeObject(deviceConfig.Properties.ToString()); + var enableFeature = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupied")); + if (enableFeature != null) + devProps.EnableRoomOnWhenOccupied = bool.Parse(enableFeature.CustomFieldValue); - var enableFeature = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupied")); - if (enableFeature != null) - devProps.EnableRoomOnWhenOccupied = bool.Parse(enableFeature.CustomFieldValue); + var enableTime = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("RoomOnWhenOccupiedStartTime")); + if (enableTime != null) + devProps.OccupancyStartTime = enableTime.CustomFieldValue; - var enableTime = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("RoomOnWhenOccupiedStartTime")); - if (enableTime != null) - devProps.OccupancyStartTime = enableTime.CustomFieldValue; + var disableTime = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("RoomOnWhenOccupiedEndTime")); + if (disableTime != null) + devProps.OccupancyEndTime = disableTime.CustomFieldValue; - var disableTime = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("RoomOnWhenOccupiedEndTime")); - if (disableTime != null) - devProps.OccupancyEndTime = disableTime.CustomFieldValue; + var enableSunday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedSun")); + if (enableSunday != null) + devProps.EnableSunday = bool.Parse(enableSunday.CustomFieldValue); - var enableSunday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedSun")); - if (enableSunday != null) - devProps.EnableSunday = bool.Parse(enableSunday.CustomFieldValue); + var enableMonday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedMon")); + if (enableMonday != null) + devProps.EnableMonday = bool.Parse(enableMonday.CustomFieldValue); - var enableMonday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedMon")); - if (enableMonday != null) - devProps.EnableMonday = bool.Parse(enableMonday.CustomFieldValue); + var enableTuesday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedTue")); + if (enableTuesday != null) + devProps.EnableTuesday = bool.Parse(enableTuesday.CustomFieldValue); - var enableTuesday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedTue")); - if (enableTuesday != null) - devProps.EnableTuesday = bool.Parse(enableTuesday.CustomFieldValue); + var enableWednesday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedWed")); + if (enableWednesday != null) + devProps.EnableWednesday = bool.Parse(enableWednesday.CustomFieldValue); - var enableWednesday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedWed")); - if (enableWednesday != null) - devProps.EnableWednesday = bool.Parse(enableWednesday.CustomFieldValue); + var enableThursday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedThu")); + if (enableThursday != null) + devProps.EnableThursday = bool.Parse(enableThursday.CustomFieldValue); - var enableThursday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedThu")); - if (enableThursday != null) - devProps.EnableThursday = bool.Parse(enableThursday.CustomFieldValue); + var enableFriday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedFri")); + if (enableFriday != null) + devProps.EnableFriday = bool.Parse(enableFriday.CustomFieldValue); - var enableFriday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedFri")); - if (enableFriday != null) - devProps.EnableFriday = bool.Parse(enableFriday.CustomFieldValue); + var enableSaturday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedSat")); + if (enableSaturday != null) + devProps.EnableSaturday = bool.Parse(enableSaturday.CustomFieldValue); - var enableSaturday = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("EnRoomOnWhenOccupiedSat")); - if (enableSaturday != null) - devProps.EnableSaturday = bool.Parse(enableSaturday.CustomFieldValue); + deviceConfig.Properties = JToken.FromObject(devProps); + } + else if (device is IEssentialsRoom) + { + // Set the room name + if (!string.IsNullOrEmpty(roomInfo.Name)) + { + Debug.LogMessage(LogEventLevel.Debug, "Current Room Name: {0}. New Room Name: {1}", deviceConfig.Name, roomInfo.Name); + // Set the name in config + deviceConfig.Name = roomInfo.Name; - deviceConfig.Properties = JToken.FromObject(devProps); + Debug.LogMessage(LogEventLevel.Debug, "Room Name Successfully Changed."); } - else if (device is IEssentialsRoom) + + // Set the help message + var helpMessage = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("RoomHelpMessage")); + if (helpMessage != null) { - // Set the room name - if (!string.IsNullOrEmpty(roomInfo.Name)) - { - Debug.LogMessage(LogEventLevel.Debug, "Current Room Name: {0}. New Room Name: {1}", deviceConfig.Name, roomInfo.Name); - // Set the name in config - deviceConfig.Name = roomInfo.Name; - - Debug.LogMessage(LogEventLevel.Debug, "Room Name Successfully Changed."); - } - - // Set the help message - var helpMessage = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("RoomHelpMessage")); - if (helpMessage != null) - { - //Debug.LogMessage(LogEventLevel.Debug, "Current Help Message: {0}. New Help Message: {1}", deviceConfig.Properties["help"]["message"].Value(ToString()), helpMessage.CustomFieldValue); - deviceConfig.Properties["helpMessage"] = (string)helpMessage.CustomFieldValue; - } + //Debug.LogMessage(LogEventLevel.Debug, "Current Help Message: {0}. New Help Message: {1}", deviceConfig.Properties["help"]["message"].Value(ToString()), helpMessage.CustomFieldValue); + deviceConfig.Properties["helpMessage"] = (string)helpMessage.CustomFieldValue; } - - // Set the config on the device - (device as ReconfigurableDevice).SetConfig(deviceConfig); } - - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Debug, "FusionCustomPropetiesBridge: Error mapping properties: {0}", e); + // Set the config on the device + (device as ReconfigurableDevice).SetConfig(deviceConfig); } + + + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Debug, "FusionCustomPropetiesBridge: Error mapping properties: {0}", e); } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Fusion/FusionEventHandlers.cs b/src/PepperDash.Essentials.Core/Fusion/FusionEventHandlers.cs index 26647a961..dc0c38226 100644 --- a/src/PepperDash.Essentials.Core/Fusion/FusionEventHandlers.cs +++ b/src/PepperDash.Essentials.Core/Fusion/FusionEventHandlers.cs @@ -4,15 +4,14 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core.Fusion +namespace PepperDash.Essentials.Core.Fusion; + +public class ScheduleChangeEventArgs : EventArgs { - public class ScheduleChangeEventArgs : EventArgs - { - public RoomSchedule Schedule { get; set; } - } + public RoomSchedule Schedule { get; set; } +} - public class MeetingChangeEventArgs : EventArgs - { - public Event Meeting { get; set; } - } +public class MeetingChangeEventArgs : EventArgs +{ + public Event Meeting { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Fusion/FusionProcessorQueries.cs b/src/PepperDash.Essentials.Core/Fusion/FusionProcessorQueries.cs index cdf1dfa8f..ea44f98a2 100644 --- a/src/PepperDash.Essentials.Core/Fusion/FusionProcessorQueries.cs +++ b/src/PepperDash.Essentials.Core/Fusion/FusionProcessorQueries.cs @@ -6,58 +6,57 @@ using PepperDash.Core; using Serilog.Events; -namespace PepperDash.Essentials.Core.Fusion +namespace PepperDash.Essentials.Core.Fusion; + +/// +/// When created, runs progcomments on every slot and stores the program names in a list +/// +public class ProcessorProgReg { - /// - /// When created, runs progcomments on every slot and stores the program names in a list - /// - public class ProcessorProgReg - { - //public static Dictionary Programs { get; private set; } + //public static Dictionary Programs { get; private set; } - public static Dictionary GetProcessorProgReg() + public static Dictionary GetProcessorProgReg() + { + var programs = new Dictionary(); + for (int i = 1; i <= Global.ControlSystem.NumProgramsSupported; i++) { - var programs = new Dictionary(); - for (int i = 1; i <= Global.ControlSystem.NumProgramsSupported; i++) + string response = null; + var success = CrestronConsole.SendControlSystemCommand("progcomments:" + i, ref response); + var item = new ProcessorProgramItem(); + if (!success) + item.Name = "Error: PROGCOMMENTS failed"; + else { - string response = null; - var success = CrestronConsole.SendControlSystemCommand("progcomments:" + i, ref response); - var item = new ProcessorProgramItem(); - if (!success) - item.Name = "Error: PROGCOMMENTS failed"; + if (response.ToLower().Contains("bad or incomplete")) + item.Name = ""; else { - if (response.ToLower().Contains("bad or incomplete")) - item.Name = ""; - else + var startPos = response.IndexOf("Program File"); + var colonPos = response.IndexOf(":", startPos) + 1; + var endPos = response.IndexOf(CrestronEnvironment.NewLine, colonPos); + item.Name = response.Substring(colonPos, endPos - colonPos).Trim(); + item.Exists = true; + if (item.Name.Contains(".dll")) { - var startPos = response.IndexOf("Program File"); - var colonPos = response.IndexOf(":", startPos) + 1; - var endPos = response.IndexOf(CrestronEnvironment.NewLine, colonPos); - item.Name = response.Substring(colonPos, endPos - colonPos).Trim(); - item.Exists = true; - if (item.Name.Contains(".dll")) - { - startPos = response.IndexOf("Compiler Revision"); - colonPos = response.IndexOf(":", startPos) + 1; - endPos = response.IndexOf(CrestronEnvironment.NewLine, colonPos); - item.Name = item.Name + "_v" + response.Substring(colonPos, endPos - colonPos).Trim(); - } + startPos = response.IndexOf("Compiler Revision"); + colonPos = response.IndexOf(":", startPos) + 1; + endPos = response.IndexOf(CrestronEnvironment.NewLine, colonPos); + item.Name = item.Name + "_v" + response.Substring(colonPos, endPos - colonPos).Trim(); } } - programs[i] = item; - Debug.LogMessage(LogEventLevel.Debug, "Program {0}: {1}", i, item.Name); } - return programs; + programs[i] = item; + Debug.LogMessage(LogEventLevel.Debug, "Program {0}: {1}", i, item.Name); } + return programs; } +} - /// - /// Used in ProcessorProgReg - /// - public class ProcessorProgramItem - { - public bool Exists { get; set; } - public string Name { get; set; } - } +/// +/// Used in ProcessorProgReg +/// +public class ProcessorProgramItem +{ + public bool Exists { get; set; } + public string Name { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Fusion/FusionRviDataClasses.cs b/src/PepperDash.Essentials.Core/Fusion/FusionRviDataClasses.cs index 1ac5dbde8..ba53564a9 100644 --- a/src/PepperDash.Essentials.Core/Fusion/FusionRviDataClasses.cs +++ b/src/PepperDash.Essentials.Core/Fusion/FusionRviDataClasses.cs @@ -8,493 +8,492 @@ using PepperDash.Core; using Serilog.Events; -namespace PepperDash.Essentials.Core.Fusion +namespace PepperDash.Essentials.Core.Fusion; + +// Helper Classes for GUIDs + +/// +/// Stores GUIDs to be written to a file in NVRAM +/// +public class FusionRoomGuids { - // Helper Classes for GUIDs + public string RoomName { get; set; } + public uint IpId { get; set; } + public string RoomGuid { get; set; } + public FusionOccupancySensorAsset OccupancyAsset { get; set; } + public Dictionary StaticAssets { get; set; } - /// - /// Stores GUIDs to be written to a file in NVRAM - /// - public class FusionRoomGuids + public FusionRoomGuids() { - public string RoomName { get; set; } - public uint IpId { get; set; } - public string RoomGuid { get; set; } - public FusionOccupancySensorAsset OccupancyAsset { get; set; } - public Dictionary StaticAssets { get; set; } + StaticAssets = new Dictionary(); + OccupancyAsset = new FusionOccupancySensorAsset(); + } - public FusionRoomGuids() - { - StaticAssets = new Dictionary(); - OccupancyAsset = new FusionOccupancySensorAsset(); - } + public FusionRoomGuids(string roomName, uint ipId, string roomGuid, Dictionary staticAssets) + { + RoomName = roomName; + IpId = ipId; + RoomGuid = roomGuid; - public FusionRoomGuids(string roomName, uint ipId, string roomGuid, Dictionary staticAssets) - { - RoomName = roomName; - IpId = ipId; - RoomGuid = roomGuid; + StaticAssets = staticAssets; + OccupancyAsset = new FusionOccupancySensorAsset(); + } - StaticAssets = staticAssets; - OccupancyAsset = new FusionOccupancySensorAsset(); - } + public FusionRoomGuids(string roomName, uint ipId, string roomGuid, Dictionary staticAssets, FusionOccupancySensorAsset occAsset) + { + RoomName = roomName; + IpId = ipId; + RoomGuid = roomGuid; - public FusionRoomGuids(string roomName, uint ipId, string roomGuid, Dictionary staticAssets, FusionOccupancySensorAsset occAsset) - { - RoomName = roomName; - IpId = ipId; - RoomGuid = roomGuid; + StaticAssets = staticAssets; + OccupancyAsset = occAsset; + } - StaticAssets = staticAssets; - OccupancyAsset = occAsset; - } + /// + /// Generates a new room GUID prefixed by the program slot number and NIC MAC address + /// + /// + /// + public string GenerateNewRoomGuid(uint progSlot, string mac) + { + Guid roomGuid = Guid.NewGuid(); - /// - /// Generates a new room GUID prefixed by the program slot number and NIC MAC address - /// - /// - /// - public string GenerateNewRoomGuid(uint progSlot, string mac) - { - Guid roomGuid = Guid.NewGuid(); + return string.Format("{0}-{1}-{2}", progSlot, mac, roomGuid.ToString()); + } - return string.Format("{0}-{1}-{2}", progSlot, mac, roomGuid.ToString()); - } + /// + /// Adds an asset to the StaticAssets collection and returns the new asset + /// + /// + /// + /// + /// + /// + /// + public FusionAsset AddStaticAsset(FusionRoom room, int uid, string assetName, string type, string instanceId) + { + var slotNum = GetNextAvailableAssetNumber(room); - /// - /// Adds an asset to the StaticAssets collection and returns the new asset - /// - /// - /// - /// - /// - /// - /// - public FusionAsset AddStaticAsset(FusionRoom room, int uid, string assetName, string type, string instanceId) - { - var slotNum = GetNextAvailableAssetNumber(room); + Debug.LogMessage(LogEventLevel.Verbose, "Adding Fusion Asset: {0} of Type: {1} at Slot Number: {2} with GUID: {3}", assetName, type, slotNum, instanceId); - Debug.LogMessage(LogEventLevel.Verbose, "Adding Fusion Asset: {0} of Type: {1} at Slot Number: {2} with GUID: {3}", assetName, type, slotNum, instanceId); + var tempAsset = new FusionAsset(slotNum, assetName, type, instanceId); - var tempAsset = new FusionAsset(slotNum, assetName, type, instanceId); + StaticAssets.Add(uid, tempAsset); - StaticAssets.Add(uid, tempAsset); + return tempAsset; + } + + /// + /// Returns the next available slot number in the Fusion UserConfigurableAssetDetails collection + /// + /// + /// + public static uint GetNextAvailableAssetNumber(FusionRoom room) + { + uint slotNum = 0; - return tempAsset; + foreach (var item in room.UserConfigurableAssetDetails) + { + if(item.Number > slotNum) + slotNum = item.Number; } - /// - /// Returns the next available slot number in the Fusion UserConfigurableAssetDetails collection - /// - /// - /// - public static uint GetNextAvailableAssetNumber(FusionRoom room) + if (slotNum < 5) { - uint slotNum = 0; + slotNum = 5; + } + else + slotNum = slotNum + 1; - foreach (var item in room.UserConfigurableAssetDetails) - { - if(item.Number > slotNum) - slotNum = item.Number; - } + Debug.LogMessage(LogEventLevel.Verbose, "#Next available fusion asset number is: {0}", slotNum); - if (slotNum < 5) - { - slotNum = 5; - } - else - slotNum = slotNum + 1; + return slotNum; + } - Debug.LogMessage(LogEventLevel.Verbose, "#Next available fusion asset number is: {0}", slotNum); +} - return slotNum; - } +public class FusionOccupancySensorAsset +{ + // SlotNumber fixed at 4 + + public uint SlotNumber { get { return 4; } } + public string Name { get { return "Occupancy Sensor"; } } + public eAssetType Type { get; set; } + public string InstanceId { get; set; } + public FusionOccupancySensorAsset() + { } - public class FusionOccupancySensorAsset + public FusionOccupancySensorAsset(eAssetType type) { - // SlotNumber fixed at 4 + Type = type; - public uint SlotNumber { get { return 4; } } - public string Name { get { return "Occupancy Sensor"; } } - public eAssetType Type { get; set; } - public string InstanceId { get; set; } + InstanceId = Guid.NewGuid().ToString(); + } +} - public FusionOccupancySensorAsset() - { - } +public class FusionAsset +{ + public uint SlotNumber { get; set; } + public string Name { get; set; } + public string Type { get; set; } + public string InstanceId { get;set; } - public FusionOccupancySensorAsset(eAssetType type) - { - Type = type; + public FusionAsset() + { - InstanceId = Guid.NewGuid().ToString(); - } } - public class FusionAsset + public FusionAsset(uint slotNum, string assetName, string type, string instanceId) { - public uint SlotNumber { get; set; } - public string Name { get; set; } - public string Type { get; set; } - public string InstanceId { get;set; } - - public FusionAsset() - { - - } - - public FusionAsset(uint slotNum, string assetName, string type, string instanceId) + SlotNumber = slotNum; + Name = assetName; + Type = type; + if (string.IsNullOrEmpty(instanceId)) { - SlotNumber = slotNum; - Name = assetName; - Type = type; - if (string.IsNullOrEmpty(instanceId)) - { - InstanceId = Guid.NewGuid().ToString(); - } - else - { - InstanceId = instanceId; - } + InstanceId = Guid.NewGuid().ToString(); } - } - - //*************************************************************************************************** - - public class RoomSchedule - { - public List Meetings { get; set; } - - public RoomSchedule() + else { - Meetings = new List(); + InstanceId = instanceId; } } +} - //**************************************************************************************************** - // Helper Classes for XML API +//*************************************************************************************************** - /// - /// Data needed to request the local time from the Fusion server - /// - public class LocalTimeRequest - { - public string RequestID { get; set; } - } +public class RoomSchedule +{ + public List Meetings { get; set; } - /// - /// All the data needed for a full schedule request in a room - /// - /// //[XmlRoot(ElementName = "RequestSchedule")] - public class RequestSchedule + public RoomSchedule() { - //[XmlElement(ElementName = "RequestID")] - public string RequestID { get; set; } - //[XmlElement(ElementName = "RoomID")] - public string RoomID { get; set; } - //[XmlElement(ElementName = "Start")] - public DateTime Start { get; set; } - //[XmlElement(ElementName = "HourSpan")] - public double HourSpan { get; set; } - - public RequestSchedule(string requestID, string roomID) - { - RequestID = requestID; - RoomID = roomID; - Start = DateTime.Now; - HourSpan = 24; - } + Meetings = new List(); } +} +//**************************************************************************************************** +// Helper Classes for XML API - //[XmlRoot(ElementName = "RequestAction")] - public class RequestAction +/// +/// Data needed to request the local time from the Fusion server +/// +public class LocalTimeRequest +{ + public string RequestID { get; set; } +} + +/// +/// All the data needed for a full schedule request in a room +/// +/// //[XmlRoot(ElementName = "RequestSchedule")] +public class RequestSchedule +{ + //[XmlElement(ElementName = "RequestID")] + public string RequestID { get; set; } + //[XmlElement(ElementName = "RoomID")] + public string RoomID { get; set; } + //[XmlElement(ElementName = "Start")] + public DateTime Start { get; set; } + //[XmlElement(ElementName = "HourSpan")] + public double HourSpan { get; set; } + + public RequestSchedule(string requestID, string roomID) { - //[XmlElement(ElementName = "RequestID")] - public string RequestID { get; set; } - //[XmlElement(ElementName = "RoomID")] - public string RoomID { get; set; } - //[XmlElement(ElementName = "ActionID")] - public string ActionID { get; set; } - //[XmlElement(ElementName = "Parameters")] - public List Parameters { get; set; } - - public RequestAction(string roomID, string actionID, List parameters) - { - RoomID = roomID; - ActionID = actionID; - Parameters = parameters; - } + RequestID = requestID; + RoomID = roomID; + Start = DateTime.Now; + HourSpan = 24; } +} + - //[XmlRoot(ElementName = "ActionResponse")] - public class ActionResponse +//[XmlRoot(ElementName = "RequestAction")] +public class RequestAction +{ + //[XmlElement(ElementName = "RequestID")] + public string RequestID { get; set; } + //[XmlElement(ElementName = "RoomID")] + public string RoomID { get; set; } + //[XmlElement(ElementName = "ActionID")] + public string ActionID { get; set; } + //[XmlElement(ElementName = "Parameters")] + public List Parameters { get; set; } + + public RequestAction(string roomID, string actionID, List parameters) { - //[XmlElement(ElementName = "RequestID")] - public string RequestID { get; set; } - //[XmlElement(ElementName = "ActionID")] - public string ActionID { get; set; } - //[XmlElement(ElementName = "Parameters")] - public List Parameters { get; set; } + RoomID = roomID; + ActionID = actionID; + Parameters = parameters; } +} - //[XmlRoot(ElementName = "Parameter")] - public class Parameter +//[XmlRoot(ElementName = "ActionResponse")] +public class ActionResponse +{ + //[XmlElement(ElementName = "RequestID")] + public string RequestID { get; set; } + //[XmlElement(ElementName = "ActionID")] + public string ActionID { get; set; } + //[XmlElement(ElementName = "Parameters")] + public List Parameters { get; set; } +} + +//[XmlRoot(ElementName = "Parameter")] +public class Parameter +{ + //[XmlAttribute(AttributeName = "ID")] + public string ID { get; set; } + //[XmlAttribute(AttributeName = "Value")] + public string Value { get; set; } +} + +////[XmlRoot(ElementName = "Parameters")] +//public class Parameters +//{ +// //[XmlElement(ElementName = "Parameter")] +// public List Parameter { get; set; } +//} + +/// +/// Data structure for a ScheduleResponse from Fusion +/// +/// //[XmlRoot(ElementName = "ScheduleResponse")] +public class ScheduleResponse +{ + //[XmlElement(ElementName = "RequestID")] + public string RequestID { get; set; } + //[XmlElement(ElementName = "RoomID")] + public string RoomID { get; set; } + //[XmlElement(ElementName = "RoomName")] + public string RoomName { get; set; } + //[XmlElement("Event")] + public List Events { get; set; } + + public ScheduleResponse() { - //[XmlAttribute(AttributeName = "ID")] - public string ID { get; set; } - //[XmlAttribute(AttributeName = "Value")] - public string Value { get; set; } + Events = new List(); } +} - ////[XmlRoot(ElementName = "Parameters")] - //public class Parameters - //{ - // //[XmlElement(ElementName = "Parameter")] - // public List Parameter { get; set; } - //} +//[XmlRoot(ElementName = "Event")] +public class Event +{ + //[XmlElement(ElementName = "MeetingID")] + public string MeetingID { get; set; } + //[XmlElement(ElementName = "RVMeetingID")] + public string RVMeetingID { get; set; } + //[XmlElement(ElementName = "Recurring")] + public string Recurring { get; set; } + //[XmlElement(ElementName = "InstanceID")] + public string InstanceID { get; set; } + //[XmlElement(ElementName = "dtStart")] + public DateTime dtStart { get; set; } + //[XmlElement(ElementName = "dtEnd")] + public DateTime dtEnd { get; set; } + //[XmlElement(ElementName = "Organizer")] + public string Organizer { get; set; } + //[XmlElement(ElementName = "Attendees")] + public Attendees Attendees { get; set; } + //[XmlElement(ElementName = "Resources")] + public Resources Resources { get; set; } + //[XmlElement(ElementName = "IsEvent")] + public string IsEvent { get; set; } + //[XmlElement(ElementName = "IsRoomViewMeeting")] + public string IsRoomViewMeeting { get; set; } + //[XmlElement(ElementName = "IsPrivate")] + public string IsPrivate { get; set; } + //[XmlElement(ElementName = "IsExchangePrivate")] + public string IsExchangePrivate { get; set; } + //[XmlElement(ElementName = "MeetingTypes")] + public MeetingTypes MeetingTypes { get; set; } + //[XmlElement(ElementName = "ParticipantCode")] + public string ParticipantCode { get; set; } + //[XmlElement(ElementName = "PhoneNo")] + public string PhoneNo { get; set; } + //[XmlElement(ElementName = "WelcomeMsg")] + public string WelcomeMsg { get; set; } + //[XmlElement(ElementName = "Subject")] + public string Subject { get; set; } + //[XmlElement(ElementName = "LiveMeeting")] + public LiveMeeting LiveMeeting { get; set; } + //[XmlElement(ElementName = "ShareDocPath")] + public string ShareDocPath { get; set; } + //[XmlElement(ElementName = "HaveAttendees")] + public string HaveAttendees { get; set; } + //[XmlElement(ElementName = "HaveResources")] + public string HaveResources { get; set; } /// - /// Data structure for a ScheduleResponse from Fusion + /// Gets the duration of the meeting /// - /// //[XmlRoot(ElementName = "ScheduleResponse")] - public class ScheduleResponse + public string DurationInMinutes { - //[XmlElement(ElementName = "RequestID")] - public string RequestID { get; set; } - //[XmlElement(ElementName = "RoomID")] - public string RoomID { get; set; } - //[XmlElement(ElementName = "RoomName")] - public string RoomName { get; set; } - //[XmlElement("Event")] - public List Events { get; set; } - - public ScheduleResponse() + get { - Events = new List(); + string duration; + + var timeSpan = dtEnd.Subtract(dtStart); + int hours = timeSpan.Hours; + double minutes = timeSpan.Minutes; + double roundedMinutes = Math.Round(minutes); + if (hours > 0) + { + duration = string.Format("{0} hours {1} minutes", hours, roundedMinutes); + } + else + { + duration = string.Format("{0} minutes", roundedMinutes); + } + + return duration; } } - //[XmlRoot(ElementName = "Event")] - public class Event + /// + /// Gets the remaining time in the meeting. Returns null if the meeting is not currently in progress. + /// + public string RemainingTime { - //[XmlElement(ElementName = "MeetingID")] - public string MeetingID { get; set; } - //[XmlElement(ElementName = "RVMeetingID")] - public string RVMeetingID { get; set; } - //[XmlElement(ElementName = "Recurring")] - public string Recurring { get; set; } - //[XmlElement(ElementName = "InstanceID")] - public string InstanceID { get; set; } - //[XmlElement(ElementName = "dtStart")] - public DateTime dtStart { get; set; } - //[XmlElement(ElementName = "dtEnd")] - public DateTime dtEnd { get; set; } - //[XmlElement(ElementName = "Organizer")] - public string Organizer { get; set; } - //[XmlElement(ElementName = "Attendees")] - public Attendees Attendees { get; set; } - //[XmlElement(ElementName = "Resources")] - public Resources Resources { get; set; } - //[XmlElement(ElementName = "IsEvent")] - public string IsEvent { get; set; } - //[XmlElement(ElementName = "IsRoomViewMeeting")] - public string IsRoomViewMeeting { get; set; } - //[XmlElement(ElementName = "IsPrivate")] - public string IsPrivate { get; set; } - //[XmlElement(ElementName = "IsExchangePrivate")] - public string IsExchangePrivate { get; set; } - //[XmlElement(ElementName = "MeetingTypes")] - public MeetingTypes MeetingTypes { get; set; } - //[XmlElement(ElementName = "ParticipantCode")] - public string ParticipantCode { get; set; } - //[XmlElement(ElementName = "PhoneNo")] - public string PhoneNo { get; set; } - //[XmlElement(ElementName = "WelcomeMsg")] - public string WelcomeMsg { get; set; } - //[XmlElement(ElementName = "Subject")] - public string Subject { get; set; } - //[XmlElement(ElementName = "LiveMeeting")] - public LiveMeeting LiveMeeting { get; set; } - //[XmlElement(ElementName = "ShareDocPath")] - public string ShareDocPath { get; set; } - //[XmlElement(ElementName = "HaveAttendees")] - public string HaveAttendees { get; set; } - //[XmlElement(ElementName = "HaveResources")] - public string HaveResources { get; set; } - - /// - /// Gets the duration of the meeting - /// - public string DurationInMinutes + get { - get - { - string duration; + var now = DateTime.Now; - var timeSpan = dtEnd.Subtract(dtStart); + string remainingTime; + + if (GetInProgress()) + { + var timeSpan = dtEnd.Subtract(now); int hours = timeSpan.Hours; double minutes = timeSpan.Minutes; double roundedMinutes = Math.Round(minutes); if (hours > 0) { - duration = string.Format("{0} hours {1} minutes", hours, roundedMinutes); + remainingTime = string.Format("{0} hours {1} minutes", hours, roundedMinutes); } else { - duration = string.Format("{0} minutes", roundedMinutes); + remainingTime = string.Format("{0} minutes", roundedMinutes); } - return duration; - } - } - - /// - /// Gets the remaining time in the meeting. Returns null if the meeting is not currently in progress. - /// - public string RemainingTime - { - get - { - var now = DateTime.Now; - - string remainingTime; - - if (GetInProgress()) - { - var timeSpan = dtEnd.Subtract(now); - int hours = timeSpan.Hours; - double minutes = timeSpan.Minutes; - double roundedMinutes = Math.Round(minutes); - if (hours > 0) - { - remainingTime = string.Format("{0} hours {1} minutes", hours, roundedMinutes); - } - else - { - remainingTime = string.Format("{0} minutes", roundedMinutes); - } - - return remainingTime; - } - else - return null; - } - - } - - /// - /// Indicates that the meeting is in progress - /// - public bool isInProgress - { - get - { - return GetInProgress(); - } - } - - /// - /// Determines if the meeting is in progress - /// - /// Returns true if in progress - bool GetInProgress() - { - var now = DateTime.Now; - - if (now > dtStart && now < dtEnd) - { - return true; + return remainingTime; } else - return false; + return null; } - } - //[XmlRoot(ElementName = "Resources")] - public class Resources - { - //[XmlElement(ElementName = "Rooms")] - public Rooms Rooms { get; set; } } - //[XmlRoot(ElementName = "Rooms")] - public class Rooms + /// + /// Indicates that the meeting is in progress + /// + public bool isInProgress { - //[XmlElement(ElementName = "Room")] - public List Room { get; set; } + get + { + return GetInProgress(); + } } - //[XmlRoot(ElementName = "Room")] - public class Room + /// + /// Determines if the meeting is in progress + /// + /// Returns true if in progress + bool GetInProgress() { - //[XmlElement(ElementName = "Name")] - public string Name { get; set; } - //[XmlElement(ElementName = "ID")] - public string ID { get; set; } - //[XmlElement(ElementName = "MPType")] - public string MPType { get; set; } - } + var now = DateTime.Now; - //[XmlRoot(ElementName = "Attendees")] - public class Attendees - { - //[XmlElement(ElementName = "Required")] - public Required Required { get; set; } - //[XmlElement(ElementName = "Optional")] - public Optional Optional { get; set; } + if (now > dtStart && now < dtEnd) + { + return true; + } + else + return false; } +} - //[XmlRoot(ElementName = "Required")] - public class Required - { - //[XmlElement(ElementName = "Attendee")] - public List Attendee { get; set; } - } +//[XmlRoot(ElementName = "Resources")] +public class Resources +{ + //[XmlElement(ElementName = "Rooms")] + public Rooms Rooms { get; set; } +} - //[XmlRoot(ElementName = "Optional")] - public class Optional - { - //[XmlElement(ElementName = "Attendee")] - public List Attendee { get; set; } - } +//[XmlRoot(ElementName = "Rooms")] +public class Rooms +{ + //[XmlElement(ElementName = "Room")] + public List Room { get; set; } +} - //[XmlRoot(ElementName = "MeetingType")] - public class MeetingType - { - //[XmlAttribute(AttributeName = "ID")] - public string ID { get; set; } - //[XmlAttribute(AttributeName = "Value")] - public string Value { get; set; } - } +//[XmlRoot(ElementName = "Room")] +public class Room +{ + //[XmlElement(ElementName = "Name")] + public string Name { get; set; } + //[XmlElement(ElementName = "ID")] + public string ID { get; set; } + //[XmlElement(ElementName = "MPType")] + public string MPType { get; set; } +} + +//[XmlRoot(ElementName = "Attendees")] +public class Attendees +{ + //[XmlElement(ElementName = "Required")] + public Required Required { get; set; } + //[XmlElement(ElementName = "Optional")] + public Optional Optional { get; set; } +} + +//[XmlRoot(ElementName = "Required")] +public class Required +{ + //[XmlElement(ElementName = "Attendee")] + public List Attendee { get; set; } +} - //[XmlRoot(ElementName = "MeetingTypes")] - public class MeetingTypes - { - //[XmlElement(ElementName = "MeetingType")] - public List MeetingType { get; set; } - } +//[XmlRoot(ElementName = "Optional")] +public class Optional +{ + //[XmlElement(ElementName = "Attendee")] + public List Attendee { get; set; } +} - //[XmlRoot(ElementName = "LiveMeeting")] - public class LiveMeeting - { - //[XmlElement(ElementName = "URL")] - public string URL { get; set; } - //[XmlElement(ElementName = "ID")] - public string ID { get; set; } - //[XmlElement(ElementName = "Key")] - public string Key { get; set; } - //[XmlElement(ElementName = "Subject")] - public string Subject { get; set; } - } +//[XmlRoot(ElementName = "MeetingType")] +public class MeetingType +{ + //[XmlAttribute(AttributeName = "ID")] + public string ID { get; set; } + //[XmlAttribute(AttributeName = "Value")] + public string Value { get; set; } +} + +//[XmlRoot(ElementName = "MeetingTypes")] +public class MeetingTypes +{ + //[XmlElement(ElementName = "MeetingType")] + public List MeetingType { get; set; } +} - //[XmlRoot(ElementName = "LiveMeetingURL")] - public class LiveMeetingURL - { - //[XmlElement(ElementName = "LiveMeeting")] - public LiveMeeting LiveMeeting { get; set; } - } +//[XmlRoot(ElementName = "LiveMeeting")] +public class LiveMeeting +{ + //[XmlElement(ElementName = "URL")] + public string URL { get; set; } + //[XmlElement(ElementName = "ID")] + public string ID { get; set; } + //[XmlElement(ElementName = "Key")] + public string Key { get; set; } + //[XmlElement(ElementName = "Subject")] + public string Subject { get; set; } +} + +//[XmlRoot(ElementName = "LiveMeetingURL")] +public class LiveMeetingURL +{ + //[XmlElement(ElementName = "LiveMeeting")] + public LiveMeeting LiveMeeting { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Global/EthernetAdapterInfo.cs b/src/PepperDash.Essentials.Core/Global/EthernetAdapterInfo.cs index c21df0989..ec33512c9 100644 --- a/src/PepperDash.Essentials.Core/Global/EthernetAdapterInfo.cs +++ b/src/PepperDash.Essentials.Core/Global/EthernetAdapterInfo.cs @@ -4,20 +4,19 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public class EthernetAdapterInfo { - public class EthernetAdapterInfo - { - public EthernetAdapterType Type { get; set; } - public bool DhcpIsOn { get; set; } - public string Hostname { get; set; } - public string MacAddress { get; set; } - public string IpAddress { get; set; } - public string Subnet { get; set; } - public string Gateway { get; set; } - public string Dns1 { get; set; } - public string Dns2 { get; set; } - public string Dns3 { get; set; } - public string Domain { get; set; } - } + public EthernetAdapterType Type { get; set; } + public bool DhcpIsOn { get; set; } + public string Hostname { get; set; } + public string MacAddress { get; set; } + public string IpAddress { get; set; } + public string Subnet { get; set; } + public string Gateway { get; set; } + public string Dns1 { get; set; } + public string Dns2 { get; set; } + public string Dns3 { get; set; } + public string Domain { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Global/Global.cs b/src/PepperDash.Essentials.Core/Global/Global.cs index 9e4b64621..5bde3e060 100644 --- a/src/PepperDash.Essentials.Core/Global/Global.cs +++ b/src/PepperDash.Essentials.Core/Global/Global.cs @@ -1,6 +1,4 @@ - - -using System; +using System; using System.Linq; using System.Text.RegularExpressions; using System.Globalization; @@ -20,169 +18,170 @@ using Serilog.Events; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public static class Global { public static CrestronControlSystem ControlSystem { get; set; } - public static eDevicePlatform Platform { get { return CrestronEnvironment.DevicePlatform; } } + public static eDevicePlatform Platform { get { return CrestronEnvironment.DevicePlatform; } } - public static Dictionary EthernetAdapterInfoCollection { get; private set; } + public static Dictionary EthernetAdapterInfoCollection { get; private set; } public static LicenseManager LicenseManager { get; set; } - public static eCrestronSeries ProcessorSeries { get { return CrestronEnvironment.ProgramCompatibility; } } + public static eCrestronSeries ProcessorSeries { get { return CrestronEnvironment.ProgramCompatibility; } } - // TODO: consider making this configurable later - public static IFormatProvider Culture = CultureInfo.CreateSpecificCulture("en-US"); + // TODO: consider making this configurable later + public static IFormatProvider Culture = CultureInfo.InvariantCulture; - /// - /// True when the processor type is a DMPS variant - /// - public static bool ControlSystemIsDmpsType + + /// + /// True when the processor type is a DMPS variant + /// + public static bool ControlSystemIsDmpsType + { + get { - get + if(ControlSystem.SystemControl != null) { - if(ControlSystem.SystemControl != null) + if(ControlSystem.SystemControl.SystemControlType > 0) { - if(ControlSystem.SystemControl.SystemControlType > 0) - { - return true; - } - } - return false; + return true; + } } + return false; } - - /// - /// True when the processor type is a DMPS 4K variant - /// - public static bool ControlSystemIsDmps4kType + } + + /// + /// True when the processor type is a DMPS 4K variant + /// + public static bool ControlSystemIsDmps4kType + { + get { - get + if(ControlSystem.SystemControl != null) { - if(ControlSystem.SystemControl != null) + if(ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K150CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K200CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K250CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K300CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K350CSystemControl) { - if(ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K150CSystemControl || - ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K200CSystemControl || - ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K250CSystemControl || - ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K300CSystemControl || - ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K350CSystemControl) - { - return true; - } - } - return false; + return true; + } } + return false; } - - /// - /// True when the processor type is a DMPS 4K 200/300/250/350 variant - /// - public static bool ControlSystemIsDmps4k3xxType + } + + /// + /// True when the processor type is a DMPS 4K 200/300/250/350 variant + /// + public static bool ControlSystemIsDmps4k3xxType + { + get { - get + if(ControlSystem.SystemControl != null) { - if(ControlSystem.SystemControl != null) + if(ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K200CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K250CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K300CSystemControl || + ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K350CSystemControl) { - if(ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K200CSystemControl || - ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K250CSystemControl || - ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K300CSystemControl || - ControlSystem.SystemControl.SystemControlType == eSystemControlType.Dmps34K350CSystemControl) - { - return true; - } - } - return false; + return true; + } } + return false; } - - /// - /// The file path prefix to the folder containing configuration files - /// - public static string FilePathPrefix { get; private set; } - - /// - /// The file path prefix to the applciation directory - /// - public static string ApplicationDirectoryPathPrefix + } + + /// + /// The file path prefix to the folder containing configuration files + /// + public static string FilePathPrefix { get; private set; } + + /// + /// The file path prefix to the applciation directory + /// + public static string ApplicationDirectoryPathPrefix + { + get { - get - { - return Crestron.SimplSharp.CrestronIO.Directory.GetApplicationDirectory(); - } + return Crestron.SimplSharp.CrestronIO.Directory.GetApplicationDirectory(); } - - /// - /// Returns the directory separator character based on the running OS - /// - public static char DirectorySeparator + } + + /// + /// Returns the directory separator character based on the running OS + /// + public static char DirectorySeparator + { + get { - get - { - return System.IO.Path.DirectorySeparatorChar; - } + return System.IO.Path.DirectorySeparatorChar; } - - /// - /// Wildcarded config file name for global reference - /// - public const string ConfigFileName = "*configurationFile*.json"; - - /// - /// Sets the file path prefix - /// - /// - public static void SetFilePathPrefix(string prefix) + } + + /// + /// Wildcarded config file name for global reference + /// + public const string ConfigFileName = "*configurationFile*.json"; + + /// + /// Sets the file path prefix + /// + /// + public static void SetFilePathPrefix(string prefix) + { + FilePathPrefix = prefix; + Debug.LogMessage(LogEventLevel.Information, "File Path Prefix set to '{0}'", FilePathPrefix); + } + + static string _AssemblyVersion; + + /// + /// Gets the Assembly Version of Essentials + /// + /// The Assembly Version at Runtime + public static string AssemblyVersion + { + get { - FilePathPrefix = prefix; - Debug.LogMessage(LogEventLevel.Information, "File Path Prefix set to '{0}'", FilePathPrefix); + return _AssemblyVersion; } - - static string _AssemblyVersion; - - /// - /// Gets the Assembly Version of Essentials - /// - /// The Assembly Version at Runtime - public static string AssemblyVersion + private set { - get - { - return _AssemblyVersion; - } - private set - { - _AssemblyVersion = value; - } + _AssemblyVersion = value; } + } - /// - /// Sets the Assembly version to the version of the Essentials Library - /// - /// - public static void SetAssemblyVersion(string assemblyVersion) - { - AssemblyVersion = assemblyVersion; - } + /// + /// Sets the Assembly version to the version of the Essentials Library + /// + /// + public static void SetAssemblyVersion(string assemblyVersion) + { + AssemblyVersion = assemblyVersion; + } public static bool IsRunningDevelopmentVersion(List developmentVersions, string minimumVersion) { if (Regex.Match(AssemblyVersion, @"^(\d*).(\d*).(\d*).*").Groups[1].Value == "0") { - Debug.LogMessage(LogEventLevel.Verbose, "Running Local Build. Bypassing Dependency Check."); - return true; + Debug.LogMessage(LogEventLevel.Verbose, "Running Local Build. Bypassing Dependency Check."); + return true; } if (developmentVersions == null) { Debug.LogMessage(LogEventLevel.Information, - "Development Plugin does not specify a list of versions. Loading plugin may not work as expected. Checking Minumum version"); - return IsRunningMinimumVersionOrHigher(minimumVersion); + "Development Plugin does not specify a list of versions. Loading plugin may not work as expected. Checking Minumum version"); + return IsRunningMinimumVersionOrHigher(minimumVersion); } - Debug.LogMessage(LogEventLevel.Verbose, "Comparing running version '{0}' to minimum versions '{1}'", AssemblyVersion, developmentVersions); + Debug.LogMessage(LogEventLevel.Verbose, "Comparing running version '{0}' to minimum versions '{1}'", AssemblyVersion, developmentVersions); var versionMatch = developmentVersions.FirstOrDefault(x => x == AssemblyVersion); @@ -192,83 +191,83 @@ public static bool IsRunningDevelopmentVersion(List developmentVersions, return false; } - Debug.LogMessage(LogEventLevel.Verbose, "Essentials Build {0} matches list of development builds", AssemblyVersion); + Debug.LogMessage(LogEventLevel.Verbose, "Essentials Build {0} matches list of development builds", AssemblyVersion); return IsRunningMinimumVersionOrHigher(minimumVersion); } - /// - /// Checks to see if the running version meets or exceed the minimum specified version. For beta versions (0.xx.yy), will always return true. - /// - /// Minimum specified version in format of xx.yy.zz - /// Returns true if the running version meets or exceeds the minimum specified version - public static bool IsRunningMinimumVersionOrHigher(string minimumVersion) - { - Debug.LogMessage(LogEventLevel.Verbose, "Comparing running version '{0}' to minimum version '{1}'", AssemblyVersion, minimumVersion); + /// + /// Checks to see if the running version meets or exceed the minimum specified version. For beta versions (0.xx.yy), will always return true. + /// + /// Minimum specified version in format of xx.yy.zz + /// Returns true if the running version meets or exceeds the minimum specified version + public static bool IsRunningMinimumVersionOrHigher(string minimumVersion) + { + Debug.LogMessage(LogEventLevel.Verbose, "Comparing running version '{0}' to minimum version '{1}'", AssemblyVersion, minimumVersion); - if (String.IsNullOrEmpty(minimumVersion)) - { - Debug.LogMessage(LogEventLevel.Information,"Plugin does not specify a minimum version. Loading plugin may not work as expected. Proceeding with loading plugin"); - return true; - } - - var runtimeVersion = Regex.Match(AssemblyVersion, @"^(\d*).(\d*).(\d*).*"); + if (String.IsNullOrEmpty(minimumVersion)) + { + Debug.LogMessage(LogEventLevel.Information,"Plugin does not specify a minimum version. Loading plugin may not work as expected. Proceeding with loading plugin"); + return true; + } + + var runtimeVersion = Regex.Match(AssemblyVersion, @"^(\d*).(\d*).(\d*).*"); - var runtimeVersionMajor = Int16.Parse(runtimeVersion.Groups[1].Value); - var runtimeVersionMinor = Int16.Parse(runtimeVersion.Groups[2].Value); - var runtimeVersionBuild = Int16.Parse(runtimeVersion.Groups[3].Value); + var runtimeVersionMajor = Int16.Parse(runtimeVersion.Groups[1].Value); + var runtimeVersionMinor = Int16.Parse(runtimeVersion.Groups[2].Value); + var runtimeVersionBuild = Int16.Parse(runtimeVersion.Groups[3].Value); - var runtimeVer = new Version(runtimeVersionMajor, runtimeVersionMinor, runtimeVersionBuild); + var runtimeVer = new Version(runtimeVersionMajor, runtimeVersionMinor, runtimeVersionBuild); - Version minimumVer; - try - { - minimumVer = new Version(minimumVersion); - } - catch - { - Debug.LogMessage(LogEventLevel.Verbose, "unable to parse minimum version {0}. Bypassing plugin load.", minimumVersion); - return false; - } + Version minimumVer; + try + { + minimumVer = new Version(minimumVersion); + } + catch + { + Debug.LogMessage(LogEventLevel.Verbose, "unable to parse minimum version {0}. Bypassing plugin load.", minimumVersion); + return false; + } - // Check for beta build version - if (runtimeVer.Major != 0) - { - return runtimeVer.CompareTo(minimumVer) >= 0; - } + // Check for beta build version + if (runtimeVer.Major != 0) + { + return runtimeVer.CompareTo(minimumVer) >= 0; + } - Debug.LogMessage(LogEventLevel.Verbose, "Running Local Build. Bypassing Dependency Check."); - return true; + Debug.LogMessage(LogEventLevel.Verbose, "Running Local Build. Bypassing Dependency Check."); + return true; - /* - var minVersion = Regex.Match(minimumVersion, @"^(\d*).(\d*).(\d*)$"); + /* + var minVersion = Regex.Match(minimumVersion, @"^(\d*).(\d*).(\d*)$"); - if(!minVersion.Success) - { - - } + if(!minVersion.Success) + { + + } - var minVersionMajor = Int16.Parse(minVersion.Groups[1].Value); - var minVersionMinor = Int16.Parse(minVersion.Groups[2].Value); - var minVersionBuild = Int16.Parse(minVersion.Groups[3].Value); + var minVersionMajor = Int16.Parse(minVersion.Groups[1].Value); + var minVersionMinor = Int16.Parse(minVersion.Groups[2].Value); + var minVersionBuild = Int16.Parse(minVersion.Groups[3].Value); - if (minVersionMajor > runtimeVersionMajor) - return false; + if (minVersionMajor > runtimeVersionMajor) + return false; - if (minVersionMinor > runtimeVersionMinor) - return false; + if (minVersionMinor > runtimeVersionMinor) + return false; - if (minVersionBuild > runtimeVersionBuild) - return false; + if (minVersionBuild > runtimeVersionBuild) + return false; - return true; - */ - } + return true; + */ + } static Global() { @@ -279,7 +278,18 @@ static Global() CrestronConsole.PrintLine("Error starting CrestronDataStoreStatic: {0}", err); return; } + + try + { + CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture("en"); + CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CreateSpecificCulture("en"); + } + catch (CultureNotFoundException) + { + // If specific culture fails, fall back to invariant + CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture; + CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture; + } } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Global/JobTimer.cs b/src/PepperDash.Essentials.Core/Global/JobTimer.cs index 83159c120..c79fa53df 100644 --- a/src/PepperDash.Essentials.Core/Global/JobTimer.cs +++ b/src/PepperDash.Essentials.Core/Global/JobTimer.cs @@ -4,8 +4,8 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public static class JobTimer { static CTimer MinuteTimer; @@ -72,9 +72,8 @@ public JobTimerItem(string key, eJobTimerCycleTypes cycle, Action act) public enum eJobTimerCycleTypes { - RunEveryDay, + RunEveryDay, RunEveryHour, RunEveryHalfHour, RunEveryMinute - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Global/Scheduler.cs b/src/PepperDash.Essentials.Core/Global/Scheduler.cs index e226ce5c7..55a2116d2 100644 --- a/src/PepperDash.Essentials.Core/Global/Scheduler.cs +++ b/src/PepperDash.Essentials.Core/Global/Scheduler.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using Crestron.SimplSharp; -using Crestron.SimplSharp.Reflection; using Crestron.SimplSharp.Scheduler; using PepperDash.Core; @@ -11,94 +10,94 @@ using Serilog.Events; using Activator = System.Activator; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Global Scheduler for the system +/// +public static class Scheduler { - /// - /// Global Scheduler for the system - /// - public static class Scheduler - { - private static readonly Dictionary EventGroups = new Dictionary(); + private static readonly Dictionary EventGroups = new Dictionary(); - static Scheduler() - { - CrestronConsole.AddNewConsoleCommand(DeleteEventGroup, "DeleteEventGroup", "Deletes the event group by key", ConsoleAccessLevelEnum.AccessOperator); + static Scheduler() + { + CrestronConsole.AddNewConsoleCommand(DeleteEventGroup, "DeleteEventGroup", "Deletes the event group by key", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(ClearEventsFromGroup, "ClearAllEvents", "Clears all scheduled events for this group", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(ClearEventsFromGroup, "ClearAllEvents", "Clears all scheduled events for this group", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(ListAllEventGroups, "ListAllEventGroups", "Lists all the event groups by key", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(ListAllEventGroups, "ListAllEventGroups", "Lists all the event groups by key", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(ListAllEventsForGroup, "ListEventsForGroup", - "Lists all events for the given group", ConsoleAccessLevelEnum.AccessOperator); - } + CrestronConsole.AddNewConsoleCommand(ListAllEventsForGroup, "ListEventsForGroup", + "Lists all events for the given group", ConsoleAccessLevelEnum.AccessOperator); + } - static void DeleteEventGroup(string groupName) + static void DeleteEventGroup(string groupName) + { + if (EventGroups.ContainsKey(groupName)) { - if (EventGroups.ContainsKey(groupName)) - { - var group = EventGroups[groupName]; - - EventGroups.Remove(groupName); + var group = EventGroups[groupName]; + + EventGroups.Remove(groupName); - group.Dispose(); + group.Dispose(); - group = null; - } - } + group = null; + } + } - /// - /// Clears (deletes) all events from a group - /// - /// - static void ClearEventsFromGroup(string groupName) + /// + /// Clears (deletes) all events from a group + /// + /// + static void ClearEventsFromGroup(string groupName) + { + if (!EventGroups.ContainsKey(groupName)) { - if (!EventGroups.ContainsKey(groupName)) - { - Debug.LogMessage(LogEventLevel.Information, - "[Scheduler]: Unable to delete events from group '{0}'. Group not found in EventGroups dictionary.", null, - groupName); - return; - } + Debug.LogMessage(LogEventLevel.Information, + "[Scheduler]: Unable to delete events from group '{0}'. Group not found in EventGroups dictionary.", null, + groupName); + return; + } - var group = EventGroups[groupName]; + var group = EventGroups[groupName]; - if (group != null) - { - group.ClearAllEvents(); + if (group != null) + { + group.ClearAllEvents(); - Debug.LogMessage(LogEventLevel.Information, "[Scheduler]: All events deleted from group '{0}'", null, groupName); - } - else - Debug.LogMessage(LogEventLevel.Information, - "[Scheduler]: Unable to delete events from group '{0}'. Group not found in EventGroups dictionary.", null, - groupName); + Debug.LogMessage(LogEventLevel.Information, "[Scheduler]: All events deleted from group '{0}'", null, groupName); } + else + Debug.LogMessage(LogEventLevel.Information, + "[Scheduler]: Unable to delete events from group '{0}'. Group not found in EventGroups dictionary.", null, + groupName); + } - static void ListAllEventGroups(string command) + static void ListAllEventGroups(string command) + { + CrestronConsole.ConsoleCommandResponse("Event Groups:"); + foreach (var group in EventGroups) { - CrestronConsole.ConsoleCommandResponse("Event Groups:"); - foreach (var group in EventGroups) - { - CrestronConsole.ConsoleCommandResponse($"{group.Key}"); - } + CrestronConsole.ConsoleCommandResponse($"{group.Key}"); } + } - static void ListAllEventsForGroup(string args) - { - Debug.LogMessage(LogEventLevel.Information, "Getting events for group {0}...", null, args); + static void ListAllEventsForGroup(string args) + { + Debug.LogMessage(LogEventLevel.Information, "Getting events for group {0}...", null, args); - ScheduledEventGroup group; + ScheduledEventGroup group; - if (!EventGroups.TryGetValue(args, out group)) - { - Debug.LogMessage(LogEventLevel.Information, "Unabled to get event group for key {0}", null, args); - return; - } + if (!EventGroups.TryGetValue(args, out group)) + { + Debug.LogMessage(LogEventLevel.Information, "Unabled to get event group for key {0}", null, args); + return; + } - foreach (var evt in group.ScheduledEvents) - { - CrestronConsole.ConsoleCommandResponse( + foreach (var evt in group.ScheduledEvents) + { + CrestronConsole.ConsoleCommandResponse( $@" ****Event key {evt.Key}**** Event state: {evt.Value.EventState} @@ -108,198 +107,197 @@ static void ListAllEventsForGroup(string args) Recurrence: {evt.Value.Recurrence.Recurrence} Recurrence Days: {evt.Value.Recurrence.RecurrenceDays} ********************"); - } } + } - /// - /// Adds the event group to the global list - /// - /// - public static void AddEventGroup(ScheduledEventGroup eventGroup) - { - // Add this group to the global collection - if (!EventGroups.ContainsKey(eventGroup.Name)) - EventGroups.Add(eventGroup.Name, eventGroup); - } + /// + /// Adds the event group to the global list + /// + /// + public static void AddEventGroup(ScheduledEventGroup eventGroup) + { + // Add this group to the global collection + if (!EventGroups.ContainsKey(eventGroup.Name)) + EventGroups.Add(eventGroup.Name, eventGroup); + } - /// - /// Removes the event group from the global list - /// - /// - public static void RemoveEventGroup(ScheduledEventGroup eventGroup) - { - if(!EventGroups.ContainsKey(eventGroup.Name)) - EventGroups.Remove(eventGroup.Name); - } + /// + /// Removes the event group from the global list + /// + /// + public static void RemoveEventGroup(ScheduledEventGroup eventGroup) + { + if(!EventGroups.ContainsKey(eventGroup.Name)) + EventGroups.Remove(eventGroup.Name); + } - public static ScheduledEventGroup GetEventGroup(string key) - { - ScheduledEventGroup returnValue; + public static ScheduledEventGroup GetEventGroup(string key) + { + ScheduledEventGroup returnValue; - return EventGroups.TryGetValue(key, out returnValue) ? returnValue : null; - } + return EventGroups.TryGetValue(key, out returnValue) ? returnValue : null; } +} - public static class SchedulerUtilities +public static class SchedulerUtilities +{ + /// + /// Checks the day of week in eventTime to see if it matches the weekdays defined in the recurrence enum. + /// + /// + /// + /// + public static bool CheckIfDayOfWeekMatchesRecurrenceDays(DateTime eventTime, ScheduledEventCommon.eWeekDays recurrence) { - /// - /// Checks the day of week in eventTime to see if it matches the weekdays defined in the recurrence enum. - /// - /// - /// - /// - public static bool CheckIfDayOfWeekMatchesRecurrenceDays(DateTime eventTime, ScheduledEventCommon.eWeekDays recurrence) - { - bool isMatch = false; - - var dayOfWeek = eventTime.DayOfWeek; - - Debug.LogMessage(LogEventLevel.Debug, "[Scheduler]: eventTime day of week is: {0}",null, dayOfWeek); - switch (dayOfWeek) - { - case DayOfWeek.Sunday: - { - if ((recurrence & ScheduledEventCommon.eWeekDays.Sunday) == ScheduledEventCommon.eWeekDays.Sunday) - isMatch = true; - break; - } - case DayOfWeek.Monday: - { - if ((recurrence & ScheduledEventCommon.eWeekDays.Monday) == ScheduledEventCommon.eWeekDays.Monday) - isMatch = true; - break; - } - case DayOfWeek.Tuesday: - { - if ((recurrence & ScheduledEventCommon.eWeekDays.Tuesday) == ScheduledEventCommon.eWeekDays.Tuesday) - isMatch = true; - break; - } - case DayOfWeek.Wednesday: - { - if ((recurrence & ScheduledEventCommon.eWeekDays.Wednesday) == ScheduledEventCommon.eWeekDays.Wednesday) - isMatch = true; - break; - } - case DayOfWeek.Thursday: - { - if ((recurrence & ScheduledEventCommon.eWeekDays.Thursday) == ScheduledEventCommon.eWeekDays.Thursday) - isMatch = true; - break; - } - case DayOfWeek.Friday: - { - if ((recurrence & ScheduledEventCommon.eWeekDays.Friday) == ScheduledEventCommon.eWeekDays.Friday) - isMatch = true; - break; - } - case DayOfWeek.Saturday: - { - if ((recurrence & ScheduledEventCommon.eWeekDays.Saturday) == ScheduledEventCommon.eWeekDays.Saturday) - isMatch = true; - break; - } - } + bool isMatch = false; - Debug.LogMessage(LogEventLevel.Debug, "[Scheduler]: eventTime day of week matches recurrence days: {0}", isMatch); + var dayOfWeek = eventTime.DayOfWeek; - return isMatch; + Debug.LogMessage(LogEventLevel.Debug, "[Scheduler]: eventTime day of week is: {0}",null, dayOfWeek); + switch (dayOfWeek) + { + case DayOfWeek.Sunday: + { + if ((recurrence & ScheduledEventCommon.eWeekDays.Sunday) == ScheduledEventCommon.eWeekDays.Sunday) + isMatch = true; + break; + } + case DayOfWeek.Monday: + { + if ((recurrence & ScheduledEventCommon.eWeekDays.Monday) == ScheduledEventCommon.eWeekDays.Monday) + isMatch = true; + break; + } + case DayOfWeek.Tuesday: + { + if ((recurrence & ScheduledEventCommon.eWeekDays.Tuesday) == ScheduledEventCommon.eWeekDays.Tuesday) + isMatch = true; + break; + } + case DayOfWeek.Wednesday: + { + if ((recurrence & ScheduledEventCommon.eWeekDays.Wednesday) == ScheduledEventCommon.eWeekDays.Wednesday) + isMatch = true; + break; + } + case DayOfWeek.Thursday: + { + if ((recurrence & ScheduledEventCommon.eWeekDays.Thursday) == ScheduledEventCommon.eWeekDays.Thursday) + isMatch = true; + break; + } + case DayOfWeek.Friday: + { + if ((recurrence & ScheduledEventCommon.eWeekDays.Friday) == ScheduledEventCommon.eWeekDays.Friday) + isMatch = true; + break; + } + case DayOfWeek.Saturday: + { + if ((recurrence & ScheduledEventCommon.eWeekDays.Saturday) == ScheduledEventCommon.eWeekDays.Saturday) + isMatch = true; + break; + } } - public static bool CheckEventTimeForMatch(ScheduledEvent evnt, DateTime time) - { - return evnt.DateAndTime.Hour == time.Hour && evnt.DateAndTime.Minute == time.Minute; - } + Debug.LogMessage(LogEventLevel.Debug, "[Scheduler]: eventTime day of week matches recurrence days: {0}", isMatch); - public static bool CheckEventRecurrenceForMatch(ScheduledEvent evnt, ScheduledEventCommon.eWeekDays days) - { - return evnt.Recurrence.RecurrenceDays == days; - } + return isMatch; + } - public static void CreateEventFromConfig(ScheduledEventConfig config, ScheduledEventGroup group, ScheduledEvent.UserEventCallBack handler) + public static bool CheckEventTimeForMatch(ScheduledEvent evnt, DateTime time) + { + return evnt.DateAndTime.Hour == time.Hour && evnt.DateAndTime.Minute == time.Minute; + } + + public static bool CheckEventRecurrenceForMatch(ScheduledEvent evnt, ScheduledEventCommon.eWeekDays days) + { + return evnt.Recurrence.RecurrenceDays == days; + } + + public static void CreateEventFromConfig(ScheduledEventConfig config, ScheduledEventGroup group, ScheduledEvent.UserEventCallBack handler) + { + try { - try + if (group == null) { - if (group == null) - { - Debug.LogMessage(LogEventLevel.Information, "Unable to create event. Group is null", null, null); - return; - } - var scheduledEvent = new ScheduledEvent(config.Key, group) - { - Acknowledgeable = config.Acknowledgeable, - Persistent = config.Persistent - }; + Debug.LogMessage(LogEventLevel.Information, "Unable to create event. Group is null", null, null); + return; + } + var scheduledEvent = new ScheduledEvent(config.Key, group) + { + Acknowledgeable = config.Acknowledgeable, + Persistent = config.Persistent + }; - scheduledEvent.UserCallBack += handler; + scheduledEvent.UserCallBack += handler; - scheduledEvent.DateAndTime.SetFirstDayOfWeek(ScheduledEventCommon.eFirstDayOfWeek.Sunday); + scheduledEvent.DateAndTime.SetFirstDayOfWeek(ScheduledEventCommon.eFirstDayOfWeek.Sunday); - var eventTime = DateTime.Parse(config.Time); + var eventTime = DateTime.Parse(config.Time); - if (DateTime.Now > eventTime) - { - eventTime = eventTime.AddDays(1); - } + if (DateTime.Now > eventTime) + { + eventTime = eventTime.AddDays(1); + } - Debug.LogMessage(LogEventLevel.Verbose, "[Scheduler] Current Date day of week: {0} recurrence days: {1}", null, eventTime.DayOfWeek, - config.Days); + Debug.LogMessage(LogEventLevel.Verbose, "[Scheduler] Current Date day of week: {0} recurrence days: {1}", null, eventTime.DayOfWeek, + config.Days); - var dayOfWeekConverted = ConvertDayOfWeek(eventTime); + var dayOfWeekConverted = ConvertDayOfWeek(eventTime); - Debug.LogMessage(LogEventLevel.Debug, "[Scheduler] eventTime Day: {0}", null, dayOfWeekConverted); + Debug.LogMessage(LogEventLevel.Debug, "[Scheduler] eventTime Day: {0}", null, dayOfWeekConverted); - while (!dayOfWeekConverted.IsFlagSet(config.Days)) - { - eventTime = eventTime.AddDays(1); + while (!dayOfWeekConverted.IsFlagSet(config.Days)) + { + eventTime = eventTime.AddDays(1); - dayOfWeekConverted = ConvertDayOfWeek(eventTime); - } + dayOfWeekConverted = ConvertDayOfWeek(eventTime); + } - scheduledEvent.DateAndTime.SetAbsoluteEventTime(eventTime); + scheduledEvent.DateAndTime.SetAbsoluteEventTime(eventTime); - scheduledEvent.Recurrence.Weekly(config.Days); + scheduledEvent.Recurrence.Weekly(config.Days); - Debug.LogMessage(LogEventLevel.Verbose, $"[Scheduler] Event State: {scheduledEvent.EventState}", null, null); + Debug.LogMessage(LogEventLevel.Verbose, $"[Scheduler] Event State: {scheduledEvent.EventState}", null, null); - if (config.Enable && scheduledEvent.EventState != ScheduledEventCommon.eEventState.Enabled) - { - scheduledEvent.Enable(); - } - else if (!config.Enable && scheduledEvent.EventState != ScheduledEventCommon.eEventState.Disabled) - { - scheduledEvent.Disable(); - } - + if (config.Enable && scheduledEvent.EventState != ScheduledEventCommon.eEventState.Enabled) + { + scheduledEvent.Enable(); } - catch (Exception e) + else if (!config.Enable && scheduledEvent.EventState != ScheduledEventCommon.eEventState.Disabled) { - - Debug.LogMessage(LogEventLevel.Error, "Error creating scheduled event: {0}", null, e); + scheduledEvent.Disable(); } - } - private static ScheduledEventCommon.eWeekDays ConvertDayOfWeek(DateTime eventTime) + } + catch (Exception e) { - return (ScheduledEventCommon.eWeekDays) Enum.Parse(typeof(ScheduledEventCommon.eWeekDays), eventTime.DayOfWeek.ToString(), true); + + Debug.LogMessage(LogEventLevel.Error, "Error creating scheduled event: {0}", null, e); } + } - private static bool IsFlagSet(this T value, T flag) where T : struct - { - CheckIsEnum(true); + private static ScheduledEventCommon.eWeekDays ConvertDayOfWeek(DateTime eventTime) + { + return (ScheduledEventCommon.eWeekDays) Enum.Parse(typeof(ScheduledEventCommon.eWeekDays), eventTime.DayOfWeek.ToString(), true); + } - var lValue = Convert.ToInt64(value); - var lFlag = Convert.ToInt64(flag); + private static bool IsFlagSet(this T value, T flag) where T : struct + { + CheckIsEnum(true); - return (lValue & lFlag) != 0; - } + var lValue = Convert.ToInt64(value); + var lFlag = Convert.ToInt64(flag); - private static void CheckIsEnum(bool withFlags) - { - if (!typeof(T).IsEnum) - throw new ArgumentException(string.Format("Type '{0}' is not an enum", typeof(T).FullName)); - if (withFlags && !Attribute.IsDefined(typeof(T), typeof(FlagsAttribute))) - throw new ArgumentException(string.Format("Type '{0}' doesn't have the 'Flags' attribute", typeof(T).FullName)); - } + return (lValue & lFlag) != 0; + } + + private static void CheckIsEnum(bool withFlags) + { + if (!typeof(T).IsEnum) + throw new ArgumentException(string.Format("Type '{0}' is not an enum", typeof(T).FullName)); + if (withFlags && !Attribute.IsDefined(typeof(T), typeof(FlagsAttribute))) + throw new ArgumentException(string.Format("Type '{0}' doesn't have the 'Flags' attribute", typeof(T).FullName)); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/InUseTracking/IInUseTracking.cs b/src/PepperDash.Essentials.Core/InUseTracking/IInUseTracking.cs index 97a7c7f60..404c52af1 100644 --- a/src/PepperDash.Essentials.Core/InUseTracking/IInUseTracking.cs +++ b/src/PepperDash.Essentials.Core/InUseTracking/IInUseTracking.cs @@ -4,13 +4,12 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// Defines a class that uses an InUseTracker /// public interface IInUseTracking { InUseTracking InUseTracker { get; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/InUseTracking/InUseTracking.cs b/src/PepperDash.Essentials.Core/InUseTracking/InUseTracking.cs index 4bf1a551a..3015171c5 100644 --- a/src/PepperDash.Essentials.Core/InUseTracking/InUseTracking.cs +++ b/src/PepperDash.Essentials.Core/InUseTracking/InUseTracking.cs @@ -4,8 +4,8 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// Provides in use tracking. Objects can register with this. InUseFeedback can provide /// events when usage changes. @@ -96,5 +96,4 @@ public InUseTrackingObject(object user, string label) // Tracker = tracker; // EventType = eventType; // } - //} -} \ No newline at end of file + //} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Interfaces/ILogStrings.cs b/src/PepperDash.Essentials.Core/Interfaces/ILogStrings.cs index 4f48e278e..fbf46abba 100644 --- a/src/PepperDash.Essentials.Core/Interfaces/ILogStrings.cs +++ b/src/PepperDash.Essentials.Core/Interfaces/ILogStrings.cs @@ -5,13 +5,12 @@ using Crestron.SimplSharp; using PepperDash.Core; -namespace PepperDash.Essentials.Core.Interfaces -{ +namespace PepperDash.Essentials.Core.Interfaces; + public interface ILogStrings : IKeyed { /// /// Defines a class that is capable of logging a string /// void SendToLog(IKeyed device, string logMessage); - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Interfaces/ILogStringsWithLevel.cs b/src/PepperDash.Essentials.Core/Interfaces/ILogStringsWithLevel.cs index 47c3674eb..2768d2839 100644 --- a/src/PepperDash.Essentials.Core/Interfaces/ILogStringsWithLevel.cs +++ b/src/PepperDash.Essentials.Core/Interfaces/ILogStringsWithLevel.cs @@ -5,14 +5,12 @@ using Crestron.SimplSharp; using PepperDash.Core; -namespace PepperDash.Essentials.Core.Interfaces -{ +namespace PepperDash.Essentials.Core.Interfaces; + public interface ILogStringsWithLevel : IKeyed { /// /// Defines a class that is capable of logging a string with an int level /// void SendToLog(IKeyed device, Debug.ErrorLogLevel level,string logMessage); - } - -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/JoinMaps/JoinMapBase.cs b/src/PepperDash.Essentials.Core/JoinMaps/JoinMapBase.cs index 37760e09c..9cd6776e3 100644 --- a/src/PepperDash.Essentials.Core/JoinMaps/JoinMapBase.cs +++ b/src/PepperDash.Essentials.Core/JoinMaps/JoinMapBase.cs @@ -15,527 +15,526 @@ using Newtonsoft.Json; using Serilog.Events; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public static class JoinMapHelper { - public static class JoinMapHelper + /// + /// Attempts to get the serialized join map from config + /// + /// + /// + public static string GetSerializedJoinMapForDevice(string joinMapKey) { - /// - /// Attempts to get the serialized join map from config - /// - /// - /// - public static string GetSerializedJoinMapForDevice(string joinMapKey) - { - if (string.IsNullOrEmpty(joinMapKey)) - return null; + if (string.IsNullOrEmpty(joinMapKey)) + return null; - var joinMap = ConfigReader.ConfigObject.JoinMaps[joinMapKey]; + var joinMap = ConfigReader.ConfigObject.JoinMaps[joinMapKey]; - return joinMap.ToString(); - } + return joinMap.ToString(); + } - /// - /// Attempts to get the serialized join map from config - /// - /// - /// - public static string GetJoinMapForDevice(string joinMapKey) - { - return GetSerializedJoinMapForDevice(joinMapKey); - } + /// + /// 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) + /// + /// Attempts to find a custom join map by key and returns it deserialized if found + /// + /// + /// + public static Dictionary TryGetJoinMapAdvancedForDevice(string joinMapKey) + { + try { - try - { - if (string.IsNullOrEmpty(joinMapKey)) - return null; - - if (!ConfigReader.ConfigObject.JoinMaps.ContainsKey(joinMapKey)) - { - Debug.LogMessage(LogEventLevel.Verbose, "No Join Map found in config with key: '{0}'", joinMapKey); - return null; - } - - Debug.LogMessage(LogEventLevel.Verbose, "Attempting to load custom join map with key: {0}", joinMapKey); - - var joinMapJToken = ConfigReader.ConfigObject.JoinMaps[joinMapKey]; - - if (joinMapJToken == null) - return null; - - var joinMapData = joinMapJToken.ToObject>(); + if (string.IsNullOrEmpty(joinMapKey)) + return null; - return joinMapData; - } - catch (Exception e) + if (!ConfigReader.ConfigObject.JoinMaps.ContainsKey(joinMapKey)) { - Debug.LogMessage(LogEventLevel.Verbose, "Error getting join map for key: '{0}'. Error: {1}", joinMapKey, e); + Debug.LogMessage(LogEventLevel.Verbose, "No Join Map found in config with key: '{0}'", joinMapKey); return null; } - } - } + Debug.LogMessage(LogEventLevel.Verbose, "Attempting to load custom join map with key: {0}", joinMapKey); - /// - /// Base class for join maps - /// - public abstract class JoinMapBaseAdvanced - { - protected uint JoinOffset; + var joinMapJToken = ConfigReader.ConfigObject.JoinMaps[joinMapKey]; - /// - /// The collection of joins and associated metadata - /// - public Dictionary Joins { get; private set; } + if (joinMapJToken == null) + return null; - protected JoinMapBaseAdvanced(uint joinStart) - { - Joins = new Dictionary(); + var joinMapData = joinMapJToken.ToObject>(); - JoinOffset = joinStart - 1; + return joinMapData; } - - protected JoinMapBaseAdvanced(uint joinStart, Type type):this(joinStart) + catch (Exception e) { - AddJoins(type); + Debug.LogMessage(LogEventLevel.Verbose, "Error getting join map for key: '{0}'. Error: {1}", joinMapKey, e); + return null; } + } - protected void AddJoins(Type type) - { - var fields = - type.GetFields(BindingFlags.Public | BindingFlags.Instance) - .Where(f => f.IsDefined(typeof (JoinNameAttribute), true)).ToList(); +} - Debug.LogMessage(LogEventLevel.Debug, "Got {fields} with JoinNameAttribute", fields.Count); +/// +/// Base class for join maps +/// +public abstract class JoinMapBaseAdvanced +{ + protected uint JoinOffset; - foreach (var field in fields) - { - var childClass = Convert.ChangeType(this, type, null); + /// + /// The collection of joins and associated metadata + /// + public Dictionary Joins { get; private set; } - //this here is JoinMapBaseAdvanced, not the child class. JoinMapBaseAdvanced has no fields. + protected JoinMapBaseAdvanced(uint joinStart) + { + Joins = new Dictionary(); - if (!(field.GetValue(childClass) is JoinDataComplete value)) - { - Debug.LogMessage(LogEventLevel.Information, "Unable to cast base class to {0}", type.Name); - continue; - } + JoinOffset = joinStart - 1; + } - value.SetJoinOffset(JoinOffset); + protected JoinMapBaseAdvanced(uint joinStart, Type type):this(joinStart) + { + AddJoins(type); + } - var joinName = value.GetNameAttribute(field); + protected void AddJoins(Type type) + { + var fields = + type.GetFields(BindingFlags.Public | BindingFlags.Instance) + .Where(f => f.IsDefined(typeof (JoinNameAttribute), true)).ToList(); - if (string.IsNullOrEmpty(joinName)) continue; + Debug.LogMessage(LogEventLevel.Debug, "Got {fields} with JoinNameAttribute", fields.Count); - Joins.Add(joinName, value); - } + foreach (var field in fields) + { + var childClass = Convert.ChangeType(this, type, null); + //this here is JoinMapBaseAdvanced, not the child class. JoinMapBaseAdvanced has no fields. - if (Debug.Level > 0) + if (!(field.GetValue(childClass) is JoinDataComplete value)) { - PrintJoinMapInfo(); + Debug.LogMessage(LogEventLevel.Information, "Unable to cast base class to {0}", type.Name); + continue; } - } - /// - /// Prints the join information to console - /// - public void PrintJoinMapInfo() - { - var sb = JoinmapStringBuilder(); + value.SetJoinOffset(JoinOffset); - CrestronConsole.ConsoleCommandResponse(sb.ToString()); + var joinName = value.GetNameAttribute(field); + + if (string.IsNullOrEmpty(joinName)) continue; + + Joins.Add(joinName, value); } - private StringBuilder JoinmapStringBuilder() + + if (Debug.Level > 0) { - var sb = new StringBuilder(); - - var lineEnding = "\r\n"; - - var digitals = - Joins.Where(j => j.Value.Metadata.JoinType.HasFlag(eJoinType.Digital)) - .ToDictionary(j => j.Key, j => j.Value); - - var analogs = Joins.Where(j => j.Value.Metadata.JoinType.HasFlag(eJoinType.Analog)) - .ToDictionary(j => j.Key, j => j.Value); - - var serials = - Joins.Where(j => j.Value.Metadata.JoinType.HasFlag(eJoinType.Serial)) - .ToDictionary(j => j.Key, j => j.Value); - - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Digital join count {digitalCount} Analog join count {analogCount} Serial join count {serialCount}", null, digitals.Count, analogs.Count, serials.Count); - - // Get the joins of each type and print them - sb.Append($"# {GetType().Name}\r\n"); - sb.Append(lineEnding); - sb.Append($"## Digitals{lineEnding}"); - sb.Append(lineEnding); - // Get the joins of each type and print them - - var digitalSb = AppendJoinList(GetSortedJoins(digitals)); - digitalSb.Append($"## Analogs{lineEnding}"); - digitalSb.Append(lineEnding); - - var analogSb = AppendJoinList(GetSortedJoins(analogs)); - analogSb.Append($"## Serials{lineEnding}"); - analogSb.Append(lineEnding); - - - var serialSb = AppendJoinList(GetSortedJoins(serials)); - - sb.EnsureCapacity(sb.Length + digitalSb.Length + analogSb.Length + serialSb.Length); - sb.Append(digitalSb).Append(analogSb).Append(serialSb); - return sb; + PrintJoinMapInfo(); } + } - /// - /// Prints the join information to console - /// - public void MarkdownJoinMapInfo(string deviceKey, string bridgeKey) - { - var pluginType = GetType().Name; + /// + /// Prints the join information to console + /// + public void PrintJoinMapInfo() + { + var sb = JoinmapStringBuilder(); - CrestronConsole.ConsoleCommandResponse("{0}:\n", pluginType); + CrestronConsole.ConsoleCommandResponse(sb.ToString()); + } + private StringBuilder JoinmapStringBuilder() + { + var sb = new StringBuilder(); + + var lineEnding = "\r\n"; + + var digitals = + Joins.Where(j => j.Value.Metadata.JoinType.HasFlag(eJoinType.Digital)) + .ToDictionary(j => j.Key, j => j.Value); + + var analogs = Joins.Where(j => j.Value.Metadata.JoinType.HasFlag(eJoinType.Analog)) + .ToDictionary(j => j.Key, j => j.Value); + + var serials = + Joins.Where(j => j.Value.Metadata.JoinType.HasFlag(eJoinType.Serial)) + .ToDictionary(j => j.Key, j => j.Value); + + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Digital join count {digitalCount} Analog join count {analogCount} Serial join count {serialCount}", null, digitals.Count, analogs.Count, serials.Count); + + // Get the joins of each type and print them + sb.Append($"# {GetType().Name}\r\n"); + sb.Append(lineEnding); + sb.Append($"## Digitals{lineEnding}"); + sb.Append(lineEnding); + // Get the joins of each type and print them + + var digitalSb = AppendJoinList(GetSortedJoins(digitals)); + digitalSb.Append($"## Analogs{lineEnding}"); + digitalSb.Append(lineEnding); + + var analogSb = AppendJoinList(GetSortedJoins(analogs)); + analogSb.Append($"## Serials{lineEnding}"); + analogSb.Append(lineEnding); + + + var serialSb = AppendJoinList(GetSortedJoins(serials)); + + sb.EnsureCapacity(sb.Length + digitalSb.Length + analogSb.Length + serialSb.Length); + sb.Append(digitalSb).Append(analogSb).Append(serialSb); + return sb; + } + /// + /// Prints the join information to console + /// + public void MarkdownJoinMapInfo(string deviceKey, string bridgeKey) + { + var pluginType = GetType().Name; - WriteJoinmapMarkdown(JoinmapStringBuilder(), pluginType, bridgeKey, deviceKey); + CrestronConsole.ConsoleCommandResponse("{0}:\n", pluginType); - } - private static void WriteJoinmapMarkdown(StringBuilder stringBuilder, string pluginType, string bridgeKey, string deviceKey) - { - var fileName = string.Format("{0}{1}{2}__{3}__{4}.md", Global.FilePathPrefix, "joinMaps/", pluginType, bridgeKey, deviceKey); - using (var sw = new StreamWriter(fileName)) - { - sw.WriteLine(stringBuilder.ToString()); - CrestronConsole.ConsoleCommandResponse("Joinmap Readme generated and written to {0}", fileName); - } + WriteJoinmapMarkdown(JoinmapStringBuilder(), pluginType, bridgeKey, deviceKey); - } + } + + private static void WriteJoinmapMarkdown(StringBuilder stringBuilder, string pluginType, string bridgeKey, string deviceKey) + { + var fileName = string.Format("{0}{1}{2}__{3}__{4}.md", Global.FilePathPrefix, "joinMaps/", pluginType, bridgeKey, deviceKey); - /// - /// Returns a sorted list by JoinNumber - /// - /// - /// - static List> GetSortedJoins(Dictionary joins) + using (var sw = new StreamWriter(fileName)) { - var sortedJoins = joins.ToList(); + sw.WriteLine(stringBuilder.ToString()); + CrestronConsole.ConsoleCommandResponse("Joinmap Readme generated and written to {0}", fileName); + } + + } - sortedJoins.Sort((pair1, pair2) => pair1.Value.JoinNumber.CompareTo(pair2.Value.JoinNumber)); + /// + /// Returns a sorted list by JoinNumber + /// + /// + /// + static List> GetSortedJoins(Dictionary joins) + { + var sortedJoins = joins.ToList(); - return sortedJoins; - } + sortedJoins.Sort((pair1, pair2) => pair1.Value.JoinNumber.CompareTo(pair2.Value.JoinNumber)); + + return sortedJoins; + } - static StringBuilder AppendJoinList(List> joins) + static StringBuilder AppendJoinList(List> joins) + { + var sb = new StringBuilder(); + const string stringFormatter = "| {0} | {1} | {2} | {3} | {4} |\r\n"; + const int joinNumberLen = 11; + const int joinSpanLen = 9; + const int typeLen = 19; + const int capabilitiesLen = 12; + var descriptionLen = (from @join in joins select @join.Value into j select j.Metadata.Description.Length).Concat(new[] {11}).Max(); + + //build header + sb.Append(string.Format(stringFormatter, + string.Format("Join Number").PadRight(joinNumberLen, ' '), + string.Format("Join Span").PadRight(joinSpanLen, ' '), + string.Format("Description").PadRight(descriptionLen, ' '), + string.Format("Type").PadRight(typeLen, ' '), + string.Format("Capabilities").PadRight(capabilitiesLen, ' '))); + //build table seperator + sb.Append(string.Format(stringFormatter, + new string('-', joinNumberLen), + new string('-', joinSpanLen), + new string('-', descriptionLen), + new string('-', typeLen), + new string('-', capabilitiesLen))); + + foreach (var join in joins) { - var sb = new StringBuilder(); - const string stringFormatter = "| {0} | {1} | {2} | {3} | {4} |\r\n"; - const int joinNumberLen = 11; - const int joinSpanLen = 9; - const int typeLen = 19; - const int capabilitiesLen = 12; - var descriptionLen = (from @join in joins select @join.Value into j select j.Metadata.Description.Length).Concat(new[] {11}).Max(); - - //build header - sb.Append(string.Format(stringFormatter, - string.Format("Join Number").PadRight(joinNumberLen, ' '), - string.Format("Join Span").PadRight(joinSpanLen, ' '), - string.Format("Description").PadRight(descriptionLen, ' '), - string.Format("Type").PadRight(typeLen, ' '), - string.Format("Capabilities").PadRight(capabilitiesLen, ' '))); - //build table seperator - sb.Append(string.Format(stringFormatter, - new string('-', joinNumberLen), - new string('-', joinSpanLen), - new string('-', descriptionLen), - new string('-', typeLen), - new string('-', capabilitiesLen))); - - foreach (var join in joins) - { - sb.Append(join.Value.GetMarkdownFormattedData(stringFormatter, descriptionLen)); - } - sb.Append("\r\n"); - return sb; + sb.Append(join.Value.GetMarkdownFormattedData(stringFormatter, descriptionLen)); } + sb.Append("\r\n"); + return sb; + } - /// - /// 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) + /// + /// 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) { - foreach (var customJoinData in joinData) + JoinDataComplete join; + + if (!Joins.TryGetValue(customJoinData.Key, out join)) { - JoinDataComplete join; - - if (!Joins.TryGetValue(customJoinData.Key, out join)) - { - Debug.LogMessage(LogEventLevel.Verbose, "No matching key found in join map for: '{0}'", customJoinData.Key); - continue; - } - - if (join != null) - { - join.SetCustomJoinData(customJoinData.Value); - } + Debug.LogMessage(LogEventLevel.Verbose, "No matching key found in join map for: '{0}'", customJoinData.Key); + continue; } - PrintJoinMapInfo(); + if (join != null) + { + join.SetCustomJoinData(customJoinData.Value); + } } - ///// - ///// 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; - //} + 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, + ToFusion = 4, + FromFusion = 8, + ToFromFusion = ToFusion | FromFusion, +} + +[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; /// - /// Read = Provides feedback to SIMPL - /// Write = Responds to sig values from SIMPL + /// A description for the join to better describe its usage /// - [Flags] - public enum eJoinCapabilities - { - None = 0, - ToSIMPL = 1, - FromSIMPL = 2, - ToFromSIMPL = ToSIMPL | FromSIMPL, - ToFusion = 4, - FromFusion = 8, - ToFromFusion = ToFusion | FromFusion, - } - - [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, - } - + [JsonProperty("description")] + public string Description { get { return _description; } set { _description = value; } } /// - /// Metadata describing the join + /// Signal type(s) /// - public class JoinMetadata - { - private string _description; - /// - /// 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; } + [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 overridden from configuratino +/// +public class JoinData +{ /// - /// Data describing the join. Can be overridden from configuratino + /// Join number (based on join offset value) /// - 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; } - /// - /// Fusion Attribute Name (optional) - /// - [JsonProperty("attributeName")] - public string AttributeName { get; set; } - } + [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; } + /// + /// Fusion Attribute Name (optional) + /// + [JsonProperty("attributeName")] + public string AttributeName { 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; } /// - /// A class to aggregate the JoinData and JoinMetadata for a join + /// To store some future information as you please /// - public class JoinDataComplete + public object UserObject { get; private set; } + + public JoinDataComplete(JoinData data, JoinMetadata metadata) { - private uint _joinOffset; + _data = data; + Metadata = metadata; + } - private JoinData _data; - public JoinMetadata Metadata { get; set; } - /// - /// To store some future information as you please - /// - public object UserObject { get; private set; } + public string GetMarkdownFormattedData(string stringFormatter, int descriptionLen) + { - public JoinDataComplete(JoinData data, JoinMetadata metadata) - { - _data = data; - Metadata = metadata; - } + //Fixed Width Headers + var joinNumberLen = string.Format("Join Number").Length; + var joinSpanLen = string.Format("Join Span").Length; + var typeLen = string.Format("AnalogDigitalSerial").Length; + var capabilitiesLen = string.Format("ToFromFusion").Length; - public string GetMarkdownFormattedData(string stringFormatter, int descriptionLen) + //Track which one failed, if it did + const string placeholder = "unknown"; + var dataArray = new Dictionary { + {"joinNumber", placeholder.PadRight(joinNumberLen, ' ')}, + {"joinSpan", placeholder.PadRight(joinSpanLen, ' ')}, + {"description", placeholder.PadRight(descriptionLen, ' ')}, + {"joinType", placeholder.PadRight(typeLen, ' ')}, + {"capabilities", placeholder.PadRight(capabilitiesLen, ' ')} + }; - //Fixed Width Headers - var joinNumberLen = string.Format("Join Number").Length; - var joinSpanLen = string.Format("Join Span").Length; - var typeLen = string.Format("AnalogDigitalSerial").Length; - var capabilitiesLen = string.Format("ToFromFusion").Length; - //Track which one failed, if it did - const string placeholder = "unknown"; - var dataArray = new Dictionary - { - {"joinNumber", placeholder.PadRight(joinNumberLen, ' ')}, - {"joinSpan", placeholder.PadRight(joinSpanLen, ' ')}, - {"description", placeholder.PadRight(descriptionLen, ' ')}, - {"joinType", placeholder.PadRight(typeLen, ' ')}, - {"capabilities", placeholder.PadRight(capabilitiesLen, ' ')} - }; - - - try - { - dataArray["joinNumber"] = string.Format("{0}", JoinNumber.ToString(CultureInfo.InvariantCulture).ReplaceIfNullOrEmpty(placeholder)).PadRight(joinNumberLen, ' '); - dataArray["joinSpan"] = string.Format("{0}", JoinSpan.ToString(CultureInfo.InvariantCulture).ReplaceIfNullOrEmpty(placeholder)).PadRight(joinSpanLen, ' '); - dataArray["description"] = string.Format("{0}", Metadata.Description.ReplaceIfNullOrEmpty(placeholder)).PadRight(descriptionLen, ' '); - dataArray["joinType"] = string.Format("{0}", Metadata.JoinType.ToString().ReplaceIfNullOrEmpty(placeholder)).PadRight(typeLen, ' '); - dataArray["capabilities"] = string.Format("{0}", Metadata.JoinCapabilities.ToString().ReplaceIfNullOrEmpty(placeholder)).PadRight(capabilitiesLen, ' '); - - return string.Format(stringFormatter, - dataArray["joinNumber"], - dataArray["joinSpan"], - dataArray["description"], - dataArray["joinType"], - dataArray["capabilities"]); + try + { + dataArray["joinNumber"] = string.Format("{0}", JoinNumber.ToString(CultureInfo.InvariantCulture).ReplaceIfNullOrEmpty(placeholder)).PadRight(joinNumberLen, ' '); + dataArray["joinSpan"] = string.Format("{0}", JoinSpan.ToString(CultureInfo.InvariantCulture).ReplaceIfNullOrEmpty(placeholder)).PadRight(joinSpanLen, ' '); + dataArray["description"] = string.Format("{0}", Metadata.Description.ReplaceIfNullOrEmpty(placeholder)).PadRight(descriptionLen, ' '); + dataArray["joinType"] = string.Format("{0}", Metadata.JoinType.ToString().ReplaceIfNullOrEmpty(placeholder)).PadRight(typeLen, ' '); + dataArray["capabilities"] = string.Format("{0}", Metadata.JoinCapabilities.ToString().ReplaceIfNullOrEmpty(placeholder)).PadRight(capabilitiesLen, ' '); + + return string.Format(stringFormatter, + dataArray["joinNumber"], + dataArray["joinSpan"], + dataArray["description"], + dataArray["joinType"], + dataArray["capabilities"]); - } - catch (Exception e) + } + catch (Exception e) + { + //Don't Throw - we don't want to kill the system if this falls over - it's not mission critical. Print the error, use placeholder data + var errorKey = string.Empty; + foreach (var item in dataArray) { - //Don't Throw - we don't want to kill the system if this falls over - it's not mission critical. Print the error, use placeholder data - var errorKey = string.Empty; - foreach (var item in dataArray) - { - if (item.Value.TrimEnd() == placeholder) continue; - errorKey = item.Key; - break; - } - Debug.LogMessage(LogEventLevel.Information, "Unable to decode join metadata {1}- {0}", e.Message, !string.IsNullOrEmpty(errorKey) ? (' ' + errorKey) : string.Empty); - return string.Format(stringFormatter, - dataArray["joinNumber"], - dataArray["joinSpan"], - dataArray["description"], - dataArray["joinType"], - dataArray["capabilities"]); + if (item.Value.TrimEnd() == placeholder) continue; + errorKey = item.Key; + break; } + Debug.LogMessage(LogEventLevel.Information, "Unable to decode join metadata {1}- {0}", e.Message, !string.IsNullOrEmpty(errorKey) ? (' ' + errorKey) : string.Empty); + return string.Format(stringFormatter, + dataArray["joinNumber"], + dataArray["joinSpan"], + dataArray["description"], + dataArray["joinType"], + dataArray["capabilities"]); } + } - /// - /// Sets the join offset value - /// - /// - public void SetJoinOffset(uint joinOffset) - { - _joinOffset = joinOffset; - } + /// + /// 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; } - } + /// + /// 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 uint JoinSpan + { + get { return _data.JoinSpan; } + } - public string AttributeName - { - get { return _data.AttributeName; } - } + public string AttributeName + { + get { return _data.AttributeName; } + } - public void SetCustomJoinData(JoinData customJoinData) - { - _data = customJoinData; - } + public void SetCustomJoinData(JoinData customJoinData) + { + _data = customJoinData; + } - public string GetNameAttribute(MemberInfo memberInfo) - { - var name = string.Empty; - var attribute = (JoinNameAttribute)Attribute.GetCustomAttribute(memberInfo, typeof(JoinNameAttribute)); + public string GetNameAttribute(MemberInfo memberInfo) + { + var name = string.Empty; + var attribute = (JoinNameAttribute)Attribute.GetCustomAttribute(memberInfo, typeof(JoinNameAttribute)); - if (attribute == null) return name; + if (attribute == null) return name; - name = attribute.Name; - Debug.LogMessage(LogEventLevel.Verbose, "JoinName Attribute value: {0}", name); - return name; - } + name = attribute.Name; + Debug.LogMessage(LogEventLevel.Verbose, "JoinName Attribute value: {0}", name); + return name; } +} - - [AttributeUsage(AttributeTargets.All)] - public class JoinNameAttribute : Attribute - { - private string _Name; - public JoinNameAttribute(string name) - { - Debug.LogMessage(LogEventLevel.Verbose, "Setting Attribute Name: {0}",null, name); - _Name = name; - } +[AttributeUsage(AttributeTargets.All)] +public class JoinNameAttribute : Attribute +{ + private string _Name; - public string Name - { - get { return _Name; } - } + public JoinNameAttribute(string name) + { + Debug.LogMessage(LogEventLevel.Verbose, "Setting Attribute Name: {0}",null, name); + _Name = name; + } + + public string Name + { + get { return _Name; } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/License/EssentialsLicenseManager.cs b/src/PepperDash.Essentials.Core/License/EssentialsLicenseManager.cs index a242591e6..4c2df0c3b 100644 --- a/src/PepperDash.Essentials.Core/License/EssentialsLicenseManager.cs +++ b/src/PepperDash.Essentials.Core/License/EssentialsLicenseManager.cs @@ -11,8 +11,8 @@ using Serilog.Events; -namespace PepperDash.Essentials.License -{ +namespace PepperDash.Essentials.License; + public abstract class LicenseManager { public BoolFeedback LicenseIsValid { get; protected set; } @@ -83,5 +83,4 @@ protected override string GetStatusString() { return string.Format("License Status: {0}", IsValid ? "Valid" : "Not Valid"); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Lighting/Lighting Interfaces.cs b/src/PepperDash.Essentials.Core/Lighting/Lighting Interfaces.cs index c762147cd..8cc9e815e 100644 --- a/src/PepperDash.Essentials.Core/Lighting/Lighting Interfaces.cs +++ b/src/PepperDash.Essentials.Core/Lighting/Lighting Interfaces.cs @@ -1,59 +1,57 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.Core.Lighting +namespace PepperDash.Essentials.Core.Lighting; + +/// +/// Requirements for a device that implements lighting scene control +/// +public interface ILightingScenes { - /// - /// Requirements for a device that implements lighting scene control - /// - public interface ILightingScenes - { - event EventHandler LightingSceneChange; + event EventHandler LightingSceneChange; - List LightingScenes { get; } + List LightingScenes { get; } - void SelectScene(LightingScene scene); + void SelectScene(LightingScene scene); - LightingScene CurrentLightingScene { get; } + LightingScene CurrentLightingScene { get; } - } +} - public interface ILightingScenesDynamic : ILightingScenes - { - event EventHandler LightingScenesUpdated; - } +public interface ILightingScenesDynamic : ILightingScenes +{ + event EventHandler LightingScenesUpdated; +} - /// - /// Requirements for a device that implements master raise/lower - /// - public interface ILightingMasterRaiseLower - { - void MasterRaise(); - void MasterLower(); - void MasterRaiseLowerStop(); - } +/// +/// Requirements for a device that implements master raise/lower +/// +public interface ILightingMasterRaiseLower +{ + void MasterRaise(); + void MasterLower(); + void MasterRaiseLowerStop(); +} + +/// +/// Requiremnts for controlling a lighting load +/// +public interface ILightingLoad +{ + void SetLoadLevel(int level); + void Raise(); + void Lower(); - /// - /// Requiremnts for controlling a lighting load - /// - public interface ILightingLoad - { - void SetLoadLevel(int level); - void Raise(); - void Lower(); + IntFeedback LoadLevelFeedback { get; } + BoolFeedback LoadIsOnFeedback { get; } +} - IntFeedback LoadLevelFeedback { get; } - BoolFeedback LoadIsOnFeedback { get; } - } +public class LightingSceneChangeEventArgs : EventArgs +{ + public LightingScene CurrentLightingScene { get; private set; } - public class LightingSceneChangeEventArgs : EventArgs + public LightingSceneChangeEventArgs(LightingScene scene) { - public LightingScene CurrentLightingScene { get; private set; } - - public LightingSceneChangeEventArgs(LightingScene scene) - { - CurrentLightingScene = scene; - } + CurrentLightingScene = scene; } - } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Lighting/LightingScene.cs b/src/PepperDash.Essentials.Core/Lighting/LightingScene.cs index b0e0ddbe3..c9d93ef7f 100644 --- a/src/PepperDash.Essentials.Core/Lighting/LightingScene.cs +++ b/src/PepperDash.Essentials.Core/Lighting/LightingScene.cs @@ -3,38 +3,37 @@ using System; using Newtonsoft.Json; -namespace PepperDash.Essentials.Core.Lighting +namespace PepperDash.Essentials.Core.Lighting; + +public class LightingScene { - public class LightingScene + [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] + public string Name { get; set; } + [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] + public string ID { get; set; } + bool _IsActive; + [JsonProperty("isActive", NullValueHandling = NullValueHandling.Ignore)] + public bool IsActive { - [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] - public string Name { get; set; } - [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] - public string ID { get; set; } - bool _IsActive; - [JsonProperty("isActive", NullValueHandling = NullValueHandling.Ignore)] - public bool IsActive + get + { + return _IsActive; + } + set { - get - { - return _IsActive; - } - set - { - _IsActive = value; - IsActiveFeedback.FireUpdate(); - } + _IsActive = value; + IsActiveFeedback.FireUpdate(); } + } - [JsonProperty("sortOrder", NullValueHandling = NullValueHandling.Ignore)] - public int SortOrder { get; set; } + [JsonProperty("sortOrder", NullValueHandling = NullValueHandling.Ignore)] + public int SortOrder { get; set; } - [JsonIgnore] - public BoolFeedback IsActiveFeedback { get; set; } + [JsonIgnore] + public BoolFeedback IsActiveFeedback { get; set; } - public LightingScene() - { - IsActiveFeedback = new BoolFeedback(new Func(() => IsActive)); - } + public LightingScene() + { + IsActiveFeedback = new BoolFeedback(new Func(() => IsActive)); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Microphone Privacy/MicrophonePrivacyController.cs b/src/PepperDash.Essentials.Core/Microphone Privacy/MicrophonePrivacyController.cs index 653e2b18e..c34ac0d66 100644 --- a/src/PepperDash.Essentials.Core/Microphone Privacy/MicrophonePrivacyController.cs +++ b/src/PepperDash.Essentials.Core/Microphone Privacy/MicrophonePrivacyController.cs @@ -11,245 +11,243 @@ using Serilog.Events; -namespace PepperDash.Essentials.Core.Privacy +namespace PepperDash.Essentials.Core.Privacy; + +/// +/// Used for applications where one or more microphones with momentary contact closure outputs are used to +/// toggle the privacy state of the room. Privacy state feedback is represented +/// +public class MicrophonePrivacyController : EssentialsDevice { - /// - /// Used for applications where one or more microphones with momentary contact closure outputs are used to - /// toggle the privacy state of the room. Privacy state feedback is represented - /// - public class MicrophonePrivacyController : EssentialsDevice - { - MicrophonePrivacyControllerConfig Config; + MicrophonePrivacyControllerConfig Config; - bool initialized; + bool initialized; - public bool EnableLeds + public bool EnableLeds + { + get { - get - { - return _enableLeds; - } - set - { - _enableLeds = value; + return _enableLeds; + } + set + { + _enableLeds = value; - if (initialized) + if (initialized) + { + if (value) { - if (value) - { - CheckPrivacyMode(); - SetLedStates(); - } - else - TurnOffAllLeds(); + CheckPrivacyMode(); + SetLedStates(); } + else + TurnOffAllLeds(); } } - bool _enableLeds; + } + bool _enableLeds; - public List Inputs { get; private set; } + public List Inputs { get; private set; } - public GenericRelayDevice RedLedRelay { get; private set; } - bool _redLedRelayState; + public GenericRelayDevice RedLedRelay { get; private set; } + bool _redLedRelayState; - public GenericRelayDevice GreenLedRelay { get; private set; } - bool _greenLedRelayState; + public GenericRelayDevice GreenLedRelay { get; private set; } + bool _greenLedRelayState; - public IPrivacy PrivacyDevice { get; private set; } + public IPrivacy PrivacyDevice { get; private set; } - public MicrophonePrivacyController(string key, MicrophonePrivacyControllerConfig config) : - base(key) - { - Config = config; + public MicrophonePrivacyController(string key, MicrophonePrivacyControllerConfig config) : + base(key) + { + Config = config; - Inputs = new List(); - } + Inputs = new List(); + } - public override bool CustomActivate() + public override bool CustomActivate() + { + foreach (var i in Config.Inputs) { - foreach (var i in Config.Inputs) - { - var input = DeviceManager.GetDeviceForKey(i.DeviceKey) as IDigitalInput; + var input = DeviceManager.GetDeviceForKey(i.DeviceKey) as IDigitalInput; - if(input != null) - AddInput(input); - } + if(input != null) + AddInput(input); + } - var greenLed = DeviceManager.GetDeviceForKey(Config.GreenLedRelay.DeviceKey) as GenericRelayDevice; + var greenLed = DeviceManager.GetDeviceForKey(Config.GreenLedRelay.DeviceKey) as GenericRelayDevice; - if (greenLed != null) - GreenLedRelay = greenLed; - else - Debug.LogMessage(LogEventLevel.Information, this, "Unable to add Green LED device"); + if (greenLed != null) + GreenLedRelay = greenLed; + else + Debug.LogMessage(LogEventLevel.Information, this, "Unable to add Green LED device"); - var redLed = DeviceManager.GetDeviceForKey(Config.RedLedRelay.DeviceKey) as GenericRelayDevice; + var redLed = DeviceManager.GetDeviceForKey(Config.RedLedRelay.DeviceKey) as GenericRelayDevice; - if (redLed != null) - RedLedRelay = redLed; - else - Debug.LogMessage(LogEventLevel.Information, this, "Unable to add Red LED device"); + if (redLed != null) + RedLedRelay = redLed; + else + Debug.LogMessage(LogEventLevel.Information, this, "Unable to add Red LED device"); - AddPostActivationAction(() => { - PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange -= PrivacyModeIsOnFeedback_OutputChange; - PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange; - }); + AddPostActivationAction(() => { + PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange -= PrivacyModeIsOnFeedback_OutputChange; + PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange; + }); - initialized = true; + initialized = true; - return base.CustomActivate(); - } + return base.CustomActivate(); + } - #region Overrides of Device + #region Overrides of Device - public override void Initialize() - { - CheckPrivacyMode(); - } + public override void Initialize() + { + CheckPrivacyMode(); + } - #endregion + #endregion - public void SetPrivacyDevice(IPrivacy privacyDevice) - { - PrivacyDevice = privacyDevice; - } + public void SetPrivacyDevice(IPrivacy privacyDevice) + { + PrivacyDevice = privacyDevice; + } - void PrivacyModeIsOnFeedback_OutputChange(object sender, EventArgs e) - { + void PrivacyModeIsOnFeedback_OutputChange(object sender, EventArgs e) + { Debug.LogMessage(LogEventLevel.Debug, this, "Privacy mode change: {0}", sender as BoolFeedback); - CheckPrivacyMode(); - } + CheckPrivacyMode(); + } - void CheckPrivacyMode() + void CheckPrivacyMode() + { + if (PrivacyDevice != null) { - if (PrivacyDevice != null) - { - var privacyState = PrivacyDevice.PrivacyModeIsOnFeedback.BoolValue; + var privacyState = PrivacyDevice.PrivacyModeIsOnFeedback.BoolValue; - if (privacyState) - TurnOnRedLeds(); - else - TurnOnGreenLeds(); - } + if (privacyState) + TurnOnRedLeds(); + else + TurnOnGreenLeds(); } + } - void AddInput(IDigitalInput input) - { - Inputs.Add(input); - - input.InputStateFeedback.OutputChange += InputStateFeedback_OutputChange; - } + void AddInput(IDigitalInput input) + { + Inputs.Add(input); - void RemoveInput(IDigitalInput input) - { - var tempInput = Inputs.FirstOrDefault(i => i.Equals(input)); + input.InputStateFeedback.OutputChange += InputStateFeedback_OutputChange; + } - if (tempInput != null) - tempInput.InputStateFeedback.OutputChange -= InputStateFeedback_OutputChange; + void RemoveInput(IDigitalInput input) + { + var tempInput = Inputs.FirstOrDefault(i => i.Equals(input)); - Inputs.Remove(input); - } + if (tempInput != null) + tempInput.InputStateFeedback.OutputChange -= InputStateFeedback_OutputChange; - void SetRedLedRelay(GenericRelayDevice relay) - { - RedLedRelay = relay; - } + Inputs.Remove(input); + } - void SetGreenLedRelay(GenericRelayDevice relay) - { - GreenLedRelay = relay; - } + void SetRedLedRelay(GenericRelayDevice relay) + { + RedLedRelay = relay; + } - /// - /// Check the state of the input change and handle accordingly - /// - /// - /// - void InputStateFeedback_OutputChange(object sender, EventArgs e) - { - if ((sender as BoolFeedback).BoolValue == true) - TogglePrivacyMute(); - } + void SetGreenLedRelay(GenericRelayDevice relay) + { + GreenLedRelay = relay; + } - /// - /// Toggles the state of the privacy mute - /// - public void TogglePrivacyMute() - { - PrivacyDevice.PrivacyModeToggle(); - } + /// + /// Check the state of the input change and handle accordingly + /// + /// + /// + void InputStateFeedback_OutputChange(object sender, EventArgs e) + { + if ((sender as BoolFeedback).BoolValue == true) + TogglePrivacyMute(); + } - void TurnOnRedLeds() - { - _greenLedRelayState = false; - _redLedRelayState = true; - SetLedStates(); - } + /// + /// Toggles the state of the privacy mute + /// + public void TogglePrivacyMute() + { + PrivacyDevice.PrivacyModeToggle(); + } - void TurnOnGreenLeds() - { - _redLedRelayState = false; - _greenLedRelayState = true; - SetLedStates(); - } + void TurnOnRedLeds() + { + _greenLedRelayState = false; + _redLedRelayState = true; + SetLedStates(); + } - /// - /// If enabled, sets the actual state of the relays - /// - void SetLedStates() - { - if (_enableLeds) - { - SetRelayStates(); - } - else - TurnOffAllLeds(); - } + void TurnOnGreenLeds() + { + _redLedRelayState = false; + _greenLedRelayState = true; + SetLedStates(); + } - /// - /// Turns off all LEDs - /// - void TurnOffAllLeds() + /// + /// If enabled, sets the actual state of the relays + /// + void SetLedStates() + { + if (_enableLeds) { - _redLedRelayState = false; - _greenLedRelayState = false; - SetRelayStates(); } + else + TurnOffAllLeds(); + } - void SetRelayStates() - { - if (RedLedRelay != null) - { - if (_redLedRelayState) - RedLedRelay.CloseRelay(); - else - RedLedRelay.OpenRelay(); - } + /// + /// Turns off all LEDs + /// + void TurnOffAllLeds() + { + _redLedRelayState = false; + _greenLedRelayState = false; - if(GreenLedRelay != null) - { - if (_greenLedRelayState) - GreenLedRelay.CloseRelay(); - else - GreenLedRelay.OpenRelay(); - } - } + SetRelayStates(); } - public class MicrophonePrivacyControllerFactory : EssentialsDeviceFactory + void SetRelayStates() { - public MicrophonePrivacyControllerFactory() + if (RedLedRelay != null) { - TypeNames = new List() { "microphoneprivacycontroller" }; + if (_redLedRelayState) + RedLedRelay.CloseRelay(); + else + RedLedRelay.OpenRelay(); } - public override EssentialsDevice BuildDevice(DeviceConfig dc) + if(GreenLedRelay != null) { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new MIcrophonePrivacyController Device"); - var props = Newtonsoft.Json.JsonConvert.DeserializeObject(dc.Properties.ToString()); - - return new Core.Privacy.MicrophonePrivacyController(dc.Key, props); + if (_greenLedRelayState) + GreenLedRelay.CloseRelay(); + else + GreenLedRelay.OpenRelay(); } } +} +public class MicrophonePrivacyControllerFactory : EssentialsDeviceFactory +{ + public MicrophonePrivacyControllerFactory() + { + TypeNames = new List() { "microphoneprivacycontroller" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new MIcrophonePrivacyController Device"); + var props = Newtonsoft.Json.JsonConvert.DeserializeObject(dc.Properties.ToString()); + + return new Core.Privacy.MicrophonePrivacyController(dc.Key, props); + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Microphone Privacy/MicrophonePrivacyControllerConfig.cs b/src/PepperDash.Essentials.Core/Microphone Privacy/MicrophonePrivacyControllerConfig.cs index 1c1720907..25ade531f 100644 --- a/src/PepperDash.Essentials.Core/Microphone Privacy/MicrophonePrivacyControllerConfig.cs +++ b/src/PepperDash.Essentials.Core/Microphone Privacy/MicrophonePrivacyControllerConfig.cs @@ -6,17 +6,16 @@ using PepperDash.Essentials.Core.CrestronIO; -namespace PepperDash.Essentials.Core.Privacy +namespace PepperDash.Essentials.Core.Privacy; + +public class MicrophonePrivacyControllerConfig { - public class MicrophonePrivacyControllerConfig - { - public List Inputs { get; set; } - public KeyedDevice GreenLedRelay { get; set; } - public KeyedDevice RedLedRelay { get; set; } - } + public List Inputs { get; set; } + public KeyedDevice GreenLedRelay { get; set; } + public KeyedDevice RedLedRelay { get; set; } +} - public class KeyedDevice - { - public string DeviceKey { get; set; } - } +public class KeyedDevice +{ + public string DeviceKey { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Monitoring/CrestronGenericBaseCommunicationMonitor.cs b/src/PepperDash.Essentials.Core/Monitoring/CrestronGenericBaseCommunicationMonitor.cs index bd57b70af..22d0f0b47 100644 --- a/src/PepperDash.Essentials.Core/Monitoring/CrestronGenericBaseCommunicationMonitor.cs +++ b/src/PepperDash.Essentials.Core/Monitoring/CrestronGenericBaseCommunicationMonitor.cs @@ -11,8 +11,8 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// /// @@ -53,5 +53,4 @@ void GetStatus() else StartErrorTimers(); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Monitoring/GenericCommunicationMonitor.cs b/src/PepperDash.Essentials.Core/Monitoring/GenericCommunicationMonitor.cs index a3a427f10..46691909e 100644 --- a/src/PepperDash.Essentials.Core/Monitoring/GenericCommunicationMonitor.cs +++ b/src/PepperDash.Essentials.Core/Monitoring/GenericCommunicationMonitor.cs @@ -3,48 +3,48 @@ using System.Threading; using PepperDash.Core.Logging; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// Used for monitoring comms that are IBasicCommunication. Will send a poll string and provide an event when /// statuses change. - /// Default monitoring uses TextReceived event on Client. +/// Default monitoring uses TextReceived event on Client. /// public class GenericCommunicationMonitor : StatusMonitorBase { public IBasicCommunication Client { get; private set; } - /// - /// Will monitor Client.BytesReceived if set to true. Otherwise the default is to monitor Client.TextReceived - /// - public bool MonitorBytesReceived { get; private set; } + /// + /// Will monitor Client.BytesReceived if set to true. Otherwise the default is to monitor Client.TextReceived + /// + public bool MonitorBytesReceived { get; private set; } - /// - /// Return true if the Client is ISocketStatus - /// - public bool IsSocket => Client is ISocketStatus; + /// + /// Return true if the Client is ISocketStatus + /// + public bool IsSocket => Client is ISocketStatus; - private readonly string PollString; - private readonly Action PollAction; - private readonly long PollTime; + private readonly string PollString; + private readonly Action PollAction; + private readonly long PollTime; private Timer PollTimer; - private SemaphoreSlim semaphore = new SemaphoreSlim(1, 1); - - /// - /// GenericCommunicationMonitor constructor - /// - /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected - /// - /// Parent device - /// Communications Client - /// Time in MS for polling - /// Warning time in MS. If a message is not received before this elapsed time the status will be Warning - /// Error time in MS. If a message is not received before this elapsed time the status will be Error - /// string to send for polling - /// Poll time must be less than warning and error time - public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime, + private SemaphoreSlim semaphore = new SemaphoreSlim(1, 1); + + /// + /// GenericCommunicationMonitor constructor + /// + /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected + /// + /// Parent device + /// Communications Client + /// Time in MS for polling + /// Warning time in MS. If a message is not received before this elapsed time the status will be Warning + /// Error time in MS. If a message is not received before this elapsed time the status will be Error + /// string to send for polling + /// Poll time must be less than warning and error time + public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime, long warningTime, long errorTime, string pollString) : base(parent, warningTime, errorTime) { @@ -55,212 +55,212 @@ public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, lo PollTime = pollTime; PollString = pollString; - if (IsSocket) - { - (Client as ISocketStatus).ConnectionChange += Socket_ConnectionChange; - } - } - - /// - /// GenericCommunicationMonitor constructor with a bool to specify whether to monitor BytesReceived - /// - /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected - /// - /// Parent device - /// Communications Client - /// Time in MS for polling - /// Warning time in MS. If a message is not received before this elapsed time the status will be Warning - /// Error time in MS. If a message is not received before this elapsed time the status will be Error - /// string to send for polling - /// Use bytesReceived event instead of textReceived when true - public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime, - long warningTime, long errorTime, string pollString, bool monitorBytesReceived) : - this(parent, client, pollTime, warningTime, errorTime, pollString) + if (IsSocket) { - MonitorBytesReceived = monitorBytesReceived; + (Client as ISocketStatus).ConnectionChange += Socket_ConnectionChange; } + } - /// - /// GenericCommunicationMonitor constructor with a poll action instead of a poll string - /// - /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected - /// - /// Parent device - /// Communications Client - /// Time in MS for polling - /// Warning time in MS. If a message is not received before this elapsed time the status will be Warning - /// Error time in MS. If a message is not received before this elapsed time the status will be Error - /// Action to execute for polling - /// Poll time must be less than warning and error time - public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime, - long warningTime, long errorTime, Action pollAction) : - base(parent, warningTime, errorTime) - { - if (pollTime > warningTime || pollTime > errorTime) - throw new ArgumentException("pollTime must be less than warning or errorTime"); - //if (pollTime < 5000) - // throw new ArgumentException("pollTime cannot be less than 5000 ms"); - - Client = client; - PollTime = pollTime; - PollAction = pollAction; - - if (IsSocket) - { - (Client as ISocketStatus).ConnectionChange += Socket_ConnectionChange; - } - - } + /// + /// GenericCommunicationMonitor constructor with a bool to specify whether to monitor BytesReceived + /// + /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected + /// + /// Parent device + /// Communications Client + /// Time in MS for polling + /// Warning time in MS. If a message is not received before this elapsed time the status will be Warning + /// Error time in MS. If a message is not received before this elapsed time the status will be Error + /// string to send for polling + /// Use bytesReceived event instead of textReceived when true + public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime, + long warningTime, long errorTime, string pollString, bool monitorBytesReceived) : + this(parent, client, pollTime, warningTime, errorTime, pollString) + { + MonitorBytesReceived = monitorBytesReceived; + } - /// - /// GenericCommunicationMonitor constructor with a poll action instead of a poll string and a bool to specify whether to monitor BytesReceived - /// - /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected - /// - /// Parent device - /// Communications Client - /// Time in MS for polling - /// Warning time in MS. If a message is not received before this elapsed time the status will be Warning - /// Error time in MS. If a message is not received before this elapsed time the status will be Error - /// Action to execute for polling - /// Use bytesReceived event instead of textReceived when true - public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime, - long warningTime, long errorTime, Action pollAction, bool monitorBytesReceived) : - this(parent, client, pollTime, warningTime, errorTime, pollAction) + /// + /// GenericCommunicationMonitor constructor with a poll action instead of a poll string + /// + /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected + /// + /// Parent device + /// Communications Client + /// Time in MS for polling + /// Warning time in MS. If a message is not received before this elapsed time the status will be Warning + /// Error time in MS. If a message is not received before this elapsed time the status will be Error + /// Action to execute for polling + /// Poll time must be less than warning and error time + public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime, + long warningTime, long errorTime, Action pollAction) : + base(parent, warningTime, errorTime) + { + if (pollTime > warningTime || pollTime > errorTime) + throw new ArgumentException("pollTime must be less than warning or errorTime"); + //if (pollTime < 5000) + // throw new ArgumentException("pollTime cannot be less than 5000 ms"); + + Client = client; + PollTime = pollTime; + PollAction = pollAction; + + if (IsSocket) { - MonitorBytesReceived = monitorBytesReceived; + (Client as ISocketStatus).ConnectionChange += Socket_ConnectionChange; } + } + + /// + /// GenericCommunicationMonitor constructor with a poll action instead of a poll string and a bool to specify whether to monitor BytesReceived + /// + /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected + /// + /// Parent device + /// Communications Client + /// Time in MS for polling + /// Warning time in MS. If a message is not received before this elapsed time the status will be Warning + /// Error time in MS. If a message is not received before this elapsed time the status will be Error + /// Action to execute for polling + /// Use bytesReceived event instead of textReceived when true + public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime, + long warningTime, long errorTime, Action pollAction, bool monitorBytesReceived) : + this(parent, client, pollTime, warningTime, errorTime, pollAction) + { + MonitorBytesReceived = monitorBytesReceived; + } + - /// - /// GenericCommunicationMonitor constructor with a config object - /// - /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected - /// - /// Parent Device - /// Communications Client - /// Communication Monitor Config object - public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, + /// + /// GenericCommunicationMonitor constructor with a config object + /// + /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected + /// + /// Parent Device + /// Communications Client + /// Communication Monitor Config object + public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, CommunicationMonitorConfig props) : this(parent, client, props.PollInterval, props.TimeToWarning, props.TimeToError, props.PollString) { - if (IsSocket) - { - (Client as ISocketStatus).ConnectionChange += Socket_ConnectionChange; - } - } - - /// - /// GenericCommunicationMonitor constructor with a config object and a bool to specify whether to monitor BytesReceived - /// - /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected - /// - /// Parent Device - /// Communications Client - /// Communication Monitor Config object - /// Use bytesReceived event instead of textReceived when true - public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, CommunicationMonitorConfig props, bool monitorBytesReceived) : - this(parent, client, props.PollInterval, props.TimeToWarning, props.TimeToError, props.PollString) + if (IsSocket) { - MonitorBytesReceived = monitorBytesReceived; + (Client as ISocketStatus).ConnectionChange += Socket_ConnectionChange; } + } + + /// + /// GenericCommunicationMonitor constructor with a config object and a bool to specify whether to monitor BytesReceived + /// + /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected + /// + /// Parent Device + /// Communications Client + /// Communication Monitor Config object + /// Use bytesReceived event instead of textReceived when true + public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, CommunicationMonitorConfig props, bool monitorBytesReceived) : + this(parent, client, props.PollInterval, props.TimeToWarning, props.TimeToError, props.PollString) + { + MonitorBytesReceived = monitorBytesReceived; + } - /// - /// Start the poll cycle - /// + /// + /// Start the poll cycle + /// public override void Start() { - if (MonitorBytesReceived) - { + if (MonitorBytesReceived) + { Client.BytesReceived -= Client_BytesReceived; - Client.BytesReceived += Client_BytesReceived; - } - else - { - Client.TextReceived -= Client_TextReceived; - Client.TextReceived += Client_TextReceived; - } + Client.BytesReceived += Client_BytesReceived; + } + else + { + Client.TextReceived -= Client_TextReceived; + Client.TextReceived += Client_TextReceived; + } - BeginPolling(); + BeginPolling(); } - private void Socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e) + private void Socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e) + { + if (!e.Client.IsConnected) { - if (!e.Client.IsConnected) - { - // Immediately stop polling and notify that device is offline - Stop(); - Status = MonitorStatus.InError; - ResetErrorTimers(); - } - else - { - // Start polling and set status to unknow and let poll result update the status to IsOk when a response is received - Status = MonitorStatus.StatusUnknown; - Start(); - } + // Immediately stop polling and notify that device is offline + Stop(); + Status = MonitorStatus.InError; + ResetErrorTimers(); + } + else + { + // Start polling and set status to unknow and let poll result update the status to IsOk when a response is received + Status = MonitorStatus.StatusUnknown; + Start(); } + } - private void BeginPolling() + private void BeginPolling() + { + try { - try + semaphore.Wait(); { - semaphore.Wait(); + if (PollTimer != null) { - if (PollTimer != null) - { - return; - } - - PollTimer = new Timer(o => Poll(), null, 0, PollTime); + return; } + + PollTimer = new Timer(o => Poll(), null, 0, PollTime); } - finally - { - semaphore.Release(); - } } + finally + { + semaphore.Release(); + } + } - /// - /// Stop the poll cycle - /// + /// + /// Stop the poll cycle + /// public override void Stop() { - if(MonitorBytesReceived) - { + if(MonitorBytesReceived) + { Client.BytesReceived -= Client_BytesReceived; - } - else - { - Client.TextReceived -= Client_TextReceived; - } - - StopErrorTimers(); + } + else + { + Client.TextReceived -= Client_TextReceived; + } - if (PollTimer == null) - { - return; - } - - PollTimer.Dispose(); - PollTimer = null; - } + StopErrorTimers(); - private void Client_TextReceived(object sender, GenericCommMethodReceiveTextArgs e) + if (PollTimer == null) { - DataReceived(); + return; } + + PollTimer.Dispose(); + PollTimer = null; + } + + private void Client_TextReceived(object sender, GenericCommMethodReceiveTextArgs e) + { + DataReceived(); + } private void Client_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e) { - DataReceived(); - } + DataReceived(); + } - private void DataReceived() - { - Status = MonitorStatus.IsOk; - ResetErrorTimers(); - } + private void DataReceived() + { + Status = MonitorStatus.IsOk; + ResetErrorTimers(); + } private void Poll() { @@ -268,10 +268,10 @@ private void Poll() if (Client.IsConnected) { //Debug.LogMessage(LogEventLevel.Verbose, this, "Polling"); - if(PollAction != null) - PollAction.Invoke(); - else - Client.SendText(PollString); + if(PollAction != null) + PollAction.Invoke(); + else + Client.SendText(PollString); } else { @@ -280,9 +280,9 @@ private void Poll() } } - /// - /// Communication Monitor Configuration from Essentials Configuration - /// +/// +/// Communication Monitor Configuration from Essentials Configuration +/// public class CommunicationMonitorConfig { public int PollInterval { get; set; } @@ -290,9 +290,9 @@ public class CommunicationMonitorConfig public int TimeToError { get; set; } public string PollString { get; set; } - /// - /// Default constructor. Sets pollInterval to 30s, TimeToWarning to 120s, and TimeToError to 300s - /// + /// + /// Default constructor. Sets pollInterval to 30s, TimeToWarning to 120s, and TimeToError to 300s + /// public CommunicationMonitorConfig() { PollInterval = 30000; @@ -300,5 +300,4 @@ public CommunicationMonitorConfig() TimeToError = 300000; PollString = ""; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Monitoring/Interfaces.cs b/src/PepperDash.Essentials.Core/Monitoring/Interfaces.cs index 6e4a847e5..b9cc8c6b7 100644 --- a/src/PepperDash.Essentials.Core/Monitoring/Interfaces.cs +++ b/src/PepperDash.Essentials.Core/Monitoring/Interfaces.cs @@ -4,8 +4,8 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public interface IStatusMonitor { IKeyed Parent { get; } @@ -31,10 +31,10 @@ public interface ICommunicationMonitor /// public enum MonitorStatus { - StatusUnknown = 0, + StatusUnknown = 0, IsOk = 1, - InWarning = 2, - InError = 3 + InWarning = 2, + InError = 3 } public class MonitorStatusChangeEventArgs : EventArgs @@ -53,5 +53,4 @@ public MonitorStatusChangeEventArgs(MonitorStatus status, string message) Status = status; Message = message; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Monitoring/StatusMonitorBase.cs b/src/PepperDash.Essentials.Core/Monitoring/StatusMonitorBase.cs index 4abb930f2..6c3923170 100644 --- a/src/PepperDash.Essentials.Core/Monitoring/StatusMonitorBase.cs +++ b/src/PepperDash.Essentials.Core/Monitoring/StatusMonitorBase.cs @@ -11,18 +11,18 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public abstract class StatusMonitorBase : IStatusMonitor, IKeyName { public event EventHandler StatusChange; - /// - /// Format returned: "parentdevkey-comMonitor" - /// - public string Key { get { return Parent.Key + "-comMonitor"; } } + /// + /// Format returned: "parentdevkey-comMonitor" + /// + public string Key { get { return Parent.Key + "-comMonitor"; } } - public string Name { get { return "Comm. monitor"; } } + public string Name { get { return "Comm. monitor"; } } public IKeyed Parent { get; private set; } @@ -118,13 +118,12 @@ protected void StopErrorTimers() ErrorTimer = null; } - protected void ResetErrorTimers() - { - if(WarningTimer != null) - WarningTimer.Reset(WarningTime, WarningTime); - if(ErrorTimer != null) - ErrorTimer.Reset(ErrorTime, ErrorTime); + protected void ResetErrorTimers() + { + if(WarningTimer != null) + WarningTimer.Reset(WarningTime, WarningTime); + if(ErrorTimer != null) + ErrorTimer.Reset(ErrorTime, ErrorTime); - } - } -} \ No newline at end of file + } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Monitoring/StatusMonitorCollection.cs b/src/PepperDash.Essentials.Core/Monitoring/StatusMonitorCollection.cs index 7f985fe01..9f3a5b3c0 100644 --- a/src/PepperDash.Essentials.Core/Monitoring/StatusMonitorCollection.cs +++ b/src/PepperDash.Essentials.Core/Monitoring/StatusMonitorCollection.cs @@ -11,8 +11,8 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// /// @@ -70,28 +70,28 @@ void ProcessStatuses() initialStatus = MonitorStatus.StatusUnknown; // Build the error message string - if (InError.Count() > 0 || InWarning.Count() > 0) + if (InError.Count() > 0 || InWarning.Count() > 0) + { + StringBuilder sb = new StringBuilder(prefix); + if (InError.Count() > 0) { - StringBuilder sb = new StringBuilder(prefix); - if (InError.Count() > 0) - { - // Do string splits and joins - sb.Append(string.Format("{0} Errors:", InError.Count())); - foreach (var mon in InError) - sb.Append(string.Format("{0}, ", mon.Parent.Key)); - } - if (InWarning.Count() > 0) - { - sb.Append(string.Format("{0} Warnings:", InWarning.Count())); - foreach (var mon in InWarning) - sb.Append(string.Format("{0}, ", mon.Parent.Key)); - } - Message = sb.ToString(); + // Do string splits and joins + sb.Append(string.Format("{0} Errors:", InError.Count())); + foreach (var mon in InError) + sb.Append(string.Format("{0}, ", mon.Parent.Key)); } - else + if (InWarning.Count() > 0) { - Message = "Room Ok."; + sb.Append(string.Format("{0} Warnings:", InWarning.Count())); + foreach (var mon in InWarning) + sb.Append(string.Format("{0}, ", mon.Parent.Key)); } + Message = sb.ToString(); + } + else + { + Message = "Room Ok."; + } // Want to fire even if status doesn't change because the message may. Status = initialStatus; @@ -124,5 +124,4 @@ protected void OnStatusChange(MonitorStatus status, string message) if (handler != null) handler(this, new MonitorStatusChangeEventArgs(status, message)); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs b/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs index 06a4fbd97..99a58ec66 100644 --- a/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs +++ b/src/PepperDash.Essentials.Core/Monitoring/SystemMonitorController.cs @@ -12,39 +12,39 @@ using PepperDash.Essentials.Core.Bridges; using Serilog.Events; -namespace PepperDash.Essentials.Core.Monitoring +namespace PepperDash.Essentials.Core.Monitoring; + +/// +/// Wrapper for the static SystemMonitor class to extend functionality and provide external access +/// to SystemMonitor via APIs +/// +public class SystemMonitorController : EssentialsBridgeableDevice { - /// - /// Wrapper for the static SystemMonitor class to extend functionality and provide external access - /// to SystemMonitor via APIs - /// - public class SystemMonitorController : EssentialsBridgeableDevice - { - private const long UptimePollTime = 300000; - private CTimer _uptimePollTimer; + private const long UptimePollTime = 300000; + private CTimer _uptimePollTimer; - private string _uptime; - private string _lastStart; + private string _uptime; + private string _lastStart; - public event EventHandler SystemMonitorPropertiesChanged; + public event EventHandler SystemMonitorPropertiesChanged; - public Dictionary ProgramStatusFeedbackCollection; - public Dictionary EthernetStatusFeedbackCollection; + public Dictionary ProgramStatusFeedbackCollection; + public Dictionary EthernetStatusFeedbackCollection; - public IntFeedback TimeZoneFeedback { get; protected set; } - public StringFeedback TimeZoneTextFeedback { get; protected set; } + public IntFeedback TimeZoneFeedback { get; protected set; } + public StringFeedback TimeZoneTextFeedback { get; protected set; } - public StringFeedback IoControllerVersionFeedback { get; protected set; } - public StringFeedback SnmpVersionFeedback { get; protected set; } - public StringFeedback BaCnetAppVersionFeedback { get; protected set; } - public StringFeedback ControllerVersionFeedback { get; protected set; } + public StringFeedback IoControllerVersionFeedback { get; protected set; } + public StringFeedback SnmpVersionFeedback { get; protected set; } + public StringFeedback BaCnetAppVersionFeedback { get; protected set; } + public StringFeedback ControllerVersionFeedback { get; protected set; } - //new feedbacks. Issue #50 - public StringFeedback SerialNumberFeedback { get; protected set; } - public StringFeedback ModelFeedback { get; set; } + //new feedbacks. Issue #50 + public StringFeedback SerialNumberFeedback { get; protected set; } + public StringFeedback ModelFeedback { get; set; } - public StringFeedback UptimeFeedback { get; set; } - public StringFeedback LastStartFeedback { get; set; } + public StringFeedback UptimeFeedback { get; set; } + public StringFeedback LastStartFeedback { get; set; } public BoolFeedback IsApplianceFeedback { get; protected set; } private bool _isApplianceFb @@ -60,104 +60,104 @@ private bool _isServerFb public SystemMonitorController(string key) - : base(key) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Adding SystemMonitorController."); + : base(key) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Adding SystemMonitorController."); - SystemMonitor.ProgramInitialization.ProgramInitializationUnderUserControl = true; + SystemMonitor.ProgramInitialization.ProgramInitializationUnderUserControl = true; - TimeZoneFeedback = new IntFeedback(() => SystemMonitor.TimeZoneInformation.TimeZoneNumber); - TimeZoneTextFeedback = new StringFeedback(() => SystemMonitor.TimeZoneInformation.TimeZoneName); + TimeZoneFeedback = new IntFeedback(() => SystemMonitor.TimeZoneInformation.TimeZoneNumber); + TimeZoneTextFeedback = new StringFeedback(() => SystemMonitor.TimeZoneInformation.TimeZoneName); - IoControllerVersionFeedback = new StringFeedback(() => SystemMonitor.VersionInformation.IOPVersion); - SnmpVersionFeedback = new StringFeedback(() => SystemMonitor.VersionInformation.SNMPVersion); - BaCnetAppVersionFeedback = new StringFeedback(() => SystemMonitor.VersionInformation.BACNetVersion); - ControllerVersionFeedback = new StringFeedback(() => SystemMonitor.VersionInformation.ControlSystemVersion); + IoControllerVersionFeedback = new StringFeedback(() => SystemMonitor.VersionInformation.IOPVersion); + SnmpVersionFeedback = new StringFeedback(() => SystemMonitor.VersionInformation.SNMPVersion); + BaCnetAppVersionFeedback = new StringFeedback(() => SystemMonitor.VersionInformation.BACNetVersion); + ControllerVersionFeedback = new StringFeedback(() => SystemMonitor.VersionInformation.ControlSystemVersion); - SerialNumberFeedback = new StringFeedback(() => CrestronEnvironment.SystemInfo.SerialNumber); - ModelFeedback = new StringFeedback(() => InitialParametersClass.ControllerPromptName); - UptimeFeedback = new StringFeedback(() => _uptime); - LastStartFeedback = new StringFeedback(()=> _lastStart); + SerialNumberFeedback = new StringFeedback(() => CrestronEnvironment.SystemInfo.SerialNumber); + ModelFeedback = new StringFeedback(() => InitialParametersClass.ControllerPromptName); + UptimeFeedback = new StringFeedback(() => _uptime); + LastStartFeedback = new StringFeedback(()=> _lastStart); IsApplianceFeedback = new BoolFeedback(() => _isApplianceFb); IsServerFeedback = new BoolFeedback(() => _isServerFb); - ProgramStatusFeedbackCollection = new Dictionary(); + ProgramStatusFeedbackCollection = new Dictionary(); - foreach (var prog in SystemMonitor.ProgramCollection) - { - var program = new ProgramStatusFeedbacks(prog); - ProgramStatusFeedbackCollection.Add(prog.Number, program); - } + foreach (var prog in SystemMonitor.ProgramCollection) + { + var program = new ProgramStatusFeedbacks(prog); + ProgramStatusFeedbackCollection.Add(prog.Number, program); + } - CreateEthernetStatusFeedbacks(); - UpdateEthernetStatusFeeedbacks(); + CreateEthernetStatusFeedbacks(); + UpdateEthernetStatusFeeedbacks(); - _uptimePollTimer = new CTimer(PollUptime,null,0, UptimePollTime); + _uptimePollTimer = new CTimer(PollUptime,null,0, UptimePollTime); - SystemMonitor.ProgramChange += SystemMonitor_ProgramChange; - SystemMonitor.TimeZoneInformation.TimeZoneChange += TimeZoneInformation_TimeZoneChange; - CrestronEnvironment.EthernetEventHandler += CrestronEnvironmentOnEthernetEventHandler; - CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironmentOnProgramStatusEventHandler; - } + SystemMonitor.ProgramChange += SystemMonitor_ProgramChange; + SystemMonitor.TimeZoneInformation.TimeZoneChange += TimeZoneInformation_TimeZoneChange; + CrestronEnvironment.EthernetEventHandler += CrestronEnvironmentOnEthernetEventHandler; + CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironmentOnProgramStatusEventHandler; + } - private void CrestronEnvironmentOnProgramStatusEventHandler(eProgramStatusEventType programEventType) - { - if (programEventType != eProgramStatusEventType.Stopping) return; + private void CrestronEnvironmentOnProgramStatusEventHandler(eProgramStatusEventType programEventType) + { + if (programEventType != eProgramStatusEventType.Stopping) return; - _uptimePollTimer.Stop(); - _uptimePollTimer.Dispose(); - _uptimePollTimer = null; - } + _uptimePollTimer.Stop(); + _uptimePollTimer.Dispose(); + _uptimePollTimer = null; + } - public void PollUptime(object obj) - { - var consoleResponse = string.Empty; + public void PollUptime(object obj) + { + var consoleResponse = string.Empty; - CrestronConsole.SendControlSystemCommand("uptime", ref consoleResponse); + CrestronConsole.SendControlSystemCommand("uptime", ref consoleResponse); - ParseUptime(consoleResponse); + ParseUptime(consoleResponse); - UptimeFeedback.FireUpdate(); - LastStartFeedback.FireUpdate(); - } + UptimeFeedback.FireUpdate(); + LastStartFeedback.FireUpdate(); + } - private void ParseUptime(string response) - { - var splitString = response.Trim().Split('\r', '\n'); + private void ParseUptime(string response) + { + var splitString = response.Trim().Split('\r', '\n'); - var lastStartRaw = splitString.FirstOrDefault(o => o.Contains("started")); - var uptimeRaw = splitString.FirstOrDefault(o => o.Contains("running")); + var lastStartRaw = splitString.FirstOrDefault(o => o.Contains("started")); + var uptimeRaw = splitString.FirstOrDefault(o => o.Contains("running")); - if (!String.IsNullOrEmpty(lastStartRaw)) - { - var lastStartIndex = lastStartRaw.IndexOf(':'); - _lastStart = lastStartRaw.Substring(lastStartIndex + 1).Trim(); - } + if (!String.IsNullOrEmpty(lastStartRaw)) + { + var lastStartIndex = lastStartRaw.IndexOf(':'); + _lastStart = lastStartRaw.Substring(lastStartIndex + 1).Trim(); + } - if (String.IsNullOrEmpty(uptimeRaw)) return; - var forIndex = uptimeRaw.IndexOf("for", StringComparison.Ordinal); + if (String.IsNullOrEmpty(uptimeRaw)) return; + var forIndex = uptimeRaw.IndexOf("for", StringComparison.Ordinal); - //4 => "for " to get what's on the right - _uptime = uptimeRaw.Substring(forIndex + 4); - } + //4 => "for " to get what's on the right + _uptime = uptimeRaw.Substring(forIndex + 4); + } public static void ProcessorReboot() { if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Server) return; - Debug.LogMessage(LogEventLevel.Information, "Rebooting..."); + Debug.LogMessage(LogEventLevel.Information, "Rebooting..."); - var response = string.Empty; + var response = string.Empty; CrestronConsole.SendControlSystemCommand("reboot", ref response); } public static void ProgramReset(uint index) { if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Server) return; - Debug.LogMessage(LogEventLevel.Information, "Resetting Program {0}...", index); + Debug.LogMessage(LogEventLevel.Information, "Resetting Program {0}...", index); - if (index <= 0 || index > 10) return; + if (index <= 0 || index > 10) return; var cmd = string.Format("progreset -p:{0}", index); @@ -165,493 +165,493 @@ public static void ProgramReset(uint index) CrestronConsole.SendControlSystemCommand(cmd, ref response); } - private void CrestronEnvironmentOnEthernetEventHandler(EthernetEventArgs ethernetEventArgs) - { - if (ethernetEventArgs.EthernetEventType != eEthernetEventType.LinkUp) return; - - foreach (var fb in EthernetStatusFeedbackCollection) - { - fb.Value.UpdateEthernetStatus(); - } - } + private void CrestronEnvironmentOnEthernetEventHandler(EthernetEventArgs ethernetEventArgs) + { + if (ethernetEventArgs.EthernetEventType != eEthernetEventType.LinkUp) return; - private void CreateEthernetStatusFeedbacks() + foreach (var fb in EthernetStatusFeedbackCollection) { - EthernetStatusFeedbackCollection = new Dictionary(); + fb.Value.UpdateEthernetStatus(); + } + } - Debug.LogMessage(LogEventLevel.Verbose, "Creating {0} EthernetStatusFeedbacks", InitialParametersClass.NumberOfEthernetInterfaces); + private void CreateEthernetStatusFeedbacks() + { + EthernetStatusFeedbackCollection = new Dictionary(); - for (short i = 0; i < InitialParametersClass.NumberOfEthernetInterfaces; i++) - { - Debug.LogMessage(LogEventLevel.Verbose, "Creating EthernetStatusFeedback for Interface {0}", i); - var ethernetInterface = new EthernetStatusFeedbacks(i); - EthernetStatusFeedbackCollection.Add(i, ethernetInterface); - } - } + Debug.LogMessage(LogEventLevel.Verbose, "Creating {0} EthernetStatusFeedbacks", InitialParametersClass.NumberOfEthernetInterfaces); - private void UpdateEthernetStatusFeeedbacks() + for (short i = 0; i < InitialParametersClass.NumberOfEthernetInterfaces; i++) { - foreach (var iface in EthernetStatusFeedbackCollection) - { - iface.Value.CurrentIpAddressFeedback.FireUpdate(); - iface.Value.CurrentSubnetMaskFeedback.FireUpdate(); - iface.Value.CurrentDefaultGatewayFeedback.FireUpdate(); - iface.Value.StaticIpAddressFeedback.FireUpdate(); - iface.Value.StaticSubnetMaskFeedback.FireUpdate(); - iface.Value.StaticDefaultGatewayFeedback.FireUpdate(); - iface.Value.HostNameFeedback.FireUpdate(); - iface.Value.DnsServerFeedback.FireUpdate(); - iface.Value.DomainFeedback.FireUpdate(); - iface.Value.DhcpStatusFeedback.FireUpdate(); - iface.Value.MacAddressFeedback.FireUpdate(); - } + Debug.LogMessage(LogEventLevel.Verbose, "Creating EthernetStatusFeedback for Interface {0}", i); + var ethernetInterface = new EthernetStatusFeedbacks(i); + EthernetStatusFeedbackCollection.Add(i, ethernetInterface); } + } - /// - /// Gets data in separate thread - /// - private void RefreshSystemMonitorData() + private void UpdateEthernetStatusFeeedbacks() + { + foreach (var iface in EthernetStatusFeedbackCollection) { - // this takes a while, launch a new thread - CrestronInvoke.BeginInvoke(UpdateFeedback); + iface.Value.CurrentIpAddressFeedback.FireUpdate(); + iface.Value.CurrentSubnetMaskFeedback.FireUpdate(); + iface.Value.CurrentDefaultGatewayFeedback.FireUpdate(); + iface.Value.StaticIpAddressFeedback.FireUpdate(); + iface.Value.StaticSubnetMaskFeedback.FireUpdate(); + iface.Value.StaticDefaultGatewayFeedback.FireUpdate(); + iface.Value.HostNameFeedback.FireUpdate(); + iface.Value.DnsServerFeedback.FireUpdate(); + iface.Value.DomainFeedback.FireUpdate(); + iface.Value.DhcpStatusFeedback.FireUpdate(); + iface.Value.MacAddressFeedback.FireUpdate(); } + } - private void UpdateFeedback(object o) - { - TimeZoneFeedback.FireUpdate(); - TimeZoneTextFeedback.FireUpdate(); - IoControllerVersionFeedback.FireUpdate(); - SnmpVersionFeedback.FireUpdate(); - BaCnetAppVersionFeedback.FireUpdate(); - ControllerVersionFeedback.FireUpdate(); - SerialNumberFeedback.FireUpdate(); - ModelFeedback.FireUpdate(); + /// + /// Gets data in separate thread + /// + private void RefreshSystemMonitorData() + { + // this takes a while, launch a new thread + CrestronInvoke.BeginInvoke(UpdateFeedback); + } + + private void UpdateFeedback(object o) + { + TimeZoneFeedback.FireUpdate(); + TimeZoneTextFeedback.FireUpdate(); + IoControllerVersionFeedback.FireUpdate(); + SnmpVersionFeedback.FireUpdate(); + BaCnetAppVersionFeedback.FireUpdate(); + ControllerVersionFeedback.FireUpdate(); + SerialNumberFeedback.FireUpdate(); + ModelFeedback.FireUpdate(); IsApplianceFeedback.FireUpdate(); IsServerFeedback.FireUpdate(); - OnSystemMonitorPropertiesChanged(); - } + OnSystemMonitorPropertiesChanged(); + } - private void OnSystemMonitorPropertiesChanged() + private void OnSystemMonitorPropertiesChanged() + { + var handler = SystemMonitorPropertiesChanged; + if (handler != null) { - var handler = SystemMonitorPropertiesChanged; - if (handler != null) - { - handler(this, new EventArgs()); - } + handler(this, new EventArgs()); } + } - public override bool CustomActivate() - { - RefreshSystemMonitorData(); + public override bool CustomActivate() + { + RefreshSystemMonitorData(); - return base.CustomActivate(); - } + return base.CustomActivate(); + } - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = new SystemMonitorJoinMap(joinStart); + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new SystemMonitorJoinMap(joinStart); - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - if (!string.IsNullOrEmpty(joinMapSerialized)) - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } - Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - Debug.LogMessage(LogEventLevel.Verbose, this, "Linking API starting at join: {0}", joinStart); + Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + Debug.LogMessage(LogEventLevel.Verbose, this, "Linking API starting at join: {0}", joinStart); - TimeZoneFeedback.LinkInputSig(trilist.UShortInput[joinMap.TimeZone.JoinNumber]); - TimeZoneTextFeedback.LinkInputSig(trilist.StringInput[joinMap.TimeZoneName.JoinNumber]); + TimeZoneFeedback.LinkInputSig(trilist.UShortInput[joinMap.TimeZone.JoinNumber]); + TimeZoneTextFeedback.LinkInputSig(trilist.StringInput[joinMap.TimeZoneName.JoinNumber]); - IoControllerVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.IOControllerVersion.JoinNumber]); - SnmpVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.SnmpAppVersion.JoinNumber]); - BaCnetAppVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.BACnetAppVersion.JoinNumber]); - ControllerVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.ControllerVersion.JoinNumber]); - SerialNumberFeedback.LinkInputSig(trilist.StringInput[joinMap.SerialNumber.JoinNumber]); - ModelFeedback.LinkInputSig(trilist.StringInput[joinMap.Model.JoinNumber]); - UptimeFeedback.LinkInputSig(trilist.StringInput[joinMap.Uptime.JoinNumber]); - LastStartFeedback.LinkInputSig(trilist.StringInput[joinMap.LastBoot.JoinNumber]); + IoControllerVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.IOControllerVersion.JoinNumber]); + SnmpVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.SnmpAppVersion.JoinNumber]); + BaCnetAppVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.BACnetAppVersion.JoinNumber]); + ControllerVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.ControllerVersion.JoinNumber]); + SerialNumberFeedback.LinkInputSig(trilist.StringInput[joinMap.SerialNumber.JoinNumber]); + ModelFeedback.LinkInputSig(trilist.StringInput[joinMap.Model.JoinNumber]); + UptimeFeedback.LinkInputSig(trilist.StringInput[joinMap.Uptime.JoinNumber]); + LastStartFeedback.LinkInputSig(trilist.StringInput[joinMap.LastBoot.JoinNumber]); trilist.SetSigHeldAction(joinMap.ProcessorReboot.JoinNumber, 10000, ProcessorReboot); IsApplianceFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsAppliance.JoinNumber]); IsServerFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsServer.JoinNumber]); - // iterate the program status feedback collection and map all the joins - LinkProgramInfoJoins(this, trilist, joinMap); + // iterate the program status feedback collection and map all the joins + LinkProgramInfoJoins(this, trilist, joinMap); - LinkEthernetInfoJoins(this, trilist, joinMap); - } + LinkEthernetInfoJoins(this, trilist, joinMap); + } - private static void LinkEthernetInfoJoins(SystemMonitorController systemMonitorController, BasicTriList trilist, SystemMonitorJoinMap joinMap) + private static void LinkEthernetInfoJoins(SystemMonitorController systemMonitorController, BasicTriList trilist, SystemMonitorJoinMap joinMap) + { + uint ethernetSlotJoinStart = 0; + foreach (var fb in systemMonitorController.EthernetStatusFeedbackCollection) { - uint ethernetSlotJoinStart = 0; - foreach (var fb in systemMonitorController.EthernetStatusFeedbackCollection) - { - fb.Value.CurrentIpAddressFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.CurrentIpAddress.JoinNumber]); - fb.Value.CurrentSubnetMaskFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.CurrentSubnetMask.JoinNumber]); - fb.Value.CurrentDefaultGatewayFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.CurrentDefaultGateway.JoinNumber]); - fb.Value.StaticIpAddressFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.StaticIpAddress.JoinNumber]); - fb.Value.StaticSubnetMaskFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.StaticSubnetMask.JoinNumber]); - fb.Value.StaticDefaultGatewayFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.StaticDefaultGateway.JoinNumber]); - fb.Value.HostNameFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.HostName.JoinNumber]); - fb.Value.MacAddressFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.MacAddress.JoinNumber]); - fb.Value.DomainFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.Domain.JoinNumber]); - fb.Value.DnsServerFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.DnsServer.JoinNumber]); - fb.Value.DhcpStatusFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.DhcpStatus.JoinNumber]); - - ethernetSlotJoinStart += joinMap.EthernetOffsetJoin.JoinNumber; - } + fb.Value.CurrentIpAddressFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.CurrentIpAddress.JoinNumber]); + fb.Value.CurrentSubnetMaskFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.CurrentSubnetMask.JoinNumber]); + fb.Value.CurrentDefaultGatewayFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.CurrentDefaultGateway.JoinNumber]); + fb.Value.StaticIpAddressFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.StaticIpAddress.JoinNumber]); + fb.Value.StaticSubnetMaskFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.StaticSubnetMask.JoinNumber]); + fb.Value.StaticDefaultGatewayFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.StaticDefaultGateway.JoinNumber]); + fb.Value.HostNameFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.HostName.JoinNumber]); + fb.Value.MacAddressFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.MacAddress.JoinNumber]); + fb.Value.DomainFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.Domain.JoinNumber]); + fb.Value.DnsServerFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.DnsServer.JoinNumber]); + fb.Value.DhcpStatusFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.DhcpStatus.JoinNumber]); + + ethernetSlotJoinStart += joinMap.EthernetOffsetJoin.JoinNumber; } + } - private static void LinkProgramInfoJoins(SystemMonitorController systemMonitorController, BasicTriList trilist, - SystemMonitorJoinMap joinMap) - { - uint programSlotJoinStart = 0; + private static void LinkProgramInfoJoins(SystemMonitorController systemMonitorController, BasicTriList trilist, + SystemMonitorJoinMap joinMap) + { + uint programSlotJoinStart = 0; - foreach (var p in systemMonitorController.ProgramStatusFeedbackCollection) - { - var programNumber = p.Value.Program.Number; - - trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramStart.JoinNumber, - b => SystemMonitor.ProgramCollection[programNumber].OperatingState = eProgramOperatingState.Start); - p.Value.ProgramStartedFeedback.LinkInputSig(trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramStart.JoinNumber]); - - trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramStop.JoinNumber, - b => SystemMonitor.ProgramCollection[programNumber].OperatingState = eProgramOperatingState.Stop); - p.Value.ProgramStoppedFeedback.LinkInputSig(trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramStop.JoinNumber]); - - trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramRegister.JoinNumber, - b => SystemMonitor.ProgramCollection[programNumber].RegistrationState = eProgramRegistrationState.Register); - p.Value.ProgramRegisteredFeedback.LinkInputSig( - trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramRegister.JoinNumber]); - - trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramUnregister.JoinNumber, - b => SystemMonitor.ProgramCollection[programNumber].RegistrationState = eProgramRegistrationState.Unregister); - p.Value.ProgramUnregisteredFeedback.LinkInputSig( - trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramUnregister.JoinNumber]); - - p.Value.ProgramNameFeedback.LinkInputSig(trilist.StringInput[programSlotJoinStart + joinMap.ProgramName.JoinNumber]); - p.Value.ProgramCompileTimeFeedback.LinkInputSig( - trilist.StringInput[programSlotJoinStart + joinMap.ProgramCompiledTime.JoinNumber]); - p.Value.CrestronDataBaseVersionFeedback.LinkInputSig( - trilist.StringInput[programSlotJoinStart + joinMap.ProgramCrestronDatabaseVersion.JoinNumber]); - p.Value.EnvironmentVersionFeedback.LinkInputSig( - trilist.StringInput[programSlotJoinStart + joinMap.ProgramEnvironmentVersion.JoinNumber]); - p.Value.AggregatedProgramInfoFeedback.LinkInputSig( - trilist.StringInput[programSlotJoinStart + joinMap.AggregatedProgramInfo.JoinNumber]); + foreach (var p in systemMonitorController.ProgramStatusFeedbackCollection) + { + var programNumber = p.Value.Program.Number; + + trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramStart.JoinNumber, + b => SystemMonitor.ProgramCollection[programNumber].OperatingState = eProgramOperatingState.Start); + p.Value.ProgramStartedFeedback.LinkInputSig(trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramStart.JoinNumber]); + + trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramStop.JoinNumber, + b => SystemMonitor.ProgramCollection[programNumber].OperatingState = eProgramOperatingState.Stop); + p.Value.ProgramStoppedFeedback.LinkInputSig(trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramStop.JoinNumber]); + + trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramRegister.JoinNumber, + b => SystemMonitor.ProgramCollection[programNumber].RegistrationState = eProgramRegistrationState.Register); + p.Value.ProgramRegisteredFeedback.LinkInputSig( + trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramRegister.JoinNumber]); + + trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramUnregister.JoinNumber, + b => SystemMonitor.ProgramCollection[programNumber].RegistrationState = eProgramRegistrationState.Unregister); + p.Value.ProgramUnregisteredFeedback.LinkInputSig( + trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramUnregister.JoinNumber]); + + p.Value.ProgramNameFeedback.LinkInputSig(trilist.StringInput[programSlotJoinStart + joinMap.ProgramName.JoinNumber]); + p.Value.ProgramCompileTimeFeedback.LinkInputSig( + trilist.StringInput[programSlotJoinStart + joinMap.ProgramCompiledTime.JoinNumber]); + p.Value.CrestronDataBaseVersionFeedback.LinkInputSig( + trilist.StringInput[programSlotJoinStart + joinMap.ProgramCrestronDatabaseVersion.JoinNumber]); + p.Value.EnvironmentVersionFeedback.LinkInputSig( + trilist.StringInput[programSlotJoinStart + joinMap.ProgramEnvironmentVersion.JoinNumber]); + p.Value.AggregatedProgramInfoFeedback.LinkInputSig( + trilist.StringInput[programSlotJoinStart + joinMap.AggregatedProgramInfo.JoinNumber]); trilist.SetSigHeldAction(programSlotJoinStart + joinMap.ProgramReset.JoinNumber, 10000, () => ProgramReset(programNumber)); - programSlotJoinStart = programSlotJoinStart + joinMap.ProgramOffsetJoin.JoinSpan; - } - } + programSlotJoinStart = programSlotJoinStart + joinMap.ProgramOffsetJoin.JoinSpan; + } + } //// Sets the time zone - //public void SetTimeZone(int timeZone) - //{ - // SystemMonitor.TimeZoneInformation.TimeZoneNumber = timeZone; - //} + //public void SetTimeZone(int timeZone) + //{ + // SystemMonitor.TimeZoneInformation.TimeZoneNumber = timeZone; + //} - /// - /// Responds to program change events and triggers the appropriate feedbacks to update - /// - /// - /// - private void SystemMonitor_ProgramChange(Program sender, ProgramEventArgs args) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Program Change Detected for slot: {0}", sender.Number); - Debug.LogMessage(LogEventLevel.Verbose, this, "Event Type: {0}", args.EventType); + /// + /// Responds to program change events and triggers the appropriate feedbacks to update + /// + /// + /// + private void SystemMonitor_ProgramChange(Program sender, ProgramEventArgs args) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Program Change Detected for slot: {0}", sender.Number); + Debug.LogMessage(LogEventLevel.Verbose, this, "Event Type: {0}", args.EventType); - var program = ProgramStatusFeedbackCollection[sender.Number]; + var program = ProgramStatusFeedbackCollection[sender.Number]; - switch (args.EventType) - { - case eProgramChangeEventType.OperatingState: - program.ProgramStartedFeedback.FireUpdate(); - program.ProgramStoppedFeedback.FireUpdate(); - program.ProgramInfo.OperatingState = args.OperatingState; - if (args.OperatingState == eProgramOperatingState.Start) - program.GetProgramInfo(); - else - { - program.AggregatedProgramInfoFeedback.FireUpdate(); - program.OnProgramInfoChanged(); - } - break; - case eProgramChangeEventType.RegistrationState: - program.ProgramRegisteredFeedback.FireUpdate(); - program.ProgramUnregisteredFeedback.FireUpdate(); - program.ProgramInfo.RegistrationState = args.RegistrationState; + switch (args.EventType) + { + case eProgramChangeEventType.OperatingState: + program.ProgramStartedFeedback.FireUpdate(); + program.ProgramStoppedFeedback.FireUpdate(); + program.ProgramInfo.OperatingState = args.OperatingState; + if (args.OperatingState == eProgramOperatingState.Start) program.GetProgramInfo(); - break; - } + else + { + program.AggregatedProgramInfoFeedback.FireUpdate(); + program.OnProgramInfoChanged(); + } + break; + case eProgramChangeEventType.RegistrationState: + program.ProgramRegisteredFeedback.FireUpdate(); + program.ProgramUnregisteredFeedback.FireUpdate(); + program.ProgramInfo.RegistrationState = args.RegistrationState; + program.GetProgramInfo(); + break; } + } - /// - /// Responds to time zone changes and updates the appropriate feedbacks - /// - /// - private void TimeZoneInformation_TimeZoneChange(TimeZoneEventArgs args) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Time Zone Change Detected."); - TimeZoneFeedback.FireUpdate(); - TimeZoneTextFeedback.FireUpdate(); + /// + /// Responds to time zone changes and updates the appropriate feedbacks + /// + /// + private void TimeZoneInformation_TimeZoneChange(TimeZoneEventArgs args) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Time Zone Change Detected."); + TimeZoneFeedback.FireUpdate(); + TimeZoneTextFeedback.FireUpdate(); - OnSystemMonitorPropertiesChanged(); - } + OnSystemMonitorPropertiesChanged(); + } - public class EthernetStatusFeedbacks + public class EthernetStatusFeedbacks + { + public StringFeedback HostNameFeedback { get; protected set; } + public StringFeedback DnsServerFeedback { get; protected set; } + public StringFeedback DomainFeedback { get; protected set; } + public StringFeedback MacAddressFeedback { get; protected set; } + public StringFeedback DhcpStatusFeedback { get; protected set; } + + public StringFeedback CurrentIpAddressFeedback { get; protected set; } + public StringFeedback CurrentSubnetMaskFeedback { get; protected set; } + public StringFeedback CurrentDefaultGatewayFeedback { get; protected set; } + + public StringFeedback StaticIpAddressFeedback { get; protected set; } + public StringFeedback StaticSubnetMaskFeedback { get; protected set; } + public StringFeedback StaticDefaultGatewayFeedback { get; protected set; } + + public EthernetStatusFeedbacks(short adapterIndex) { - public StringFeedback HostNameFeedback { get; protected set; } - public StringFeedback DnsServerFeedback { get; protected set; } - public StringFeedback DomainFeedback { get; protected set; } - public StringFeedback MacAddressFeedback { get; protected set; } - public StringFeedback DhcpStatusFeedback { get; protected set; } - - public StringFeedback CurrentIpAddressFeedback { get; protected set; } - public StringFeedback CurrentSubnetMaskFeedback { get; protected set; } - public StringFeedback CurrentDefaultGatewayFeedback { get; protected set; } - - public StringFeedback StaticIpAddressFeedback { get; protected set; } - public StringFeedback StaticSubnetMaskFeedback { get; protected set; } - public StringFeedback StaticDefaultGatewayFeedback { get; protected set; } - - public EthernetStatusFeedbacks(short adapterIndex) - { - Debug.LogMessage(LogEventLevel.Verbose, "Ethernet Information for interface {0}", adapterIndex); - Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} Hostname: {0}", CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, adapterIndex), adapterIndex); - Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} Current IP Address: {0}", CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, adapterIndex), adapterIndex); - Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} Current Subnet Mask: {0}", CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, adapterIndex), adapterIndex); - Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} Current Router: {0}", CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, adapterIndex), adapterIndex); - Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} Static IP Address: {0}", CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_STATIC_IPADDRESS, adapterIndex), adapterIndex); - Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} Static Subnet Mask: {0}", CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_STATIC_IPMASK, adapterIndex), adapterIndex); - Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} Static Router: {0}", CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_STATIC_ROUTER, adapterIndex), adapterIndex); - Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} DNS Servers: {0}", CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DNS_SERVER, adapterIndex), adapterIndex); - Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} DHCP State: {0}", CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_DHCP_STATE, adapterIndex), adapterIndex); - Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} Domain Name: {0}", CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DOMAIN_NAME, adapterIndex), adapterIndex); - Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} MAC Address: {0}", CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, adapterIndex), adapterIndex); - HostNameFeedback = - new StringFeedback( - () => - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, adapterIndex)); - - CurrentIpAddressFeedback = - new StringFeedback( - () => - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, adapterIndex)); - CurrentDefaultGatewayFeedback = - new StringFeedback( - () => - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, adapterIndex)); - CurrentSubnetMaskFeedback = - new StringFeedback( - () => - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, adapterIndex)); - StaticIpAddressFeedback = - new StringFeedback( - () => - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, adapterIndex)); - StaticDefaultGatewayFeedback = - new StringFeedback( - () => - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, adapterIndex)); - StaticSubnetMaskFeedback = - new StringFeedback( - () => - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, adapterIndex)); - DomainFeedback = - new StringFeedback( - () => - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DOMAIN_NAME, adapterIndex)); - DnsServerFeedback = - new StringFeedback( - () => - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DNS_SERVER, adapterIndex)); - MacAddressFeedback = - new StringFeedback( - () => - CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, adapterIndex)); - - DhcpStatusFeedback = new StringFeedback( + Debug.LogMessage(LogEventLevel.Verbose, "Ethernet Information for interface {0}", adapterIndex); + Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} Hostname: {0}", CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, adapterIndex), adapterIndex); + Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} Current IP Address: {0}", CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, adapterIndex), adapterIndex); + Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} Current Subnet Mask: {0}", CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, adapterIndex), adapterIndex); + Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} Current Router: {0}", CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, adapterIndex), adapterIndex); + Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} Static IP Address: {0}", CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_STATIC_IPADDRESS, adapterIndex), adapterIndex); + Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} Static Subnet Mask: {0}", CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_STATIC_IPMASK, adapterIndex), adapterIndex); + Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} Static Router: {0}", CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_STATIC_ROUTER, adapterIndex), adapterIndex); + Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} DNS Servers: {0}", CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DNS_SERVER, adapterIndex), adapterIndex); + Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} DHCP State: {0}", CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_DHCP_STATE, adapterIndex), adapterIndex); + Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} Domain Name: {0}", CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DOMAIN_NAME, adapterIndex), adapterIndex); + Debug.LogMessage(LogEventLevel.Verbose, "Adapter Index: {1} MAC Address: {0}", CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, adapterIndex), adapterIndex); + HostNameFeedback = + new StringFeedback( () => CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_DHCP_STATE, adapterIndex)); - } + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, adapterIndex)); - public void UpdateEthernetStatus() - { - HostNameFeedback.FireUpdate(); - CurrentIpAddressFeedback.FireUpdate(); - CurrentSubnetMaskFeedback.FireUpdate(); - CurrentDefaultGatewayFeedback.FireUpdate(); - StaticIpAddressFeedback.FireUpdate(); - StaticSubnetMaskFeedback.FireUpdate(); - StaticDefaultGatewayFeedback.FireUpdate(); - DomainFeedback.FireUpdate(); - DnsServerFeedback.FireUpdate(); - MacAddressFeedback.FireUpdate(); - DhcpStatusFeedback.FireUpdate(); - } - } + CurrentIpAddressFeedback = + new StringFeedback( + () => + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, adapterIndex)); + CurrentDefaultGatewayFeedback = + new StringFeedback( + () => + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, adapterIndex)); + CurrentSubnetMaskFeedback = + new StringFeedback( + () => + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, adapterIndex)); + StaticIpAddressFeedback = + new StringFeedback( + () => + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, adapterIndex)); + StaticDefaultGatewayFeedback = + new StringFeedback( + () => + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, adapterIndex)); + StaticSubnetMaskFeedback = + new StringFeedback( + () => + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, adapterIndex)); + DomainFeedback = + new StringFeedback( + () => + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DOMAIN_NAME, adapterIndex)); + DnsServerFeedback = + new StringFeedback( + () => + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DNS_SERVER, adapterIndex)); + MacAddressFeedback = + new StringFeedback( + () => + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, adapterIndex)); + DhcpStatusFeedback = new StringFeedback( + () => + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_DHCP_STATE, adapterIndex)); + } - public class ProgramStatusFeedbacks + public void UpdateEthernetStatus() { - public event EventHandler ProgramInfoChanged; + HostNameFeedback.FireUpdate(); + CurrentIpAddressFeedback.FireUpdate(); + CurrentSubnetMaskFeedback.FireUpdate(); + CurrentDefaultGatewayFeedback.FireUpdate(); + StaticIpAddressFeedback.FireUpdate(); + StaticSubnetMaskFeedback.FireUpdate(); + StaticDefaultGatewayFeedback.FireUpdate(); + DomainFeedback.FireUpdate(); + DnsServerFeedback.FireUpdate(); + MacAddressFeedback.FireUpdate(); + DhcpStatusFeedback.FireUpdate(); + } + } - public Program Program; - public ProgramInfo ProgramInfo { get; set; } + public class ProgramStatusFeedbacks + { + public event EventHandler ProgramInfoChanged; - public BoolFeedback ProgramStartedFeedback; - public BoolFeedback ProgramStoppedFeedback; - public BoolFeedback ProgramRegisteredFeedback; - public BoolFeedback ProgramUnregisteredFeedback; + public Program Program; - public StringFeedback ProgramNameFeedback; - public StringFeedback ProgramCompileTimeFeedback; - public StringFeedback CrestronDataBaseVersionFeedback; - // SIMPL windows version - public StringFeedback EnvironmentVersionFeedback; - public StringFeedback AggregatedProgramInfoFeedback; + public ProgramInfo ProgramInfo { get; set; } - public ProgramStatusFeedbacks(Program program) - { - ProgramInfo = new ProgramInfo(program.Number); + public BoolFeedback ProgramStartedFeedback; + public BoolFeedback ProgramStoppedFeedback; + public BoolFeedback ProgramRegisteredFeedback; + public BoolFeedback ProgramUnregisteredFeedback; + + public StringFeedback ProgramNameFeedback; + public StringFeedback ProgramCompileTimeFeedback; + public StringFeedback CrestronDataBaseVersionFeedback; + // SIMPL windows version + public StringFeedback EnvironmentVersionFeedback; + public StringFeedback AggregatedProgramInfoFeedback; + + public ProgramStatusFeedbacks(Program program) + { + ProgramInfo = new ProgramInfo(program.Number); - Program = program; + Program = program; - ProgramInfo.OperatingState = Program.OperatingState; - ProgramInfo.RegistrationState = Program.RegistrationState; + ProgramInfo.OperatingState = Program.OperatingState; + ProgramInfo.RegistrationState = Program.RegistrationState; - ProgramStartedFeedback = new BoolFeedback(() => Program.OperatingState == eProgramOperatingState.Start); - ProgramStartedFeedback.FireUpdate(); + ProgramStartedFeedback = new BoolFeedback(() => Program.OperatingState == eProgramOperatingState.Start); + ProgramStartedFeedback.FireUpdate(); - ProgramStoppedFeedback = new BoolFeedback(() => Program.OperatingState == eProgramOperatingState.Stop); - ProgramStoppedFeedback.FireUpdate(); + ProgramStoppedFeedback = new BoolFeedback(() => Program.OperatingState == eProgramOperatingState.Stop); + ProgramStoppedFeedback.FireUpdate(); - ProgramRegisteredFeedback = - new BoolFeedback(() => Program.RegistrationState == eProgramRegistrationState.Register); - ProgramRegisteredFeedback.FireUpdate(); + ProgramRegisteredFeedback = + new BoolFeedback(() => Program.RegistrationState == eProgramRegistrationState.Register); + ProgramRegisteredFeedback.FireUpdate(); - ProgramUnregisteredFeedback = - new BoolFeedback(() => Program.RegistrationState == eProgramRegistrationState.Unregister); - ProgramUnregisteredFeedback.FireUpdate(); + ProgramUnregisteredFeedback = + new BoolFeedback(() => Program.RegistrationState == eProgramRegistrationState.Unregister); + ProgramUnregisteredFeedback.FireUpdate(); ProgramNameFeedback = new StringFeedback(() => ProgramInfo.ProgramFile); CrestronDataBaseVersionFeedback = new StringFeedback(() => ProgramInfo.CrestronDb); EnvironmentVersionFeedback = new StringFeedback(() => ProgramInfo.Environment); - ProgramCompileTimeFeedback = new StringFeedback(() => ProgramInfo.CompileTime); - AggregatedProgramInfoFeedback = new StringFeedback(() => JsonConvert.SerializeObject(ProgramInfo)); + ProgramCompileTimeFeedback = new StringFeedback(() => ProgramInfo.CompileTime); + AggregatedProgramInfoFeedback = new StringFeedback(() => JsonConvert.SerializeObject(ProgramInfo)); - GetProgramInfo(); - } + GetProgramInfo(); + } - /// - /// Retrieves information about a running program - /// - public void GetProgramInfo() - { - CrestronInvoke.BeginInvoke(GetProgramInfo); - } + /// + /// Retrieves information about a running program + /// + public void GetProgramInfo() + { + CrestronInvoke.BeginInvoke(GetProgramInfo); + } - private void GetProgramInfo(object o) - { - Debug.LogMessage(LogEventLevel.Verbose, "Attempting to get program info for slot: {0}", Program.Number); + private void GetProgramInfo(object o) + { + Debug.LogMessage(LogEventLevel.Verbose, "Attempting to get program info for slot: {0}", Program.Number); - string response = null; + string response = null; - if (Program.RegistrationState == eProgramRegistrationState.Unregister || Program.OperatingState == eProgramOperatingState.Stop) + if (Program.RegistrationState == eProgramRegistrationState.Unregister || Program.OperatingState == eProgramOperatingState.Stop) + { + Debug.LogMessage(LogEventLevel.Verbose, "Program {0} not registered. Setting default values for program information.", + Program.Number); + + ProgramInfo = new ProgramInfo(Program.Number) { - Debug.LogMessage(LogEventLevel.Verbose, "Program {0} not registered. Setting default values for program information.", - Program.Number); + OperatingState = Program.OperatingState, + RegistrationState = Program.RegistrationState + }; - ProgramInfo = new ProgramInfo(Program.Number) - { - OperatingState = Program.OperatingState, - RegistrationState = Program.RegistrationState - }; + return; + } - return; - } + var success = CrestronConsole.SendControlSystemCommand( + string.Format("progcomments:{0}", Program.Number), ref response); - var success = CrestronConsole.SendControlSystemCommand( - string.Format("progcomments:{0}", Program.Number), ref response); + if (!success) + { + Debug.LogMessage(LogEventLevel.Verbose, "Progcomments Attempt Unsuccessful for slot: {0}", Program.Number); + UpdateFeedbacks(); + return; + } - if (!success) - { - Debug.LogMessage(LogEventLevel.Verbose, "Progcomments Attempt Unsuccessful for slot: {0}", Program.Number); - UpdateFeedbacks(); - return; - } + if (response.ToLower().Contains("bad or incomplete")) + { + Debug.LogMessage(LogEventLevel.Verbose, + "Program in slot {0} not running. Setting default ProgramInfo for slot: {0}", + Program.Number); - if (response.ToLower().Contains("bad or incomplete")) + // Assume no valid program info. Constructing a new object will wipe all properties + ProgramInfo = new ProgramInfo(Program.Number) { - Debug.LogMessage(LogEventLevel.Verbose, - "Program in slot {0} not running. Setting default ProgramInfo for slot: {0}", - Program.Number); - - // Assume no valid program info. Constructing a new object will wipe all properties - ProgramInfo = new ProgramInfo(Program.Number) - { OperatingState = Program.OperatingState, - RegistrationState = Program.RegistrationState - }; + RegistrationState = Program.RegistrationState + }; - UpdateFeedbacks(); + UpdateFeedbacks(); - return; - } + return; + } - // Shared properteis - ProgramInfo.ProgramFile = ParseConsoleData(response, "Program File", ": ", "\n"); - ProgramInfo.CompilerRevision = ParseConsoleData(response, "Compiler Rev", ": ", "\n"); - ProgramInfo.CompileTime = ParseConsoleData(response, "Compiled On", ": ", "\n"); - ProgramInfo.Include4Dat = ParseConsoleData(response, "Include4.dat", ": ", "\n"); + // Shared properteis + ProgramInfo.ProgramFile = ParseConsoleData(response, "Program File", ": ", "\n"); + ProgramInfo.CompilerRevision = ParseConsoleData(response, "Compiler Rev", ": ", "\n"); + ProgramInfo.CompileTime = ParseConsoleData(response, "Compiled On", ": ", "\n"); + ProgramInfo.Include4Dat = ParseConsoleData(response, "Include4.dat", ": ", "\n"); - if (ProgramInfo.ProgramFile.Contains(".dll")) - { - // SSP Program - ProgramInfo.FriendlyName = ParseConsoleData(response, "Friendly Name", ": ", "\n"); - ProgramInfo.ApplicationName = ParseConsoleData(response, "Application Name", ": ", "\n"); - ProgramInfo.ProgramTool = ParseConsoleData(response, "Program Tool", ": ", "\n"); - ProgramInfo.MinFirmwareVersion = ParseConsoleData(response, "Min Firmware Version", ": ", - "\n"); - ProgramInfo.PlugInVersion = ParseConsoleData(response, "PlugInVersion", ": ", "\n"); + if (ProgramInfo.ProgramFile.Contains(".dll")) + { + // SSP Program + ProgramInfo.FriendlyName = ParseConsoleData(response, "Friendly Name", ": ", "\n"); + ProgramInfo.ApplicationName = ParseConsoleData(response, "Application Name", ": ", "\n"); + ProgramInfo.ProgramTool = ParseConsoleData(response, "Program Tool", ": ", "\n"); + ProgramInfo.MinFirmwareVersion = ParseConsoleData(response, "Min Firmware Version", ": ", + "\n"); + ProgramInfo.PlugInVersion = ParseConsoleData(response, "PlugInVersion", ": ", "\n"); ProgramInfo.ProgramFile += string.Format(" {0}.{1}.{2}", ProgramInfo.CompilerRevisionInfo.Major, @@ -659,101 +659,101 @@ private void GetProgramInfo(object o) ProgramInfo.CompilerRevisionInfo.Build); ProgramInfo.Environment = ProgramInfo.ProgramTool; - } - else if (ProgramInfo.ProgramFile.Contains(".smw")) - { - // SIMPL Windows Program - ProgramInfo.FriendlyName = ParseConsoleData(response, "Friendly Name", ":", "\n"); - ProgramInfo.SystemName = ParseConsoleData(response, "System Name", ": ", "\n"); - ProgramInfo.CrestronDb = ParseConsoleData(response, "CrestronDB", ": ", "\n"); - ProgramInfo.Environment = ParseConsoleData(response, "Source Env", ": ", "\n"); - ProgramInfo.Programmer = ParseConsoleData(response, "Programmer", ": ", "\n"); - } - Debug.LogMessage(LogEventLevel.Verbose, "Program info for slot {0} successfully updated", Program.Number); - - UpdateFeedbacks(); } - - private void UpdateFeedbacks() + else if (ProgramInfo.ProgramFile.Contains(".smw")) { - ProgramNameFeedback.FireUpdate(); - ProgramCompileTimeFeedback.FireUpdate(); - CrestronDataBaseVersionFeedback.FireUpdate(); - EnvironmentVersionFeedback.FireUpdate(); + // SIMPL Windows Program + ProgramInfo.FriendlyName = ParseConsoleData(response, "Friendly Name", ":", "\n"); + ProgramInfo.SystemName = ParseConsoleData(response, "System Name", ": ", "\n"); + ProgramInfo.CrestronDb = ParseConsoleData(response, "CrestronDB", ": ", "\n"); + ProgramInfo.Environment = ParseConsoleData(response, "Source Env", ": ", "\n"); + ProgramInfo.Programmer = ParseConsoleData(response, "Programmer", ": ", "\n"); + } + Debug.LogMessage(LogEventLevel.Verbose, "Program info for slot {0} successfully updated", Program.Number); - AggregatedProgramInfoFeedback.FireUpdate(); + UpdateFeedbacks(); + } - OnProgramInfoChanged(); - } + private void UpdateFeedbacks() + { + ProgramNameFeedback.FireUpdate(); + ProgramCompileTimeFeedback.FireUpdate(); + CrestronDataBaseVersionFeedback.FireUpdate(); + EnvironmentVersionFeedback.FireUpdate(); - public void OnProgramInfoChanged() - { - //Debug.LogMessage(LogEventLevel.Debug, "Firing ProgramInfoChanged for slot: {0}", Program.Number); - var handler = ProgramInfoChanged; - if (handler != null) - { - handler(this, new ProgramInfoEventArgs(ProgramInfo)); - } - } + AggregatedProgramInfoFeedback.FireUpdate(); - private string ParseConsoleData(string data, string line, string startString, string endString) - { - var outputData = ""; + OnProgramInfoChanged(); + } - if (data.Length <= 0) return outputData; + public void OnProgramInfoChanged() + { + //Debug.LogMessage(LogEventLevel.Debug, "Firing ProgramInfoChanged for slot: {0}", Program.Number); + var handler = ProgramInfoChanged; + if (handler != null) + { + handler(this, new ProgramInfoEventArgs(ProgramInfo)); + } + } - if (!data.Contains(line)) - { - return outputData; - } + private string ParseConsoleData(string data, string line, string startString, string endString) + { + var outputData = ""; - try - { - //Debug.LogMessage(LogEventLevel.Verbose, "ParseConsoleData Data: {0}, Line {1}, startStirng {2}, endString {3}", data, line, startString, endString); - var linePosition = data.IndexOf(line, StringComparison.Ordinal); - var startPosition = data.IndexOf(startString, linePosition, StringComparison.Ordinal) + - startString.Length; - var endPosition = data.IndexOf(endString, startPosition, StringComparison.Ordinal); - outputData = data.Substring(startPosition, endPosition - startPosition).Trim(); - //Debug.LogMessage(LogEventLevel.Verbose, "ParseConsoleData Return: {0}", outputData); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Error, "Error Parsing Console Data: {0}", e); - Debug.LogMessage(LogEventLevel.Verbose, "Stack Trace: {stackTrace}", e.StackTrace); - } + if (data.Length <= 0) return outputData; + if (!data.Contains(line)) + { return outputData; } + + try + { + //Debug.LogMessage(LogEventLevel.Verbose, "ParseConsoleData Data: {0}, Line {1}, startStirng {2}, endString {3}", data, line, startString, endString); + var linePosition = data.IndexOf(line, StringComparison.Ordinal); + var startPosition = data.IndexOf(startString, linePosition, StringComparison.Ordinal) + + startString.Length; + var endPosition = data.IndexOf(endString, startPosition, StringComparison.Ordinal); + outputData = data.Substring(startPosition, endPosition - startPosition).Trim(); + //Debug.LogMessage(LogEventLevel.Verbose, "ParseConsoleData Return: {0}", outputData); + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Error, "Error Parsing Console Data: {0}", e); + Debug.LogMessage(LogEventLevel.Verbose, "Stack Trace: {stackTrace}", e.StackTrace); + } + + return outputData; } } +} - /// - /// Class for serializing program slot information - /// - public class ProgramInfo - { - // Shared properties +/// +/// Class for serializing program slot information +/// +public class ProgramInfo +{ + // Shared properties - [JsonProperty("programNumber")] - public uint ProgramNumber { get; private set; } + [JsonProperty("programNumber")] + public uint ProgramNumber { get; private set; } - [JsonConverter(typeof (StringEnumConverter))] - [JsonProperty("operatingState")] - public eProgramOperatingState OperatingState { get; set; } + [JsonConverter(typeof (StringEnumConverter))] + [JsonProperty("operatingState")] + public eProgramOperatingState OperatingState { get; set; } - [JsonConverter(typeof (StringEnumConverter))] - [JsonProperty("registrationState")] - public eProgramRegistrationState RegistrationState { get; set; } + [JsonConverter(typeof (StringEnumConverter))] + [JsonProperty("registrationState")] + public eProgramRegistrationState RegistrationState { get; set; } - [JsonProperty("programFile")] - public string ProgramFile { get; set; } + [JsonProperty("programFile")] + public string ProgramFile { get; set; } - [JsonProperty("friendlyName")] - public string FriendlyName { get; set; } + [JsonProperty("friendlyName")] + public string FriendlyName { get; set; } - [JsonProperty("compilerRevision")] - public string CompilerRevision { get; set; } + [JsonProperty("compilerRevision")] + public string CompilerRevision { get; set; } [JsonIgnore] public Version CompilerRevisionInfo @@ -764,68 +764,67 @@ public Version CompilerRevisionInfo } } - [JsonProperty("compileTime")] - public string CompileTime { get; set; } + [JsonProperty("compileTime")] + public string CompileTime { get; set; } - [JsonProperty("include4Dat")] - public string Include4Dat { get; set; } + [JsonProperty("include4Dat")] + public string Include4Dat { get; set; } - // SIMPL Windows properties - [JsonProperty("systemName")] - public string SystemName { get; set; } + // SIMPL Windows properties + [JsonProperty("systemName")] + public string SystemName { get; set; } - [JsonProperty("crestronDb")] - public string CrestronDb { get; set; } + [JsonProperty("crestronDb")] + public string CrestronDb { get; set; } - [JsonProperty("environment")] - public string Environment { get; set; } + [JsonProperty("environment")] + public string Environment { get; set; } - [JsonProperty("programmer")] - public string Programmer { get; set; } + [JsonProperty("programmer")] + public string Programmer { get; set; } - // SSP Properties - [JsonProperty("applicationName")] - public string ApplicationName { get; set; } + // SSP Properties + [JsonProperty("applicationName")] + public string ApplicationName { get; set; } - [JsonProperty("programTool")] - public string ProgramTool { get; set; } + [JsonProperty("programTool")] + public string ProgramTool { get; set; } - [JsonProperty("minFirmwareVersion")] - public string MinFirmwareVersion { get; set; } + [JsonProperty("minFirmwareVersion")] + public string MinFirmwareVersion { get; set; } - [JsonProperty("plugInVersion")] - public string PlugInVersion { get; set; } + [JsonProperty("plugInVersion")] + public string PlugInVersion { get; set; } - public ProgramInfo(uint number) - { - ProgramNumber = number; + public ProgramInfo(uint number) + { + ProgramNumber = number; - ProgramFile = ""; - FriendlyName = ""; - CompilerRevision = ""; + ProgramFile = ""; + FriendlyName = ""; + CompilerRevision = ""; CompileTime = ""; - Include4Dat = ""; + Include4Dat = ""; - SystemName = ""; - CrestronDb = ""; - Environment = ""; - Programmer = ""; + SystemName = ""; + CrestronDb = ""; + Environment = ""; + Programmer = ""; - ApplicationName = ""; - ProgramTool = ""; - MinFirmwareVersion = ""; - PlugInVersion = ""; - } + ApplicationName = ""; + ProgramTool = ""; + MinFirmwareVersion = ""; + PlugInVersion = ""; } +} - public class ProgramInfoEventArgs : EventArgs - { - public ProgramInfo ProgramInfo; +public class ProgramInfoEventArgs : EventArgs +{ + public ProgramInfo ProgramInfo; - public ProgramInfoEventArgs(ProgramInfo progInfo) - { - ProgramInfo = progInfo; - } + public ProgramInfoEventArgs(ProgramInfo progInfo) + { + ProgramInfo = progInfo; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs b/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs index aca4f0089..352d7cef1 100644 --- a/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs +++ b/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs @@ -1,187 +1,186 @@ using PepperDash.Core; using System.Collections.Generic; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Represents an abstract controller device for a partition dividing rooms that are combinable +/// +/// In Auto mode, it can use a partition sensor to automatically determine whether the partition is present. +/// +/// In Manual mode it accepts user input to tell it whether the partition is present. +/// +public class EssentialsPartitionController : IPartitionController { - /// - /// Represents an abstract controller device for a partition dividing rooms that are combinable - /// - /// In Auto mode, it can use a partition sensor to automatically determine whether the partition is present. - /// - /// In Manual mode it accepts user input to tell it whether the partition is present. - /// - public class EssentialsPartitionController : IPartitionController - { - private IPartitionStateProvider _partitionSensor; + private IPartitionStateProvider _partitionSensor; - public bool IsInAutoMode { get; private set; } + public bool IsInAutoMode { get; private set; } - private bool _partitionPresent; + private bool _partitionPresent; - public bool PartitionPresent + public bool PartitionPresent + { + get { - get + if (IsInAutoMode) { - if (IsInAutoMode) - { - return _partitionSensor.PartitionPresentFeedback.BoolValue; - } - - return _partitionPresent; + return _partitionSensor.PartitionPresentFeedback.BoolValue; } - set + + return _partitionPresent; + } + set + { + if (_partitionPresent == value) { - if (_partitionPresent == value) - { - return; - } + return; + } - _partitionPresent = value; + _partitionPresent = value; - if (PartitionPresentFeedback != null) - { - PartitionPresentFeedback.FireUpdate(); - } + if (PartitionPresentFeedback != null) + { + PartitionPresentFeedback.FireUpdate(); } } + } - public EssentialsPartitionController(string key, string name, IPartitionStateProvider sensor, bool defaultToManualMode, List adjacentRoomKeys) - { - Key = key; + public EssentialsPartitionController(string key, string name, IPartitionStateProvider sensor, bool defaultToManualMode, List adjacentRoomKeys) + { + Key = key; - Name = name; + Name = name; - AdjacentRoomKeys = adjacentRoomKeys; + AdjacentRoomKeys = adjacentRoomKeys; + + if (sensor != null) + { + _partitionSensor = sensor; - if (sensor != null) + if (!defaultToManualMode) { - _partitionSensor = sensor; - - if (!defaultToManualMode) - { - SetAutoMode(); - } - else - { - SetManualMode(); - } + SetAutoMode(); } else { SetManualMode(); } - - PartitionPresentFeedback.FireUpdate(); } - - private void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e) + else { - if (IsInAutoMode) - { - PartitionPresent = e.BoolValue; - } + SetManualMode(); } - #region IPartitionController Members - - public List AdjacentRoomKeys { get; private set; } + PartitionPresentFeedback.FireUpdate(); + } - public void SetAutoMode() + private void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + if (IsInAutoMode) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Setting {Key} to Auto Mode", this); + PartitionPresent = e.BoolValue; + } + } - IsInAutoMode = true; - if (PartitionPresentFeedback != null) - { - PartitionPresentFeedback.SetValueFunc(() => _partitionSensor.PartitionPresentFeedback.BoolValue); - } - else - { - PartitionPresentFeedback = new BoolFeedback(() => _partitionSensor.PartitionPresentFeedback.BoolValue); - } + #region IPartitionController Members - if (_partitionSensor != null) - { - _partitionSensor.PartitionPresentFeedback.OutputChange -= PartitionPresentFeedback_OutputChange; - _partitionSensor.PartitionPresentFeedback.OutputChange += PartitionPresentFeedback_OutputChange; - PartitionPresent = _partitionSensor.PartitionPresentFeedback.BoolValue; - } + public List AdjacentRoomKeys { get; private set; } - PartitionPresentFeedback.FireUpdate(); + public void SetAutoMode() + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Setting {Key} to Auto Mode", this); + + IsInAutoMode = true; + if (PartitionPresentFeedback != null) + { + PartitionPresentFeedback.SetValueFunc(() => _partitionSensor.PartitionPresentFeedback.BoolValue); + } + else + { + PartitionPresentFeedback = new BoolFeedback(() => _partitionSensor.PartitionPresentFeedback.BoolValue); } - public void SetManualMode() + if (_partitionSensor != null) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Setting {Key} to Manual Mode", this); + _partitionSensor.PartitionPresentFeedback.OutputChange -= PartitionPresentFeedback_OutputChange; + _partitionSensor.PartitionPresentFeedback.OutputChange += PartitionPresentFeedback_OutputChange; + PartitionPresent = _partitionSensor.PartitionPresentFeedback.BoolValue; + } - IsInAutoMode = false; - if (PartitionPresentFeedback != null) - { - PartitionPresentFeedback.SetValueFunc(() => _partitionPresent); - } - else - { - PartitionPresentFeedback = new BoolFeedback(() => _partitionPresent); - } + PartitionPresentFeedback.FireUpdate(); + } - if (_partitionSensor != null) - { - _partitionSensor.PartitionPresentFeedback.OutputChange -= PartitionPresentFeedback_OutputChange; - PartitionPresent = _partitionSensor.PartitionPresentFeedback.BoolValue; - } + public void SetManualMode() + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Setting {Key} to Manual Mode", this); - PartitionPresentFeedback.FireUpdate(); + IsInAutoMode = false; + if (PartitionPresentFeedback != null) + { + PartitionPresentFeedback.SetValueFunc(() => _partitionPresent); + } + else + { + PartitionPresentFeedback = new BoolFeedback(() => _partitionPresent); } - - public void SetPartitionStatePresent() + if (_partitionSensor != null) { - if (!IsInAutoMode) - { - PartitionPresent = true; - PartitionPresentFeedback.FireUpdate(); - } + _partitionSensor.PartitionPresentFeedback.OutputChange -= PartitionPresentFeedback_OutputChange; + PartitionPresent = _partitionSensor.PartitionPresentFeedback.BoolValue; } - public void SetPartitionStateNotPresent() + PartitionPresentFeedback.FireUpdate(); + } + + + public void SetPartitionStatePresent() + { + if (!IsInAutoMode) { - if (!IsInAutoMode) - { - PartitionPresent = false; - PartitionPresentFeedback.FireUpdate(); - } + PartitionPresent = true; + PartitionPresentFeedback.FireUpdate(); } + } - public void ToggglePartitionState() + public void SetPartitionStateNotPresent() + { + if (!IsInAutoMode) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Toggling Partition State for {Key}", this); - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"IsInAutoMode: {IsInAutoMode}", this); + PartitionPresent = false; + PartitionPresentFeedback.FireUpdate(); + } + } - if (!IsInAutoMode) - { - PartitionPresent = !PartitionPresent; - PartitionPresentFeedback.FireUpdate(); - } + public void ToggglePartitionState() + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Toggling Partition State for {Key}", this); + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"IsInAutoMode: {IsInAutoMode}", this); + + if (!IsInAutoMode) + { + PartitionPresent = !PartitionPresent; + PartitionPresentFeedback.FireUpdate(); } + } - #endregion + #endregion - #region IPartitionStateProvider Members + #region IPartitionStateProvider Members - public BoolFeedback PartitionPresentFeedback { get; private set; } + public BoolFeedback PartitionPresentFeedback { get; private set; } - #endregion + #endregion - #region IKeyName Members + #region IKeyName Members - public string Name { get; private set; } + public string Name { get; private set; } - #endregion + #endregion - #region IKeyed Members + #region IKeyed Members - public string Key { get; private set; } + public string Key { get; private set; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/PartitionSensor/IPartitionStateProvider.cs b/src/PepperDash.Essentials.Core/PartitionSensor/IPartitionStateProvider.cs index 418da80c2..47c04a4dd 100644 --- a/src/PepperDash.Essentials.Core/PartitionSensor/IPartitionStateProvider.cs +++ b/src/PepperDash.Essentials.Core/PartitionSensor/IPartitionStateProvider.cs @@ -2,39 +2,38 @@ using Newtonsoft.Json; using PepperDash.Core; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Describes the functionality of a device that senses and provides partition state +/// +public interface IPartitionStateProvider : IKeyName { - /// - /// Describes the functionality of a device that senses and provides partition state - /// - public interface IPartitionStateProvider : IKeyName - { - [JsonIgnore] - BoolFeedback PartitionPresentFeedback { get; } + [JsonIgnore] + BoolFeedback PartitionPresentFeedback { get; } - [JsonProperty("partitionPresent")] - bool PartitionPresent { get; } - } + [JsonProperty("partitionPresent")] + bool PartitionPresent { get; } +} - /// - /// Describes the functionality of a device that can provide partition state either manually via user input or optionally via a sensor state - /// - public interface IPartitionController : IPartitionStateProvider - { - [JsonProperty("adjacentRoomKeys")] - List AdjacentRoomKeys { get; } +/// +/// Describes the functionality of a device that can provide partition state either manually via user input or optionally via a sensor state +/// +public interface IPartitionController : IPartitionStateProvider +{ + [JsonProperty("adjacentRoomKeys")] + List AdjacentRoomKeys { get; } - [JsonProperty("isInAutoMode")] - bool IsInAutoMode { get; } + [JsonProperty("isInAutoMode")] + bool IsInAutoMode { get; } - void SetPartitionStatePresent(); + void SetPartitionStatePresent(); - void SetPartitionStateNotPresent(); + void SetPartitionStateNotPresent(); - void ToggglePartitionState(); + void ToggglePartitionState(); - void SetManualMode(); + void SetManualMode(); - void SetAutoMode(); - } + void SetAutoMode(); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj b/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj index b1406d69a..026f49761 100644 --- a/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj +++ b/src/PepperDash.Essentials.Core/PepperDash.Essentials.Core.csproj @@ -3,7 +3,7 @@ Debug;Release;Debug 4.7.2 - net472 + net8 true true bin\$(Configuration)\ @@ -24,7 +24,8 @@ pdbonly - + + diff --git a/src/PepperDash.Essentials.Core/Plugins/IPluginDeviceFactory.cs b/src/PepperDash.Essentials.Core/Plugins/IPluginDeviceFactory.cs index ec8230074..116c4aa1c 100644 --- a/src/PepperDash.Essentials.Core/Plugins/IPluginDeviceFactory.cs +++ b/src/PepperDash.Essentials.Core/Plugins/IPluginDeviceFactory.cs @@ -1,25 +1,29 @@ +using PepperDash.Essentials.Core.Config; using System.Collections.Generic; -using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + +/// +/// Defines a class that is capable of loading custom plugin device types +/// +public interface IPluginDeviceFactory : IDeviceFactory +{ /// - /// Defines a class that is capable of loading custom plugin device types + /// Required to define the minimum version for Essentials in the format xx.yy.zz /// - public interface IPluginDeviceFactory : IDeviceFactory - { - /// - /// Required to define the minimum version for Essentials in the format xx.yy.zz - /// - string MinimumEssentialsFrameworkVersion { get; } - - } - - public interface IPluginDevelopmentDeviceFactory : IPluginDeviceFactory - { - List DevelopmentEssentialsFrameworkVersions { get; } - } + string MinimumEssentialsFrameworkVersion { get; } } - +/// +/// Defines a factory for creating plugin development devices, including support for specific framework versions. +/// +/// This interface extends to provide additional functionality +/// specific to plugin development, such as access to supported framework versions. +public interface IPluginDevelopmentDeviceFactory : IPluginDeviceFactory +{ + /// + /// Gets a list of framework versions that are essential for development. + /// + List DevelopmentEssentialsFrameworkVersions { get; } +} diff --git a/src/PepperDash.Essentials.Core/Plugins/IncompatiblePlugin.cs b/src/PepperDash.Essentials.Core/Plugins/IncompatiblePlugin.cs new file mode 100644 index 000000000..8cce6f62e --- /dev/null +++ b/src/PepperDash.Essentials.Core/Plugins/IncompatiblePlugin.cs @@ -0,0 +1,47 @@ +using Newtonsoft.Json; + + +namespace PepperDash.Essentials; + +/// +/// Represents a plugin that is incompatible with the current system or configuration. +/// +/// This class provides details about an incompatible plugin, including its name, the reason for the +/// incompatibility, and the plugin that triggered the incompatibility. The triggering plugin can be updated dynamically +/// using the method. +/// +/// +/// +public class IncompatiblePlugin(string name, string reason, string triggeredBy = null) +{ + /// + /// Gets the name associated with the object. + /// + [JsonProperty("name")] + public string Name { get; private set; } = name; + + /// + /// Gets the reason associated with the current operation or response. + /// + [JsonProperty("reason")] + public string Reason { get; private set; } = reason; + + /// + /// Gets the identifier of the entity or process that triggered the current operation. + /// + [JsonProperty("triggeredBy")] + public string TriggeredBy { get; private set; } = triggeredBy ?? "Direct load"; + + /// + /// Updates the name of the plugin that triggered the current operation. + /// + /// The name of the triggering plugin. Must not be null or empty. If the value is null or empty, the operation is + /// ignored. + public void UpdateTriggeringPlugin(string triggeringPlugin) + { + if (!string.IsNullOrEmpty(triggeringPlugin)) + { + TriggeredBy = triggeringPlugin; + } + } +} diff --git a/src/PepperDash.Essentials.Core/Plugins/LoadedAssembly.cs b/src/PepperDash.Essentials.Core/Plugins/LoadedAssembly.cs new file mode 100644 index 000000000..64c639e5c --- /dev/null +++ b/src/PepperDash.Essentials.Core/Plugins/LoadedAssembly.cs @@ -0,0 +1,46 @@ +using System.Reflection; +using Newtonsoft.Json; + + +namespace PepperDash.Essentials; + +/// +/// Represents an assembly that has been loaded, including its name, version, and the associated instance. +/// +/// This class provides information about a loaded assembly, including its name and version as strings, +/// and the associated object. The assembly instance can be updated using the +/// method. +/// +/// +/// +public class LoadedAssembly(string name, string version, Assembly assembly) +{ + /// + /// Gets the name associated with the object. + /// + [JsonProperty("name")] + public string Name { get; private set; } = name; + + /// + /// Gets the version of the object as a string. + /// + [JsonProperty("version")] + public string Version { get; private set; } = version; + + /// + /// Gets the assembly associated with the current instance. + /// + [JsonIgnore] + public Assembly Assembly { get; private set; } = assembly; + + /// + /// Sets the assembly associated with the current instance. + /// + /// The to associate with the current instance. Cannot be . + public void SetAssembly(Assembly assembly) + { + Assembly = assembly; + } +} diff --git a/src/PepperDash.Essentials.Core/Plugins/Net8CompatibleAttribute.cs b/src/PepperDash.Essentials.Core/Plugins/Net8CompatibleAttribute.cs new file mode 100644 index 000000000..1a5b250a0 --- /dev/null +++ b/src/PepperDash.Essentials.Core/Plugins/Net8CompatibleAttribute.cs @@ -0,0 +1,20 @@ +using System; + + +namespace PepperDash.Essentials; + +/// +/// Indicates whether the assembly is compatible with .NET 8. +/// +/// This attribute is used to specify compatibility with .NET 8 for an assembly. By default, the +/// assembly is considered compatible unless explicitly marked otherwise. +/// A boolean value indicating whether the assembly is compatible with .NET 8. The default value is . +[AttributeUsage(AttributeTargets.Assembly)] +public class Net8CompatibleAttribute(bool isCompatible = true) : Attribute +{ + /// + /// Gets a value indicating whether the current object is compatible with the required conditions. + /// + public bool IsCompatible { get; } = isCompatible; +} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs b/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs index 3de088060..9211080c4 100644 --- a/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs +++ b/src/PepperDash.Essentials.Core/Plugins/PluginLoader.cs @@ -1,577 +1,915 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Crestron.SimplSharp; -// using Crestron.SimplSharp.CrestronIO; -using System.Reflection; - -using PepperDash.Core; -using PepperDash.Essentials.Core; -using Serilog.Events; -using Newtonsoft.Json; -using System.IO; - -namespace PepperDash.Essentials -{ - /// - /// Deals with loading plugins at runtime - /// - public static class PluginLoader - { - /// - /// The complete list of loaded assemblies. Includes Essentials Framework assemblies and plugins - /// - public static List LoadedAssemblies { get; private set; } - - /// - /// The list of assemblies loaded from the plugins folder - /// - static List LoadedPluginFolderAssemblies; - - public static LoadedAssembly EssentialsAssembly { get; private set; } - - public static LoadedAssembly PepperDashCoreAssembly { get; private set; } - - public static List EssentialsPluginAssemblies { get; private set; } - - /// - /// The directory to look in for .cplz plugin packages - /// - static string _pluginDirectory => Global.FilePathPrefix + "plugins"; - - /// - /// The directory where plugins will be moved to and loaded from - /// - static string _loadedPluginsDirectoryPath => _pluginDirectory + Global.DirectorySeparator + "loadedAssemblies"; - - // The temp directory where .cplz archives will be unzipped to - static string _tempDirectory => _pluginDirectory + Global.DirectorySeparator + "temp"; - - - static PluginLoader() - { - LoadedAssemblies = new List(); - LoadedPluginFolderAssemblies = new List(); - EssentialsPluginAssemblies = new List(); - } - - /// - /// Retrieves all the loaded assemblies from the program directory - /// - public static void AddProgramAssemblies() - { - Debug.LogMessage(LogEventLevel.Verbose, "Getting Assemblies loaded with Essentials"); - // Get the loaded assembly filenames - var appDi = new DirectoryInfo(Global.ApplicationDirectoryPathPrefix); - var assemblyFiles = appDi.GetFiles("*.dll"); - - Debug.LogMessage(LogEventLevel.Verbose, "Found {0} Assemblies", assemblyFiles.Length); - - foreach (var fi in assemblyFiles.Where(fi => fi.Name.Contains("Essentials") || fi.Name.Contains("PepperDash"))) - { - string version = string.Empty; - Assembly assembly = null; - - switch (fi.Name) - { - case ("PepperDashEssentials.dll"): - { - version = Global.AssemblyVersion; - EssentialsAssembly = new LoadedAssembly(fi.Name, version, assembly); - break; - } - case ("PepperDash_Essentials_Core.dll"): - { - version = Global.AssemblyVersion; - break; - } - case ("Essentials Devices Common.dll"): - { - version = Global.AssemblyVersion; - break; - } - case ("PepperDashCore.dll"): - { - Debug.LogMessage(LogEventLevel.Verbose, "Found PepperDash_Core.dll"); - version = Debug.PepperDashCoreVersion; - Debug.LogMessage(LogEventLevel.Verbose, "PepperDash_Core Version: {0}", version); - PepperDashCoreAssembly = new LoadedAssembly(fi.Name, version, assembly); - break; - } - } - - LoadedAssemblies.Add(new LoadedAssembly(fi.Name, version, assembly)); - } - - if (Debug.Level > 1) - { - Debug.LogMessage(LogEventLevel.Verbose, "Loaded Assemblies:"); - - foreach (var assembly in LoadedAssemblies) - { - Debug.LogMessage(LogEventLevel.Verbose, "Assembly: {0}", assembly.Name); - } - } - } - - - public static void SetEssentialsAssembly(string name, Assembly assembly) - { - var loadedAssembly = LoadedAssemblies.FirstOrDefault(la => la.Name.Equals(name)); - - if (loadedAssembly != null) - { - loadedAssembly.SetAssembly(assembly); - } - } - - /// - /// Loads an assembly via Reflection and adds it to the list of loaded assemblies - /// - /// - static LoadedAssembly LoadAssembly(string filePath) - { - try - { - //Debug.LogMessage(LogEventLevel.Verbose, "Attempting to load {0}", filePath); - var assembly = Assembly.LoadFrom(filePath); - if (assembly != null) - { - var assyVersion = GetAssemblyVersion(assembly); - - var loadedAssembly = new LoadedAssembly(assembly.GetName().Name, assyVersion, assembly); - LoadedAssemblies.Add(loadedAssembly); - Debug.LogMessage(LogEventLevel.Information, "Loaded assembly '{0}', version {1}", loadedAssembly.Name, loadedAssembly.Version); - return loadedAssembly; - } - else - { - Debug.LogMessage(LogEventLevel.Information, "Unable to load assembly: '{0}'", filePath); - } - - return null; - } catch(Exception ex) - { - Debug.LogMessage(ex, "Error loading assembly from {path}", null, filePath); - return null; - } - - } - - /// - /// Attempts to get the assembly informational version and if not possible gets the version - /// - /// - /// - public static string GetAssemblyVersion(Assembly assembly) - { - var ver = assembly.GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false); - if (ver != null && ver.Length > 0) - { - // Get the AssemblyInformationalVersion - AssemblyInformationalVersionAttribute verAttribute = ver[0] as AssemblyInformationalVersionAttribute; - return verAttribute.InformationalVersion; - } - else - { - // Get the AssemblyVersion - var version = assembly.GetName().Version; - var verStr = string.Format("{0}.{1}.{2}.{3}", version.Major, version.Minor, version.Build, version.Revision); - return verStr; - } - } - - /// - /// Checks if the filename matches an already loaded assembly file's name - /// - /// - /// True if file already matches loaded assembly file. - public static bool CheckIfAssemblyLoaded(string name) - { - Debug.LogMessage(LogEventLevel.Verbose, "Checking if assembly: {0} is loaded...", name); - var loadedAssembly = LoadedAssemblies.FirstOrDefault(s => s.Name.Equals(name)); - - if (loadedAssembly != null) - { - Debug.LogMessage(LogEventLevel.Verbose, "Assembly already loaded."); - return true; - } - else - { - Debug.LogMessage(LogEventLevel.Verbose, "Assembly not loaded."); - return false; - } - } - - /// - /// Used by console command to report the currently loaded assemblies and versions - /// - /// - public static void ReportAssemblyVersions(string command) - { - CrestronConsole.ConsoleCommandResponse("Essentials Version: {0}" + CrestronEnvironment.NewLine, Global.AssemblyVersion); - CrestronConsole.ConsoleCommandResponse("PepperDash Core Version: {0}" + CrestronEnvironment.NewLine, PepperDashCoreAssembly.Version); - CrestronConsole.ConsoleCommandResponse("Essentials Plugin Versions:" + CrestronEnvironment.NewLine); - foreach (var assembly in EssentialsPluginAssemblies) - { - CrestronConsole.ConsoleCommandResponse("{0} Version: {1}" + CrestronEnvironment.NewLine, assembly.Name, assembly.Version); - } - - //CrestronConsole.ConsoleCommandResponse("Loaded Assemblies:" + CrestronEnvironment.NewLine); - //foreach (var assembly in LoadedAssemblies) - //{ - // CrestronConsole.ConsoleCommandResponse("{0} Version: {1}" + CrestronEnvironment.NewLine, assembly.Name, assembly.Version); - //} - } - /// - /// Moves any .dll assemblies not already loaded from the plugins folder to loadedPlugins folder - /// - static void MoveDllAssemblies() - { - Debug.LogMessage(LogEventLevel.Information, "Looking for .dll assemblies from plugins folder..."); - - var pluginDi = new DirectoryInfo(_pluginDirectory); - var pluginFiles = pluginDi.GetFiles("*.dll"); - - if (pluginFiles.Length > 0) - { - if (!Directory.Exists(_loadedPluginsDirectoryPath)) - { - Directory.CreateDirectory(_loadedPluginsDirectoryPath); - } - } - - foreach (var pluginFile in pluginFiles) - { - try - { - Debug.LogMessage(LogEventLevel.Information, "Found .dll: {0}", pluginFile.Name); - - if (!CheckIfAssemblyLoaded(pluginFile.Name)) - { - string filePath = string.Empty; - - filePath = _loadedPluginsDirectoryPath + Global.DirectorySeparator + pluginFile.Name; - - // Check if there is a previous file in the loadedPlugins directory and delete - if (File.Exists(filePath)) - { - Debug.LogMessage(LogEventLevel.Information, "Found existing file in loadedPlugins: {0} Deleting and moving new file to replace it", filePath); - File.Delete(filePath); - } - - // Move the file - File.Move(pluginFile.FullName, filePath); - Debug.LogMessage(LogEventLevel.Verbose, "Moved {0} to {1}", pluginFile.FullName, filePath); - } - else - { - Debug.LogMessage(LogEventLevel.Information, "Skipping assembly: {0}. There is already an assembly with that name loaded.", pluginFile.FullName); - } - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Verbose, "Error with plugin file {0} . Exception: {1}", pluginFile.FullName, e); - continue; //catching any load issues and continuing. There will be exceptions loading Crestron .dlls from the cplz Probably should do something different here - } - } - - Debug.LogMessage(LogEventLevel.Information, "Done with .dll assemblies"); - } - - /// - /// Unzips each .cplz archive into the temp directory and moves any unloaded files into loadedPlugins - /// - static void UnzipAndMoveCplzArchives() - { - Debug.LogMessage(LogEventLevel.Information, "Looking for .cplz archives from user folder..."); - //var di = new DirectoryInfo(_pluginDirectory); - //var zFiles = di.GetFiles("*.cplz"); - - //// Find cplz files at the root of the user folder. Makes development/testing easier for VC-4, and helps with mistakes by end users - - //var userDi = new DirectoryInfo(Global.FilePathPrefix); - //var userZFiles = userDi.GetFiles("*.cplz"); - - Debug.LogInformation("Checking {folder} for .cplz files", Global.FilePathPrefix); - var cplzFiles = Directory.GetFiles(Global.FilePathPrefix, "*.cplz", SearchOption.AllDirectories) - .Select(f => new FileInfo(f)) - .ToArray(); - - if (cplzFiles.Length > 0) - { - if (!Directory.Exists(_loadedPluginsDirectoryPath)) - { - Directory.CreateDirectory(_loadedPluginsDirectoryPath); - } - } - - foreach (var zfi in cplzFiles) - { - Directory.CreateDirectory(_tempDirectory); - var tempDi = new DirectoryInfo(_tempDirectory); - - Debug.LogMessage(LogEventLevel.Information, "Found cplz: {0}. Unzipping into temp plugins directory", zfi.FullName); - var result = CrestronZIP.Unzip(zfi.FullName, tempDi.FullName); - Debug.LogMessage(LogEventLevel.Information, "UnZip Result: {0}", result.ToString()); - - var tempFiles = tempDi.GetFiles("*.dll"); - foreach (var tempFile in tempFiles) - { - try - { - if (!CheckIfAssemblyLoaded(tempFile.Name)) - { - string filePath = string.Empty; - - filePath = _loadedPluginsDirectoryPath + Global.DirectorySeparator + tempFile.Name; - - // Check if there is a previous file in the loadedPlugins directory and delete - if (File.Exists(filePath)) - { - Debug.LogMessage(LogEventLevel.Information, "Found existing file in loadedPlugins: {0} Deleting and moving new file to replace it", filePath); - File.Delete(filePath); - } - - // Move the file - File.Move(tempFile.FullName, filePath); - Debug.LogMessage(LogEventLevel.Verbose, "Moved {0} to {1}", tempFile.FullName, filePath); - } - else - { - Debug.LogMessage(LogEventLevel.Information, "Skipping assembly: {0}. There is already an assembly with that name loaded.", tempFile.FullName); - } - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Verbose, "Assembly {0} is not a custom assembly. Exception: {1}", tempFile.FullName, e); - continue; //catching any load issues and continuing. There will be exceptions loading Crestron .dlls from the cplz Probably should do something different here - } - } - - // Delete the .cplz and the temp directory - Directory.Delete(_tempDirectory, true); - zfi.Delete(); - } - - Debug.LogMessage(LogEventLevel.Information, "Done with .cplz archives"); - } - - /// - /// Attempts to load the assemblies from the loadedPlugins folder - /// - static void LoadPluginAssemblies() - { - Debug.LogMessage(LogEventLevel.Information, "Loading assemblies from loadedPlugins folder..."); - var pluginDi = new DirectoryInfo(_loadedPluginsDirectoryPath); - var pluginFiles = pluginDi.GetFiles("*.dll"); - - Debug.LogMessage(LogEventLevel.Verbose, "Found {0} plugin assemblies to load", pluginFiles.Length); - - foreach (var pluginFile in pluginFiles) - { - var loadedAssembly = LoadAssembly(pluginFile.FullName); - - LoadedPluginFolderAssemblies.Add(loadedAssembly); - } - - Debug.LogMessage(LogEventLevel.Information, "All Plugins Loaded."); - } - - /// - /// Iterate the loaded assemblies and try to call the LoadPlugin method - /// - static void LoadCustomPluginTypes() - { - Debug.LogMessage(LogEventLevel.Information, "Loading Custom Plugin Types..."); - foreach (var loadedAssembly in LoadedPluginFolderAssemblies) - { - // iteratate this assembly's classes, looking for "LoadPlugin()" methods - try - { - var assy = loadedAssembly.Assembly; - Type[] types = {}; - try - { - types = assy.GetTypes(); - Debug.LogMessage(LogEventLevel.Debug, $"Got types for assembly {assy.GetName().Name}"); - } - catch (TypeLoadException e) - { - Debug.LogMessage(LogEventLevel.Error, "Unable to get types for assembly {0}: {1}", - loadedAssembly.Name, e.Message); - Debug.LogMessage(LogEventLevel.Verbose, e.StackTrace); - continue; - } - - foreach (var type in types) - { - try - { - if (typeof (IPluginDeviceFactory).IsAssignableFrom(type) && !type.IsAbstract) - { - var plugin = - (IPluginDeviceFactory)Activator.CreateInstance(type); - LoadCustomPlugin(plugin, loadedAssembly); - } - } - catch (NotSupportedException) - { - //this happens for dlls that aren't PD dlls, like ports of Mono classes into S#. Swallowing. - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Error, "Load Plugin not found. {0}.{2} is not a plugin factory. Exception: {1}", - loadedAssembly.Name, e.Message, type.Name); - continue; - } - - } - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Information, "Error Loading assembly {0}: {1}", - loadedAssembly.Name, e.Message); - Debug.LogMessage(LogEventLevel.Verbose, "{0}", e.StackTrace); - continue; - } - } - // plugin dll will be loaded. Any classes in plugin should have a static constructor - // that registers that class with the Core.DeviceFactory - Debug.LogMessage(LogEventLevel.Information, "Done Loading Custom Plugin Types."); - } - - /// - /// Loads a - /// - /// - /// - static void LoadCustomPlugin(IPluginDeviceFactory plugin, LoadedAssembly loadedAssembly) - { - var developmentPlugin = plugin as IPluginDevelopmentDeviceFactory; - - var passed = developmentPlugin != null ? Global.IsRunningDevelopmentVersion - (developmentPlugin.DevelopmentEssentialsFrameworkVersions, developmentPlugin.MinimumEssentialsFrameworkVersion) - : Global.IsRunningMinimumVersionOrHigher(plugin.MinimumEssentialsFrameworkVersion); - - if (!passed) - { - Debug.LogMessage(LogEventLevel.Information, - "\r\n********************\r\n\tPlugin indicates minimum Essentials version {0}. Dependency check failed. Skipping Plugin {1}\r\n********************", - plugin.MinimumEssentialsFrameworkVersion, loadedAssembly.Name); - return; - } - else - { - Debug.LogMessage(LogEventLevel.Information, "Passed plugin passed dependency check (required version {0})", plugin.MinimumEssentialsFrameworkVersion); - } - - Debug.LogMessage(LogEventLevel.Information, "Loading plugin: {0}", loadedAssembly.Name); - plugin.LoadTypeFactories(); - - if(!EssentialsPluginAssemblies.Contains(loadedAssembly)) - EssentialsPluginAssemblies.Add(loadedAssembly); - } - - /// - /// Loads a a custom plugin via the legacy method - /// - /// - /// - static void LoadCustomLegacyPlugin(Type type, MethodInfo loadPlugin, LoadedAssembly loadedAssembly) - { - Debug.LogMessage(LogEventLevel.Verbose, "LoadPlugin method found in {0}", type.Name); - - var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static); - - var minimumVersion = fields.FirstOrDefault(p => p.Name.Equals("MinimumEssentialsFrameworkVersion")); - if (minimumVersion != null) - { - Debug.LogMessage(LogEventLevel.Verbose, "MinimumEssentialsFrameworkVersion found"); - - var minimumVersionString = minimumVersion.GetValue(null) as string; - - if (!string.IsNullOrEmpty(minimumVersionString)) - { - var passed = Global.IsRunningMinimumVersionOrHigher(minimumVersionString); - - if (!passed) - { - Debug.LogMessage(LogEventLevel.Information, "Plugin indicates minimum Essentials version {0}. Dependency check failed. Skipping Plugin", minimumVersionString); - return; - } - else - { - Debug.LogMessage(LogEventLevel.Information, "Passed plugin passed dependency check (required version {0})", minimumVersionString); - } - } - else - { - Debug.LogMessage(LogEventLevel.Information, "MinimumEssentialsFrameworkVersion found but not set. Loading plugin, but your mileage may vary."); - } - } - else - { - Debug.LogMessage(LogEventLevel.Information, "MinimumEssentialsFrameworkVersion not found. Loading plugin, but your mileage may vary."); - } - - Debug.LogMessage(LogEventLevel.Information, "Loading legacy plugin: {0}", loadedAssembly.Name); - loadPlugin.Invoke(null, null); - - } - - /// - /// Loads plugins - /// - public static void LoadPlugins() - { - Debug.LogMessage(LogEventLevel.Information, "Attempting to Load Plugins from {_pluginDirectory}", _pluginDirectory); - - if (Directory.Exists(_pluginDirectory)) - { - Debug.LogMessage(LogEventLevel.Information, "Plugins directory found, checking for plugins"); - - // Deal with any .dll files - MoveDllAssemblies(); - - // Deal with any .cplz files - UnzipAndMoveCplzArchives(); - - if (Directory.Exists(_loadedPluginsDirectoryPath)) - { - // Load the assemblies from the loadedPlugins folder into the AppDomain - LoadPluginAssemblies(); - - // Load the types from any custom plugin assemblies - LoadCustomPluginTypes(); - } - } - } - - } - - /// - /// Represents an assembly loaded at runtime and it's associated metadata - /// - public class LoadedAssembly - { - [JsonProperty("name")] - public string Name { get; private set; } - [JsonProperty("version")] - public string Version { get; private set; } - [JsonIgnore] - public Assembly Assembly { get; private set; } - - public LoadedAssembly(string name, string version, Assembly assembly) - { - Name = name; - Version = version; - Assembly = assembly; - } - - public void SetAssembly(Assembly assembly) - { - Assembly = assembly; - } - } -} \ No newline at end of file +using System; +using System.Collections.Generic; +using System.Linq; +using Crestron.SimplSharp; +using System.Reflection; +using System.IO; +using System.Reflection.PortableExecutable; +using System.Reflection.Metadata; + +using PepperDash.Core; +using PepperDash.Essentials.Core; +using Serilog.Events; + + +namespace PepperDash.Essentials; +/// +/// Provides functionality for loading and managing plugins and assemblies in the application. +/// +/// The class is responsible for discovering, loading, and managing assemblies +/// and plugins, including handling compatibility checks for .NET 8. It supports loading assemblies from the program +/// directory, plugins folder, and .cplz archives. Additionally, it tracks incompatible plugins and provides reporting +/// capabilities for loaded assemblies and their versions. +public static class PluginLoader +{ + /// + /// Gets the list of assemblies that have been loaded into the application. + /// + public static List LoadedAssemblies { get; private set; } + + /// + /// Represents a collection of assemblies loaded from the plugin folder. + /// + /// This field is used to store assemblies that have been dynamically loaded from a designated + /// plugin folder. It is intended for internal use and should not be modified directly. + private static readonly List LoadedPluginFolderAssemblies; + + /// + /// Gets the list of plugins that are incompatible with the current system or configuration. + /// + /// This property provides information about plugins that are not supported or cannot function + /// correctly in the current environment. Use this list to identify and handle incompatible plugins appropriately in + /// your application logic. + public static List IncompatiblePlugins { get; private set; } + + /// + /// Gets the loaded assembly that contains the core functionality of the application. + /// + public static LoadedAssembly EssentialsAssembly { get; private set; } + + /// + /// Gets the loaded assembly information for the PepperDash Core library. + /// + public static LoadedAssembly PepperDashCoreAssembly { get; private set; } + + /// + /// Gets the list of assemblies that are Essentials plugins loaded by the application. + /// + public static List EssentialsPluginAssemblies { get; private set; } + + /// + /// Gets the directory path where plugins are stored. + /// + private static string PluginDirectory => Global.FilePathPrefix + "plugins"; + + /// + /// Gets the directory path where loaded plugin assemblies are stored. + /// + private static string LoadedPluginsDirectoryPath => PluginDirectory + Global.DirectorySeparator + "loadedAssemblies"; + + /// + /// Gets the path to the temporary directory used by the plugin. + /// + private static string TempDirectory => PluginDirectory + Global.DirectorySeparator + "temp"; + + /// + /// Represents a collection of fully qualified type names that are known to be incompatible with the current + /// application or framework. + /// + /// This collection contains the names of types that are deprecated, obsolete, or otherwise + /// incompatible with the intended usage of the application. These types may represent security risks, unsupported + /// features, or legacy APIs that should be avoided. + private static readonly HashSet KnownIncompatibleTypes = + [ + "System.Net.ICertificatePolicy", + "System.Security.Cryptography.SHA1CryptoServiceProvider", + "System.Web.HttpUtility", + "System.Configuration.ConfigurationManager", + "System.Web.Services.Protocols.SoapHttpClientProtocol", + "System.Runtime.Remoting", + "System.EnterpriseServices", + "System.Runtime.Serialization.Formatters.Binary.BinaryFormatter", + "System.Security.SecurityManager", + "System.Security.Permissions.FileIOPermission", + "System.AppDomain.CreateDomain" + ]; + + /// + /// Initializes static members of the class. + /// + /// This static constructor initializes the collections used to manage plugin assemblies and + /// track incompatible plugins. + static PluginLoader() + { + LoadedAssemblies = []; + LoadedPluginFolderAssemblies = []; + EssentialsPluginAssemblies = []; + IncompatiblePlugins = []; + } + + /// + /// Loads and registers assemblies from the application's directory that match specific naming patterns. + /// + /// This method scans the application's directory for assemblies with filenames containing + /// "Essentials" or "PepperDash" and registers them in the collection. It also + /// assigns specific assemblies to predefined properties, such as and , based on their names. Debug messages are logged at various stages to provide + /// detailed information about the process, including the number of assemblies found and their versions. This + /// method is intended to be used during application initialization to ensure required assemblies are loaded and + /// tracked. + public static void AddProgramAssemblies() + { + Debug.LogMessage(LogEventLevel.Verbose, "Getting Assemblies loaded with Essentials"); + // Get the loaded assembly filenames + var appDi = new DirectoryInfo(Global.ApplicationDirectoryPathPrefix); + var assemblyFiles = appDi.GetFiles("*.dll"); + + Debug.LogMessage(LogEventLevel.Verbose, "Found {0} Assemblies", assemblyFiles.Length); + + foreach (var fi in assemblyFiles.Where(fi => fi.Name.Contains("Essentials") || fi.Name.Contains("PepperDash"))) + { + string version = string.Empty; + Assembly assembly = null; + + switch (fi.Name) + { + case ("PepperDashEssentials.dll"): + { + version = Global.AssemblyVersion; + EssentialsAssembly = new LoadedAssembly(fi.Name, version, assembly); + break; + } + case ("PepperDash_Essentials_Core.dll"): + { + version = Global.AssemblyVersion; + break; + } + case ("Essentials Devices Common.dll"): + { + version = Global.AssemblyVersion; + break; + } + case ("PepperDashCore.dll"): + { + Debug.LogMessage(LogEventLevel.Verbose, "Found PepperDash_Core.dll"); + version = Debug.PepperDashCoreVersion; + Debug.LogMessage(LogEventLevel.Verbose, "PepperDash_Core Version: {0}", version); + PepperDashCoreAssembly = new LoadedAssembly(fi.Name, version, assembly); + break; + } + } + + LoadedAssemblies.Add(new LoadedAssembly(fi.Name, version, assembly)); + } + + if (Debug.Level > 1) + { + Debug.LogMessage(LogEventLevel.Verbose, "Loaded Assemblies:"); + + foreach (var assembly in LoadedAssemblies) + { + Debug.LogMessage(LogEventLevel.Verbose, "Assembly: {0}", assembly.Name); + } + } + } + + /// + /// Associates the specified assembly with the given name in the loaded assemblies collection. + /// + /// If an assembly with the specified name already exists in the loaded assemblies collection, + /// this method updates its associated assembly. If no matching name is found, the method does nothing. + /// The name used to identify the assembly. This value is case-sensitive and must not be null or empty. + /// The assembly to associate with the specified name. This value must not be null. + public static void AddLoadedAssembly(string name, Assembly assembly) + { + var loadedAssembly = LoadedAssemblies.FirstOrDefault(la => la.Name.Equals(name)); + + loadedAssembly?.SetAssembly(assembly); + } + + /// + /// Determines whether a plugin assembly is compatible with .NET 8. + /// + /// This method analyzes the provided assembly to determine compatibility with .NET 8 by checking + /// for known incompatible types, inspecting custom attributes, and collecting assembly references. If the analysis + /// encounters an error, the method returns with an appropriate error message. + /// The file path to the plugin assembly to analyze. + /// A tuple containing the following: if the plugin + /// is compatible with .NET 8; otherwise, . A + /// string providing the reason for incompatibility, or if the plugin is + /// compatible. A list of assembly references found in the + /// plugin. + public static (bool IsCompatible, string Reason, List References) IsPluginCompatibleWithNet8(string filePath) + { + try + { + List referencedAssemblies = []; + + using FileStream fs = new(filePath, FileMode.Open, + FileAccess.Read, FileShare.ReadWrite); + using PEReader peReader = new(fs); + + if (!peReader.HasMetadata) + return (false, "Not a valid .NET assembly", referencedAssemblies); + + MetadataReader metadataReader = peReader.GetMetadataReader(); + + // Collect assembly references + foreach (var assemblyRefHandle in metadataReader.AssemblyReferences) + { + var assemblyRef = metadataReader.GetAssemblyReference(assemblyRefHandle); + string assemblyName = metadataReader.GetString(assemblyRef.Name); + referencedAssemblies.Add(assemblyName); + } + + // Check for references to known incompatible types + foreach (var typeRefHandle in metadataReader.TypeReferences) + { + var typeRef = metadataReader.GetTypeReference(typeRefHandle); + string typeNamespace = metadataReader.GetString(typeRef.Namespace); + string typeName = metadataReader.GetString(typeRef.Name); + + string fullTypeName = $"{typeNamespace}.{typeName}"; + if (KnownIncompatibleTypes.Contains(fullTypeName)) + { + return (false, $"Uses incompatible type: {fullTypeName}", referencedAssemblies); + } + } + + // Check for explicit .NET 8 compatibility attribute + bool hasNet8Attribute = false; + foreach (var customAttributeHandle in metadataReader.GetAssemblyDefinition().GetCustomAttributes()) + { + var customAttribute = metadataReader.GetCustomAttribute(customAttributeHandle); + var ctorHandle = customAttribute.Constructor; + + if (ctorHandle.Kind == HandleKind.MemberReference) + { + var memberRef = metadataReader.GetMemberReference((MemberReferenceHandle)ctorHandle); + var typeRef = metadataReader.GetTypeReference((TypeReferenceHandle)memberRef.Parent); + + string typeName = metadataReader.GetString(typeRef.Name); + if (typeName == "Net8CompatibleAttribute" || typeName == "TargetFrameworkAttribute") + { + hasNet8Attribute = true; + break; + } + } + } + + if (hasNet8Attribute) + { + return (true, null, referencedAssemblies); + } + + // If we can't determine incompatibility, assume it's compatible + return (true, null, referencedAssemblies); + } + catch (Exception ex) + { + return (false, $"Error analyzing assembly: {ex.Message}", new List()); + } + } + + /// + /// Loads an assembly from the specified file path and verifies its compatibility with .NET 8. + /// + /// This method performs a compatibility check to ensure the assembly is compatible with .NET 8 + /// before attempting to load it. If the assembly is incompatible, it is added to the list of incompatible plugins, + /// and a warning is logged. If the assembly is already loaded, the existing instance is returned instead of + /// reloading it. Exceptions during the load process are handled internally, and appropriate log messages are + /// generated for issues such as: Incompatibility with .NET + /// 8. File load conflicts (e.g., an assembly with the same name is already + /// loaded). General errors, including potential .NET Framework + /// compatibility issues. + /// The full path to the assembly file to load. This cannot be null or empty. + /// An optional identifier for the entity requesting the load operation. This can be null. + /// A object representing the loaded assembly if the operation succeeds; otherwise, + /// . + private static LoadedAssembly LoadAssembly(string filePath, string requestedBy = null) + { + try + { + // Check .NET 8 compatibility before loading + var (isCompatible, reason, references) = IsPluginCompatibleWithNet8(filePath); + if (!isCompatible) + { + string fileName = Path.GetFileName(filePath); + Debug.LogMessage(LogEventLevel.Warning, "Assembly '{0}' is not compatible with .NET 8: {1}", fileName, reason); + + var incompatiblePlugin = new IncompatiblePlugin(fileName, reason, requestedBy); + IncompatiblePlugins.Add(incompatiblePlugin); + return null; + } + + var assembly = Assembly.LoadFrom(filePath); + if (assembly != null) + { + var assyVersion = GetAssemblyVersion(assembly); + var loadedAssembly = new LoadedAssembly(assembly.GetName().Name, assyVersion, assembly); + LoadedAssemblies.Add(loadedAssembly); + Debug.LogMessage(LogEventLevel.Information, "Loaded assembly '{0}', version {1}", loadedAssembly.Name, loadedAssembly.Version); + return loadedAssembly; + } + else + { + Debug.LogMessage(LogEventLevel.Information, "Unable to load assembly: '{0}'", filePath); + } + return null; + } + catch(FileLoadException ex) when (ex.Message.Contains("Assembly with same name is already loaded")) + { + // Get the assembly name from the file path + string assemblyName = Path.GetFileNameWithoutExtension(filePath); + + // Try to find the already loaded assembly + var existingAssembly = AppDomain.CurrentDomain.GetAssemblies() + .FirstOrDefault(a => a.GetName().Name.Equals(assemblyName, StringComparison.OrdinalIgnoreCase)); + + if (existingAssembly != null) + { + Debug.LogMessage(LogEventLevel.Information, "Assembly '{0}' is already loaded, using existing instance", assemblyName); + var assyVersion = GetAssemblyVersion(existingAssembly); + var loadedAssembly = new LoadedAssembly(existingAssembly.GetName().Name, assyVersion, existingAssembly); + LoadedAssemblies.Add(loadedAssembly); + return loadedAssembly; + } + + Debug.LogMessage(LogEventLevel.Warning, "Assembly with same name already loaded but couldn't find it: {0}", filePath); + return null; + } + catch(Exception ex) + { + string fileName = Path.GetFileName(filePath); + + // Check if this might be a .NET Framework compatibility issue + if (ex.Message.Contains("Could not load type") || + ex.Message.Contains("Unable to load one or more of the requested types")) + { + Debug.LogMessage(LogEventLevel.Error, "Error loading assembly {0}: Likely .NET 8 compatibility issue: {1}", + fileName, ex.Message); + IncompatiblePlugins.Add(new IncompatiblePlugin(fileName, ex.Message, requestedBy)); + } + else + { + Debug.LogMessage(ex, "Error loading assembly from {path}", null, filePath); + } + return null; + } + } + + /// + /// Retrieves the version information of the specified assembly. + /// + /// This method first attempts to retrieve the version from the . If the attribute is not present, it falls back to the assembly's + /// version as defined in its metadata. + /// The assembly from which to retrieve the version information. Cannot be . + /// A string representing the version of the assembly. If the assembly has an , its value is returned. Otherwise, the assembly's + /// version is returned in the format "Major.Minor.Build.Revision". + public static string GetAssemblyVersion(Assembly assembly) + { + var ver = assembly.GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false); + if (ver != null && ver.Length > 0) + { + // Get the AssemblyInformationalVersion + AssemblyInformationalVersionAttribute verAttribute = ver[0] as AssemblyInformationalVersionAttribute; + return verAttribute.InformationalVersion; + } + else + { + // Get the AssemblyVersion + var version = assembly.GetName().Version; + var verStr = string.Format("{0}.{1}.{2}.{3}", version.Major, version.Minor, version.Build, version.Revision); + return verStr; + } + } + + /// + /// Determines whether an assembly with the specified name is currently loaded. + /// + /// This method performs a case-sensitive comparison to determine if the specified assembly is + /// loaded. It logs verbose messages indicating the status of the check. + /// The name of the assembly to check. This value is case-sensitive. + /// if an assembly with the specified name is loaded; otherwise, . + public static bool CheckIfAssemblyLoaded(string name) + { + Debug.LogMessage(LogEventLevel.Verbose, "Checking if assembly: {0} is loaded...", name); + var loadedAssembly = LoadedAssemblies.FirstOrDefault(s => s.Name.Equals(name)); + + if (loadedAssembly != null) + { + Debug.LogMessage(LogEventLevel.Verbose, "Assembly already loaded."); + return true; + } + else + { + Debug.LogMessage(LogEventLevel.Verbose, "Assembly not loaded."); + return false; + } + } + + /// + /// Reports the versions of the Essentials framework, PepperDash Core, and loaded plugins to the console. + /// + /// This method outputs version information for the Essentials framework, PepperDash Core, and + /// all loaded Essentials plugins to the Crestron console. If any incompatible plugins are detected, their details + /// are also reported, including the reason for incompatibility and the plugin that required them, if + /// applicable. + /// The command string that triggered the version report. This parameter is not used directly by the method. + public static void ReportAssemblyVersions(string command) + { + CrestronConsole.ConsoleCommandResponse("Essentials Version: {0}" + CrestronEnvironment.NewLine, Global.AssemblyVersion); + CrestronConsole.ConsoleCommandResponse("PepperDash Core Version: {0}" + CrestronEnvironment.NewLine, PepperDashCoreAssembly.Version); + CrestronConsole.ConsoleCommandResponse("Essentials Plugin Versions:" + CrestronEnvironment.NewLine); + foreach (var assembly in EssentialsPluginAssemblies) + { + CrestronConsole.ConsoleCommandResponse("{0} Version: {1}" + CrestronEnvironment.NewLine, assembly.Name, assembly.Version); + } + + if (IncompatiblePlugins.Count > 0) + { + CrestronConsole.ConsoleCommandResponse("Incompatible Plugins:" + CrestronEnvironment.NewLine); + foreach (var plugin in IncompatiblePlugins) + { + if (plugin.TriggeredBy != "Direct load") + { + CrestronConsole.ConsoleCommandResponse("{0}: {1} (Required by: {2})" + CrestronEnvironment.NewLine, + plugin.Name, plugin.Reason, plugin.TriggeredBy); + } + else + { + CrestronConsole.ConsoleCommandResponse("{0}: {1}" + CrestronEnvironment.NewLine, + plugin.Name, plugin.Reason); + } + } + } + } + + /// + /// Moves .dll assemblies from the plugins folder to the loaded plugins directory. + /// + /// This method scans the plugins folder for .dll files and moves them to the loaded plugins + /// directory if they are not already loaded. If a file with the same name exists in the target directory, it is + /// replaced. The method logs the process at various stages and handles exceptions for individual files to ensure + /// the operation continues for other files. + private static void MoveDllAssemblies() + { + Debug.LogMessage(LogEventLevel.Information, "Looking for .dll assemblies from plugins folder..."); + + var pluginDi = new DirectoryInfo(PluginDirectory); + var pluginFiles = pluginDi.GetFiles("*.dll"); + + if (pluginFiles.Length > 0) + { + if (!Directory.Exists(LoadedPluginsDirectoryPath)) + { + Directory.CreateDirectory(LoadedPluginsDirectoryPath); + } + } + + foreach (var pluginFile in pluginFiles) + { + try + { + Debug.LogMessage(LogEventLevel.Information, "Found .dll: {0}", pluginFile.Name); + + if (!CheckIfAssemblyLoaded(pluginFile.Name)) + { + string filePath = string.Empty; + + filePath = LoadedPluginsDirectoryPath + Global.DirectorySeparator + pluginFile.Name; + + // Check if there is a previous file in the loadedPlugins directory and delete + if (File.Exists(filePath)) + { + Debug.LogMessage(LogEventLevel.Information, "Found existing file in loadedPlugins: {0} Deleting and moving new file to replace it", filePath); + File.Delete(filePath); + } + + // Move the file + File.Move(pluginFile.FullName, filePath); + Debug.LogMessage(LogEventLevel.Verbose, "Moved {0} to {1}", pluginFile.FullName, filePath); + } + else + { + Debug.LogMessage(LogEventLevel.Information, "Skipping assembly: {0}. There is already an assembly with that name loaded.", pluginFile.FullName); + } + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Verbose, "Error with plugin file {0} . Exception: {1}", pluginFile.FullName, e); + continue; //catching any load issues and continuing. There will be exceptions loading Crestron .dlls from the cplz Probably should do something different here + } + } + + Debug.LogMessage(LogEventLevel.Information, "Done with .dll assemblies"); + } + + /// + /// Extracts and processes .cplz archive files found in the specified directories, moving their contents to the + /// appropriate plugin directory. + /// + /// This method searches for .cplz files in the plugin directory and user folder, extracts their + /// contents, and moves any .dll files to the loaded plugins directory. If a .dll file with the same name already + /// exists in the target directory, it is replaced with the new file. Temporary files and directories created during + /// the process are cleaned up after the operation completes. + private static void UnzipAndMoveCplzArchives() + { + Debug.LogMessage(LogEventLevel.Information, "Looking for .cplz archives from plugins folder..."); + var di = new DirectoryInfo(PluginDirectory); + var zFiles = di.GetFiles("*.cplz"); + + //// Find cplz files at the root of the user folder. Makes development/testing easier for VC-4, and helps with mistakes by end users + + //var userDi = new DirectoryInfo(Global.FilePathPrefix); + //var userZFiles = userDi.GetFiles("*.cplz"); + + Debug.LogInformation("Checking {folder} for .cplz files", Global.FilePathPrefix); + var cplzFiles = Directory.GetFiles(Global.FilePathPrefix, "*.cplz", SearchOption.AllDirectories) + .Select(f => new FileInfo(f)) + .ToArray(); + + if (cplzFiles.Length > 0) + { + if (!Directory.Exists(LoadedPluginsDirectoryPath)) + { + Directory.CreateDirectory(LoadedPluginsDirectoryPath); + } + } + + foreach (var zfi in cplzFiles) + { + Directory.CreateDirectory(TempDirectory); + var tempDi = new DirectoryInfo(TempDirectory); + + Debug.LogMessage(LogEventLevel.Information, "Found cplz: {0}. Unzipping into temp plugins directory", zfi.FullName); + var result = CrestronZIP.Unzip(zfi.FullName, tempDi.FullName); + Debug.LogMessage(LogEventLevel.Information, "UnZip Result: {0}", result.ToString()); + + var tempFiles = tempDi.GetFiles("*.dll"); + foreach (var tempFile in tempFiles) + { + try + { + if (!CheckIfAssemblyLoaded(tempFile.Name)) + { + string filePath = string.Empty; + + filePath = LoadedPluginsDirectoryPath + Global.DirectorySeparator + tempFile.Name; + + // Check if there is a previous file in the loadedPlugins directory and delete + if (File.Exists(filePath)) + { + Debug.LogMessage(LogEventLevel.Information, "Found existing file in loadedPlugins: {0} Deleting and moving new file to replace it", filePath); + File.Delete(filePath); + } + + // Move the file + File.Move(tempFile.FullName, filePath); + Debug.LogMessage(LogEventLevel.Verbose, "Moved {0} to {1}", tempFile.FullName, filePath); + } + else + { + Debug.LogMessage(LogEventLevel.Information, "Skipping assembly: {0}. There is already an assembly with that name loaded.", tempFile.FullName); + } + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Verbose, "Assembly {0} is not a custom assembly. Exception: {1}", tempFile.FullName, e); + continue; //catching any load issues and continuing. There will be exceptions loading Crestron .dlls from the cplz Probably should do something different here + } + } + + // Delete the .cplz and the temp directory + Directory.Delete(TempDirectory, true); + zfi.Delete(); + } + + Debug.LogMessage(LogEventLevel.Information, "Done with .cplz archives"); + } + + /// + /// Loads plugin assemblies from the designated plugin directory, checks their compatibility with .NET 8, and loads + /// the compatible assemblies into the application. + /// + /// This method scans the plugin directory for all `.dll` files, verifies their compatibility + /// with .NET 8, and attempts to load the compatible assemblies. Assemblies that are incompatible are logged as + /// warnings and added to a list of incompatible plugins for further inspection. + private static void LoadPluginAssemblies() + { + Debug.LogMessage(LogEventLevel.Information, "Loading assemblies from loadedPlugins folder..."); + var pluginDi = new DirectoryInfo(LoadedPluginsDirectoryPath); + var pluginFiles = pluginDi.GetFiles("*.dll"); + + Debug.LogMessage(LogEventLevel.Verbose, "Found {0} plugin assemblies to load", pluginFiles.Length); + + // First, check compatibility of all assemblies before loading any + var assemblyCompatibility = new Dictionary References)>(); + + foreach (var pluginFile in pluginFiles) + { + string fileName = pluginFile.Name; + assemblyCompatibility[fileName] = IsPluginCompatibleWithNet8(pluginFile.FullName); + } + + // Now load compatible assemblies and track incompatible ones + foreach (var pluginFile in pluginFiles) + { + string fileName = pluginFile.Name; + var (isCompatible, reason, _) = assemblyCompatibility[fileName]; + + if (!isCompatible) + { + Debug.LogMessage(LogEventLevel.Warning, "Assembly '{0}' is not compatible with .NET 8: {1}", fileName, reason); + IncompatiblePlugins.Add(new IncompatiblePlugin(fileName, reason, null)); + continue; + } + + // Try to load the assembly + var loadedAssembly = LoadAssembly(pluginFile.FullName, null); + + if (loadedAssembly != null) + { + LoadedPluginFolderAssemblies.Add(loadedAssembly); + } + } + + Debug.LogMessage(LogEventLevel.Information, "All Plugins Loaded."); + } + + /// + /// Loads and initializes custom plugin types from the assemblies in the plugin folder. + /// + /// This method iterates through all loaded plugin assemblies, identifies types that implement + /// the interface, and attempts to instantiate and load them. Assemblies or + /// types that cannot be loaded due to missing dependencies, type loading errors, or other exceptions are logged, + /// and incompatible plugins are tracked for further analysis. + private static void LoadCustomPluginTypes() + { + Debug.LogMessage(LogEventLevel.Information, "Loading Custom Plugin Types..."); + + foreach (var loadedAssembly in LoadedPluginFolderAssemblies) + { + // Skip if assembly is null (can happen if we had loading issues) + if (loadedAssembly == null || loadedAssembly.Assembly == null) + continue; + + // iteratate this assembly's classes, looking for "LoadPlugin()" methods + try + { + var assy = loadedAssembly.Assembly; + Type[] types = []; + try + { + types = assy.GetTypes(); + Debug.LogMessage(LogEventLevel.Debug, $"Got types for assembly {assy.GetName().Name}"); + } + catch (ReflectionTypeLoadException e) + { + Debug.LogMessage(LogEventLevel.Error, "Unable to get types for assembly {0}: {1}", + loadedAssembly.Name, e.Message); + + // Check if any of the loader exceptions are due to missing assemblies + foreach (var loaderEx in e.LoaderExceptions) + { + if (loaderEx is FileNotFoundException fileNotFoundEx) + { + string missingAssembly = fileNotFoundEx.FileName; + if (!string.IsNullOrEmpty(missingAssembly)) + { + Debug.LogMessage(LogEventLevel.Warning, "Assembly {0} requires missing dependency: {1}", + loadedAssembly.Name, missingAssembly); + + // Add to incompatible plugins with dependency information + IncompatiblePlugins.Add(new IncompatiblePlugin( + Path.GetFileName(missingAssembly), + $"Missing dependency required by {loadedAssembly.Name}", + loadedAssembly.Name)); + } + } + } + + Debug.LogMessage(LogEventLevel.Verbose, e.StackTrace); + continue; + } + catch (TypeLoadException e) + { + Debug.LogMessage(LogEventLevel.Error, "Unable to get types for assembly {0}: {1}", + loadedAssembly.Name, e.Message); + Debug.LogMessage(LogEventLevel.Verbose, e.StackTrace); + + // Add to incompatible plugins if this is likely a .NET 8 compatibility issue + if (e.Message.Contains("Could not load type") || + e.Message.Contains("Unable to load one or more of the requested types")) + { + IncompatiblePlugins.Add(new IncompatiblePlugin(loadedAssembly.Name, + $"Type loading error: {e.Message}", + null)); + } + + continue; + } + + foreach (var type in types) + { + try + { + if (!typeof(IPluginDeviceFactory).IsAssignableFrom(type) || type.IsAbstract) + { + continue; + } + + var plugin = (IPluginDeviceFactory)Activator.CreateInstance(type); + LoadCustomPlugin(plugin, loadedAssembly); + } + catch (NotSupportedException) + { + //this happens for dlls that aren't PD dlls, like ports of Mono classes into S#. Swallowing. + } + catch (Exception ex) + { + Debug.LogError("Load Plugin not found. {assemblyName}.{typeName} is not a plugin factory. Exception: {exception}", + loadedAssembly.Name, type.Name, ex.Message); + continue; + } + } + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Information, "Error Loading assembly {0}: {1}", + loadedAssembly.Name, e.Message); + Debug.LogMessage(LogEventLevel.Verbose, "{0}", e.StackTrace); + + // Add to incompatible plugins if this is likely a .NET 8 compatibility issue + if (e.Message.Contains("Could not load type") || + e.Message.Contains("Unable to load one or more of the requested types")) + { + IncompatiblePlugins.Add(new IncompatiblePlugin(loadedAssembly.Name, + $"Assembly loading error: {e.Message}", + null)); + } + + continue; + } + } + + // Update incompatible plugins with dependency information + var pluginDependencies = new Dictionary>(); + // Populate pluginDependencies with relevant data + // Example: pluginDependencies["PluginA"] = new List { "Dependency1", "Dependency2" }; + UpdateIncompatiblePluginDependencies(pluginDependencies); + + // plugin dll will be loaded. Any classes in plugin should have a static constructor + // that registers that class with the Core.DeviceFactory + Debug.LogMessage(LogEventLevel.Information, "Done Loading Custom Plugin Types."); + } + + /// + /// Updates the triggering plugin information for incompatible plugins based on their dependencies. + /// + /// This method iterates through a predefined list of incompatible plugins and updates their + /// triggering plugin information if they were directly loaded and are found to be dependencies of other plugins. + /// The update is performed for the first plugin that depends on the incompatible plugin. + /// A dictionary where the key is the name of a plugin and the value is a list of its dependencies. Each dependency + /// is represented as a string, which may include additional metadata. + private static void UpdateIncompatiblePluginDependencies(Dictionary> pluginDependencies) + { + // For each incompatible plugin + foreach (var incompatiblePlugin in IncompatiblePlugins) + { + // If it already has a requestedBy, skip it + if (incompatiblePlugin.TriggeredBy != "Direct load") + continue; + + // Find plugins that depend on this incompatible plugin + foreach (var plugin in pluginDependencies) + { + string pluginName = plugin.Key; + List dependencies = plugin.Value; + + // If this plugin depends on the incompatible plugin + if (dependencies.Contains(incompatiblePlugin.Name) || + dependencies.Any(d => d.StartsWith(incompatiblePlugin.Name + ","))) + { + incompatiblePlugin.UpdateTriggeringPlugin(pluginName); + break; + } + } + } + } + + /// + /// Loads a custom plugin and performs a dependency check to ensure compatibility with the required Essentials + /// framework version. + /// + /// This method verifies that the plugin meets the minimum required Essentials framework version + /// before loading it. If the plugin fails the dependency check, it is skipped, and a log message is generated. If + /// the plugin passes the check, it is loaded, and its type factories are initialized. + /// The plugin to be loaded, implementing the interface. If the plugin also + /// implements , additional checks for development versions are + /// performed. + /// The assembly associated with the plugin being loaded. This is used for logging and tracking purposes. + private static void LoadCustomPlugin(IPluginDeviceFactory deviceFactory, LoadedAssembly loadedAssembly) + { + var developmentDeviceFactory = deviceFactory as IPluginDevelopmentDeviceFactory; + + var passed = developmentDeviceFactory != null ? Global.IsRunningDevelopmentVersion + (developmentDeviceFactory.DevelopmentEssentialsFrameworkVersions, developmentDeviceFactory.MinimumEssentialsFrameworkVersion) + : Global.IsRunningMinimumVersionOrHigher(deviceFactory.MinimumEssentialsFrameworkVersion); + + if (!passed) + { + Debug.LogInformation( + "\r\n********************\r\n\tPlugin indicates minimum Essentials version {minimumEssentialsVersion}. Dependency check failed. Skipping Plugin {pluginName}\r\n********************", + deviceFactory.MinimumEssentialsFrameworkVersion, loadedAssembly.Name); + return; + } + else + { + Debug.LogInformation("Passed plugin passed dependency check (required version {essentialsMinimumVersion})", deviceFactory.MinimumEssentialsFrameworkVersion); + } + + Debug.LogInformation("Loading plugin: {pluginName}", loadedAssembly.Name); + + LoadDeviceFactories(deviceFactory); + + if(!EssentialsPluginAssemblies.Contains(loadedAssembly)) + EssentialsPluginAssemblies.Add(loadedAssembly); + } + + /// + /// Loads device factories from the specified plugin device factory and registers them for use. + /// + /// This method retrieves metadata from the provided , including + /// type names, descriptions, and configuration snippets, and registers the factory for each device type. The type + /// names are converted to lowercase for registration. + /// The plugin device factory that provides the device types, descriptions, and factory methods to be registered. + private static void LoadDeviceFactories(IPluginDeviceFactory deviceFactory) + { + foreach (var typeName in deviceFactory.TypeNames) + { + //Debug.LogMessage(LogEventLevel.Verbose, "Getting Description Attribute from class: '{0}'", typeof(T).FullName); + var descriptionAttribute = deviceFactory.FactoryType.GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[]; + string description = descriptionAttribute[0].Description; + var snippetAttribute = deviceFactory.FactoryType.GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[]; + DeviceFactory.AddFactoryForType(typeName.ToLower(), description, deviceFactory.FactoryType, deviceFactory.BuildDevice); + } + } + + /// + /// Loads plugins from the designated plugin directory, processes them, and integrates them into the application. + /// + /// This method performs the following steps: Checks if + /// the plugin directory exists. Processes any plugin files, including .dll + /// and .cplz files, by moving or extracting them as needed. Loads + /// assemblies from the processed plugins into the application domain. + /// Identifies and reports any incompatible plugins, including the reason for + /// incompatibility. Plugins that are successfully loaded are made available for use, + /// while incompatible plugins are logged for review. + public static void LoadPlugins() + { + Debug.LogMessage(LogEventLevel.Information, "Attempting to Load Plugins from {_pluginDirectory}", PluginDirectory); + + if (Directory.Exists(PluginDirectory)) + { + Debug.LogMessage(LogEventLevel.Information, "Plugins directory found, checking for plugins"); + + // Deal with any .dll files + MoveDllAssemblies(); + + // Deal with any .cplz files + UnzipAndMoveCplzArchives(); + + if (Directory.Exists(LoadedPluginsDirectoryPath)) + { + // Load the assemblies from the loadedPlugins folder into the AppDomain + LoadPluginAssemblies(); + + // Load the types from any custom plugin assemblies + LoadCustomPluginTypes(); + } + + // Report on incompatible plugins + if (IncompatiblePlugins.Count > 0) + { + Debug.LogMessage(LogEventLevel.Warning, "Found {0} incompatible plugins:", IncompatiblePlugins.Count); + foreach (var plugin in IncompatiblePlugins) + { + if (plugin.TriggeredBy != "Direct load") + { + Debug.LogMessage(LogEventLevel.Warning, " - {0}: {1} (Required by: {2})", + plugin.Name, plugin.Reason, plugin.TriggeredBy); + } + else + { + Debug.LogMessage(LogEventLevel.Warning, " - {0}: {1}", + plugin.Name, plugin.Reason); + } + } + } + } + } +} diff --git a/src/PepperDash.Essentials.Core/Presets/DevicePresets.cs b/src/PepperDash.Essentials.Core/Presets/DevicePresets.cs index 42059c789..7346981b8 100644 --- a/src/PepperDash.Essentials.Core/Presets/DevicePresets.cs +++ b/src/PepperDash.Essentials.Core/Presets/DevicePresets.cs @@ -12,294 +12,293 @@ using PepperDash.Core.WebApi.Presets; using Serilog.Events; -namespace PepperDash.Essentials.Core.Presets +namespace PepperDash.Essentials.Core.Presets; + +/// +/// Class that represents the model behind presets display +/// +public class DevicePresetsModel : Device { - /// - /// Class that represents the model behind presets display - /// - public class DevicePresetsModel : Device - { - public delegate void PresetRecalledCallback(ISetTopBoxNumericKeypad device, string channel); + public delegate void PresetRecalledCallback(ISetTopBoxNumericKeypad device, string channel); - public delegate void PresetsSavedCallback(List presets); + public delegate void PresetsSavedCallback(List presets); - private readonly CCriticalSection _fileOps = new CCriticalSection(); - private readonly bool _initSuccess; + private readonly CCriticalSection _fileOps = new CCriticalSection(); + private readonly bool _initSuccess; - private readonly ISetTopBoxNumericKeypad _setTopBox; + private readonly ISetTopBoxNumericKeypad _setTopBox; - /// - /// The methods on the STB device to call when dialing - /// - private Dictionary> _dialFunctions; + /// + /// The methods on the STB device to call when dialing + /// + private Dictionary> _dialFunctions; - private bool _dialIsRunning; - private Action _enterFunction; - private string _filePath; + private bool _dialIsRunning; + private Action _enterFunction; + private string _filePath; - public DevicePresetsModel(string key, ISetTopBoxNumericKeypad setTopBox, string fileName) - : this(key, fileName) + public DevicePresetsModel(string key, ISetTopBoxNumericKeypad setTopBox, string fileName) + : this(key, fileName) + { + try { - try - { - _setTopBox = setTopBox; + _setTopBox = setTopBox; - // Grab the digit functions from the device - // If any fail, the whole thing fails peacefully - _dialFunctions = new Dictionary>(10) - { - {'1', setTopBox.Digit1}, - {'2', setTopBox.Digit2}, - {'3', setTopBox.Digit3}, - {'4', setTopBox.Digit4}, - {'5', setTopBox.Digit5}, - {'6', setTopBox.Digit6}, - {'7', setTopBox.Digit7}, - {'8', setTopBox.Digit8}, - {'9', setTopBox.Digit9}, - {'0', setTopBox.Digit0}, - {'-', setTopBox.Dash} - }; - } - catch + // Grab the digit functions from the device + // If any fail, the whole thing fails peacefully + _dialFunctions = new Dictionary>(10) { - Debug.LogMessage(LogEventLevel.Information, "DevicePresets '{0}', not attached to INumericKeypad device. Ignoring", key); - _dialFunctions = null; - return; - } - - _enterFunction = setTopBox.KeypadEnter; + {'1', setTopBox.Digit1}, + {'2', setTopBox.Digit2}, + {'3', setTopBox.Digit3}, + {'4', setTopBox.Digit4}, + {'5', setTopBox.Digit5}, + {'6', setTopBox.Digit6}, + {'7', setTopBox.Digit7}, + {'8', setTopBox.Digit8}, + {'9', setTopBox.Digit9}, + {'0', setTopBox.Digit0}, + {'-', setTopBox.Dash} + }; } - - public DevicePresetsModel(string key, string fileName) : base(key) + catch { - PulseTime = 150; - DigitSpacingMs = 150; + Debug.LogMessage(LogEventLevel.Information, "DevicePresets '{0}', not attached to INumericKeypad device. Ignoring", key); + _dialFunctions = null; + return; + } - UseLocalImageStorage = true; + _enterFunction = setTopBox.KeypadEnter; + } - ImagesLocalHostPrefix = "http://" + CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0); - ImagesPathPrefix = @"/presets/images.zip/"; - ListPathPrefix = @"/html/presets/lists/"; + public DevicePresetsModel(string key, string fileName) : base(key) + { + PulseTime = 150; + DigitSpacingMs = 150; - SetFileName(fileName); + UseLocalImageStorage = true; - _initSuccess = true; - } + ImagesLocalHostPrefix = "http://" + CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0); + ImagesPathPrefix = @"/presets/images.zip/"; + ListPathPrefix = @"/html/presets/lists/"; - public event PresetRecalledCallback PresetRecalled; - public event PresetsSavedCallback PresetsSaved; + SetFileName(fileName); - public int PulseTime { get; set; } - public int DigitSpacingMs { get; set; } - public bool PresetsAreLoaded { get; private set; } + _initSuccess = true; + } - public List PresetsList { get; private set; } + public event PresetRecalledCallback PresetRecalled; + public event PresetsSavedCallback PresetsSaved; - public int Count - { - get { return PresetsList != null ? PresetsList.Count : 0; } - } + public int PulseTime { get; set; } + public int DigitSpacingMs { get; set; } + public bool PresetsAreLoaded { get; private set; } - public bool UseLocalImageStorage { get; set; } - public string ImagesLocalHostPrefix { get; set; } - public string ImagesPathPrefix { get; set; } - public string ListPathPrefix { get; set; } - public event EventHandler PresetsLoaded; + public List PresetsList { get; private set; } + public int Count + { + get { return PresetsList != null ? PresetsList.Count : 0; } + } - public void SetFileName(string path) - { - _filePath = ListPathPrefix + path; + public bool UseLocalImageStorage { get; set; } + public string ImagesLocalHostPrefix { get; set; } + public string ImagesPathPrefix { get; set; } + public string ListPathPrefix { get; set; } + public event EventHandler PresetsLoaded; - Debug.LogMessage(LogEventLevel.Verbose, this, "Setting presets file path to {0}", _filePath); - LoadChannels(); - } - public void LoadChannels() + public void SetFileName(string path) + { + _filePath = ListPathPrefix + path; + + Debug.LogMessage(LogEventLevel.Verbose, this, "Setting presets file path to {0}", _filePath); + LoadChannels(); + } + + public void LoadChannels() + { + try { + _fileOps.Enter(); + + Debug.LogMessage(LogEventLevel.Verbose, this, "Loading presets from {0}", _filePath); + PresetsAreLoaded = false; try { - _fileOps.Enter(); - - Debug.LogMessage(LogEventLevel.Verbose, this, "Loading presets from {0}", _filePath); - PresetsAreLoaded = false; - try - { - var pl = JsonConvert.DeserializeObject(File.ReadToEnd(_filePath, Encoding.ASCII)); - Name = pl.Name; - PresetsList = pl.Channels; - - Debug.LogMessage(LogEventLevel.Verbose, this, "Loaded {0} presets", PresetsList.Count); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Verbose, this, - "LoadChannels: Error reading presets file. These presets will be empty:\r '{0}'\r Error:{1}", - _filePath, e.Message); - // Just save a default empty list - PresetsList = new List(); - } - PresetsAreLoaded = true; + var pl = JsonConvert.DeserializeObject(File.ReadToEnd(_filePath, Encoding.ASCII)); + Name = pl.Name; + PresetsList = pl.Channels; - var handler = PresetsLoaded; - if (handler != null) - { - handler(this, EventArgs.Empty); - } + Debug.LogMessage(LogEventLevel.Verbose, this, "Loaded {0} presets", PresetsList.Count); } - finally + catch (Exception e) { - _fileOps.Leave(); + Debug.LogMessage(LogEventLevel.Verbose, this, + "LoadChannels: Error reading presets file. These presets will be empty:\r '{0}'\r Error:{1}", + _filePath, e.Message); + // Just save a default empty list + PresetsList = new List(); } - } + PresetsAreLoaded = true; - public void Dial(int presetNum) - { - if (presetNum <= PresetsList.Count) + var handler = PresetsLoaded; + if (handler != null) { - Dial(PresetsList[presetNum - 1].Channel); + handler(this, EventArgs.Empty); } } - - public void Dial(string chanNum) + finally { - if (_dialIsRunning || !_initSuccess) - { - return; - } - if (_dialFunctions == null) - { - Debug.LogMessage(LogEventLevel.Debug, "DevicePresets '{0}', not attached to keypad device. Ignoring channel", Key); - return; - } - - _dialIsRunning = true; - CrestronInvoke.BeginInvoke(o => - { - foreach (var c in chanNum.ToCharArray()) - { - if (_dialFunctions.ContainsKey(c)) - { - Pulse(_dialFunctions[c]); - } - CrestronEnvironment.Sleep(DigitSpacingMs); - } - - if (_enterFunction != null) - { - Pulse(_enterFunction); - } - _dialIsRunning = false; - }); + _fileOps.Leave(); + } + } - if (_setTopBox == null) return; + public void Dial(int presetNum) + { + if (presetNum <= PresetsList.Count) + { + Dial(PresetsList[presetNum - 1].Channel); + } + } - OnPresetRecalled(_setTopBox, chanNum); + public void Dial(string chanNum) + { + if (_dialIsRunning || !_initSuccess) + { + return; + } + if (_dialFunctions == null) + { + Debug.LogMessage(LogEventLevel.Debug, "DevicePresets '{0}', not attached to keypad device. Ignoring channel", Key); + return; } - public void Dial(int presetNum, ISetTopBoxNumericKeypad setTopBox) + _dialIsRunning = true; + CrestronInvoke.BeginInvoke(o => { - if (presetNum <= PresetsList.Count) + foreach (var c in chanNum.ToCharArray()) { - Dial(PresetsList[presetNum - 1].Channel, setTopBox); + if (_dialFunctions.ContainsKey(c)) + { + Pulse(_dialFunctions[c]); + } + CrestronEnvironment.Sleep(DigitSpacingMs); } - } - public void Dial(string chanNum, ISetTopBoxNumericKeypad setTopBox) - { - _dialFunctions = new Dictionary>(10) + if (_enterFunction != null) { - {'1', setTopBox.Digit1}, - {'2', setTopBox.Digit2}, - {'3', setTopBox.Digit3}, - {'4', setTopBox.Digit4}, - {'5', setTopBox.Digit5}, - {'6', setTopBox.Digit6}, - {'7', setTopBox.Digit7}, - {'8', setTopBox.Digit8}, - {'9', setTopBox.Digit9}, - {'0', setTopBox.Digit0}, - {'-', setTopBox.Dash} - }; + Pulse(_enterFunction); + } + _dialIsRunning = false; + }); - _enterFunction = setTopBox.KeypadEnter; + if (_setTopBox == null) return; - OnPresetRecalled(setTopBox, chanNum); + OnPresetRecalled(_setTopBox, chanNum); + } - Dial(chanNum); + public void Dial(int presetNum, ISetTopBoxNumericKeypad setTopBox) + { + if (presetNum <= PresetsList.Count) + { + Dial(PresetsList[presetNum - 1].Channel, setTopBox); } + } - private void OnPresetRecalled(ISetTopBoxNumericKeypad setTopBox, string channel) + public void Dial(string chanNum, ISetTopBoxNumericKeypad setTopBox) + { + _dialFunctions = new Dictionary>(10) { - var handler = PresetRecalled; + {'1', setTopBox.Digit1}, + {'2', setTopBox.Digit2}, + {'3', setTopBox.Digit3}, + {'4', setTopBox.Digit4}, + {'5', setTopBox.Digit5}, + {'6', setTopBox.Digit6}, + {'7', setTopBox.Digit7}, + {'8', setTopBox.Digit8}, + {'9', setTopBox.Digit9}, + {'0', setTopBox.Digit0}, + {'-', setTopBox.Dash} + }; + + _enterFunction = setTopBox.KeypadEnter; + + OnPresetRecalled(setTopBox, chanNum); + + Dial(chanNum); + } - if (handler == null) - { - return; - } + private void OnPresetRecalled(ISetTopBoxNumericKeypad setTopBox, string channel) + { + var handler = PresetRecalled; - handler(setTopBox, channel); + if (handler == null) + { + return; } - public void UpdatePreset(int index, PresetChannel preset) + handler(setTopBox, channel); + } + + public void UpdatePreset(int index, PresetChannel preset) + { + if (index >= PresetsList.Count) { - if (index >= PresetsList.Count) - { - return; - } + return; + } - PresetsList[index] = preset; + PresetsList[index] = preset; - SavePresets(); + SavePresets(); - OnPresetsSaved(); - } + OnPresetsSaved(); + } - public void UpdatePresets(List presets) - { - PresetsList = presets; + public void UpdatePresets(List presets) + { + PresetsList = presets; - SavePresets(); + SavePresets(); - OnPresetsSaved(); - } + OnPresetsSaved(); + } - private void SavePresets() + private void SavePresets() + { + try { - try - { - _fileOps.Enter(); - var pl = new PresetsList {Channels = PresetsList, Name = Name}; - var json = JsonConvert.SerializeObject(pl, Formatting.Indented); + _fileOps.Enter(); + var pl = new PresetsList {Channels = PresetsList, Name = Name}; + var json = JsonConvert.SerializeObject(pl, Formatting.Indented); - using (var file = File.Open(_filePath, FileMode.Truncate)) - { - file.Write(json, Encoding.UTF8); - } - } - finally + using (var file = File.Open(_filePath, FileMode.Truncate)) { - _fileOps.Leave(); + file.Write(json, Encoding.UTF8); } - } - - private void OnPresetsSaved() + finally { - var handler = PresetsSaved; + _fileOps.Leave(); + } + + } - if (handler == null) return; + private void OnPresetsSaved() + { + var handler = PresetsSaved; - handler(PresetsList); - } + if (handler == null) return; - private void Pulse(Action act) - { - act(true); - CrestronEnvironment.Sleep(PulseTime); - act(false); - } + handler(PresetsList); + } + + private void Pulse(Action act) + { + act(true); + CrestronEnvironment.Sleep(PulseTime); + act(false); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Presets/DevicePresetsView.cs b/src/PepperDash.Essentials.Core/Presets/DevicePresetsView.cs index a43a7a2c6..bae583de9 100644 --- a/src/PepperDash.Essentials.Core/Presets/DevicePresetsView.cs +++ b/src/PepperDash.Essentials.Core/Presets/DevicePresetsView.cs @@ -6,15 +6,15 @@ using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; -namespace PepperDash.Essentials.Core.Presets -{ +namespace PepperDash.Essentials.Core.Presets; + public class DevicePresetsView { public bool ShowNumbers { get; set; } public bool ShowName { get; set; } public bool ShowIcon { get; set; } - public SubpageReferenceList SRL { get; private set; } + public SubpageReferenceList SRL { get; private set; } public DevicePresetsModel Model { get; private set; } public DevicePresetsView(BasicTriListWithSmartObject tl, DevicePresetsModel model) @@ -56,5 +56,4 @@ void Model_PresetsLoaded(object sender, EventArgs e) Detach(); Attach(); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Presets/PresetBase.cs b/src/PepperDash.Essentials.Core/Presets/PresetBase.cs index 1eaf7739c..8aff84479 100644 --- a/src/PepperDash.Essentials.Core/Presets/PresetBase.cs +++ b/src/PepperDash.Essentials.Core/Presets/PresetBase.cs @@ -8,34 +8,33 @@ using Newtonsoft.Json; -namespace PepperDash.Essentials.Core.Presets +namespace PepperDash.Essentials.Core.Presets; + +public class PresetBase { - public class PresetBase - { - [JsonProperty("id")] - public int ID { get; set; } - /// - /// Used to store the name of the preset - /// - [JsonProperty("description")] - public string Description { get; set; } - /// - /// Indicates if the preset is defined(stored) in the codec - /// - [JsonProperty("defined")] - public bool Defined { get; set; } - /// - /// Indicates if the preset has the capability to be defined - /// - [JsonProperty("isDefinable")] - public bool IsDefinable { get; set; } + [JsonProperty("id")] + public int ID { get; set; } + /// + /// Used to store the name of the preset + /// + [JsonProperty("description")] + public string Description { get; set; } + /// + /// Indicates if the preset is defined(stored) in the codec + /// + [JsonProperty("defined")] + public bool Defined { get; set; } + /// + /// Indicates if the preset has the capability to be defined + /// + [JsonProperty("isDefinable")] + public bool IsDefinable { get; set; } - public PresetBase(int id, string description, bool def, bool isDef) - { - ID = id; - Description = description; - Defined = def; - IsDefinable = isDef; - } + public PresetBase(int id, string description, bool def, bool isDef) + { + ID = id; + Description = description; + Defined = def; + IsDefinable = isDef; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Presets/PresetChannel.cs b/src/PepperDash.Essentials.Core/Presets/PresetChannel.cs index c10ba75de..a2c8423fa 100644 --- a/src/PepperDash.Essentials.Core/Presets/PresetChannel.cs +++ b/src/PepperDash.Essentials.Core/Presets/PresetChannel.cs @@ -7,8 +7,8 @@ using Crestron.SimplSharp; using Newtonsoft.Json; -namespace PepperDash.Essentials.Core.Presets -{ +namespace PepperDash.Essentials.Core.Presets; + public class PresetChannel { @@ -29,5 +29,4 @@ public class PresetsList [JsonProperty(Required = Required.Always, PropertyName = "channels")] public List Channels { get; set; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Presets/PresetsListSubpageReferenceListItem.cs b/src/PepperDash.Essentials.Core/Presets/PresetsListSubpageReferenceListItem.cs index c43494145..dc63e0cee 100644 --- a/src/PepperDash.Essentials.Core/Presets/PresetsListSubpageReferenceListItem.cs +++ b/src/PepperDash.Essentials.Core/Presets/PresetsListSubpageReferenceListItem.cs @@ -10,8 +10,8 @@ using Serilog.Events; -namespace PepperDash.Essentials.Core.Presets -{ +namespace PepperDash.Essentials.Core.Presets; + public class PresetsListSubpageReferenceListItem : SubpageReferenceListItem { DevicePresetsView View; @@ -46,5 +46,4 @@ public override void Refresh() var icon = View.ShowIcon ? url : ""; Owner.StringInputSig(Index, 3).StringValue = icon; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Queues/ComsMessage.cs b/src/PepperDash.Essentials.Core/Queues/ComsMessage.cs index 596c59215..b1e751641 100644 --- a/src/PepperDash.Essentials.Core/Queues/ComsMessage.cs +++ b/src/PepperDash.Essentials.Core/Queues/ComsMessage.cs @@ -1,73 +1,72 @@ using System; using PepperDash.Core; -namespace PepperDash.Essentials.Core.Queues +namespace PepperDash.Essentials.Core.Queues; + +/// +/// IBasicCommunication Message for IQueue +/// +public class ComsMessage : IQueueMessage { + private readonly byte[] _bytes; + private readonly IBasicCommunication _coms; + private readonly string _string; + private readonly bool _isByteMessage; + /// - /// IBasicCommunication Message for IQueue + /// Constructor for a string message /// - public class ComsMessage : IQueueMessage + /// IBasicCommunication to send the message + /// Message to send + public ComsMessage(IBasicCommunication coms, string message) { - private readonly byte[] _bytes; - private readonly IBasicCommunication _coms; - private readonly string _string; - private readonly bool _isByteMessage; - - /// - /// Constructor for a string message - /// - /// IBasicCommunication to send the message - /// Message to send - public ComsMessage(IBasicCommunication coms, string message) - { - Validate(coms, message); - _coms = coms; - _string = message; - } + Validate(coms, message); + _coms = coms; + _string = message; + } - /// - /// Constructor for a byte message - /// - /// IBasicCommunication to send the message - /// Message to send - public ComsMessage(IBasicCommunication coms, byte[] message) - { - Validate(coms, message); - _coms = coms; - _bytes = message; - _isByteMessage = true; - } + /// + /// Constructor for a byte message + /// + /// IBasicCommunication to send the message + /// Message to send + public ComsMessage(IBasicCommunication coms, byte[] message) + { + Validate(coms, message); + _coms = coms; + _bytes = message; + _isByteMessage = true; + } - private void Validate(IBasicCommunication coms, object message) - { - if (coms == null) - throw new ArgumentNullException("coms"); + private void Validate(IBasicCommunication coms, object message) + { + if (coms == null) + throw new ArgumentNullException("coms"); - if (message == null) - throw new ArgumentNullException("message"); - } + if (message == null) + throw new ArgumentNullException("message"); + } - /// - /// Dispatchs the string/byte[] to the IBasicCommunication specified - /// - public void Dispatch() + /// + /// Dispatchs the string/byte[] to the IBasicCommunication specified + /// + public void Dispatch() + { + if (_isByteMessage) { - if (_isByteMessage) - { - _coms.SendBytes(_bytes); - } - else - { - _coms.SendText(_string); - } + _coms.SendBytes(_bytes); } - - /// - /// Shows either the byte[] or string to be sent - /// - public override string ToString() + else { - return _bytes != null ? _bytes.ToString() : _string; + _coms.SendText(_string); } } + + /// + /// Shows either the byte[] or string to be sent + /// + public override string ToString() + { + return _bytes != null ? _bytes.ToString() : _string; + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Queues/GenericQueue.cs b/src/PepperDash.Essentials.Core/Queues/GenericQueue.cs index 74b406fce..8cb265240 100644 --- a/src/PepperDash.Essentials.Core/Queues/GenericQueue.cs +++ b/src/PepperDash.Essentials.Core/Queues/GenericQueue.cs @@ -6,265 +6,264 @@ using Serilog.Events; using Thread = Crestron.SimplSharpPro.CrestronThread.Thread; -namespace PepperDash.Essentials.Core.Queues +namespace PepperDash.Essentials.Core.Queues; + +/// +/// Threadsafe processing of queued items with pacing if required +/// +public class GenericQueue : IQueue { - /// - /// Threadsafe processing of queued items with pacing if required - /// - public class GenericQueue : IQueue - { - private readonly string _key; - protected readonly ConcurrentQueue _queue; - protected readonly Thread _worker; - protected readonly CEvent _waitHandle = new CEvent(); + private readonly string _key; + protected readonly ConcurrentQueue _queue; + protected readonly Thread _worker; + protected readonly CEvent _waitHandle = new CEvent(); - private bool _delayEnabled; - private int _delayTime; + private bool _delayEnabled; + private int _delayTime; - private const Thread.eThreadPriority _defaultPriority = Thread.eThreadPriority.MediumPriority; + private const Thread.eThreadPriority _defaultPriority = Thread.eThreadPriority.MediumPriority; - /// - /// If the instance has been disposed. - /// - public bool Disposed { get; private set; } + /// + /// If the instance has been disposed. + /// + public bool Disposed { get; private set; } - /// - /// Returns the capacity of the CrestronQueue (fixed Size property) - /// - public int QueueCapacity + /// + /// Returns the capacity of the CrestronQueue (fixed Size property) + /// + public int QueueCapacity + { + get { - get - { - return int.MaxValue; - } + return int.MaxValue; } + } - /// - /// Returns the number of elements currently in the CrestronQueue - /// - public int QueueCount + /// + /// Returns the number of elements currently in the CrestronQueue + /// + public int QueueCount + { + get { - get - { - return _queue.Count; - } + return _queue.Count; } + } - /// - /// Constructor with no thread priority - /// - /// - public GenericQueue(string key) - : this(key, _defaultPriority, 0, 0) - { - } + /// + /// Constructor with no thread priority + /// + /// + public GenericQueue(string key) + : this(key, _defaultPriority, 0, 0) + { + } - /// - /// Constructor with queue size - /// - /// - /// Fixed size for the queue to hold - public GenericQueue(string key, int capacity) - : this(key, _defaultPriority, capacity, 0) - { - } + /// + /// Constructor with queue size + /// + /// + /// Fixed size for the queue to hold + public GenericQueue(string key, int capacity) + : this(key, _defaultPriority, capacity, 0) + { + } - /// - /// Constructor for generic queue with no pacing - /// - /// Key - /// Pacing in ms between actions - public GenericQueue(int pacing, string key) - : this(key, _defaultPriority, 0, pacing) - { - } + /// + /// Constructor for generic queue with no pacing + /// + /// Key + /// Pacing in ms between actions + public GenericQueue(int pacing, string key) + : this(key, _defaultPriority, 0, pacing) + { + } - /// - /// Constructor with pacing and capacity - /// - /// - /// - /// - public GenericQueue(string key, int pacing, int capacity) - : this(key, _defaultPriority, capacity, pacing) - { - } + /// + /// Constructor with pacing and capacity + /// + /// + /// + /// + public GenericQueue(string key, int pacing, int capacity) + : this(key, _defaultPriority, capacity, pacing) + { + } - /// - /// Constructor with pacing and priority - /// - /// - /// - /// - public GenericQueue(string key, int pacing, Thread.eThreadPriority priority) - : this(key, priority, 0, pacing) - { - } + /// + /// Constructor with pacing and priority + /// + /// + /// + /// + public GenericQueue(string key, int pacing, Thread.eThreadPriority priority) + : this(key, priority, 0, pacing) + { + } - /// - /// Constructor with pacing, priority and capacity - /// - /// - /// - /// - public GenericQueue(string key, Thread.eThreadPriority priority, int capacity) - : this(key, priority, capacity, 0) - { - } + /// + /// Constructor with pacing, priority and capacity + /// + /// + /// + /// + public GenericQueue(string key, Thread.eThreadPriority priority, int capacity) + : this(key, priority, capacity, 0) + { + } - /// - /// Constructor with pacing, priority and capacity - /// - /// - /// - /// - /// - public GenericQueue(string key, int pacing, Thread.eThreadPriority priority, int capacity) - : this(key, priority, capacity, pacing) - { + /// + /// Constructor with pacing, priority and capacity + /// + /// + /// + /// + /// + public GenericQueue(string key, int pacing, Thread.eThreadPriority priority, int capacity) + : this(key, priority, capacity, pacing) + { + } + + /// + /// Constructor for generic queue with no pacing + /// + /// Key + /// + /// + /// + protected GenericQueue(string key, Thread.eThreadPriority priority, int capacity, int pacing) + { + _key = key; + int cap = 25; // sets default + if (capacity > 0) + { + cap = capacity; // overrides default } - /// - /// Constructor for generic queue with no pacing - /// - /// Key - /// - /// - /// - protected GenericQueue(string key, Thread.eThreadPriority priority, int capacity, int pacing) + _queue = new ConcurrentQueue(); + _worker = new Thread(ProcessQueue, null, Thread.eThreadStartOptions.Running) { - _key = key; - int cap = 25; // sets default - if (capacity > 0) - { - cap = capacity; // overrides default - } + Priority = priority, + Name = _key + }; - _queue = new ConcurrentQueue(); - _worker = new Thread(ProcessQueue, null, Thread.eThreadStartOptions.Running) - { - Priority = priority, - Name = _key - }; + SetDelayValues(pacing); + } - SetDelayValues(pacing); - } + private void SetDelayValues(int pacing) + { + _delayEnabled = pacing > 0; + _delayTime = pacing; - private void SetDelayValues(int pacing) + CrestronEnvironment.ProgramStatusEventHandler += programEvent => { - _delayEnabled = pacing > 0; - _delayTime = pacing; - - CrestronEnvironment.ProgramStatusEventHandler += programEvent => - { - if (programEvent != eProgramStatusEventType.Stopping) - return; + if (programEvent != eProgramStatusEventType.Stopping) + return; - Dispose(true); - }; - } + Dispose(true); + }; + } - /// - /// Thread callback - /// - /// The action used to process dequeued items - /// Null when the thread is exited - private object ProcessQueue(object obj) + /// + /// Thread callback + /// + /// The action used to process dequeued items + /// Null when the thread is exited + private object ProcessQueue(object obj) + { + while (true) { - while (true) + if (_queue.TryDequeue(out var item) && item == null) + break; + + if (item != null) { - if (_queue.TryDequeue(out var item) && item == null) - break; + try + { + //Debug.LogMessage(LogEventLevel.Verbose, this, "Processing queue item: '{0}'", item.ToString()); + item.Dispatch(); - if (item != null) + if (_delayEnabled) + Thread.Sleep(_delayTime); + } + catch (ThreadAbortException) { - try - { - //Debug.LogMessage(LogEventLevel.Verbose, this, "Processing queue item: '{0}'", item.ToString()); - item.Dispatch(); + //swallowing this exception, as it should only happen on shut down + } + catch (Exception ex) + { + Debug.LogMessage(LogEventLevel.Information, this, "Caught an exception in the Queue: {1}:{0}", ex.Message, ex); + Debug.LogMessage(LogEventLevel.Verbose, this, "Stack Trace: {0}", ex.StackTrace); - if (_delayEnabled) - Thread.Sleep(_delayTime); - } - catch (ThreadAbortException) - { - //swallowing this exception, as it should only happen on shut down - } - catch (Exception ex) + if (ex.InnerException != null) { - Debug.LogMessage(LogEventLevel.Information, this, "Caught an exception in the Queue: {1}:{0}", ex.Message, ex); - Debug.LogMessage(LogEventLevel.Verbose, this, "Stack Trace: {0}", ex.StackTrace); - - if (ex.InnerException != null) - { - Debug.LogMessage(LogEventLevel.Information, this, "---\r\n{0}", ex.InnerException.Message); - Debug.LogMessage(LogEventLevel.Verbose, this, "Stack Trace: {0}", ex.InnerException.StackTrace); - } + Debug.LogMessage(LogEventLevel.Information, this, "---\r\n{0}", ex.InnerException.Message); + Debug.LogMessage(LogEventLevel.Verbose, this, "Stack Trace: {0}", ex.InnerException.StackTrace); } } - else _waitHandle.Wait(); } - - return null; + else _waitHandle.Wait(); } - public void Enqueue(IQueueMessage item) - { - if (Disposed) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Queue has been disposed. Enqueuing messages not allowed while program is stopping."); - return; - } - - _queue.Enqueue(item); - _waitHandle.Set(); - } + return null; + } - /// - /// Disposes the thread and cleans up resources. Thread cannot be restarted once - /// disposed. - /// - public void Dispose() + public void Enqueue(IQueueMessage item) + { + if (Disposed) { - Dispose(true); - CrestronEnvironment.GC.SuppressFinalize(this); + Debug.LogMessage(LogEventLevel.Debug, this, "Queue has been disposed. Enqueuing messages not allowed while program is stopping."); + return; } - /// - /// Actually does the disposing. If you override this method, be sure to either call the base implementation - /// or clean up all the resources yourself. - /// - /// set to true unless called from finalizer - protected void Dispose(bool disposing) - { - if (Disposed) - return; + _queue.Enqueue(item); + _waitHandle.Set(); + } - if (disposing) - { - using (_waitHandle) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Disposing..."); - _queue.Enqueue(null); - _waitHandle.Set(); - _worker.Join(); - } - } + /// + /// Disposes the thread and cleans up resources. Thread cannot be restarted once + /// disposed. + /// + public void Dispose() + { + Dispose(true); + CrestronEnvironment.GC.SuppressFinalize(this); + } - Disposed = true; - } + /// + /// Actually does the disposing. If you override this method, be sure to either call the base implementation + /// or clean up all the resources yourself. + /// + /// set to true unless called from finalizer + protected void Dispose(bool disposing) + { + if (Disposed) + return; - ~GenericQueue() + if (disposing) { - Dispose(true); + using (_waitHandle) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Disposing..."); + _queue.Enqueue(null); + _waitHandle.Set(); + _worker.Join(); + } } - /// - /// Key - /// - public string Key - { - get { return _key; } - } + Disposed = true; + } + + ~GenericQueue() + { + Dispose(true); + } + + /// + /// Key + /// + public string Key + { + get { return _key; } } } diff --git a/src/PepperDash.Essentials.Core/Queues/IQueue.cs b/src/PepperDash.Essentials.Core/Queues/IQueue.cs index cb3bb947f..077f42abd 100644 --- a/src/PepperDash.Essentials.Core/Queues/IQueue.cs +++ b/src/PepperDash.Essentials.Core/Queues/IQueue.cs @@ -1,11 +1,10 @@ using System; using PepperDash.Core; -namespace PepperDash.Essentials.Core.Queues +namespace PepperDash.Essentials.Core.Queues; + +public interface IQueue : IKeyed, IDisposable where T : class { - public interface IQueue : IKeyed, IDisposable where T : class - { - void Enqueue(T item); - bool Disposed { get; } - } + void Enqueue(T item); + bool Disposed { get; } } diff --git a/src/PepperDash.Essentials.Core/Queues/IQueueMessage.cs b/src/PepperDash.Essentials.Core/Queues/IQueueMessage.cs index 408bffca4..206a1744e 100644 --- a/src/PepperDash.Essentials.Core/Queues/IQueueMessage.cs +++ b/src/PepperDash.Essentials.Core/Queues/IQueueMessage.cs @@ -1,9 +1,8 @@ using System; -namespace PepperDash.Essentials.Core.Queues +namespace PepperDash.Essentials.Core.Queues; + +public interface IQueueMessage { - public interface IQueueMessage - { - void Dispatch(); - } + void Dispatch(); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Queues/ProcessStringMessage.cs b/src/PepperDash.Essentials.Core/Queues/ProcessStringMessage.cs index 5617326fb..9d9f38cbd 100644 --- a/src/PepperDash.Essentials.Core/Queues/ProcessStringMessage.cs +++ b/src/PepperDash.Essentials.Core/Queues/ProcessStringMessage.cs @@ -1,44 +1,43 @@ using System; -namespace PepperDash.Essentials.Core.Queues +namespace PepperDash.Essentials.Core.Queues; + +/// +/// Message class for processing strings via an IQueue +/// +public class ProcessStringMessage : IQueueMessage { + private readonly Action _action; + private readonly string _message; + /// - /// Message class for processing strings via an IQueue + /// Constructor /// - public class ProcessStringMessage : IQueueMessage + /// Message to be processed + /// Action to invoke on the message + public ProcessStringMessage(string message, Action action) { - private readonly Action _action; - private readonly string _message; - - /// - /// Constructor - /// - /// Message to be processed - /// Action to invoke on the message - public ProcessStringMessage(string message, Action action) - { - _message = message; - _action = action; - } + _message = message; + _action = action; + } - /// - /// Processes the string with the given action - /// - public void Dispatch() - { - if (_action == null || String.IsNullOrEmpty(_message)) - return; + /// + /// Processes the string with the given action + /// + public void Dispatch() + { + if (_action == null || String.IsNullOrEmpty(_message)) + return; - _action(_message); - } + _action(_message); + } - /// - /// To string - /// - /// The current message - public override string ToString() - { - return _message ?? String.Empty; - } + /// + /// To string + /// + /// The current message + public override string ToString() + { + return _message ?? String.Empty; } } diff --git a/src/PepperDash.Essentials.Core/Queues/StringResponseProcessor.cs b/src/PepperDash.Essentials.Core/Queues/StringResponseProcessor.cs index 62020af0a..44c83e37a 100644 --- a/src/PepperDash.Essentials.Core/Queues/StringResponseProcessor.cs +++ b/src/PepperDash.Essentials.Core/Queues/StringResponseProcessor.cs @@ -2,105 +2,104 @@ using Crestron.SimplSharp; using PepperDash.Core; -namespace PepperDash.Essentials.Core.Queues +namespace PepperDash.Essentials.Core.Queues; + +public sealed class StringResponseProcessor : IKeyed, IDisposable { - public sealed class StringResponseProcessor : IKeyed, IDisposable + private readonly Action _processStringAction; + private readonly IQueue _queue; + private readonly IBasicCommunication _coms; + private readonly CommunicationGather _gather; + + private StringResponseProcessor(string key, Action processStringAction) { - private readonly Action _processStringAction; - private readonly IQueue _queue; - private readonly IBasicCommunication _coms; - private readonly CommunicationGather _gather; + _processStringAction = processStringAction; + _queue = new GenericQueue(key); - private StringResponseProcessor(string key, Action processStringAction) + CrestronEnvironment.ProgramStatusEventHandler += programEvent => { - _processStringAction = processStringAction; - _queue = new GenericQueue(key); + if (programEvent != eProgramStatusEventType.Stopping) + return; - CrestronEnvironment.ProgramStatusEventHandler += programEvent => - { - if (programEvent != eProgramStatusEventType.Stopping) - return; + Dispose(); + }; + } - Dispose(); - }; - } + /// + /// Constructor that builds an instance and subscribes to coms TextReceived for processing + /// + /// Com port to process strings from + /// Action to process the incoming strings + public StringResponseProcessor(IBasicCommunication coms, Action processStringAction) + : this(coms.Key, processStringAction) + { + _coms = coms; + coms.TextReceived += OnResponseReceived; + } - /// - /// Constructor that builds an instance and subscribes to coms TextReceived for processing - /// - /// Com port to process strings from - /// Action to process the incoming strings - public StringResponseProcessor(IBasicCommunication coms, Action processStringAction) - : this(coms.Key, processStringAction) - { - _coms = coms; - coms.TextReceived += OnResponseReceived; - } + /// + /// Constructor that builds an instance and subscribes to gather Line Received for processing + /// + /// Gather to process strings from + /// Action to process the incoming strings + public StringResponseProcessor(CommunicationGather gather, Action processStringAction) + : this(gather.Port.Key, processStringAction) + { + _gather = gather; + gather.LineReceived += OnResponseReceived; + } - /// - /// Constructor that builds an instance and subscribes to gather Line Received for processing - /// - /// Gather to process strings from - /// Action to process the incoming strings - public StringResponseProcessor(CommunicationGather gather, Action processStringAction) - : this(gather.Port.Key, processStringAction) - { - _gather = gather; - gather.LineReceived += OnResponseReceived; - } + private void OnResponseReceived(object sender, GenericCommMethodReceiveTextArgs args) + { + _queue.Enqueue(new ProcessStringMessage(args.Text, _processStringAction)); + } - private void OnResponseReceived(object sender, GenericCommMethodReceiveTextArgs args) - { - _queue.Enqueue(new ProcessStringMessage(args.Text, _processStringAction)); - } + /// + /// Key + /// + public string Key + { + get { return _queue.Key; } + } - /// - /// Key - /// - public string Key - { - get { return _queue.Key; } - } + /// + /// Disposes the instance and cleans up resources. + /// + public void Dispose() + { + Dispose(true); + CrestronEnvironment.GC.SuppressFinalize(this); + } - /// - /// Disposes the instance and cleans up resources. - /// - public void Dispose() - { - Dispose(true); - CrestronEnvironment.GC.SuppressFinalize(this); - } + private void Dispose(bool disposing) + { + if (Disposed) + return; - private void Dispose(bool disposing) + if (disposing) { - if (Disposed) - return; + if (_coms != null) + _coms.TextReceived -= OnResponseReceived; - if (disposing) + if (_gather != null) { - if (_coms != null) - _coms.TextReceived -= OnResponseReceived; - - if (_gather != null) - { - _gather.LineReceived -= OnResponseReceived; - _gather.Stop(); - } - - _queue.Dispose(); + _gather.LineReceived -= OnResponseReceived; + _gather.Stop(); } - Disposed = true; + _queue.Dispose(); } - /// - /// If the instance has been disposed or not. If it has, you can not use it anymore - /// - public bool Disposed { get; private set; } + Disposed = true; + } + + /// + /// If the instance has been disposed or not. If it has, you can not use it anymore + /// + public bool Disposed { get; private set; } - ~StringResponseProcessor() - { - Dispose(false); - } + ~StringResponseProcessor() + { + Dispose(false); } } diff --git a/src/PepperDash.Essentials.Core/Ramps and Increments/ActionIncrementer.cs b/src/PepperDash.Essentials.Core/Ramps and Increments/ActionIncrementer.cs index f63d57bfb..ded7d9f33 100644 --- a/src/PepperDash.Essentials.Core/Ramps and Increments/ActionIncrementer.cs +++ b/src/PepperDash.Essentials.Core/Ramps and Increments/ActionIncrementer.cs @@ -6,115 +6,114 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// An incrementer that can use the values of some other object/primitive value to do its thing. +/// It uses an Action to set the value and a Func to get the value from whatever this is +/// attached to. +/// +public class ActionIncrementer { + public int ChangeAmount { get; set; } + public int MaxValue { get; set; } + public int MinValue { get; set; } + public uint RepeatDelay { get; set; } + public uint RepeatTime { get; set; } + + Action SetAction; + Func GetFunc; + CTimer Timer; + /// - /// An incrementer that can use the values of some other object/primitive value to do its thing. - /// It uses an Action to set the value and a Func to get the value from whatever this is - /// attached to. + /// /// - public class ActionIncrementer + /// + /// + /// + /// + /// + /// Action that will be called when this needs to set the destination value + /// Func that is called to get the current value + public ActionIncrementer(int changeAmount, int minValue, int maxValue, uint repeatDelay, uint repeatTime, Action setAction, Func getFunc) { - public int ChangeAmount { get; set; } - public int MaxValue { get; set; } - public int MinValue { get; set; } - public uint RepeatDelay { get; set; } - public uint RepeatTime { get; set; } + SetAction = setAction; + GetFunc = getFunc; + ChangeAmount = changeAmount; + MaxValue = maxValue; + MinValue = minValue; + RepeatDelay = repeatDelay; + RepeatTime = repeatTime; + } - Action SetAction; - Func GetFunc; - CTimer Timer; + /// + /// Starts incrementing cycle + /// + public void StartUp() + { + if (Timer != null) return; + Go(ChangeAmount); + } - /// - /// - /// - /// - /// - /// - /// - /// - /// Action that will be called when this needs to set the destination value - /// Func that is called to get the current value - public ActionIncrementer(int changeAmount, int minValue, int maxValue, uint repeatDelay, uint repeatTime, Action setAction, Func getFunc) - { - SetAction = setAction; - GetFunc = getFunc; - ChangeAmount = changeAmount; - MaxValue = maxValue; - MinValue = minValue; - RepeatDelay = repeatDelay; - RepeatTime = repeatTime; - } + /// + /// Starts decrementing cycle + /// + public void StartDown() + { + if (Timer != null) return; + Go(-ChangeAmount); + } - /// - /// Starts incrementing cycle - /// - public void StartUp() - { - if (Timer != null) return; - Go(ChangeAmount); - } + /// + /// Stops the repeat + /// + public void Stop() + { + if (Timer != null) + Timer.Stop(); + Timer = null; + } - /// - /// Starts decrementing cycle - /// - public void StartDown() - { - if (Timer != null) return; - Go(-ChangeAmount); - } + /// + /// Helper that does the work of setting new level, and starting repeat loop, checking against bounds first. + /// + /// + void Go(int change) + { + int currentLevel = GetFunc(); + // Fire once then pause + int newLevel = currentLevel + change; + bool atLimit = CheckLevel(newLevel, out newLevel); + SetAction(newLevel); - /// - /// Stops the repeat - /// - public void Stop() - { - if (Timer != null) - Timer.Stop(); - Timer = null; - } + if (atLimit) // Don't go past end + Stop(); + else if (Timer == null) // Only enter the timer if it's not already running + Timer = new CTimer(o => { Go(change); }, null, RepeatDelay, RepeatTime); + } - /// - /// Helper that does the work of setting new level, and starting repeat loop, checking against bounds first. - /// - /// - void Go(int change) + /// + /// Helper to check a new level against min/max. Returns revised level if new level + /// will go out of bounds + /// + /// The level to check against bounds + /// Revised level if bounds are exceeded. Min or max + /// true if new level is at or past bounds + bool CheckLevel(int levelIn, out int levelOut) + { + bool isAtLimit = false; + if (levelIn > MaxValue) { - int currentLevel = GetFunc(); - // Fire once then pause - int newLevel = currentLevel + change; - bool atLimit = CheckLevel(newLevel, out newLevel); - SetAction(newLevel); - - if (atLimit) // Don't go past end - Stop(); - else if (Timer == null) // Only enter the timer if it's not already running - Timer = new CTimer(o => { Go(change); }, null, RepeatDelay, RepeatTime); + levelOut = MaxValue; + isAtLimit = true; } - - /// - /// Helper to check a new level against min/max. Returns revised level if new level - /// will go out of bounds - /// - /// The level to check against bounds - /// Revised level if bounds are exceeded. Min or max - /// true if new level is at or past bounds - bool CheckLevel(int levelIn, out int levelOut) + else if (levelIn < MinValue) { - bool isAtLimit = false; - if (levelIn > MaxValue) - { - levelOut = MaxValue; - isAtLimit = true; - } - else if (levelIn < MinValue) - { - levelOut = MinValue; - isAtLimit = true; - } - else - levelOut = levelIn; - return isAtLimit; + levelOut = MinValue; + isAtLimit = true; } + else + levelOut = levelIn; + return isAtLimit; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Ramps and Increments/NumericalHelpers.cs b/src/PepperDash.Essentials.Core/Ramps and Increments/NumericalHelpers.cs index fefeb7022..b26d5fac1 100644 --- a/src/PepperDash.Essentials.Core/Ramps and Increments/NumericalHelpers.cs +++ b/src/PepperDash.Essentials.Core/Ramps and Increments/NumericalHelpers.cs @@ -4,37 +4,36 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core -{ - public class NumericalHelpers - { - /// - /// Scales a value - /// - /// - /// - /// - /// - /// - /// - public static double Scale(double input, double inMin, double inMax, double outMin, double outMax) - { - //Debug.LogMessage(LogEventLevel.Verbose, this, "Scaling (double) input '{0}' with min '{1}'/max '{2}' to output range min '{3}'/max '{4}'", input, inMin, inMax, outMin, outMax); +namespace PepperDash.Essentials.Core; - double inputRange = inMax - inMin; +public class NumericalHelpers +{ + /// + /// Scales a value + /// + /// + /// + /// + /// + /// + /// + public static double Scale(double input, double inMin, double inMax, double outMin, double outMax) + { + //Debug.LogMessage(LogEventLevel.Verbose, this, "Scaling (double) input '{0}' with min '{1}'/max '{2}' to output range min '{3}'/max '{4}'", input, inMin, inMax, outMin, outMax); - if (inputRange <= 0) - { - throw new ArithmeticException(string.Format("Invalid Input Range '{0}' for Scaling. Min '{1}' Max '{2}'.", inputRange, inMin, inMax)); - } + double inputRange = inMax - inMin; - double outputRange = outMax - outMin; + if (inputRange <= 0) + { + throw new ArithmeticException(string.Format("Invalid Input Range '{0}' for Scaling. Min '{1}' Max '{2}'.", inputRange, inMin, inMax)); + } - var output = (((input - inMin) * outputRange) / inputRange) + outMin; + double outputRange = outMax - outMin; - // Debug.LogMessage(LogEventLevel.Verbose, this, "Scaled output '{0}'", output); + var output = (((input - inMin) * outputRange) / inputRange) + outMin; - return output; - } + // Debug.LogMessage(LogEventLevel.Verbose, this, "Scaled output '{0}'", output); + + return output; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Ramps and Increments/UshortSigIncrementer.cs b/src/PepperDash.Essentials.Core/Ramps and Increments/UshortSigIncrementer.cs index 3d29be770..7ee4c956a 100644 --- a/src/PepperDash.Essentials.Core/Ramps and Increments/UshortSigIncrementer.cs +++ b/src/PepperDash.Essentials.Core/Ramps and Increments/UshortSigIncrementer.cs @@ -8,94 +8,93 @@ using PepperDash.Core; using Serilog.Events; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Attaches to UShortInputSig and does incremental ramping of the signal +/// +public class UshortSigIncrementer { - /// - /// Attaches to UShortInputSig and does incremental ramping of the signal - /// - public class UshortSigIncrementer - { - UShortInputSig TheSig; - public ushort ChangeAmount { get; set; } - public int MaxValue { get; set; } - public int MinValue { get; set; } - public uint RepeatDelay { get; set; } - public uint RepeatTime { get; set; } - bool SignedMode; - CTimer Timer; + UShortInputSig TheSig; + public ushort ChangeAmount { get; set; } + public int MaxValue { get; set; } + public int MinValue { get; set; } + public uint RepeatDelay { get; set; } + public uint RepeatTime { get; set; } + bool SignedMode; + CTimer Timer; - public UshortSigIncrementer(UShortInputSig sig, ushort changeAmount, int minValue, int maxValue, uint repeatDelay, uint repeatTime) - { - TheSig = sig; - ChangeAmount = changeAmount; - MaxValue = maxValue; - MinValue = minValue; - if (MinValue < 0 || MaxValue < 0) SignedMode = true; - RepeatDelay = repeatDelay; - RepeatTime = repeatTime; - if (SignedMode && (MinValue < -32768 || MaxValue > 32767)) - Debug.LogMessage(LogEventLevel.Debug, "UshortSigIncrementer has signed values that exceed range of -32768, 32767"); - } + public UshortSigIncrementer(UShortInputSig sig, ushort changeAmount, int minValue, int maxValue, uint repeatDelay, uint repeatTime) + { + TheSig = sig; + ChangeAmount = changeAmount; + MaxValue = maxValue; + MinValue = minValue; + if (MinValue < 0 || MaxValue < 0) SignedMode = true; + RepeatDelay = repeatDelay; + RepeatTime = repeatTime; + if (SignedMode && (MinValue < -32768 || MaxValue > 32767)) + Debug.LogMessage(LogEventLevel.Debug, "UshortSigIncrementer has signed values that exceed range of -32768, 32767"); + } - public void StartUp() - { - if (Timer != null) return; - Go(ChangeAmount); - } + public void StartUp() + { + if (Timer != null) return; + Go(ChangeAmount); + } - public void StartDown() - { - if (Timer != null) return; - Go(-ChangeAmount); - } + public void StartDown() + { + if (Timer != null) return; + Go(-ChangeAmount); + } - void Go(int change) - { - int level; - if (SignedMode) level = TheSig.ShortValue; - else level = TheSig.UShortValue; + void Go(int change) + { + int level; + if (SignedMode) level = TheSig.ShortValue; + else level = TheSig.UShortValue; - // Fire once then pause - int newLevel = level + change; - bool atLimit = CheckLevel(newLevel, out newLevel); - SetValue((ushort)newLevel); + // Fire once then pause + int newLevel = level + change; + bool atLimit = CheckLevel(newLevel, out newLevel); + SetValue((ushort)newLevel); - if (atLimit) // Don't go past end - Stop(); - else if (Timer == null) // Only enter the timer if it's not already running - Timer = new CTimer(o => { Go(change); }, null, RepeatDelay, RepeatTime); - } + if (atLimit) // Don't go past end + Stop(); + else if (Timer == null) // Only enter the timer if it's not already running + Timer = new CTimer(o => { Go(change); }, null, RepeatDelay, RepeatTime); + } - bool CheckLevel(int levelIn, out int levelOut) + bool CheckLevel(int levelIn, out int levelOut) + { + bool IsAtLimit = false; + if (levelIn > MaxValue) { - bool IsAtLimit = false; - if (levelIn > MaxValue) - { - levelOut = MaxValue; - IsAtLimit = true; - } - else if (levelIn < MinValue) - { - levelOut = MinValue; - IsAtLimit = true; - } - else - levelOut = levelIn; - return IsAtLimit; + levelOut = MaxValue; + IsAtLimit = true; } - - public void Stop() + else if (levelIn < MinValue) { - if (Timer != null) - Timer.Stop(); - Timer = null; + levelOut = MinValue; + IsAtLimit = true; } + else + levelOut = levelIn; + return IsAtLimit; + } - void SetValue(ushort value) - { - //CrestronConsole.PrintLine("Increment level:{0} / {1}", value, (short)value); - TheSig.UShortValue = value; - } + public void Stop() + { + if (Timer != null) + Timer.Stop(); + Timer = null; + } + + void SetValue(ushort value) + { + //CrestronConsole.PrintLine("Increment level:{0} / {1}", value, (short)value); + TheSig.UShortValue = value; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Behaviours/RoomOnToDefaultSourceWhenOccupied.cs b/src/PepperDash.Essentials.Core/Room/Behaviours/RoomOnToDefaultSourceWhenOccupied.cs index e96e2a23d..d19aaa0c7 100644 --- a/src/PepperDash.Essentials.Core/Room/Behaviours/RoomOnToDefaultSourceWhenOccupied.cs +++ b/src/PepperDash.Essentials.Core/Room/Behaviours/RoomOnToDefaultSourceWhenOccupied.cs @@ -16,543 +16,541 @@ using PepperDash.Essentials.Core.Devices; using Serilog.Events; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// A device that when linked to a room can power the room on when enabled during scheduled hours. +/// +public class RoomOnToDefaultSourceWhenOccupied : ReconfigurableDevice { - /// - /// A device that when linked to a room can power the room on when enabled during scheduled hours. - /// - public class RoomOnToDefaultSourceWhenOccupied : ReconfigurableDevice - { - RoomOnToDefaultSourceWhenOccupiedConfig PropertiesConfig; + RoomOnToDefaultSourceWhenOccupiedConfig PropertiesConfig; - public bool FeatureEnabled { get; private set; } + public bool FeatureEnabled { get; private set; } - public DateTime FeatureEnabledTime { get; private set; } + public DateTime FeatureEnabledTime { get; private set; } - ScheduledEvent FeatureEnableEvent; + ScheduledEvent FeatureEnableEvent; - const string FeatureEnableEventName = "EnableRoomOnToDefaultSourceWhenOccupied"; + const string FeatureEnableEventName = "EnableRoomOnToDefaultSourceWhenOccupied"; - public DateTime FeatureDisabledTime { get; private set; } + public DateTime FeatureDisabledTime { get; private set; } - ScheduledEvent FeatureDisableEvent; + ScheduledEvent FeatureDisableEvent; - const string FeatureDisableEventName = "DisableRoomOnToDefaultSourceWhenOccupied"; + const string FeatureDisableEventName = "DisableRoomOnToDefaultSourceWhenOccupied"; - ScheduledEventGroup FeatureEventGroup; + ScheduledEventGroup FeatureEventGroup; - public IRoomOccupancy Room { get; private set; } + public IRoomOccupancy Room { get; private set; } - private Fusion.EssentialsHuddleSpaceFusionSystemControllerBase FusionRoom; + private Fusion.EssentialsHuddleSpaceFusionSystemControllerBase FusionRoom; - public RoomOnToDefaultSourceWhenOccupied(DeviceConfig config) : - base (config) - { - PropertiesConfig = JsonConvert.DeserializeObject(config.Properties.ToString()); + public RoomOnToDefaultSourceWhenOccupied(DeviceConfig config) : + base (config) + { + PropertiesConfig = JsonConvert.DeserializeObject(config.Properties.ToString()); - FeatureEventGroup = new ScheduledEventGroup(this.Key); + FeatureEventGroup = new ScheduledEventGroup(this.Key); - FeatureEventGroup.RetrieveAllEvents(); + FeatureEventGroup.RetrieveAllEvents(); - // Add to the global class for tracking - Scheduler.AddEventGroup(FeatureEventGroup); + // Add to the global class for tracking + Scheduler.AddEventGroup(FeatureEventGroup); - AddPostActivationAction(() => - { - // Subscribe to room event to know when RoomOccupancy is set and ready to be subscribed to - if (Room != null) - Room.RoomOccupancyIsSet += new EventHandler(RoomOccupancyIsSet); + AddPostActivationAction(() => + { + // Subscribe to room event to know when RoomOccupancy is set and ready to be subscribed to + if (Room != null) + Room.RoomOccupancyIsSet += new EventHandler(RoomOccupancyIsSet); - else - Debug.LogMessage(LogEventLevel.Debug, this, "Room has no RoomOccupancy object set"); + else + Debug.LogMessage(LogEventLevel.Debug, this, "Room has no RoomOccupancy object set"); - var fusionRoomKey = PropertiesConfig.RoomKey + "-fusion"; + var fusionRoomKey = PropertiesConfig.RoomKey + "-fusion"; - FusionRoom = DeviceManager.GetDeviceForKey(fusionRoomKey) as Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase; + FusionRoom = DeviceManager.GetDeviceForKey(fusionRoomKey) as Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase; - if (FusionRoom == null) - Debug.LogMessage(LogEventLevel.Debug, this, "Unable to get Fusion Room from Device Manager with key: {0}", fusionRoomKey); - }); - } + if (FusionRoom == null) + Debug.LogMessage(LogEventLevel.Debug, this, "Unable to get Fusion Room from Device Manager with key: {0}", fusionRoomKey); + }); + } - public override bool CustomActivate() - { - SetUpDevice(); + public override bool CustomActivate() + { + SetUpDevice(); - return base.CustomActivate(); - } + return base.CustomActivate(); + } - /// - /// Sets up device based on config values - /// - void SetUpDevice() - { - Room = DeviceManager.GetDeviceForKey(PropertiesConfig.RoomKey) as IRoomOccupancy; + /// + /// Sets up device based on config values + /// + void SetUpDevice() + { + Room = DeviceManager.GetDeviceForKey(PropertiesConfig.RoomKey) as IRoomOccupancy; - if (Room != null) + if (Room != null) + { + try { - try - { - FeatureEnabledTime = DateTime.Parse(PropertiesConfig.OccupancyStartTime); + FeatureEnabledTime = DateTime.Parse(PropertiesConfig.OccupancyStartTime); - if (FeatureEnabledTime != null) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Enabled Time: {0}", FeatureEnabledTime.ToString()); - } - else - Debug.LogMessage(LogEventLevel.Debug, this, "Unable to parse {0} to DateTime", PropertiesConfig.OccupancyStartTime); - } - catch (Exception e) + if (FeatureEnabledTime != null) { - Debug.LogMessage(LogEventLevel.Debug, this, "Unable to parse OccupancyStartTime property: {0} \n Error: {1}", PropertiesConfig.OccupancyStartTime, e); + Debug.LogMessage(LogEventLevel.Debug, this, "Enabled Time: {0}", FeatureEnabledTime.ToString()); } + else + Debug.LogMessage(LogEventLevel.Debug, this, "Unable to parse {0} to DateTime", PropertiesConfig.OccupancyStartTime); + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Unable to parse OccupancyStartTime property: {0} \n Error: {1}", PropertiesConfig.OccupancyStartTime, e); + } - try - { - FeatureDisabledTime = DateTime.Parse(PropertiesConfig.OccupancyEndTime); + try + { + FeatureDisabledTime = DateTime.Parse(PropertiesConfig.OccupancyEndTime); - if (FeatureDisabledTime != null) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Disabled Time: {0}", FeatureDisabledTime.ToString()); - } - else - Debug.LogMessage(LogEventLevel.Debug, this, "Unable to parse {0} to DateTime", PropertiesConfig.OccupancyEndTime); - } - catch (Exception e) + if (FeatureDisabledTime != null) { - Debug.LogMessage(LogEventLevel.Debug, this, "Unable to parse a DateTime config value \n Error: {1}", e); + Debug.LogMessage(LogEventLevel.Debug, this, "Disabled Time: {0}", FeatureDisabledTime.ToString()); } - - if (!PropertiesConfig.EnableRoomOnWhenOccupied) - FeatureEventGroup.ClearAllEvents(); else - { - AddEnableEventToGroup(); + Debug.LogMessage(LogEventLevel.Debug, this, "Unable to parse {0} to DateTime", PropertiesConfig.OccupancyEndTime); + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Unable to parse a DateTime config value \n Error: {1}", e); + } - AddDisableEventToGroup(); + if (!PropertiesConfig.EnableRoomOnWhenOccupied) + FeatureEventGroup.ClearAllEvents(); + else + { + AddEnableEventToGroup(); - FeatureEventGroup.UserGroupCallBack += new ScheduledEventGroup.UserEventGroupCallBack(FeatureEventGroup_UserGroupCallBack); + AddDisableEventToGroup(); - FeatureEventGroup.EnableAllEvents(); - } + FeatureEventGroup.UserGroupCallBack += new ScheduledEventGroup.UserEventGroupCallBack(FeatureEventGroup_UserGroupCallBack); - FeatureEnabled = CheckIfFeatureShouldBeEnabled(); + FeatureEventGroup.EnableAllEvents(); } - else - Debug.LogMessage(LogEventLevel.Debug, this, "Unable to get room from Device Manager with key: {0}", PropertiesConfig.RoomKey); + + FeatureEnabled = CheckIfFeatureShouldBeEnabled(); } + else + Debug.LogMessage(LogEventLevel.Debug, this, "Unable to get room from Device Manager with key: {0}", PropertiesConfig.RoomKey); + } - protected override void CustomSetConfig(DeviceConfig config) - { - var newPropertiesConfig = JsonConvert.DeserializeObject(config.Properties.ToString()); + protected override void CustomSetConfig(DeviceConfig config) + { + var newPropertiesConfig = JsonConvert.DeserializeObject(config.Properties.ToString()); - if(newPropertiesConfig != null) - PropertiesConfig = newPropertiesConfig; + if(newPropertiesConfig != null) + PropertiesConfig = newPropertiesConfig; - ConfigWriter.UpdateDeviceConfig(config); + ConfigWriter.UpdateDeviceConfig(config); - SetUpDevice(); - } + SetUpDevice(); + } - /// - /// Subscribe to feedback from RoomIsOccupiedFeedback on Room - /// - /// - /// - void RoomOccupancyIsSet(object sender, EventArgs e) + /// + /// Subscribe to feedback from RoomIsOccupiedFeedback on Room + /// + /// + /// + void RoomOccupancyIsSet(object sender, EventArgs e) + { + if (Room.RoomOccupancy != null) { - if (Room.RoomOccupancy != null) - { - Room.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange -= RoomIsOccupiedFeedback_OutputChange; - Room.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += new EventHandler(RoomIsOccupiedFeedback_OutputChange); - Debug.LogMessage(LogEventLevel.Debug, this, "Subscribed to RoomOccupancy status from: '{0}'", Room.Key); - } + Room.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange -= RoomIsOccupiedFeedback_OutputChange; + Room.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += new EventHandler(RoomIsOccupiedFeedback_OutputChange); + Debug.LogMessage(LogEventLevel.Debug, this, "Subscribed to RoomOccupancy status from: '{0}'", Room.Key); } + } + + void FeatureEventGroup_UserGroupCallBack(ScheduledEvent SchEvent, ScheduledEventCommon.eCallbackReason type) + { + Debug.LogMessage(LogEventLevel.Debug, this, "{0}:{1} @ {2}", SchEvent.Name, type, DateTime.Now); - void FeatureEventGroup_UserGroupCallBack(ScheduledEvent SchEvent, ScheduledEventCommon.eCallbackReason type) + if (type == ScheduledEventCommon.eCallbackReason.NormalExpiration) { - Debug.LogMessage(LogEventLevel.Debug, this, "{0}:{1} @ {2}", SchEvent.Name, type, DateTime.Now); + SchEvent.Acknowledge(); - if (type == ScheduledEventCommon.eCallbackReason.NormalExpiration) + if (SchEvent.Name == FeatureEnableEventName) { - SchEvent.Acknowledge(); - - if (SchEvent.Name == FeatureEnableEventName) - { - - if (PropertiesConfig.EnableRoomOnWhenOccupied) - FeatureEnabled = true; + + if (PropertiesConfig.EnableRoomOnWhenOccupied) + FeatureEnabled = true; - Debug.LogMessage(LogEventLevel.Debug, this, "*****Feature Enabled by event.*****"); - } - else if (SchEvent.Name == FeatureDisableEventName) - { - FeatureEnabled = false; + Debug.LogMessage(LogEventLevel.Debug, this, "*****Feature Enabled by event.*****"); + } + else if (SchEvent.Name == FeatureDisableEventName) + { + FeatureEnabled = false; - Debug.LogMessage(LogEventLevel.Debug, this, "*****Feature Disabled by event.*****"); - } + Debug.LogMessage(LogEventLevel.Debug, this, "*****Feature Disabled by event.*****"); } } + } - /// - /// Checks if the feature should be currently enabled. Used on startup if processor starts after start time but before end time - /// - /// - bool CheckIfFeatureShouldBeEnabled() + /// + /// Checks if the feature should be currently enabled. Used on startup if processor starts after start time but before end time + /// + /// + bool CheckIfFeatureShouldBeEnabled() + { + bool enabled = false; + + if(PropertiesConfig.EnableRoomOnWhenOccupied) { - bool enabled = false; + Debug.LogMessage(LogEventLevel.Debug, this, "Current Time: {0} \n FeatureEnabledTime: {1} \n FeatureDisabledTime: {2}", DateTime.Now, FeatureEnabledTime, FeatureDisabledTime); - if(PropertiesConfig.EnableRoomOnWhenOccupied) + if (DateTime.Now.TimeOfDay.CompareTo(FeatureEnabledTime.TimeOfDay) >= 0 && FeatureDisabledTime.TimeOfDay.CompareTo(DateTime.Now.TimeOfDay) > 0) { - Debug.LogMessage(LogEventLevel.Debug, this, "Current Time: {0} \n FeatureEnabledTime: {1} \n FeatureDisabledTime: {2}", DateTime.Now, FeatureEnabledTime, FeatureDisabledTime); - - if (DateTime.Now.TimeOfDay.CompareTo(FeatureEnabledTime.TimeOfDay) >= 0 && FeatureDisabledTime.TimeOfDay.CompareTo(DateTime.Now.TimeOfDay) > 0) + if (SchedulerUtilities.CheckIfDayOfWeekMatchesRecurrenceDays(DateTime.Now, CalculateDaysOfWeekRecurrence())) { - if (SchedulerUtilities.CheckIfDayOfWeekMatchesRecurrenceDays(DateTime.Now, CalculateDaysOfWeekRecurrence())) - { - enabled = true; - } + enabled = true; } } + } - if(enabled) - Debug.LogMessage(LogEventLevel.Debug, this, "*****Feature Enabled*****"); - else - Debug.LogMessage(LogEventLevel.Debug, this, "*****Feature Disabled*****"); + if(enabled) + Debug.LogMessage(LogEventLevel.Debug, this, "*****Feature Enabled*****"); + else + Debug.LogMessage(LogEventLevel.Debug, this, "*****Feature Disabled*****"); - return enabled; - } + return enabled; + } - /// - /// Respond to Occupancy status event - /// - /// - /// - void RoomIsOccupiedFeedback_OutputChange(object sender, FeedbackEventArgs e) + /// + /// Respond to Occupancy status event + /// + /// + /// + void RoomIsOccupiedFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + Debug.LogMessage(LogEventLevel.Debug, this, "RoomIsOccupiedFeeback.OutputChange event fired. e.BoolValue: {0}", e.BoolValue); + if(e.BoolValue) { - Debug.LogMessage(LogEventLevel.Debug, this, "RoomIsOccupiedFeeback.OutputChange event fired. e.BoolValue: {0}", e.BoolValue); - if(e.BoolValue) - { - // Occupancy detected + // Occupancy detected - if (FeatureEnabled) - { - var essentialsRoom = Room as IEssentialsRoom; + if (FeatureEnabled) + { + var essentialsRoom = Room as IEssentialsRoom; - if (essentialsRoom != null) { - if (!essentialsRoom.OnFeedback.BoolValue) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Powering Room on to default source"); + if (essentialsRoom != null) { + if (!essentialsRoom.OnFeedback.BoolValue) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Powering Room on to default source"); - var defaultRouteRoom = Room as IRunDefaultPresentRoute; + var defaultRouteRoom = Room as IRunDefaultPresentRoute; - if (defaultRouteRoom != null) - { - defaultRouteRoom.RunDefaultPresentRoute(); - } + if (defaultRouteRoom != null) + { + defaultRouteRoom.RunDefaultPresentRoute(); } } - // Check room power state first - } + // Check room power state first + } } + } - void CreateEvent(ScheduledEvent schEvent, string name) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Adding Event: '{0}'", name); - // Create the event - if (schEvent == null) - schEvent = new ScheduledEvent(name, FeatureEventGroup); + void CreateEvent(ScheduledEvent schEvent, string name) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Adding Event: '{0}'", name); + // Create the event + if (schEvent == null) + schEvent = new ScheduledEvent(name, FeatureEventGroup); - // Set up its initial properties - - schEvent.Acknowledgeable = false; + // Set up its initial properties + + schEvent.Acknowledgeable = false; - if(!schEvent.Persistent) - schEvent.Persistent = true; + if(!schEvent.Persistent) + schEvent.Persistent = true; - schEvent.DateAndTime.SetFirstDayOfWeek(ScheduledEventCommon.eFirstDayOfWeek.Sunday); + schEvent.DateAndTime.SetFirstDayOfWeek(ScheduledEventCommon.eFirstDayOfWeek.Sunday); - // Set config driven properties + // Set config driven properties - if (schEvent.Name == FeatureEnableEventName) - { - schEvent.Description = "Enables the RoomOnToDefaultSourceWhenOccupiedFeature"; + if (schEvent.Name == FeatureEnableEventName) + { + schEvent.Description = "Enables the RoomOnToDefaultSourceWhenOccupiedFeature"; - var eventRecurrennce = CalculateDaysOfWeekRecurrence(); + var eventRecurrennce = CalculateDaysOfWeekRecurrence(); - var eventTime = new DateTime(); + var eventTime = new DateTime(); - // Check to make sure the date for this event is in the future - if (DateTime.Now.CompareTo(FeatureEnabledTime) > 0) - eventTime = FeatureEnabledTime.AddDays(1); - else - eventTime = FeatureEnabledTime; + // Check to make sure the date for this event is in the future + if (DateTime.Now.CompareTo(FeatureEnabledTime) > 0) + eventTime = FeatureEnabledTime.AddDays(1); + else + eventTime = FeatureEnabledTime; - Debug.LogMessage(LogEventLevel.Debug, this, "eventTime (before recurrence check): {0}", eventTime); + Debug.LogMessage(LogEventLevel.Debug, this, "eventTime (before recurrence check): {0}", eventTime); - // Check day of week against recurrence days and move date ahead as necessary to avoid throwing an exception by trying to set the event - // start date on a day of the week that doesn't match teh recurrence values - while(!SchedulerUtilities.CheckIfDayOfWeekMatchesRecurrenceDays(eventTime, eventRecurrennce)) - { - eventTime = eventTime.AddDays(1); - Debug.LogMessage(LogEventLevel.Debug, this, "eventTime does not fall on a recurrence weekday. eventTime: {0}", eventTime); - } + // Check day of week against recurrence days and move date ahead as necessary to avoid throwing an exception by trying to set the event + // start date on a day of the week that doesn't match teh recurrence values + while(!SchedulerUtilities.CheckIfDayOfWeekMatchesRecurrenceDays(eventTime, eventRecurrennce)) + { + eventTime = eventTime.AddDays(1); + Debug.LogMessage(LogEventLevel.Debug, this, "eventTime does not fall on a recurrence weekday. eventTime: {0}", eventTime); + } - schEvent.DateAndTime.SetAbsoluteEventTime(eventTime); + schEvent.DateAndTime.SetAbsoluteEventTime(eventTime); - Debug.LogMessage(LogEventLevel.Debug, this, "Event '{0}' Absolute time set to {1}", schEvent.Name, schEvent.DateAndTime.ToString()); + Debug.LogMessage(LogEventLevel.Debug, this, "Event '{0}' Absolute time set to {1}", schEvent.Name, schEvent.DateAndTime.ToString()); - //CalculateAndSetAcknowledgeExpirationTimeout(schEvent, FeatureEnabledTime, FeatureDisabledTime); + //CalculateAndSetAcknowledgeExpirationTimeout(schEvent, FeatureEnabledTime, FeatureDisabledTime); - schEvent.Recurrence.Weekly(eventRecurrennce); + schEvent.Recurrence.Weekly(eventRecurrennce); - } - else if (schEvent.Name == FeatureDisableEventName) - { - schEvent.Description = "Disables the RoomOnToDefaultSourceWhenOccupiedFeature"; + } + else if (schEvent.Name == FeatureDisableEventName) + { + schEvent.Description = "Disables the RoomOnToDefaultSourceWhenOccupiedFeature"; - // Check to make sure the date for this event is in the future - if (DateTime.Now.CompareTo(FeatureDisabledTime) > 0) - schEvent.DateAndTime.SetAbsoluteEventTime(FeatureDisabledTime.AddDays(1)); - else - schEvent.DateAndTime.SetAbsoluteEventTime(FeatureDisabledTime); + // Check to make sure the date for this event is in the future + if (DateTime.Now.CompareTo(FeatureDisabledTime) > 0) + schEvent.DateAndTime.SetAbsoluteEventTime(FeatureDisabledTime.AddDays(1)); + else + schEvent.DateAndTime.SetAbsoluteEventTime(FeatureDisabledTime); - Debug.LogMessage(LogEventLevel.Debug, this, "Event '{0}' Absolute time set to {1}", schEvent.Name, schEvent.DateAndTime.ToString()); + Debug.LogMessage(LogEventLevel.Debug, this, "Event '{0}' Absolute time set to {1}", schEvent.Name, schEvent.DateAndTime.ToString()); - CalculateAndSetAcknowledgeExpirationTimeout(schEvent, FeatureDisabledTime, FeatureEnabledTime); + CalculateAndSetAcknowledgeExpirationTimeout(schEvent, FeatureDisabledTime, FeatureEnabledTime); - schEvent.Recurrence.Daily(); - } + schEvent.Recurrence.Daily(); } + } - void CalculateAndSetAcknowledgeExpirationTimeout(ScheduledEvent schEvent, DateTime time1, DateTime time2) - { - Debug.LogMessage(LogEventLevel.Debug, this, "time1.Hour = {0}", time1.Hour); - Debug.LogMessage(LogEventLevel.Debug, this, "time2.Hour = {0}", time2.Hour); - Debug.LogMessage(LogEventLevel.Debug, this, "time1.Minute = {0}", time1.Minute); - Debug.LogMessage(LogEventLevel.Debug, this, "time2.Minute = {0}", time2.Minute); + void CalculateAndSetAcknowledgeExpirationTimeout(ScheduledEvent schEvent, DateTime time1, DateTime time2) + { + Debug.LogMessage(LogEventLevel.Debug, this, "time1.Hour = {0}", time1.Hour); + Debug.LogMessage(LogEventLevel.Debug, this, "time2.Hour = {0}", time2.Hour); + Debug.LogMessage(LogEventLevel.Debug, this, "time1.Minute = {0}", time1.Minute); + Debug.LogMessage(LogEventLevel.Debug, this, "time2.Minute = {0}", time2.Minute); - // Calculate the Acknowledge Expiration timer to be the time between the enable and dispable events, less one minute - var ackHours = time2.Hour - time1.Hour; - if(ackHours < 0) - ackHours = ackHours + 24; - var ackMinutes = time2.Minute - time1.Minute; + // Calculate the Acknowledge Expiration timer to be the time between the enable and dispable events, less one minute + var ackHours = time2.Hour - time1.Hour; + if(ackHours < 0) + ackHours = ackHours + 24; + var ackMinutes = time2.Minute - time1.Minute; - Debug.LogMessage(LogEventLevel.Debug, this, "ackHours = {0}, ackMinutes = {1}", ackHours, ackMinutes); + Debug.LogMessage(LogEventLevel.Debug, this, "ackHours = {0}, ackMinutes = {1}", ackHours, ackMinutes); - var ackTotalMinutes = ((ackHours * 60) + ackMinutes) - 1; + var ackTotalMinutes = ((ackHours * 60) + ackMinutes) - 1; - var ackExpHour = ackTotalMinutes / 60; - var ackExpMinutes = ackTotalMinutes % 60; + var ackExpHour = ackTotalMinutes / 60; + var ackExpMinutes = ackTotalMinutes % 60; - Debug.LogMessage(LogEventLevel.Debug, this, "Acknowledge Expiration Timeout: {0} hours, {1} minutes", ackExpHour, ackExpMinutes); + Debug.LogMessage(LogEventLevel.Debug, this, "Acknowledge Expiration Timeout: {0} hours, {1} minutes", ackExpHour, ackExpMinutes); - schEvent.AcknowledgeExpirationTimeout.Hour = (ushort)(ackHours); - schEvent.AcknowledgeExpirationTimeout.Minute = (ushort)(ackExpMinutes); - } + schEvent.AcknowledgeExpirationTimeout.Hour = (ushort)(ackHours); + schEvent.AcknowledgeExpirationTimeout.Minute = (ushort)(ackExpMinutes); + } - /// - /// Checks existing event to see if it matches the execution time - /// - /// - /// - bool CheckExistingEventTimeForMatch(ScheduledEvent existingEvent, DateTime newTime) - { - bool isMatch = true; + /// + /// Checks existing event to see if it matches the execution time + /// + /// + /// + bool CheckExistingEventTimeForMatch(ScheduledEvent existingEvent, DateTime newTime) + { + bool isMatch = true; - // Check to see if hour and minute match - if (existingEvent.DateAndTime.Hour != newTime.Hour || existingEvent.DateAndTime.Minute != newTime.Minute) - return false; + // Check to see if hour and minute match + if (existingEvent.DateAndTime.Hour != newTime.Hour || existingEvent.DateAndTime.Minute != newTime.Minute) + return false; - return isMatch; - } + return isMatch; + } - /// - /// Checks existing event to see if it matches the recurrence days - /// - /// - /// - /// - bool CheckExistingEventRecurrenceForMatch(ScheduledEvent existingEvent, ScheduledEventCommon.eWeekDays eWeekdays) - { - bool isMatch = true; + /// + /// Checks existing event to see if it matches the recurrence days + /// + /// + /// + /// + bool CheckExistingEventRecurrenceForMatch(ScheduledEvent existingEvent, ScheduledEventCommon.eWeekDays eWeekdays) + { + bool isMatch = true; - // Check to see if recurrence matches - if (eWeekdays != existingEvent.Recurrence.RecurrenceDays) - return false; + // Check to see if recurrence matches + if (eWeekdays != existingEvent.Recurrence.RecurrenceDays) + return false; - return isMatch; - } + return isMatch; + } - /// - /// Adds the Enable event to the local event group and sets its properties based on config - /// - void AddEnableEventToGroup() + /// + /// Adds the Enable event to the local event group and sets its properties based on config + /// + void AddEnableEventToGroup() + { + if (!FeatureEventGroup.ScheduledEvents.ContainsKey(FeatureEnableEventName)) { - if (!FeatureEventGroup.ScheduledEvents.ContainsKey(FeatureEnableEventName)) - { - CreateEvent(FeatureEnableEvent, FeatureEnableEventName); - } - else - { - // Check if existing event has same time and recurrence as config values + CreateEvent(FeatureEnableEvent, FeatureEnableEventName); + } + else + { + // Check if existing event has same time and recurrence as config values - FeatureEnableEvent = FeatureEventGroup.ScheduledEvents[FeatureEnableEventName]; - Debug.LogMessage(LogEventLevel.Debug, this, "Enable event already found in group"); + FeatureEnableEvent = FeatureEventGroup.ScheduledEvents[FeatureEnableEventName]; + Debug.LogMessage(LogEventLevel.Debug, this, "Enable event already found in group"); - // Check config times and days against DateAndTime of existing event. If different, delete existing event and create new event - if(!CheckExistingEventTimeForMatch(FeatureEnableEvent, FeatureEnabledTime) || !CheckExistingEventRecurrenceForMatch(FeatureEnableEvent, CalculateDaysOfWeekRecurrence())) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Existing event does not match new config properties. Deleting exisiting event: '{0}'", FeatureEnableEvent.Name); - FeatureEventGroup.DeleteEvent(FeatureEnableEvent); + // Check config times and days against DateAndTime of existing event. If different, delete existing event and create new event + if(!CheckExistingEventTimeForMatch(FeatureEnableEvent, FeatureEnabledTime) || !CheckExistingEventRecurrenceForMatch(FeatureEnableEvent, CalculateDaysOfWeekRecurrence())) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Existing event does not match new config properties. Deleting exisiting event: '{0}'", FeatureEnableEvent.Name); + FeatureEventGroup.DeleteEvent(FeatureEnableEvent); - FeatureEnableEvent = null; + FeatureEnableEvent = null; - CreateEvent(FeatureEnableEvent, FeatureEnableEventName); - } + CreateEvent(FeatureEnableEvent, FeatureEnableEventName); } - } - /// - /// Adds the Enable event to the local event group and sets its properties based on config - /// - void AddDisableEventToGroup() + } + + /// + /// Adds the Enable event to the local event group and sets its properties based on config + /// + void AddDisableEventToGroup() + { + if (!FeatureEventGroup.ScheduledEvents.ContainsKey(FeatureDisableEventName)) { - if (!FeatureEventGroup.ScheduledEvents.ContainsKey(FeatureDisableEventName)) - { - CreateEvent(FeatureDisableEvent, FeatureDisableEventName); - } - else - { - FeatureDisableEvent = FeatureEventGroup.ScheduledEvents[FeatureDisableEventName]; - Debug.LogMessage(LogEventLevel.Debug, this, "Disable event already found in group"); + CreateEvent(FeatureDisableEvent, FeatureDisableEventName); + } + else + { + FeatureDisableEvent = FeatureEventGroup.ScheduledEvents[FeatureDisableEventName]; + Debug.LogMessage(LogEventLevel.Debug, this, "Disable event already found in group"); - // Check config times against DateAndTime of existing event. If different, delete existing event and create new event - if(!CheckExistingEventTimeForMatch(FeatureDisableEvent, FeatureDisabledTime)) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Existing event does not match new config properties. Deleting exisiting event: '{0}'", FeatureDisableEvent.Name); + // Check config times against DateAndTime of existing event. If different, delete existing event and create new event + if(!CheckExistingEventTimeForMatch(FeatureDisableEvent, FeatureDisabledTime)) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Existing event does not match new config properties. Deleting exisiting event: '{0}'", FeatureDisableEvent.Name); - FeatureEventGroup.DeleteEvent(FeatureDisableEvent); + FeatureEventGroup.DeleteEvent(FeatureDisableEvent); - FeatureDisableEvent = null; + FeatureDisableEvent = null; - CreateEvent(FeatureDisableEvent, FeatureDisableEventName); - } + CreateEvent(FeatureDisableEvent, FeatureDisableEventName); } } + } - /// - /// Calculates the correct bitfield enum value for the event recurrence based on the config values - /// - /// - ScheduledEventCommon.eWeekDays CalculateDaysOfWeekRecurrence() - { - ScheduledEventCommon.eWeekDays value = new ScheduledEventCommon.eWeekDays(); - - if (PropertiesConfig.EnableSunday) - value = value | ScheduledEventCommon.eWeekDays.Sunday; - if (PropertiesConfig.EnableMonday) - value = value | ScheduledEventCommon.eWeekDays.Monday; - if (PropertiesConfig.EnableTuesday) - value = value | ScheduledEventCommon.eWeekDays.Tuesday; - if (PropertiesConfig.EnableWednesday) - value = value | ScheduledEventCommon.eWeekDays.Wednesday; - if (PropertiesConfig.EnableThursday) - value = value | ScheduledEventCommon.eWeekDays.Thursday; - if (PropertiesConfig.EnableFriday) - value = value | ScheduledEventCommon.eWeekDays.Friday; - if (PropertiesConfig.EnableSaturday) - value = value | ScheduledEventCommon.eWeekDays.Saturday; - - return value; - } + /// + /// Calculates the correct bitfield enum value for the event recurrence based on the config values + /// + /// + ScheduledEventCommon.eWeekDays CalculateDaysOfWeekRecurrence() + { + ScheduledEventCommon.eWeekDays value = new ScheduledEventCommon.eWeekDays(); + + if (PropertiesConfig.EnableSunday) + value = value | ScheduledEventCommon.eWeekDays.Sunday; + if (PropertiesConfig.EnableMonday) + value = value | ScheduledEventCommon.eWeekDays.Monday; + if (PropertiesConfig.EnableTuesday) + value = value | ScheduledEventCommon.eWeekDays.Tuesday; + if (PropertiesConfig.EnableWednesday) + value = value | ScheduledEventCommon.eWeekDays.Wednesday; + if (PropertiesConfig.EnableThursday) + value = value | ScheduledEventCommon.eWeekDays.Thursday; + if (PropertiesConfig.EnableFriday) + value = value | ScheduledEventCommon.eWeekDays.Friday; + if (PropertiesConfig.EnableSaturday) + value = value | ScheduledEventCommon.eWeekDays.Saturday; + + return value; + } - /// - /// Callback for event that enables feature. Enables feature if config property is true - /// - /// - /// - void FeatureEnableEvent_UserCallBack(ScheduledEvent SchEvent, ScheduledEventCommon.eCallbackReason type) + /// + /// Callback for event that enables feature. Enables feature if config property is true + /// + /// + /// + void FeatureEnableEvent_UserCallBack(ScheduledEvent SchEvent, ScheduledEventCommon.eCallbackReason type) + { + if (type == ScheduledEventCommon.eCallbackReason.NormalExpiration) { - if (type == ScheduledEventCommon.eCallbackReason.NormalExpiration) - { - if(PropertiesConfig.EnableRoomOnWhenOccupied) - FeatureEnabled = true; + if(PropertiesConfig.EnableRoomOnWhenOccupied) + FeatureEnabled = true; - Debug.LogMessage(LogEventLevel.Debug, this, "RoomOnToDefaultSourceWhenOccupied Feature Enabled."); - } + Debug.LogMessage(LogEventLevel.Debug, this, "RoomOnToDefaultSourceWhenOccupied Feature Enabled."); } + } - /// - /// Callback for event that enables feature. Disables feature - /// - /// - /// - void FeatureDisableEvent_UserCallBack(ScheduledEvent SchEvent, ScheduledEventCommon.eCallbackReason type) + /// + /// Callback for event that enables feature. Disables feature + /// + /// + /// + void FeatureDisableEvent_UserCallBack(ScheduledEvent SchEvent, ScheduledEventCommon.eCallbackReason type) + { + if (type == ScheduledEventCommon.eCallbackReason.NormalExpiration) { - if (type == ScheduledEventCommon.eCallbackReason.NormalExpiration) - { - FeatureEnabled = false; + FeatureEnabled = false; - Debug.LogMessage(LogEventLevel.Debug, this, "RoomOnToDefaultSourceWhenOccupied Feature Disabled."); - } + Debug.LogMessage(LogEventLevel.Debug, this, "RoomOnToDefaultSourceWhenOccupied Feature Disabled."); } } +} - public class RoomOnToDefaultSourceWhenOccupiedConfig - { - [JsonProperty("roomKey")] - public string RoomKey { get; set; } +public class RoomOnToDefaultSourceWhenOccupiedConfig +{ + [JsonProperty("roomKey")] + public string RoomKey { get; set; } - [JsonProperty("enableRoomOnWhenOccupied")] - public bool EnableRoomOnWhenOccupied { get; set; } + [JsonProperty("enableRoomOnWhenOccupied")] + public bool EnableRoomOnWhenOccupied { get; set; } - [JsonProperty("occupancyStartTime")] - public string OccupancyStartTime { get; set; } + [JsonProperty("occupancyStartTime")] + public string OccupancyStartTime { get; set; } - [JsonProperty("occupancyEndTime")] - public string OccupancyEndTime { get; set; } + [JsonProperty("occupancyEndTime")] + public string OccupancyEndTime { get; set; } - [JsonProperty("enableSunday")] - public bool EnableSunday { get; set; } + [JsonProperty("enableSunday")] + public bool EnableSunday { get; set; } - [JsonProperty("enableMonday")] - public bool EnableMonday { get; set; } + [JsonProperty("enableMonday")] + public bool EnableMonday { get; set; } - [JsonProperty("enableTuesday")] - public bool EnableTuesday { get; set; } + [JsonProperty("enableTuesday")] + public bool EnableTuesday { get; set; } - [JsonProperty("enableWednesday")] - public bool EnableWednesday { get; set; } + [JsonProperty("enableWednesday")] + public bool EnableWednesday { get; set; } - [JsonProperty("enableThursday")] - public bool EnableThursday { get; set; } + [JsonProperty("enableThursday")] + public bool EnableThursday { get; set; } - [JsonProperty("enableFriday")] - public bool EnableFriday { get; set; } + [JsonProperty("enableFriday")] + public bool EnableFriday { get; set; } - [JsonProperty("enableSaturday")] - public bool EnableSaturday { get; set; } - } + [JsonProperty("enableSaturday")] + public bool EnableSaturday { get; set; } +} - public class RoomOnToDefaultSourceWhenOccupiedFactory : EssentialsDeviceFactory +public class RoomOnToDefaultSourceWhenOccupiedFactory : EssentialsDeviceFactory +{ + public RoomOnToDefaultSourceWhenOccupiedFactory() { - public RoomOnToDefaultSourceWhenOccupiedFactory() - { - TypeNames = new List() { "roomonwhenoccupancydetectedfeature" }; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new RoomOnToDefaultSourceWhenOccupied Device"); - return new RoomOnToDefaultSourceWhenOccupied(dc); - } + TypeNames = new List() { "roomonwhenoccupancydetectedfeature" }; } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new RoomOnToDefaultSourceWhenOccupied Device"); + return new RoomOnToDefaultSourceWhenOccupied(dc); + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs index d2a167394..3d1010e44 100644 --- a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs +++ b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs @@ -8,482 +8,481 @@ using System.Threading; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Represents a device that manages room combinations by controlling partitions and scenarios. +/// +/// The allows for dynamic configuration of room +/// combinations based on partition states and predefined scenarios. It supports both automatic and manual modes +/// for managing room combinations. In automatic mode, the device determines the current room combination scenario +/// based on partition sensor states. In manual mode, scenarios can be set explicitly by the user. +public class EssentialsRoomCombiner : EssentialsDevice, IEssentialsRoomCombiner { - /// - /// Represents a device that manages room combinations by controlling partitions and scenarios. - /// - /// The allows for dynamic configuration of room - /// combinations based on partition states and predefined scenarios. It supports both automatic and manual modes - /// for managing room combinations. In automatic mode, the device determines the current room combination scenario - /// based on partition sensor states. In manual mode, scenarios can be set explicitly by the user. - public class EssentialsRoomCombiner : EssentialsDevice, IEssentialsRoomCombiner - { - private EssentialsRoomCombinerPropertiesConfig _propertiesConfig; + private EssentialsRoomCombinerPropertiesConfig _propertiesConfig; - private IRoomCombinationScenario _currentScenario; + private IRoomCombinationScenario _currentScenario; - private List _rooms; + private List _rooms; - /// - /// Gets a list of rooms represented as key-name pairs. - /// - public List Rooms + /// + /// Gets a list of rooms represented as key-name pairs. + /// + public List Rooms + { + get { - get - { - return _rooms.Cast().ToList(); - } + return _rooms.Cast().ToList(); } + } - private bool _isInAutoMode; + private bool _isInAutoMode; - /// - /// Gets or sets a value indicating whether the system is operating in automatic mode. - /// - /// Changing this property triggers an update event via - /// IsInAutoModeFeedback.FireUpdate(). Ensure that any event listeners are properly configured to handle - /// this update. - public bool IsInAutoMode + /// + /// Gets or sets a value indicating whether the system is operating in automatic mode. + /// + /// Changing this property triggers an update event via + /// IsInAutoModeFeedback.FireUpdate(). Ensure that any event listeners are properly configured to handle + /// this update. + public bool IsInAutoMode + { + get { - get + return _isInAutoMode; + } + set + { + if (value == _isInAutoMode) { - return _isInAutoMode; + return; } - set - { - if (value == _isInAutoMode) - { - return; - } - _isInAutoMode = value; - IsInAutoModeFeedback.FireUpdate(); - } + _isInAutoMode = value; + IsInAutoModeFeedback.FireUpdate(); } + } - /// - /// Gets a value indicating whether automatic mode is disabled. - /// - public bool DisableAutoMode + /// + /// Gets a value indicating whether automatic mode is disabled. + /// + public bool DisableAutoMode + { + get { - get - { - return _propertiesConfig.DisableAutoMode; - } + return _propertiesConfig.DisableAutoMode; } + } - private CTimer _scenarioChangeDebounceTimer; - - private int _scenarioChangeDebounceTimeSeconds = 10; // default to 10s - - private Mutex _scenarioChange = new Mutex(); - - /// - /// Initializes a new instance of the class, which manages room combination - /// scenarios and partition states. - /// - /// The class is designed to handle dynamic room - /// combination scenarios based on partition states. It supports both automatic and manual modes for managing - /// room combinations. By default, the instance starts in automatic mode unless the - /// specifies otherwise. After activation, the room combiner initializes partition state providers and sets up - /// the initial room configuration. Additionally, it subscribes to the event to ensure proper initialization of dependent devices - /// before determining or setting the room combination scenario. - /// The unique identifier for the room combiner instance. - /// The configuration properties for the room combiner, including default settings and debounce times. - public EssentialsRoomCombiner(string key, EssentialsRoomCombinerPropertiesConfig props) - : base(key) - { - _propertiesConfig = props; + private CTimer _scenarioChangeDebounceTimer; - Partitions = new List(); - RoomCombinationScenarios = new List(); + private int _scenarioChangeDebounceTimeSeconds = 10; // default to 10s - if (_propertiesConfig.ScenarioChangeDebounceTimeSeconds > 0) - { - _scenarioChangeDebounceTimeSeconds = _propertiesConfig.ScenarioChangeDebounceTimeSeconds; - } + private Mutex _scenarioChange = new Mutex(); - IsInAutoModeFeedback = new BoolFeedback(() => _isInAutoMode); + /// + /// Initializes a new instance of the class, which manages room combination + /// scenarios and partition states. + /// + /// The class is designed to handle dynamic room + /// combination scenarios based on partition states. It supports both automatic and manual modes for managing + /// room combinations. By default, the instance starts in automatic mode unless the + /// specifies otherwise. After activation, the room combiner initializes partition state providers and sets up + /// the initial room configuration. Additionally, it subscribes to the event to ensure proper initialization of dependent devices + /// before determining or setting the room combination scenario. + /// The unique identifier for the room combiner instance. + /// The configuration properties for the room combiner, including default settings and debounce times. + public EssentialsRoomCombiner(string key, EssentialsRoomCombinerPropertiesConfig props) + : base(key) + { + _propertiesConfig = props; - // default to auto mode - IsInAutoMode = true; + Partitions = new List(); + RoomCombinationScenarios = new List(); - if (_propertiesConfig.defaultToManualMode) - { - IsInAutoMode = false; - } + if (_propertiesConfig.ScenarioChangeDebounceTimeSeconds > 0) + { + _scenarioChangeDebounceTimeSeconds = _propertiesConfig.ScenarioChangeDebounceTimeSeconds; + } - IsInAutoModeFeedback.FireUpdate(); + IsInAutoModeFeedback = new BoolFeedback(() => _isInAutoMode); - CreateScenarios(); + // default to auto mode + IsInAutoMode = true; - AddPostActivationAction(() => - { - SetupPartitionStateProviders(); + if (_propertiesConfig.defaultToManualMode) + { + IsInAutoMode = false; + } - SetRooms(); - }); + IsInAutoModeFeedback.FireUpdate(); + CreateScenarios(); - // Subscribe to the AllDevicesInitialized event - // We need to wait until all devices are initialized in case - // any actions are dependent on 3rd party devices already being - // connected and initialized - DeviceManager.AllDevicesInitialized += (o, a) => - { - if (IsInAutoMode) - { - DetermineRoomCombinationScenario(); - } - else - { - SetRoomCombinationScenario(_propertiesConfig.defaultScenarioKey); - } - }; - } + AddPostActivationAction(() => + { + SetupPartitionStateProviders(); + + SetRooms(); + }); - private void CreateScenarios() + + // Subscribe to the AllDevicesInitialized event + // We need to wait until all devices are initialized in case + // any actions are dependent on 3rd party devices already being + // connected and initialized + DeviceManager.AllDevicesInitialized += (o, a) => { - foreach (var scenarioConfig in _propertiesConfig.Scenarios) + if (IsInAutoMode) { - var scenario = new RoomCombinationScenario(scenarioConfig); - RoomCombinationScenarios.Add(scenario); + DetermineRoomCombinationScenario(); } + else + { + SetRoomCombinationScenario(_propertiesConfig.defaultScenarioKey); + } + }; + } + + private void CreateScenarios() + { + foreach (var scenarioConfig in _propertiesConfig.Scenarios) + { + var scenario = new RoomCombinationScenario(scenarioConfig); + RoomCombinationScenarios.Add(scenario); } + } - private void SetRooms() + private void SetRooms() + { + _rooms = new List(); + + foreach (var roomKey in _propertiesConfig.RoomKeys) { - _rooms = new List(); + var room = DeviceManager.GetDeviceForKey(roomKey); - foreach (var roomKey in _propertiesConfig.RoomKeys) + if (DeviceManager.GetDeviceForKey(roomKey) is IEssentialsRoom essentialsRoom) { - var room = DeviceManager.GetDeviceForKey(roomKey); - - if (DeviceManager.GetDeviceForKey(roomKey) is IEssentialsRoom essentialsRoom) - { - _rooms.Add(essentialsRoom); - } + _rooms.Add(essentialsRoom); } + } - var rooms = DeviceManager.AllDevices.OfType().Cast(); + var rooms = DeviceManager.AllDevices.OfType().Cast(); - foreach (var room in rooms) - { - room.Deactivate(); - } + foreach (var room in rooms) + { + room.Deactivate(); } + } - private void SetupPartitionStateProviders() + private void SetupPartitionStateProviders() + { + foreach (var pConfig in _propertiesConfig.Partitions) { - foreach (var pConfig in _propertiesConfig.Partitions) - { - var sensor = DeviceManager.GetDeviceForKey(pConfig.DeviceKey) as IPartitionStateProvider; + var sensor = DeviceManager.GetDeviceForKey(pConfig.DeviceKey) as IPartitionStateProvider; - var partition = new EssentialsPartitionController(pConfig.Key, pConfig.Name, sensor, _propertiesConfig.defaultToManualMode, pConfig.AdjacentRoomKeys); + var partition = new EssentialsPartitionController(pConfig.Key, pConfig.Name, sensor, _propertiesConfig.defaultToManualMode, pConfig.AdjacentRoomKeys); - partition.PartitionPresentFeedback.OutputChange += PartitionPresentFeedback_OutputChange; + partition.PartitionPresentFeedback.OutputChange += PartitionPresentFeedback_OutputChange; - Partitions.Add(partition); - } + Partitions.Add(partition); } + } + + private void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + StartDebounceTimer(); + } + + private void StartDebounceTimer() + { + // default to 500ms for manual mode + var time = 500; - private void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e) + // if in auto mode, debounce the scenario change + if (IsInAutoMode) time = _scenarioChangeDebounceTimeSeconds * 1000; + + if (_scenarioChangeDebounceTimer == null) { - StartDebounceTimer(); + _scenarioChangeDebounceTimer = new CTimer((o) => DetermineRoomCombinationScenario(), time); } - - private void StartDebounceTimer() + else { - // default to 500ms for manual mode - var time = 500; - - // if in auto mode, debounce the scenario change - if (IsInAutoMode) time = _scenarioChangeDebounceTimeSeconds * 1000; + _scenarioChangeDebounceTimer.Reset(time); + } + } - if (_scenarioChangeDebounceTimer == null) - { - _scenarioChangeDebounceTimer = new CTimer((o) => DetermineRoomCombinationScenario(), time); - } - else - { - _scenarioChangeDebounceTimer.Reset(time); - } + /// + /// Determines the current room combination scenario based on the state of the partition sensors + /// + private void DetermineRoomCombinationScenario() + { + if (_scenarioChangeDebounceTimer != null) + { + _scenarioChangeDebounceTimer.Dispose(); + _scenarioChangeDebounceTimer = null; } - /// - /// Determines the current room combination scenario based on the state of the partition sensors - /// - private void DetermineRoomCombinationScenario() + this.LogInformation("Determining Combination Scenario"); + + var currentScenario = RoomCombinationScenarios.FirstOrDefault((s) => { - if (_scenarioChangeDebounceTimer != null) + this.LogDebug("Checking scenario {scenarioKey}", s.Key); + // iterate the partition states + foreach (var partitionState in s.PartitionStates) { - _scenarioChangeDebounceTimer.Dispose(); - _scenarioChangeDebounceTimer = null; - } + this.LogDebug("checking PartitionState {partitionStateKey}", partitionState.PartitionKey); + // get the partition by key + var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionState.PartitionKey)); - this.LogInformation("Determining Combination Scenario"); + this.LogDebug("Expected State: {partitionPresent} Actual State: {partitionState}", partitionState.PartitionPresent, partition.PartitionPresentFeedback.BoolValue); - var currentScenario = RoomCombinationScenarios.FirstOrDefault((s) => - { - this.LogDebug("Checking scenario {scenarioKey}", s.Key); - // iterate the partition states - foreach (var partitionState in s.PartitionStates) + if (partition != null && partitionState.PartitionPresent != partition.PartitionPresentFeedback.BoolValue) { - this.LogDebug("checking PartitionState {partitionStateKey}", partitionState.PartitionKey); - // get the partition by key - var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionState.PartitionKey)); + // the partition can't be found or the state doesn't match + return false; + } + } + // if it hasn't returned false by now we have the matching scenario + return true; + }); + + if (currentScenario != null) + { + this.LogInformation("Found combination Scenario {scenarioKey}", currentScenario.Key); + ChangeScenario(currentScenario); + } + } - this.LogDebug("Expected State: {partitionPresent} Actual State: {partitionState}", partitionState.PartitionPresent, partition.PartitionPresentFeedback.BoolValue); + private async Task ChangeScenario(IRoomCombinationScenario newScenario) + { + - if (partition != null && partitionState.PartitionPresent != partition.PartitionPresentFeedback.BoolValue) - { - // the partition can't be found or the state doesn't match - return false; - } - } - // if it hasn't returned false by now we have the matching scenario - return true; - }); + if (newScenario == _currentScenario) + { + return; + } - if (currentScenario != null) + // Deactivate the old scenario first + if (_currentScenario != null) { - this.LogInformation("Found combination Scenario {scenarioKey}", currentScenario.Key); - ChangeScenario(currentScenario); + Debug.LogMessage(LogEventLevel.Information, "Deactivating scenario {currentScenario}", this, _currentScenario.Name); + await _currentScenario.Deactivate(); } - } - private async Task ChangeScenario(IRoomCombinationScenario newScenario) - { - + _currentScenario = newScenario; - if (newScenario == _currentScenario) - { - return; - } + // Activate the new scenario + if (_currentScenario != null) + { + Debug.LogMessage(LogEventLevel.Debug, $"Current Scenario: {_currentScenario.Name}", this); + await _currentScenario.Activate(); + } - // Deactivate the old scenario first - if (_currentScenario != null) - { - Debug.LogMessage(LogEventLevel.Information, "Deactivating scenario {currentScenario}", this, _currentScenario.Name); - await _currentScenario.Deactivate(); - } + RoomCombinationScenarioChanged?.Invoke(this, new EventArgs()); - _currentScenario = newScenario; + + } - // Activate the new scenario - if (_currentScenario != null) - { - Debug.LogMessage(LogEventLevel.Debug, $"Current Scenario: {_currentScenario.Name}", this); - await _currentScenario.Activate(); - } + #region IEssentialsRoomCombiner Members - RoomCombinationScenarioChanged?.Invoke(this, new EventArgs()); + /// + /// Occurs when the room combination scenario changes. + /// + /// This event is triggered whenever the configuration or state of the room combination + /// changes. Subscribers can use this event to update their logic or UI based on the new scenario. + public event EventHandler RoomCombinationScenarioChanged; - + /// + /// Gets the current room combination scenario. + /// + public IRoomCombinationScenario CurrentScenario + { + get + { + return _currentScenario; } + } - #region IEssentialsRoomCombiner Members + /// + /// Gets the feedback indicating whether the system is currently in auto mode. + /// + public BoolFeedback IsInAutoModeFeedback { get; private set; } - /// - /// Occurs when the room combination scenario changes. - /// - /// This event is triggered whenever the configuration or state of the room combination - /// changes. Subscribers can use this event to update their logic or UI based on the new scenario. - public event EventHandler RoomCombinationScenarioChanged; + /// + /// Enables auto mode for the room combiner and its partitions, allowing automatic room combination scenarios to + /// be determined. + /// + /// Auto mode allows the room combiner to automatically adjust its configuration based on + /// the state of its partitions. If auto mode is disabled in the configuration, this method logs a warning and + /// does not enable auto mode. + public void SetAutoMode() + { + if(_propertiesConfig.DisableAutoMode) + { + this.LogWarning("Auto mode is disabled for this room combiner. Cannot set to auto mode."); + return; + } + IsInAutoMode = true; - /// - /// Gets the current room combination scenario. - /// - public IRoomCombinationScenario CurrentScenario + foreach (var partition in Partitions) { - get - { - return _currentScenario; - } + partition.SetAutoMode(); } - /// - /// Gets the feedback indicating whether the system is currently in auto mode. - /// - public BoolFeedback IsInAutoModeFeedback { get; private set; } - - /// - /// Enables auto mode for the room combiner and its partitions, allowing automatic room combination scenarios to - /// be determined. - /// - /// Auto mode allows the room combiner to automatically adjust its configuration based on - /// the state of its partitions. If auto mode is disabled in the configuration, this method logs a warning and - /// does not enable auto mode. - public void SetAutoMode() - { - if(_propertiesConfig.DisableAutoMode) - { - this.LogWarning("Auto mode is disabled for this room combiner. Cannot set to auto mode."); - return; - } - IsInAutoMode = true; + DetermineRoomCombinationScenario(); + } - foreach (var partition in Partitions) - { - partition.SetAutoMode(); - } + /// + /// Switches the system to manual mode, disabling automatic operations. + /// + /// This method sets the system to manual mode by updating the mode state and propagates + /// the change to all partitions. Once in manual mode, automatic operations are disabled for the system and its + /// partitions. + public void SetManualMode() + { + IsInAutoMode = false; - DetermineRoomCombinationScenario(); + foreach (var partition in Partitions) + { + partition.SetManualMode(); } + } - /// - /// Switches the system to manual mode, disabling automatic operations. - /// - /// This method sets the system to manual mode by updating the mode state and propagates - /// the change to all partitions. Once in manual mode, automatic operations are disabled for the system and its - /// partitions. - public void SetManualMode() + /// + /// Toggles the current mode between automatic and manual. + /// + /// If the current mode is automatic, this method switches to manual mode. If the + /// current mode is manual, it switches to automatic mode. + public void ToggleMode() + { + if (IsInAutoMode) { - IsInAutoMode = false; - - foreach (var partition in Partitions) - { - partition.SetManualMode(); - } + SetManualMode(); } - - /// - /// Toggles the current mode between automatic and manual. - /// - /// If the current mode is automatic, this method switches to manual mode. If the - /// current mode is manual, it switches to automatic mode. - public void ToggleMode() + else { - if (IsInAutoMode) - { - SetManualMode(); - } - else - { - SetAutoMode(); - } + SetAutoMode(); } + } - /// - /// Gets the collection of room combination scenarios. - /// - public List RoomCombinationScenarios { get; private set; } - - /// - /// Gets the collection of partition controllers managed by this instance. - /// - public List Partitions { get; private set; } - - /// - /// Toggles the state of the partition identified by the specified partition key. - /// - /// If no partition with the specified key exists, the method performs no - /// action. - /// The key of the partition whose state is to be toggled. This value cannot be null or empty. - public void TogglePartitionState(string partitionKey) - { - var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionKey)); + /// + /// Gets the collection of room combination scenarios. + /// + public List RoomCombinationScenarios { get; private set; } - if (partition != null) - { - partition.ToggglePartitionState(); - } + /// + /// Gets the collection of partition controllers managed by this instance. + /// + public List Partitions { get; private set; } + + /// + /// Toggles the state of the partition identified by the specified partition key. + /// + /// If no partition with the specified key exists, the method performs no + /// action. + /// The key of the partition whose state is to be toggled. This value cannot be null or empty. + public void TogglePartitionState(string partitionKey) + { + var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionKey)); + + if (partition != null) + { + partition.ToggglePartitionState(); } + } - /// - /// Sets the room combination scenario based on the specified scenario key. - /// - /// This method manually adjusts the partition states according to the specified - /// scenario. If the application is in auto mode, the operation will not proceed, and a log message will be - /// generated indicating that the mode must be set to manual first. If the specified scenario key does not - /// match any existing scenario, a debug log message will be generated. For each partition state in the - /// scenario, the corresponding partition will be updated to either "Present" or "Not Present" based on the - /// scenario's configuration. If a partition key in the scenario cannot be found, a debug log message will be - /// generated. - /// The key identifying the room combination scenario to apply. This must match the key of an existing scenario. - public void SetRoomCombinationScenario(string scenarioKey) + /// + /// Sets the room combination scenario based on the specified scenario key. + /// + /// This method manually adjusts the partition states according to the specified + /// scenario. If the application is in auto mode, the operation will not proceed, and a log message will be + /// generated indicating that the mode must be set to manual first. If the specified scenario key does not + /// match any existing scenario, a debug log message will be generated. For each partition state in the + /// scenario, the corresponding partition will be updated to either "Present" or "Not Present" based on the + /// scenario's configuration. If a partition key in the scenario cannot be found, a debug log message will be + /// generated. + /// The key identifying the room combination scenario to apply. This must match the key of an existing scenario. + public void SetRoomCombinationScenario(string scenarioKey) + { + if (IsInAutoMode) { - if (IsInAutoMode) - { - Debug.LogMessage(LogEventLevel.Information, this, "Cannot set room combination scenario when in auto mode. Set to auto mode first."); - return; - } + Debug.LogMessage(LogEventLevel.Information, this, "Cannot set room combination scenario when in auto mode. Set to auto mode first."); + return; + } - // Get the scenario - var scenario = RoomCombinationScenarios.FirstOrDefault((s) => s.Key.Equals(scenarioKey)); + // Get the scenario + var scenario = RoomCombinationScenarios.FirstOrDefault((s) => s.Key.Equals(scenarioKey)); - // Set the parition states from the scenario manually - if (scenario != null) + // Set the parition states from the scenario manually + if (scenario != null) + { + Debug.LogMessage(LogEventLevel.Information, this, "Manually setting scenario to '{0}'", scenario.Key); + foreach (var partitionState in scenario.PartitionStates) { - Debug.LogMessage(LogEventLevel.Information, this, "Manually setting scenario to '{0}'", scenario.Key); - foreach (var partitionState in scenario.PartitionStates) - { - var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionState.PartitionKey)); + var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionState.PartitionKey)); - if (partition != null) + if (partition != null) + { + if (partitionState.PartitionPresent) { - if (partitionState.PartitionPresent) - { - Debug.LogMessage(LogEventLevel.Information, this, "Manually setting state to Present for: '{0}'", partition.Key); - partition.SetPartitionStatePresent(); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Manually setting state to Not Present for: '{0}'", partition.Key); - partition.SetPartitionStateNotPresent(); - } + Debug.LogMessage(LogEventLevel.Information, this, "Manually setting state to Present for: '{0}'", partition.Key); + partition.SetPartitionStatePresent(); } else { - Debug.LogMessage(LogEventLevel.Debug, this, "Unable to find partition with key: '{0}'", partitionState.PartitionKey); + Debug.LogMessage(LogEventLevel.Information, this, "Manually setting state to Not Present for: '{0}'", partition.Key); + partition.SetPartitionStateNotPresent(); } } - } - else - { - Debug.LogMessage(LogEventLevel.Debug, this, "Unable to find scenario with key: '{0}'", scenarioKey); + else + { + Debug.LogMessage(LogEventLevel.Debug, this, "Unable to find partition with key: '{0}'", partitionState.PartitionKey); + } } } - - #endregion + else + { + Debug.LogMessage(LogEventLevel.Debug, this, "Unable to find scenario with key: '{0}'", scenarioKey); + } } + #endregion +} + +/// +/// Provides a factory for creating instances of devices. +/// +/// This factory is responsible for constructing devices +/// based on the provided configuration. It supports the type name "essentialsroomcombiner" for device +/// creation. +public class EssentialsRoomCombinerFactory : EssentialsDeviceFactory +{ /// - /// Provides a factory for creating instances of devices. + /// Initializes a new instance of the class. /// - /// This factory is responsible for constructing devices - /// based on the provided configuration. It supports the type name "essentialsroomcombiner" for device - /// creation. - public class EssentialsRoomCombinerFactory : EssentialsDeviceFactory + /// This factory is used to create instances of room combiners with the specified type + /// names. By default, the factory includes the type name "essentialsroomcombiner". + public EssentialsRoomCombinerFactory() { - /// - /// Initializes a new instance of the class. - /// - /// This factory is used to create instances of room combiners with the specified type - /// names. By default, the factory includes the type name "essentialsroomcombiner". - public EssentialsRoomCombinerFactory() - { - TypeNames = new List { "essentialsroomcombiner" }; - } + TypeNames = new List { "essentialsroomcombiner" }; + } - /// - /// Creates and initializes a new instance of the device. - /// - /// This method uses the provided device configuration to extract the properties and - /// create an device. Ensure that the configuration contains valid - /// properties for the device to be created successfully. - /// The device configuration containing the key and properties required to build the device. - /// A new instance of initialized with the specified configuration. - public override EssentialsDevice BuildDevice(PepperDash.Essentials.Core.Config.DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new EssentialsRoomCombiner Device"); + /// + /// Creates and initializes a new instance of the device. + /// + /// This method uses the provided device configuration to extract the properties and + /// create an device. Ensure that the configuration contains valid + /// properties for the device to be created successfully. + /// The device configuration containing the key and properties required to build the device. + /// A new instance of initialized with the specified configuration. + public override EssentialsDevice BuildDevice(PepperDash.Essentials.Core.Config.DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new EssentialsRoomCombiner Device"); - var props = dc.Properties.ToObject(); + var props = dc.Properties.ToObject(); - return new EssentialsRoomCombiner(dc.Key, props); - } + return new EssentialsRoomCombiner(dc.Key, props); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs index fec7e380b..9e4f6a154 100644 --- a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombinerPropertiesConfig.cs @@ -4,145 +4,144 @@ using Newtonsoft.Json; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Config properties for an EssentialsRoomCombiner device +/// +public class EssentialsRoomCombinerPropertiesConfig { + /// + /// Gets or sets a value indicating whether the system operates in automatic mode. + /// Some systems don't have partitions sensors, and show shouldn't allow auto mode to be turned on. When this is true in the configuration, + /// auto mode won't be allowed to be turned on. + /// + [JsonProperty("disableAutoMode")] + public bool DisableAutoMode { get; set; } + + /// + /// The list of partitions that device the rooms + /// + [JsonProperty("partitions")] + public List Partitions {get; set;} + /// - /// Config properties for an EssentialsRoomCombiner device - /// - public class EssentialsRoomCombinerPropertiesConfig - { - /// - /// Gets or sets a value indicating whether the system operates in automatic mode. - /// Some systems don't have partitions sensors, and show shouldn't allow auto mode to be turned on. When this is true in the configuration, - /// auto mode won't be allowed to be turned on. - /// - [JsonProperty("disableAutoMode")] - public bool DisableAutoMode { get; set; } - - /// - /// The list of partitions that device the rooms - /// - [JsonProperty("partitions")] - public List Partitions {get; set;} - - /// - /// The list of combinations scenarios for the rooms - /// - [JsonProperty("scenarios")] - public List Scenarios { get; set; } - - /// - /// The list of rooms keys that can be combined - /// - [JsonProperty("roomKeys")] - public List RoomKeys {get; set;} - - /// - /// Set to true to default to manual mode - /// - [JsonProperty("defaultToManualMode")] - public bool defaultToManualMode { get; set; } - - /// - /// The key of the scenario to default to at system startup if in manual mode - /// - [JsonProperty("defaultScenarioKey")] - public string defaultScenarioKey { get; set; } - - /// - /// Gets or sets the debounce time, in seconds, for scenario changes. - /// - [JsonProperty("scenarioChangeDebounceTimeSeconds")] - public int ScenarioChangeDebounceTimeSeconds { get; set; } - } + /// The list of combinations scenarios for the rooms + /// + [JsonProperty("scenarios")] + public List Scenarios { get; set; } + + /// + /// The list of rooms keys that can be combined + /// + [JsonProperty("roomKeys")] + public List RoomKeys {get; set;} /// - /// Config properties for a partition that separates rooms - /// - public class PartitionConfig : IKeyName - { - /// - /// Gets or sets the unique key associated with the object. - /// - [JsonProperty("key")] - public string Key { get; set; } - - /// - /// Gets or sets the name associated with the object. - /// - [JsonProperty("name")] - public string Name { get; set; } - - /// - /// Key of the device that implements IPartitionStateProvider to provide the state of the partition - /// - [JsonProperty("deviceKey")] - public string DeviceKey { get; set; } - - /// - /// Keys of the rooms that this partion would be located between - /// - [JsonProperty("adjacentRoomKeys")] - public List AdjacentRoomKeys { get; set; } - } + /// Set to true to default to manual mode + /// + [JsonProperty("defaultToManualMode")] + public bool defaultToManualMode { get; set; } /// - /// Config propeties for a room combination scenario - /// - public class RoomCombinationScenarioConfig : IKeyName - { - /// - /// Gets or sets the key associated with the object. - /// - [JsonProperty("key")] - public string Key { get; set; } - - /// - /// Gets or sets the name associated with the object. - /// - [JsonProperty("name")] - public string Name { get; set; } - - /// - /// Gets or sets the collection of partition states. - /// - [JsonProperty("partitionStates")] - public List PartitionStates { get; set; } - - /// - /// Determines which UI devices get mapped to which room in this scenario. The Key should be the key of the UI device and the Value should be the key of the room to map to - /// - [JsonProperty("uiMap")] - public Dictionary UiMap { get; set; } - - /// - /// Gets or sets the list of actions to be performed during device activation. - /// - [JsonProperty("activationActions")] - public List ActivationActions { get; set; } - - /// - /// Gets or sets the list of actions to be performed when a device is deactivated. - /// - [JsonProperty("deactivationActions")] - public List DeactivationActions { get; set; } - } + /// The key of the scenario to default to at system startup if in manual mode + /// + [JsonProperty("defaultScenarioKey")] + public string defaultScenarioKey { get; set; } + + /// + /// Gets or sets the debounce time, in seconds, for scenario changes. + /// + [JsonProperty("scenarioChangeDebounceTimeSeconds")] + public int ScenarioChangeDebounceTimeSeconds { get; set; } +} + +/// +/// Config properties for a partition that separates rooms +/// +public class PartitionConfig : IKeyName +{ + /// + /// Gets or sets the unique key associated with the object. + /// + [JsonProperty("key")] + public string Key { get; set; } + + /// + /// Gets or sets the name associated with the object. + /// + [JsonProperty("name")] + public string Name { get; set; } /// - /// Config properties to represent the state of a partition sensor in a RoomCombinationScenario - /// - public class PartitionState - { - /// - /// Gets or sets the partition key used to group and organize data within a storage system. - /// - [JsonProperty("partitionKey")] - public string PartitionKey { get; set; } - - /// - /// Gets or sets a value indicating whether a partition is currently present. - /// - [JsonProperty("partitionSensedState")] - public bool PartitionPresent { get; set; } - } + /// Key of the device that implements IPartitionStateProvider to provide the state of the partition + /// + [JsonProperty("deviceKey")] + public string DeviceKey { get; set; } + + /// + /// Keys of the rooms that this partion would be located between + /// + [JsonProperty("adjacentRoomKeys")] + public List AdjacentRoomKeys { get; set; } +} + +/// +/// Config propeties for a room combination scenario +/// +public class RoomCombinationScenarioConfig : IKeyName +{ + /// + /// Gets or sets the key associated with the object. + /// + [JsonProperty("key")] + public string Key { get; set; } + + /// + /// Gets or sets the name associated with the object. + /// + [JsonProperty("name")] + public string Name { get; set; } + + /// + /// Gets or sets the collection of partition states. + /// + [JsonProperty("partitionStates")] + public List PartitionStates { get; set; } + + /// + /// Determines which UI devices get mapped to which room in this scenario. The Key should be the key of the UI device and the Value should be the key of the room to map to + /// + [JsonProperty("uiMap")] + public Dictionary UiMap { get; set; } + + /// + /// Gets or sets the list of actions to be performed during device activation. + /// + [JsonProperty("activationActions")] + public List ActivationActions { get; set; } + + /// + /// Gets or sets the list of actions to be performed when a device is deactivated. + /// + [JsonProperty("deactivationActions")] + public List DeactivationActions { get; set; } +} + +/// +/// Config properties to represent the state of a partition sensor in a RoomCombinationScenario +/// +public class PartitionState +{ + /// + /// Gets or sets the partition key used to group and organize data within a storage system. + /// + [JsonProperty("partitionKey")] + public string PartitionKey { get; set; } + + /// + /// Gets or sets a value indicating whether a partition is currently present. + /// + [JsonProperty("partitionSensedState")] + public bool PartitionPresent { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Combining/IEssentialsRoomCombiner.cs b/src/PepperDash.Essentials.Core/Room/Combining/IEssentialsRoomCombiner.cs index 04dfd16fd..bf015b6f9 100644 --- a/src/PepperDash.Essentials.Core/Room/Combining/IEssentialsRoomCombiner.cs +++ b/src/PepperDash.Essentials.Core/Room/Combining/IEssentialsRoomCombiner.cs @@ -4,129 +4,127 @@ using Newtonsoft.Json; using PepperDash.Core; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Describes the functionality for an EssentailsRoomCombiner device +/// +public interface IEssentialsRoomCombiner : IKeyed +{ + /// + /// Indicates that the room combination scenario has changed + /// + event EventHandler RoomCombinationScenarioChanged; + + /// + /// The current room combination scenario + /// + [JsonProperty("currentScenario")] + IRoomCombinationScenario CurrentScenario { get; } + + /// + /// When true, indicates the current mode is auto mode + /// + [JsonIgnore] + BoolFeedback IsInAutoModeFeedback {get;} + + /// + /// Gets a value indicating whether the automatic mode is disabled. + /// + [JsonProperty("disableAutoMode")] + bool DisableAutoMode { get; } + /// + /// Gets a value indicating whether the system is operating in automatic mode. + /// + [JsonProperty("isInAutoMode")] + bool IsInAutoMode { get; } + + /// + /// Gets the collection of rooms associated with the current object. + /// + [JsonProperty("rooms")] + List Rooms { get; } + + /// + /// Sets auto mode + /// + void SetAutoMode(); + + /// + /// Sets manual mode + /// + void SetManualMode(); + + /// + /// Toggles the current mode between auto and manual + /// + void ToggleMode(); + + /// + /// The available room combinatino scenarios + /// + [JsonProperty("roomCombinationScenarios")] + List RoomCombinationScenarios { get; } + + /// + /// The partition + /// + [JsonProperty("partitions")] + List Partitions { get; } + + /// + /// Toggles the state of a manual partition sensor + /// + /// + void TogglePartitionState(string partitionKey); + + /// + /// Sets the room combination scenario (if in manual mode) + /// + /// + void SetRoomCombinationScenario(string scenarioKey); +} + +/// +/// Represents a scenario for combining rooms, including activation, deactivation, and associated state. +/// +/// This interface defines the behavior for managing room combination scenarios, including +/// activation and deactivation, tracking the active state, and managing related partition states and UI mappings. +/// Implementations of this interface are expected to handle the logic for room combinations based on the provided +/// partition states and UI mappings. +public interface IRoomCombinationScenario : IKeyName { /// - /// Describes the functionality for an EssentailsRoomCombiner device - /// - public interface IEssentialsRoomCombiner : IKeyed - { - /// - /// Indicates that the room combination scenario has changed - /// - event EventHandler RoomCombinationScenarioChanged; - - /// - /// The current room combination scenario - /// - [JsonProperty("currentScenario")] - IRoomCombinationScenario CurrentScenario { get; } - - /// - /// When true, indicates the current mode is auto mode - /// - [JsonIgnore] - BoolFeedback IsInAutoModeFeedback {get;} - - /// - /// Gets a value indicating whether the automatic mode is disabled. - /// - [JsonProperty("disableAutoMode")] - bool DisableAutoMode { get; } - /// - /// Gets a value indicating whether the system is operating in automatic mode. - /// - [JsonProperty("isInAutoMode")] - bool IsInAutoMode { get; } - - /// - /// Gets the collection of rooms associated with the current object. - /// - [JsonProperty("rooms")] - List Rooms { get; } - - /// - /// Sets auto mode - /// - void SetAutoMode(); - - /// - /// Sets manual mode - /// - void SetManualMode(); - - /// - /// Toggles the current mode between auto and manual - /// - void ToggleMode(); - - /// - /// The available room combinatino scenarios - /// - [JsonProperty("roomCombinationScenarios")] - List RoomCombinationScenarios { get; } - - /// - /// The partition - /// - [JsonProperty("partitions")] - List Partitions { get; } - - /// - /// Toggles the state of a manual partition sensor - /// - /// - void TogglePartitionState(string partitionKey); - - /// - /// Sets the room combination scenario (if in manual mode) - /// - /// - void SetRoomCombinationScenario(string scenarioKey); - } + /// When true, indicates that this room combination scenario is active + /// + [JsonIgnore] + BoolFeedback IsActiveFeedback { get; } /// - /// Represents a scenario for combining rooms, including activation, deactivation, and associated state. - /// - /// This interface defines the behavior for managing room combination scenarios, including - /// activation and deactivation, tracking the active state, and managing related partition states and UI mappings. - /// Implementations of this interface are expected to handle the logic for room combinations based on the provided - /// partition states and UI mappings. - public interface IRoomCombinationScenario : IKeyName - { - /// - /// When true, indicates that this room combination scenario is active - /// - [JsonIgnore] - BoolFeedback IsActiveFeedback { get; } - - /// - /// Gets a value indicating whether the entity is active. - /// - [JsonProperty("isActive")] - bool IsActive { get; } - - /// - /// Activates this room combination scenario - /// - Task Activate(); - - /// - /// Deactivates this room combination scenario - /// - Task Deactivate(); - - /// - /// The state of the partitions that would activate this scenario - /// - [JsonProperty("partitionStates")] - List PartitionStates { get; } - - /// - /// The mapping of UIs by key to rooms by key - /// - [JsonProperty("uiMap")] - Dictionary UiMap { get; set; } - } + /// Gets a value indicating whether the entity is active. + /// + [JsonProperty("isActive")] + bool IsActive { get; } + /// + /// Activates this room combination scenario + /// + Task Activate(); + + /// + /// Deactivates this room combination scenario + /// + Task Deactivate(); + + /// + /// The state of the partitions that would activate this scenario + /// + [JsonProperty("partitionStates")] + List PartitionStates { get; } + + /// + /// The mapping of UIs by key to rooms by key + /// + [JsonProperty("uiMap")] + Dictionary UiMap { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Combining/RoomCombinationScenario.cs b/src/PepperDash.Essentials.Core/Room/Combining/RoomCombinationScenario.cs index b0b338ec6..575528a50 100644 --- a/src/PepperDash.Essentials.Core/Room/Combining/RoomCombinationScenario.cs +++ b/src/PepperDash.Essentials.Core/Room/Combining/RoomCombinationScenario.cs @@ -5,107 +5,105 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Represents a room combination scenario +/// +public class RoomCombinationScenario : IRoomCombinationScenario, IKeyName { - /// - /// Represents a room combination scenario - /// - public class RoomCombinationScenario : IRoomCombinationScenario, IKeyName - { - private RoomCombinationScenarioConfig _config; + private RoomCombinationScenarioConfig _config; - [JsonProperty("key")] - public string Key { get; set; } + [JsonProperty("key")] + public string Key { get; set; } - [JsonProperty("name")] - public string Name { get; set; } + [JsonProperty("name")] + public string Name { get; set; } - [JsonProperty("partitionStates")] - public List PartitionStates { get; private set; } + [JsonProperty("partitionStates")] + public List PartitionStates { get; private set; } - [JsonProperty("uiMap")] - public Dictionary UiMap { get; set; } + [JsonProperty("uiMap")] + public Dictionary UiMap { get; set; } - private bool _isActive; + private bool _isActive; - [JsonProperty("isActive")] - public bool IsActive + [JsonProperty("isActive")] + public bool IsActive + { + get { return _isActive; } + set { - get { return _isActive; } - set + if (value == _isActive) { - if (value == _isActive) - { - return; - } - - _isActive = value; - IsActiveFeedback.FireUpdate(); + return; } + + _isActive = value; + IsActiveFeedback.FireUpdate(); } + } - [JsonIgnore] - public BoolFeedback IsActiveFeedback { get; private set; } + [JsonIgnore] + public BoolFeedback IsActiveFeedback { get; private set; } - private List activationActions; + private List activationActions; - private List deactivationActions; + private List deactivationActions; - public RoomCombinationScenario(RoomCombinationScenarioConfig config) - { - Key = config.Key; + public RoomCombinationScenario(RoomCombinationScenarioConfig config) + { + Key = config.Key; - Name = config.Name; + Name = config.Name; - PartitionStates = config.PartitionStates; + PartitionStates = config.PartitionStates; - UiMap = config.UiMap; + UiMap = config.UiMap; - activationActions = config.ActivationActions; + activationActions = config.ActivationActions; - deactivationActions = config.DeactivationActions; + deactivationActions = config.DeactivationActions; - _config = config; + _config = config; - IsActiveFeedback = new BoolFeedback(() => _isActive); - } + IsActiveFeedback = new BoolFeedback(() => _isActive); + } - public async Task Activate() - { - this.LogInformation("Activating Scenario {name} with {activationActionCount} action(s) defined", Name, activationActions.Count); + public async Task Activate() + { + this.LogInformation("Activating Scenario {name} with {activationActionCount} action(s) defined", Name, activationActions.Count); - List tasks = new List(); + List tasks = new List(); - if (activationActions != null) + if (activationActions != null) + { + foreach (var action in activationActions) { - foreach (var action in activationActions) - { - this.LogInformation("Running Activation action {@action}", action); - await DeviceJsonApi.DoDeviceActionAsync(action); - } + this.LogInformation("Running Activation action {@action}", action); + await DeviceJsonApi.DoDeviceActionAsync(action); } - - IsActive = true; } - public async Task Deactivate() - { - this.LogInformation("Deactivating Scenario {name} with {deactivationActionCount} action(s) defined", Name, deactivationActions.Count); + IsActive = true; + } + + public async Task Deactivate() + { + this.LogInformation("Deactivating Scenario {name} with {deactivationActionCount} action(s) defined", Name, deactivationActions.Count); - List tasks = new List(); + List tasks = new List(); - if (deactivationActions != null) + if (deactivationActions != null) + { + foreach (var action in deactivationActions) { - foreach (var action in deactivationActions) - { - this.LogInformation("Running deactivation action {actionDeviceKey}:{actionMethod}", action.DeviceKey, action.MethodName); - await DeviceJsonApi.DoDeviceActionAsync(action); - } + this.LogInformation("Running deactivation action {actionDeviceKey}:{actionMethod}", action.DeviceKey, action.MethodName); + await DeviceJsonApi.DoDeviceActionAsync(action); } - - IsActive = false; } + IsActive = false; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsDualDisplayRoomPropertiesConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsDualDisplayRoomPropertiesConfig.cs index 2eb56fd36..9420a3ac3 100644 --- a/src/PepperDash.Essentials.Core/Room/Config/EssentialsDualDisplayRoomPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsDualDisplayRoomPropertiesConfig.cs @@ -1,8 +1,7 @@  -namespace PepperDash.Essentials.Room.Config +namespace PepperDash.Essentials.Room.Config; + +public class EssentialsDualDisplayRoomPropertiesConfig : EssentialsNDisplayRoomPropertiesConfig { - public class EssentialsDualDisplayRoomPropertiesConfig : EssentialsNDisplayRoomPropertiesConfig - { - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsHuddleRoomPropertiesConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsHuddleRoomPropertiesConfig.cs index a0b3499f0..2ac5f2ffe 100644 --- a/src/PepperDash.Essentials.Core/Room/Config/EssentialsHuddleRoomPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsHuddleRoomPropertiesConfig.cs @@ -1,34 +1,33 @@ using Newtonsoft.Json; -namespace PepperDash.Essentials.Room.Config +namespace PepperDash.Essentials.Room.Config; + +/// +/// +/// +public class EssentialsHuddleRoomPropertiesConfig : EssentialsRoomPropertiesConfig { /// - /// + /// The key of the default display device /// - public class EssentialsHuddleRoomPropertiesConfig : EssentialsRoomPropertiesConfig - { - /// - /// The key of the default display device - /// - [JsonProperty("defaultDisplayKey")] - public string DefaultDisplayKey { get; set; } + [JsonProperty("defaultDisplayKey")] + public string DefaultDisplayKey { get; set; } - /// - /// The key of the default audio device - /// - [JsonProperty("defaultAudioKey")] - public string DefaultAudioKey { get; set; } + /// + /// The key of the default audio device + /// + [JsonProperty("defaultAudioKey")] + public string DefaultAudioKey { get; set; } - /// - /// The key of the source list for the room - /// - [JsonProperty("sourceListKey")] - public string SourceListKey { get; set; } + /// + /// The key of the source list for the room + /// + [JsonProperty("sourceListKey")] + public string SourceListKey { get; set; } - /// - /// The key of the default source item from the source list - /// - [JsonProperty("defaultSourceItem")] - public string DefaultSourceItem { get; set; } - } + /// + /// The key of the default source item from the source list + /// + [JsonProperty("defaultSourceItem")] + public string DefaultSourceItem { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs index 27164f573..852eff32f 100644 --- a/src/PepperDash.Essentials.Core/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs +++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsHuddleVtc1PropertiesConfig.cs @@ -1,13 +1,12 @@  using Newtonsoft.Json; -namespace PepperDash.Essentials.Room.Config -{ +namespace PepperDash.Essentials.Room.Config; + - public class EssentialsHuddleVtc1PropertiesConfig : EssentialsConferenceRoomPropertiesConfig - { +public class EssentialsHuddleVtc1PropertiesConfig : EssentialsConferenceRoomPropertiesConfig +{ [JsonProperty("defaultDisplayKey")] public string DefaultDisplayKey { get; set; } - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsNDisplayRoomPropertiesConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsNDisplayRoomPropertiesConfig.cs index 6d8762fab..a7c9344b6 100644 --- a/src/PepperDash.Essentials.Core/Room/Config/EssentialsNDisplayRoomPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsNDisplayRoomPropertiesConfig.cs @@ -4,31 +4,29 @@ using PepperDash.Core; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Room.Config -{ - /// - /// - /// - public class EssentialsNDisplayRoomPropertiesConfig : EssentialsConferenceRoomPropertiesConfig - { - [JsonProperty("defaultAudioBehavior")] - public string DefaultAudioBehavior { get; set; } - [JsonProperty("defaultVideoBehavior")] - public string DefaultVideoBehavior { get; set; } - [JsonProperty("displays")] - public Dictionary Displays { get; set; } +namespace PepperDash.Essentials.Room.Config; - public EssentialsNDisplayRoomPropertiesConfig() - { - Displays = new Dictionary(); - } - - } +/// +/// +/// +public class EssentialsNDisplayRoomPropertiesConfig : EssentialsConferenceRoomPropertiesConfig +{ + [JsonProperty("defaultAudioBehavior")] + public string DefaultAudioBehavior { get; set; } + [JsonProperty("defaultVideoBehavior")] + public string DefaultVideoBehavior { get; set; } + [JsonProperty("displays")] + public Dictionary Displays { get; set; } - public class DisplayItem : IKeyName + public EssentialsNDisplayRoomPropertiesConfig() { - public string Key { get; set; } - public string Name { get; set; } + Displays = new Dictionary(); } +} + +public class DisplayItem : IKeyName +{ + public string Key { get; set; } + public string Name { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsPresentationPropertiesConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsPresentationPropertiesConfig.cs index 53333f072..accf09ed1 100644 --- a/src/PepperDash.Essentials.Core/Room/Config/EssentialsPresentationPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsPresentationPropertiesConfig.cs @@ -1,22 +1,21 @@ using System.Collections.Generic; -namespace PepperDash.Essentials.Room.Config +namespace PepperDash.Essentials.Room.Config; + +/// +/// +/// +public class EssentialsPresentationRoomPropertiesConfig : EssentialsRoomPropertiesConfig { - /// - /// - /// - public class EssentialsPresentationRoomPropertiesConfig : EssentialsRoomPropertiesConfig - { - public string DefaultAudioBehavior { get; set; } - public string DefaultAudioKey { get; set; } - public string DefaultVideoBehavior { get; set; } - public List DisplayKeys { get; set; } - public string SourceListKey { get; set; } - public bool HasDsp { get; set; } + public string DefaultAudioBehavior { get; set; } + public string DefaultAudioKey { get; set; } + public string DefaultVideoBehavior { get; set; } + public List DisplayKeys { get; set; } + public string SourceListKey { get; set; } + public bool HasDsp { get; set; } - public EssentialsPresentationRoomPropertiesConfig() - { - DisplayKeys = new List(); - } + public EssentialsPresentationRoomPropertiesConfig() + { + DisplayKeys = new List(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs index e9a2c29bb..d2302d5a3 100644 --- a/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs +++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomConfig.cs @@ -7,27 +7,27 @@ using PepperDash.Essentials.Core.Privacy; using Serilog.Events; -namespace PepperDash.Essentials.Room.Config -{ +namespace PepperDash.Essentials.Room.Config; + public class EssentialsRoomConfigHelper { - /// - /// Gets and operating, standalone emergegncy object that can be plugged into a room. - /// Returns null if there is no emergency defined - /// - public static EssentialsRoomEmergencyBase GetEmergency(EssentialsRoomPropertiesConfig props, IEssentialsRoom room) + /// + /// Gets and operating, standalone emergegncy object that can be plugged into a room. + /// Returns null if there is no emergency defined + /// + public static EssentialsRoomEmergencyBase GetEmergency(EssentialsRoomPropertiesConfig props, IEssentialsRoom room) + { + // This emergency + var emergency = props.Emergency; + if (emergency != null) { - // This emergency - var emergency = props.Emergency; - if (emergency != null) - { - //switch on emergency type here. Right now only contact and shutdown - var e = new EssentialsRoomEmergencyContactClosure(room.Key + "-emergency", props.Emergency, room); - DeviceManager.AddDevice(e); - return e; - } - return null; + //switch on emergency type here. Right now only contact and shutdown + var e = new EssentialsRoomEmergencyContactClosure(room.Key + "-emergency", props.Emergency, room); + DeviceManager.AddDevice(e); + return e; } + return null; + } /// /// @@ -64,30 +64,30 @@ public static MicrophonePrivacyController GetMicrophonePrivacy( if (behaviour == "trackroomstate") { // Tie LED enable to room power state - var essRoom = room as IEssentialsRoom; - essRoom.OnFeedback.OutputChange += (o, a) => + var essRoom = room as IEssentialsRoom; + essRoom.OnFeedback.OutputChange += (o, a) => { - if (essRoom.OnFeedback.BoolValue) + if (essRoom.OnFeedback.BoolValue) mP.EnableLeds = true; else mP.EnableLeds = false; }; - mP.EnableLeds = essRoom.OnFeedback.BoolValue; + mP.EnableLeds = essRoom.OnFeedback.BoolValue; } else if (behaviour == "trackcallstate") { // Tie LED enable to room power state - var inCallRoom = room as IHasInCallFeedback; - inCallRoom.InCallFeedback.OutputChange += (o, a) => + var inCallRoom = room as IHasInCallFeedback; + inCallRoom.InCallFeedback.OutputChange += (o, a) => { - if (inCallRoom.InCallFeedback.BoolValue) + if (inCallRoom.InCallFeedback.BoolValue) mP.EnableLeds = true; else mP.EnableLeds = false; }; - mP.EnableLeds = inCallRoom.InCallFeedback.BoolValue; + mP.EnableLeds = inCallRoom.InCallFeedback.BoolValue; } return mP; @@ -95,9 +95,9 @@ public static MicrophonePrivacyController GetMicrophonePrivacy( } - /// - /// - /// +/// +/// +/// public class EssentialsRoomPropertiesConfig { [JsonProperty("addresses")] @@ -115,23 +115,23 @@ public class EssentialsRoomPropertiesConfig [JsonProperty("helpMessage")] public string HelpMessage { get; set; } - /// - /// Read this value to get the help message. It checks for the old and new config format. - /// - public string HelpMessageForDisplay + /// + /// Read this value to get the help message. It checks for the old and new config format. + /// + public string HelpMessageForDisplay + { + get { - get + if(Help != null && !string.IsNullOrEmpty(Help.Message)) { - if(Help != null && !string.IsNullOrEmpty(Help.Message)) - { - return Help.Message; - } - else - { - return HelpMessage; - } + return Help.Message; + } + else + { + return HelpMessage; } } + } [JsonProperty("environment")] public EssentialsEnvironmentPropertiesConfig Environment { get; set; } @@ -139,8 +139,8 @@ public string HelpMessageForDisplay [JsonProperty("logo")] public EssentialsLogoPropertiesConfig LogoLight { get; set; } - [JsonProperty("logoDark")] - public EssentialsLogoPropertiesConfig LogoDark { get; set; } + [JsonProperty("logoDark")] + public EssentialsLogoPropertiesConfig LogoDark { get; set; } [JsonProperty("microphonePrivacy")] public EssentialsRoomMicrophonePrivacyConfig MicrophonePrivacy { get; set; } @@ -163,215 +163,214 @@ public string HelpMessageForDisplay [JsonProperty("volumes")] public EssentialsRoomVolumesConfig Volumes { get; set; } - [JsonProperty("fusion")] - public EssentialsRoomFusionConfig Fusion { get; set; } + [JsonProperty("fusion")] + public EssentialsRoomFusionConfig Fusion { get; set; } - [JsonProperty("essentialsRoomUiBehaviorConfig", NullValueHandling=NullValueHandling.Ignore)] - public EssentialsRoomUiBehaviorConfig UiBehavior { get; set; } + [JsonProperty("essentialsRoomUiBehaviorConfig", NullValueHandling=NullValueHandling.Ignore)] + public EssentialsRoomUiBehaviorConfig UiBehavior { get; set; } [JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")] public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; } - /// - /// Indicates if this room represents a combination of other rooms - /// - [JsonProperty("isRoomCombinationScenario")] - public bool IsRoomCombinationScenario { get; set; } - - public EssentialsRoomPropertiesConfig() - { - LogoLight = new EssentialsLogoPropertiesConfig(); - LogoDark = new EssentialsLogoPropertiesConfig(); - } - } + /// + /// Indicates if this room represents a combination of other rooms + /// + [JsonProperty("isRoomCombinationScenario")] + public bool IsRoomCombinationScenario { get; set; } - public class EssentialsRoomUiBehaviorConfig + public EssentialsRoomPropertiesConfig() { - [JsonProperty("disableActivityButtonsWhileWarmingCooling")] - public bool DisableActivityButtonsWhileWarmingCooling { get; set; } + LogoLight = new EssentialsLogoPropertiesConfig(); + LogoDark = new EssentialsLogoPropertiesConfig(); } + } - public class EssentialsAvRoomPropertiesConfig : EssentialsRoomPropertiesConfig - { - [JsonProperty("defaultAudioKey")] - public string DefaultAudioKey { get; set; } - [JsonProperty("sourceListKey")] - public string SourceListKey { get; set; } - [JsonProperty("destinationListKey")] - public string DestinationListKey { get; set; } - [JsonProperty("audioControlPointListKey")] - public string AudioControlPointListKey { get; set; } - [JsonProperty("cameraListKey")] - public string CameraListKey { get; set; } - - - [JsonProperty("defaultSourceItem")] - public string DefaultSourceItem { get; set; } - /// - /// Indicates if the room supports advanced sharing - /// - [JsonProperty("supportsAdvancedSharing")] - public bool SupportsAdvancedSharing { get; set; } - /// - /// Indicates if non-tech users can change the share mode - /// - [JsonProperty("userCanChangeShareMode")] - public bool UserCanChangeShareMode { get; set; } - - - [JsonProperty("matrixRoutingKey", NullValueHandling = NullValueHandling.Ignore)] - public string MatrixRoutingKey { get; set; } - } +public class EssentialsRoomUiBehaviorConfig +{ + [JsonProperty("disableActivityButtonsWhileWarmingCooling")] + public bool DisableActivityButtonsWhileWarmingCooling { get; set; } +} - public class EssentialsConferenceRoomPropertiesConfig : EssentialsAvRoomPropertiesConfig - { - [JsonProperty("videoCodecKey")] - public string VideoCodecKey { get; set; } - [JsonProperty("audioCodecKey")] - public string AudioCodecKey { get; set; } +public class EssentialsAvRoomPropertiesConfig : EssentialsRoomPropertiesConfig +{ + [JsonProperty("defaultAudioKey")] + public string DefaultAudioKey { get; set; } + [JsonProperty("sourceListKey")] + public string SourceListKey { get; set; } + [JsonProperty("destinationListKey")] + public string DestinationListKey { get; set; } + [JsonProperty("audioControlPointListKey")] + public string AudioControlPointListKey { get; set; } + [JsonProperty("cameraListKey")] + public string CameraListKey { get; set; } + + + [JsonProperty("defaultSourceItem")] + public string DefaultSourceItem { get; set; } + /// + /// Indicates if the room supports advanced sharing + /// + [JsonProperty("supportsAdvancedSharing")] + public bool SupportsAdvancedSharing { get; set; } + /// + /// Indicates if non-tech users can change the share mode + /// + [JsonProperty("userCanChangeShareMode")] + public bool UserCanChangeShareMode { get; set; } - } + + [JsonProperty("matrixRoutingKey", NullValueHandling = NullValueHandling.Ignore)] + public string MatrixRoutingKey { get; set; } +} + +public class EssentialsConferenceRoomPropertiesConfig : EssentialsAvRoomPropertiesConfig +{ + [JsonProperty("videoCodecKey")] + public string VideoCodecKey { get; set; } + [JsonProperty("audioCodecKey")] + public string AudioCodecKey { get; set; } + +} public class EssentialsEnvironmentPropertiesConfig { public bool Enabled { get; set; } - [JsonProperty("deviceKeys")] - public List DeviceKeys { get; set; } + [JsonProperty("deviceKeys")] + public List DeviceKeys { get; set; } - public EssentialsEnvironmentPropertiesConfig() - { - DeviceKeys = new List(); - } + public EssentialsEnvironmentPropertiesConfig() + { + DeviceKeys = new List(); + } } - public class EssentialsRoomFusionConfig +public class EssentialsRoomFusionConfig +{ + public uint IpIdInt { - public uint IpIdInt + get { - get + try { - try - { - return Convert.ToUInt32(IpId, 16); - } - catch (Exception) - { - throw new FormatException(string.Format("ERROR:Unable to convert IP ID: {0} to hex. Error:\n{1}", IpId)); - } - + return Convert.ToUInt32(IpId, 16); } + catch (Exception) + { + throw new FormatException(string.Format("ERROR:Unable to convert IP ID: {0} to hex. Error:\n{1}", IpId)); + } + } + } - [JsonProperty("ipId")] - public string IpId { get; set; } + [JsonProperty("ipId")] + public string IpId { get; set; } - [JsonProperty("joinMapKey")] - public string JoinMapKey { get; set; } + [JsonProperty("joinMapKey")] + public string JoinMapKey { get; set; } - } +} - public class EssentialsRoomMicrophonePrivacyConfig - { +public class EssentialsRoomMicrophonePrivacyConfig +{ [JsonProperty("deviceKey")] public string DeviceKey { get; set; } [JsonProperty("behaviour")] public string Behaviour { get; set; } - } +} - /// - /// Properties for the help text box - /// - public class EssentialsHelpPropertiesConfig - { +/// +/// Properties for the help text box +/// +public class EssentialsHelpPropertiesConfig +{ [JsonProperty("message")] public string Message { get; set; } [JsonProperty("showCallButton")] public bool ShowCallButton { get; set; } - + /// - /// Defaults to "Call Help Desk" - /// + /// Defaults to "Call Help Desk" + /// [JsonProperty("callButtonText")] public string CallButtonText { get; set; } - public EssentialsHelpPropertiesConfig() - { - CallButtonText = "Call Help Desk"; - } + public EssentialsHelpPropertiesConfig() + { + CallButtonText = "Call Help Desk"; } +} - /// - /// - /// - public class EssentialsOneButtonMeetingPropertiesConfig - { +/// +/// +/// +public class EssentialsOneButtonMeetingPropertiesConfig +{ [JsonProperty("enable")] public bool Enable { get; set; } - } +} - public class EssentialsRoomAddressPropertiesConfig - { +public class EssentialsRoomAddressPropertiesConfig +{ [JsonProperty("phoneNumber")] public string PhoneNumber { get; set; } [JsonProperty("sipAddress")] public string SipAddress { get; set; } - } +} - /// - /// Properties for the room's logo on panels - /// - public class EssentialsLogoPropertiesConfig - { +/// +/// Properties for the room's logo on panels +/// +public class EssentialsLogoPropertiesConfig +{ [JsonProperty("type")] public string Type { get; set; } [JsonProperty("url")] public string Url { get; set; } - /// - /// Gets either the custom URL, a local-to-processor URL, or null if it's a default logo - /// - public string GetLogoUrlLight() - { - if (Type == "url") - return Url; - if (Type == "system") - return string.Format("http://{0}:8080/logo.png", - CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0)); - return null; - } - - public string GetLogoUrlDark() - { - if (Type == "url") - return Url; - if (Type == "system") - return string.Format("http://{0}:8080/logo-dark.png", - CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0)); - return null; - } - } - /// - /// Represents occupancy sensor(s) setup for a room + /// Gets either the custom URL, a local-to-processor URL, or null if it's a default logo /// - public class EssentialsRoomOccSensorConfig + public string GetLogoUrlLight() + { + if (Type == "url") + return Url; + if (Type == "system") + return string.Format("http://{0}:8080/logo.png", + CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0)); + return null; + } + + public string GetLogoUrlDark() { + if (Type == "url") + return Url; + if (Type == "system") + return string.Format("http://{0}:8080/logo-dark.png", + CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0)); + return null; + } +} + +/// +/// Represents occupancy sensor(s) setup for a room +/// +public class EssentialsRoomOccSensorConfig +{ [JsonProperty("deviceKey")] public string DeviceKey { get; set; } [JsonProperty("timeoutMinutes")] public int TimeoutMinutes { get; set; } - } +} public class EssentialsRoomTechConfig { [JsonProperty("password")] public string Password { get; set; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomEmergencyConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomEmergencyConfig.cs index dbc068ebc..f34400436 100644 --- a/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomEmergencyConfig.cs +++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomEmergencyConfig.cs @@ -1,30 +1,29 @@ -namespace PepperDash.Essentials.Room.Config +namespace PepperDash.Essentials.Room.Config; + +/// +/// +/// +public class EssentialsRoomEmergencyConfig { - /// - /// - /// - public class EssentialsRoomEmergencyConfig - { - public EssentialsRoomEmergencyTriggerConfig Trigger { get; set; } + public EssentialsRoomEmergencyTriggerConfig Trigger { get; set; } - public string Behavior { get; set; } - } + public string Behavior { get; set; } +} +/// +/// +/// +public class EssentialsRoomEmergencyTriggerConfig +{ + /// + /// contact,versiport + /// + public string Type { get; set; } /// - /// + /// Input number if contact /// - public class EssentialsRoomEmergencyTriggerConfig - { - /// - /// contact,versiport - /// - public string Type { get; set; } - /// - /// Input number if contact - /// - public int Number { get; set; } + public int Number { get; set; } - public bool TriggerOnClose { get; set; } + public bool TriggerOnClose { get; set; } - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomScheduledEventsConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomScheduledEventsConfig.cs index 617b7c9f5..a41d00052 100644 --- a/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomScheduledEventsConfig.cs +++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsRoomScheduledEventsConfig.cs @@ -6,38 +6,37 @@ using Newtonsoft.Json.Converters; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Room.Config +namespace PepperDash.Essentials.Room.Config; + +public class EssentialsRoomScheduledEventsConfig { - public class EssentialsRoomScheduledEventsConfig - { - [JsonProperty("scheduledEvents")] - public List ScheduledEvents; - } + [JsonProperty("scheduledEvents")] + public List ScheduledEvents; +} - public class ScheduledEventConfig - { - [JsonProperty("key")] - public string Key; +public class ScheduledEventConfig +{ + [JsonProperty("key")] + public string Key; - [JsonProperty("name")] - public string Name; + [JsonProperty("name")] + public string Name; - [JsonProperty("days")] - public ScheduledEventCommon.eWeekDays Days; + [JsonProperty("days")] + public ScheduledEventCommon.eWeekDays Days; - [JsonProperty("time")] - public string Time; + [JsonProperty("time")] + public string Time; - [JsonProperty("actions")] - public List Actions; + [JsonProperty("actions")] + public List Actions; - [JsonProperty("persistent")] - public bool Persistent; + [JsonProperty("persistent")] + public bool Persistent; - [JsonProperty("acknowledgeable")] - public bool Acknowledgeable; + [JsonProperty("acknowledgeable")] + public bool Acknowledgeable; - [JsonProperty("enable")] - public bool Enable; - } + [JsonProperty("enable")] + public bool Enable; } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsTechRoomConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsTechRoomConfig.cs index 507bac5e8..67e0ba2c7 100644 --- a/src/PepperDash.Essentials.Core/Room/Config/EssentialsTechRoomConfig.cs +++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsTechRoomConfig.cs @@ -3,75 +3,74 @@ using Newtonsoft.Json; using PepperDash.Essentials.Room.Config; -namespace PepperDash.Essentials.Room.Config +namespace PepperDash.Essentials.Room.Config; + +public class EssentialsTechRoomConfig { - public class EssentialsTechRoomConfig - { - /// - /// The key of the dummy device used to enable routing - /// - [JsonProperty("dummySourceKey")] - public string DummySourceKey { get; set; } + /// + /// The key of the dummy device used to enable routing + /// + [JsonProperty("dummySourceKey")] + public string DummySourceKey { get; set; } - /// - /// The keys of the displays assigned to this room - /// - [JsonProperty("displays")] - public List Displays { get; set; } - - /// - /// The keys of the tuners assinged to this room - /// - [JsonProperty("tuners")] - public List Tuners { get; set; } + /// + /// The keys of the displays assigned to this room + /// + [JsonProperty("displays")] + public List Displays { get; set; } + + /// + /// The keys of the tuners assinged to this room + /// + [JsonProperty("tuners")] + public List Tuners { get; set; } - /// - /// PIN to access the room as a normal user - /// - [JsonProperty("userPin")] - public string UserPin { get; set; } + /// + /// PIN to access the room as a normal user + /// + [JsonProperty("userPin")] + public string UserPin { get; set; } - /// - /// PIN to access the room as a tech user - /// - [JsonProperty("techPin")] - public string TechPin { get; set; } + /// + /// PIN to access the room as a tech user + /// + [JsonProperty("techPin")] + public string TechPin { get; set; } - /// - /// Name of the presets file. Path prefix is assumed to be /html/presets/lists/ - /// - [JsonProperty("presetsFileName")] - public string PresetsFileName { get; set; } + /// + /// Name of the presets file. Path prefix is assumed to be /html/presets/lists/ + /// + [JsonProperty("presetsFileName")] + public string PresetsFileName { get; set; } - [JsonProperty("scheduledEvents")] - public List ScheduledEvents { get; set; } + [JsonProperty("scheduledEvents")] + public List ScheduledEvents { get; set; } - /// - /// Indicates that the room is the primary when true - /// - [JsonProperty("isPrimary")] - public bool IsPrimary { get; set; } + /// + /// Indicates that the room is the primary when true + /// + [JsonProperty("isPrimary")] + public bool IsPrimary { get; set; } - /// - /// Indicates which tuners should mirror preset recall when two rooms are configured in a primary->secondary scenario - /// - [JsonProperty("mirroredTuners")] - public Dictionary MirroredTuners { get; set; } + /// + /// Indicates which tuners should mirror preset recall when two rooms are configured in a primary->secondary scenario + /// + [JsonProperty("mirroredTuners")] + public Dictionary MirroredTuners { get; set; } - [JsonProperty("helpMessage")] - public string HelpMessage { get; set; } + [JsonProperty("helpMessage")] + public string HelpMessage { get; set; } - /// - /// Indicates the room - /// - [JsonProperty("isTvPresetsProvider")] - public bool IsTvPresetsProvider; + /// + /// Indicates the room + /// + [JsonProperty("isTvPresetsProvider")] + public bool IsTvPresetsProvider; - public EssentialsTechRoomConfig() - { - Displays = new List(); - Tuners = new List(); - ScheduledEvents = new List(); - } + public EssentialsTechRoomConfig() + { + Displays = new List(); + Tuners = new List(); + ScheduledEvents = new List(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Config/EssentialsVolumeLevelConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/EssentialsVolumeLevelConfig.cs index 5b9450f2a..c509ad857 100644 --- a/src/PepperDash.Essentials.Core/Room/Config/EssentialsVolumeLevelConfig.cs +++ b/src/PepperDash.Essentials.Core/Room/Config/EssentialsVolumeLevelConfig.cs @@ -1,91 +1,90 @@ using System; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Room.Config +namespace PepperDash.Essentials.Room.Config; + +/// +/// +/// +public class EssentialsRoomVolumesConfig { - /// - /// - /// - public class EssentialsRoomVolumesConfig - { - public EssentialsVolumeLevelConfig Master { get; set; } - public EssentialsVolumeLevelConfig Program { get; set; } - public EssentialsVolumeLevelConfig AudioCallRx { get; set; } - public EssentialsVolumeLevelConfig AudioCallTx { get; set; } - } + public EssentialsVolumeLevelConfig Master { get; set; } + public EssentialsVolumeLevelConfig Program { get; set; } + public EssentialsVolumeLevelConfig AudioCallRx { get; set; } + public EssentialsVolumeLevelConfig AudioCallTx { get; set; } +} + +/// +/// +/// +public class EssentialsVolumeLevelConfig +{ + public string DeviceKey { get; set; } + public string Label { get; set; } + public int Level { get; set; } /// - /// + /// Helper to get the device associated with key - one timer. /// - public class EssentialsVolumeLevelConfig + public IBasicVolumeWithFeedback GetDevice() { - public string DeviceKey { get; set; } - public string Label { get; set; } - public int Level { get; set; } - - /// - /// Helper to get the device associated with key - one timer. - /// - public IBasicVolumeWithFeedback GetDevice() + throw new NotImplementedException("This method references DM CHASSIS Directly"); + /* + // DM output card format: deviceKey--output~number, dm8x8-1--output~4 + var match = Regex.Match(DeviceKey, @"([-_\w]+)--(\w+)~(\d+)"); + if (match.Success) { - throw new NotImplementedException("This method references DM CHASSIS Directly"); - /* - // DM output card format: deviceKey--output~number, dm8x8-1--output~4 - var match = Regex.Match(DeviceKey, @"([-_\w]+)--(\w+)~(\d+)"); - if (match.Success) + var devKey = match.Groups[1].Value; + var chassis = DeviceManager.GetDeviceForKey(devKey) as DmChassisController; + if (chassis != null) { - var devKey = match.Groups[1].Value; - var chassis = DeviceManager.GetDeviceForKey(devKey) as DmChassisController; - if (chassis != null) - { - var outputNum = Convert.ToUInt32(match.Groups[3].Value); - if (chassis.VolumeControls.ContainsKey(outputNum)) // should always... - return chassis.VolumeControls[outputNum]; - } - // No volume for some reason. We have failed as developers - return null; + var outputNum = Convert.ToUInt32(match.Groups[3].Value); + if (chassis.VolumeControls.ContainsKey(outputNum)) // should always... + return chassis.VolumeControls[outputNum]; } + // No volume for some reason. We have failed as developers + return null; + } - // DSP/DMPS format: deviceKey--levelName, biampTesira-1--master - match = Regex.Match(DeviceKey, @"([-_\w]+)--(.+)"); - if (match.Success) + // DSP/DMPS format: deviceKey--levelName, biampTesira-1--master + match = Regex.Match(DeviceKey, @"([-_\w]+)--(.+)"); + if (match.Success) + { + var devKey = match.Groups[1].Value; + var dsp = DeviceManager.GetDeviceForKey(devKey) as BiampTesiraForteDsp; + if (dsp != null) { - var devKey = match.Groups[1].Value; - var dsp = DeviceManager.GetDeviceForKey(devKey) as BiampTesiraForteDsp; - if (dsp != null) - { - var levelTag = match.Groups[2].Value; - if (dsp.LevelControlPoints.ContainsKey(levelTag)) // should always... - return dsp.LevelControlPoints[levelTag]; - } + var levelTag = match.Groups[2].Value; + if (dsp.LevelControlPoints.ContainsKey(levelTag)) // should always... + return dsp.LevelControlPoints[levelTag]; + } - var dmps = DeviceManager.GetDeviceForKey(devKey) as DmpsAudioOutputController; - if (dmps != null) + var dmps = DeviceManager.GetDeviceForKey(devKey) as DmpsAudioOutputController; + if (dmps != null) + { + var levelTag = match.Groups[2].Value; + switch (levelTag) { - var levelTag = match.Groups[2].Value; - switch (levelTag) - { - case "master": - return dmps.MasterVolumeLevel; - case "source": - return dmps.SourceVolumeLevel; - case "micsmaster": - return dmps.MicsMasterVolumeLevel; - case "codec1": - return dmps.Codec1VolumeLevel; - case "codec2": - return dmps.Codec2VolumeLevel; - default: - return dmps.MasterVolumeLevel; - } + case "master": + return dmps.MasterVolumeLevel; + case "source": + return dmps.SourceVolumeLevel; + case "micsmaster": + return dmps.MicsMasterVolumeLevel; + case "codec1": + return dmps.Codec1VolumeLevel; + case "codec2": + return dmps.Codec2VolumeLevel; + default: + return dmps.MasterVolumeLevel; } - // No volume for some reason. We have failed as developers - return null; } - + // No volume for some reason. We have failed as developers return null; } - * */ - } + + return null; + } + * */ } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Config/SimplRoomPropertiesConfig.cs b/src/PepperDash.Essentials.Core/Room/Config/SimplRoomPropertiesConfig.cs index fdd9b857f..3b5832a96 100644 --- a/src/PepperDash.Essentials.Core/Room/Config/SimplRoomPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Core/Room/Config/SimplRoomPropertiesConfig.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace PepperDash.Essentials.Room.Config -{ +namespace PepperDash.Essentials.Room.Config; + public class SimplRoomPropertiesConfig : EssentialsHuddleVtc1PropertiesConfig { [JsonProperty("roomPhoneNumber")] @@ -21,5 +21,4 @@ public class SimplSpeedDial public string Name { get; set; } [JsonProperty("number")] public string Number { get; set; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/EsentialsRoomEmergencyContactClosure.cs b/src/PepperDash.Essentials.Core/Room/EsentialsRoomEmergencyContactClosure.cs index 48d24ab0e..ee81c4d0d 100644 --- a/src/PepperDash.Essentials.Core/Room/EsentialsRoomEmergencyContactClosure.cs +++ b/src/PepperDash.Essentials.Core/Room/EsentialsRoomEmergencyContactClosure.cs @@ -2,95 +2,94 @@ using Crestron.SimplSharpPro; using PepperDash.Essentials.Room.Config; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public class EssentialsRoomEmergencyContactClosure : EssentialsRoomEmergencyBase, IEssentialsRoomEmergency { - public class EssentialsRoomEmergencyContactClosure : EssentialsRoomEmergencyBase, IEssentialsRoomEmergency - { - public event EventHandler EmergencyStateChange; + public event EventHandler EmergencyStateChange; - IEssentialsRoom Room; - string Behavior; - bool TriggerOnClose; + IEssentialsRoom Room; + string Behavior; + bool TriggerOnClose; - public bool InEmergency { get; private set; } + public bool InEmergency { get; private set; } - public EssentialsRoomEmergencyContactClosure(string key, EssentialsRoomEmergencyConfig config, IEssentialsRoom room) : - base(key) - { - Room = room; - var cs = Global.ControlSystem; + public EssentialsRoomEmergencyContactClosure(string key, EssentialsRoomEmergencyConfig config, IEssentialsRoom room) : + base(key) + { + Room = room; + var cs = Global.ControlSystem; - if (config.Trigger.Type.Equals("contact", StringComparison.OrdinalIgnoreCase)) - { - var portNum = (uint)config.Trigger.Number; - if (portNum <= cs.NumberOfDigitalInputPorts) - { - cs.DigitalInputPorts[portNum].Register(); - cs.DigitalInputPorts[portNum].StateChange += EsentialsRoomEmergencyContactClosure_StateChange; - } - } - else if (config.Trigger.Type.Equals("versiport", StringComparison.OrdinalIgnoreCase)) + if (config.Trigger.Type.Equals("contact", StringComparison.OrdinalIgnoreCase)) + { + var portNum = (uint)config.Trigger.Number; + if (portNum <= cs.NumberOfDigitalInputPorts) { - var portNum = (uint)config.Trigger.Number; - if (portNum <= cs.NumberOfVersiPorts) - { - cs.VersiPorts[portNum].Register(); - cs.VersiPorts[portNum].SetVersiportConfiguration(eVersiportConfiguration.DigitalInput); - cs.VersiPorts[portNum].DisablePullUpResistor = true; - cs.VersiPorts[portNum].VersiportChange += EssentialsRoomEmergencyContactClosure_VersiportChange; - } + cs.DigitalInputPorts[portNum].Register(); + cs.DigitalInputPorts[portNum].StateChange += EsentialsRoomEmergencyContactClosure_StateChange; } - Behavior = config.Behavior; - TriggerOnClose = config.Trigger.TriggerOnClose; } - - private void EssentialsRoomEmergencyContactClosure_VersiportChange(Versiport port, VersiportEventArgs args) + else if (config.Trigger.Type.Equals("versiport", StringComparison.OrdinalIgnoreCase)) { - if (args.Event == eVersiportEvent.DigitalInChange) + var portNum = (uint)config.Trigger.Number; + if (portNum <= cs.NumberOfVersiPorts) { - ContactClosure_StateChange(port.DigitalIn); + cs.VersiPorts[portNum].Register(); + cs.VersiPorts[portNum].SetVersiportConfiguration(eVersiportConfiguration.DigitalInput); + cs.VersiPorts[portNum].DisablePullUpResistor = true; + cs.VersiPorts[portNum].VersiportChange += EssentialsRoomEmergencyContactClosure_VersiportChange; } } + Behavior = config.Behavior; + TriggerOnClose = config.Trigger.TriggerOnClose; + } - void EsentialsRoomEmergencyContactClosure_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args) + private void EssentialsRoomEmergencyContactClosure_VersiportChange(Versiport port, VersiportEventArgs args) + { + if (args.Event == eVersiportEvent.DigitalInChange) { - ContactClosure_StateChange(args.State); + ContactClosure_StateChange(port.DigitalIn); } + } + + void EsentialsRoomEmergencyContactClosure_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args) + { + ContactClosure_StateChange(args.State); + } - void ContactClosure_StateChange(bool portState) + void ContactClosure_StateChange(bool portState) + { + if (portState && TriggerOnClose || !portState && !TriggerOnClose) { - if (portState && TriggerOnClose || !portState && !TriggerOnClose) - { - InEmergency = true; - if (EmergencyStateChange != null) - EmergencyStateChange(this, new EventArgs()); - RunEmergencyBehavior(); - } - else - { - InEmergency = false; - if (EmergencyStateChange != null) - EmergencyStateChange(this, new EventArgs()); - } + InEmergency = true; + if (EmergencyStateChange != null) + EmergencyStateChange(this, new EventArgs()); + RunEmergencyBehavior(); } - - /// - /// - /// - public void RunEmergencyBehavior() + else { - if (Behavior.Equals("shutdown")) - Room.Shutdown(); + InEmergency = false; + if (EmergencyStateChange != null) + EmergencyStateChange(this, new EventArgs()); } } /// - /// Describes the functionality of a room emergency contact closure + /// /// - public interface IEssentialsRoomEmergency + public void RunEmergencyBehavior() { - event EventHandler EmergencyStateChange; - - bool InEmergency { get; } + if (Behavior.Equals("shutdown")) + Room.Shutdown(); } +} + +/// +/// Describes the functionality of a room emergency contact closure +/// +public interface IEssentialsRoomEmergency +{ + event EventHandler EmergencyStateChange; + + bool InEmergency { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs b/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs index 232c02ed6..c4866b928 100644 --- a/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs +++ b/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs @@ -12,188 +12,188 @@ using PepperDash.Essentials.Core.DeviceTypeInterfaces; using Serilog.Events; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// +/// +public abstract class EssentialsRoomBase : ReconfigurableDevice, IEssentialsRoom { /// - /// + /// /// - public abstract class EssentialsRoomBase : ReconfigurableDevice, IEssentialsRoom - { - /// - /// - /// - public BoolFeedback OnFeedback { get; private set; } + public BoolFeedback OnFeedback { get; private set; } - /// - /// Fires when the RoomOccupancy object is set - /// - public event EventHandler RoomOccupancyIsSet; + /// + /// Fires when the RoomOccupancy object is set + /// + public event EventHandler RoomOccupancyIsSet; - public BoolFeedback IsWarmingUpFeedback { get; private set; } - public BoolFeedback IsCoolingDownFeedback { get; private set; } + public BoolFeedback IsWarmingUpFeedback { get; private set; } + public BoolFeedback IsCoolingDownFeedback { get; private set; } - public IOccupancyStatusProvider RoomOccupancy { get; protected set; } + public IOccupancyStatusProvider RoomOccupancy { get; protected set; } - public bool OccupancyStatusProviderIsRemote { get; private set; } + public bool OccupancyStatusProviderIsRemote { get; private set; } - public List EnvironmentalControlDevices { get; protected set; } + public List EnvironmentalControlDevices { get; protected set; } - public bool HasEnvironmentalControlDevices + public bool HasEnvironmentalControlDevices + { + get { - get - { - return EnvironmentalControlDevices != null && EnvironmentalControlDevices.Count > 0; - } + return EnvironmentalControlDevices != null && EnvironmentalControlDevices.Count > 0; } + } - protected abstract Func IsWarmingFeedbackFunc { get; } - protected abstract Func IsCoolingFeedbackFunc { get; } + protected abstract Func IsWarmingFeedbackFunc { get; } + protected abstract Func IsCoolingFeedbackFunc { get; } - /// - /// Indicates if this room is Mobile Control Enabled - /// - public bool IsMobileControlEnabled { get; private set; } + /// + /// Indicates if this room is Mobile Control Enabled + /// + public bool IsMobileControlEnabled { get; private set; } - /// - /// The bridge for this room if Mobile Control is enabled - /// - public IMobileControlRoomMessenger MobileControlRoomBridge { get; private set; } + /// + /// The bridge for this room if Mobile Control is enabled + /// + public IMobileControlRoomMessenger MobileControlRoomBridge { get; private set; } - protected const string _defaultListKey = "default"; + protected const string _defaultListKey = "default"; - /// - /// The config name of the source list - /// + /// + /// The config name of the source list + /// /// private string _sourceListKey; - public string SourceListKey { + public string SourceListKey { get { - if(string.IsNullOrEmpty(_sourceListKey)) - { - return _defaultListKey; - } - else - { - return _sourceListKey; - } + if(string.IsNullOrEmpty(_sourceListKey)) + { + return _defaultListKey; + } + else + { + return _sourceListKey; + } } protected set { - if (value != _sourceListKey) - { - _sourceListKey = value; - } + if (value != _sourceListKey) + { + _sourceListKey = value; + } } } - private string _destinationListKey; - public string DestinationListKey + private string _destinationListKey; + public string DestinationListKey + { + get { - get + if (string.IsNullOrEmpty(_destinationListKey)) { - if (string.IsNullOrEmpty(_destinationListKey)) - { - return _defaultListKey; - } - else - { - return _destinationListKey; - } + return _defaultListKey; } - protected set + else { - if (value != _destinationListKey) - { - _destinationListKey = value; - } + return _destinationListKey; + } + } + protected set + { + if (value != _destinationListKey) + { + _destinationListKey = value; } } + } - private string _audioControlPointListKey; - public string AudioControlPointListKey + private string _audioControlPointListKey; + public string AudioControlPointListKey + { + get { - get + if (string.IsNullOrEmpty(_audioControlPointListKey)) { - if (string.IsNullOrEmpty(_audioControlPointListKey)) - { - return _defaultListKey; - } - else - { - return _destinationListKey; - } + return _defaultListKey; } - protected set + else { - if (value != _audioControlPointListKey) - { - _audioControlPointListKey = value; - } + return _destinationListKey; + } + } + protected set + { + if (value != _audioControlPointListKey) + { + _audioControlPointListKey = value; } } + } - private string _cameraListKey; - public string CameraListKey + private string _cameraListKey; + public string CameraListKey + { + get { - get + if (string.IsNullOrEmpty(_cameraListKey)) { - if (string.IsNullOrEmpty(_cameraListKey)) - { - return _defaultListKey; - } - else - { - return _cameraListKey; - } + return _defaultListKey; } - protected set + else { - if (value != _cameraListKey) - { - _cameraListKey = value; - } + return _cameraListKey; } } + protected set + { + if (value != _cameraListKey) + { + _cameraListKey = value; + } + } + } - /// - /// Timer used for informing the UIs of a shutdown - /// - public SecondsCountdownTimer ShutdownPromptTimer { get; private set; } + /// + /// Timer used for informing the UIs of a shutdown + /// + public SecondsCountdownTimer ShutdownPromptTimer { get; private set; } - /// - /// - /// - public int ShutdownPromptSeconds { get; set; } - public int ShutdownVacancySeconds { get; set; } - public eShutdownType ShutdownType { get; private set; } + /// + /// + /// + public int ShutdownPromptSeconds { get; set; } + public int ShutdownVacancySeconds { get; set; } + public eShutdownType ShutdownType { get; private set; } - public EssentialsRoomEmergencyBase Emergency { get; set; } + public EssentialsRoomEmergencyBase Emergency { get; set; } - public Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; set; } + public Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; set; } - public string LogoUrlLightBkgnd { get; set; } + public string LogoUrlLightBkgnd { get; set; } - public string LogoUrlDarkBkgnd { get; set; } + public string LogoUrlDarkBkgnd { get; set; } - protected SecondsCountdownTimer RoomVacancyShutdownTimer { get; private set; } + protected SecondsCountdownTimer RoomVacancyShutdownTimer { get; private set; } - public eVacancyMode VacancyMode { get; private set; } + public eVacancyMode VacancyMode { get; private set; } - /// - /// Seconds after vacancy prompt is displayed until shutdown - /// - protected int RoomVacancyShutdownSeconds; + /// + /// Seconds after vacancy prompt is displayed until shutdown + /// + protected int RoomVacancyShutdownSeconds; - /// - /// Seconds after vacancy detected until prompt is displayed - /// - protected int RoomVacancyShutdownPromptSeconds; + /// + /// Seconds after vacancy detected until prompt is displayed + /// + protected int RoomVacancyShutdownPromptSeconds; - /// - /// - /// - protected abstract Func OnFeedbackFunc { get; } + /// + /// + /// + protected abstract Func OnFeedbackFunc { get; } protected Dictionary SavedVolumeLevels = new Dictionary(); @@ -203,293 +203,292 @@ protected set public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; } - public EssentialsRoomBase(DeviceConfig config) - : base(config) + public EssentialsRoomBase(DeviceConfig config) + : base(config) + { + EnvironmentalControlDevices = new List(); + + // Setup the ShutdownPromptTimer + ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer"); + ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) => { - EnvironmentalControlDevices = new List(); + if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue) + ShutdownType = eShutdownType.None; + }; - // Setup the ShutdownPromptTimer - ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer"); - ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) => - { - if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue) - ShutdownType = eShutdownType.None; - }; + ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered - ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered + ShutdownPromptSeconds = 60; + ShutdownVacancySeconds = 120; + + ShutdownType = eShutdownType.None; - ShutdownPromptSeconds = 60; - ShutdownVacancySeconds = 120; - - ShutdownType = eShutdownType.None; + RoomVacancyShutdownTimer = new SecondsCountdownTimer(Key + "-vacancyOffTimer"); + //RoomVacancyShutdownTimer.IsRunningFeedback.OutputChange += (o, a) => + //{ + // if (!RoomVacancyShutdownTimer.IsRunningFeedback.BoolValue) + // ShutdownType = ShutdownType.Vacancy; + //}; + RoomVacancyShutdownTimer.HasFinished += new EventHandler(RoomVacancyShutdownPromptTimer_HasFinished); // Shutdown is triggered - RoomVacancyShutdownTimer = new SecondsCountdownTimer(Key + "-vacancyOffTimer"); - //RoomVacancyShutdownTimer.IsRunningFeedback.OutputChange += (o, a) => - //{ - // if (!RoomVacancyShutdownTimer.IsRunningFeedback.BoolValue) - // ShutdownType = ShutdownType.Vacancy; - //}; - RoomVacancyShutdownTimer.HasFinished += new EventHandler(RoomVacancyShutdownPromptTimer_HasFinished); // Shutdown is triggered + RoomVacancyShutdownPromptSeconds = 1500; // 25 min to prompt warning + RoomVacancyShutdownSeconds = 240; // 4 min after prompt will trigger shutdown prompt + VacancyMode = eVacancyMode.None; - RoomVacancyShutdownPromptSeconds = 1500; // 25 min to prompt warning - RoomVacancyShutdownSeconds = 240; // 4 min after prompt will trigger shutdown prompt - VacancyMode = eVacancyMode.None; + OnFeedback = new BoolFeedback(OnFeedbackFunc); - OnFeedback = new BoolFeedback(OnFeedbackFunc); + IsWarmingUpFeedback = new BoolFeedback(IsWarmingFeedbackFunc); + IsCoolingDownFeedback = new BoolFeedback(IsCoolingFeedbackFunc); - IsWarmingUpFeedback = new BoolFeedback(IsWarmingFeedbackFunc); - IsCoolingDownFeedback = new BoolFeedback(IsCoolingFeedbackFunc); + AddPostActivationAction(() => + { + if (RoomOccupancy != null) + OnRoomOccupancyIsSet(); + }); + } - AddPostActivationAction(() => - { - if (RoomOccupancy != null) - OnRoomOccupancyIsSet(); - }); - } + public override bool CustomActivate() + { + SetUpMobileControl(); - public override bool CustomActivate() - { - SetUpMobileControl(); + return base.CustomActivate(); + } - return base.CustomActivate(); + /// + /// Sets the SourceListKey property to the passed in value or the default if no value passed in + /// + /// + protected void SetSourceListKey(string sourceListKey) + { + if (!string.IsNullOrEmpty(sourceListKey)) + { + SourceListKey = sourceListKey; } - - /// - /// Sets the SourceListKey property to the passed in value or the default if no value passed in - /// - /// - protected void SetSourceListKey(string sourceListKey) + else { - if (!string.IsNullOrEmpty(sourceListKey)) - { - SourceListKey = sourceListKey; - } - else - { - sourceListKey = _defaultListKey; - } + sourceListKey = _defaultListKey; } + } - protected void SetDestinationListKey(string destinationListKey) + protected void SetDestinationListKey(string destinationListKey) + { + if (!string.IsNullOrEmpty(destinationListKey)) { - if (!string.IsNullOrEmpty(destinationListKey)) - { - DestinationListKey = destinationListKey; - } + DestinationListKey = destinationListKey; } + } - /// - /// If mobile control is enabled, sets the appropriate properties - /// - void SetUpMobileControl() + /// + /// If mobile control is enabled, sets the appropriate properties + /// + void SetUpMobileControl() + { + var mcBridgeKey = string.Format("mobileControlBridge-{0}", Key); + var mcBridge = DeviceManager.GetDeviceForKey(mcBridgeKey); + if (mcBridge == null) { - var mcBridgeKey = string.Format("mobileControlBridge-{0}", Key); - var mcBridge = DeviceManager.GetDeviceForKey(mcBridgeKey); - if (mcBridge == null) - { - Debug.LogMessage(LogEventLevel.Debug, this, "*********************Mobile Control Bridge Not found for this room."); - IsMobileControlEnabled = false; - return; - } - else - { - MobileControlRoomBridge = mcBridge as IMobileControlRoomMessenger; - Debug.LogMessage(LogEventLevel.Debug, this, "*********************Mobile Control Bridge found and enabled for this room"); - IsMobileControlEnabled = true; - } + Debug.LogMessage(LogEventLevel.Debug, this, "*********************Mobile Control Bridge Not found for this room."); + IsMobileControlEnabled = false; + return; + } + else + { + MobileControlRoomBridge = mcBridge as IMobileControlRoomMessenger; + Debug.LogMessage(LogEventLevel.Debug, this, "*********************Mobile Control Bridge found and enabled for this room"); + IsMobileControlEnabled = true; } + } - void RoomVacancyShutdownPromptTimer_HasFinished(object sender, EventArgs e) + void RoomVacancyShutdownPromptTimer_HasFinished(object sender, EventArgs e) + { + switch (VacancyMode) { - switch (VacancyMode) - { - case eVacancyMode.None: - StartRoomVacancyTimer(eVacancyMode.InInitialVacancy); - break; - case eVacancyMode.InInitialVacancy: - StartRoomVacancyTimer(eVacancyMode.InShutdownWarning); - break; - case eVacancyMode.InShutdownWarning: - { - StartShutdown(eShutdownType.Vacancy); - Debug.LogMessage(LogEventLevel.Information, this, "Shutting Down due to vacancy."); - break; - } - default: + case eVacancyMode.None: + StartRoomVacancyTimer(eVacancyMode.InInitialVacancy); + break; + case eVacancyMode.InInitialVacancy: + StartRoomVacancyTimer(eVacancyMode.InShutdownWarning); + break; + case eVacancyMode.InShutdownWarning: + { + StartShutdown(eShutdownType.Vacancy); + Debug.LogMessage(LogEventLevel.Information, this, "Shutting Down due to vacancy."); break; - } + } + default: + break; } + } - /// - /// - /// - /// - public void StartShutdown(eShutdownType type) - { - // Check for shutdowns running. Manual should override other shutdowns + /// + /// + /// + /// + public void StartShutdown(eShutdownType type) + { + // Check for shutdowns running. Manual should override other shutdowns - if (type == eShutdownType.Manual) - ShutdownPromptTimer.SecondsToCount = ShutdownPromptSeconds; - else if (type == eShutdownType.Vacancy) - ShutdownPromptTimer.SecondsToCount = ShutdownVacancySeconds; - ShutdownType = type; - ShutdownPromptTimer.Start(); + if (type == eShutdownType.Manual) + ShutdownPromptTimer.SecondsToCount = ShutdownPromptSeconds; + else if (type == eShutdownType.Vacancy) + ShutdownPromptTimer.SecondsToCount = ShutdownVacancySeconds; + ShutdownType = type; + ShutdownPromptTimer.Start(); - Debug.LogMessage(LogEventLevel.Information, this, "ShutdownPromptTimer Started. Type: {0}. Seconds: {1}", ShutdownType, ShutdownPromptTimer.SecondsToCount); - } + Debug.LogMessage(LogEventLevel.Information, this, "ShutdownPromptTimer Started. Type: {0}. Seconds: {1}", ShutdownType, ShutdownPromptTimer.SecondsToCount); + } - public void StartRoomVacancyTimer(eVacancyMode mode) - { - if (mode == eVacancyMode.None) - RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownPromptSeconds; - else if (mode == eVacancyMode.InInitialVacancy) - RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownSeconds; - else if (mode == eVacancyMode.InShutdownWarning) - RoomVacancyShutdownTimer.SecondsToCount = 60; - VacancyMode = mode; - RoomVacancyShutdownTimer.Start(); - - Debug.LogMessage(LogEventLevel.Information, this, "Vacancy Timer Started. Mode: {0}. Seconds: {1}", VacancyMode, RoomVacancyShutdownTimer.SecondsToCount); - } + public void StartRoomVacancyTimer(eVacancyMode mode) + { + if (mode == eVacancyMode.None) + RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownPromptSeconds; + else if (mode == eVacancyMode.InInitialVacancy) + RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownSeconds; + else if (mode == eVacancyMode.InShutdownWarning) + RoomVacancyShutdownTimer.SecondsToCount = 60; + VacancyMode = mode; + RoomVacancyShutdownTimer.Start(); + + Debug.LogMessage(LogEventLevel.Information, this, "Vacancy Timer Started. Mode: {0}. Seconds: {1}", VacancyMode, RoomVacancyShutdownTimer.SecondsToCount); + } - /// - /// Resets the vacancy mode and shutsdwon the room - /// - public void Shutdown() - { - VacancyMode = eVacancyMode.None; - EndShutdown(); - } + /// + /// Resets the vacancy mode and shutsdwon the room + /// + public void Shutdown() + { + VacancyMode = eVacancyMode.None; + EndShutdown(); + } - /// - /// This method is for the derived class to define it's specific shutdown - /// requirements but should not be called directly. It is called by Shutdown() - /// - protected abstract void EndShutdown(); + /// + /// This method is for the derived class to define it's specific shutdown + /// requirements but should not be called directly. It is called by Shutdown() + /// + protected abstract void EndShutdown(); - /// - /// Override this to implement a default volume level(s) method - /// - public abstract void SetDefaultLevels(); + /// + /// Override this to implement a default volume level(s) method + /// + public abstract void SetDefaultLevels(); - /// - /// Sets the object to be used as the IOccupancyStatusProvider for the room. Can be an Occupancy Aggregator or a specific device - /// - /// - public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes) - { + /// + /// Sets the object to be used as the IOccupancyStatusProvider for the room. Can be an Occupancy Aggregator or a specific device + /// + /// + public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes) + { if (statusProvider == null) { Debug.LogMessage(LogEventLevel.Information, this, "ERROR: Occupancy sensor device is null"); return; } - Debug.LogMessage(LogEventLevel.Information, this, "Room Occupancy set to device: '{0}'", (statusProvider as Device).Key); - Debug.LogMessage(LogEventLevel.Information, this, "Timeout Minutes from Config is: {0}", timeoutMinutes); + Debug.LogMessage(LogEventLevel.Information, this, "Room Occupancy set to device: '{0}'", (statusProvider as Device).Key); + Debug.LogMessage(LogEventLevel.Information, this, "Timeout Minutes from Config is: {0}", timeoutMinutes); - // If status provider is fusion, set flag to remote - if (statusProvider is Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase) - OccupancyStatusProviderIsRemote = true; + // If status provider is fusion, set flag to remote + if (statusProvider is Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase) + OccupancyStatusProviderIsRemote = true; - if(timeoutMinutes > 0) - RoomVacancyShutdownSeconds = timeoutMinutes * 60; + if(timeoutMinutes > 0) + RoomVacancyShutdownSeconds = timeoutMinutes * 60; - Debug.LogMessage(LogEventLevel.Information, this, "RoomVacancyShutdownSeconds set to {0}", RoomVacancyShutdownSeconds); + Debug.LogMessage(LogEventLevel.Information, this, "RoomVacancyShutdownSeconds set to {0}", RoomVacancyShutdownSeconds); - RoomOccupancy = statusProvider; + RoomOccupancy = statusProvider; - RoomOccupancy.RoomIsOccupiedFeedback.OutputChange -= RoomIsOccupiedFeedback_OutputChange; - RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange; + RoomOccupancy.RoomIsOccupiedFeedback.OutputChange -= RoomIsOccupiedFeedback_OutputChange; + RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange; - OnRoomOccupancyIsSet(); - } + OnRoomOccupancyIsSet(); + } - void OnRoomOccupancyIsSet() - { - var handler = RoomOccupancyIsSet; - if (handler != null) - handler(this, new EventArgs()); - } + void OnRoomOccupancyIsSet() + { + var handler = RoomOccupancyIsSet; + if (handler != null) + handler(this, new EventArgs()); + } - /// - /// To allow base class to power room on to last source - /// - public abstract void PowerOnToDefaultOrLastSource(); + /// + /// To allow base class to power room on to last source + /// + public abstract void PowerOnToDefaultOrLastSource(); - /// - /// To allow base class to power room on to default source - /// - /// - public abstract bool RunDefaultPresentRoute(); + /// + /// To allow base class to power room on to default source + /// + /// + public abstract bool RunDefaultPresentRoute(); - void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e) + void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e) + { + if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false && AllowVacancyTimerToStart()) { - if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false && AllowVacancyTimerToStart()) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Notice: Vacancy Detected"); - // Trigger the timer when the room is vacant - StartRoomVacancyTimer(eVacancyMode.InInitialVacancy); - } - else - { - Debug.LogMessage(LogEventLevel.Debug, this, "Notice: Occupancy Detected"); - // Reset the timer when the room is occupied - RoomVacancyShutdownTimer.Cancel(); - } + Debug.LogMessage(LogEventLevel.Debug, this, "Notice: Vacancy Detected"); + // Trigger the timer when the room is vacant + StartRoomVacancyTimer(eVacancyMode.InInitialVacancy); } - - /// - /// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed - /// - /// - public abstract void RoomVacatedForTimeoutPeriod(object o); - - /// - /// Allow the vacancy event from an occupancy sensor to turn the room off. - /// - /// If the timer should be allowed. Defaults to true - protected virtual bool AllowVacancyTimerToStart() + else { - return true; + Debug.LogMessage(LogEventLevel.Debug, this, "Notice: Occupancy Detected"); + // Reset the timer when the room is occupied + RoomVacancyShutdownTimer.Cancel(); } } - + /// - /// To describe the various ways a room may be shutting down + /// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed /// - public enum eShutdownType - { - None = 0, - External, - Manual, - Vacancy - } - - public enum eVacancyMode - { - None = 0, - InInitialVacancy, - InShutdownWarning - } + /// + public abstract void RoomVacatedForTimeoutPeriod(object o); /// - /// + /// Allow the vacancy event from an occupancy sensor to turn the room off. /// - public enum eWarmingCoolingMode + /// If the timer should be allowed. Defaults to true + protected virtual bool AllowVacancyTimerToStart() { - None, - Warming, - Cooling + return true; } +} + +/// +/// To describe the various ways a room may be shutting down +/// +public enum eShutdownType +{ + None = 0, + External, + Manual, + Vacancy +} - public abstract class EssentialsRoomEmergencyBase : IKeyed - { - public string Key { get; private set; } +public enum eVacancyMode +{ + None = 0, + InInitialVacancy, + InShutdownWarning +} + +/// +/// +/// +public enum eWarmingCoolingMode +{ + None, + Warming, + Cooling +} - public EssentialsRoomEmergencyBase(string key) - { - Key = key; - } +public abstract class EssentialsRoomEmergencyBase : IKeyed +{ + public string Key { get; private set; } + + public EssentialsRoomEmergencyBase(string key) + { + Key = key; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs b/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs index d452c0b93..f3283a741 100644 --- a/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs +++ b/src/PepperDash.Essentials.Core/Room/IEssentialsRoom.cs @@ -10,42 +10,40 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ - /// - /// Describes the basic functionality of an EssentialsRoom - /// - public interface IEssentialsRoom : IKeyName, IReconfigurableDevice, IRunDefaultPresentRoute, IEnvironmentalControls - { - BoolFeedback OnFeedback { get; } +namespace PepperDash.Essentials.Core; - BoolFeedback IsWarmingUpFeedback { get; } - BoolFeedback IsCoolingDownFeedback { get; } +/// +/// Describes the basic functionality of an EssentialsRoom +/// +public interface IEssentialsRoom : IKeyName, IReconfigurableDevice, IRunDefaultPresentRoute, IEnvironmentalControls +{ + BoolFeedback OnFeedback { get; } - bool IsMobileControlEnabled { get; } - IMobileControlRoomMessenger MobileControlRoomBridge { get; } + BoolFeedback IsWarmingUpFeedback { get; } + BoolFeedback IsCoolingDownFeedback { get; } - string SourceListKey { get; } + bool IsMobileControlEnabled { get; } + IMobileControlRoomMessenger MobileControlRoomBridge { get; } - string DestinationListKey { get; } + string SourceListKey { get; } - string AudioControlPointListKey { get; } + string DestinationListKey { get; } - string CameraListKey { get; } + string AudioControlPointListKey { get; } - SecondsCountdownTimer ShutdownPromptTimer { get; } - int ShutdownPromptSeconds { get; } - int ShutdownVacancySeconds { get; } - eShutdownType ShutdownType { get; } + string CameraListKey { get; } - string LogoUrlLightBkgnd { get; } - string LogoUrlDarkBkgnd { get; } + SecondsCountdownTimer ShutdownPromptTimer { get; } + int ShutdownPromptSeconds { get; } + int ShutdownVacancySeconds { get; } + eShutdownType ShutdownType { get; } - void StartShutdown(eShutdownType type); + string LogoUrlLightBkgnd { get; } + string LogoUrlDarkBkgnd { get; } - void Shutdown(); + void StartShutdown(eShutdownType type); - void PowerOnToDefaultOrLastSource(); - } + void Shutdown(); + void PowerOnToDefaultOrLastSource(); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/IRoomEventSchedule.cs b/src/PepperDash.Essentials.Core/Room/IRoomEventSchedule.cs index c2595151d..b655ce612 100644 --- a/src/PepperDash.Essentials.Core/Room/IRoomEventSchedule.cs +++ b/src/PepperDash.Essentials.Core/Room/IRoomEventSchedule.cs @@ -2,19 +2,18 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public interface IRoomEventSchedule { - public interface IRoomEventSchedule - { - void AddOrUpdateScheduledEvent(ScheduledEventConfig eventConfig); + void AddOrUpdateScheduledEvent(ScheduledEventConfig eventConfig); - List GetScheduledEvents(); + List GetScheduledEvents(); - event EventHandler ScheduledEventsChanged; - } + event EventHandler ScheduledEventsChanged; +} - public class ScheduledEventEventArgs : EventArgs - { - public List ScheduledEvents; - } +public class ScheduledEventEventArgs : EventArgs +{ + public List ScheduledEvents; } diff --git a/src/PepperDash.Essentials.Core/Room/Interfaces.cs b/src/PepperDash.Essentials.Core/Room/Interfaces.cs index 6bad45dfb..ddbfe16aa 100644 --- a/src/PepperDash.Essentials.Core/Room/Interfaces.cs +++ b/src/PepperDash.Essentials.Core/Room/Interfaces.cs @@ -7,165 +7,164 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// For rooms with in call feedback +/// +public interface IHasInCallFeedback { - /// - /// For rooms with in call feedback - /// - public interface IHasInCallFeedback - { - BoolFeedback InCallFeedback { get; } - } + BoolFeedback InCallFeedback { get; } +} - /// - /// For rooms with a single display - /// - public interface IHasDefaultDisplay - { - IRoutingSink DefaultDisplay { get; } - } +/// +/// For rooms with a single display +/// +public interface IHasDefaultDisplay +{ + IRoutingSink DefaultDisplay { get; } +} - /// - /// For rooms with multiple displays - /// - public interface IHasMultipleDisplays - { - Dictionary Displays { get; } - } +/// +/// For rooms with multiple displays +/// +public interface IHasMultipleDisplays +{ + Dictionary Displays { get; } +} - /// - /// For rooms with routing - /// - public interface IRunRouteAction - { - void RunRouteAction(string routeKey, string sourceListKey); +/// +/// For rooms with routing +/// +public interface IRunRouteAction +{ + void RunRouteAction(string routeKey, string sourceListKey); - void RunRouteAction(string routeKey, string sourceListKey, Action successCallback); - } + void RunRouteAction(string routeKey, string sourceListKey, Action successCallback); +} - /// - /// Simplified routing direct from source to destination - /// - public interface IRunDirectRouteAction - { - void RunDirectRoute(string sourceKey, string destinationKey, eRoutingSignalType type = eRoutingSignalType.AudioVideo); - } - - /// - /// Describes a room with matrix routing - /// - public interface IHasMatrixRouting - { - string MatrixRoutingDeviceKey { get; } +/// +/// Simplified routing direct from source to destination +/// +public interface IRunDirectRouteAction +{ + void RunDirectRoute(string sourceKey, string destinationKey, eRoutingSignalType type = eRoutingSignalType.AudioVideo); +} - List EndpointKeys { get; } - } +/// +/// Describes a room with matrix routing +/// +public interface IHasMatrixRouting +{ + string MatrixRoutingDeviceKey { get; } - /// - /// Describes a room with routing endpoints - /// - public interface IHasRoutingEndpoints - { - List EndpointKeys { get; } - } + List EndpointKeys { get; } +} - /// - /// Describes a room with a shutdown prompt timer - /// - public interface IShutdownPromptTimer - { - SecondsCountdownTimer ShutdownPromptTimer { get; } +/// +/// Describes a room with routing endpoints +/// +public interface IHasRoutingEndpoints +{ + List EndpointKeys { get; } +} - void SetShutdownPromptSeconds(int seconds); +/// +/// Describes a room with a shutdown prompt timer +/// +public interface IShutdownPromptTimer +{ + SecondsCountdownTimer ShutdownPromptTimer { get; } - void StartShutdown(eShutdownType type); - } + void SetShutdownPromptSeconds(int seconds); - /// - /// Describes a room with a tech password - /// - public interface ITechPassword - { - event EventHandler TechPasswordValidateResult; + void StartShutdown(eShutdownType type); +} - event EventHandler TechPasswordChanged; +/// +/// Describes a room with a tech password +/// +public interface ITechPassword +{ + event EventHandler TechPasswordValidateResult; - int TechPasswordLength { get; } + event EventHandler TechPasswordChanged; - void ValidateTechPassword(string password); + int TechPasswordLength { get; } - void SetTechPassword(string oldPassword, string newPassword); - } + void ValidateTechPassword(string password); - public class TechPasswordEventArgs : EventArgs - { - public bool IsValid { get; private set; } + void SetTechPassword(string oldPassword, string newPassword); +} - public TechPasswordEventArgs(bool isValid) - { - IsValid = isValid; - } - } +public class TechPasswordEventArgs : EventArgs +{ + public bool IsValid { get; private set; } - /// - /// For rooms that default presentation only routing - /// - public interface IRunDefaultPresentRoute + public TechPasswordEventArgs(bool isValid) { - bool RunDefaultPresentRoute(); + IsValid = isValid; } +} - /// - /// For rooms that have default presentation and calling routes - /// - public interface IRunDefaultCallRoute : IRunDefaultPresentRoute - { - bool RunDefaultCallRoute(); - } +/// +/// For rooms that default presentation only routing +/// +public interface IRunDefaultPresentRoute +{ + bool RunDefaultPresentRoute(); +} - /// - /// Describes environmental controls available on a room such as lighting, shades, temperature, etc. - /// - public interface IEnvironmentalControls - { - List EnvironmentalControlDevices { get; } +/// +/// For rooms that have default presentation and calling routes +/// +public interface IRunDefaultCallRoute : IRunDefaultPresentRoute +{ + bool RunDefaultCallRoute(); +} - bool HasEnvironmentalControlDevices { get; } - } +/// +/// Describes environmental controls available on a room such as lighting, shades, temperature, etc. +/// +public interface IEnvironmentalControls +{ + List EnvironmentalControlDevices { get; } - public interface IRoomOccupancy:IKeyed - { - IOccupancyStatusProvider RoomOccupancy { get; } - bool OccupancyStatusProviderIsRemote { get; } + bool HasEnvironmentalControlDevices { get; } +} - void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes); +public interface IRoomOccupancy:IKeyed +{ + IOccupancyStatusProvider RoomOccupancy { get; } + bool OccupancyStatusProviderIsRemote { get; } - void RoomVacatedForTimeoutPeriod(object o); + void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes); - void StartRoomVacancyTimer(eVacancyMode mode); + void RoomVacatedForTimeoutPeriod(object o); - eVacancyMode VacancyMode { get; } + void StartRoomVacancyTimer(eVacancyMode mode); - event EventHandler RoomOccupancyIsSet; - } + eVacancyMode VacancyMode { get; } - public interface IEmergency - { - EssentialsRoomEmergencyBase Emergency { get; } - } + event EventHandler RoomOccupancyIsSet; +} - public interface IMicrophonePrivacy - { - Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; } - } +public interface IEmergency +{ + EssentialsRoomEmergencyBase Emergency { get; } +} - public interface IHasAccessoryDevices : IKeyName - { - List AccessoryDeviceKeys { get; } - } +public interface IMicrophonePrivacy +{ + Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; } +} - public interface IHasCiscoNavigatorTouchpanel - { - string CiscoNavigatorTouchpanelKey { get; } - } +public interface IHasAccessoryDevices : IKeyName +{ + List AccessoryDeviceKeys { get; } +} + +public interface IHasCiscoNavigatorTouchpanel +{ + string CiscoNavigatorTouchpanelKey { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/Room.cs b/src/PepperDash.Essentials.Core/Room/Room.cs index 5e190bc96..2531b21a3 100644 --- a/src/PepperDash.Essentials.Core/Room/Room.cs +++ b/src/PepperDash.Essentials.Core/Room/Room.cs @@ -8,8 +8,8 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + //*************************************************************************************************** public abstract class Room : Device, IHasFeedback @@ -42,15 +42,14 @@ public virtual FeedbackCollection Feedbacks { get { - return new FeedbackCollection - { - RoomIsOnFeedback, - IsCoolingDownFeedback, - IsWarmingUpFeedback - }; + return new FeedbackCollection + { + RoomIsOnFeedback, + IsCoolingDownFeedback, + IsWarmingUpFeedback + }; } } #endregion - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Room/iOccupancyStatusProvider.cs b/src/PepperDash.Essentials.Core/Room/iOccupancyStatusProvider.cs index f46f10b12..530289698 100644 --- a/src/PepperDash.Essentials.Core/Room/iOccupancyStatusProvider.cs +++ b/src/PepperDash.Essentials.Core/Room/iOccupancyStatusProvider.cs @@ -6,10 +6,9 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public interface IOccupancyStatusProvider { - public interface IOccupancyStatusProvider - { - BoolFeedback RoomIsOccupiedFeedback { get; } - } + BoolFeedback RoomIsOccupiedFeedback { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/DummyRoutingInputsDevice.cs b/src/PepperDash.Essentials.Core/Routing/DummyRoutingInputsDevice.cs index d8b50a9ba..57a5119e3 100644 --- a/src/PepperDash.Essentials.Core/Routing/DummyRoutingInputsDevice.cs +++ b/src/PepperDash.Essentials.Core/Routing/DummyRoutingInputsDevice.cs @@ -6,8 +6,8 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core.Routing -{ +namespace PepperDash.Essentials.Core.Routing; + public class DummyRoutingInputsDevice : Device, IRoutingSource, IRoutingOutputs { /// @@ -32,5 +32,4 @@ public DummyRoutingInputsDevice(string key) : base(key) AudioVideoOutputPort = new RoutingOutputPort("internal", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.BackplaneOnly, null, this, true); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/Extensions.cs b/src/PepperDash.Essentials.Core/Routing/Extensions.cs index f3eec22a6..da58b586d 100644 --- a/src/PepperDash.Essentials.Core/Routing/Extensions.cs +++ b/src/PepperDash.Essentials.Core/Routing/Extensions.cs @@ -9,429 +9,428 @@ using Debug = PepperDash.Core.Debug; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + + +/// +/// Extensions added to any IRoutingInputs classes to provide discovery-based routing +/// on those destinations. +/// +public static class Extensions { + /// + /// Stores pending route requests, keyed by the destination device key. + /// Used primarily to handle routing requests while a device is cooling down. + /// + private static readonly Dictionary RouteRequests = new Dictionary(); /// - /// Extensions added to any IRoutingInputs classes to provide discovery-based routing - /// on those destinations. + /// A queue to process route requests and releases sequentially. /// - public static class Extensions + private static readonly GenericQueue routeRequestQueue = new GenericQueue("routingQueue"); + + /// + /// Gets any existing RouteDescriptor for a destination, clears it using ReleaseRoute + /// and then attempts a new Route and if sucessful, stores that RouteDescriptor + /// in RouteDescriptorCollection.DefaultCollection + /// + public static void ReleaseAndMakeRoute(this IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, string destinationPortKey = "", string sourcePortKey = "") { - /// - /// Stores pending route requests, keyed by the destination device key. - /// Used primarily to handle routing requests while a device is cooling down. - /// - private static readonly Dictionary RouteRequests = new Dictionary(); - - /// - /// A queue to process route requests and releases sequentially. - /// - private static readonly GenericQueue routeRequestQueue = new GenericQueue("routingQueue"); - - /// - /// Gets any existing RouteDescriptor for a destination, clears it using ReleaseRoute - /// and then attempts a new Route and if sucessful, stores that RouteDescriptor - /// in RouteDescriptorCollection.DefaultCollection - /// - public static void ReleaseAndMakeRoute(this IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, string destinationPortKey = "", string sourcePortKey = "") - { - // Remove this line before committing!!!!! - var frame = new StackFrame(1, true); - Debug.LogMessage(LogEventLevel.Information, "ReleaseAndMakeRoute Called from {method} with params {destinationKey}:{sourceKey}:{signalType}:{destinationPortKey}:{sourcePortKey}", frame.GetMethod().Name, destination.Key, source.Key, signalType.ToString(), destinationPortKey, sourcePortKey); + // Remove this line before committing!!!!! + var frame = new StackFrame(1, true); + Debug.LogMessage(LogEventLevel.Information, "ReleaseAndMakeRoute Called from {method} with params {destinationKey}:{sourceKey}:{signalType}:{destinationPortKey}:{sourcePortKey}", frame.GetMethod().Name, destination.Key, source.Key, signalType.ToString(), destinationPortKey, sourcePortKey); - var inputPort = string.IsNullOrEmpty(destinationPortKey) ? null : destination.InputPorts.FirstOrDefault(p => p.Key == destinationPortKey); - var outputPort = string.IsNullOrEmpty(sourcePortKey) ? null : source.OutputPorts.FirstOrDefault(p => p.Key == sourcePortKey); + var inputPort = string.IsNullOrEmpty(destinationPortKey) ? null : destination.InputPorts.FirstOrDefault(p => p.Key == destinationPortKey); + var outputPort = string.IsNullOrEmpty(sourcePortKey) ? null : source.OutputPorts.FirstOrDefault(p => p.Key == sourcePortKey); - ReleaseAndMakeRoute(destination, source, signalType, inputPort, outputPort); - } + ReleaseAndMakeRoute(destination, source, signalType, inputPort, outputPort); + } - /// - /// Will release the existing route to the destination, if a route is found. This does not CLEAR the route, only stop counting usage time on any output ports that have a usage tracker set - /// - /// destination to clear - public static void ReleaseRoute(this IRoutingInputs destination) - { - routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, string.Empty, false)); - } + /// + /// Will release the existing route to the destination, if a route is found. This does not CLEAR the route, only stop counting usage time on any output ports that have a usage tracker set + /// + /// destination to clear + public static void ReleaseRoute(this IRoutingInputs destination) + { + routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, string.Empty, false)); + } - /// - /// Will release the existing route to the destination, if a route is found. This does not CLEAR the route, only stop counting usage time on any output ports that have a usage tracker set - /// - /// destination to clear - /// Input to use to find existing route - public static void ReleaseRoute(this IRoutingInputs destination, string inputPortKey) - { - routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, inputPortKey, false)); - } + /// + /// Will release the existing route to the destination, if a route is found. This does not CLEAR the route, only stop counting usage time on any output ports that have a usage tracker set + /// + /// destination to clear + /// Input to use to find existing route + public static void ReleaseRoute(this IRoutingInputs destination, string inputPortKey) + { + routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, inputPortKey, false)); + } - /// - /// Clears the route on the destination. This will remove any routes that are currently in use - /// - /// Destination - public static void ClearRoute(this IRoutingInputs destination) - { - routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, string.Empty, true)); - } + /// + /// Clears the route on the destination. This will remove any routes that are currently in use + /// + /// Destination + public static void ClearRoute(this IRoutingInputs destination) + { + routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, string.Empty, true)); + } - /// - /// Clears the route on the destination. This will remove any routes that are currently in use - /// - /// destination - /// input to use to find existing route - public static void ClearRoute(this IRoutingInputs destination, string inputPortKey) - { - routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, inputPortKey, true)); - } + /// + /// Clears the route on the destination. This will remove any routes that are currently in use + /// + /// destination + /// input to use to find existing route + public static void ClearRoute(this IRoutingInputs destination, string inputPortKey) + { + routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, inputPortKey, true)); + } + + /// + /// Removes the route request for the destination. This will remove any routes that are currently in use + /// + /// destination device key + public static void RemoveRouteRequestForDestination(string destinationKey) + { + Debug.LogMessage(LogEventLevel.Information, "Removing route request for {destination}", null, destinationKey); + + var result = RouteRequests.Remove(destinationKey); - /// - /// Removes the route request for the destination. This will remove any routes that are currently in use - /// - /// destination device key - public static void RemoveRouteRequestForDestination(string destinationKey) + var messageTemplate = result ? "Route Request for {destination} removed" : "Route Request for {destination} not found"; + + Debug.LogMessage(LogEventLevel.Information, messageTemplate, null, destinationKey); + } + + /// + /// Builds a RouteDescriptor that contains the steps necessary to make a route between devices. + /// Routes of type AudioVideo will be built as two separate routes, audio and video. If + /// a route is discovered, a new RouteDescriptor is returned. If one or both parts + /// of an audio/video route are discovered a route descriptor is returned. If no route is + /// discovered, then null is returned + /// + public static (RouteDescriptor, RouteDescriptor) GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort, RoutingOutputPort sourcePort) + { + // if it's a single signal type, find the route + if (!signalType.HasFlag(eRoutingSignalType.AudioVideo) && + !(signalType.HasFlag(eRoutingSignalType.Video) && signalType.HasFlag(eRoutingSignalType.SecondaryAudio))) { - Debug.LogMessage(LogEventLevel.Information, "Removing route request for {destination}", null, destinationKey); + var singleTypeRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, signalType); + Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {sourceKey} of type {type}", destination, source.Key, signalType); - var result = RouteRequests.Remove(destinationKey); + if (!destination.GetRouteToSource(source, null, null, signalType, 0, singleTypeRouteDescriptor, destinationPort, sourcePort)) + singleTypeRouteDescriptor = null; - var messageTemplate = result ? "Route Request for {destination} removed" : "Route Request for {destination} not found"; + var routes = singleTypeRouteDescriptor?.Routes ?? new List(); + foreach (var route in routes) + { + Debug.LogMessage(LogEventLevel.Verbose, "Route for device: {route}", destination, route.ToString()); + } - Debug.LogMessage(LogEventLevel.Information, messageTemplate, null, destinationKey); + return (singleTypeRouteDescriptor, null); } + // otherwise, audioVideo needs to be handled as two steps. + + Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {sourceKey} of type {type}", destination, source.Key); + + RouteDescriptor audioRouteDescriptor; - /// - /// Builds a RouteDescriptor that contains the steps necessary to make a route between devices. - /// Routes of type AudioVideo will be built as two separate routes, audio and video. If - /// a route is discovered, a new RouteDescriptor is returned. If one or both parts - /// of an audio/video route are discovered a route descriptor is returned. If no route is - /// discovered, then null is returned - /// - public static (RouteDescriptor, RouteDescriptor) GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort, RoutingOutputPort sourcePort) + if (signalType.HasFlag(eRoutingSignalType.SecondaryAudio)) { - // if it's a single signal type, find the route - if (!signalType.HasFlag(eRoutingSignalType.AudioVideo) && - !(signalType.HasFlag(eRoutingSignalType.Video) && signalType.HasFlag(eRoutingSignalType.SecondaryAudio))) - { - var singleTypeRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, signalType); - Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {sourceKey} of type {type}", destination, source.Key, signalType); + audioRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, eRoutingSignalType.SecondaryAudio); + } else + { + audioRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, eRoutingSignalType.Audio); + } - if (!destination.GetRouteToSource(source, null, null, signalType, 0, singleTypeRouteDescriptor, destinationPort, sourcePort)) - singleTypeRouteDescriptor = null; + var audioSuccess = destination.GetRouteToSource(source, null, null, signalType.HasFlag(eRoutingSignalType.SecondaryAudio) ? eRoutingSignalType.SecondaryAudio : eRoutingSignalType.Audio, 0, audioRouteDescriptor, destinationPort, sourcePort); - var routes = singleTypeRouteDescriptor?.Routes ?? new List(); - foreach (var route in routes) - { - Debug.LogMessage(LogEventLevel.Verbose, "Route for device: {route}", destination, route.ToString()); - } + if (!audioSuccess) + Debug.LogMessage(LogEventLevel.Debug, "Cannot find audio route to {0}", destination, source.Key); - return (singleTypeRouteDescriptor, null); - } - // otherwise, audioVideo needs to be handled as two steps. + var videoRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, eRoutingSignalType.Video); - Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {sourceKey} of type {type}", destination, source.Key); + var videoSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Video, 0, videoRouteDescriptor, destinationPort, sourcePort); - RouteDescriptor audioRouteDescriptor; + if (!videoSuccess) + Debug.LogMessage(LogEventLevel.Debug, "Cannot find video route to {0}", destination, source.Key); - if (signalType.HasFlag(eRoutingSignalType.SecondaryAudio)) - { - audioRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, eRoutingSignalType.SecondaryAudio); - } else - { - audioRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, eRoutingSignalType.Audio); - } + foreach (var route in audioRouteDescriptor.Routes) + { + Debug.LogMessage(LogEventLevel.Verbose, "Audio route for device: {route}", destination, route.ToString()); + } - var audioSuccess = destination.GetRouteToSource(source, null, null, signalType.HasFlag(eRoutingSignalType.SecondaryAudio) ? eRoutingSignalType.SecondaryAudio : eRoutingSignalType.Audio, 0, audioRouteDescriptor, destinationPort, sourcePort); + foreach (var route in videoRouteDescriptor.Routes) + { + Debug.LogMessage(LogEventLevel.Verbose, "Video route for device: {route}", destination, route.ToString()); + } - if (!audioSuccess) - Debug.LogMessage(LogEventLevel.Debug, "Cannot find audio route to {0}", destination, source.Key); - var videoRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, eRoutingSignalType.Video); + if (!audioSuccess && !videoSuccess) + return (null, null); - var videoSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Video, 0, videoRouteDescriptor, destinationPort, sourcePort); - if (!videoSuccess) - Debug.LogMessage(LogEventLevel.Debug, "Cannot find video route to {0}", destination, source.Key); + return (audioRouteDescriptor, videoRouteDescriptor); + } - foreach (var route in audioRouteDescriptor.Routes) - { - Debug.LogMessage(LogEventLevel.Verbose, "Audio route for device: {route}", destination, route.ToString()); - } + /// + /// Internal method to handle the logic for releasing an existing route and making a new one. + /// Handles devices with cooling states by queueing the request. + /// + /// The destination device. + /// The source device. + /// The type of signal to route. + /// The specific destination input port (optional). + /// The specific source output port (optional). + private static void ReleaseAndMakeRoute(IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort = null, RoutingOutputPort sourcePort = null) + { + if (destination == null) throw new ArgumentNullException(nameof(destination)); + if (source == null) throw new ArgumentNullException(nameof(source)); + if (destinationPort == null) Debug.LogMessage(LogEventLevel.Information, "Destination port is null"); + if (sourcePort == null) Debug.LogMessage(LogEventLevel.Information, "Source port is null"); - foreach (var route in videoRouteDescriptor.Routes) - { - Debug.LogMessage(LogEventLevel.Verbose, "Video route for device: {route}", destination, route.ToString()); - } + var routeRequest = new RouteRequest + { + Destination = destination, + DestinationPort = destinationPort, + Source = source, + SourcePort = sourcePort, + SignalType = signalType + }; + var coolingDevice = destination as IWarmingCooling; - if (!audioSuccess && !videoSuccess) - return (null, null); + //We already have a route request for this device, and it's a cooling device and is cooling + if (RouteRequests.TryGetValue(destination.Key, out RouteRequest existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) + { + coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown; + coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; - return (audioRouteDescriptor, videoRouteDescriptor); - } + RouteRequests[destination.Key] = routeRequest; - /// - /// Internal method to handle the logic for releasing an existing route and making a new one. - /// Handles devices with cooling states by queueing the request. - /// - /// The destination device. - /// The source device. - /// The type of signal to route. - /// The specific destination input port (optional). - /// The specific source output port (optional). - private static void ReleaseAndMakeRoute(IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort = null, RoutingOutputPort sourcePort = null) - { - if (destination == null) throw new ArgumentNullException(nameof(destination)); - if (source == null) throw new ArgumentNullException(nameof(source)); - if (destinationPort == null) Debug.LogMessage(LogEventLevel.Information, "Destination port is null"); - if (sourcePort == null) Debug.LogMessage(LogEventLevel.Information, "Source port is null"); + Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is cooling down and already has a routing request stored. Storing new route request to route to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key); - var routeRequest = new RouteRequest - { - Destination = destination, - DestinationPort = destinationPort, - Source = source, - SourcePort = sourcePort, - SignalType = signalType - }; + return; + } - var coolingDevice = destination as IWarmingCooling; + //New Request + if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) + { + coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; - //We already have a route request for this device, and it's a cooling device and is cooling - if (RouteRequests.TryGetValue(destination.Key, out RouteRequest existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) - { - coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown; + RouteRequests.Add(destination.Key, routeRequest); - coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; + Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is cooling down. Storing route request to route to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key); + return; + } - RouteRequests[destination.Key] = routeRequest; + if (RouteRequests.ContainsKey(destination.Key) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == false) + { + var handledRequest = RouteRequests[destination.Key]; - Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is cooling down and already has a routing request stored. Storing new route request to route to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key); + coolingDevice.IsCoolingDownFeedback.OutputChange -= handledRequest.HandleCooldown; - return; - } + RouteRequests.Remove(destination.Key); - //New Request - if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) - { - coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; + Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is NOT cooling down. Removing stored route request and routing to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key); + } - RouteRequests.Add(destination.Key, routeRequest); + routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination,destinationPort?.Key ?? string.Empty, false)); - Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is cooling down. Storing route request to route to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key); + routeRequestQueue.Enqueue(new RouteRequestQueueItem(RunRouteRequest, routeRequest)); + } + + /// + /// Executes the actual routing based on a . + /// Finds the route path, adds it to the collection, and executes the switches. + /// + /// The route request details. + private static void RunRouteRequest(RouteRequest request) + { + try + { + if (request.Source == null) return; - } - if (RouteRequests.ContainsKey(destination.Key) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == false) - { - var handledRequest = RouteRequests[destination.Key]; + var (audioOrSingleRoute, videoRoute) = request.Destination.GetRouteToSource(request.Source, request.SignalType, request.DestinationPort, request.SourcePort); - coolingDevice.IsCoolingDownFeedback.OutputChange -= handledRequest.HandleCooldown; + if (audioOrSingleRoute == null && videoRoute == null) + return; - RouteRequests.Remove(destination.Key); + RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(audioOrSingleRoute); - Debug.LogMessage(LogEventLevel.Information, "Device: {destination} is NOT cooling down. Removing stored route request and routing to source key: {sourceKey}", null, destination.Key, routeRequest.Source.Key); + if (videoRoute != null) + { + RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(videoRoute); } - routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination,destinationPort?.Key ?? string.Empty, false)); + Debug.LogMessage(LogEventLevel.Verbose, "Executing full route", request.Destination); - routeRequestQueue.Enqueue(new RouteRequestQueueItem(RunRouteRequest, routeRequest)); + audioOrSingleRoute.ExecuteRoutes(); + videoRoute?.ExecuteRoutes(); + } catch(Exception ex) + { + Debug.LogMessage(ex, "Exception Running Route Request {request}", null, request); } + } - /// - /// Executes the actual routing based on a . - /// Finds the route path, adds it to the collection, and executes the switches. - /// - /// The route request details. - private static void RunRouteRequest(RouteRequest request) + /// + /// Will release the existing route on the destination, if it is found in RouteDescriptorCollection.DefaultCollection + /// + /// + /// The input port key to use to find the route. If empty, will use the first available input port + /// If true, will clear the route on the destination. This will remove any routes that are currently in use + private static void ReleaseRouteInternal(IRoutingInputs destination, string inputPortKey, bool clearRoute) + { + try { - try - { - if (request.Source == null) - return; - - var (audioOrSingleRoute, videoRoute) = request.Destination.GetRouteToSource(request.Source, request.SignalType, request.DestinationPort, request.SourcePort); - - if (audioOrSingleRoute == null && videoRoute == null) - return; + Debug.LogMessage(LogEventLevel.Information, "Release route for '{destination}':'{inputPortKey}'", destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey); - RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(audioOrSingleRoute); + if (RouteRequests.TryGetValue(destination.Key, out RouteRequest existingRequest) && destination is IWarmingCooling) + { + var coolingDevice = destination as IWarmingCooling; - if (videoRoute != null) - { - RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(videoRoute); - } + coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRequest.HandleCooldown; + } - Debug.LogMessage(LogEventLevel.Verbose, "Executing full route", request.Destination); + RouteRequests.Remove(destination.Key); - audioOrSingleRoute.ExecuteRoutes(); - videoRoute?.ExecuteRoutes(); - } catch(Exception ex) + var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination, inputPortKey); + if (current != null) { - Debug.LogMessage(ex, "Exception Running Route Request {request}", null, request); + Debug.LogMessage(LogEventLevel.Information, "Releasing current route: {0}", destination, current.Source.Key); + current.ReleaseRoutes(clearRoute); } + } catch (Exception ex) + { + Debug.LogMessage(ex, "Exception releasing route for '{destination}':'{inputPortKey}'",null, destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey); } + } - /// - /// Will release the existing route on the destination, if it is found in RouteDescriptorCollection.DefaultCollection - /// - /// - /// The input port key to use to find the route. If empty, will use the first available input port - /// If true, will clear the route on the destination. This will remove any routes that are currently in use - private static void ReleaseRouteInternal(IRoutingInputs destination, string inputPortKey, bool clearRoute) - { - try - { - Debug.LogMessage(LogEventLevel.Information, "Release route for '{destination}':'{inputPortKey}'", destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey); + /// + /// The recursive part of this. Will stop on each device, search its inputs for the + /// desired source and if not found, invoke this function for the each input port + /// hoping to find the source. + /// + /// + /// + /// The RoutingOutputPort whose link is being checked for a route + /// Prevents Devices from being twice-checked + /// This recursive function should not be called with AudioVideo + /// Just an informational counter + /// The RouteDescriptor being populated as the route is discovered + /// true if source is hit + private static bool GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source, + RoutingOutputPort outputPortToUse, List alreadyCheckedDevices, + eRoutingSignalType signalType, int cycle, RouteDescriptor routeTable, RoutingInputPort destinationPort, RoutingOutputPort sourcePort) + { + cycle++; - if (RouteRequests.TryGetValue(destination.Key, out RouteRequest existingRequest) && destination is IWarmingCooling) - { - var coolingDevice = destination as IWarmingCooling; + Debug.LogMessage(LogEventLevel.Verbose, "GetRouteToSource: {cycle} {sourceKey}:{sourcePortKey}--> {destinationKey}:{destinationPortKey} {type}", null, cycle, source.Key, sourcePort?.Key ?? "auto", destination.Key, destinationPort?.Key ?? "auto", signalType.ToString()); - coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRequest.HandleCooldown; - } + RoutingInputPort goodInputPort = null; - RouteRequests.Remove(destination.Key); + IEnumerable destinationTieLines; + TieLine directTie = null; - var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination, inputPortKey); - if (current != null) - { - Debug.LogMessage(LogEventLevel.Information, "Releasing current route: {0}", destination, current.Source.Key); - current.ReleaseRoutes(clearRoute); - } - } catch (Exception ex) - { - Debug.LogMessage(ex, "Exception releasing route for '{destination}':'{inputPortKey}'",null, destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey); - } + if (destinationPort == null) + { + destinationTieLines = TieLineCollection.Default.Where(t => + t.DestinationPort.ParentDevice.Key == destination.Key && (t.Type.HasFlag(signalType) || signalType == eRoutingSignalType.AudioVideo)); + } + else + { + destinationTieLines = TieLineCollection.Default.Where(t => t.DestinationPort.ParentDevice.Key == destination.Key && t.DestinationPort.Key == destinationPort.Key && (t.Type.HasFlag(signalType))); } - /// - /// The recursive part of this. Will stop on each device, search its inputs for the - /// desired source and if not found, invoke this function for the each input port - /// hoping to find the source. - /// - /// - /// - /// The RoutingOutputPort whose link is being checked for a route - /// Prevents Devices from being twice-checked - /// This recursive function should not be called with AudioVideo - /// Just an informational counter - /// The RouteDescriptor being populated as the route is discovered - /// true if source is hit - private static bool GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source, - RoutingOutputPort outputPortToUse, List alreadyCheckedDevices, - eRoutingSignalType signalType, int cycle, RouteDescriptor routeTable, RoutingInputPort destinationPort, RoutingOutputPort sourcePort) + // find the TieLine without a port + if (destinationPort == null && sourcePort == null) + { + directTie = destinationTieLines.FirstOrDefault(t => t.DestinationPort.ParentDevice.Key == destination.Key && t.SourcePort.ParentDevice.Key == source.Key); + } + // find a tieLine to a specific destination port without a specific source port + else if (destinationPort != null && sourcePort == null) + { + directTie = destinationTieLines.FirstOrDefault(t => t.DestinationPort.ParentDevice.Key == destination.Key && t.DestinationPort.Key == destinationPort.Key && t.SourcePort.ParentDevice.Key == source.Key); + } + // find a tieline to a specific source port without a specific destination port + else if (destinationPort == null & sourcePort != null) + { + directTie = destinationTieLines.FirstOrDefault(t => t.DestinationPort.ParentDevice.Key == destination.Key && t.SourcePort.ParentDevice.Key == source.Key && t.SourcePort.Key == sourcePort.Key); + } + // find a tieline to a specific source port and destination port + else if (destinationPort != null && sourcePort != null) { - cycle++; + directTie = destinationTieLines.FirstOrDefault(t => t.DestinationPort.ParentDevice.Key == destination.Key && t.DestinationPort.Key == destinationPort.Key && t.SourcePort.ParentDevice.Key == source.Key && t.SourcePort.Key == sourcePort.Key); + } - Debug.LogMessage(LogEventLevel.Verbose, "GetRouteToSource: {cycle} {sourceKey}:{sourcePortKey}--> {destinationKey}:{destinationPortKey} {type}", null, cycle, source.Key, sourcePort?.Key ?? "auto", destination.Key, destinationPort?.Key ?? "auto", signalType.ToString()); + if (directTie != null) // Found a tie directly to the source + { + goodInputPort = directTie.DestinationPort; + } + else // no direct-connect. Walk back devices. + { + Debug.LogMessage(LogEventLevel.Verbose, "is not directly connected to {sourceKey}. Walking down tie lines", destination, source.Key); - RoutingInputPort goodInputPort = null; + // No direct tie? Run back out on the inputs' attached devices... + // Only the ones that are routing devices + var midpointTieLines = destinationTieLines.Where(t => t.SourcePort.ParentDevice is IRoutingInputsOutputs); - IEnumerable destinationTieLines; - TieLine directTie = null; + //Create a list for tracking already checked devices to avoid loops, if it doesn't already exist from previous iteration + if (alreadyCheckedDevices == null) + alreadyCheckedDevices = new List(); + alreadyCheckedDevices.Add(destination as IRoutingInputsOutputs); - if (destinationPort == null) - { - destinationTieLines = TieLineCollection.Default.Where(t => - t.DestinationPort.ParentDevice.Key == destination.Key && (t.Type.HasFlag(signalType) || signalType == eRoutingSignalType.AudioVideo)); - } - else + foreach (var tieLine in midpointTieLines) { - destinationTieLines = TieLineCollection.Default.Where(t => t.DestinationPort.ParentDevice.Key == destination.Key && t.DestinationPort.Key == destinationPort.Key && (t.Type.HasFlag(signalType))); - } + var midpointDevice = tieLine.SourcePort.ParentDevice as IRoutingInputsOutputs; - // find the TieLine without a port - if (destinationPort == null && sourcePort == null) - { - directTie = destinationTieLines.FirstOrDefault(t => t.DestinationPort.ParentDevice.Key == destination.Key && t.SourcePort.ParentDevice.Key == source.Key); - } - // find a tieLine to a specific destination port without a specific source port - else if (destinationPort != null && sourcePort == null) - { - directTie = destinationTieLines.FirstOrDefault(t => t.DestinationPort.ParentDevice.Key == destination.Key && t.DestinationPort.Key == destinationPort.Key && t.SourcePort.ParentDevice.Key == source.Key); - } - // find a tieline to a specific source port without a specific destination port - else if (destinationPort == null & sourcePort != null) - { - directTie = destinationTieLines.FirstOrDefault(t => t.DestinationPort.ParentDevice.Key == destination.Key && t.SourcePort.ParentDevice.Key == source.Key && t.SourcePort.Key == sourcePort.Key); - } - // find a tieline to a specific source port and destination port - else if (destinationPort != null && sourcePort != null) - { - directTie = destinationTieLines.FirstOrDefault(t => t.DestinationPort.ParentDevice.Key == destination.Key && t.DestinationPort.Key == destinationPort.Key && t.SourcePort.ParentDevice.Key == source.Key && t.SourcePort.Key == sourcePort.Key); - } + // Check if this previous device has already been walked + if (alreadyCheckedDevices.Contains(midpointDevice)) + { + Debug.LogMessage(LogEventLevel.Verbose, "Skipping input {midpointDeviceKey} on {destinationKey}, this was already checked", destination, midpointDevice.Key, destination.Key); + continue; + } - if (directTie != null) // Found a tie directly to the source - { - goodInputPort = directTie.DestinationPort; - } - else // no direct-connect. Walk back devices. - { - Debug.LogMessage(LogEventLevel.Verbose, "is not directly connected to {sourceKey}. Walking down tie lines", destination, source.Key); + var midpointOutputPort = tieLine.SourcePort; - // No direct tie? Run back out on the inputs' attached devices... - // Only the ones that are routing devices - var midpointTieLines = destinationTieLines.Where(t => t.SourcePort.ParentDevice is IRoutingInputsOutputs); + Debug.LogMessage(LogEventLevel.Verbose, "Trying to find route on {midpointDeviceKey}", destination, midpointDevice.Key); - //Create a list for tracking already checked devices to avoid loops, if it doesn't already exist from previous iteration - if (alreadyCheckedDevices == null) - alreadyCheckedDevices = new List(); - alreadyCheckedDevices.Add(destination as IRoutingInputsOutputs); + // haven't seen this device yet. Do it. Pass the output port to the next + // level to enable switching on success + var upstreamRoutingSuccess = midpointDevice.GetRouteToSource(source, midpointOutputPort, + alreadyCheckedDevices, signalType, cycle, routeTable, null, sourcePort); - foreach (var tieLine in midpointTieLines) + if (upstreamRoutingSuccess) { - var midpointDevice = tieLine.SourcePort.ParentDevice as IRoutingInputsOutputs; - - // Check if this previous device has already been walked - if (alreadyCheckedDevices.Contains(midpointDevice)) - { - Debug.LogMessage(LogEventLevel.Verbose, "Skipping input {midpointDeviceKey} on {destinationKey}, this was already checked", destination, midpointDevice.Key, destination.Key); - continue; - } - - var midpointOutputPort = tieLine.SourcePort; - - Debug.LogMessage(LogEventLevel.Verbose, "Trying to find route on {midpointDeviceKey}", destination, midpointDevice.Key); - - // haven't seen this device yet. Do it. Pass the output port to the next - // level to enable switching on success - var upstreamRoutingSuccess = midpointDevice.GetRouteToSource(source, midpointOutputPort, - alreadyCheckedDevices, signalType, cycle, routeTable, null, sourcePort); - - if (upstreamRoutingSuccess) - { - Debug.LogMessage(LogEventLevel.Verbose, "Upstream device route found", destination); - Debug.LogMessage(LogEventLevel.Verbose, "Route found on {midpointDeviceKey}", destination, midpointDevice.Key); - Debug.LogMessage(LogEventLevel.Verbose, "TieLine: SourcePort: {SourcePort} DestinationPort: {DestinationPort}", destination, tieLine.SourcePort, tieLine.DestinationPort); - goodInputPort = tieLine.DestinationPort; - break; // Stop looping the inputs in this cycle - } + Debug.LogMessage(LogEventLevel.Verbose, "Upstream device route found", destination); + Debug.LogMessage(LogEventLevel.Verbose, "Route found on {midpointDeviceKey}", destination, midpointDevice.Key); + Debug.LogMessage(LogEventLevel.Verbose, "TieLine: SourcePort: {SourcePort} DestinationPort: {DestinationPort}", destination, tieLine.SourcePort, tieLine.DestinationPort); + goodInputPort = tieLine.DestinationPort; + break; // Stop looping the inputs in this cycle } } + } - if (goodInputPort == null) - { - Debug.LogMessage(LogEventLevel.Verbose, "No route found to {0}", destination, source.Key); - return false; - } - - // we have a route on corresponding inputPort. *** Do the route *** + if (goodInputPort == null) + { + Debug.LogMessage(LogEventLevel.Verbose, "No route found to {0}", destination, source.Key); + return false; + } - if (destination is IRoutingSink) - { - // it's a sink device - routeTable.Routes.Add(new RouteSwitchDescriptor(goodInputPort)); - } - else if (destination is IRouting) - { - routeTable.Routes.Add(new RouteSwitchDescriptor(outputPortToUse, goodInputPort)); - } - else // device is merely IRoutingInputOutputs - Debug.LogMessage(LogEventLevel.Verbose, "No routing. Passthrough device", destination); + // we have a route on corresponding inputPort. *** Do the route *** - return true; + if (destination is IRoutingSink) + { + // it's a sink device + routeTable.Routes.Add(new RouteSwitchDescriptor(goodInputPort)); + } + else if (destination is IRouting) + { + routeTable.Routes.Add(new RouteSwitchDescriptor(outputPortToUse, goodInputPort)); } + else // device is merely IRoutingInputOutputs + Debug.LogMessage(LogEventLevel.Verbose, "No routing. Passthrough device", destination); + + return true; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IHasCurrentSourceInfoChange.cs b/src/PepperDash.Essentials.Core/Routing/IHasCurrentSourceInfoChange.cs index 505a86524..055ac2e71 100644 --- a/src/PepperDash.Essentials.Core/Routing/IHasCurrentSourceInfoChange.cs +++ b/src/PepperDash.Essentials.Core/Routing/IHasCurrentSourceInfoChange.cs @@ -9,22 +9,21 @@ namespace PepperDash.Essentials.Core.Routing.Interfaces using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Core.Routing.Interfaces */ -namespace PepperDash.Essentials.Core -{ - /// - /// The handler type for a Room's SourceInfoChange - /// - public delegate void SourceInfoChangeHandler(SourceListItem info, ChangeType type); - //******************************************************************************************* - // Interfaces +namespace PepperDash.Essentials.Core; + +/// +/// The handler type for a Room's SourceInfoChange +/// +public delegate void SourceInfoChangeHandler(SourceListItem info, ChangeType type); +//******************************************************************************************* +// Interfaces - /// - /// For rooms with a single presentation source, change event - /// - public interface IHasCurrentSourceInfoChange - { - string CurrentSourceInfoKey { get; set; } - SourceListItem CurrentSourceInfo { get; set; } - event SourceInfoChangeHandler CurrentSourceChange; - } +/// +/// For rooms with a single presentation source, change event +/// +public interface IHasCurrentSourceInfoChange +{ + string CurrentSourceInfoKey { get; set; } + SourceListItem CurrentSourceInfo { get; set; } + event SourceInfoChangeHandler CurrentSourceChange; } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IInputSync.cs b/src/PepperDash.Essentials.Core/Routing/IInputSync.cs index accb70a7a..61218f277 100644 --- a/src/PepperDash.Essentials.Core/Routing/IInputSync.cs +++ b/src/PepperDash.Essentials.Core/Routing/IInputSync.cs @@ -5,12 +5,11 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core.Routing +namespace PepperDash.Essentials.Core.Routing; + +public interface IVideoSync : IKeyed { - public interface IVideoSync : IKeyed - { - bool VideoSyncDetected { get; } + bool VideoSyncDetected { get; } - event EventHandler VideoSyncChanged; - } + event EventHandler VideoSyncChanged; } diff --git a/src/PepperDash.Essentials.Core/Routing/IMatrixRouting.cs b/src/PepperDash.Essentials.Core/Routing/IMatrixRouting.cs index d7dc8c790..aad35e14f 100644 --- a/src/PepperDash.Essentials.Core/Routing/IMatrixRouting.cs +++ b/src/PepperDash.Essentials.Core/Routing/IMatrixRouting.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; -namespace PepperDash.Essentials.Core.Routing +namespace PepperDash.Essentials.Core.Routing; + +public interface IMatrixRouting { - public interface IMatrixRouting - { - Dictionary InputSlots { get; } - Dictionary OutputSlots { get; } + Dictionary InputSlots { get; } + Dictionary OutputSlots { get; } - void Route(string inputSlotKey, string outputSlotKey, eRoutingSignalType type); - } + void Route(string inputSlotKey, string outputSlotKey, eRoutingSignalType type); } diff --git a/src/PepperDash.Essentials.Core/Routing/IRmcRouting.cs b/src/PepperDash.Essentials.Core/Routing/IRmcRouting.cs index 52290bd26..38b3fa31b 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRmcRouting.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRmcRouting.cs @@ -1,10 +1,9 @@ -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Defines a receiver that has internal routing (DM-RMC-4K-Z-SCALER-C) +/// +public interface IRmcRouting : IRoutingNumeric { - /// - /// Defines a receiver that has internal routing (DM-RMC-4K-Z-SCALER-C) - /// - public interface IRmcRouting : IRoutingNumeric - { - IntFeedback AudioVideoSourceNumericFeedback { get; } - } + IntFeedback AudioVideoSourceNumericFeedback { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRmcRoutingWithFeedback.cs b/src/PepperDash.Essentials.Core/Routing/IRmcRoutingWithFeedback.cs index a8e6d5f08..660183c1a 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRmcRoutingWithFeedback.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRmcRoutingWithFeedback.cs @@ -1,9 +1,8 @@ -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Defines an IRmcRouting with a feedback event +/// +public interface IRmcRoutingWithFeedback : IRmcRouting { - /// - /// Defines an IRmcRouting with a feedback event - /// - public interface IRmcRoutingWithFeedback : IRmcRouting - { - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRouting.cs b/src/PepperDash.Essentials.Core/Routing/IRouting.cs index e3231858d..4856a9561 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRouting.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRouting.cs @@ -1,21 +1,20 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.Core -{ - /// - /// Defines a midpoint device as have internal routing. Any devices in the middle of the - /// signal chain, that do switching, must implement this for routing to work otherwise - /// the routing algorithm will treat the IRoutingInputsOutputs device as a passthrough - /// device. - /// - public interface IRouting : IRoutingInputsOutputs +namespace PepperDash.Essentials.Core; + +/// +/// Defines a midpoint device as have internal routing. Any devices in the middle of the +/// signal chain, that do switching, must implement this for routing to work otherwise +/// the routing algorithm will treat the IRoutingInputsOutputs device as a passthrough +/// device. +/// +public interface IRouting : IRoutingInputsOutputs { void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType); - } +} - /*public interface IRouting : IRoutingInputsOutputs - { - void ExecuteSwitch(TInputSelector inputSelector, TOutputSelector outputSelector, eRoutingSignalType signalType); - }*/ -} \ No newline at end of file +/*public interface IRouting : IRoutingInputsOutputs +{ + void ExecuteSwitch(TInputSelector inputSelector, TOutputSelector outputSelector, eRoutingSignalType signalType); +}*/ \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingFeedback.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingFeedback.cs index b8b22915c..651bb6a87 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingFeedback.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingFeedback.cs @@ -3,14 +3,13 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Defines an event structure for reporting output route data +/// +public interface IRoutingFeedback : IKeyName { - /// - /// Defines an event structure for reporting output route data - /// - public interface IRoutingFeedback : IKeyName - { - event EventHandler NumericSwitchChange; - //void OnSwitchChange(RoutingNumericEventArgs e); - } + event EventHandler NumericSwitchChange; + //void OnSwitchChange(RoutingNumericEventArgs e); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingHasVideoInputSyncFeedbacks.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingHasVideoInputSyncFeedbacks.cs index 0f6d7834c..8b3ac1578 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingHasVideoInputSyncFeedbacks.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingHasVideoInputSyncFeedbacks.cs @@ -9,11 +9,10 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public interface IRoutingHasVideoInputSyncFeedbacks { FeedbackCollection VideoInputSyncFeedbacks { get; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingInputSlot.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingInputSlot.cs index faee0fe97..a50062b5f 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingInputSlot.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingInputSlot.cs @@ -1,7 +1,6 @@ -namespace PepperDash.Essentials.Core.Routing +namespace PepperDash.Essentials.Core.Routing; + +public interface IRoutingInputSlot: IRoutingSlot, IOnline, IVideoSync { - public interface IRoutingInputSlot: IRoutingSlot, IOnline, IVideoSync - { - string TxDeviceKey { get; } - } + string TxDeviceKey { get; } } diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingInputs.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingInputs.cs index ff96fded0..129b198f9 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingInputs.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingInputs.cs @@ -1,18 +1,17 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ - /// - /// Defines a class that has a collection of RoutingInputPorts - /// - public interface IRoutingInputs : IKeyed +namespace PepperDash.Essentials.Core; + +/// +/// Defines a class that has a collection of RoutingInputPorts +/// +public interface IRoutingInputs : IKeyed { RoutingPortCollection InputPorts { get; } } /* public interface IRoutingInputs : IKeyed - { - RoutingPortCollection, TSelector> InputPorts { get; } - }*/ -} \ No newline at end of file +{ + RoutingPortCollection, TSelector> InputPorts { get; } +}*/ \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingInputsOutputs.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingInputsOutputs.cs index e202fa3c1..56cb92902 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingInputsOutputs.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingInputsOutputs.cs @@ -1,16 +1,15 @@ -namespace PepperDash.Essentials.Core -{ - /// - /// For devices like RMCs, baluns, other devices with no switching. - /// - public interface IRoutingInputsOutputs : IRoutingInputs, IRoutingOutputs +namespace PepperDash.Essentials.Core; + +/// +/// For devices like RMCs, baluns, other devices with no switching. +/// +public interface IRoutingInputsOutputs : IRoutingInputs, IRoutingOutputs { } /* /// - /// For devices like RMCs, baluns, other devices with no switching. - /// - public interface IRoutingInputsOutputs : IRoutingInputs, IRoutingOutputs - { - }*/ -} \ No newline at end of file +/// For devices like RMCs, baluns, other devices with no switching. +/// +public interface IRoutingInputsOutputs : IRoutingInputs, IRoutingOutputs +{ +}*/ \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingNumeric.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingNumeric.cs index d41909f1f..8788948e8 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingNumeric.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingNumeric.cs @@ -1,7 +1,6 @@ -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public interface IRoutingNumeric : IRouting { - public interface IRoutingNumeric : IRouting - { - void ExecuteNumericSwitch(ushort input, ushort output, eRoutingSignalType type); - } + void ExecuteNumericSwitch(ushort input, ushort output, eRoutingSignalType type); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingNumericWithFeedback.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingNumericWithFeedback.cs index e278a1936..a59e96992 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingNumericWithFeedback.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingNumericWithFeedback.cs @@ -1,9 +1,8 @@ -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Defines an IRoutingNumeric with a feedback event +/// +public interface IRoutingNumericWithFeedback : IRoutingNumeric, IRoutingFeedback { - /// - /// Defines an IRoutingNumeric with a feedback event - /// - public interface IRoutingNumericWithFeedback : IRoutingNumeric, IRoutingFeedback - { - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingOutputSlot.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingOutputSlot.cs index 478961cce..60587b8a0 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingOutputSlot.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingOutputSlot.cs @@ -1,14 +1,13 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.Core.Routing +namespace PepperDash.Essentials.Core.Routing; + +public interface IRoutingOutputSlot : IRoutingSlot { - public interface IRoutingOutputSlot : IRoutingSlot - { - event EventHandler OutputSlotChanged; + event EventHandler OutputSlotChanged; - string RxDeviceKey { get; } + string RxDeviceKey { get; } - Dictionary CurrentRoutes { get; } - } -} + Dictionary CurrentRoutes { get; } +} diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingOutputs.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingOutputs.cs index d3bc70de8..69bd0d68f 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingOutputs.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingOutputs.cs @@ -1,19 +1,18 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ - /// - /// Defines a class that has a collection of RoutingOutputPorts - /// +namespace PepperDash.Essentials.Core; + +/// +/// Defines a class that has a collection of RoutingOutputPorts +/// - public interface IRoutingOutputs : IKeyed +public interface IRoutingOutputs : IKeyed { RoutingPortCollection OutputPorts { get; } } /* public interface IRoutingOutputs : IKeyed - { - RoutingPortCollection, TSelector> OutputPorts { get; } - }*/ -} \ No newline at end of file +{ + RoutingPortCollection, TSelector> OutputPorts { get; } +}*/ \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingSink.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingSink.cs index b05c7744f..68e207a26 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingSink.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingSink.cs @@ -1,23 +1,22 @@ -namespace PepperDash.Essentials.Core -{ - /// - /// For fixed-source endpoint devices - /// - public interface IRoutingSink : IRoutingInputs, IHasCurrentSourceInfoChange - { - } +namespace PepperDash.Essentials.Core; + +/// +/// For fixed-source endpoint devices +/// +public interface IRoutingSink : IRoutingInputs, IHasCurrentSourceInfoChange +{ +} - public interface IRoutingSinkWithInputPort :IRoutingSink - { - RoutingInputPort CurrentInputPort { get; } - } - /*/// - /// For fixed-source endpoint devices - /// - public interface IRoutingSink : IRoutingInputs, IHasCurrentSourceInfoChange - { - void UpdateRouteRequest(RouteRequest request); +public interface IRoutingSinkWithInputPort :IRoutingSink +{ + RoutingInputPort CurrentInputPort { get; } +} +/*/// +/// For fixed-source endpoint devices +/// +public interface IRoutingSink : IRoutingInputs, IHasCurrentSourceInfoChange +{ + void UpdateRouteRequest(RouteRequest request); - RouteRequest GetRouteRequest(); - }*/ -} \ No newline at end of file + RouteRequest GetRouteRequest(); +}*/ \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingSinkWithFeedback.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingSinkWithFeedback.cs index d3d3e6009..f55b4f27a 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingSinkWithFeedback.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingSinkWithFeedback.cs @@ -2,24 +2,23 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + + +/// +/// For fixed-source endpoint devices +/// +public interface IRoutingSinkWithFeedback : IRoutingSinkWithSwitching { - /// - /// For fixed-source endpoint devices - /// - public interface IRoutingSinkWithFeedback : IRoutingSinkWithSwitching - { - - } +} /* /// - /// For fixed-source endpoint devices - /// - public interface IRoutingSinkWithFeedback : IRoutingSinkWithSwitching - { - RouteSwitchDescriptor CurrentRoute { get; } +/// For fixed-source endpoint devices +/// +public interface IRoutingSinkWithFeedback : IRoutingSinkWithSwitching +{ + RouteSwitchDescriptor CurrentRoute { get; } - event EventHandler InputChanged; - }*/ -} \ No newline at end of file + event EventHandler InputChanged; +}*/ \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingSinkWithSwitching.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingSinkWithSwitching.cs index d6f97c07a..010369a60 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingSinkWithSwitching.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingSinkWithSwitching.cs @@ -1,27 +1,26 @@ using System; -namespace PepperDash.Essentials.Core -{ - public delegate void InputChangedEventHandler(IRoutingSinkWithSwitching destination, RoutingInputPort currentPort); +namespace PepperDash.Essentials.Core; + +public delegate void InputChangedEventHandler(IRoutingSinkWithSwitching destination, RoutingInputPort currentPort); - /// - /// Endpoint device like a display, that selects inputs - /// - public interface IRoutingSinkWithSwitching : IRoutingSink +/// +/// Endpoint device like a display, that selects inputs +/// +public interface IRoutingSinkWithSwitching : IRoutingSink { void ExecuteSwitch(object inputSelector); - } +} - public interface IRoutingSinkWithSwitchingWithInputPort:IRoutingSinkWithSwitching, IRoutingSinkWithInputPort - { - event InputChangedEventHandler InputChanged; - } +public interface IRoutingSinkWithSwitchingWithInputPort:IRoutingSinkWithSwitching, IRoutingSinkWithInputPort +{ + event InputChangedEventHandler InputChanged; +} /* /// - /// Endpoint device like a display, that selects inputs - /// - public interface IRoutingSinkWithSwitching : IRoutingSink - { - void ExecuteSwitch(TSelector inputSelector); - }*/ -} \ No newline at end of file +/// Endpoint device like a display, that selects inputs +/// +public interface IRoutingSinkWithSwitching : IRoutingSink +{ + void ExecuteSwitch(TSelector inputSelector); +}*/ \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingSlot.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingSlot.cs index 7fabfb8bf..e3faf171e 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingSlot.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingSlot.cs @@ -5,12 +5,11 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Core.Routing +namespace PepperDash.Essentials.Core.Routing; + +public interface IRoutingSlot:IKeyName { - public interface IRoutingSlot:IKeyName - { - int SlotNumber { get; } + int SlotNumber { get; } - eRoutingSignalType SupportedSignalTypes { get; } - } + eRoutingSignalType SupportedSignalTypes { get; } } diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingSource.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingSource.cs index d3f61e72c..5eaaabf8e 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingSource.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingSource.cs @@ -1,9 +1,8 @@ -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Marker interface to identify a device that acts as the origin of a signal path (). +/// +public interface IRoutingSource : IRoutingOutputs { - /// - /// Marker interface to identify a device that acts as the origin of a signal path (). - /// - public interface IRoutingSource : IRoutingOutputs - { - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingWithClear.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingWithClear.cs index 407133efa..dc027db92 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingWithClear.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingWithClear.cs @@ -1,15 +1,14 @@ -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Defines a routing device () that supports explicitly clearing a route on an output. +/// +public interface IRoutingWithClear : IRouting { /// - /// Defines a routing device () that supports explicitly clearing a route on an output. + /// Clears a route to an output, however a device needs to do that /// - public interface IRoutingWithClear : IRouting - { - /// - /// Clears a route to an output, however a device needs to do that - /// - /// Output to clear - /// signal type to clear - void ClearRoute(object outputSelector, eRoutingSignalType signalType); - } + /// Output to clear + /// signal type to clear + void ClearRoute(object outputSelector, eRoutingSignalType signalType); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/IRoutingWithFeedback.cs b/src/PepperDash.Essentials.Core/Routing/IRoutingWithFeedback.cs index a328441a8..471e098c9 100644 --- a/src/PepperDash.Essentials.Core/Routing/IRoutingWithFeedback.cs +++ b/src/PepperDash.Essentials.Core/Routing/IRoutingWithFeedback.cs @@ -1,27 +1,26 @@ using System.Collections.Generic; using System; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Delegate for handling route change events on devices implementing . +/// +/// The routing device where the change occurred. +/// A descriptor of the new route that was established. +public delegate void RouteChangedEventHandler(IRoutingWithFeedback midpoint, RouteSwitchDescriptor newRoute); +/// +/// Defines a routing device () that provides feedback about its current routes. +/// +public interface IRoutingWithFeedback : IRouting { /// - /// Delegate for handling route change events on devices implementing . + /// Gets a list describing the currently active routes on this device. /// - /// The routing device where the change occurred. - /// A descriptor of the new route that was established. - public delegate void RouteChangedEventHandler(IRoutingWithFeedback midpoint, RouteSwitchDescriptor newRoute); + List CurrentRoutes { get; } + /// - /// Defines a routing device () that provides feedback about its current routes. + /// Event triggered when a route changes on this device. /// - public interface IRoutingWithFeedback : IRouting - { - /// - /// Gets a list describing the currently active routes on this device. - /// - List CurrentRoutes { get; } - - /// - /// Event triggered when a route changes on this device. - /// - event RouteChangedEventHandler RouteChanged; - } + event RouteChangedEventHandler RouteChanged; } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/ITxRouting.cs b/src/PepperDash.Essentials.Core/Routing/ITxRouting.cs index a157e8d10..679011171 100644 --- a/src/PepperDash.Essentials.Core/Routing/ITxRouting.cs +++ b/src/PepperDash.Essentials.Core/Routing/ITxRouting.cs @@ -1,18 +1,17 @@ -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Represents a routing device (typically a transmitter or source) that provides numeric feedback for its current route. +/// Extends . +/// +public interface ITxRouting : IRoutingNumeric { /// - /// Represents a routing device (typically a transmitter or source) that provides numeric feedback for its current route. - /// Extends . + /// Feedback indicating the currently routed video source by its numeric identifier. /// - public interface ITxRouting : IRoutingNumeric - { - /// - /// Feedback indicating the currently routed video source by its numeric identifier. - /// - IntFeedback VideoSourceNumericFeedback { get; } - /// - /// Feedback indicating the currently routed audio source by its numeric identifier. - /// - IntFeedback AudioSourceNumericFeedback { get; } - } + IntFeedback VideoSourceNumericFeedback { get; } + /// + /// Feedback indicating the currently routed audio source by its numeric identifier. + /// + IntFeedback AudioSourceNumericFeedback { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/ITxRoutingWithFeedback.cs b/src/PepperDash.Essentials.Core/Routing/ITxRoutingWithFeedback.cs index 484fa1344..0ba49439d 100644 --- a/src/PepperDash.Essentials.Core/Routing/ITxRoutingWithFeedback.cs +++ b/src/PepperDash.Essentials.Core/Routing/ITxRoutingWithFeedback.cs @@ -1,9 +1,8 @@ -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Defines an IRmcRouting with a feedback event +/// +public interface ITxRoutingWithFeedback : ITxRouting { - /// - /// Defines an IRmcRouting with a feedback event - /// - public interface ITxRoutingWithFeedback : ITxRouting - { - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/RouteDescriptor.cs b/src/PepperDash.Essentials.Core/Routing/RouteDescriptor.cs index e02dd30ed..c69285dd5 100644 --- a/src/PepperDash.Essentials.Core/Routing/RouteDescriptor.cs +++ b/src/PepperDash.Essentials.Core/Routing/RouteDescriptor.cs @@ -7,209 +7,208 @@ using Serilog.Events; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Represents a collection of individual route steps between a Source and a Destination device for a specific signal type. +/// +public class RouteDescriptor { /// - /// Represents a collection of individual route steps between a Source and a Destination device for a specific signal type. + /// The destination device (sink or midpoint) for the route. + /// + public IRoutingInputs Destination { get; private set; } + + /// + /// The specific input port on the destination device used for this route. Can be null if not specified or applicable. + /// + public RoutingInputPort InputPort { get; private set; } + + /// + /// The source device for the route. + /// + public IRoutingOutputs Source { get; private set; } + + /// + /// The type of signal being routed (e.g., Audio, Video). This descriptor represents a single signal type. /// - public class RouteDescriptor + public eRoutingSignalType SignalType { get; private set; } + + /// + /// A list of individual switching steps required to establish the route. + /// + public List Routes { get; private set; } + + /// + /// Initializes a new instance of the class for a route without a specific destination input port. + /// + /// The source device. + /// The destination device. + /// The type of signal being routed. + public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType) : this(source, destination, null, signalType) { - /// - /// The destination device (sink or midpoint) for the route. - /// - public IRoutingInputs Destination { get; private set; } - - /// - /// The specific input port on the destination device used for this route. Can be null if not specified or applicable. - /// - public RoutingInputPort InputPort { get; private set; } - - /// - /// The source device for the route. - /// - public IRoutingOutputs Source { get; private set; } - - /// - /// The type of signal being routed (e.g., Audio, Video). This descriptor represents a single signal type. - /// - public eRoutingSignalType SignalType { get; private set; } - - /// - /// A list of individual switching steps required to establish the route. - /// - public List Routes { get; private set; } - - /// - /// Initializes a new instance of the class for a route without a specific destination input port. - /// - /// The source device. - /// The destination device. - /// The type of signal being routed. - public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType) : this(source, destination, null, signalType) - { - } + } - /// - /// Initializes a new instance of the class for a route with a specific destination input port. - /// - /// The source device. - /// The destination device. - /// The destination input port (optional). - /// The signal type for this route. - public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, RoutingInputPort inputPort, eRoutingSignalType signalType) - { - Destination = destination; - InputPort = inputPort; - Source = source; - SignalType = signalType; - Routes = new List(); - } + /// + /// Initializes a new instance of the class for a route with a specific destination input port. + /// + /// The source device. + /// The destination device. + /// The destination input port (optional). + /// The signal type for this route. + public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, RoutingInputPort inputPort, eRoutingSignalType signalType) + { + Destination = destination; + InputPort = inputPort; + Source = source; + SignalType = signalType; + Routes = new List(); + } - /// - /// Executes all the switching steps defined in the list. - /// - public void ExecuteRoutes() + /// + /// Executes all the switching steps defined in the list. + /// + public void ExecuteRoutes() + { + foreach (var route in Routes) { - foreach (var route in Routes) - { - Debug.LogMessage(LogEventLevel.Verbose, "ExecuteRoutes: {0}", null, route.ToString()); + Debug.LogMessage(LogEventLevel.Verbose, "ExecuteRoutes: {0}", null, route.ToString()); - if (route.SwitchingDevice is IRoutingSinkWithSwitching sink) - { - sink.ExecuteSwitch(route.InputPort.Selector); - continue; - } + if (route.SwitchingDevice is IRoutingSinkWithSwitching sink) + { + sink.ExecuteSwitch(route.InputPort.Selector); + continue; + } - if (route.SwitchingDevice is IRouting switchingDevice) - { - switchingDevice.ExecuteSwitch(route.InputPort.Selector, route.OutputPort.Selector, SignalType); + if (route.SwitchingDevice is IRouting switchingDevice) + { + switchingDevice.ExecuteSwitch(route.InputPort.Selector, route.OutputPort.Selector, SignalType); - route.OutputPort.InUseTracker.AddUser(Destination, "destination-" + SignalType); + route.OutputPort.InUseTracker.AddUser(Destination, "destination-" + SignalType); - Debug.LogMessage(LogEventLevel.Verbose, "Output port {0} routing. Count={1}", null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue); - } + Debug.LogMessage(LogEventLevel.Verbose, "Output port {0} routing. Count={1}", null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue); } } + } - /// - /// Releases the usage tracking for the route and optionally clears the route on the switching devices. - /// - /// If true, attempts to clear the route on the switching devices (e.g., set input to null/0). - public void ReleaseRoutes(bool clearRoute = false) + /// + /// Releases the usage tracking for the route and optionally clears the route on the switching devices. + /// + /// If true, attempts to clear the route on the switching devices (e.g., set input to null/0). + public void ReleaseRoutes(bool clearRoute = false) + { + foreach (var route in Routes.Where(r => r.SwitchingDevice is IRouting)) { - foreach (var route in Routes.Where(r => r.SwitchingDevice is IRouting)) + if (route.SwitchingDevice is IRouting switchingDevice) { - if (route.SwitchingDevice is IRouting switchingDevice) + if(clearRoute) { - if(clearRoute) + try { - try - { - switchingDevice.ExecuteSwitch(null, route.OutputPort.Selector, SignalType); - } - catch (Exception e) - { - Debug.LogError("Error executing switch: {exception}", e.Message); - } + switchingDevice.ExecuteSwitch(null, route.OutputPort.Selector, SignalType); } - - if (route.OutputPort == null) + catch (Exception e) { - continue; + Debug.LogError("Error executing switch: {exception}", e.Message); } + } - if (route.OutputPort.InUseTracker != null) - { - route.OutputPort.InUseTracker.RemoveUser(Destination, "destination-" + SignalType); - Debug.LogMessage(LogEventLevel.Verbose, "Port {0} releasing. Count={1}", null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue); - } - else - { - Debug.LogMessage(LogEventLevel.Error, "InUseTracker is null for OutputPort {0}", null, route.OutputPort.Key); - } + if (route.OutputPort == null) + { + continue; } - } - } - /// - /// Returns a string representation of the route descriptor, including source, destination, and individual route steps. - /// - /// A string describing the route. - public override string ToString() - { - var routesText = Routes.Select(r => r.ToString()).ToArray(); - return string.Format("Route table from {0} to {1}:\r{2}", Source.Key, Destination.Key, string.Join("\r", routesText)); + if (route.OutputPort.InUseTracker != null) + { + route.OutputPort.InUseTracker.RemoveUser(Destination, "destination-" + SignalType); + Debug.LogMessage(LogEventLevel.Verbose, "Port {0} releasing. Count={1}", null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue); + } + else + { + Debug.LogMessage(LogEventLevel.Error, "InUseTracker is null for OutputPort {0}", null, route.OutputPort.Key); + } + } } } - /*/// - /// Represents an collection of individual route steps between Source and Destination + /// + /// Returns a string representation of the route descriptor, including source, destination, and individual route steps. /// - public class RouteDescriptor + /// A string describing the route. + public override string ToString() { - public IRoutingInputs Destination { get; private set; } - public IRoutingOutputs Source { get; private set; } - public eRoutingSignalType SignalType { get; private set; } - public List> Routes { get; private set; } + var routesText = Routes.Select(r => r.ToString()).ToArray(); + return string.Format("Route table from {0} to {1}:\r{2}", Source.Key, Destination.Key, string.Join("\r", routesText)); + } +} +/*/// +/// Represents an collection of individual route steps between Source and Destination +/// +public class RouteDescriptor +{ + public IRoutingInputs Destination { get; private set; } + public IRoutingOutputs Source { get; private set; } + public eRoutingSignalType SignalType { get; private set; } + public List> Routes { get; private set; } - public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType) - { - Destination = destination; - Source = source; - SignalType = signalType; - Routes = new List>(); - } - /// - /// Executes all routes described in this collection. Typically called via - /// extension method IRoutingInputs.ReleaseAndMakeRoute() - /// - public void ExecuteRoutes() + public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType) + { + Destination = destination; + Source = source; + SignalType = signalType; + Routes = new List>(); + } + + /// + /// Executes all routes described in this collection. Typically called via + /// extension method IRoutingInputs.ReleaseAndMakeRoute() + /// + public void ExecuteRoutes() + { + foreach (var route in Routes) { - foreach (var route in Routes) - { - Debug.LogMessage(LogEventLevel.Verbose, "ExecuteRoutes: {0}", null, route.ToString()); + Debug.LogMessage(LogEventLevel.Verbose, "ExecuteRoutes: {0}", null, route.ToString()); - if (route.SwitchingDevice is IRoutingSinkWithSwitching sink) - { - sink.ExecuteSwitch(route.InputPort.Selector); - continue; - } + if (route.SwitchingDevice is IRoutingSinkWithSwitching sink) + { + sink.ExecuteSwitch(route.InputPort.Selector); + continue; + } - if (route.SwitchingDevice is IRouting switchingDevice) - { - switchingDevice.ExecuteSwitch(route.InputPort.Selector, route.OutputPort.Selector, SignalType); + if (route.SwitchingDevice is IRouting switchingDevice) + { + switchingDevice.ExecuteSwitch(route.InputPort.Selector, route.OutputPort.Selector, SignalType); - route.OutputPort.InUseTracker.AddUser(Destination, "destination-" + SignalType); + route.OutputPort.InUseTracker.AddUser(Destination, "destination-" + SignalType); - Debug.LogMessage(LogEventLevel.Verbose, "Output port {0} routing. Count={1}", null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue); - } + Debug.LogMessage(LogEventLevel.Verbose, "Output port {0} routing. Count={1}", null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue); } } + } - /// - /// Releases all routes in this collection. Typically called via - /// extension method IRoutingInputs.ReleaseAndMakeRoute() - /// - public void ReleaseRoutes() + /// + /// Releases all routes in this collection. Typically called via + /// extension method IRoutingInputs.ReleaseAndMakeRoute() + /// + public void ReleaseRoutes() + { + foreach (var route in Routes) { - foreach (var route in Routes) + if (route.SwitchingDevice is IRouting) { - if (route.SwitchingDevice is IRouting) - { - // Pull the route from the port. Whatever is watching the output's in use tracker is - // responsible for responding appropriately. - route.OutputPort.InUseTracker.RemoveUser(Destination, "destination-" + SignalType); - Debug.LogMessage(LogEventLevel.Verbose, "Port {0} releasing. Count={1}", null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue); - } + // Pull the route from the port. Whatever is watching the output's in use tracker is + // responsible for responding appropriately. + route.OutputPort.InUseTracker.RemoveUser(Destination, "destination-" + SignalType); + Debug.LogMessage(LogEventLevel.Verbose, "Port {0} releasing. Count={1}", null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue); } } + } - public override string ToString() - { - var routesText = Routes.Select(r => r.ToString()).ToArray(); - return string.Format("Route table from {0} to {1}:\r{2}", Source.Key, Destination.Key, string.Join("\r", routesText)); - } - }*/ -} \ No newline at end of file + public override string ToString() + { + var routesText = Routes.Select(r => r.ToString()).ToArray(); + return string.Format("Route table from {0} to {1}:\r{2}", Source.Key, Destination.Key, string.Join("\r", routesText)); + } +}*/ \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/RouteDescriptorCollection.cs b/src/PepperDash.Essentials.Core/Routing/RouteDescriptorCollection.cs index 9bafc1285..617d99f15 100644 --- a/src/PepperDash.Essentials.Core/Routing/RouteDescriptorCollection.cs +++ b/src/PepperDash.Essentials.Core/Routing/RouteDescriptorCollection.cs @@ -4,90 +4,90 @@ using System.Linq; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// A collection of RouteDescriptors - typically the static DefaultCollection is used +/// +public class RouteDescriptorCollection { - /// - /// A collection of RouteDescriptors - typically the static DefaultCollection is used - /// - public class RouteDescriptorCollection + public static RouteDescriptorCollection DefaultCollection { - public static RouteDescriptorCollection DefaultCollection + get { - get - { - if (_DefaultCollection == null) - _DefaultCollection = new RouteDescriptorCollection(); - return _DefaultCollection; - } + if (_DefaultCollection == null) + _DefaultCollection = new RouteDescriptorCollection(); + return _DefaultCollection; } - private static RouteDescriptorCollection _DefaultCollection; + } + private static RouteDescriptorCollection _DefaultCollection; - private readonly List RouteDescriptors = new List(); + private readonly List RouteDescriptors = new List(); - /// - /// Adds a RouteDescriptor to the list. If an existing RouteDescriptor for the - /// destination exists already, it will not be added - in order to preserve - /// proper route releasing. - /// - /// - public void AddRouteDescriptor(RouteDescriptor descriptor) + /// + /// Adds a RouteDescriptor to the list. If an existing RouteDescriptor for the + /// destination exists already, it will not be added - in order to preserve + /// proper route releasing. + /// + /// + public void AddRouteDescriptor(RouteDescriptor descriptor) + { + if (descriptor == null) { - if (descriptor == null) - { - return; - } - - if (RouteDescriptors.Any(t => t.Destination == descriptor.Destination) - && RouteDescriptors.Any(t => t.Destination == descriptor.Destination && t.InputPort != null && descriptor.InputPort != null && t.InputPort.Key == descriptor.InputPort.Key)) - { - Debug.LogMessage(LogEventLevel.Debug, descriptor.Destination, - "Route to [{0}] already exists in global routes table", descriptor?.Source?.Key); - return; - } - RouteDescriptors.Add(descriptor); + return; } - /// - /// Gets the RouteDescriptor for a destination - /// - /// null if no RouteDescriptor for a destination exists - public RouteDescriptor GetRouteDescriptorForDestination(IRoutingInputs destination) + if (RouteDescriptors.Any(t => t.Destination == descriptor.Destination) + && RouteDescriptors.Any(t => t.Destination == descriptor.Destination && t.InputPort != null && descriptor.InputPort != null && t.InputPort.Key == descriptor.InputPort.Key)) { - Debug.LogMessage(LogEventLevel.Information, "Getting route descriptor for '{destination}'", destination?.Key ?? null); - - return RouteDescriptors.FirstOrDefault(rd => rd.Destination == destination); + Debug.LogMessage(LogEventLevel.Debug, descriptor.Destination, + "Route to [{0}] already exists in global routes table", descriptor?.Source?.Key); + return; } + RouteDescriptors.Add(descriptor); + } - public RouteDescriptor GetRouteDescriptorForDestinationAndInputPort(IRoutingInputs destination, string inputPortKey) - { - Debug.LogMessage(LogEventLevel.Information, "Getting route descriptor for '{destination}':'{inputPortKey}'", destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey); - return RouteDescriptors.FirstOrDefault(rd => rd.Destination == destination && rd.InputPort != null && rd.InputPort.Key == inputPortKey); - } + /// + /// Gets the RouteDescriptor for a destination + /// + /// null if no RouteDescriptor for a destination exists + public RouteDescriptor GetRouteDescriptorForDestination(IRoutingInputs destination) + { + Debug.LogMessage(LogEventLevel.Information, "Getting route descriptor for '{destination}'", destination?.Key ?? null); - /// - /// Returns the RouteDescriptor for a given destination AND removes it from collection. - /// Returns null if no route with the provided destination exists. - /// - public RouteDescriptor RemoveRouteDescriptor(IRoutingInputs destination, string inputPortKey = "") - { - Debug.LogMessage(LogEventLevel.Information, "Removing route descriptor for '{destination}':'{inputPortKey}'", destination.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey); + return RouteDescriptors.FirstOrDefault(rd => rd.Destination == destination); + } + + public RouteDescriptor GetRouteDescriptorForDestinationAndInputPort(IRoutingInputs destination, string inputPortKey) + { + Debug.LogMessage(LogEventLevel.Information, "Getting route descriptor for '{destination}':'{inputPortKey}'", destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey); + return RouteDescriptors.FirstOrDefault(rd => rd.Destination == destination && rd.InputPort != null && rd.InputPort.Key == inputPortKey); + } - var descr = string.IsNullOrEmpty(inputPortKey) - ? GetRouteDescriptorForDestination(destination) - : GetRouteDescriptorForDestinationAndInputPort(destination, inputPortKey); - if (descr != null) - RouteDescriptors.Remove(descr); + /// + /// Returns the RouteDescriptor for a given destination AND removes it from collection. + /// Returns null if no route with the provided destination exists. + /// + public RouteDescriptor RemoveRouteDescriptor(IRoutingInputs destination, string inputPortKey = "") + { + Debug.LogMessage(LogEventLevel.Information, "Removing route descriptor for '{destination}':'{inputPortKey}'", destination.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey); - Debug.LogMessage(LogEventLevel.Information, "Found route descriptor {routeDescriptor}", destination, descr); + var descr = string.IsNullOrEmpty(inputPortKey) + ? GetRouteDescriptorForDestination(destination) + : GetRouteDescriptorForDestinationAndInputPort(destination, inputPortKey); + if (descr != null) + RouteDescriptors.Remove(descr); - return descr; - } + Debug.LogMessage(LogEventLevel.Information, "Found route descriptor {routeDescriptor}", destination, descr); + + return descr; } +} - /*/// - /// A collection of RouteDescriptors - typically the static DefaultCollection is used - /// - public class RouteDescriptorCollection +/*/// +/// A collection of RouteDescriptors - typically the static DefaultCollection is used +/// +public class RouteDescriptorCollection { public static RouteDescriptorCollection DefaultCollection { @@ -139,5 +139,4 @@ public RouteDescriptor RemoveRouteDescriptor(IRoutingInputs dest RouteDescriptors.Remove(descr); return descr; } - }*/ -} \ No newline at end of file + }*/ \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/RouteRequest.cs b/src/PepperDash.Essentials.Core/Routing/RouteRequest.cs index a8bdf015d..087522578 100644 --- a/src/PepperDash.Essentials.Core/Routing/RouteRequest.cs +++ b/src/PepperDash.Essentials.Core/Routing/RouteRequest.cs @@ -2,77 +2,76 @@ using Serilog.Events; using System; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Represents a request to establish a route between a source and a destination device. +/// +public class RouteRequest { /// - /// Represents a request to establish a route between a source and a destination device. + /// The specific input port on the destination device to use for the route. Can be null if the port should be automatically determined or is not applicable. /// - public class RouteRequest - { - /// - /// The specific input port on the destination device to use for the route. Can be null if the port should be automatically determined or is not applicable. - /// - public RoutingInputPort DestinationPort { get; set; } + public RoutingInputPort DestinationPort { get; set; } - /// - /// The specific output port on the source device to use for the route. Can be null if the port should be automatically determined or is not applicable. - /// - public RoutingOutputPort SourcePort { get; set; } + /// + /// The specific output port on the source device to use for the route. Can be null if the port should be automatically determined or is not applicable. + /// + public RoutingOutputPort SourcePort { get; set; } - /// - /// The destination device (sink or midpoint) for the route. - /// - public IRoutingInputs Destination { get; set; } + /// + /// The destination device (sink or midpoint) for the route. + /// + public IRoutingInputs Destination { get; set; } - /// - /// The source device for the route. - /// - public IRoutingOutputs Source { get; set; } + /// + /// The source device for the route. + /// + public IRoutingOutputs Source { get; set; } - /// - /// The type of signal being routed (e.g., Audio, Video, AudioVideo). - /// - public eRoutingSignalType SignalType { get; set; } + /// + /// The type of signal being routed (e.g., Audio, Video, AudioVideo). + /// + public eRoutingSignalType SignalType { get; set; } - /// - /// Handles the route request after a device's cooldown period has finished. - /// This method is typically subscribed to the IsCoolingDownFeedback.OutputChange event. - /// - /// The object that triggered the event (usually the cooling device). - /// Event arguments indicating the cooldown state change. - public void HandleCooldown(object sender, FeedbackEventArgs args) + /// + /// Handles the route request after a device's cooldown period has finished. + /// This method is typically subscribed to the IsCoolingDownFeedback.OutputChange event. + /// + /// The object that triggered the event (usually the cooling device). + /// Event arguments indicating the cooldown state change. + public void HandleCooldown(object sender, FeedbackEventArgs args) + { + try { - try - { - Debug.LogMessage(LogEventLevel.Information, "Handling cooldown route request: {destination}:{destinationPort} -> {source}:{sourcePort} {type}", null, Destination?.Key ?? "empty destination", DestinationPort?.Key ?? "no destination port", Source?.Key ?? "empty source", SourcePort?.Key ?? "empty source port", SignalType.ToString()); + Debug.LogMessage(LogEventLevel.Information, "Handling cooldown route request: {destination}:{destinationPort} -> {source}:{sourcePort} {type}", null, Destination?.Key ?? "empty destination", DestinationPort?.Key ?? "no destination port", Source?.Key ?? "empty source", SourcePort?.Key ?? "empty source port", SignalType.ToString()); - if (args.BoolValue == true) - { - return; - } + if (args.BoolValue == true) + { + return; + } - Debug.LogMessage(LogEventLevel.Information, "Cooldown complete. Making route from {destination} to {source}", Destination?.Key, Source?.Key); + Debug.LogMessage(LogEventLevel.Information, "Cooldown complete. Making route from {destination} to {source}", Destination?.Key, Source?.Key); - Destination.ReleaseAndMakeRoute(Source, SignalType, DestinationPort?.Key ?? string.Empty, SourcePort?.Key ?? string.Empty); + Destination.ReleaseAndMakeRoute(Source, SignalType, DestinationPort?.Key ?? string.Empty, SourcePort?.Key ?? string.Empty); - if (sender is IWarmingCooling coolingDevice) - { - Debug.LogMessage(LogEventLevel.Debug, "Unsubscribing from cooling feedback for {destination}", null, Destination.Key); - coolingDevice.IsCoolingDownFeedback.OutputChange -= HandleCooldown; - } - } catch(Exception ex) + if (sender is IWarmingCooling coolingDevice) { - Debug.LogMessage(ex, "Exception handling cooldown", Destination); + Debug.LogMessage(LogEventLevel.Debug, "Unsubscribing from cooling feedback for {destination}", null, Destination.Key); + coolingDevice.IsCoolingDownFeedback.OutputChange -= HandleCooldown; } - } - - /// - /// Returns a string representation of the route request. - /// - /// A string describing the source and destination of the route request. - public override string ToString() + } catch(Exception ex) { - return $"Route {Source?.Key ?? "No Source Device"}:{SourcePort?.Key ?? "auto"} to {Destination?.Key ?? "No Destination Device"}:{DestinationPort?.Key ?? "auto"}"; + Debug.LogMessage(ex, "Exception handling cooldown", Destination); } } + + /// + /// Returns a string representation of the route request. + /// + /// A string describing the source and destination of the route request. + public override string ToString() + { + return $"Route {Source?.Key ?? "No Source Device"}:{SourcePort?.Key ?? "auto"} to {Destination?.Key ?? "No Destination Device"}:{DestinationPort?.Key ?? "auto"}"; + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/RouteRequestQueueItem.cs b/src/PepperDash.Essentials.Core/Routing/RouteRequestQueueItem.cs index 07b52c2c7..1f7ab4861 100644 --- a/src/PepperDash.Essentials.Core/Routing/RouteRequestQueueItem.cs +++ b/src/PepperDash.Essentials.Core/Routing/RouteRequestQueueItem.cs @@ -3,87 +3,86 @@ using System; using Serilog.Events; -namespace PepperDash.Essentials.Core.Routing +namespace PepperDash.Essentials.Core.Routing; + +/// +/// Represents an item in the route request queue. +/// +public class RouteRequestQueueItem : IQueueMessage { /// - /// Represents an item in the route request queue. + /// The action to perform for the route request. /// - public class RouteRequestQueueItem : IQueueMessage - { - /// - /// The action to perform for the route request. - /// - private readonly Action action; - /// - /// The route request data. - /// - private readonly RouteRequest routeRequest; - - /// - /// Initializes a new instance of the class. - /// - /// The action to perform. - /// The route request data. - public RouteRequestQueueItem(Action routeAction, RouteRequest request) - { - action = routeAction; - routeRequest = request; - } + private readonly Action action; + /// + /// The route request data. + /// + private readonly RouteRequest routeRequest; - /// - /// Dispatches the route request action. - /// - public void Dispatch() - { - Debug.LogMessage(LogEventLevel.Information, "Dispatching route request {routeRequest}", null, routeRequest); - action(routeRequest); - } + /// + /// Initializes a new instance of the class. + /// + /// The action to perform. + /// The route request data. + public RouteRequestQueueItem(Action routeAction, RouteRequest request) + { + action = routeAction; + routeRequest = request; } /// - /// Represents an item in the queue for releasing a route. + /// Dispatches the route request action. /// - public class ReleaseRouteQueueItem : IQueueMessage + public void Dispatch() { - /// - /// The action to perform for releasing the route. - /// - private readonly Action action; - /// - /// The destination device whose route is being released. - /// - private readonly IRoutingInputs destination; - /// - /// The specific input port key on the destination to release, or null/empty for any/default. - /// - private readonly string inputPortKey; - /// - /// Indicates whether to clear the route (send null) or just release the usage tracking. - /// - private readonly bool clearRoute; + Debug.LogMessage(LogEventLevel.Information, "Dispatching route request {routeRequest}", null, routeRequest); + action(routeRequest); + } +} - /// - /// Initializes a new instance of the class. - /// - /// The action to perform. - /// The destination device. - /// The input port key. - /// True to clear the route, false to just release. - public ReleaseRouteQueueItem(Action action, IRoutingInputs destination, string inputPortKey, bool clearRoute) - { - this.action = action; - this.destination = destination; - this.inputPortKey = inputPortKey; - this.clearRoute = clearRoute; - } +/// +/// Represents an item in the queue for releasing a route. +/// +public class ReleaseRouteQueueItem : IQueueMessage +{ + /// + /// The action to perform for releasing the route. + /// + private readonly Action action; + /// + /// The destination device whose route is being released. + /// + private readonly IRoutingInputs destination; + /// + /// The specific input port key on the destination to release, or null/empty for any/default. + /// + private readonly string inputPortKey; + /// + /// Indicates whether to clear the route (send null) or just release the usage tracking. + /// + private readonly bool clearRoute; - /// - /// Dispatches the release route action. - /// - public void Dispatch() - { - Debug.LogMessage(LogEventLevel.Information, "Dispatching release route request for {destination}:{inputPortKey}", null, destination?.Key ?? "no destination", string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey); - action(destination, inputPortKey, clearRoute); - } + /// + /// Initializes a new instance of the class. + /// + /// The action to perform. + /// The destination device. + /// The input port key. + /// True to clear the route, false to just release. + public ReleaseRouteQueueItem(Action action, IRoutingInputs destination, string inputPortKey, bool clearRoute) + { + this.action = action; + this.destination = destination; + this.inputPortKey = inputPortKey; + this.clearRoute = clearRoute; + } + + /// + /// Dispatches the release route action. + /// + public void Dispatch() + { + Debug.LogMessage(LogEventLevel.Information, "Dispatching release route request for {destination}:{inputPortKey}", null, destination?.Key ?? "no destination", string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey); + action(destination, inputPortKey, clearRoute); } } diff --git a/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs b/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs index 6394a3bc8..204308524 100644 --- a/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs +++ b/src/PepperDash.Essentials.Core/Routing/RouteSwitchDescriptor.cs @@ -1,9 +1,9 @@ -namespace PepperDash.Essentials.Core -{ - /// - /// Represents a single switching step within a larger route, detailing the switching device, input port, and optionally the output port. - /// - public class RouteSwitchDescriptor +namespace PepperDash.Essentials.Core; + +/// +/// Represents a single switching step within a larger route, detailing the switching device, input port, and optionally the output port. +/// +public class RouteSwitchDescriptor { /// /// The device performing the switch (derived from the InputPort's parent). @@ -44,39 +44,38 @@ public RouteSwitchDescriptor(RoutingOutputPort outputPort, RoutingInputPort inpu /// A string describing the switch operation. public override string ToString() { - if (SwitchingDevice is IRouting) - return $"{(SwitchingDevice != null ? SwitchingDevice.Key : "No Device")} switches output {(OutputPort != null ? OutputPort.Key : "No output port")} to input {(InputPort != null ? InputPort.Key : "No input port")}"; - else - return $"{(SwitchingDevice != null ? SwitchingDevice.Key : "No Device")} switches to input {(InputPort != null ? InputPort.Key : "No input port")}"; + if (SwitchingDevice is IRouting) + return $"{(SwitchingDevice != null ? SwitchingDevice.Key : "No Device")} switches output {(OutputPort != null ? OutputPort.Key : "No output port")} to input {(InputPort != null ? InputPort.Key : "No input port")}"; + else + return $"{(SwitchingDevice != null ? SwitchingDevice.Key : "No Device")} switches to input {(InputPort != null ? InputPort.Key : "No input port")}"; } } - /*/// - /// Represents an individual link for a route - /// - public class RouteSwitchDescriptor - { - public IRoutingInputs SwitchingDevice { get { return InputPort.ParentDevice; } } - public RoutingOutputPort OutputPort { get; set; } - public RoutingInputPort InputPort { get; set; } +/*/// +/// Represents an individual link for a route +/// +public class RouteSwitchDescriptor +{ + public IRoutingInputs SwitchingDevice { get { return InputPort.ParentDevice; } } + public RoutingOutputPort OutputPort { get; set; } + public RoutingInputPort InputPort { get; set; } - public RouteSwitchDescriptor(RoutingInputPort inputPort) - { - InputPort = inputPort; - } + public RouteSwitchDescriptor(RoutingInputPort inputPort) + { + InputPort = inputPort; + } - public RouteSwitchDescriptor(RoutingOutputPort outputPort, RoutingInputPort inputPort) - { - InputPort = inputPort; - OutputPort = outputPort; - } + public RouteSwitchDescriptor(RoutingOutputPort outputPort, RoutingInputPort inputPort) + { + InputPort = inputPort; + OutputPort = outputPort; + } - public override string ToString() - { - if (SwitchingDevice is IRouting) - return string.Format("{0} switches output '{1}' to input '{2}'", SwitchingDevice.Key, OutputPort.Selector, InputPort.Selector); - else - return string.Format("{0} switches to input '{1}'", SwitchingDevice.Key, InputPort.Selector); - } - }*/ -} \ No newline at end of file + public override string ToString() + { + if (SwitchingDevice is IRouting) + return string.Format("{0} switches output '{1}' to input '{2}'", SwitchingDevice.Key, OutputPort.Selector, InputPort.Selector); + else + return string.Format("{0} switches to input '{1}'", SwitchingDevice.Key, InputPort.Selector); + } +}*/ \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs b/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs index 9afdb33d3..8211f3e65 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingFeedbackManager.cs @@ -3,308 +3,307 @@ using System; using System.Linq; -namespace PepperDash.Essentials.Core.Routing +namespace PepperDash.Essentials.Core.Routing; + +/// +/// Manages routing feedback by subscribing to route changes on midpoint and sink devices, +/// tracing the route back to the original source, and updating the CurrentSourceInfo on sink devices. +/// +public class RoutingFeedbackManager:EssentialsDevice { /// - /// Manages routing feedback by subscribing to route changes on midpoint and sink devices, - /// tracing the route back to the original source, and updating the CurrentSourceInfo on sink devices. + /// Initializes a new instance of the class. + /// + /// The unique key for this manager device. + /// The name of this manager device. + public RoutingFeedbackManager(string key, string name): base(key, name) + { + AddPreActivationAction(SubscribeForMidpointFeedback); + AddPreActivationAction(SubscribeForSinkFeedback); + } + + + /// + /// Subscribes to the RouteChanged event on all devices implementing . /// - public class RoutingFeedbackManager:EssentialsDevice + private void SubscribeForMidpointFeedback() { - /// - /// Initializes a new instance of the class. - /// - /// The unique key for this manager device. - /// The name of this manager device. - public RoutingFeedbackManager(string key, string name): base(key, name) - { - AddPreActivationAction(SubscribeForMidpointFeedback); - AddPreActivationAction(SubscribeForSinkFeedback); + var midpointDevices = DeviceManager.AllDevices.OfType(); + + foreach (var device in midpointDevices) + { + device.RouteChanged += HandleMidpointUpdate; } + } + /// + /// Subscribes to the InputChanged event on all devices implementing . + /// + private void SubscribeForSinkFeedback() + { + var sinkDevices = DeviceManager.AllDevices.OfType(); + + foreach (var device in sinkDevices) + { + device.InputChanged += HandleSinkUpdate; + } + } - /// - /// Subscribes to the RouteChanged event on all devices implementing . - /// - private void SubscribeForMidpointFeedback() + /// + /// Handles the RouteChanged event from a midpoint device. + /// Triggers an update for all sink devices. + /// + /// The midpoint device that reported a route change. + /// The descriptor of the new route. + private void HandleMidpointUpdate(IRoutingWithFeedback midpoint, RouteSwitchDescriptor newRoute) + { + try { - var midpointDevices = DeviceManager.AllDevices.OfType(); + var devices = DeviceManager.AllDevices.OfType(); - foreach (var device in midpointDevices) + foreach (var device in devices) { - device.RouteChanged += HandleMidpointUpdate; + UpdateDestination(device, device.CurrentInputPort); } } - - /// - /// Subscribes to the InputChanged event on all devices implementing . - /// - private void SubscribeForSinkFeedback() + catch (Exception ex) { - var sinkDevices = DeviceManager.AllDevices.OfType(); - - foreach (var device in sinkDevices) - { - device.InputChanged += HandleSinkUpdate; - } + Debug.LogMessage(ex, "Error handling midpoint update from {midpointKey}:{Exception}", this, midpoint.Key, ex); } + } - /// - /// Handles the RouteChanged event from a midpoint device. - /// Triggers an update for all sink devices. - /// - /// The midpoint device that reported a route change. - /// The descriptor of the new route. - private void HandleMidpointUpdate(IRoutingWithFeedback midpoint, RouteSwitchDescriptor newRoute) + /// + /// Handles the InputChanged event from a sink device. + /// Triggers an update for the specific sink device. + /// + /// The sink device that reported an input change. + /// The new input port selected on the sink device. + private void HandleSinkUpdate(IRoutingSinkWithSwitching sender, RoutingInputPort currentInputPort) + { + try { - try - { - var devices = DeviceManager.AllDevices.OfType(); - - foreach (var device in devices) - { - UpdateDestination(device, device.CurrentInputPort); - } - } - catch (Exception ex) - { - Debug.LogMessage(ex, "Error handling midpoint update from {midpointKey}:{Exception}", this, midpoint.Key, ex); - } + UpdateDestination(sender, currentInputPort); + } + catch (Exception ex) + { + Debug.LogMessage(ex, "Error handling Sink update from {senderKey}:{Exception}", this, sender.Key, ex); } + } - /// - /// Handles the InputChanged event from a sink device. - /// Triggers an update for the specific sink device. - /// - /// The sink device that reported an input change. - /// The new input port selected on the sink device. - private void HandleSinkUpdate(IRoutingSinkWithSwitching sender, RoutingInputPort currentInputPort) + /// + /// Updates the CurrentSourceInfo and CurrentSourceInfoKey properties on a destination (sink) device + /// based on its currently selected input port by tracing the route back through tie lines. + /// + /// The destination sink device to update. + /// The currently selected input port on the destination device. + private void UpdateDestination(IRoutingSinkWithSwitching destination, RoutingInputPort inputPort) + { + // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Updating destination {destination} with inputPort {inputPort}", this,destination?.Key, inputPort?.Key); + + if(inputPort == null) { - try - { - UpdateDestination(sender, currentInputPort); - } - catch (Exception ex) - { - Debug.LogMessage(ex, "Error handling Sink update from {senderKey}:{Exception}", this, sender.Key, ex); - } + Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "Destination {destination} has not reported an input port yet", this,destination.Key); + return; } - /// - /// Updates the CurrentSourceInfo and CurrentSourceInfoKey properties on a destination (sink) device - /// based on its currently selected input port by tracing the route back through tie lines. - /// - /// The destination sink device to update. - /// The currently selected input port on the destination device. - private void UpdateDestination(IRoutingSinkWithSwitching destination, RoutingInputPort inputPort) - { - // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Updating destination {destination} with inputPort {inputPort}", this,destination?.Key, inputPort?.Key); - - if(inputPort == null) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "Destination {destination} has not reported an input port yet", this,destination.Key); - return; - } + TieLine firstTieLine; + try + { + var tieLines = TieLineCollection.Default; - TieLine firstTieLine; - try - { - var tieLines = TieLineCollection.Default; + firstTieLine = tieLines.FirstOrDefault(tl => tl.DestinationPort.Key == inputPort.Key && tl.DestinationPort.ParentDevice.Key == inputPort.ParentDevice.Key); - firstTieLine = tieLines.FirstOrDefault(tl => tl.DestinationPort.Key == inputPort.Key && tl.DestinationPort.ParentDevice.Key == inputPort.ParentDevice.Key); + if (firstTieLine == null) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No tieline found for inputPort {inputPort}. Clearing current source", this, inputPort); - if (firstTieLine == null) + var tempSourceListItem = new SourceListItem { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No tieline found for inputPort {inputPort}. Clearing current source", this, inputPort); - - var tempSourceListItem = new SourceListItem - { - SourceKey = "$transient", - Name = inputPort.Key, - }; + SourceKey = "$transient", + Name = inputPort.Key, + }; - destination.CurrentSourceInfo = tempSourceListItem; ; - destination.CurrentSourceInfoKey = "$transient"; - return; - } - } catch (Exception ex) - { - Debug.LogMessage(ex, "Error getting first tieline: {Exception}", this, ex); + destination.CurrentSourceInfo = tempSourceListItem; ; + destination.CurrentSourceInfoKey = "$transient"; return; } + } catch (Exception ex) + { + Debug.LogMessage(ex, "Error getting first tieline: {Exception}", this, ex); + return; + } - // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Getting source for first TieLine {tieLine}", this, firstTieLine); + // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Getting source for first TieLine {tieLine}", this, firstTieLine); - TieLine sourceTieLine; - try + TieLine sourceTieLine; + try + { + sourceTieLine = GetRootTieLine(firstTieLine); + + if (sourceTieLine == null) { - sourceTieLine = GetRootTieLine(firstTieLine); + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No route found to source for inputPort {inputPort}. Clearing current source", this, inputPort); - if (sourceTieLine == null) + var tempSourceListItem = new SourceListItem { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No route found to source for inputPort {inputPort}. Clearing current source", this, inputPort); - - var tempSourceListItem = new SourceListItem - { - SourceKey = "$transient", - Name = "None", - }; + SourceKey = "$transient", + Name = "None", + }; - destination.CurrentSourceInfo = tempSourceListItem; - destination.CurrentSourceInfoKey = string.Empty; - return; - } - } catch(Exception ex) - { - Debug.LogMessage(ex, "Error getting sourceTieLine: {Exception}", this, ex); + destination.CurrentSourceInfo = tempSourceListItem; + destination.CurrentSourceInfoKey = string.Empty; return; } + } catch(Exception ex) + { + Debug.LogMessage(ex, "Error getting sourceTieLine: {Exception}", this, ex); + return; + } - // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root TieLine {tieLine}", this, sourceTieLine); - - // Does not handle combinable scenarios or other scenarios where a display might be part of multiple rooms yet. - var room = DeviceManager.AllDevices.OfType().FirstOrDefault((r) => { - if(r is IHasMultipleDisplays roomMultipleDisplays) - { - return roomMultipleDisplays.Displays.Any(d => d.Value.Key == destination.Key); - } - - if(r is IHasDefaultDisplay roomDefaultDisplay) - { - return roomDefaultDisplay.DefaultDisplay.Key == destination.Key; - } + // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root TieLine {tieLine}", this, sourceTieLine); - return false; - }); - - if(room == null) + // Does not handle combinable scenarios or other scenarios where a display might be part of multiple rooms yet. + var room = DeviceManager.AllDevices.OfType().FirstOrDefault((r) => { + if(r is IHasMultipleDisplays roomMultipleDisplays) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "No room found for display {destination}", this, destination.Key); - return; + return roomMultipleDisplays.Displays.Any(d => d.Value.Key == destination.Key); } - // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found room {room} for destination {destination}", this, room.Key, destination.Key); - - var sourceList = ConfigReader.ConfigObject.GetSourceListForKey(room.SourceListKey); - - if (sourceList == null) + if(r is IHasDefaultDisplay roomDefaultDisplay) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "No source list found for source list key {key}. Unable to find source for tieLine {sourceTieLine}", this, room.SourceListKey, sourceTieLine); - return; + return roomDefaultDisplay.DefaultDisplay.Key == destination.Key; } - // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found sourceList for room {room}", this, room.Key); + return false; + }); + + if(room == null) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "No room found for display {destination}", this, destination.Key); + return; + } - var sourceListItem = sourceList.FirstOrDefault(sli => { - //// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, - // "SourceListItem {sourceListItem}:{sourceKey} tieLine sourceport device key {sourcePortDeviceKey}", - // this, - // sli.Key, - // sli.Value.SourceKey, - // sourceTieLine.SourcePort.ParentDevice.Key); + // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found room {room} for destination {destination}", this, room.Key, destination.Key); - return sli.Value.SourceKey.Equals(sourceTieLine.SourcePort.ParentDevice.Key,StringComparison.InvariantCultureIgnoreCase); - }); + var sourceList = ConfigReader.ConfigObject.GetSourceListForKey(room.SourceListKey); - var source = sourceListItem.Value; - var sourceKey = sourceListItem.Key; + if (sourceList == null) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "No source list found for source list key {key}. Unable to find source for tieLine {sourceTieLine}", this, room.SourceListKey, sourceTieLine); + return; + } - if (source == null) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No source found for device {key}. Creating transient source for {destination}", this, sourceTieLine.SourcePort.ParentDevice.Key, destination); + // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found sourceList for room {room}", this, room.Key); - var tempSourceListItem = new SourceListItem - { - SourceKey = "$transient", - Name = sourceTieLine.SourcePort.Key, - }; + var sourceListItem = sourceList.FirstOrDefault(sli => { + //// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, + // "SourceListItem {sourceListItem}:{sourceKey} tieLine sourceport device key {sourcePortDeviceKey}", + // this, + // sli.Key, + // sli.Value.SourceKey, + // sourceTieLine.SourcePort.ParentDevice.Key); - destination.CurrentSourceInfoKey = "$transient"; - destination.CurrentSourceInfo = tempSourceListItem; - return; - } + return sli.Value.SourceKey.Equals(sourceTieLine.SourcePort.ParentDevice.Key,StringComparison.InvariantCultureIgnoreCase); + }); - //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Got Source {@source} with key {sourceKey}", this, source, sourceKey); - - destination.CurrentSourceInfoKey = sourceKey; - destination.CurrentSourceInfo = source; - - } + var source = sourceListItem.Value; + var sourceKey = sourceListItem.Key; - /// - /// Recursively traces a route back from a given tie line to find the root source tie line. - /// It navigates through midpoint devices () by checking their current routes. - /// - /// The starting tie line (typically connected to a sink or midpoint). - /// The connected to the original source device, or null if the source cannot be determined. - private TieLine GetRootTieLine(TieLine tieLine) + if (source == null) { - TieLine nextTieLine = null; - try - { - //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "**Following tieLine {tieLine}**", this, tieLine); - - if (tieLine.SourcePort.ParentDevice is IRoutingWithFeedback midpoint) - { - // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLine Source device {sourceDevice} is midpoint", this, midpoint); + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No source found for device {key}. Creating transient source for {destination}", this, sourceTieLine.SourcePort.ParentDevice.Key, destination); - if(midpoint.CurrentRoutes == null || midpoint.CurrentRoutes.Count == 0) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Midpoint {midpointKey} has no routes",this, midpoint.Key); - return null; - } - - var currentRoute = midpoint.CurrentRoutes.FirstOrDefault(route => { - //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Checking {route} against {tieLine}", this, route, tieLine); + var tempSourceListItem = new SourceListItem + { + SourceKey = "$transient", + Name = sourceTieLine.SourcePort.Key, + }; - return route.OutputPort != null && route.InputPort != null && route.OutputPort?.Key == tieLine.SourcePort.Key && route.OutputPort?.ParentDevice.Key == tieLine.SourcePort.ParentDevice.Key; - }); + destination.CurrentSourceInfoKey = "$transient"; + destination.CurrentSourceInfo = tempSourceListItem; + return; + } - if (currentRoute == null) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No route through midpoint {midpoint} for outputPort {outputPort}", this, midpoint.Key, tieLine.SourcePort); - return null; - } + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Got Source {@source} with key {sourceKey}", this, source, sourceKey); - //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found currentRoute {currentRoute} through {midpoint}", this, currentRoute, midpoint); + destination.CurrentSourceInfoKey = sourceKey; + destination.CurrentSourceInfo = source; + + } - nextTieLine = TieLineCollection.Default.FirstOrDefault(tl => { - //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Checking {route} against {tieLine}", tl.DestinationPort.Key, currentRoute.InputPort.Key); - return tl.DestinationPort.Key == currentRoute.InputPort.Key && tl.DestinationPort.ParentDevice.Key == currentRoute.InputPort.ParentDevice.Key; }); + /// + /// Recursively traces a route back from a given tie line to find the root source tie line. + /// It navigates through midpoint devices () by checking their current routes. + /// + /// The starting tie line (typically connected to a sink or midpoint). + /// The connected to the original source device, or null if the source cannot be determined. + private TieLine GetRootTieLine(TieLine tieLine) + { + TieLine nextTieLine = null; + try + { + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "**Following tieLine {tieLine}**", this, tieLine); - if (nextTieLine != null) - { - //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found next tieLine {tieLine}. Walking the chain", this, nextTieLine); - return GetRootTieLine(nextTieLine); - } + if (tieLine.SourcePort.ParentDevice is IRoutingWithFeedback midpoint) + { + // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLine Source device {sourceDevice} is midpoint", this, midpoint); - //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root tieLine {tieLine}", this,nextTieLine); - return nextTieLine; + if(midpoint.CurrentRoutes == null || midpoint.CurrentRoutes.Count == 0) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Midpoint {midpointKey} has no routes",this, midpoint.Key); + return null; } - //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLIne Source Device {sourceDeviceKey} is IRoutingSource: {isIRoutingSource}", this, tieLine.SourcePort.ParentDevice.Key, tieLine.SourcePort.ParentDevice is IRoutingSource); - //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLine Source Device interfaces: {typeFullName}:{interfaces}", this, tieLine.SourcePort.ParentDevice.GetType().FullName, tieLine.SourcePort.ParentDevice.GetType().GetInterfaces().Select(i => i.Name)); + var currentRoute = midpoint.CurrentRoutes.FirstOrDefault(route => { + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Checking {route} against {tieLine}", this, route, tieLine); + + return route.OutputPort != null && route.InputPort != null && route.OutputPort?.Key == tieLine.SourcePort.Key && route.OutputPort?.ParentDevice.Key == tieLine.SourcePort.ParentDevice.Key; + }); - if (tieLine.SourcePort.ParentDevice is IRoutingSource || tieLine.SourcePort.ParentDevice is IRoutingOutputs) //end of the chain + if (currentRoute == null) { - // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root: {tieLine}", this, tieLine); - return tieLine; + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No route through midpoint {midpoint} for outputPort {outputPort}", this, midpoint.Key, tieLine.SourcePort); + return null; } - nextTieLine = TieLineCollection.Default.FirstOrDefault(tl => tl.DestinationPort.Key == tieLine.SourcePort.Key && tl.DestinationPort.ParentDevice.Key == tieLine.SourcePort.ParentDevice.Key ); + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found currentRoute {currentRoute} through {midpoint}", this, currentRoute, midpoint); + + nextTieLine = TieLineCollection.Default.FirstOrDefault(tl => { + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Checking {route} against {tieLine}", tl.DestinationPort.Key, currentRoute.InputPort.Key); + return tl.DestinationPort.Key == currentRoute.InputPort.Key && tl.DestinationPort.ParentDevice.Key == currentRoute.InputPort.ParentDevice.Key; }); if (nextTieLine != null) { + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found next tieLine {tieLine}. Walking the chain", this, nextTieLine); return GetRootTieLine(nextTieLine); } - } catch (Exception ex) + + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root tieLine {tieLine}", this,nextTieLine); + return nextTieLine; + } + + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLIne Source Device {sourceDeviceKey} is IRoutingSource: {isIRoutingSource}", this, tieLine.SourcePort.ParentDevice.Key, tieLine.SourcePort.ParentDevice is IRoutingSource); + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "TieLine Source Device interfaces: {typeFullName}:{interfaces}", this, tieLine.SourcePort.ParentDevice.GetType().FullName, tieLine.SourcePort.ParentDevice.GetType().GetInterfaces().Select(i => i.Name)); + + if (tieLine.SourcePort.ParentDevice is IRoutingSource || tieLine.SourcePort.ParentDevice is IRoutingOutputs) //end of the chain { - Debug.LogMessage(ex, "Error walking tieLines: {Exception}", this, ex); - return null; + // Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root: {tieLine}", this, tieLine); + return tieLine; } + nextTieLine = TieLineCollection.Default.FirstOrDefault(tl => tl.DestinationPort.Key == tieLine.SourcePort.Key && tl.DestinationPort.ParentDevice.Key == tieLine.SourcePort.ParentDevice.Key ); + + if (nextTieLine != null) + { + return GetRootTieLine(nextTieLine); + } + } catch (Exception ex) + { + Debug.LogMessage(ex, "Error walking tieLines: {Exception}", this, ex); return null; } + + return null; } } diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingInputPort.cs b/src/PepperDash.Essentials.Core/Routing/RoutingInputPort.cs index c949db4eb..479f202db 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingInputPort.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingInputPort.cs @@ -2,18 +2,18 @@ using System; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + +/// +/// Represents a basic routing input port on a device. +/// +public class RoutingInputPort : RoutingPort + { /// - /// Represents a basic routing input port on a device. + /// The IRoutingInputs object this lives on /// - public class RoutingInputPort : RoutingPort - { - /// - /// The IRoutingInputs object this lives on - /// - [JsonIgnore] - public IRoutingInputs ParentDevice { get; private set; } + [JsonIgnore] + public IRoutingInputs ParentDevice { get; private set; } /// /// Constructor for a basic RoutingInputPort @@ -41,48 +41,47 @@ public RoutingInputPort(string key, eRoutingSignalType type, eRoutingPortConnect ParentDevice = parent; } - /// - /// Returns a string representation of the input port. - /// - /// A string in the format "ParentDeviceKey|PortKey|SignalType|ConnectionType". - public override string ToString() - { - return $"{ParentDevice.Key}|{Key}|{Type}|{ConnectionType}"; - } + /// + /// Returns a string representation of the input port. + /// + /// A string in the format "ParentDeviceKey|PortKey|SignalType|ConnectionType". + public override string ToString() + { + return $"{ParentDevice.Key}|{Key}|{Type}|{ConnectionType}"; } +} + +/*/// +/// Basic RoutingInput with no statuses. +/// +public class RoutingInputPort : RoutingPort +{ + /// + /// The IRoutingInputs object this lives on + /// + public IRoutingInputs ParentDevice { get; private set; } - /*/// - /// Basic RoutingInput with no statuses. + /// + /// Constructor for a basic RoutingInputPort /// - public class RoutingInputPort : RoutingPort + /// An object used to refer to this port in the IRouting device's ExecuteSwitch method. + /// May be string, number, whatever + /// The IRoutingInputs object this lives on + public RoutingInputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, + TSelector selector, IRoutingInputs parent) + : this(key, type, connType, selector, parent, false) { - /// - /// The IRoutingInputs object this lives on - /// - public IRoutingInputs ParentDevice { get; private set; } - - /// - /// Constructor for a basic RoutingInputPort - /// - /// An object used to refer to this port in the IRouting device's ExecuteSwitch method. - /// May be string, number, whatever - /// The IRoutingInputs object this lives on - public RoutingInputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, - TSelector selector, IRoutingInputs parent) - : this(key, type, connType, selector, parent, false) - { - } + } - /// - /// Constructor for a virtual routing input port that lives inside a device. For example - /// the ports that link a DM card to a DM matrix bus - /// - /// true for internal ports - public RoutingInputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, - TSelector selector, IRoutingInputs parent, bool isInternal) - : base(key, type, connType, selector, isInternal) - { - ParentDevice = parent ?? throw new ArgumentNullException(nameof(parent)); - } - }*/ -} \ No newline at end of file + /// + /// Constructor for a virtual routing input port that lives inside a device. For example + /// the ports that link a DM card to a DM matrix bus + /// + /// true for internal ports + public RoutingInputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, + TSelector selector, IRoutingInputs parent, bool isInternal) + : base(key, type, connType, selector, isInternal) + { + ParentDevice = parent ?? throw new ArgumentNullException(nameof(parent)); + } +}*/ \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingInputPortWithVideoStatuses.cs b/src/PepperDash.Essentials.Core/Routing/RoutingInputPortWithVideoStatuses.cs index e0c6bba0e..d9719789b 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingInputPortWithVideoStatuses.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingInputPortWithVideoStatuses.cs @@ -1,10 +1,10 @@ -namespace PepperDash.Essentials.Core -{ - /// - /// Represents a routing input port that provides video status feedback (e.g., sync, resolution). - /// Suitable for devices like DM transmitters or DM input cards. - /// - public class RoutingInputPortWithVideoStatuses : RoutingInputPort +namespace PepperDash.Essentials.Core; + +/// +/// Represents a routing input port that provides video status feedback (e.g., sync, resolution). +/// Suitable for devices like DM transmitters or DM input cards. +/// +public class RoutingInputPortWithVideoStatuses : RoutingInputPort { /// /// Provides feedback outputs for video statuses associated with this port. @@ -27,5 +27,4 @@ public RoutingInputPortWithVideoStatuses(string key, { VideoStatus = new VideoStatusOutputs(funcs); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingNumericEventArgs.cs b/src/PepperDash.Essentials.Core/Routing/RoutingNumericEventArgs.cs index a0e706ac4..89cd3d5ca 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingNumericEventArgs.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingNumericEventArgs.cs @@ -1,83 +1,82 @@ using System; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Provides event arguments for routing changes, potentially including numeric or port object references. +/// +public class RoutingNumericEventArgs : EventArgs { /// - /// Provides event arguments for routing changes, potentially including numeric or port object references. + /// The numeric representation of the output, if applicable. /// - public class RoutingNumericEventArgs : EventArgs - { - /// - /// The numeric representation of the output, if applicable. - /// - public uint? Output { get; set; } - /// - /// The numeric representation of the input, if applicable. - /// - public uint? Input { get; set; } + public uint? Output { get; set; } + /// + /// The numeric representation of the input, if applicable. + /// + public uint? Input { get; set; } - /// - /// The type of signal involved in the routing change. - /// - public eRoutingSignalType SigType { get; set; } - /// - /// The input port involved in the routing change, if applicable. - /// - public RoutingInputPort InputPort { get; set; } - /// - /// The output port involved in the routing change, if applicable. - /// - public RoutingOutputPort OutputPort { get; set; } + /// + /// The type of signal involved in the routing change. + /// + public eRoutingSignalType SigType { get; set; } + /// + /// The input port involved in the routing change, if applicable. + /// + public RoutingInputPort InputPort { get; set; } + /// + /// The output port involved in the routing change, if applicable. + /// + public RoutingOutputPort OutputPort { get; set; } + + /// + /// Initializes a new instance of the class using numeric identifiers. + /// + /// The numeric output identifier. + /// The numeric input identifier. + /// The signal type. + public RoutingNumericEventArgs(uint output, uint input, eRoutingSignalType sigType) : this(output, input, null, null, sigType) + { + } - /// - /// Initializes a new instance of the class using numeric identifiers. - /// - /// The numeric output identifier. - /// The numeric input identifier. - /// The signal type. - public RoutingNumericEventArgs(uint output, uint input, eRoutingSignalType sigType) : this(output, input, null, null, sigType) - { - } + /// + /// Initializes a new instance of the class using port objects. + /// + /// The output port object. + /// The input port object. + /// The signal type. + public RoutingNumericEventArgs(RoutingOutputPort outputPort, RoutingInputPort inputPort, + eRoutingSignalType sigType) + : this(null, null, outputPort, inputPort, sigType) + { + } - /// - /// Initializes a new instance of the class using port objects. - /// - /// The output port object. - /// The input port object. - /// The signal type. - public RoutingNumericEventArgs(RoutingOutputPort outputPort, RoutingInputPort inputPort, - eRoutingSignalType sigType) - : this(null, null, outputPort, inputPort, sigType) - { - } + /// + /// Initializes a new instance of the class with default values. + /// + public RoutingNumericEventArgs() + : this(null, null, null, null, 0) + { - /// - /// Initializes a new instance of the class with default values. - /// - public RoutingNumericEventArgs() - : this(null, null, null, null, 0) - { - - } + } - /// - /// Initializes a new instance of the class with potentially mixed identifiers. - /// - /// The numeric output identifier (optional). - /// The numeric input identifier (optional). - /// The output port object (optional). - /// The input port object (optional). - /// The signal type. - public RoutingNumericEventArgs(uint? output, uint? input, RoutingOutputPort outputPort, - RoutingInputPort inputPort, eRoutingSignalType sigType) - { - OutputPort = outputPort; - InputPort = inputPort; + /// + /// Initializes a new instance of the class with potentially mixed identifiers. + /// + /// The numeric output identifier (optional). + /// The numeric input identifier (optional). + /// The output port object (optional). + /// The input port object (optional). + /// The signal type. + public RoutingNumericEventArgs(uint? output, uint? input, RoutingOutputPort outputPort, + RoutingInputPort inputPort, eRoutingSignalType sigType) + { + OutputPort = outputPort; + InputPort = inputPort; - Output = output; - Input = input; - SigType = sigType; - } + Output = output; + Input = input; + SigType = sigType; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingOutputPort.cs b/src/PepperDash.Essentials.Core/Routing/RoutingOutputPort.cs index 1cae64c00..083486e70 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingOutputPort.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingOutputPort.cs @@ -2,18 +2,18 @@ using System; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Represents a basic routing output port on a device. +/// +public class RoutingOutputPort : RoutingPort { /// - /// Represents a basic routing output port on a device. + /// The IRoutingOutputs object this port lives on. /// - public class RoutingOutputPort : RoutingPort - { - /// - /// The IRoutingOutputs object this port lives on. - /// - [JsonIgnore] - public IRoutingOutputs ParentDevice { get; private set; } + [JsonIgnore] + public IRoutingOutputs ParentDevice { get; private set; } /// /// Tracks which destinations are currently using this output port. @@ -48,52 +48,51 @@ public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnec object selector, IRoutingOutputs parent, bool isInternal) : base(key, type, connType, selector, isInternal) { - ParentDevice = parent ?? throw new ArgumentNullException(nameof(parent)); + ParentDevice = parent ?? throw new ArgumentNullException(nameof(parent)); InUseTracker = new InUseTracking(); } - /// - /// Returns a string representation of the output port. - /// - /// A string in the format "ParentDeviceKey|PortKey|SignalType|ConnectionType". - public override string ToString() - { - return $"{ParentDevice.Key}|{Key}|{Type}|{ConnectionType}"; - } + /// + /// Returns a string representation of the output port. + /// + /// A string in the format "ParentDeviceKey|PortKey|SignalType|ConnectionType". + public override string ToString() + { + return $"{ParentDevice.Key}|{Key}|{Type}|{ConnectionType}"; + } } - /*public class RoutingOutputPort : RoutingPort - { - /// - /// The IRoutingOutputs object this port lives on - /// - public IRoutingOutputs ParentDevice { get; private set; } +/*public class RoutingOutputPort : RoutingPort +{ + /// + /// The IRoutingOutputs object this port lives on + /// + public IRoutingOutputs ParentDevice { get; private set; } - public InUseTracking InUseTracker { get; private set; } + public InUseTracking InUseTracker { get; private set; } - /// - /// - /// An object used to refer to this port in the IRouting device's ExecuteSwitch method. - /// May be string, number, whatever - /// The IRoutingOutputs object this port lives on - public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, - TSelector selector, IRoutingOutputs parent) - : this(key, type, connType, selector, parent, false) - { - } + /// + /// + /// An object used to refer to this port in the IRouting device's ExecuteSwitch method. + /// May be string, number, whatever + /// The IRoutingOutputs object this port lives on + public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, + TSelector selector, IRoutingOutputs parent) + : this(key, type, connType, selector, parent, false) + { + } - public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, - TSelector selector, IRoutingOutputs parent, bool isInternal) - : base(key, type, connType, selector, isInternal) - { - ParentDevice = parent ?? throw new ArgumentNullException(nameof(parent)); - InUseTracker = new InUseTracking(); - } + public RoutingOutputPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, + TSelector selector, IRoutingOutputs parent, bool isInternal) + : base(key, type, connType, selector, isInternal) + { + ParentDevice = parent ?? throw new ArgumentNullException(nameof(parent)); + InUseTracker = new InUseTracking(); + } - public override string ToString() - { - return ParentDevice.Key + ":" + Key; - } - }*/ -} \ No newline at end of file + public override string ToString() + { + return ParentDevice.Key + ":" + Key; + } +}*/ \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingPort.cs b/src/PepperDash.Essentials.Core/Routing/RoutingPort.cs index 64fae203a..e7deadcc7 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingPort.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingPort.cs @@ -1,12 +1,12 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ - /// - /// Base class for and . - /// - public abstract class RoutingPort : IKeyed +namespace PepperDash.Essentials.Core; + +/// +/// Base class for and . +/// +public abstract class RoutingPort : IKeyed { /// /// The unique key identifying this port within its parent device. @@ -28,14 +28,14 @@ public abstract class RoutingPort : IKeyed /// Indicates if this port represents an internal connection within a device (e.g., card to backplane). /// public bool IsInternal { get; private set; } - /// - /// An object used to match feedback values to this port, if applicable. - /// - public object FeedbackMatchObject { get; set; } - /// - /// A reference to the underlying hardware port object (e.g., SimplSharpPro Port), if applicable. - /// - public object Port { get; set; } + /// + /// An object used to match feedback values to this port, if applicable. + /// + public object FeedbackMatchObject { get; set; } + /// + /// A reference to the underlying hardware port object (e.g., SimplSharpPro Port), if applicable. + /// + public object Port { get; set; } /// /// Initializes a new instance of the class. @@ -53,25 +53,24 @@ public RoutingPort(string key, eRoutingSignalType type, eRoutingPortConnectionTy Selector = selector; IsInternal = isInternal; } - } +} - /*public abstract class RoutingPort:IKeyed - { - public string Key { get; private set; } - public eRoutingSignalType Type { get; private set; } - public eRoutingPortConnectionType ConnectionType { get; private set; } - public readonly TSelector Selector; - public bool IsInternal { get; private set; } - public object FeedbackMatchObject { get; set; } - public object Port { get; set; } +/*public abstract class RoutingPort:IKeyed +{ + public string Key { get; private set; } + public eRoutingSignalType Type { get; private set; } + public eRoutingPortConnectionType ConnectionType { get; private set; } + public readonly TSelector Selector; + public bool IsInternal { get; private set; } + public object FeedbackMatchObject { get; set; } + public object Port { get; set; } - public RoutingPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, TSelector selector, bool isInternal) - { - Key = key; - Type = type; - ConnectionType = connType; - Selector = selector; - IsInternal = isInternal; - } - }*/ -} \ No newline at end of file + public RoutingPort(string key, eRoutingSignalType type, eRoutingPortConnectionType connType, TSelector selector, bool isInternal) + { + Key = key; + Type = type; + ConnectionType = connType; + Selector = selector; + IsInternal = isInternal; + } +}*/ \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingPortCollection.cs b/src/PepperDash.Essentials.Core/Routing/RoutingPortCollection.cs index e1e6bc190..073344655 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingPortCollection.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingPortCollection.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.Linq; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// Basically a List , with an indexer to find ports by key name /// @@ -25,16 +25,15 @@ public T this[string key] /// Basically a List , with an indexer to find ports by key name /// public class RoutingPortCollection : List where T : RoutingPort +{ + /// + /// Case-insensitive port lookup linked to ports' keys + /// + public T this[string key] { - /// - /// Case-insensitive port lookup linked to ports' keys - /// - public T this[string key] + get { - get - { - return this.FirstOrDefault(i => i.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); - } + return this.FirstOrDefault(i => i.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); } - }*/ -} \ No newline at end of file + } +}*/ \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/RoutingPortNames.cs b/src/PepperDash.Essentials.Core/Routing/RoutingPortNames.cs index 96a2ca322..a783a0b0b 100644 --- a/src/PepperDash.Essentials.Core/Routing/RoutingPortNames.cs +++ b/src/PepperDash.Essentials.Core/Routing/RoutingPortNames.cs @@ -4,249 +4,248 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// Defines constant string values for common routing port keys. - /// These should correspond directly with the portNames var in the config tool. +/// These should correspond directly with the portNames var in the config tool. /// public class RoutingPortNames { - /// - /// antennaIn - /// + /// + /// antennaIn + /// public const string AntennaIn = "antennaIn"; - /// - /// anyAudioIn - /// + /// + /// anyAudioIn + /// public const string AnyAudioIn = "anyAudioIn"; - /// - /// anyAudioOut - /// + /// + /// anyAudioOut + /// public const string AnyAudioOut = "anyAudioOut"; - /// - /// anyOut - /// - public const string AnyOut = "anyOut"; - /// - /// anyVideoIn - /// - public const string AnyVideoIn = "anyVideoIn"; - /// - /// anyVideoOut - /// + /// + /// anyOut + /// + public const string AnyOut = "anyOut"; + /// + /// anyVideoIn + /// + public const string AnyVideoIn = "anyVideoIn"; + /// + /// anyVideoOut + /// public const string AnyVideoOut = "anyVideoOut"; - /// - /// balancedAudioOut - /// + /// + /// balancedAudioOut + /// public const string BalancedAudioOut = "balancedAudioOut"; - /// - /// codecOsd - /// - public const string CodecOsd = "codecOsd"; - /// - /// componentIn - /// + /// + /// codecOsd + /// + public const string CodecOsd = "codecOsd"; + /// + /// componentIn + /// public const string ComponentIn = "componentIn"; - /// - /// componentOut - /// + /// + /// componentOut + /// public const string ComponentOut = "componentOut"; - /// - /// compositeIn - /// + /// + /// compositeIn + /// public const string CompositeIn = "compositeIn"; - /// - /// compositeOut - /// + /// + /// compositeOut + /// public const string CompositeOut = "compositeOut"; - /// - /// displayPortIn - /// + /// + /// displayPortIn + /// public const string DisplayPortIn = "displayPortIn"; - /// - /// displayPortIn1 - /// + /// + /// displayPortIn1 + /// public const string DisplayPortIn1 = "displayPortIn1"; - /// - /// displayPortIn2 - /// + /// + /// displayPortIn2 + /// public const string DisplayPortIn2 = "displayPortIn2"; - /// - /// displayPortIn3 - /// + /// + /// displayPortIn3 + /// public const string DisplayPortIn3 = "displayPortIn3"; - /// - /// displayPortOut - /// + /// + /// displayPortOut + /// public const string DisplayPortOut = "displayPortOut"; - /// - /// dmIn - /// + /// + /// dmIn + /// public const string DmIn = "dmIn"; - /// - /// dmOut - /// + /// + /// dmOut + /// public const string DmOut = "dmOut"; - /// - /// dviIn - /// + /// + /// dviIn + /// public const string DviIn = "dviIn"; - /// - /// dviIn1 - /// - public const string DviIn1 = "dviIn1"; - /// - /// dviOut - /// - public const string DviOut = "dviOut"; - /// - /// hdmiIn - /// + /// + /// dviIn1 + /// + public const string DviIn1 = "dviIn1"; + /// + /// dviOut + /// + public const string DviOut = "dviOut"; + /// + /// hdmiIn + /// public const string HdmiIn = "hdmiIn"; - /// - /// hdmiIn1 - /// + /// + /// hdmiIn1 + /// public const string HdmiIn1 = "hdmiIn1"; - /// - /// hdmiIn1PC - /// - public const string HdmiIn1PC = "hdmiIn1PC"; - /// - /// hdmiIn2 - /// + /// + /// hdmiIn1PC + /// + public const string HdmiIn1PC = "hdmiIn1PC"; + /// + /// hdmiIn2 + /// public const string HdmiIn2 = "hdmiIn2"; - /// - /// hdmiIn2PC - /// - public const string HdmiIn2PC = "hdmiIn2PC"; - /// - /// hdmiIn3 - /// + /// + /// hdmiIn2PC + /// + public const string HdmiIn2PC = "hdmiIn2PC"; + /// + /// hdmiIn3 + /// public const string HdmiIn3 = "hdmiIn3"; - /// - /// hdmiIn4 - /// + /// + /// hdmiIn4 + /// public const string HdmiIn4 = "hdmiIn4"; - /// - /// hdmiIn5 - /// + /// + /// hdmiIn5 + /// public const string HdmiIn5 = "hdmiIn5"; - /// - /// hdmiIn6 - /// + /// + /// hdmiIn6 + /// public const string HdmiIn6 = "hdmiIn6"; - /// - /// hdmiOut - /// + /// + /// hdmiOut + /// public const string HdmiOut = "hdmiOut"; - /// - /// hdmiOut1 - /// - public const string HdmiOut1 = "hdmiOut1"; - /// - /// hdmiOut2 - /// - public const string HdmiOut2 = "hdmiOut2"; - /// - /// hdmiOut3 - /// - public const string HdmiOut3 = "hdmiOut3"; - /// - /// hdmiOut4 - /// - public const string HdmiOut4 = "hdmiOut4"; - /// - /// hdmiOut5 - /// - public const string HdmiOut5 = "hdmiOut5"; - /// - /// hdmiOut6 - /// - public const string HdmiOut6 = "hdmiOut6"; - /// - /// none - /// - public const string None = "none"; - /// - /// rgbIn - /// + /// + /// hdmiOut1 + /// + public const string HdmiOut1 = "hdmiOut1"; + /// + /// hdmiOut2 + /// + public const string HdmiOut2 = "hdmiOut2"; + /// + /// hdmiOut3 + /// + public const string HdmiOut3 = "hdmiOut3"; + /// + /// hdmiOut4 + /// + public const string HdmiOut4 = "hdmiOut4"; + /// + /// hdmiOut5 + /// + public const string HdmiOut5 = "hdmiOut5"; + /// + /// hdmiOut6 + /// + public const string HdmiOut6 = "hdmiOut6"; + /// + /// none + /// + public const string None = "none"; + /// + /// rgbIn + /// public const string RgbIn = "rgbIn"; - /// - /// rgbIn1 - /// - public const string RgbIn1 = "rgbIn1"; - /// - /// rgbIn2 - /// - public const string RgbIn2 = "rgbIn2"; - /// - /// vgaIn - /// + /// + /// rgbIn1 + /// + public const string RgbIn1 = "rgbIn1"; + /// + /// rgbIn2 + /// + public const string RgbIn2 = "rgbIn2"; + /// + /// vgaIn + /// public const string VgaIn = "vgaIn"; - /// - /// vgaIn1 - /// - public const string VgaIn1 = "vgaIn1"; - /// - /// vgaOut - /// + /// + /// vgaIn1 + /// + public const string VgaIn1 = "vgaIn1"; + /// + /// vgaOut + /// public const string VgaOut = "vgaOut"; - /// - /// IPC/OPS - /// - public const string IpcOps = "ipcOps"; - /// - /// MediaPlayer - /// - public const string MediaPlayer = "mediaPlayer"; - /// - /// UsbCIn - /// - public const string UsbCIn = "usbCIn"; - /// - /// UsbCIn1 - /// - public const string UsbCIn1 = "usbCIn1"; - /// - /// UsbCIn2 - /// - public const string UsbCIn2 = "usbCIn2"; - /// - /// UsbCIn3 - /// - public const string UsbCIn3 = "usbCIn3"; - /// - /// UsbCOut - /// - public const string UsbCOut = "usbCOut"; - /// - /// UsbCOut1 - /// - public const string UsbCOut1 = "usbCOut1"; - /// - /// UsbCOut2 - /// - public const string UsbCOut2 = "usbCOut2"; - /// - /// UsbCOut3 - /// - public const string UsbCOut3 = "usbCOut3"; - /// - /// HdBaseTIn - /// - public const string HdBaseTIn = "hdBaseTIn"; - /// - /// HdBaseTOut - /// - public const string HdBaseTOut = "hdBaseTOut"; - /// - /// SdiIn - /// - public const string SdiIn = "sdiIn"; - /// - /// SdiOut - /// - public const string SdiOut = "sdiOut"; - } + /// + /// IPC/OPS + /// + public const string IpcOps = "ipcOps"; + /// + /// MediaPlayer + /// + public const string MediaPlayer = "mediaPlayer"; + /// + /// UsbCIn + /// + public const string UsbCIn = "usbCIn"; + /// + /// UsbCIn1 + /// + public const string UsbCIn1 = "usbCIn1"; + /// + /// UsbCIn2 + /// + public const string UsbCIn2 = "usbCIn2"; + /// + /// UsbCIn3 + /// + public const string UsbCIn3 = "usbCIn3"; + /// + /// UsbCOut + /// + public const string UsbCOut = "usbCOut"; + /// + /// UsbCOut1 + /// + public const string UsbCOut1 = "usbCOut1"; + /// + /// UsbCOut2 + /// + public const string UsbCOut2 = "usbCOut2"; + /// + /// UsbCOut3 + /// + public const string UsbCOut3 = "usbCOut3"; + /// + /// HdBaseTIn + /// + public const string HdBaseTIn = "hdBaseTIn"; + /// + /// HdBaseTOut + /// + public const string HdBaseTOut = "hdBaseTOut"; + /// + /// SdiIn + /// + public const string SdiIn = "sdiIn"; + /// + /// SdiOut + /// + public const string SdiOut = "sdiOut"; } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/TieLine.cs b/src/PepperDash.Essentials.Core/Routing/TieLine.cs index f3a2c71d2..39a07aba1 100644 --- a/src/PepperDash.Essentials.Core/Routing/TieLine.cs +++ b/src/PepperDash.Essentials.Core/Routing/TieLine.cs @@ -2,152 +2,151 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Represents a connection (tie line) between a and a . +/// +public class TieLine { /// - /// Represents a connection (tie line) between a and a . + /// The source output port of the tie line. /// - public class TieLine - { - /// - /// The source output port of the tie line. - /// - public RoutingOutputPort SourcePort { get; private set; } - /// - /// The destination input port of the tie line. - /// - public RoutingInputPort DestinationPort { get; private set; } - //public int InUseCount { get { return DestinationUsingThis.Count; } } + public RoutingOutputPort SourcePort { get; private set; } + /// + /// The destination input port of the tie line. + /// + public RoutingInputPort DestinationPort { get; private set; } + //public int InUseCount { get { return DestinationUsingThis.Count; } } - /// - /// Gets the type of this tie line. Will either be the type of the destination port - /// or the type of OverrideType when it is set. - /// - public eRoutingSignalType Type + /// + /// Gets the type of this tie line. Will either be the type of the destination port + /// or the type of OverrideType when it is set. + /// + public eRoutingSignalType Type + { + get { - get - { - if (OverrideType.HasValue) return OverrideType.Value; - return DestinationPort.Type; - } + if (OverrideType.HasValue) return OverrideType.Value; + return DestinationPort.Type; } + } - /// - /// Use this to override the Type property for the destination port. For example, - /// when the tie line is type AudioVideo, and the signal flow should be limited to - /// Audio-only or Video only, changing this type will alter the signal paths - /// available to the routing algorithm without affecting the actual Type - /// of the destination port. - /// - public eRoutingSignalType? OverrideType { get; set; } + /// + /// Use this to override the Type property for the destination port. For example, + /// when the tie line is type AudioVideo, and the signal flow should be limited to + /// Audio-only or Video only, changing this type will alter the signal paths + /// available to the routing algorithm without affecting the actual Type + /// of the destination port. + /// + public eRoutingSignalType? OverrideType { get; set; } - //List DestinationUsingThis = new List(); + //List DestinationUsingThis = new List(); - /// - /// Gets a value indicating whether this tie line represents an internal connection within a device (both source and destination ports are internal). - /// - public bool IsInternal { get { return SourcePort.IsInternal && DestinationPort.IsInternal; } } - /// - /// Gets a value indicating whether the signal types of the source and destination ports differ. - /// - public bool TypeMismatch { get { return SourcePort.Type != DestinationPort.Type; } } - /// - /// Gets a value indicating whether the connection types of the source and destination ports differ. - /// - public bool ConnectionTypeMismatch { get { return SourcePort.ConnectionType != DestinationPort.ConnectionType; } } - /// - /// A descriptive note about any type mismatch, if applicable. - /// - public string TypeMismatchNote { get; set; } + /// + /// Gets a value indicating whether this tie line represents an internal connection within a device (both source and destination ports are internal). + /// + public bool IsInternal { get { return SourcePort.IsInternal && DestinationPort.IsInternal; } } + /// + /// Gets a value indicating whether the signal types of the source and destination ports differ. + /// + public bool TypeMismatch { get { return SourcePort.Type != DestinationPort.Type; } } + /// + /// Gets a value indicating whether the connection types of the source and destination ports differ. + /// + public bool ConnectionTypeMismatch { get { return SourcePort.ConnectionType != DestinationPort.ConnectionType; } } + /// + /// A descriptive note about any type mismatch, if applicable. + /// + public string TypeMismatchNote { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The source output port. - /// The destination input port. - public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort) - { - if (sourcePort == null || destinationPort == null) - throw new ArgumentNullException("source or destination port"); - SourcePort = sourcePort; - DestinationPort = destinationPort; - } + /// + /// Initializes a new instance of the class. + /// + /// The source output port. + /// The destination input port. + public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort) + { + if (sourcePort == null || destinationPort == null) + throw new ArgumentNullException("source or destination port"); + SourcePort = sourcePort; + DestinationPort = destinationPort; + } - /// - /// Creates a tie line with an overriding Type. See help for OverrideType property for info. - /// - /// The source output port. - /// The destination input port. - /// The signal type to limit the link to. Overrides DestinationPort.Type for routing calculations. - public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType? overrideType) : - this(sourcePort, destinationPort) - { - OverrideType = overrideType; - } + /// + /// Creates a tie line with an overriding Type. See help for OverrideType property for info. + /// + /// The source output port. + /// The destination input port. + /// The signal type to limit the link to. Overrides DestinationPort.Type for routing calculations. + public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType? overrideType) : + this(sourcePort, destinationPort) + { + OverrideType = overrideType; + } - /// - /// Creates a tie line with an overriding Type. See help for OverrideType property for info. - /// - /// The source output port. - /// The destination input port. - /// The signal type to limit the link to. Overrides DestinationPort.Type for routing calculations. - public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType overrideType) : - this(sourcePort, destinationPort) - { - OverrideType = overrideType; - } + /// + /// Creates a tie line with an overriding Type. See help for OverrideType property for info. + /// + /// The source output port. + /// The destination input port. + /// The signal type to limit the link to. Overrides DestinationPort.Type for routing calculations. + public TieLine(RoutingOutputPort sourcePort, RoutingInputPort destinationPort, eRoutingSignalType overrideType) : + this(sourcePort, destinationPort) + { + OverrideType = overrideType; + } - /// - /// Will link up video status from supporting inputs to connected outputs. - /// - public void Activate() - { - // Now does nothing - } + /// + /// Will link up video status from supporting inputs to connected outputs. + /// + public void Activate() + { + // Now does nothing + } - /// - /// Deactivates the tie line. - /// - public void Deactivate() - { - // Now does nothing - } + /// + /// Deactivates the tie line. + /// + public void Deactivate() + { + // Now does nothing + } - /// - /// Returns a string representation of the tie line. - /// - /// A string describing the source, destination, and type of the tie line. - public override string ToString() - { - return string.Format("Tie line: {0}:{1} --> {2}:{3} {4}", SourcePort.ParentDevice.Key, SourcePort.Key, - DestinationPort.ParentDevice.Key, DestinationPort.Key, Type.ToString()); - } + /// + /// Returns a string representation of the tie line. + /// + /// A string describing the source, destination, and type of the tie line. + public override string ToString() + { + return string.Format("Tie line: {0}:{1} --> {2}:{3} {4}", SourcePort.ParentDevice.Key, SourcePort.Key, + DestinationPort.ParentDevice.Key, DestinationPort.Key, Type.ToString()); } +} - //******************************************************************************** +//******************************************************************************** +/// +/// Represents a collection of objects. +/// +public class TieLineCollection : List +{ /// - /// Represents a collection of objects. + /// Gets the default singleton instance of the . /// - public class TieLineCollection : List + public static TieLineCollection Default { - /// - /// Gets the default singleton instance of the . - /// - public static TieLineCollection Default + get { - get - { - if (_Default == null) - _Default = new TieLineCollection(); - return _Default; - } + if (_Default == null) + _Default = new TieLineCollection(); + return _Default; } - - /// - /// Backing field for the singleton instance. - /// - [JsonIgnore] - private static TieLineCollection _Default; } + + /// + /// Backing field for the singleton instance. + /// + [JsonIgnore] + private static TieLineCollection _Default; } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/TieLineConfig.cs b/src/PepperDash.Essentials.Core/Routing/TieLineConfig.cs index 5090f9c22..d5c582b80 100644 --- a/src/PepperDash.Essentials.Core/Routing/TieLineConfig.cs +++ b/src/PepperDash.Essentials.Core/Routing/TieLineConfig.cs @@ -11,8 +11,8 @@ using PepperDash.Essentials.Core; using Serilog.Events; -namespace PepperDash.Essentials.Core.Config -{ +namespace PepperDash.Essentials.Core.Config; + /// /// Represents the configuration data for a single tie line between two routing ports. /// @@ -48,12 +48,12 @@ public class TieLineConfig /// public string DestinationPort { get; set; } - /// - /// Optional override for the signal type of the tie line. If set, this overrides the destination port's type for routing calculations. - /// - [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] - [JsonConverter(typeof(StringEnumConverter))] - public eRoutingSignalType? OverrideType { get; set; } + /// + /// Optional override for the signal type of the tie line. If set, this overrides the destination port's type for routing calculations. + /// + [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] + [JsonConverter(typeof(StringEnumConverter))] + public eRoutingSignalType? OverrideType { get; set; } /// /// Returns the appropriate tie line for either a card-based device or @@ -79,19 +79,19 @@ public TieLine GetTieLine() return null; } - //Get the source port - var sourceOutputPort = sourceDev.OutputPorts[SourcePort]; + //Get the source port + var sourceOutputPort = sourceDev.OutputPorts[SourcePort]; - if (sourceOutputPort == null) + if (sourceOutputPort == null) { LogError("Source does not contain port"); return null; } - //Get the Destination port - var destinationInputPort = destDev.InputPorts[DestinationPort]; + //Get the Destination port + var destinationInputPort = destDev.InputPorts[DestinationPort]; - if (destinationInputPort == null) + if (destinationInputPort == null) { LogError("Destination does not contain port"); return null; @@ -118,5 +118,4 @@ public override string ToString() return string.Format("{0}.{1}.{2} --> {3}.{4}.{5}", SourceKey, SourceCard, SourcePort, DestinationKey, DestinationCard, DestinationPort); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/eRoutingPortConnectionType.cs b/src/PepperDash.Essentials.Core/Routing/eRoutingPortConnectionType.cs index 436ef9e64..f57037be2 100644 --- a/src/PepperDash.Essentials.Core/Routing/eRoutingPortConnectionType.cs +++ b/src/PepperDash.Essentials.Core/Routing/eRoutingPortConnectionType.cs @@ -1,8 +1,7 @@ -namespace PepperDash.Essentials.Core -{ - public enum eRoutingPortConnectionType +namespace PepperDash.Essentials.Core; + +public enum eRoutingPortConnectionType { None, BackplaneOnly, DisplayPort, Dvi, Hdmi, Rgb, Vga, LineAudio, DigitalAudio, Sdi, Composite, Component, DmCat, DmMmFiber, DmSmFiber, Speaker, Streaming, UsbC, HdBaseT - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Routing/eRoutingSignalType.cs b/src/PepperDash.Essentials.Core/Routing/eRoutingSignalType.cs index b5f3d9f7c..7e623058a 100644 --- a/src/PepperDash.Essentials.Core/Routing/eRoutingSignalType.cs +++ b/src/PepperDash.Essentials.Core/Routing/eRoutingSignalType.cs @@ -1,16 +1,15 @@ using System; -namespace PepperDash.Essentials.Core -{ - [Flags] +namespace PepperDash.Essentials.Core; + +[Flags] public enum eRoutingSignalType { Audio = 1, Video = 2, AudioVideo = Audio | Video, - UsbOutput = 8, - UsbInput = 16, - SecondaryAudio = 32 - } -} \ No newline at end of file + UsbOutput = 8, + UsbInput = 16, + SecondaryAudio = 32 + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Secrets/CrestronGlobalSecretsProvider.cs b/src/PepperDash.Essentials.Core/Secrets/CrestronGlobalSecretsProvider.cs index 4614e6610..d89efd2c6 100644 --- a/src/PepperDash.Essentials.Core/Secrets/CrestronGlobalSecretsProvider.cs +++ b/src/PepperDash.Essentials.Core/Secrets/CrestronGlobalSecretsProvider.cs @@ -5,99 +5,97 @@ using Serilog.Events; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public class CrestronGlobalSecretsProvider : ISecretProvider { - public class CrestronGlobalSecretsProvider : ISecretProvider + public string Key { get; set; } + //Added for reference + public string Description { get; private set; } + + public CrestronGlobalSecretsProvider(string key) { - public string Key { get; set; } - //Added for reference - public string Description { get; private set; } + Key = key; + Description = String.Format("Default secret provider serving all local applications"); - public CrestronGlobalSecretsProvider(string key) - { - Key = key; - Description = String.Format("Default secret provider serving all local applications"); + } - } + static CrestronGlobalSecretsProvider() + { + //Added for future encrypted reference + var secureSupported = CrestronSecureStorage.Supported; - static CrestronGlobalSecretsProvider() + CrestronDataStoreStatic.InitCrestronDataStore(); + if (secureSupported) { - //Added for future encrypted reference - var secureSupported = CrestronSecureStorage.Supported; - - CrestronDataStoreStatic.InitCrestronDataStore(); - if (secureSupported) - { - //doThingsFuture - } + //doThingsFuture } + } - /// - /// Set secret for item in the CrestronSecretsProvider - /// - /// Secret Key - /// Secret Value - public bool SetSecret(string key, object value) - { - var secret = value as string; - CrestronDataStore.CDS_ERROR returnCode; - - if (String.IsNullOrEmpty(secret)) - { - returnCode = CrestronDataStoreStatic.clearGlobal(key); - if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) - { - Debug.LogMessage(LogEventLevel.Information, this, "Successfully removed secret \"{0}\"", secret); - return true; - } - } + /// + /// Set secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// Secret Value + public bool SetSecret(string key, object value) + { + var secret = value as string; + CrestronDataStore.CDS_ERROR returnCode; - else + if (String.IsNullOrEmpty(secret)) + { + returnCode = CrestronDataStoreStatic.clearGlobal(key); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) { - returnCode = CrestronDataStoreStatic.SetGlobalStringValue(key, secret); - if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) - { - Debug.LogMessage(LogEventLevel.Information, this, "Successfully set secret \"{0}\"", secret); - return true; - } + Debug.LogMessage(LogEventLevel.Information, this, "Successfully removed secret \"{0}\"", secret); + return true; } - - Debug.LogMessage(LogEventLevel.Information, this, "Unable to set secret for {0}:{1} - {2}", Key, key, returnCode.ToString()); - return false; } - /// - /// Retrieve secret for item in the CrestronSecretsProvider - /// - /// Secret Key - /// ISecret Object containing key, provider, and value - public ISecret GetSecret(string key) + else { - string mySecret; - var getErrorCode = CrestronDataStoreStatic.GetGlobalStringValue(key, out mySecret); - - switch (getErrorCode) + returnCode = CrestronDataStoreStatic.SetGlobalStringValue(key, secret); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) { - case CrestronDataStore.CDS_ERROR.CDS_SUCCESS: - Debug.LogMessage(LogEventLevel.Verbose, this, "Secret Successfully retrieved for {0}:{1}", Key, key); - return new CrestronSecret(key, mySecret, this); - default: - Debug.LogMessage(LogEventLevel.Information, this, "Unable to retrieve secret for {0}:{1} - {2}", - Key, key, getErrorCode.ToString()); - return null; + Debug.LogMessage(LogEventLevel.Information, this, "Successfully set secret \"{0}\"", secret); + return true; } } - /// - /// Determine if a secret is present within the provider without retrieving it - /// - /// Secret Key - /// bool if present - public bool TestSecret(string key) + Debug.LogMessage(LogEventLevel.Information, this, "Unable to set secret for {0}:{1} - {2}", Key, key, returnCode.ToString()); + return false; + } + + /// + /// Retrieve secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// ISecret Object containing key, provider, and value + public ISecret GetSecret(string key) + { + string mySecret; + var getErrorCode = CrestronDataStoreStatic.GetGlobalStringValue(key, out mySecret); + + switch (getErrorCode) { - string mySecret; - return CrestronDataStoreStatic.GetGlobalStringValue(key, out mySecret) == CrestronDataStore.CDS_ERROR.CDS_SUCCESS; + case CrestronDataStore.CDS_ERROR.CDS_SUCCESS: + Debug.LogMessage(LogEventLevel.Verbose, this, "Secret Successfully retrieved for {0}:{1}", Key, key); + return new CrestronSecret(key, mySecret, this); + default: + Debug.LogMessage(LogEventLevel.Information, this, "Unable to retrieve secret for {0}:{1} - {2}", + Key, key, getErrorCode.ToString()); + return null; } } + /// + /// Determine if a secret is present within the provider without retrieving it + /// + /// Secret Key + /// bool if present + public bool TestSecret(string key) + { + string mySecret; + return CrestronDataStoreStatic.GetGlobalStringValue(key, out mySecret) == CrestronDataStore.CDS_ERROR.CDS_SUCCESS; + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Secrets/CrestronLocalSecretsProvider.cs b/src/PepperDash.Essentials.Core/Secrets/CrestronLocalSecretsProvider.cs index 6c355d30a..0bffd23eb 100644 --- a/src/PepperDash.Essentials.Core/Secrets/CrestronLocalSecretsProvider.cs +++ b/src/PepperDash.Essentials.Core/Secrets/CrestronLocalSecretsProvider.cs @@ -6,99 +6,97 @@ using Serilog.Events; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public class CrestronLocalSecretsProvider : ISecretProvider { - public class CrestronLocalSecretsProvider : ISecretProvider + public string Key { get; set; } + //Added for reference + public string Description { get; private set; } + + + public CrestronLocalSecretsProvider(string key) { - public string Key { get; set; } - //Added for reference - public string Description { get; private set; } + Key = key; + Description = String.Format("Default secret provider serving Essentials Application {0}", InitialParametersClass.ApplicationNumber); + } + static CrestronLocalSecretsProvider() + { + //Added for future encrypted reference + var secureSupported = CrestronSecureStorage.Supported; - public CrestronLocalSecretsProvider(string key) + CrestronDataStoreStatic.InitCrestronDataStore(); + if (secureSupported) { - Key = key; - Description = String.Format("Default secret provider serving Essentials Application {0}", InitialParametersClass.ApplicationNumber); + //doThingsFuture } + } - static CrestronLocalSecretsProvider() - { - //Added for future encrypted reference - var secureSupported = CrestronSecureStorage.Supported; + /// + /// Set secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// Secret Value + public bool SetSecret(string key, object value) + { + var secret = value as string; + CrestronDataStore.CDS_ERROR returnCode; - CrestronDataStoreStatic.InitCrestronDataStore(); - if (secureSupported) + if (String.IsNullOrEmpty(secret)) + { + returnCode = CrestronDataStoreStatic.clearLocal(key); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) { - //doThingsFuture + Debug.LogMessage(LogEventLevel.Information, this, "Successfully removed secret \"{0}\"", secret); + return true; } } - /// - /// Set secret for item in the CrestronSecretsProvider - /// - /// Secret Key - /// Secret Value - public bool SetSecret(string key, object value) + else { - var secret = value as string; - CrestronDataStore.CDS_ERROR returnCode; - - if (String.IsNullOrEmpty(secret)) - { - returnCode = CrestronDataStoreStatic.clearLocal(key); - if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) - { - Debug.LogMessage(LogEventLevel.Information, this, "Successfully removed secret \"{0}\"", secret); - return true; - } - } - - else + returnCode = CrestronDataStoreStatic.SetLocalStringValue(key, secret); + if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) { - returnCode = CrestronDataStoreStatic.SetLocalStringValue(key, secret); - if (returnCode == CrestronDataStore.CDS_ERROR.CDS_SUCCESS) - { - Debug.LogMessage(LogEventLevel.Information, this, "Successfully set secret \"{0}\"", secret); - return true; - } + Debug.LogMessage(LogEventLevel.Information, this, "Successfully set secret \"{0}\"", secret); + return true; } - - Debug.LogMessage(LogEventLevel.Information, this, "Unable to set secret for {0}:{1} - {2}", Key, key, returnCode.ToString()); - return false; } - /// - /// Retrieve secret for item in the CrestronSecretsProvider - /// - /// Secret Key - /// ISecret Object containing key, provider, and value - public ISecret GetSecret(string key) - { - string mySecret; - var getErrorCode = CrestronDataStoreStatic.GetLocalStringValue(key, out mySecret); + Debug.LogMessage(LogEventLevel.Information, this, "Unable to set secret for {0}:{1} - {2}", Key, key, returnCode.ToString()); + return false; + } - switch (getErrorCode) - { - case CrestronDataStore.CDS_ERROR.CDS_SUCCESS: - Debug.LogMessage(LogEventLevel.Verbose, this, "Secret Successfully retrieved for {0}:{1}", Key, key); - return new CrestronSecret(key, mySecret, this); - default: - Debug.LogMessage(LogEventLevel.Information, this, "Unable to retrieve secret for {0}:{1} - {2}", - Key, key, getErrorCode.ToString()); - return null; - } - } + /// + /// Retrieve secret for item in the CrestronSecretsProvider + /// + /// Secret Key + /// ISecret Object containing key, provider, and value + public ISecret GetSecret(string key) + { + string mySecret; + var getErrorCode = CrestronDataStoreStatic.GetLocalStringValue(key, out mySecret); - /// - /// Determine if a secret is present within the provider without retrieving it - /// - /// Secret Key - /// bool if present - public bool TestSecret(string key) + switch (getErrorCode) { - string mySecret; - return CrestronDataStoreStatic.GetLocalStringValue(key, out mySecret) == CrestronDataStore.CDS_ERROR.CDS_SUCCESS; + case CrestronDataStore.CDS_ERROR.CDS_SUCCESS: + Debug.LogMessage(LogEventLevel.Verbose, this, "Secret Successfully retrieved for {0}:{1}", Key, key); + return new CrestronSecret(key, mySecret, this); + default: + Debug.LogMessage(LogEventLevel.Information, this, "Unable to retrieve secret for {0}:{1} - {2}", + Key, key, getErrorCode.ToString()); + return null; } } + /// + /// Determine if a secret is present within the provider without retrieving it + /// + /// Secret Key + /// bool if present + public bool TestSecret(string key) + { + string mySecret; + return CrestronDataStoreStatic.GetLocalStringValue(key, out mySecret) == CrestronDataStore.CDS_ERROR.CDS_SUCCESS; + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Secrets/CrestronSecret.cs b/src/PepperDash.Essentials.Core/Secrets/CrestronSecret.cs index 27fbcdad5..1b628a441 100644 --- a/src/PepperDash.Essentials.Core/Secrets/CrestronSecret.cs +++ b/src/PepperDash.Essentials.Core/Secrets/CrestronSecret.cs @@ -4,25 +4,23 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Core -{ - /// - /// Special container class for CrestronSecret provider - /// - public class CrestronSecret : ISecret - { - public ISecretProvider Provider { get; private set; } - public string Key { get; private set; } +namespace PepperDash.Essentials.Core; - public object Value { get; private set; } +/// +/// Special container class for CrestronSecret provider +/// +public class CrestronSecret : ISecret +{ + public ISecretProvider Provider { get; private set; } + public string Key { get; private set; } - public CrestronSecret(string key, string value, ISecretProvider provider) - { - Key = key; - Value = value; - Provider = provider; - } + public object Value { get; private set; } + public CrestronSecret(string key, string value, ISecretProvider provider) + { + Key = key; + Value = value; + Provider = provider; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Secrets/Interfaces.cs b/src/PepperDash.Essentials.Core/Secrets/Interfaces.cs index d2fd750a3..f0b7fd381 100644 --- a/src/PepperDash.Essentials.Core/Secrets/Interfaces.cs +++ b/src/PepperDash.Essentials.Core/Secrets/Interfaces.cs @@ -1,58 +1,57 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// All ISecrecretProvider classes must implement this interface. +/// +public interface ISecretProvider : IKeyed { /// - /// All ISecrecretProvider classes must implement this interface. + /// Set secret value for provider by key + /// + /// key of secret to set + /// value to set secret to + /// + bool SetSecret(string key, object value); + + /// + /// Return object containing secret from provider + /// + /// key of secret to retrieve + /// + ISecret GetSecret(string key); + + /// + /// Verifies presence of secret + /// + /// key of secret to chek + /// + bool TestSecret(string key); + + /// + /// Description of the secrets provider + /// + string Description { get; } +} + +/// +/// interface for delivering secrets in Essentials. +/// +public interface ISecret +{ + /// + /// Instance of ISecretProvider that the secret belongs to + /// + ISecretProvider Provider { get; } + + /// + /// Key of the secret in the provider /// - public interface ISecretProvider : IKeyed - { - /// - /// Set secret value for provider by key - /// - /// key of secret to set - /// value to set secret to - /// - bool SetSecret(string key, object value); - - /// - /// Return object containing secret from provider - /// - /// key of secret to retrieve - /// - ISecret GetSecret(string key); - - /// - /// Verifies presence of secret - /// - /// key of secret to chek - /// - bool TestSecret(string key); - - /// - /// Description of the secrets provider - /// - string Description { get; } - } + string Key { get; } /// - /// interface for delivering secrets in Essentials. + /// Value of the secret /// - public interface ISecret - { - /// - /// Instance of ISecretProvider that the secret belongs to - /// - ISecretProvider Provider { get; } - - /// - /// Key of the secret in the provider - /// - string Key { get; } - - /// - /// Value of the secret - /// - object Value { get; } - } + object Value { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Secrets/SecretsManager.cs b/src/PepperDash.Essentials.Core/Secrets/SecretsManager.cs index 8309b7e98..f66c0c604 100644 --- a/src/PepperDash.Essentials.Core/Secrets/SecretsManager.cs +++ b/src/PepperDash.Essentials.Core/Secrets/SecretsManager.cs @@ -5,372 +5,375 @@ using PepperDash.Core; using Serilog.Events; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public static class SecretsManager { - public static class SecretsManager - { - public static Dictionary Secrets { get; private set; } + public static Dictionary Secrets { get; private set; } - /// - /// Initialize the SecretsManager - /// - public static void Initialize() + /// + /// Initialize the SecretsManager + /// + public static void Initialize() + { + try + { + AddSecretProvider("default", new CrestronLocalSecretsProvider("default")); + + AddSecretProvider("CrestronGlobalSecrets", new CrestronGlobalSecretsProvider("CrestronGlobalSecrets")); + + CrestronConsole.AddNewConsoleCommand(SetSecretProcess, "setsecret", + "Adds secret to secrets provider", + ConsoleAccessLevelEnum.AccessOperator); + + CrestronConsole.AddNewConsoleCommand(UpdateSecretProcess, "updatesecret", + "Updates secret in secrets provider", + ConsoleAccessLevelEnum.AccessAdministrator); + + CrestronConsole.AddNewConsoleCommand(DeleteSecretProcess, "deletesecret", + "Deletes secret from secrest provider", + ConsoleAccessLevelEnum.AccessAdministrator); + + CrestronConsole.AddNewConsoleCommand(ListProviders, "secretproviderlist", + "Return list of all valid secrets providers", + ConsoleAccessLevelEnum.AccessAdministrator); + + CrestronConsole.AddNewConsoleCommand(GetProviderInfo, "secretproviderinfo", + "Return data about secrets provider", + ConsoleAccessLevelEnum.AccessAdministrator); + } + catch (Exception e) { + Debug.LogError(e, "SecretsManager Initialize failed"); + } + } - AddSecretProvider("default", new CrestronLocalSecretsProvider("default")); - - AddSecretProvider("CrestronGlobalSecrets", new CrestronGlobalSecretsProvider("CrestronGlobalSecrets")); - - CrestronConsole.AddNewConsoleCommand(SetSecretProcess, "setsecret", - "Adds secret to secrets provider", - ConsoleAccessLevelEnum.AccessOperator); - - CrestronConsole.AddNewConsoleCommand(UpdateSecretProcess, "updatesecret", - "Updates secret in secrets provider", - ConsoleAccessLevelEnum.AccessAdministrator); - - CrestronConsole.AddNewConsoleCommand(DeleteSecretProcess, "deletesecret", - "Deletes secret from secrest provider", - ConsoleAccessLevelEnum.AccessAdministrator); + static SecretsManager() + { + Secrets = new Dictionary(); + } - CrestronConsole.AddNewConsoleCommand(ListProviders, "secretproviderlist", - "Return list of all valid secrets providers", - ConsoleAccessLevelEnum.AccessAdministrator); + /// + /// Get Secret Provider from dictionary by key + /// + /// Dictionary Key for provider + /// ISecretProvider + public static ISecretProvider GetSecretProviderByKey(string key) + { + ISecretProvider secret; - CrestronConsole.AddNewConsoleCommand(GetProviderInfo, "secretproviderinfo", - "Return data about secrets provider", - ConsoleAccessLevelEnum.AccessAdministrator); - } + Secrets.TryGetValue(key, out secret); - static SecretsManager() + if (secret == null) { - Secrets = new Dictionary(); + Debug.LogMessage(LogEventLevel.Debug, "SecretsManager unable to retrieve SecretProvider with the key '{0}'", key); } + return secret; + } - /// - /// Get Secret Provider from dictionary by key - /// - /// Dictionary Key for provider - /// ISecretProvider - public static ISecretProvider GetSecretProviderByKey(string key) - { - ISecretProvider secret; + public static void GetProviderInfo(string cmd) + { + string response; + var args = cmd.Split(' '); - Secrets.TryGetValue(key, out secret); + if (cmd.Length == 0 || (args.Length == 1 && args[0] == "?")) + { + response = "Returns data about secrets provider. Format 'secretproviderinfo '"; + CrestronConsole.ConsoleCommandResponse(response); + return; - if (secret == null) - { - Debug.LogMessage(LogEventLevel.Debug, "SecretsManager unable to retrieve SecretProvider with the key '{0}'", key); - } - return secret; } - public static void GetProviderInfo(string cmd) + if (args.Length == 1) { - string response; - var args = cmd.Split(' '); + var provider = GetSecretProviderByKey(args[0]); - if (cmd.Length == 0 || (args.Length == 1 && args[0] == "?")) + if (provider == null) { - response = "Returns data about secrets provider. Format 'secretproviderinfo '"; + response = "Invalid secrets provider key"; CrestronConsole.ConsoleCommandResponse(response); return; - } - if (args.Length == 1) - { - var provider = GetSecretProviderByKey(args[0]); - - if (provider == null) - { - response = "Invalid secrets provider key"; - CrestronConsole.ConsoleCommandResponse(response); - return; - } + response = String.Format("{0} : {1}", provider.Key, provider.Description); + CrestronConsole.ConsoleCommandResponse(response); + return; + } - response = String.Format("{0} : {1}", provider.Key, provider.Description); - CrestronConsole.ConsoleCommandResponse(response); - return; - } + response = "Improper number of arguments"; + CrestronConsole.ConsoleCommandResponse(response); - response = "Improper number of arguments"; - CrestronConsole.ConsoleCommandResponse(response); + } - } + /// + /// Console Command that returns all valid secrets in the essentials program. + /// + /// + public static void ListProviders(string cmd) + { + var response = String.Empty; + var args = cmd.Split(' '); - /// - /// Console Command that returns all valid secrets in the essentials program. - /// - /// - public static void ListProviders(string cmd) + if (cmd.Length == 0) { - var response = String.Empty; - var args = cmd.Split(' '); - - if (cmd.Length == 0) + if (Secrets != null && Secrets.Count > 0) { - if (Secrets != null && Secrets.Count > 0) - { - response = Secrets.Aggregate(response, - (current, secretProvider) => current + (secretProvider.Key + "\n\r")); - } - else - { - response = "No Secrets Providers Available"; - } - CrestronConsole.ConsoleCommandResponse(response); - return; - + response = Secrets.Aggregate(response, + (current, secretProvider) => current + (secretProvider.Key + "\n\r")); } - - if (args.Length == 1 && args[0] == "?") + else { - response = "Reports all valid and preset Secret providers"; - CrestronConsole.ConsoleCommandResponse(response); - return; + response = "No Secrets Providers Available"; } + CrestronConsole.ConsoleCommandResponse(response); + return; + } - response = "Improper number of arguments"; + if (args.Length == 1 && args[0] == "?") + { + response = "Reports all valid and preset Secret providers"; CrestronConsole.ConsoleCommandResponse(response); + return; + } + + + response = "Improper number of arguments"; + CrestronConsole.ConsoleCommandResponse(response); + + } + /// + /// Add secret provider to secrets dictionary + /// + /// Key of new entry + /// New Provider Entry + public static void AddSecretProvider(string key, ISecretProvider provider) + { + if (!Secrets.ContainsKey(key)) + { + Secrets.Add(key, provider); + Debug.LogMessage(LogEventLevel.Debug, "Secrets provider '{0}' added to SecretsManager", key); + return; } + Debug.LogMessage(LogEventLevel.Information, "Unable to add Provider '{0}' to Secrets. Provider with that key already exists", key ); + } - /// - /// Add secret provider to secrets dictionary - /// - /// Key of new entry - /// New Provider Entry - public static void AddSecretProvider(string key, ISecretProvider provider) + /// + /// Add secret provider to secrets dictionary, with optional overwrite parameter + /// + /// Key of new entry + /// New provider entry + /// true to overwrite any existing providers in the dictionary + public static void AddSecretProvider(string key, ISecretProvider provider, bool overwrite) + { + if (!Secrets.ContainsKey(key)) { - if (!Secrets.ContainsKey(key)) - { - Secrets.Add(key, provider); - Debug.LogMessage(LogEventLevel.Debug, "Secrets provider '{0}' added to SecretsManager", key); - return; - } - Debug.LogMessage(LogEventLevel.Information, "Unable to add Provider '{0}' to Secrets. Provider with that key already exists", key ); + Secrets.Add(key, provider); + Debug.LogMessage(LogEventLevel.Debug, "Secrets provider '{0}' added to SecretsManager", key); + return; + } + if (overwrite) + { + Secrets.Add(key, provider); + Debug.LogMessage(LogEventLevel.Debug, "Provider with the key '{0}' already exists in secrets. Overwriting with new secrets provider.", key); + return; } + Debug.LogMessage(LogEventLevel.Information, "Unable to add Provider '{0}' to Secrets. Provider with that key already exists", key); + } + + private static void SetSecretProcess(string cmd) + { + string response; + var args = cmd.Split(' '); - /// - /// Add secret provider to secrets dictionary, with optional overwrite parameter - /// - /// Key of new entry - /// New provider entry - /// true to overwrite any existing providers in the dictionary - public static void AddSecretProvider(string key, ISecretProvider provider, bool overwrite) + if (args.Length == 0) { - if (!Secrets.ContainsKey(key)) - { - Secrets.Add(key, provider); - Debug.LogMessage(LogEventLevel.Debug, "Secrets provider '{0}' added to SecretsManager", key); - return; - } - if (overwrite) - { - Secrets.Add(key, provider); - Debug.LogMessage(LogEventLevel.Debug, "Provider with the key '{0}' already exists in secrets. Overwriting with new secrets provider.", key); - return; - } - Debug.LogMessage(LogEventLevel.Information, "Unable to add Provider '{0}' to Secrets. Provider with that key already exists", key); + //some Instructional Text + response = "Adds secrets to secret provider. Format 'setsecret '"; + CrestronConsole.ConsoleCommandResponse(response); + return; } - private static void SetSecretProcess(string cmd) + if (args.Length == 1 && args[0] == "?") { - string response; - var args = cmd.Split(' '); + response = "Adds secrets to secret provider. Format 'setsecret '"; + CrestronConsole.ConsoleCommandResponse(response); + return; + } - if (args.Length == 0) - { - //some Instructional Text - response = "Adds secrets to secret provider. Format 'setsecret '"; - CrestronConsole.ConsoleCommandResponse(response); - return; - } + if (args.Length < 3) + { + response = "Improper number of arguments"; + CrestronConsole.ConsoleCommandResponse(response); + return; - if (args.Length == 1 && args[0] == "?") - { - response = "Adds secrets to secret provider. Format 'setsecret '"; - CrestronConsole.ConsoleCommandResponse(response); - return; - } + } - if (args.Length < 3) - { - response = "Improper number of arguments"; - CrestronConsole.ConsoleCommandResponse(response); - return; + var provider = GetSecretProviderByKey(args[0]); - } + if (provider == null) + { + //someFail + response = "Provider key invalid"; + CrestronConsole.ConsoleCommandResponse(response); + return; - var provider = GetSecretProviderByKey(args[0]); + } - if (provider == null) - { - //someFail - response = "Provider key invalid"; - CrestronConsole.ConsoleCommandResponse(response); - return; + var key = args[1]; + var secret = args[2]; - } + CrestronConsole.ConsoleCommandResponse(SetSecret(provider, key, secret)); + } - var key = args[1]; - var secret = args[2]; + private static void UpdateSecretProcess(string cmd) + { + string response; + var args = cmd.Split(' '); + + if (args.Length == 0) + { + //some Instructional Text + response = "Updates secrets in secret provider. Format 'updatesecret '"; + CrestronConsole.ConsoleCommandResponse(response); + return; - CrestronConsole.ConsoleCommandResponse(SetSecret(provider, key, secret)); } - private static void UpdateSecretProcess(string cmd) + if (args.Length == 1 && args[0] == "?") { - string response; - var args = cmd.Split(' '); + response = "Updates secrets in secret provider. Format 'updatesecret '"; + CrestronConsole.ConsoleCommandResponse(response); + return; + } - if (args.Length == 0) - { - //some Instructional Text - response = "Updates secrets in secret provider. Format 'updatesecret '"; - CrestronConsole.ConsoleCommandResponse(response); - return; - } + if (args.Length < 3) + { + //someFail + response = "Improper number of arguments"; + CrestronConsole.ConsoleCommandResponse(response); + return; - if (args.Length == 1 && args[0] == "?") - { - response = "Updates secrets in secret provider. Format 'updatesecret '"; - CrestronConsole.ConsoleCommandResponse(response); - return; - } + } + var provider = GetSecretProviderByKey(args[0]); - if (args.Length < 3) - { - //someFail - response = "Improper number of arguments"; - CrestronConsole.ConsoleCommandResponse(response); - return; + if (provider == null) + { + //someFail + response = "Provider key invalid"; + CrestronConsole.ConsoleCommandResponse(response); + return; - } + } - var provider = GetSecretProviderByKey(args[0]); + var key = args[1]; + var secret = args[2]; - if (provider == null) - { - //someFail - response = "Provider key invalid"; - CrestronConsole.ConsoleCommandResponse(response); - return; + CrestronConsole.ConsoleCommandResponse(UpdateSecret(provider, key, secret)); - } + } - var key = args[1]; - var secret = args[2]; + private static string UpdateSecret(ISecretProvider provider, string key, string secret) + { + var secretPresent = provider.TestSecret(key); + + Debug.LogMessage(LogEventLevel.Verbose, provider, "SecretsProvider {0} {1} contain a secret entry for {2}", provider.Key, secretPresent ? "does" : "does not", key); + + if (!secretPresent) + return + String.Format( + "Unable to update secret for {0}:{1} - Please use the 'SetSecret' command to modify it"); + var response = provider.SetSecret(key, secret) + ? String.Format( + "Secret successfully set for {0}:{1}", + provider.Key, key) + : String.Format( + "Unable to set secret for {0}:{1}", + provider.Key, key); + return response; + } - CrestronConsole.ConsoleCommandResponse(UpdateSecret(provider, key, secret)); + private static string SetSecret(ISecretProvider provider, string key, string secret) + { + var secretPresent = provider.TestSecret(key); + + Debug.LogMessage(LogEventLevel.Verbose, provider, "SecretsProvider {0} {1} contain a secret entry for {2}", provider.Key, secretPresent ? "does" : "does not", key); + + if (secretPresent) + return + String.Format( + "Unable to set secret for {0}:{1} - Please use the 'UpdateSecret' command to modify it"); + var response = provider.SetSecret(key, secret) + ? String.Format( + "Secret successfully set for {0}:{1}", + provider.Key, key) + : String.Format( + "Unable to set secret for {0}:{1}", + provider.Key, key); + return response; - } + } - private static string UpdateSecret(ISecretProvider provider, string key, string secret) - { - var secretPresent = provider.TestSecret(key); - - Debug.LogMessage(LogEventLevel.Verbose, provider, "SecretsProvider {0} {1} contain a secret entry for {2}", provider.Key, secretPresent ? "does" : "does not", key); - - if (!secretPresent) - return - String.Format( - "Unable to update secret for {0}:{1} - Please use the 'SetSecret' command to modify it"); - var response = provider.SetSecret(key, secret) - ? String.Format( - "Secret successfully set for {0}:{1}", - provider.Key, key) - : String.Format( - "Unable to set secret for {0}:{1}", - provider.Key, key); - return response; - } + private static void DeleteSecretProcess(string cmd) + { + string response; + var args = cmd.Split(' '); - private static string SetSecret(ISecretProvider provider, string key, string secret) + if (args.Length == 0) { - var secretPresent = provider.TestSecret(key); - - Debug.LogMessage(LogEventLevel.Verbose, provider, "SecretsProvider {0} {1} contain a secret entry for {2}", provider.Key, secretPresent ? "does" : "does not", key); - - if (secretPresent) - return - String.Format( - "Unable to set secret for {0}:{1} - Please use the 'UpdateSecret' command to modify it"); - var response = provider.SetSecret(key, secret) - ? String.Format( - "Secret successfully set for {0}:{1}", - provider.Key, key) - : String.Format( - "Unable to set secret for {0}:{1}", - provider.Key, key); - return response; + //some Instructional Text + response = "Deletes secrets in secret provider. Format 'deletesecret '"; + CrestronConsole.ConsoleCommandResponse(response); + return; } - - private static void DeleteSecretProcess(string cmd) + if (args.Length == 1 && args[0] == "?") { - string response; - var args = cmd.Split(' '); - - if (args.Length == 0) - { - //some Instructional Text - response = "Deletes secrets in secret provider. Format 'deletesecret '"; - CrestronConsole.ConsoleCommandResponse(response); - return; - - } - if (args.Length == 1 && args[0] == "?") - { - response = "Deletes secrets in secret provider. Format 'deletesecret '"; - CrestronConsole.ConsoleCommandResponse(response); - return; - } + response = "Deletes secrets in secret provider. Format 'deletesecret '"; + CrestronConsole.ConsoleCommandResponse(response); + return; + } - if (args.Length < 2) - { - //someFail - response = "Improper number of arguments"; - CrestronConsole.ConsoleCommandResponse(response); - return; + if (args.Length < 2) + { + //someFail + response = "Improper number of arguments"; + CrestronConsole.ConsoleCommandResponse(response); + return; - } + } - var provider = GetSecretProviderByKey(args[0]); + var provider = GetSecretProviderByKey(args[0]); - if (provider == null) - { - //someFail - response = "Provider key invalid"; - CrestronConsole.ConsoleCommandResponse(response); - return; + if (provider == null) + { + //someFail + response = "Provider key invalid"; + CrestronConsole.ConsoleCommandResponse(response); + return; - } + } - var key = args[1]; + var key = args[1]; - provider.SetSecret(key, ""); - response = provider.SetSecret(key, "") - ? String.Format( - "Secret successfully deleted for {0}:{1}", - provider.Key, key) - : String.Format( - "Unable to delete secret for {0}:{1}", - provider.Key, key); - CrestronConsole.ConsoleCommandResponse(response); - return; + provider.SetSecret(key, ""); + response = provider.SetSecret(key, "") + ? String.Format( + "Secret successfully deleted for {0}:{1}", + provider.Key, key) + : String.Format( + "Unable to delete secret for {0}:{1}", + provider.Key, key); + CrestronConsole.ConsoleCommandResponse(response); + return; - } } - - } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Secrets/SecretsPropertiesConfig.cs b/src/PepperDash.Essentials.Core/Secrets/SecretsPropertiesConfig.cs index f092d5d3a..b447851a3 100644 --- a/src/PepperDash.Essentials.Core/Secrets/SecretsPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Core/Secrets/SecretsPropertiesConfig.cs @@ -7,16 +7,15 @@ using Crestron.SimplSharp; using Newtonsoft.Json; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +/// +/// Provide a way to easily deserialize into a secret object from config +/// +public class SecretsPropertiesConfig { - /// - /// Provide a way to easily deserialize into a secret object from config - /// - public class SecretsPropertiesConfig - { - [JsonProperty("provider")] - public string Provider { get; set; } - [JsonProperty("key")] - public string Key { get; set; } - } + [JsonProperty("provider")] + public string Provider { get; set; } + [JsonProperty("key")] + public string Key { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Shades/Shade Interfaces.cs b/src/PepperDash.Essentials.Core/Shades/Shade Interfaces.cs index 93fcbc52e..d595e7f02 100644 --- a/src/PepperDash.Essentials.Core/Shades/Shade Interfaces.cs +++ b/src/PepperDash.Essentials.Core/Shades/Shade Interfaces.cs @@ -1,44 +1,44 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.Core.Shades -{ +namespace PepperDash.Essentials.Core.Shades; + /// /// Requirements for an object that contains shades /// - public interface IShades - { - List Shades { get; } - } +public interface IShades +{ + List Shades { get; } +} - /// - /// Requirements for a device that implements basic Open/Close/Stop shade control (Uses 3 relays) - /// - public interface IShadesOpenCloseStop - { - void Open(); - void Close(); - void Stop(); - } +/// +/// Requirements for a device that implements basic Open/Close/Stop shade control (Uses 3 relays) +/// +public interface IShadesOpenCloseStop +{ + void Open(); + void Close(); + void Stop(); +} - public interface IShadesOpenClosePreset : IShadesOpenCloseStop - { - void RecallPreset(uint presetNumber); - void SavePreset(uint presetNumber); - string StopOrPresetButtonLabel { get; } +public interface IShadesOpenClosePreset : IShadesOpenCloseStop +{ + void RecallPreset(uint presetNumber); + void SavePreset(uint presetNumber); + string StopOrPresetButtonLabel { get; } - event EventHandler PresetSaved; - } + event EventHandler PresetSaved; +} - /// - /// Requirements for a shade device that provides raising/lowering feedback - /// - public interface IShadesRaiseLowerFeedback - { +/// +/// Requirements for a shade device that provides raising/lowering feedback +/// +public interface IShadesRaiseLowerFeedback +{ BoolFeedback ShadeIsLoweringFeedback { get; } BoolFeedback ShadeIsRaisingFeedback { get; } - } +} /// /// Requirements for a shade/scene that is open or closed @@ -96,5 +96,4 @@ public interface ICrestronBasicShade : IShadesOpenClosedFeedback, IShadesStopOrMove, IShadesFeedback, IShadesRaiseLowerFeedback { - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Shades/ShadeBase.cs b/src/PepperDash.Essentials.Core/Shades/ShadeBase.cs index c44abac64..fbd630638 100644 --- a/src/PepperDash.Essentials.Core/Shades/ShadeBase.cs +++ b/src/PepperDash.Essentials.Core/Shades/ShadeBase.cs @@ -7,24 +7,23 @@ using PepperDash.Core; using PepperDash.Essentials.Core.CrestronIO; -namespace PepperDash.Essentials.Core.Shades -{ +namespace PepperDash.Essentials.Core.Shades; + - [Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")] - public abstract class ShadeBase : EssentialsDevice, IShadesOpenCloseStop +[Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")] +public abstract class ShadeBase : EssentialsDevice, IShadesOpenCloseStop +{ + public ShadeBase(string key, string name) + : base(key, name) { - public ShadeBase(string key, string name) - : base(key, name) - { - } + } - #region iShadesOpenClose Members + #region iShadesOpenClose Members - public abstract void Open(); - public abstract void Stop(); - public abstract void Close(); + public abstract void Open(); + public abstract void Stop(); + public abstract void Close(); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/SigHelper.cs b/src/PepperDash.Essentials.Core/SigHelper.cs index 863951141..c97b706e4 100644 --- a/src/PepperDash.Essentials.Core/SigHelper.cs +++ b/src/PepperDash.Essentials.Core/SigHelper.cs @@ -7,8 +7,8 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// Helper class for various Sig events /// @@ -68,5 +68,4 @@ public static void Ramp(Sig sig, ushort level, uint time) { sig.CreateRamp(level, time / 10); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectDPad.cs b/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectDPad.cs index 2307be7e9..3dfaff6a2 100644 --- a/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectDPad.cs +++ b/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectDPad.cs @@ -6,8 +6,8 @@ using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; -namespace PepperDash.Essentials.Core.SmartObjects -{ +namespace PepperDash.Essentials.Core.SmartObjects; + public class SmartObjectDPad : SmartObjectHelperBase { public BoolOutputSig SigUp { get { return GetBoolOutputNamed("Up"); } } @@ -20,5 +20,4 @@ public SmartObjectDPad(SmartObject so, bool useUserObjectHandler) : base(so, useUserObjectHandler) { } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectDynamicList.cs b/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectDynamicList.cs index 5d7688033..793fb50d0 100644 --- a/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectDynamicList.cs +++ b/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectDynamicList.cs @@ -10,8 +10,8 @@ using Serilog.Events; -namespace PepperDash.Essentials.Core.SmartObjects -{ +namespace PepperDash.Essentials.Core.SmartObjects; + public class SmartObjectDynamicList : SmartObjectHelperBase { public const string SigNameScrollToItem = "Scroll To Item"; @@ -34,12 +34,12 @@ public ushort Count /// public int MaxCount { get; private set; } - /// - /// Wrapper for smart object - /// - /// - /// True if the standard user object action handler will be used - /// The starting join of the string sigs for the button labels + /// + /// Wrapper for smart object + /// + /// + /// True if the standard user object action handler will be used + /// The starting join of the string sigs for the button labels public SmartObjectDynamicList(SmartObject so, bool useUserObjectHandler, uint nameSigOffset) : base(so, useUserObjectHandler) { try @@ -125,5 +125,4 @@ public void ClearActions() for(ushort i = 1; i <= MaxCount; i++) SmartObject.BooleanOutput[string.Format("Item {0} Pressed", i)].UserObject = null; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectHelperBase.cs b/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectHelperBase.cs index 23bf4530b..ce0354718 100644 --- a/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectHelperBase.cs +++ b/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectHelperBase.cs @@ -9,8 +9,8 @@ using PepperDash.Core; using Serilog.Events; -namespace PepperDash.Essentials.Core.SmartObjects -{ +namespace PepperDash.Essentials.Core.SmartObjects; + public class SmartObjectHelperBase { public SmartObject SmartObject { get; private set; } @@ -36,36 +36,36 @@ public SmartObjectHelperBase(SmartObject so, bool useUserObjectHandler) SmartObject.SigChange -= this.SmartObject_SigChange; } - /// - /// Helper to get a sig name with debugging when fail - /// - /// - /// + /// + /// Helper to get a sig name with debugging when fail + /// + /// + /// public BoolOutputSig GetBoolOutputNamed(string name) { if (SmartObject.BooleanOutput.Contains(name)) return SmartObject.BooleanOutput[name]; - else - Debug.LogMessage(LogEventLevel.Information, "WARNING: Cannot get signal. Smart object {0} on trilist {1:x2} does not contain signal '{2}'", - SmartObject.ID, SmartObject.Device.ID, name); + else + Debug.LogMessage(LogEventLevel.Information, "WARNING: Cannot get signal. Smart object {0} on trilist {1:x2} does not contain signal '{2}'", + SmartObject.ID, SmartObject.Device.ID, name); return null; } - /// - /// Sets action on signal after checking for existence. - /// - /// - /// - public void SetBoolAction(string name, Action a) + /// + /// Sets action on signal after checking for existence. + /// + /// + /// + public void SetBoolAction(string name, Action a) + { + if (SmartObject.BooleanOutput.Contains(name)) + SmartObject.BooleanOutput[name].UserObject = a; + else { - if (SmartObject.BooleanOutput.Contains(name)) - SmartObject.BooleanOutput[name].UserObject = a; - else - { - Debug.LogMessage(LogEventLevel.Information, "WARNING: Cannot set action. Smart object {0} on trilist {1:x2} does not contain signal '{2}'", - SmartObject.ID, SmartObject.Device.ID, name); - } + Debug.LogMessage(LogEventLevel.Information, "WARNING: Cannot set action. Smart object {0} on trilist {1:x2} does not contain signal '{2}'", + SmartObject.ID, SmartObject.Device.ID, name); } + } /// /// Standard Action listener @@ -83,5 +83,4 @@ void SmartObject_SigChange(GenericBase currentDevice, SmartObjectEventArgs args) (uo as Action)(args.Sig.StringValue); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectNumeric.cs b/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectNumeric.cs index 7e5742423..6409a4b39 100644 --- a/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectNumeric.cs +++ b/src/PepperDash.Essentials.Core/SmartObjects/SmartObjectNumeric.cs @@ -6,18 +6,18 @@ using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; -namespace PepperDash.Essentials.Core.SmartObjects -{ +namespace PepperDash.Essentials.Core.SmartObjects; + public class SmartObjectNumeric : SmartObjectHelperBase { - /// - /// Defaults to "Misc_1". The name of the button in VTPro (Usually the text) - /// - public string Misc1SigName { get; set; } - /// - /// Defaults to "Misc_2". The name of the button in VTPro (Usually the text) - /// - public string Misc2SigName { get; set; } + /// + /// Defaults to "Misc_1". The name of the button in VTPro (Usually the text) + /// + public string Misc1SigName { get; set; } + /// + /// Defaults to "Misc_2". The name of the button in VTPro (Usually the text) + /// + public string Misc2SigName { get; set; } public BoolOutputSig Digit1 { get { return GetBoolOutputNamed("1"); } } public BoolOutputSig Digit2 { get { return GetBoolOutputNamed("2"); } } @@ -34,8 +34,7 @@ public class SmartObjectNumeric : SmartObjectHelperBase public SmartObjectNumeric(SmartObject so, bool useUserObjectHandler) : base(so, useUserObjectHandler) { - Misc1SigName = "Misc_1"; - Misc2SigName = "Misc_2"; + Misc1SigName = "Misc_1"; + Misc2SigName = "Misc_2"; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/SmartObjects/SubpageReferencList/SubpageReferenceList.cs b/src/PepperDash.Essentials.Core/SmartObjects/SubpageReferencList/SubpageReferenceList.cs index f92e182b6..0e8751255 100644 --- a/src/PepperDash.Essentials.Core/SmartObjects/SubpageReferencList/SubpageReferenceList.cs +++ b/src/PepperDash.Essentials.Core/SmartObjects/SubpageReferencList/SubpageReferenceList.cs @@ -12,16 +12,16 @@ using Serilog.Events; -namespace PepperDash.Essentials.Core -{ - ////***************************************************************************** - ///// - ///// Base class for all subpage reference list controllers - ///// - //public class SubpageReferenceListController - //{ - // public SubpageReferenceList TheList { get; protected set; } - //} +namespace PepperDash.Essentials.Core; + +////***************************************************************************** +///// +///// Base class for all subpage reference list controllers +///// +//public class SubpageReferenceListController +//{ +// public SubpageReferenceList TheList { get; protected set; } +//} //***************************************************************************** /// @@ -76,7 +76,7 @@ public SubpageReferenceList(BasicTriListWithSmartObject triList, uint smartObjec } else Debug.LogMessage(LogEventLevel.Information, "ERROR: TriList 0x{0:X2} Cannot load smart object {1}. Verify correct SGD file is loaded", - triList.ID, smartObjectId); + triList.ID, smartObjectId); } /// @@ -145,7 +145,7 @@ public BoolOutputSig GetBoolFeedbackSig(uint index, uint sigNum) public UShortOutputSig GetUShortOutputSig(uint index, uint sigNum) { if (sigNum > UShortIncrement) return null; - return SRL.UShortOutput.FirstOrDefault(s => s.Name.Equals(GetUShortOutputSigName(index, sigNum))); + return SRL.UShortOutput.FirstOrDefault(s => s.Name.Equals(GetUShortOutputSigName(index, sigNum))); } /// @@ -160,7 +160,7 @@ public UShortOutputSig GetUShortOutputSig(uint index, uint sigNum) public StringOutputSig GetStringOutputSig(uint index, uint sigNum) { if (sigNum > StringIncrement) return null; - return SRL.StringOutput.FirstOrDefault(s => s.Name.Equals(GetStringOutputSigName(index, sigNum))); + return SRL.StringOutput.FirstOrDefault(s => s.Name.Equals(GetStringOutputSigName(index, sigNum))); } /// @@ -261,5 +261,4 @@ public static void SRL_SigChange(GenericBase currentDevice, SmartObjectEventArgs else if (uo is Action) (uo as Action)(args.Sig.StringValue); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/SmartObjects/SubpageReferencList/SubpageReferenceListItem.cs b/src/PepperDash.Essentials.Core/SmartObjects/SubpageReferencList/SubpageReferenceListItem.cs index 30e15f740..e5c0dc8a8 100644 --- a/src/PepperDash.Essentials.Core/SmartObjects/SubpageReferencList/SubpageReferenceListItem.cs +++ b/src/PepperDash.Essentials.Core/SmartObjects/SubpageReferencList/SubpageReferenceListItem.cs @@ -6,8 +6,8 @@ using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.UI; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public class SubpageReferenceListItem { /// @@ -30,5 +30,4 @@ public virtual void Clear() } public virtual void Refresh() { } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/SomeWebSocketClass.cs b/src/PepperDash.Essentials.Core/SomeWebSocketClass.cs new file mode 100644 index 000000000..b87e87ae8 --- /dev/null +++ b/src/PepperDash.Essentials.Core/SomeWebSocketClass.cs @@ -0,0 +1,37 @@ +using System; +using System.Net.WebSockets; +using System.Threading; +using System.Threading.Tasks; + +public class SomeWebSocketClass +{ + private ClientWebSocket _webSocket; + + public SomeWebSocketClass() + { + _webSocket = new ClientWebSocket(); + } + + public async Task ConnectAsync(Uri uri) + { + await _webSocket.ConnectAsync(uri, CancellationToken.None); + } + + public async Task SendAsync(string message) + { + var buffer = System.Text.Encoding.UTF8.GetBytes(message); + await _webSocket.SendAsync(new ArraySegment(buffer), WebSocketMessageType.Text, true, CancellationToken.None); + } + + public async Task ReceiveAsync() + { + var buffer = new byte[1024]; + var result = await _webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); + return System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count); + } + + public async Task CloseAsync() + { + await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); + } +} diff --git a/src/PepperDash.Essentials.Core/Timers/CountdownTimer.cs b/src/PepperDash.Essentials.Core/Timers/CountdownTimer.cs index cbb470d6d..b44005e35 100644 --- a/src/PepperDash.Essentials.Core/Timers/CountdownTimer.cs +++ b/src/PepperDash.Essentials.Core/Timers/CountdownTimer.cs @@ -7,153 +7,152 @@ using PepperDash.Core; using Serilog.Events; -namespace PepperDash.Essentials.Core -{ - public class SecondsCountdownTimer: IKeyed - { - public event EventHandler HasStarted; - public event EventHandler HasFinished; - public event EventHandler WasCancelled; +namespace PepperDash.Essentials.Core; - public string Key { get; private set; } +public class SecondsCountdownTimer: IKeyed +{ + public event EventHandler HasStarted; + public event EventHandler HasFinished; + public event EventHandler WasCancelled; - public BoolFeedback IsRunningFeedback { get; private set; } - bool _isRunning; + public string Key { get; private set; } - public IntFeedback PercentFeedback { get; private set; } - public StringFeedback TimeRemainingFeedback { get; private set; } + public BoolFeedback IsRunningFeedback { get; private set; } + bool _isRunning; - public IntFeedback SecondsRemainingFeedback { get; private set; } + public IntFeedback PercentFeedback { get; private set; } + public StringFeedback TimeRemainingFeedback { get; private set; } - public bool CountsDown { get; set; } + public IntFeedback SecondsRemainingFeedback { get; private set; } - /// - /// The number of seconds to countdown - /// - public int SecondsToCount { get; set; } - - public DateTime StartTime { get; private set; } - public DateTime FinishTime { get; private set; } - - private CTimer _secondTimer; - - /// - /// Constructor - /// - /// - public SecondsCountdownTimer(string key) - { - Key = key; - IsRunningFeedback = new BoolFeedback(() => _isRunning); + public bool CountsDown { get; set; } - TimeRemainingFeedback = new StringFeedback(() => - { - // Need to handle up and down here. + /// + /// The number of seconds to countdown + /// + public int SecondsToCount { get; set; } + + public DateTime StartTime { get; private set; } + public DateTime FinishTime { get; private set; } - var timeSpan = FinishTime - DateTime.Now; + private CTimer _secondTimer; - Debug.LogMessage(LogEventLevel.Verbose, - "timeSpan.Minutes == {0}, timeSpan.Seconds == {1}, timeSpan.TotalSeconds == {2}", this, - timeSpan.Minutes, timeSpan.Seconds, timeSpan.TotalSeconds); + /// + /// Constructor + /// + /// + public SecondsCountdownTimer(string key) + { + Key = key; + IsRunningFeedback = new BoolFeedback(() => _isRunning); - if (Math.Floor(timeSpan.TotalSeconds) < 60 && Math.Floor(timeSpan.TotalSeconds) >= 0) //ignore milliseconds - { - return String.Format("{0:00}", timeSpan.Seconds); - } + TimeRemainingFeedback = new StringFeedback(() => + { + // Need to handle up and down here. - return Math.Floor(timeSpan.TotalSeconds) < 0 - ? "00" - : String.Format("{0:00}:{1:00}", timeSpan.Minutes, timeSpan.Seconds); - }); + var timeSpan = FinishTime - DateTime.Now; - SecondsRemainingFeedback = new IntFeedback(() => (int)(FinishTime - DateTime.Now).TotalSeconds); + Debug.LogMessage(LogEventLevel.Verbose, + "timeSpan.Minutes == {0}, timeSpan.Seconds == {1}, timeSpan.TotalSeconds == {2}", this, + timeSpan.Minutes, timeSpan.Seconds, timeSpan.TotalSeconds); - PercentFeedback = - new IntFeedback( - () => - (int) - (Math.Floor((FinishTime - DateTime.Now).TotalSeconds)/ - Math.Floor((FinishTime - StartTime).TotalSeconds)*100)); - } + if (Math.Floor(timeSpan.TotalSeconds) < 60 && Math.Floor(timeSpan.TotalSeconds) >= 0) //ignore milliseconds + { + return String.Format("{0:00}", timeSpan.Seconds); + } + + return Math.Floor(timeSpan.TotalSeconds) < 0 + ? "00" + : String.Format("{0:00}:{1:00}", timeSpan.Minutes, timeSpan.Seconds); + }); + + SecondsRemainingFeedback = new IntFeedback(() => (int)(FinishTime - DateTime.Now).TotalSeconds); + + PercentFeedback = + new IntFeedback( + () => + (int) + (Math.Floor((FinishTime - DateTime.Now).TotalSeconds)/ + Math.Floor((FinishTime - StartTime).TotalSeconds)*100)); + } - /// - /// Starts the Timer - /// - public void Start() - { - if (_isRunning) - return; - StartTime = DateTime.Now; - FinishTime = StartTime + TimeSpan.FromSeconds(SecondsToCount); - - if (_secondTimer != null) - _secondTimer.Stop(); - _secondTimer = new CTimer(SecondElapsedTimerCallback, null, 0, 1000); - _isRunning = true; - IsRunningFeedback.FireUpdate(); - - var handler = HasStarted; - if (handler != null) - handler(this, new EventArgs()); - } + /// + /// Starts the Timer + /// + public void Start() + { + if (_isRunning) + return; + StartTime = DateTime.Now; + FinishTime = StartTime + TimeSpan.FromSeconds(SecondsToCount); + + if (_secondTimer != null) + _secondTimer.Stop(); + _secondTimer = new CTimer(SecondElapsedTimerCallback, null, 0, 1000); + _isRunning = true; + IsRunningFeedback.FireUpdate(); + + var handler = HasStarted; + if (handler != null) + handler(this, new EventArgs()); + } - /// - /// Restarts the timer - /// - public void Reset() - { - _isRunning = false; - IsRunningFeedback.FireUpdate(); - Start(); - } + /// + /// Restarts the timer + /// + public void Reset() + { + _isRunning = false; + IsRunningFeedback.FireUpdate(); + Start(); + } - /// - /// Cancels the timer (without triggering it to finish) - /// - public void Cancel() - { - StopHelper(); - - var handler = WasCancelled; - if (handler != null) - handler(this, new EventArgs()); - } + /// + /// Cancels the timer (without triggering it to finish) + /// + public void Cancel() + { + StopHelper(); + + var handler = WasCancelled; + if (handler != null) + handler(this, new EventArgs()); + } - /// - /// Called upon expiration, or calling this will force timer to finish. - /// - public void Finish() - { - StopHelper(); + /// + /// Called upon expiration, or calling this will force timer to finish. + /// + public void Finish() + { + StopHelper(); - var handler = HasFinished; - if (handler != null) - handler(this, new EventArgs()); - } + var handler = HasFinished; + if (handler != null) + handler(this, new EventArgs()); + } - void StopHelper() + void StopHelper() + { + if (_secondTimer != null) { - if (_secondTimer != null) - { - _secondTimer.Stop(); - _secondTimer = null; - } - - _isRunning = false; - IsRunningFeedback.FireUpdate(); + _secondTimer.Stop(); + _secondTimer = null; } - void SecondElapsedTimerCallback(object o) - { - if (DateTime.Now >= FinishTime) - { - Finish(); - return; - } + _isRunning = false; + IsRunningFeedback.FireUpdate(); + } - PercentFeedback.FireUpdate(); - TimeRemainingFeedback.FireUpdate(); - SecondsRemainingFeedback.FireUpdate(); + void SecondElapsedTimerCallback(object o) + { + if (DateTime.Now >= FinishTime) + { + Finish(); + return; } + + PercentFeedback.FireUpdate(); + TimeRemainingFeedback.FireUpdate(); + SecondsRemainingFeedback.FireUpdate(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Timers/RetriggerableTimer.cs b/src/PepperDash.Essentials.Core/Timers/RetriggerableTimer.cs index 968c10bbe..f9f32176e 100644 --- a/src/PepperDash.Essentials.Core/Timers/RetriggerableTimer.cs +++ b/src/PepperDash.Essentials.Core/Timers/RetriggerableTimer.cs @@ -14,167 +14,164 @@ using Serilog.Events; -namespace PepperDash.Essentials.Core.Timers -{ - /// - /// A device that runs a retriggerable timer and can execute actions specified in config - /// - [Description("A retriggerable timer device")] - public class RetriggerableTimer : EssentialsDevice - { - private RetriggerableTimerPropertiesConfig _propertiesConfig; +namespace PepperDash.Essentials.Core.Timers; - private CTimer _timer; - private long _timerIntervalMs; +/// +/// A device that runs a retriggerable timer and can execute actions specified in config +/// +[Description("A retriggerable timer device")] +public class RetriggerableTimer : EssentialsDevice +{ + private RetriggerableTimerPropertiesConfig _propertiesConfig; - public RetriggerableTimer(string key, DeviceConfig config) - : base(key, config.Name) - { - var props = config.Properties.ToObject(); - _propertiesConfig = props; + private CTimer _timer; + private long _timerIntervalMs; - if (_propertiesConfig != null) - { - _timerIntervalMs = _propertiesConfig.TimerIntervalMs; - } - } + public RetriggerableTimer(string key, DeviceConfig config) + : base(key, config.Name) + { + var props = config.Properties.ToObject(); + _propertiesConfig = props; - public override bool CustomActivate() + if (_propertiesConfig != null) { - if (_propertiesConfig.StartTimerOnActivation) - { - StartTimer(); - } - - return base.CustomActivate(); + _timerIntervalMs = _propertiesConfig.TimerIntervalMs; } + } - private void CleanUpTimer() + public override bool CustomActivate() + { + if (_propertiesConfig.StartTimerOnActivation) { - if (_timer != null) - { - _timer.Stop(); - _timer.Dispose(); - } - - _timer = null; + StartTimer(); } - public void StartTimer() - { - CleanUpTimer(); - Debug.LogMessage(LogEventLevel.Information, this, "Starting Timer"); - - _timer = new CTimer(TimerElapsedCallback, GetActionFromConfig(eRetriggerableTimerEvents.Elapsed), _timerIntervalMs, _timerIntervalMs); - } + return base.CustomActivate(); + } - public void StopTimer() + private void CleanUpTimer() + { + if (_timer != null) { - Debug.LogMessage(LogEventLevel.Information, this, "Stopping Timer"); _timer.Stop(); - - ExecuteAction(GetActionFromConfig(eRetriggerableTimerEvents.Stopped)); + _timer.Dispose(); } - private DeviceActionWrapper GetActionFromConfig(eRetriggerableTimerEvents eventType) - { - var action = _propertiesConfig.Events[eRetriggerableTimerEvents.Elapsed]; + _timer = null; + } - if (action != null) - return action; - else return null; - } + public void StartTimer() + { + CleanUpTimer(); + Debug.LogMessage(LogEventLevel.Information, this, "Starting Timer"); - /// - /// Executes the Elapsed action from confing when the timer elapses - /// - /// - private void TimerElapsedCallback(object action) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Timer Elapsed. Executing Action"); - - if (action == null) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Timer elapsed but unable to execute action. Action is null."); - return; - } - - var devAction = action as DeviceActionWrapper; - if (devAction != null) - ExecuteAction(devAction); - else - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Unable to cast action as DeviceActionWrapper. Cannot Execute"); - } + _timer = new CTimer(TimerElapsedCallback, GetActionFromConfig(eRetriggerableTimerEvents.Elapsed), _timerIntervalMs, _timerIntervalMs); + } - } + public void StopTimer() + { + Debug.LogMessage(LogEventLevel.Information, this, "Stopping Timer"); + _timer.Stop(); - private void ExecuteAction(DeviceActionWrapper action) - { - if (action == null) - return; - - try - { - DeviceJsonApi.DoDeviceAction(action); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Error Executing Action: {0}", e); - } - //finally // Not sure this is needed - //{ - // _Timer.Reset(0, _TimerIntervalMs); - //} - } + ExecuteAction(GetActionFromConfig(eRetriggerableTimerEvents.Stopped)); + } + + private DeviceActionWrapper GetActionFromConfig(eRetriggerableTimerEvents eventType) + { + var action = _propertiesConfig.Events[eRetriggerableTimerEvents.Elapsed]; + + if (action != null) + return action; + else return null; } /// - /// Configuration Properties for RetriggerableTimer + /// Executes the Elapsed action from confing when the timer elapses /// - public class RetriggerableTimerPropertiesConfig + /// + private void TimerElapsedCallback(object action) { - [JsonProperty("startTimerOnActivation")] - public bool StartTimerOnActivation { get; set; } - - [JsonProperty("timerIntervalMs")] - public long TimerIntervalMs { get; set; } + Debug.LogMessage(LogEventLevel.Debug, this, "Timer Elapsed. Executing Action"); - [JsonProperty("events")] - public Dictionary Events { get; set; } + if (action == null) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Timer elapsed but unable to execute action. Action is null."); + return; + } - public RetriggerableTimerPropertiesConfig() + var devAction = action as DeviceActionWrapper; + if (devAction != null) + ExecuteAction(devAction); + else { - Events = new Dictionary(); + Debug.LogMessage(LogEventLevel.Verbose, this, "Unable to cast action as DeviceActionWrapper. Cannot Execute"); } - } - /// - /// The set of values describing events on the timer - /// - public enum eRetriggerableTimerEvents - { - Elapsed, - Stopped, } - /// - /// Factory class - /// - public class RetriggerableTimerFactory : EssentialsDeviceFactory + private void ExecuteAction(DeviceActionWrapper action) { - public RetriggerableTimerFactory() + if (action == null) + return; + + try { - TypeNames = new List() { "retriggerabletimer" }; + DeviceJsonApi.DoDeviceAction(action); } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) + catch (Exception e) { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new RetriggerableTimer Device"); - - return new RetriggerableTimer(dc.Key, dc); + Debug.LogMessage(LogEventLevel.Verbose, this, "Error Executing Action: {0}", e); } + //finally // Not sure this is needed + //{ + // _Timer.Reset(0, _TimerIntervalMs); + //} } +} +/// +/// Configuration Properties for RetriggerableTimer +/// +public class RetriggerableTimerPropertiesConfig +{ + [JsonProperty("startTimerOnActivation")] + public bool StartTimerOnActivation { get; set; } + + [JsonProperty("timerIntervalMs")] + public long TimerIntervalMs { get; set; } + + [JsonProperty("events")] + public Dictionary Events { get; set; } + + public RetriggerableTimerPropertiesConfig() + { + Events = new Dictionary(); + } +} + +/// +/// The set of values describing events on the timer +/// +public enum eRetriggerableTimerEvents +{ + Elapsed, + Stopped, +} + +/// +/// Factory class +/// +public class RetriggerableTimerFactory : EssentialsDeviceFactory +{ + public RetriggerableTimerFactory() + { + TypeNames = new List() { "retriggerabletimer" }; + } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new RetriggerableTimer Device"); + + return new RetriggerableTimer(dc.Key, dc); + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Touchpanels/CrestronTouchpanelPropertiesConfig.cs b/src/PepperDash.Essentials.Core/Touchpanels/CrestronTouchpanelPropertiesConfig.cs index aa4dac6de..478869b3e 100644 --- a/src/PepperDash.Essentials.Core/Touchpanels/CrestronTouchpanelPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Core/Touchpanels/CrestronTouchpanelPropertiesConfig.cs @@ -1,91 +1,90 @@ using Newtonsoft.Json; -namespace PepperDash.Essentials.Core -{ - public class CrestronTouchpanelPropertiesConfig - { - [JsonProperty("control")] - public EssentialsControlPropertiesConfig ControlProperties { get; set; } +namespace PepperDash.Essentials.Core; - [JsonProperty("ipId", NullValueHandling = NullValueHandling.Ignore)] - public string IpId { get; set; } +public class CrestronTouchpanelPropertiesConfig +{ + [JsonProperty("control")] + public EssentialsControlPropertiesConfig ControlProperties { get; set; } - [JsonProperty("defaultRoomKey", NullValueHandling = NullValueHandling.Ignore)] - public string DefaultRoomKey { get; set; } - - [JsonProperty("roomListKey", NullValueHandling = NullValueHandling.Ignore)] - public string RoomListKey { get; set; } + [JsonProperty("ipId", NullValueHandling = NullValueHandling.Ignore)] + public string IpId { get; set; } - [JsonProperty("sgdFile", NullValueHandling = NullValueHandling.Ignore)] - public string SgdFile { get; set; } + [JsonProperty("defaultRoomKey", NullValueHandling = NullValueHandling.Ignore)] + public string DefaultRoomKey { get; set; } + + [JsonProperty("roomListKey", NullValueHandling = NullValueHandling.Ignore)] + public string RoomListKey { get; set; } - [JsonProperty("projectName", NullValueHandling = NullValueHandling.Ignore)] - public string ProjectName { get; set; } + [JsonProperty("sgdFile", NullValueHandling = NullValueHandling.Ignore)] + public string SgdFile { get; set; } - [JsonProperty("showVolumeGauge", NullValueHandling = NullValueHandling.Ignore)] - public bool? ShowVolumeGauge { get; set; } + [JsonProperty("projectName", NullValueHandling = NullValueHandling.Ignore)] + public string ProjectName { get; set; } - [JsonProperty("usesSplashPage", NullValueHandling = NullValueHandling.Ignore)] - public bool? UsesSplashPage { get; set; } + [JsonProperty("showVolumeGauge", NullValueHandling = NullValueHandling.Ignore)] + public bool? ShowVolumeGauge { get; set; } - [JsonProperty("showDate", NullValueHandling = NullValueHandling.Ignore)] - public bool? ShowDate { get; set; } + [JsonProperty("usesSplashPage", NullValueHandling = NullValueHandling.Ignore)] + public bool? UsesSplashPage { get; set; } - [JsonProperty("showTime", NullValueHandling = NullValueHandling.Ignore)] - public bool? ShowTime { get; set; } + [JsonProperty("showDate", NullValueHandling = NullValueHandling.Ignore)] + public bool? ShowDate { get; set; } - [JsonProperty("setup", NullValueHandling = NullValueHandling.Ignore)] - public UiSetupPropertiesConfig Setup { get; set; } + [JsonProperty("showTime", NullValueHandling = NullValueHandling.Ignore)] + public bool? ShowTime { get; set; } - [JsonProperty("headerStyle", NullValueHandling = NullValueHandling.Ignore)] - public string HeaderStyle { get; set; } + [JsonProperty("setup", NullValueHandling = NullValueHandling.Ignore)] + public UiSetupPropertiesConfig Setup { get; set; } - [JsonProperty("includeInFusionRoomHealth", NullValueHandling = NullValueHandling.Ignore)] - public bool? IncludeInFusionRoomHealth { get; set; } + [JsonProperty("headerStyle", NullValueHandling = NullValueHandling.Ignore)] + public string HeaderStyle { get; set; } - [JsonProperty("screenSaverTimeoutMin", NullValueHandling = NullValueHandling.Ignore)] - public uint? ScreenSaverTimeoutMin { get; set; } + [JsonProperty("includeInFusionRoomHealth", NullValueHandling = NullValueHandling.Ignore)] + public bool? IncludeInFusionRoomHealth { get; set; } - [JsonProperty("screenSaverMovePositionIntervalMs", NullValueHandling = NullValueHandling.Ignore)] - public uint? ScreenSaverMovePositionIntervalMs { get; set; } + [JsonProperty("screenSaverTimeoutMin", NullValueHandling = NullValueHandling.Ignore)] + public uint? ScreenSaverTimeoutMin { get; set; } + [JsonProperty("screenSaverMovePositionIntervalMs", NullValueHandling = NullValueHandling.Ignore)] + public uint? ScreenSaverMovePositionIntervalMs { get; set; } - /// - /// The count of sources that will trigger the "additional" arrows to show on the SRL. - /// Defaults to 5 - /// - [JsonProperty("sourcesOverflowCount", NullValueHandling = NullValueHandling.Ignore)] - public int? SourcesOverflowCount { get; set; } - public CrestronTouchpanelPropertiesConfig() : this(false) { } + /// + /// The count of sources that will trigger the "additional" arrows to show on the SRL. + /// Defaults to 5 + /// + [JsonProperty("sourcesOverflowCount", NullValueHandling = NullValueHandling.Ignore)] + public int? SourcesOverflowCount { get; set; } - public CrestronTouchpanelPropertiesConfig(bool setDefaultValues = false) - { - if(!setDefaultValues) { return; } - SourcesOverflowCount = 5; - HeaderStyle = Habanero; + public CrestronTouchpanelPropertiesConfig() : this(false) { } - // Default values - ScreenSaverTimeoutMin = 5; - ScreenSaverMovePositionIntervalMs = 15000; - } + public CrestronTouchpanelPropertiesConfig(bool setDefaultValues = false) + { + if(!setDefaultValues) { return; } + SourcesOverflowCount = 5; + HeaderStyle = Habanero; - /// - /// "habanero" - /// - public const string Habanero = "habanero"; - /// - /// "verbose" - /// - public const string Verbose = "verbose"; - } + // Default values + ScreenSaverTimeoutMin = 5; + ScreenSaverMovePositionIntervalMs = 15000; + } /// - /// + /// "habanero" /// - public class UiSetupPropertiesConfig - { - [JsonProperty("isVisible", NullValueHandling = NullValueHandling.Ignore)] - public bool IsVisible { get; set; } - } + public const string Habanero = "habanero"; + /// + /// "verbose" + /// + public const string Verbose = "verbose"; +} + +/// +/// +/// +public class UiSetupPropertiesConfig +{ + [JsonProperty("isVisible", NullValueHandling = NullValueHandling.Ignore)] + public bool IsVisible { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Touchpanels/Interfaces.cs b/src/PepperDash.Essentials.Core/Touchpanels/Interfaces.cs index 946f4f9d8..5a035405b 100644 --- a/src/PepperDash.Essentials.Core/Touchpanels/Interfaces.cs +++ b/src/PepperDash.Essentials.Core/Touchpanels/Interfaces.cs @@ -5,10 +5,9 @@ using Crestron.SimplSharp; using Crestron.SimplSharpPro.DeviceSupport; -namespace PepperDash.Essentials.Core +namespace PepperDash.Essentials.Core; + +public interface IHasBasicTriListWithSmartObject { - public interface IHasBasicTriListWithSmartObject - { - BasicTriListWithSmartObject Panel { get; } - } + BasicTriListWithSmartObject Panel { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Touchpanels/Keyboards/HabaneroKeyboardController.cs b/src/PepperDash.Essentials.Core/Touchpanels/Keyboards/HabaneroKeyboardController.cs index 5e068c120..091eaad8a 100644 --- a/src/PepperDash.Essentials.Core/Touchpanels/Keyboards/HabaneroKeyboardController.cs +++ b/src/PepperDash.Essentials.Core/Touchpanels/Keyboards/HabaneroKeyboardController.cs @@ -5,207 +5,207 @@ using Crestron.SimplSharp; using Crestron.SimplSharpPro.DeviceSupport; -namespace PepperDash.Essentials.Core.Touchpanels.Keyboards +namespace PepperDash.Essentials.Core.Touchpanels.Keyboards; + +public class HabaneroKeyboardController { - public class HabaneroKeyboardController - { - /// - /// Single-key press events, rather than using a built-up text string on the OutputFeedback - /// - public event EventHandler KeyPress; + /// + /// Single-key press events, rather than using a built-up text string on the OutputFeedback + /// + public event EventHandler KeyPress; - public BasicTriList TriList { get; private set; } + public BasicTriList TriList { get; private set; } - public StringFeedback OutputFeedback { get; private set; } + public StringFeedback OutputFeedback { get; private set; } - public bool IsVisible { get; private set; } + public bool IsVisible { get; private set; } - public string DotComButtonString { get; set; } + public string DotComButtonString { get; set; } - public string GoButtonText { get; set; } + public string GoButtonText { get; set; } - public string SecondaryButtonText { get; set; } + public string SecondaryButtonText { get; set; } - public bool GoButtonVisible { get; set; } + public bool GoButtonVisible { get; set; } - public bool SecondaryButtonVisible { get; set; } + public bool SecondaryButtonVisible { get; set; } - int ShiftMode = 0; - - StringBuilder Output; + int ShiftMode = 0; + + StringBuilder Output; - public Action HideAction { get; set; } + public Action HideAction { get; set; } CTimer BackspaceTimer; - /// - /// - /// - /// - public HabaneroKeyboardController(BasicTriList trilist) - { - TriList = trilist; - Output = new StringBuilder(); - OutputFeedback = new StringFeedback(() => Output.ToString()); - DotComButtonString = ".com"; - } + /// + /// + /// + /// + public HabaneroKeyboardController(BasicTriList trilist) + { + TriList = trilist; + Output = new StringBuilder(); + OutputFeedback = new StringFeedback(() => Output.ToString()); + DotComButtonString = ".com"; + } - /// - /// Shows the keyboard and attaches sig handlers in the range of 2901-2969 - /// - public void Show() - { - if (IsVisible) - return; - - TriList.SetSigTrueAction(ClosePressJoin, Hide); - TriList.SetSigTrueAction(GoButtonPressJoin, () => OnKeyPress(KeyboardSpecialKey.GoButton)); - TriList.SetSigTrueAction(SecondaryButtonPressJoin, () => OnKeyPress(KeyboardSpecialKey.SecondaryButton)); - TriList.SetSigTrueAction(2921, () => Press(A(ShiftMode))); - TriList.SetSigTrueAction(2922, () => Press(B(ShiftMode))); - TriList.SetSigTrueAction(2923, () => Press(C(ShiftMode))); - TriList.SetSigTrueAction(2924, () => Press(D(ShiftMode))); - TriList.SetSigTrueAction(2925, () => Press(E(ShiftMode))); - TriList.SetSigTrueAction(2926, () => Press(F(ShiftMode))); - TriList.SetSigTrueAction(2927, () => Press(G(ShiftMode))); - TriList.SetSigTrueAction(2928, () => Press(H(ShiftMode))); - TriList.SetSigTrueAction(2929, () => Press(I(ShiftMode))); - TriList.SetSigTrueAction(2930, () => Press(J(ShiftMode))); - TriList.SetSigTrueAction(2931, () => Press(K(ShiftMode))); - TriList.SetSigTrueAction(2932, () => Press(L(ShiftMode))); - TriList.SetSigTrueAction(2933, () => Press(M(ShiftMode))); - TriList.SetSigTrueAction(2934, () => Press(N(ShiftMode))); - TriList.SetSigTrueAction(2935, () => Press(O(ShiftMode))); - TriList.SetSigTrueAction(2936, () => Press(P(ShiftMode))); - TriList.SetSigTrueAction(2937, () => Press(Q(ShiftMode))); - TriList.SetSigTrueAction(2938, () => Press(R(ShiftMode))); - TriList.SetSigTrueAction(2939, () => Press(S(ShiftMode))); - TriList.SetSigTrueAction(2940, () => Press(T(ShiftMode))); - TriList.SetSigTrueAction(2941, () => Press(U(ShiftMode))); - TriList.SetSigTrueAction(2942, () => Press(V(ShiftMode))); - TriList.SetSigTrueAction(2943, () => Press(W(ShiftMode))); - TriList.SetSigTrueAction(2944, () => Press(X(ShiftMode))); - TriList.SetSigTrueAction(2945, () => Press(Y(ShiftMode))); - TriList.SetSigTrueAction(2946, () => Press(Z(ShiftMode))); - TriList.SetSigTrueAction(2947, () => Press('.')); - TriList.SetSigTrueAction(2948, () => Press('@')); - TriList.SetSigTrueAction(2949, () => Press(' ')); + /// + /// Shows the keyboard and attaches sig handlers in the range of 2901-2969 + /// + public void Show() + { + if (IsVisible) + return; + + TriList.SetSigTrueAction(ClosePressJoin, Hide); + TriList.SetSigTrueAction(GoButtonPressJoin, () => OnKeyPress(KeyboardSpecialKey.GoButton)); + TriList.SetSigTrueAction(SecondaryButtonPressJoin, () => OnKeyPress(KeyboardSpecialKey.SecondaryButton)); + TriList.SetSigTrueAction(2921, () => Press(A(ShiftMode))); + TriList.SetSigTrueAction(2922, () => Press(B(ShiftMode))); + TriList.SetSigTrueAction(2923, () => Press(C(ShiftMode))); + TriList.SetSigTrueAction(2924, () => Press(D(ShiftMode))); + TriList.SetSigTrueAction(2925, () => Press(E(ShiftMode))); + TriList.SetSigTrueAction(2926, () => Press(F(ShiftMode))); + TriList.SetSigTrueAction(2927, () => Press(G(ShiftMode))); + TriList.SetSigTrueAction(2928, () => Press(H(ShiftMode))); + TriList.SetSigTrueAction(2929, () => Press(I(ShiftMode))); + TriList.SetSigTrueAction(2930, () => Press(J(ShiftMode))); + TriList.SetSigTrueAction(2931, () => Press(K(ShiftMode))); + TriList.SetSigTrueAction(2932, () => Press(L(ShiftMode))); + TriList.SetSigTrueAction(2933, () => Press(M(ShiftMode))); + TriList.SetSigTrueAction(2934, () => Press(N(ShiftMode))); + TriList.SetSigTrueAction(2935, () => Press(O(ShiftMode))); + TriList.SetSigTrueAction(2936, () => Press(P(ShiftMode))); + TriList.SetSigTrueAction(2937, () => Press(Q(ShiftMode))); + TriList.SetSigTrueAction(2938, () => Press(R(ShiftMode))); + TriList.SetSigTrueAction(2939, () => Press(S(ShiftMode))); + TriList.SetSigTrueAction(2940, () => Press(T(ShiftMode))); + TriList.SetSigTrueAction(2941, () => Press(U(ShiftMode))); + TriList.SetSigTrueAction(2942, () => Press(V(ShiftMode))); + TriList.SetSigTrueAction(2943, () => Press(W(ShiftMode))); + TriList.SetSigTrueAction(2944, () => Press(X(ShiftMode))); + TriList.SetSigTrueAction(2945, () => Press(Y(ShiftMode))); + TriList.SetSigTrueAction(2946, () => Press(Z(ShiftMode))); + TriList.SetSigTrueAction(2947, () => Press('.')); + TriList.SetSigTrueAction(2948, () => Press('@')); + TriList.SetSigTrueAction(2949, () => Press(' ')); TriList.SetSigHeldAction(2950, 500, StartBackspaceRepeat, StopBackspaceRepeat, Backspace); //TriList.SetSigTrueAction(2950, Backspace); - TriList.SetSigTrueAction(2951, Shift); - TriList.SetSigTrueAction(2952, NumShift); - TriList.SetSigTrueAction(2953, Clear); - TriList.SetSigTrueAction(2954, () => Press(DotComButtonString)); - - TriList.SetBool(GoButtonVisibleJoin, GoButtonVisible); - TriList.SetString(GoButtonTextJoin, GoButtonText); - TriList.SetBool(SecondaryButtonVisibleJoin, SecondaryButtonVisible); - TriList.SetString(SecondaryButtonTextJoin, SecondaryButtonText); + TriList.SetSigTrueAction(2951, Shift); + TriList.SetSigTrueAction(2952, NumShift); + TriList.SetSigTrueAction(2953, Clear); + TriList.SetSigTrueAction(2954, () => Press(DotComButtonString)); + + TriList.SetBool(GoButtonVisibleJoin, GoButtonVisible); + TriList.SetString(GoButtonTextJoin, GoButtonText); + TriList.SetBool(SecondaryButtonVisibleJoin, SecondaryButtonVisible); + TriList.SetString(SecondaryButtonTextJoin, SecondaryButtonText); + + TriList.SetBool(KeyboardVisible, true); + ShowKeys(); + IsVisible = true; + } - TriList.SetBool(KeyboardVisible, true); - ShowKeys(); - IsVisible = true; - } + /// + /// Hides the keyboard and disconnects ALL sig handlers from 2901 - 2969 + /// + public void Hide() + { + if (!IsVisible) + return; - /// - /// Hides the keyboard and disconnects ALL sig handlers from 2901 - 2969 - /// - public void Hide() - { - if (!IsVisible) - return; + for (uint i = 2901; i < 2970; i++) + TriList.ClearBoolSigAction(i); - for (uint i = 2901; i < 2970; i++) - TriList.ClearBoolSigAction(i); + // run attached actions + if(HideAction != null) + HideAction(); - // run attached actions - if(HideAction != null) - HideAction(); + TriList.SetBool(KeyboardVisible, false); + IsVisible = false; + } - TriList.SetBool(KeyboardVisible, false); - IsVisible = false; - } + /// + /// + /// + /// + public void Press(char c) + { + OnKeyPress(c.ToString()); + Output.Append(c); + OutputFeedback.FireUpdate(); + ResetShift(); + } - /// - /// - /// - /// - public void Press(char c) - { - OnKeyPress(c.ToString()); - Output.Append(c); - OutputFeedback.FireUpdate(); - ResetShift(); - } + /// + /// + /// + /// + public void Press(string s) + { + OnKeyPress(s); + Output.Append(s); + OutputFeedback.FireUpdate(); + ResetShift(); + } - /// - /// - /// - /// - public void Press(string s) - { - OnKeyPress(s); - Output.Append(s); - OutputFeedback.FireUpdate(); - ResetShift(); - } + /// + /// + /// + public void EnableGoButton() + { + TriList.SetBool(GoButtonEnableJoin, true); + } - /// - /// - /// - public void EnableGoButton() - { - TriList.SetBool(GoButtonEnableJoin, true); - } + /// + /// + /// + public void DisableGoButton() + { + TriList.SetBool(GoButtonEnableJoin, false); + } - /// - /// - /// - public void DisableGoButton() + void ResetShift() + { + if (ShiftMode == 1) { - TriList.SetBool(GoButtonEnableJoin, false); + ShiftMode = 0; + ShowKeys(); } - - void ResetShift() + else if (ShiftMode == 3) { - if (ShiftMode == 1) - { - ShiftMode = 0; - ShowKeys(); - } - else if (ShiftMode == 3) - { - ShiftMode = 2; - ShowKeys(); - } + ShiftMode = 2; + ShowKeys(); } + } - char A(int i) { return new char[] { 'a', 'A', '?', '?' }[i]; } - char B(int i) { return new char[] { 'b', 'B', ':', ':' }[i]; } - char C(int i) { return new char[] { 'c', 'C', '>', '>' }[i]; } - char D(int i) { return new char[] { 'd', 'D', '_', '_' }[i]; } - char E(int i) { return new char[] { 'e', 'E', '3', '#' }[i]; } - char F(int i) { return new char[] { 'f', 'F', '=', '=' }[i]; } - char G(int i) { return new char[] { 'g', 'G', '+', '+' }[i]; } - char H(int i) { return new char[] { 'h', 'H', '[', '[' }[i]; } - char I(int i) { return new char[] { 'i', 'I', '8', '*' }[i]; } - char J(int i) { return new char[] { 'j', 'J', ']', ']' }[i]; } - char K(int i) { return new char[] { 'k', 'K', '/', '/' }[i]; } - char L(int i) { return new char[] { 'l', 'L', '\\', '\\' }[i]; } - char M(int i) { return new char[] { 'm', 'M', '"', '"' }[i]; } - char N(int i) { return new char[] { 'n', 'N', '\'', '\'' }[i]; } - char O(int i) { return new char[] { 'o', 'O', '9', '(' }[i]; } - char P(int i) { return new char[] { 'p', 'P', '0', ')' }[i]; } - char Q(int i) { return new char[] { 'q', 'Q', '1', '!' }[i]; } - char R(int i) { return new char[] { 'r', 'R', '4', '$' }[i]; } - char S(int i) { return new char[] { 's', 'S', '-', '-' }[i]; } - char T(int i) { return new char[] { 't', 'T', '5', '%' }[i]; } - char U(int i) { return new char[] { 'u', 'U', '7', '&' }[i]; } - char V(int i) { return new char[] { 'v', 'V', ';', ';' }[i]; } - char W(int i) { return new char[] { 'w', 'W', '2', '@' }[i]; } - char X(int i) { return new char[] { 'x', 'X', '<', '<' }[i]; } - char Y(int i) { return new char[] { 'y', 'Y', '6', '^' }[i]; } - char Z(int i) { return new char[] { 'z', 'Z', ',', ',' }[i]; } + char A(int i) { return new char[] { 'a', 'A', '?', '?' }[i]; } + char B(int i) { return new char[] { 'b', 'B', ':', ':' }[i]; } + char C(int i) { return new char[] { 'c', 'C', '>', '>' }[i]; } + char D(int i) { return new char[] { 'd', 'D', '_', '_' }[i]; } + char E(int i) { return new char[] { 'e', 'E', '3', '#' }[i]; } + char F(int i) { return new char[] { 'f', 'F', '=', '=' }[i]; } + char G(int i) { return new char[] { 'g', 'G', '+', '+' }[i]; } + char H(int i) { return new char[] { 'h', 'H', '[', '[' }[i]; } + char I(int i) { return new char[] { 'i', 'I', '8', '*' }[i]; } + char J(int i) { return new char[] { 'j', 'J', ']', ']' }[i]; } + char K(int i) { return new char[] { 'k', 'K', '/', '/' }[i]; } + char L(int i) { return new char[] { 'l', 'L', '\\', '\\' }[i]; } + char M(int i) { return new char[] { 'm', 'M', '"', '"' }[i]; } + char N(int i) { return new char[] { 'n', 'N', '\'', '\'' }[i]; } + char O(int i) { return new char[] { 'o', 'O', '9', '(' }[i]; } + char P(int i) { return new char[] { 'p', 'P', '0', ')' }[i]; } + char Q(int i) { return new char[] { 'q', 'Q', '1', '!' }[i]; } + char R(int i) { return new char[] { 'r', 'R', '4', '$' }[i]; } + char S(int i) { return new char[] { 's', 'S', '-', '-' }[i]; } + char T(int i) { return new char[] { 't', 'T', '5', '%' }[i]; } + char U(int i) { return new char[] { 'u', 'U', '7', '&' }[i]; } + char V(int i) { return new char[] { 'v', 'V', ';', ';' }[i]; } + char W(int i) { return new char[] { 'w', 'W', '2', '@' }[i]; } + char X(int i) { return new char[] { 'x', 'X', '<', '<' }[i]; } + char Y(int i) { return new char[] { 'y', 'Y', '6', '^' }[i]; } + char Z(int i) { return new char[] { 'z', 'Z', ',', ',' }[i]; } /// /// Does what it says @@ -230,207 +230,206 @@ void StopBackspaceRepeat() } } - void Backspace() - { - OnKeyPress(KeyboardSpecialKey.Backspace); - - if (Output.Length > 0) - { - Output.Remove(Output.Length - 1, 1); - OutputFeedback.FireUpdate(); - } - } + void Backspace() + { + OnKeyPress(KeyboardSpecialKey.Backspace); - void Clear() + if (Output.Length > 0) { - OnKeyPress(KeyboardSpecialKey.Clear); - - Output.Remove(0, Output.Length); + Output.Remove(Output.Length - 1, 1); OutputFeedback.FireUpdate(); } + } - /* When in mode 0 (lowercase): - * shift button: up arrow 0 - * numShift button: 123/#$@#$ 0 - * - * - shift --> mode 1 - * - double-tap shift --> caps lock - * - numShift --> mode 2 - * - * mode 1 (uppercase) - * shift button: down arrow 1 - * numShift button: 123/##$# 0 - * - * - shift --> mode 0 - * - numShift --> mode 2 - * - * - Tapping any key will go back to mode 0 - * - * mode 2 (numbers-sym) - * Shift button: #$#$#$ 2 - * numShift: ABC 1 - * - * - shift --> mode 3 - * - double-tap shift --> caps lock - * - numShift --> mode 0 - * - * mode 3 (sym) - * Shift button: 123 3 - * numShift: ABC 1 - * - * - shift --> mode 2 - * - numShift --> mode 0 - * - * - Tapping any key will go back to mode 2 - */ - void Shift() - { - if (ShiftMode == 0) - ShiftMode = 1; - else if (ShiftMode == 1) - ShiftMode = 0; - else if (ShiftMode == 2) - ShiftMode = 3; - else - ShiftMode = 2; - - ShowKeys(); - } - - void NumShift() - { - if (ShiftMode == 0 || ShiftMode == 1) - ShiftMode = 2; - else if (ShiftMode == 2 || ShiftMode == 3) - ShiftMode = 0; - ShowKeys(); - } - - void ShowKeys() - { - TriList.SetString(2921, A(ShiftMode).ToString()); - TriList.SetString(2922, B(ShiftMode).ToString()); - TriList.SetString(2923, C(ShiftMode).ToString()); - TriList.SetString(2924, D(ShiftMode).ToString()); - TriList.SetString(2925, E(ShiftMode).ToString()); - TriList.SetString(2926, F(ShiftMode).ToString()); - TriList.SetString(2927, G(ShiftMode).ToString()); - TriList.SetString(2928, H(ShiftMode).ToString()); - TriList.SetString(2929, I(ShiftMode).ToString()); - TriList.SetString(2930, J(ShiftMode).ToString()); - TriList.SetString(2931, K(ShiftMode).ToString()); - TriList.SetString(2932, L(ShiftMode).ToString()); - TriList.SetString(2933, M(ShiftMode).ToString()); - TriList.SetString(2934, N(ShiftMode).ToString()); - TriList.SetString(2935, O(ShiftMode).ToString()); - TriList.SetString(2936, P(ShiftMode).ToString()); - TriList.SetString(2937, Q(ShiftMode).ToString()); - TriList.SetString(2938, R(ShiftMode).ToString()); - TriList.SetString(2939, S(ShiftMode).ToString()); - TriList.SetString(2940, T(ShiftMode).ToString()); - TriList.SetString(2941, U(ShiftMode).ToString()); - TriList.SetString(2942, V(ShiftMode).ToString()); - TriList.SetString(2943, W(ShiftMode).ToString()); - TriList.SetString(2944, X(ShiftMode).ToString()); - TriList.SetString(2945, Y(ShiftMode).ToString()); - TriList.SetString(2946, Z(ShiftMode).ToString()); - TriList.SetString(2954, DotComButtonString); - - TriList.SetUshort(2951, (ushort)ShiftMode); // 0 = up, 1 = down, 2 = #, 3 = 123 - TriList.SetUshort(2952, (ushort)(ShiftMode < 2 ? 0 : 1)); // 0 = #, 1 = abc - } + void Clear() + { + OnKeyPress(KeyboardSpecialKey.Clear); - /// - /// Event fire helper for text - /// - /// - void OnKeyPress(string text) - { - var handler = KeyPress; - if (handler != null) - KeyPress(this, new KeyboardControllerPressEventArgs(text)); - } + Output.Remove(0, Output.Length); + OutputFeedback.FireUpdate(); + } - /// - /// event helper for special keys - /// - /// - void OnKeyPress(KeyboardSpecialKey key) - { - var handler = KeyPress; - if (handler != null) - KeyPress(this, new KeyboardControllerPressEventArgs(key)); - } + /* When in mode 0 (lowercase): + * shift button: up arrow 0 + * numShift button: 123/#$@#$ 0 + * + * - shift --> mode 1 + * - double-tap shift --> caps lock + * - numShift --> mode 2 + * + * mode 1 (uppercase) + * shift button: down arrow 1 + * numShift button: 123/##$# 0 + * + * - shift --> mode 0 + * - numShift --> mode 2 + * + * - Tapping any key will go back to mode 0 + * + * mode 2 (numbers-sym) + * Shift button: #$#$#$ 2 + * numShift: ABC 1 + * + * - shift --> mode 3 + * - double-tap shift --> caps lock + * - numShift --> mode 0 + * + * mode 3 (sym) + * Shift button: 123 3 + * numShift: ABC 1 + * + * - shift --> mode 2 + * - numShift --> mode 0 + * + * - Tapping any key will go back to mode 2 + */ + void Shift() + { + if (ShiftMode == 0) + ShiftMode = 1; + else if (ShiftMode == 1) + ShiftMode = 0; + else if (ShiftMode == 2) + ShiftMode = 3; + else + ShiftMode = 2; + + ShowKeys(); + } + void NumShift() + { + if (ShiftMode == 0 || ShiftMode == 1) + ShiftMode = 2; + else if (ShiftMode == 2 || ShiftMode == 3) + ShiftMode = 0; + ShowKeys(); + } - /// - /// 2901 - /// - public const uint KeyboardVisible = 2901; - /// - /// 2902 - /// - public const uint ClosePressJoin = 2902; - /// - /// 2903 - /// - public const uint GoButtonPressJoin = 2903; - /// - /// 2903 - /// - public const uint GoButtonTextJoin = 2903; - /// - /// 2904 - /// - public const uint SecondaryButtonPressJoin = 2904; - /// - /// 2904 - /// - public const uint SecondaryButtonTextJoin = 2904; - /// - /// 2905 - /// - public const uint GoButtonVisibleJoin = 2905; - /// - /// 2906 - /// - public const uint SecondaryButtonVisibleJoin = 2906; - /// - /// 2907 - /// - public const uint GoButtonEnableJoin = 2907; - /// - /// 2910 - /// - public const uint ClearPressJoin = 2910; - /// - /// 2911 - /// - public const uint ClearVisibleJoin = 2911; + void ShowKeys() + { + TriList.SetString(2921, A(ShiftMode).ToString()); + TriList.SetString(2922, B(ShiftMode).ToString()); + TriList.SetString(2923, C(ShiftMode).ToString()); + TriList.SetString(2924, D(ShiftMode).ToString()); + TriList.SetString(2925, E(ShiftMode).ToString()); + TriList.SetString(2926, F(ShiftMode).ToString()); + TriList.SetString(2927, G(ShiftMode).ToString()); + TriList.SetString(2928, H(ShiftMode).ToString()); + TriList.SetString(2929, I(ShiftMode).ToString()); + TriList.SetString(2930, J(ShiftMode).ToString()); + TriList.SetString(2931, K(ShiftMode).ToString()); + TriList.SetString(2932, L(ShiftMode).ToString()); + TriList.SetString(2933, M(ShiftMode).ToString()); + TriList.SetString(2934, N(ShiftMode).ToString()); + TriList.SetString(2935, O(ShiftMode).ToString()); + TriList.SetString(2936, P(ShiftMode).ToString()); + TriList.SetString(2937, Q(ShiftMode).ToString()); + TriList.SetString(2938, R(ShiftMode).ToString()); + TriList.SetString(2939, S(ShiftMode).ToString()); + TriList.SetString(2940, T(ShiftMode).ToString()); + TriList.SetString(2941, U(ShiftMode).ToString()); + TriList.SetString(2942, V(ShiftMode).ToString()); + TriList.SetString(2943, W(ShiftMode).ToString()); + TriList.SetString(2944, X(ShiftMode).ToString()); + TriList.SetString(2945, Y(ShiftMode).ToString()); + TriList.SetString(2946, Z(ShiftMode).ToString()); + TriList.SetString(2954, DotComButtonString); + + TriList.SetUshort(2951, (ushort)ShiftMode); // 0 = up, 1 = down, 2 = #, 3 = 123 + TriList.SetUshort(2952, (ushort)(ShiftMode < 2 ? 0 : 1)); // 0 = #, 1 = abc + } + /// + /// Event fire helper for text + /// + /// + void OnKeyPress(string text) + { + var handler = KeyPress; + if (handler != null) + KeyPress(this, new KeyboardControllerPressEventArgs(text)); } /// - /// + /// event helper for special keys /// - public class KeyboardControllerPressEventArgs : EventArgs + /// + void OnKeyPress(KeyboardSpecialKey key) { - public string Text { get; private set; } - public KeyboardSpecialKey SpecialKey { get; private set; } + var handler = KeyPress; + if (handler != null) + KeyPress(this, new KeyboardControllerPressEventArgs(key)); + } - public KeyboardControllerPressEventArgs(string text) - { - Text = text; - } - public KeyboardControllerPressEventArgs(KeyboardSpecialKey key) - { - SpecialKey = key; - } + /// + /// 2901 + /// + public const uint KeyboardVisible = 2901; + /// + /// 2902 + /// + public const uint ClosePressJoin = 2902; + /// + /// 2903 + /// + public const uint GoButtonPressJoin = 2903; + /// + /// 2903 + /// + public const uint GoButtonTextJoin = 2903; + /// + /// 2904 + /// + public const uint SecondaryButtonPressJoin = 2904; + /// + /// 2904 + /// + public const uint SecondaryButtonTextJoin = 2904; + /// + /// 2905 + /// + public const uint GoButtonVisibleJoin = 2905; + /// + /// 2906 + /// + public const uint SecondaryButtonVisibleJoin = 2906; + /// + /// 2907 + /// + public const uint GoButtonEnableJoin = 2907; + /// + /// 2910 + /// + public const uint ClearPressJoin = 2910; + /// + /// 2911 + /// + public const uint ClearVisibleJoin = 2911; + +} + +/// +/// +/// +public class KeyboardControllerPressEventArgs : EventArgs +{ + public string Text { get; private set; } + public KeyboardSpecialKey SpecialKey { get; private set; } + + public KeyboardControllerPressEventArgs(string text) + { + Text = text; } - public enum KeyboardSpecialKey + public KeyboardControllerPressEventArgs(KeyboardSpecialKey key) { - None = 0, Backspace, Clear, GoButton, SecondaryButton + SpecialKey = key; } +} + +public enum KeyboardSpecialKey +{ + None = 0, Backspace, Clear, GoButton, SecondaryButton } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Touchpanels/ModalDialog.cs b/src/PepperDash.Essentials.Core/Touchpanels/ModalDialog.cs index 4dbe7158b..91bde7f5f 100644 --- a/src/PepperDash.Essentials.Core/Touchpanels/ModalDialog.cs +++ b/src/PepperDash.Essentials.Core/Touchpanels/ModalDialog.cs @@ -4,8 +4,8 @@ using PepperDash.Core; using Serilog.Events; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public class ModalDialog { /// @@ -16,10 +16,10 @@ public class ModalDialog /// Bool press 3992 /// public const uint Button2Join = 3992; - /// - /// 3993 - /// - public const uint CancelButtonJoin = 3993; + /// + /// 3993 + /// + public const uint CancelButtonJoin = 3993; /// ///For visibility of single button. Bool feedback 3994 /// @@ -32,10 +32,10 @@ public class ModalDialog /// Shows the timer guage if in use. Bool feedback 3996 /// public const uint TimerVisibleJoin = 3996; - /// - /// Visibility join to show "X" button 3997 - /// - public const uint CancelVisibleJoin = 3997; + /// + /// Visibility join to show "X" button 3997 + /// + public const uint CancelVisibleJoin = 3997; /// /// Shows the modal subpage. Boolean feeback join 3999 /// @@ -44,7 +44,7 @@ public class ModalDialog /// /// The seconds value of the countdown timer. Ushort join 3991 /// - //public const uint TimerSecondsJoin = 3991; + //public const uint TimerSecondsJoin = 3991; /// /// The full ushort value of the countdown timer for a gauge. Ushort join 3992 /// @@ -79,10 +79,10 @@ public bool ModalIsVisible get { return TriList.BooleanInput[ModalVisibleJoin].BoolValue; } } - /// - /// - /// - public bool CanCancel { get; private set; } + /// + /// + /// + public bool CanCancel { get; private set; } BasicTriList TriList; @@ -100,10 +100,10 @@ public ModalDialog(BasicTriList triList) TriList = triList; // Attach actions to buttons - triList.SetSigFalseAction(Button1Join, () => OnModalComplete(1)); + triList.SetSigFalseAction(Button1Join, () => OnModalComplete(1)); triList.SetSigFalseAction(Button2Join, () => OnModalComplete(2)); - triList.SetSigFalseAction(CancelButtonJoin, () => { if (CanCancel) CancelDialog(); }); - CanCancel = true; + triList.SetSigFalseAction(CancelButtonJoin, () => { if (CanCancel) CancelDialog(); }); + CanCancel = true; } /// @@ -148,15 +148,15 @@ public bool PresentModalDialog(uint numberOfButtons, string title, string iconNa TriList.StringInput[Button2TextJoin].StringValue = button2Text; } // Show/hide guage - TriList.BooleanInput[TimerVisibleJoin].BoolValue = showGauge; - - CanCancel = showCancel; - TriList.BooleanInput[CancelVisibleJoin].BoolValue = showCancel; + TriList.BooleanInput[TimerVisibleJoin].BoolValue = showGauge; + + CanCancel = showCancel; + TriList.BooleanInput[CancelVisibleJoin].BoolValue = showCancel; //Reveal and activate TriList.BooleanInput[ModalVisibleJoin].BoolValue = true; - WakePanel(); + WakePanel(); return true; } @@ -164,49 +164,47 @@ public bool PresentModalDialog(uint numberOfButtons, string title, string iconNa return false; } - /// - /// Wakes the panel by turning on the backlight if off - /// - public void WakePanel() + /// + /// Wakes the panel by turning on the backlight if off + /// + public void WakePanel() + { + try + { + var panel = TriList as TswFt5Button; + + if (panel != null && panel.ExtenderSystemReservedSigs.BacklightOffFeedback.BoolValue) + panel.ExtenderSystemReservedSigs.BacklightOn(); + } + catch { - try - { - var panel = TriList as TswFt5Button; - - if (panel != null && panel.ExtenderSystemReservedSigs.BacklightOffFeedback.BoolValue) - panel.ExtenderSystemReservedSigs.BacklightOn(); - } - catch - { - Debug.LogMessage(LogEventLevel.Debug, "Error Waking Panel. Maybe testing with Xpanel?"); - } + Debug.LogMessage(LogEventLevel.Debug, "Error Waking Panel. Maybe testing with Xpanel?"); } + } - /// - /// Hide dialog from elsewhere, fires CompleteAction - /// + /// + /// Hide dialog from elsewhere, fires CompleteAction + /// public void CancelDialog() { - OnModalComplete(0); + OnModalComplete(0); } - /// - /// Hides dialog. Fires no action - /// - public void HideDialog() - { - TriList.BooleanInput[ModalVisibleJoin].BoolValue = false; - } + /// + /// Hides dialog. Fires no action + /// + public void HideDialog() + { + TriList.BooleanInput[ModalVisibleJoin].BoolValue = false; + } // When the modal is cleared or times out, clean up the various bits void OnModalComplete(uint buttonNum) { TriList.BooleanInput[ModalVisibleJoin].BoolValue = false; - var action = ModalCompleteAction; - if (action != null) - action(buttonNum); + var action = ModalCompleteAction; + if (action != null) + action(buttonNum); } - } - -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Touchpanels/Mpc3Touchpanel.cs b/src/PepperDash.Essentials.Core/Touchpanels/Mpc3Touchpanel.cs index 8649d292a..f97b83588 100644 --- a/src/PepperDash.Essentials.Core/Touchpanels/Mpc3Touchpanel.cs +++ b/src/PepperDash.Essentials.Core/Touchpanels/Mpc3Touchpanel.cs @@ -7,8 +7,8 @@ using PepperDash.Core.Logging; using Serilog.Events; -namespace PepperDash.Essentials.Core.Touchpanels -{ +namespace PepperDash.Essentials.Core.Touchpanels; + /// /// A wrapper class for the touchpanel portion of an MPC3 class process to allow for configurable /// behavior of the keybad buttons @@ -75,9 +75,9 @@ public void InitializeButton(string key, KeypadButton config) return; } - TryParseInt(key, out int buttonNumber); + TryParseInt(key, out int buttonNumber); - var buttonEventTypes = config.EventTypes; + var buttonEventTypes = config.EventTypes; BoolOutputSig enabledFb = null; BoolOutputSig disabledFb = null; @@ -161,10 +161,10 @@ public void InitializeButtonFeedback(string key, KeypadButton config) return; } - TryParseInt(key, out int buttonNumber); + TryParseInt(key, out int buttonNumber); - // Link up the button feedbacks to the specified device feedback - var buttonFeedback = config.Feedback; + // Link up the button feedbacks to the specified device feedback + var buttonFeedback = config.Feedback; if (buttonFeedback == null || string.IsNullOrEmpty(buttonFeedback.DeviceKey)) { Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' feedback not configured, skipping.", @@ -176,14 +176,14 @@ public void InitializeButtonFeedback(string key, KeypadButton config) try { - if (!(DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) is Device device)) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' feedback deviceKey '{1}' not found.", - key, buttonFeedback.DeviceKey); - return; - } + if (!(DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) is Device device)) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' feedback deviceKey '{1}' not found.", + key, buttonFeedback.DeviceKey); + return; + } - deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); + deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); if (deviceFeedback == null) { Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' feedbackName property '{1}' not found.", @@ -223,36 +223,36 @@ public void InitializeButtonFeedback(string key, KeypadButton config) var boolFeedback = deviceFeedback as BoolFeedback; - switch (key) - { - case ("power"): - { - boolFeedback?.LinkCrestronFeedback(_touchpanel.FeedbackPower); - break; - } - case ("volumeup"): - case ("volumedown"): - case ("volumefeedback"): - { - if (deviceFeedback is IntFeedback intFeedback) - { - var volumeFeedback = intFeedback; - volumeFeedback.LinkInputSig(_touchpanel.VolumeBargraph); - } - break; - } - case ("mute"): - { - boolFeedback?.LinkCrestronFeedback(_touchpanel.FeedbackMute); - break; - } - default: + switch (key) + { + case ("power"): + { + boolFeedback?.LinkCrestronFeedback(_touchpanel.FeedbackPower); + break; + } + case ("volumeup"): + case ("volumedown"): + case ("volumefeedback"): + { + if (deviceFeedback is IntFeedback intFeedback) { - boolFeedback?.LinkCrestronFeedback(_touchpanel.Feedbacks[(uint)buttonNumber]); - break; + var volumeFeedback = intFeedback; + volumeFeedback.LinkInputSig(_touchpanel.VolumeBargraph); } - } + break; + } + case ("mute"): + { + boolFeedback?.LinkCrestronFeedback(_touchpanel.FeedbackMute); + break; + } + default: + { + boolFeedback?.LinkCrestronFeedback(_touchpanel.Feedbacks[(uint)buttonNumber]); + break; + } } + } /// /// Try parse int helper method @@ -359,5 +359,4 @@ public class KeypadButtonFeedback [JsonProperty("feedbackName")] public string FeedbackName { get; set; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Touchpanels/TriListExtensions.cs b/src/PepperDash.Essentials.Core/Touchpanels/TriListExtensions.cs index bfbb73f00..0d31e44d0 100644 --- a/src/PepperDash.Essentials.Core/Touchpanels/TriListExtensions.cs +++ b/src/PepperDash.Essentials.Core/Touchpanels/TriListExtensions.cs @@ -9,8 +9,8 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// Extensions used for more-clear attachment of Actions to user objects on sigs /// @@ -18,7 +18,7 @@ public static class SigAndTriListExtensions { /// /// Attaches Action to Sig's user object and returns the same Sig. This provides no protection - /// from null sigs + /// from null sigs /// /// The BoolOutputSig to attach the Action to /// An action to run when sig is pressed and when released @@ -64,14 +64,14 @@ public static BoolOutputSig SetSigFalseAction(this BoolOutputSig sig, Action a) return sig.SetBoolSigAction(b => { if (!b) a(); }); } - /// - /// Sets an action to a held sig - /// - /// The sig - public static BoolOutputSig SetSigHeldAction(this BasicTriList tl, uint sigNum, uint heldMs, Action heldAction) - { - return SetSigHeldAction(tl, sigNum, heldMs, heldAction, null); - } + /// + /// Sets an action to a held sig + /// + /// The sig + public static BoolOutputSig SetSigHeldAction(this BasicTriList tl, uint sigNum, uint heldMs, Action heldAction) + { + return SetSigHeldAction(tl, sigNum, heldMs, heldAction, null); + } /// /// Sets an action to a held sig as well as a released-without-hold action @@ -114,14 +114,14 @@ public static BoolOutputSig SetSigHeldAction(this BoolOutputSig sig, uint heldMs } - /// - /// Sets an action to a held sig as well as a released-without-hold action - /// - /// The sig - public static BoolOutputSig SetSigHeldAction(this BasicTriList tl, uint sigNum, uint heldMs, Action heldAction, Action releaseAction) - { + /// + /// Sets an action to a held sig as well as a released-without-hold action + /// + /// The sig + public static BoolOutputSig SetSigHeldAction(this BasicTriList tl, uint sigNum, uint heldMs, Action heldAction, Action releaseAction) + { return tl.BooleanOutput[sigNum].SetSigHeldAction(heldMs, heldAction, null, releaseAction); - } + } /// /// Sets an action to a held sig, an action for the release of hold, as well as a released-without-hold action @@ -206,34 +206,34 @@ public static StringOutputSig ClearStringSigAction(this BasicTriList tl, uint si return ClearSigAction(tl.StringOutput[sigNum]) as StringOutputSig; } - /// - /// Clears all actions on all sigs - /// - public static void ClearAllSigActions(this BasicTriList t1) + /// + /// Clears all actions on all sigs + /// + public static void ClearAllSigActions(this BasicTriList t1) + { + foreach (var sig in t1.BooleanOutput) + { + ClearSigAction(sig); + } + + foreach (var sig in t1.UShortOutput) { - foreach (var sig in t1.BooleanOutput) - { - ClearSigAction(sig); - } - - foreach (var sig in t1.UShortOutput) - { - ClearSigAction(sig); - } - - foreach (var sig in t1.StringOutput) - { - ClearSigAction(sig); - } + ClearSigAction(sig); } - /// - /// Helper method to set the value of a bool Sig on TriList - /// - public static void SetBool(this BasicTriList tl, uint sigNum, bool value) + foreach (var sig in t1.StringOutput) { - tl.BooleanInput[sigNum].BoolValue = value; + ClearSigAction(sig); } + } + + /// + /// Helper method to set the value of a bool Sig on TriList + /// + public static void SetBool(this BasicTriList tl, uint sigNum, bool value) + { + tl.BooleanInput[sigNum].BoolValue = value; + } /// /// Sends an true-false pulse to the sig @@ -256,21 +256,21 @@ public static void PulseBool(this BasicTriList tl, uint sigNum, int ms) tl.BooleanInput[sigNum].Pulse(ms); } - /// - /// Helper method to set the value of a ushort Sig on TriList - /// - public static void SetUshort(this BasicTriList tl, uint sigNum, ushort value) - { - tl.UShortInput[sigNum].UShortValue = value; - } + /// + /// Helper method to set the value of a ushort Sig on TriList + /// + public static void SetUshort(this BasicTriList tl, uint sigNum, ushort value) + { + tl.UShortInput[sigNum].UShortValue = value; + } - /// - /// Helper method to set the value of a string Sig on TriList - /// - public static void SetString(this BasicTriList tl, uint sigNum, string value) - { - tl.StringInput[sigNum].StringValue = value; - } + /// + /// Helper method to set the value of a string Sig on TriList + /// + public static void SetString(this BasicTriList tl, uint sigNum, string value) + { + tl.StringInput[sigNum].StringValue = value; + } public static void SetString(this BasicTriList tl, uint sigNum, string value, eStringEncoding encoding) { @@ -310,5 +310,4 @@ public static string GetString(this BasicTriList tl, uint sigNum) { return tl.StringOutput[sigNum].StringValue; } - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/TriListBridges/HandlerBridge.cs b/src/PepperDash.Essentials.Core/TriListBridges/HandlerBridge.cs index e1a697074..b804c370c 100644 --- a/src/PepperDash.Essentials.Core/TriListBridges/HandlerBridge.cs +++ b/src/PepperDash.Essentials.Core/TriListBridges/HandlerBridge.cs @@ -7,8 +7,8 @@ using Crestron.SimplSharpPro.DeviceSupport; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + public abstract class HandlerBridge { public bool IsAttached { get; protected set; } @@ -22,5 +22,4 @@ public abstract class HandlerBridge /// Removes the handler from the panel's user objects /// public abstract void DetachFromTriListOutputs(); - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/UI PageManagers/BlurayPageManager.cs b/src/PepperDash.Essentials.Core/UI PageManagers/BlurayPageManager.cs index c272a65a0..892027cfa 100644 --- a/src/PepperDash.Essentials.Core/UI PageManagers/BlurayPageManager.cs +++ b/src/PepperDash.Essentials.Core/UI PageManagers/BlurayPageManager.cs @@ -1,8 +1,8 @@ using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core.PageManagers -{ +namespace PepperDash.Essentials.Core.PageManagers; + public class DiscPlayerMediumPageManager : MediumLeftSwitchablePageManager { IDiscPlayerControls Player; @@ -38,5 +38,4 @@ public override void Hide() TriList.BooleanInput[BackingPageJoin].BoolValue = false; TriList.BooleanInput[LeftSubpageJoin].BoolValue = false; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/UI PageManagers/PageManager.cs b/src/PepperDash.Essentials.Core/UI PageManagers/PageManager.cs index 1f261f875..2323f0ce5 100644 --- a/src/PepperDash.Essentials.Core/UI PageManagers/PageManager.cs +++ b/src/PepperDash.Essentials.Core/UI PageManagers/PageManager.cs @@ -2,8 +2,8 @@ using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core.PageManagers -{ +namespace PepperDash.Essentials.Core.PageManagers; + /// /// The PageManager classes are used to bridge a device to subpage /// visibility. @@ -92,5 +92,4 @@ protected uint GetOffsetJoin() { return GetOffsetJoin(DisplayUiType); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/UI PageManagers/SetTopBoxThreePanelPageManager.cs b/src/PepperDash.Essentials.Core/UI PageManagers/SetTopBoxThreePanelPageManager.cs index 539bb9d4e..b47ab2559 100644 --- a/src/PepperDash.Essentials.Core/UI PageManagers/SetTopBoxThreePanelPageManager.cs +++ b/src/PepperDash.Essentials.Core/UI PageManagers/SetTopBoxThreePanelPageManager.cs @@ -7,8 +7,8 @@ using PepperDash.Essentials.Core.Presets; using Serilog.Events; -namespace PepperDash.Essentials.Core.PageManagers -{ +namespace PepperDash.Essentials.Core.PageManagers; + public class ThreePanelPlusOnePageManager : PageManager { protected BasicTriListWithSmartObject TriList; @@ -37,7 +37,7 @@ public class ThreePanelPlusOnePageManager : PageManager public ThreePanelPlusOnePageManager(BasicTriListWithSmartObject trilist) { TriList = trilist; - CurrentVisiblePosition5Item = 1; + CurrentVisiblePosition5Item = 1; } /// @@ -56,8 +56,8 @@ public override void Show() { // Project the joins into corresponding sigs. var fixedSigs = FixedVisibilityJoins.Select(u => TriList.BooleanInput[u]).ToList(); - foreach (var sig in fixedSigs) - sig.BoolValue = true; + foreach (var sig in fixedSigs) + sig.BoolValue = true; if (ShowPosition5Tabs) { @@ -65,32 +65,32 @@ public override void Show() TriList.BooleanInput[Position5SubpageJoins[CurrentVisiblePosition5Item]].BoolValue = true; // hook up tab object var tabSo = TriList.SmartObjects[Position5TabsId]; - tabSo.BooleanOutput["Tab Button 1 Press"].UserObject = new Action(b => { if (!b) ShowTab(1); }); - tabSo.BooleanOutput["Tab Button 2 Press"].UserObject = new Action(b => { if (!b) ShowTab(2); }); - tabSo.SigChange -= tabSo_SigChange; - tabSo.SigChange += tabSo_SigChange; - } + tabSo.BooleanOutput["Tab Button 1 Press"].UserObject = new Action(b => { if (!b) ShowTab(1); }); + tabSo.BooleanOutput["Tab Button 2 Press"].UserObject = new Action(b => { if (!b) ShowTab(2); }); + tabSo.SigChange -= tabSo_SigChange; + tabSo.SigChange += tabSo_SigChange; + } } - void tabSo_SigChange(Crestron.SimplSharpPro.GenericBase currentDevice, Crestron.SimplSharpPro.SmartObjectEventArgs args) - { - var uo = args.Sig.UserObject; - if(uo is Action) - (uo as Action)(args.Sig.BoolValue); - } + void tabSo_SigChange(Crestron.SimplSharpPro.GenericBase currentDevice, Crestron.SimplSharpPro.SmartObjectEventArgs args) + { + var uo = args.Sig.UserObject; + if(uo is Action) + (uo as Action)(args.Sig.BoolValue); + } public override void Hide() { - var fixedSigs = FixedVisibilityJoins.Select(u => TriList.BooleanInput[u]).ToList(); - foreach (var sig in fixedSigs) - sig.BoolValue = false; + var fixedSigs = FixedVisibilityJoins.Select(u => TriList.BooleanInput[u]).ToList(); + foreach (var sig in fixedSigs) + sig.BoolValue = false; if (ShowPosition5Tabs) { - TriList.BooleanInput[Position5SubpageJoins[CurrentVisiblePosition5Item]].BoolValue = false; + TriList.BooleanInput[Position5SubpageJoins[CurrentVisiblePosition5Item]].BoolValue = false; - //var tabSo = TriList.SmartObjects[Position5TabsId]; - //tabSo.BooleanOutput["Tab Button 1 Press"].UserObject = null; - //tabSo.BooleanOutput["Tab Button 2 Press"].UserObject = null; + //var tabSo = TriList.SmartObjects[Position5TabsId]; + //tabSo.BooleanOutput["Tab Button 1 Press"].UserObject = null; + //tabSo.BooleanOutput["Tab Button 2 Press"].UserObject = null; } } @@ -140,37 +140,37 @@ public SetTopBoxThreePanelPageManager(ISetTopBoxControls stb, BasicTriListWithSm bool dvr = stb.HasDvr; bool numbers = stb.HasNumeric; - if (dpad && !preset && !dvr && !numbers) FixedVisibilityJoins = new uint[] { 10031, 10091 }; - else if (!dpad && preset && !dvr && !numbers) FixedVisibilityJoins = new uint[] { 10032, 10091 }; - else if (!dpad && !preset && dvr && !numbers) FixedVisibilityJoins = new uint[] { 10033, 10091 }; - else if (!dpad && !preset && !dvr && numbers) FixedVisibilityJoins = new uint[] { 10034, 10091 }; - - else if (dpad && preset && !dvr && !numbers) FixedVisibilityJoins = new uint[] { 10042, 10021, 10092 }; - else if (dpad && !preset && dvr && !numbers) FixedVisibilityJoins = new uint[] { 10043, 10021, 10092 }; - else if (dpad && !preset && !dvr && numbers) FixedVisibilityJoins = new uint[] { 10044, 10021, 10092 }; - else if (!dpad && preset && dvr && !numbers) FixedVisibilityJoins = new uint[] { 10043, 10022, 10092 }; - else if (!dpad && preset && !dvr && numbers) FixedVisibilityJoins = new uint[] { 10044, 10022, 10092 }; - else if (!dpad && !preset && dvr && numbers) FixedVisibilityJoins = new uint[] { 10044, 10023, 10092 }; - - else if (dpad && preset && dvr && !numbers) FixedVisibilityJoins = new uint[] { 10053, 10032, 10011, 10093 }; - else if (dpad && preset && !dvr && numbers) FixedVisibilityJoins = new uint[] { 10054, 10032, 10011, 10093 }; - else if (dpad && !preset && dvr && numbers) FixedVisibilityJoins = new uint[] { 10054, 10033, 10011, 10093 }; - else if (!dpad && preset && dvr && numbers) FixedVisibilityJoins = new uint[] { 10054, 10033, 10012, 10093 }; - - else if (dpad && preset && dvr && numbers) - { - FixedVisibilityJoins = new uint[] { 10081, 10032, 10011, 10093 }; // special case - ShowPosition5Tabs = true; - } - // Bad config case - else - { - Debug.LogMessage(LogEventLevel.Debug, stb, "WARNING: Not configured to show any UI elements"); - FixedVisibilityJoins = new uint[] { 10091 }; - } + if (dpad && !preset && !dvr && !numbers) FixedVisibilityJoins = new uint[] { 10031, 10091 }; + else if (!dpad && preset && !dvr && !numbers) FixedVisibilityJoins = new uint[] { 10032, 10091 }; + else if (!dpad && !preset && dvr && !numbers) FixedVisibilityJoins = new uint[] { 10033, 10091 }; + else if (!dpad && !preset && !dvr && numbers) FixedVisibilityJoins = new uint[] { 10034, 10091 }; + + else if (dpad && preset && !dvr && !numbers) FixedVisibilityJoins = new uint[] { 10042, 10021, 10092 }; + else if (dpad && !preset && dvr && !numbers) FixedVisibilityJoins = new uint[] { 10043, 10021, 10092 }; + else if (dpad && !preset && !dvr && numbers) FixedVisibilityJoins = new uint[] { 10044, 10021, 10092 }; + else if (!dpad && preset && dvr && !numbers) FixedVisibilityJoins = new uint[] { 10043, 10022, 10092 }; + else if (!dpad && preset && !dvr && numbers) FixedVisibilityJoins = new uint[] { 10044, 10022, 10092 }; + else if (!dpad && !preset && dvr && numbers) FixedVisibilityJoins = new uint[] { 10044, 10023, 10092 }; + + else if (dpad && preset && dvr && !numbers) FixedVisibilityJoins = new uint[] { 10053, 10032, 10011, 10093 }; + else if (dpad && preset && !dvr && numbers) FixedVisibilityJoins = new uint[] { 10054, 10032, 10011, 10093 }; + else if (dpad && !preset && dvr && numbers) FixedVisibilityJoins = new uint[] { 10054, 10033, 10011, 10093 }; + else if (!dpad && preset && dvr && numbers) FixedVisibilityJoins = new uint[] { 10054, 10033, 10012, 10093 }; + + else if (dpad && preset && dvr && numbers) + { + FixedVisibilityJoins = new uint[] { 10081, 10032, 10011, 10093 }; // special case + ShowPosition5Tabs = true; + } + // Bad config case + else + { + Debug.LogMessage(LogEventLevel.Debug, stb, "WARNING: Not configured to show any UI elements"); + FixedVisibilityJoins = new uint[] { 10091 }; + } // Build presets - if (stb.HasPresets && stb.TvPresets != null) + if (stb.HasPresets && stb.TvPresets != null) { PresetsView = new DevicePresetsView(trilist, stb.TvPresets); } @@ -185,9 +185,8 @@ public override void Show() public override void Hide() { - if (PresetsView != null) - PresetsView.Detach(); + if (PresetsView != null) + PresetsView.Detach(); base.Hide(); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/UI PageManagers/SetTopBoxTwoPanelPageManager.cs b/src/PepperDash.Essentials.Core/UI PageManagers/SetTopBoxTwoPanelPageManager.cs index 2797695e1..4a4804229 100644 --- a/src/PepperDash.Essentials.Core/UI PageManagers/SetTopBoxTwoPanelPageManager.cs +++ b/src/PepperDash.Essentials.Core/UI PageManagers/SetTopBoxTwoPanelPageManager.cs @@ -2,8 +2,8 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Presets; -namespace PepperDash.Essentials.Core.PageManagers -{ +namespace PepperDash.Essentials.Core.PageManagers; + /// /// A fixed-layout page manager that expects a DPad on the right, fixed portion of the page, and a two/three /// tab switchable area on the left for presets, numeric and transport controls @@ -56,5 +56,4 @@ public override void Hide() TriList.BooleanInput[BackingPageJoin].BoolValue = false; TriList.BooleanInput[LeftSubpageJoin].BoolValue = false; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/UI PageManagers/SinglePageManager.cs b/src/PepperDash.Essentials.Core/UI PageManagers/SinglePageManager.cs index dd7d605c5..f4d05364c 100644 --- a/src/PepperDash.Essentials.Core/UI PageManagers/SinglePageManager.cs +++ b/src/PepperDash.Essentials.Core/UI PageManagers/SinglePageManager.cs @@ -2,8 +2,8 @@ using Crestron.SimplSharpPro.DeviceSupport; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Core.PageManagers -{ +namespace PepperDash.Essentials.Core.PageManagers; + /// /// A simple class that hides and shows the default subpage for a given source type /// @@ -27,5 +27,4 @@ public override void Hide() { TriList.BooleanInput[BackingPageJoin].BoolValue = false; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/UI/TouchpanelBase.cs b/src/PepperDash.Essentials.Core/UI/TouchpanelBase.cs index 1d83ea5b6..ecc0fdaec 100644 --- a/src/PepperDash.Essentials.Core/UI/TouchpanelBase.cs +++ b/src/PepperDash.Essentials.Core/UI/TouchpanelBase.cs @@ -11,149 +11,149 @@ using Crestron.SimplSharpPro; using Serilog.Events; -namespace PepperDash.Essentials.Core.UI +namespace PepperDash.Essentials.Core.UI; + +public abstract class TouchpanelBase: EssentialsDevice, IHasBasicTriListWithSmartObject { - public abstract class TouchpanelBase: EssentialsDevice, IHasBasicTriListWithSmartObject + protected CrestronTouchpanelPropertiesConfig _config; + public BasicTriListWithSmartObject Panel { get; private set; } + + /// + /// Constructor for use with device Factory. A touch panel device will be created based on the provided IP-ID and the + /// type of the panel. The SGD File path can be specified using the config property, or a default one located in the program directory if none + /// is provided. + /// + /// Essentials Device Key + /// Essentials Device Name + /// Touchpanel Type to build + /// Touchpanel Configuration + /// IP-ID to use for touch panel + protected TouchpanelBase(string key, string name, BasicTriListWithSmartObject panel, CrestronTouchpanelPropertiesConfig config) + :base(key, name) { - protected CrestronTouchpanelPropertiesConfig _config; - public BasicTriListWithSmartObject Panel { get; private set; } - - /// - /// Constructor for use with device Factory. A touch panel device will be created based on the provided IP-ID and the - /// type of the panel. The SGD File path can be specified using the config property, or a default one located in the program directory if none - /// is provided. - /// - /// Essentials Device Key - /// Essentials Device Name - /// Touchpanel Type to build - /// Touchpanel Configuration - /// IP-ID to use for touch panel - protected TouchpanelBase(string key, string name, BasicTriListWithSmartObject panel, CrestronTouchpanelPropertiesConfig config) - :base(key, name) + + if (panel == null) { + Debug.LogMessage(LogEventLevel.Information, this, "Panel is not valid. Touchpanel class WILL NOT work correctly"); + return; + } - if (panel == null) - { - Debug.LogMessage(LogEventLevel.Information, this, "Panel is not valid. Touchpanel class WILL NOT work correctly"); - return; - } + Panel = panel; - Panel = panel; + Panel.SigChange += Panel_SigChange; - Panel.SigChange += Panel_SigChange; + if (Panel is TswFt5ButtonSystem) + { + var tsw = Panel as TswFt5ButtonSystem; + tsw.ExtenderSystemReservedSigs.Use(); + tsw.ExtenderSystemReservedSigs.DeviceExtenderSigChange + += ExtenderSystemReservedSigs_DeviceExtenderSigChange; - if (Panel is TswFt5ButtonSystem) - { - var tsw = Panel as TswFt5ButtonSystem; - tsw.ExtenderSystemReservedSigs.Use(); - tsw.ExtenderSystemReservedSigs.DeviceExtenderSigChange - += ExtenderSystemReservedSigs_DeviceExtenderSigChange; + tsw.ButtonStateChange += Tsw_ButtonStateChange; + } - tsw.ButtonStateChange += Tsw_ButtonStateChange; - } + _config = config; - _config = config; + AddPreActivationAction(() => { + if (Panel.Register() != eDeviceRegistrationUnRegistrationResponse.Success) + Debug.LogMessage(LogEventLevel.Information, this, "WARNING: Registration failed. Continuing, but panel may not function: {0}", Panel.RegistrationFailureReason); - AddPreActivationAction(() => { - if (Panel.Register() != eDeviceRegistrationUnRegistrationResponse.Success) - Debug.LogMessage(LogEventLevel.Information, this, "WARNING: Registration failed. Continuing, but panel may not function: {0}", Panel.RegistrationFailureReason); + // Give up cleanly if SGD is not present. + var sgdName = Global.FilePathPrefix + "sgd" + Global.DirectorySeparator + _config.SgdFile; + if (!File.Exists(sgdName)) + { + Debug.LogMessage(LogEventLevel.Information, this, "Smart object file '{0}' not present in User folder. Looking for embedded file", sgdName); + + sgdName = Global.ApplicationDirectoryPathPrefix + Global.DirectorySeparator + "SGD" + Global.DirectorySeparator + _config.SgdFile; - // Give up cleanly if SGD is not present. - var sgdName = Global.FilePathPrefix + "sgd" + Global.DirectorySeparator + _config.SgdFile; if (!File.Exists(sgdName)) { - Debug.LogMessage(LogEventLevel.Information, this, "Smart object file '{0}' not present in User folder. Looking for embedded file", sgdName); - - sgdName = Global.ApplicationDirectoryPathPrefix + Global.DirectorySeparator + "SGD" + Global.DirectorySeparator + _config.SgdFile; - - if (!File.Exists(sgdName)) - { - Debug.LogMessage(LogEventLevel.Information, this, "Unable to find SGD file '{0}' in User sgd or application SGD folder. Exiting touchpanel load.", sgdName); - return; - } + Debug.LogMessage(LogEventLevel.Information, this, "Unable to find SGD file '{0}' in User sgd or application SGD folder. Exiting touchpanel load.", sgdName); + return; } + } - Panel.LoadSmartObjects(sgdName); - }); + Panel.LoadSmartObjects(sgdName); + }); - AddPostActivationAction(() => + AddPostActivationAction(() => + { + // Check for IEssentialsRoomCombiner in DeviceManager and if found, subscribe to its event + var roomCombiner = DeviceManager.AllDevices.FirstOrDefault((d) => d is IEssentialsRoomCombiner) as IEssentialsRoomCombiner; + + if (roomCombiner != null) { - // Check for IEssentialsRoomCombiner in DeviceManager and if found, subscribe to its event - var roomCombiner = DeviceManager.AllDevices.FirstOrDefault((d) => d is IEssentialsRoomCombiner) as IEssentialsRoomCombiner; + // Subscribe to the even + roomCombiner.RoomCombinationScenarioChanged += new EventHandler(roomCombiner_RoomCombinationScenarioChanged); - if (roomCombiner != null) + // Connect to the initial roomKey + if (roomCombiner.CurrentScenario != null) { - // Subscribe to the even - roomCombiner.RoomCombinationScenarioChanged += new EventHandler(roomCombiner_RoomCombinationScenarioChanged); - - // Connect to the initial roomKey - if (roomCombiner.CurrentScenario != null) - { - // Use the current scenario - DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario); - } - else - { - // Current Scenario not yet set. Use default - SetupPanelDrivers(_config.DefaultRoomKey); - } + // Use the current scenario + DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario); } else { - // No room combiner, use the default key + // Current Scenario not yet set. Use default SetupPanelDrivers(_config.DefaultRoomKey); } - }); - } - - /// - /// Setup Panel operation - /// - /// Room Key for this panel - protected abstract void SetupPanelDrivers(string roomKey); + } + else + { + // No room combiner, use the default key + SetupPanelDrivers(_config.DefaultRoomKey); + } + }); + } + /// + /// Setup Panel operation + /// + /// Room Key for this panel + protected abstract void SetupPanelDrivers(string roomKey); - /// - /// Event handler for System Extender Events - /// - /// - /// - protected abstract void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args); + /// + /// Event handler for System Extender Events + /// + /// + /// + protected abstract void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args); - /// - /// - /// - /// - /// - protected virtual void roomCombiner_RoomCombinationScenarioChanged(object sender, EventArgs e) - { - var roomCombiner = sender as IEssentialsRoomCombiner; - DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario); - } + /// + /// + /// + /// + /// + protected virtual void roomCombiner_RoomCombinationScenarioChanged(object sender, EventArgs e) + { + var roomCombiner = sender as IEssentialsRoomCombiner; - /// - /// Determines the room key to use based on the scenario - /// - /// - protected virtual void DetermineRoomKeyFromScenario(IRoomCombinationScenario scenario) - { - string newRoomKey = null; + DetermineRoomKeyFromScenario(roomCombiner.CurrentScenario); + } - if (scenario.UiMap.ContainsKey(Key)) - { - newRoomKey = scenario.UiMap[Key]; - } - else if (scenario.UiMap.ContainsKey(_config.DefaultRoomKey)) - { - newRoomKey = scenario.UiMap[_config.DefaultRoomKey]; - } + /// + /// Determines the room key to use based on the scenario + /// + /// + protected virtual void DetermineRoomKeyFromScenario(IRoomCombinationScenario scenario) + { + string newRoomKey = null; - SetupPanelDrivers(newRoomKey); + if (scenario.UiMap.ContainsKey(Key)) + { + newRoomKey = scenario.UiMap[Key]; } + else if (scenario.UiMap.ContainsKey(_config.DefaultRoomKey)) + { + newRoomKey = scenario.UiMap[_config.DefaultRoomKey]; + } + + SetupPanelDrivers(newRoomKey); + } - private void Panel_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args) + private void Panel_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args) { Debug.LogMessage(LogEventLevel.Verbose, this, "Sig change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue); var uo = args.Sig.UserObject; @@ -171,5 +171,4 @@ private void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args) if(uo is Action) (uo as Action)(args.Button.State == eButtonState.Pressed); } - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Utilities/ActionSequence.cs b/src/PepperDash.Essentials.Core/Utilities/ActionSequence.cs index 5c519f609..e78dec8af 100644 --- a/src/PepperDash.Essentials.Core/Utilities/ActionSequence.cs +++ b/src/PepperDash.Essentials.Core/Utilities/ActionSequence.cs @@ -14,149 +14,147 @@ using Newtonsoft.Json; using Serilog.Events; -namespace PepperDash.Essentials.Core.Utilities -{ - /// - /// A device that executes a sequence of actions with optional delays between actions - /// - [Description("A device that executes a sequence of actions with optional delays between actions")] - public class ActionSequence : EssentialsDevice - { - private ActionSequencePropertiesConfig _propertiesConfig; +namespace PepperDash.Essentials.Core.Utilities; - private CrestronQueue _actionQueue; +/// +/// A device that executes a sequence of actions with optional delays between actions +/// +[Description("A device that executes a sequence of actions with optional delays between actions")] +public class ActionSequence : EssentialsDevice +{ + private ActionSequencePropertiesConfig _propertiesConfig; - private Thread _worker; + private CrestronQueue _actionQueue; - private bool _allowActionsToExecute; + private Thread _worker; - public ActionSequence(string key, DeviceConfig config) - : base(key, config.Name) - { - var props = config.Properties.ToObject(); - _propertiesConfig = props; + private bool _allowActionsToExecute; - if (_propertiesConfig != null) - { - if (_propertiesConfig.ActionSequence.Count > 0) - { - _actionQueue = new CrestronQueue(_propertiesConfig.ActionSequence.Count); - } - } - } + public ActionSequence(string key, DeviceConfig config) + : base(key, config.Name) + { + var props = config.Properties.ToObject(); + _propertiesConfig = props; - /// - /// Starts executing the sequenced actions - /// - public void StartSequence() + if (_propertiesConfig != null) { - if (_worker !=null && _worker.ThreadState == Thread.eThreadStates.ThreadRunning) + if (_propertiesConfig.ActionSequence.Count > 0) { - Debug.LogMessage(LogEventLevel.Debug, this, "Thread already running. Cannot Start Sequence"); - return; + _actionQueue = new CrestronQueue(_propertiesConfig.ActionSequence.Count); } - - Debug.LogMessage(LogEventLevel.Debug, this, "Starting Action Sequence"); - _allowActionsToExecute = true; - AddActionsToQueue(); - _worker = new Thread(ProcessActions, null, Thread.eThreadStartOptions.Running); - } - - /// - /// Stops executing the sequenced actions - /// - public void StopSequence() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Action Sequence"); - _allowActionsToExecute = false; - _worker.Abort(); } + } - /// - /// Populates the queue from the configuration information - /// - private void AddActionsToQueue() + /// + /// Starts executing the sequenced actions + /// + public void StartSequence() + { + if (_worker !=null && _worker.ThreadState == Thread.eThreadStates.ThreadRunning) { - Debug.LogMessage(LogEventLevel.Debug, this, "Adding {0} actions to queue", _propertiesConfig.ActionSequence.Count); - - for (int i = 0; i < _propertiesConfig.ActionSequence.Count; i++) - { - _actionQueue.Enqueue(_propertiesConfig.ActionSequence[i]); - } + Debug.LogMessage(LogEventLevel.Debug, this, "Thread already running. Cannot Start Sequence"); + return; } - private object ProcessActions(object obj) - { - while (_allowActionsToExecute && _actionQueue.Count > 0) - { - SequencedDeviceActionWrapper action = null; - - action = _actionQueue.Dequeue(); - if (action == null) - break; + Debug.LogMessage(LogEventLevel.Debug, this, "Starting Action Sequence"); + _allowActionsToExecute = true; + AddActionsToQueue(); + _worker = new Thread(ProcessActions, null, Thread.eThreadStartOptions.Running); + } - // Delay before executing - if (action.DelayMs > 0) - Thread.Sleep(action.DelayMs); + /// + /// Stops executing the sequenced actions + /// + public void StopSequence() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Action Sequence"); + _allowActionsToExecute = false; + _worker.Abort(); + } - ExecuteAction(action); - } + /// + /// Populates the queue from the configuration information + /// + private void AddActionsToQueue() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Adding {0} actions to queue", _propertiesConfig.ActionSequence.Count); - return null; + for (int i = 0; i < _propertiesConfig.ActionSequence.Count; i++) + { + _actionQueue.Enqueue(_propertiesConfig.ActionSequence[i]); } + } - private void ExecuteAction(DeviceActionWrapper action) + private object ProcessActions(object obj) + { + while (_allowActionsToExecute && _actionQueue.Count > 0) { + SequencedDeviceActionWrapper action = null; + + action = _actionQueue.Dequeue(); if (action == null) - return; + break; - try - { - DeviceJsonApi.DoDeviceAction(action); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Error Executing Action: {0}", e); - } + // Delay before executing + if (action.DelayMs > 0) + Thread.Sleep(action.DelayMs); + + ExecuteAction(action); } + + return null; } - /// - /// Configuration Properties for ActionSequence - /// - public class ActionSequencePropertiesConfig + private void ExecuteAction(DeviceActionWrapper action) { - [JsonProperty("actionSequence")] - public List ActionSequence { get; set; } + if (action == null) + return; - public ActionSequencePropertiesConfig() + try { - ActionSequence = new List(); + DeviceJsonApi.DoDeviceAction(action); + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Error Executing Action: {0}", e); } } +} + +/// +/// Configuration Properties for ActionSequence +/// +public class ActionSequencePropertiesConfig +{ + [JsonProperty("actionSequence")] + public List ActionSequence { get; set; } - public class SequencedDeviceActionWrapper : DeviceActionWrapper + public ActionSequencePropertiesConfig() { - [JsonProperty("delayMs")] - public int DelayMs { get; set; } + ActionSequence = new List(); } +} - /// - /// Factory class - /// - public class ActionSequenceFactory : EssentialsDeviceFactory +public class SequencedDeviceActionWrapper : DeviceActionWrapper +{ + [JsonProperty("delayMs")] + public int DelayMs { get; set; } +} + +/// +/// Factory class +/// +public class ActionSequenceFactory : EssentialsDeviceFactory +{ + public ActionSequenceFactory() { - public ActionSequenceFactory() - { - TypeNames = new List() { "actionsequence" }; - } + TypeNames = new List() { "actionsequence" }; + } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new ActionSequence Device"); + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new ActionSequence Device"); - return new ActionSequence(dc.Key, dc); - } + return new ActionSequence(dc.Key, dc); } - } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/VideoStatus/VideoStatusOutputs.cs b/src/PepperDash.Essentials.Core/VideoStatus/VideoStatusOutputs.cs index 62d0040ab..c3efc5e25 100644 --- a/src/PepperDash.Essentials.Core/VideoStatus/VideoStatusOutputs.cs +++ b/src/PepperDash.Essentials.Core/VideoStatus/VideoStatusOutputs.cs @@ -6,8 +6,8 @@ using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DM; -namespace PepperDash.Essentials.Core -{ +namespace PepperDash.Essentials.Core; + /// /// Use this class to pass in values to RoutingInputPorts. Unused properties will have default /// funcs assigned to them. @@ -144,5 +144,4 @@ public List ToList() // bool VideoSync { get; } //} - //public delegate void VideoStatusChangeHandler(IBasicVideoStatus device, eVideoStatusChangeType type); -} \ No newline at end of file + //public delegate void VideoStatusChangeHandler(IBasicVideoStatus device, eVideoStatusChangeType type); \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/DebugWebsocketSink.cs b/src/PepperDash.Essentials.Core/Web/DebugWebsocketSink.cs new file mode 100644 index 000000000..e69de29bb diff --git a/src/PepperDash.Essentials.Core/Web/EssentialsWebApi.cs b/src/PepperDash.Essentials.Core/Web/EssentialsWebApi.cs index 94dbf5ad7..84b594e1b 100644 --- a/src/PepperDash.Essentials.Core/Web/EssentialsWebApi.cs +++ b/src/PepperDash.Essentials.Core/Web/EssentialsWebApi.cs @@ -8,8 +8,8 @@ using PepperDash.Essentials.Core.Web.RequestHandlers; using Serilog.Events; -namespace PepperDash.Essentials.Core.Web -{ +namespace PepperDash.Essentials.Core.Web; + public class EssentialsWebApi : EssentialsDevice { private readonly WebApiServer _server; @@ -72,146 +72,146 @@ public EssentialsWebApi(string key, string name, EssentialsWebApiPropertiesConfi private void SetupRoutes() { - var routes = new List + var routes = new List + { + new HttpCwsRoute("versions") + { + Name = "ReportVersions", + RouteHandler = new ReportVersionsRequestHandler() + }, + new HttpCwsRoute("appdebug") + { + Name = "AppDebug", + RouteHandler = new AppDebugRequestHandler() + }, + new HttpCwsRoute("devices") + { + Name = "DevList", + RouteHandler = new DevListRequestHandler() + }, + new HttpCwsRoute("deviceCommands/{deviceKey}") + { + Name = "DevJson", + RouteHandler = new DevJsonRequestHandler() + }, + new HttpCwsRoute("deviceProperties/{deviceKey}") + { + Name = "DevProps", + RouteHandler = new DevPropsRequestHandler() + }, + new HttpCwsRoute("deviceMethods/{deviceKey}") + { + Name = "DevMethods", + RouteHandler = new DevMethodsRequestHandler() + }, + new HttpCwsRoute("deviceFeedbacks/{deviceKey}") + { + Name = "GetFeedbacksForDeviceKey", + RouteHandler = new GetFeedbacksForDeviceRequestHandler() + }, + new HttpCwsRoute("deviceStreamDebug") + { + Name = "SetDeviceStreamDebug", + RouteHandler = new SetDeviceStreamDebugRequestHandler() + }, + new HttpCwsRoute("disableAllStreamDebug") + { + Name = "DisableAllStreamDebug", + RouteHandler = new DisableAllStreamDebugRequestHandler() + }, + new HttpCwsRoute("config") + { + Name = "ShowConfig", + RouteHandler = new ShowConfigRequestHandler() + }, + new HttpCwsRoute("types") + { + Name = "GetTypes", + RouteHandler = new GetTypesRequestHandler() + }, + new HttpCwsRoute("types/{filter}") { - new HttpCwsRoute("versions") - { - Name = "ReportVersions", - RouteHandler = new ReportVersionsRequestHandler() - }, - new HttpCwsRoute("appdebug") - { - Name = "AppDebug", - RouteHandler = new AppDebugRequestHandler() - }, - new HttpCwsRoute("devices") - { - Name = "DevList", - RouteHandler = new DevListRequestHandler() - }, - new HttpCwsRoute("deviceCommands/{deviceKey}") - { - Name = "DevJson", - RouteHandler = new DevJsonRequestHandler() - }, - new HttpCwsRoute("deviceProperties/{deviceKey}") - { - Name = "DevProps", - RouteHandler = new DevPropsRequestHandler() - }, - new HttpCwsRoute("deviceMethods/{deviceKey}") - { - Name = "DevMethods", - RouteHandler = new DevMethodsRequestHandler() - }, - new HttpCwsRoute("deviceFeedbacks/{deviceKey}") - { - Name = "GetFeedbacksForDeviceKey", - RouteHandler = new GetFeedbacksForDeviceRequestHandler() - }, - new HttpCwsRoute("deviceStreamDebug") - { - Name = "SetDeviceStreamDebug", - RouteHandler = new SetDeviceStreamDebugRequestHandler() - }, - new HttpCwsRoute("disableAllStreamDebug") - { - Name = "DisableAllStreamDebug", - RouteHandler = new DisableAllStreamDebugRequestHandler() - }, - new HttpCwsRoute("config") - { - Name = "ShowConfig", - RouteHandler = new ShowConfigRequestHandler() - }, - new HttpCwsRoute("types") - { - Name = "GetTypes", - RouteHandler = new GetTypesRequestHandler() - }, - new HttpCwsRoute("types/{filter}") - { - Name = "GetTypesByFilter", - RouteHandler = new GetTypesByFilterRequestHandler() - }, - new HttpCwsRoute("joinMap/{bridgeKey}") - { - Name = "GetJoinMapsForBridgeKey", - RouteHandler = new GetJoinMapForBridgeKeyRequestHandler() - }, - new HttpCwsRoute("joinMap/{bridgeKey}/{deviceKey}") - { - Name = "GetJoinMapsForDeviceKey", - RouteHandler = new GetJoinMapForDeviceKeyRequestHandler() - }, - new HttpCwsRoute("debugSession") - { - Name = "DebugSession", - RouteHandler = new DebugSessionRequestHandler() - }, - new HttpCwsRoute("doNotLoadConfigOnNextBoot") - { - Name = "DoNotLoadConfigOnNextBoot", - RouteHandler = new DoNotLoadConfigOnNextBootRequestHandler() - }, - new HttpCwsRoute("restartProgram") - { - Name = "Restart Program", - RouteHandler = new RestartProgramRequestHandler() - }, - new HttpCwsRoute("loadConfig") - { - Name = "Load Config", - RouteHandler = new LoadConfigRequestHandler() - }, - new HttpCwsRoute("tielines") - { - Name = "Get TieLines", - RouteHandler = new GetTieLinesRequestHandler() - }, - new HttpCwsRoute("device/{deviceKey}/routingPorts") - { - Name = "Get Routing Ports for a device", - RouteHandler = new GetRoutingPortsHandler() - }, - }; + Name = "GetTypesByFilter", + RouteHandler = new GetTypesByFilterRequestHandler() + }, + new HttpCwsRoute("joinMap/{bridgeKey}") + { + Name = "GetJoinMapsForBridgeKey", + RouteHandler = new GetJoinMapForBridgeKeyRequestHandler() + }, + new HttpCwsRoute("joinMap/{bridgeKey}/{deviceKey}") + { + Name = "GetJoinMapsForDeviceKey", + RouteHandler = new GetJoinMapForDeviceKeyRequestHandler() + }, + new HttpCwsRoute("debugSession") + { + Name = "DebugSession", + RouteHandler = new DebugSessionRequestHandler() + }, + new HttpCwsRoute("doNotLoadConfigOnNextBoot") + { + Name = "DoNotLoadConfigOnNextBoot", + RouteHandler = new DoNotLoadConfigOnNextBootRequestHandler() + }, + new HttpCwsRoute("restartProgram") + { + Name = "Restart Program", + RouteHandler = new RestartProgramRequestHandler() + }, + new HttpCwsRoute("loadConfig") + { + Name = "Load Config", + RouteHandler = new LoadConfigRequestHandler() + }, + new HttpCwsRoute("tielines") + { + Name = "Get TieLines", + RouteHandler = new GetTieLinesRequestHandler() + }, + new HttpCwsRoute("device/{deviceKey}/routingPorts") + { + Name = "Get Routing Ports for a device", + RouteHandler = new GetRoutingPortsHandler() + }, + }; - AddRoute(routes); - } + AddRoute(routes); + } - /// - /// Add a single route to the API. MUST be done during the activation phase - /// - /// - public void AddRoute(HttpCwsRoute route) - { - _server.AddRoute(route); - } + /// + /// Add a single route to the API. MUST be done during the activation phase + /// + /// + public void AddRoute(HttpCwsRoute route) + { + _server.AddRoute(route); + } - /// - /// Add a collection of routes to the API. MUST be done during the activation phase - /// - /// - public void AddRoute(List routes) + /// + /// Add a collection of routes to the API. MUST be done during the activation phase + /// + /// + public void AddRoute(List routes) + { + foreach (var route in routes) { - foreach (var route in routes) - { - AddRoute(route); - } + AddRoute(route); } + } - /// - /// Initializes the CWS class - /// - public override void Initialize() + /// + /// Initializes the CWS class + /// + public override void Initialize() { - AddRoute(new HttpCwsRoute("apiPaths") { - Name = "GetPaths", - RouteHandler = new GetRoutesHandler(_server.GetRouteCollection(), BasePath) - }); + AddRoute(new HttpCwsRoute("apiPaths") { + Name = "GetPaths", + RouteHandler = new GetRoutesHandler(_server.GetRouteCollection(), BasePath) + }); - // If running on an appliance - if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance) + // If running on an appliance + if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance) { /* WEBSERVER [ON | OFF | TIMEOUT | MAXSESSIONSPERUSER ] @@ -253,11 +253,11 @@ public void GetPaths() CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0); var hostname = CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0); + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0); - var path = CrestronEnvironment.DevicePlatform == eDevicePlatform.Server - ? $"https://{hostname}/VirtualControl/Rooms/{InitialParametersClass.RoomId}/cws{BasePath}" - : $"https://{currentIp}/cws{BasePath}"; + var path = CrestronEnvironment.DevicePlatform == eDevicePlatform.Server + ? $"https://{hostname}/VirtualControl/Rooms/{InitialParametersClass.RoomId}/cws{BasePath}" + : $"https://{currentIp}/cws{BasePath}"; Debug.LogMessage(LogEventLevel.Information, this, "Server:{path:l}", path); @@ -274,5 +274,4 @@ public void GetPaths() } Debug.LogMessage(LogEventLevel.Information, this, new string('-', 50)); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/EssentialsWebApiFactory.cs b/src/PepperDash.Essentials.Core/Web/EssentialsWebApiFactory.cs index d0610ede3..d15cbc491 100644 --- a/src/PepperDash.Essentials.Core/Web/EssentialsWebApiFactory.cs +++ b/src/PepperDash.Essentials.Core/Web/EssentialsWebApiFactory.cs @@ -3,8 +3,8 @@ using PepperDash.Essentials.Core.Config; using Serilog.Events; -namespace PepperDash.Essentials.Core.Web -{ +namespace PepperDash.Essentials.Core.Web; + public class EssentialsWebApiFactory : EssentialsDeviceFactory { public EssentialsWebApiFactory() @@ -22,5 +22,4 @@ public override EssentialsDevice BuildDevice(DeviceConfig dc) Debug.LogMessage(LogEventLevel.Debug, "Factory failed to create new Essentials Web API Server"); return null; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/EssentialsWebApiHelpers.cs b/src/PepperDash.Essentials.Core/Web/EssentialsWebApiHelpers.cs index d5f5af36c..14fbd32a4 100644 --- a/src/PepperDash.Essentials.Core/Web/EssentialsWebApiHelpers.cs +++ b/src/PepperDash.Essentials.Core/Web/EssentialsWebApiHelpers.cs @@ -5,8 +5,8 @@ using Crestron.SimplSharp.WebScripting; using PepperDash.Core; -namespace PepperDash.Essentials.Core.Web -{ +namespace PepperDash.Essentials.Core.Web; + public static class EssentialsWebApiHelpers { public static string GetRequestBody(this HttpCwsRequest request) @@ -22,8 +22,8 @@ public static object MapToAssemblyObject(LoadedAssembly assembly) { return new { - assembly.Name, - assembly.Version + assembly.Name, + assembly.Version }; } @@ -31,7 +31,7 @@ public static object MapToDeviceListObject(IKeyed device) { return new { - device.Key, + device.Key, Name = (device is IKeyName) ? (device as IKeyName).Name : "---" @@ -83,5 +83,4 @@ public static object MapDeviceTypeToObject(KeyValuePair @@ -80,7 +80,6 @@ protected override void HandlePost(HttpCwsContext context) public class AppDebug { [JsonProperty("minimumLevel", NullValueHandling = NullValueHandling.Ignore)] - [JsonConverter(typeof(StringEnumConverter))] - public LogEventLevel MinimumLevel { get; set; } - } -} \ No newline at end of file + [JsonConverter(typeof(StringEnumConverter))] + public LogEventLevel MinimumLevel { get; set; } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DebugSessionRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DebugSessionRequestHandler.cs index 80c7bfbeb..7d7e26cbe 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DebugSessionRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DebugSessionRequestHandler.cs @@ -10,88 +10,90 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using PepperDash.Essentials.Core.Web.RequestHandlers; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ - public class DebugSessionRequestHandler : WebApiBaseRequestHandler - { - public DebugSessionRequestHandler() - : base(true) +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + +public class DebugSessionRequestHandler : WebApiBaseRequestHandler +{ + private readonly DebugWebsocketSink _sink = new DebugWebsocketSink(); + + public DebugSessionRequestHandler() + : base(true) + { + } + + /// + /// Gets details for a debug session + /// + /// + protected override void HandleGet(Crestron.SimplSharp.WebScripting.HttpCwsContext context) + { + var routeData = context.Request.RouteData; + if (routeData == null) { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + + return; } - /// - /// Gets details for a debug session - /// - /// - protected override void HandleGet(Crestron.SimplSharp.WebScripting.HttpCwsContext context) + try { - var routeData = context.Request.RouteData; - if (routeData == null) - { - context.Response.StatusCode = 400; - context.Response.StatusDescription = "Bad Request"; - context.Response.End(); + var ip = CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0); - return; - } + var port = 0; - try + if (!_sink.IsRunning) { - var ip = CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0); - - var port = 0; - - if (!Debug.WebsocketSink.IsRunning) - { - Debug.LogMessage(LogEventLevel.Information, "Starting WS Server"); - // Generate a random port within a specified range - port = new Random().Next(65435, 65535); - // Start the WS Server - Debug.WebsocketSink.StartServerAndSetPort(port); - Debug.SetWebSocketMinimumDebugLevel(Serilog.Events.LogEventLevel.Verbose); - } - - var url = Debug.WebsocketSink.Url; - - object data = new - { - url = Debug.WebsocketSink.Url - }; - - Debug.LogMessage(LogEventLevel.Information, "Debug Session URL: {0}", url); - - // Return the port number with the full url of the WS Server - var res = JsonConvert.SerializeObject(data); - - context.Response.ContentType = "application/json"; - context.Response.ContentEncoding = Encoding.UTF8; - context.Response.StatusCode = 200; - context.Response.StatusDescription = "OK"; - context.Response.Write(res, false); - context.Response.End(); + Debug.LogMessage(LogEventLevel.Information, "Starting WS Server"); + // Generate a random port within a specified range + port = new Random().Next(65435, 65535); + // Start the WS Server + _sink.StartServerAndSetPort(port); + Debug.SetWebSocketMinimumDebugLevel(Serilog.Events.LogEventLevel.Verbose); } - catch (Exception e) + + var url = _sink.Url; + + object data = new { - Debug.LogMessage(LogEventLevel.Information, "Error: {0}", e); - } - } + url = _sink.Url + }; - /// - /// Stops a debug session - /// - /// - protected override void HandlePost(HttpCwsContext context) - { - Debug.WebsocketSink.StopServer(); + Debug.LogMessage(LogEventLevel.Information, "Debug Session URL: {0}", url); + + // Return the port number with the full url of the WS Server + var res = JsonConvert.SerializeObject(data); + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = Encoding.UTF8; context.Response.StatusCode = 200; context.Response.StatusDescription = "OK"; + context.Response.Write(res, false); context.Response.End(); - - Debug.LogMessage(LogEventLevel.Information, "Websocket Debug Session Stopped"); } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Information, "Error: {0}", e); + } + } + + /// + /// Stops a debug session + /// + /// + protected override void HandlePost(HttpCwsContext context) + { + _sink.StopServer(); + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.End(); + + Debug.LogMessage(LogEventLevel.Information, "Websocket Debug Session Stopped"); } + } diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DebugWebsocketSink.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DebugWebsocketSink.cs new file mode 100644 index 000000000..34d8b4465 --- /dev/null +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DebugWebsocketSink.cs @@ -0,0 +1,41 @@ +using System; + +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + +public class DebugWebsocketSink +{ + private bool _isRunning; + private string _url; + + public bool IsRunning => _isRunning; + public string Url => _url; + + public void StartServerAndSetPort(int port) + { + try + { + _url = $"ws://localhost:{port}"; + _isRunning = true; + // Implement actual server startup logic here + } + catch (Exception ex) + { + _isRunning = false; + throw new Exception($"Failed to start debug websocket server: {ex.Message}"); + } + } + + public void StopServer() + { + try + { + // Implement actual server shutdown logic here + _isRunning = false; + _url = null; + } + catch (Exception ex) + { + throw new Exception($"Failed to stop debug websocket server: {ex.Message}"); + } + } +} diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DefaultRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DefaultRequestHandler.cs index 3320de7e5..24ad97bc6 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DefaultRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DefaultRequestHandler.cs @@ -1,8 +1,8 @@ using Crestron.SimplSharp.WebScripting; using PepperDash.Core.Web.RequestHandlers; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class DefaultRequestHandler : WebApiBaseRequestHandler { /// @@ -114,5 +114,4 @@ protected override void HandleTrace(HttpCwsContext context) context.Response.StatusDescription = "I'm a teapot"; context.Response.End(); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevJsonRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevJsonRequestHandler.cs index d14ffb835..f0cefb1c5 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevJsonRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevJsonRequestHandler.cs @@ -5,8 +5,8 @@ using PepperDash.Core.Web.RequestHandlers; using Serilog.Events; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class DevJsonRequestHandler : WebApiBaseRequestHandler { /// @@ -26,25 +26,25 @@ public DevJsonRequestHandler() /// protected override void HandlePost(HttpCwsContext context) { - var routeData = context.Request.RouteData; + var routeData = context.Request.RouteData; - if(routeData == null) - { - context.Response.StatusCode = 400; - context.Response.StatusDescription = "Bad Request"; - context.Response.End(); + if(routeData == null) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); - return; - } + return; + } - if(!routeData.Values.TryGetValue("deviceKey", out var deviceKey)) - { - context.Response.StatusCode = 400; - context.Response.StatusDescription = "Bad Request"; - context.Response.End(); + if(!routeData.Values.TryGetValue("deviceKey", out var deviceKey)) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); - return; - } + return; + } if (context.Request.ContentLength < 0) { @@ -68,11 +68,11 @@ protected override void HandlePost(HttpCwsContext context) try { - var daw = new DeviceActionWrapper { DeviceKey = (string) deviceKey}; + var daw = new DeviceActionWrapper { DeviceKey = (string) deviceKey}; - JsonConvert.PopulateObject(data, daw); + JsonConvert.PopulateObject(data, daw); - Debug.LogMessage(LogEventLevel.Verbose, "Device Action Wrapper: {@wrapper}", null, daw); + Debug.LogMessage(LogEventLevel.Verbose, "Device Action Wrapper: {@wrapper}", null, daw); DeviceJsonApi.DoDeviceAction(daw); @@ -86,9 +86,8 @@ protected override void HandlePost(HttpCwsContext context) context.Response.StatusCode = 400; context.Response.StatusDescription = "Bad Request"; - context.Response.Write(JsonConvert.SerializeObject(new { error = ex.Message }), false); + context.Response.Write(JsonConvert.SerializeObject(new { error = ex.Message }), false); context.Response.End(); } } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevListRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevListRequestHandler.cs index a83685fbd..25eca5af4 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevListRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevListRequestHandler.cs @@ -3,8 +3,8 @@ using Newtonsoft.Json; using PepperDash.Core.Web.RequestHandlers; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class DevListRequestHandler : WebApiBaseRequestHandler { /// @@ -47,5 +47,4 @@ protected override void HandleGet(HttpCwsContext context) context.Response.Write(js, false); context.Response.End(); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevMethodsRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevMethodsRequestHandler.cs index 263eb161c..844f9b696 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevMethodsRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevMethodsRequestHandler.cs @@ -4,8 +4,8 @@ using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class DevMethodsRequestHandler : WebApiBaseRequestHandler { /// @@ -25,18 +25,18 @@ public DevMethodsRequestHandler() /// protected override void HandleGet(HttpCwsContext context) { - var routeData = context.Request.RouteData; - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Getting DevMethods: {@routeData}", routeData); - if (routeData == null) - { - context.Response.StatusCode = 400; - context.Response.StatusDescription = "Bad Request"; - context.Response.End(); + var routeData = context.Request.RouteData; + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Getting DevMethods: {@routeData}", routeData); + if (routeData == null) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); - return; - } + return; + } - object deviceObj; + object deviceObj; if (!routeData.Values.TryGetValue("deviceKey", out deviceObj)) { context.Response.StatusCode = 400; @@ -51,13 +51,13 @@ protected override void HandleGet(HttpCwsContext context) if (device == null) { context.Response.StatusCode = 404; - context.Response.StatusDescription = "Device Not Found"; - context.Response.End(); + context.Response.StatusDescription = "Device Not Found"; + context.Response.End(); - return; + return; } - var deviceMethods = DeviceJsonApi.GetMethods(device.Key); + var deviceMethods = DeviceJsonApi.GetMethods(device.Key); if (deviceMethods == null || deviceMethods.ToLower().Contains("no device")) { context.Response.StatusCode = 404; @@ -74,5 +74,4 @@ protected override void HandleGet(HttpCwsContext context) context.Response.Write(deviceMethods, false); context.Response.End(); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevPropsRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevPropsRequestHandler.cs index c00e47c23..1968f0912 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevPropsRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DevPropsRequestHandler.cs @@ -3,8 +3,8 @@ using Newtonsoft.Json; using PepperDash.Core.Web.RequestHandlers; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class DevPropsRequestHandler : WebApiBaseRequestHandler { /// @@ -18,59 +18,58 @@ public DevPropsRequestHandler() { } - /// - /// Handles GET method requests - /// - /// - protected override void HandleGet(HttpCwsContext context) + /// + /// Handles GET method requests + /// + /// + protected override void HandleGet(HttpCwsContext context) + { + var routeData = context.Request.RouteData; + if (routeData == null) { - var routeData = context.Request.RouteData; - if (routeData == null) - { - context.Response.StatusCode = 400; - context.Response.StatusDescription = "Bad Request"; - context.Response.End(); - - return; - } - - object deviceObj; - if (!routeData.Values.TryGetValue("deviceKey", out deviceObj)) - { - context.Response.StatusCode = 400; - context.Response.StatusDescription = "Bad Request"; - context.Response.End(); + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); - return; - } + return; + } - var device = DeviceManager.GetDeviceForKey(deviceObj.ToString()); + object deviceObj; + if (!routeData.Values.TryGetValue("deviceKey", out deviceObj)) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); - if (device == null) - { - context.Response.StatusCode = 404; - context.Response.StatusDescription = "Device Not Found"; - context.Response.End(); + return; + } - return; - } + var device = DeviceManager.GetDeviceForKey(deviceObj.ToString()); - var deviceProperties = DeviceJsonApi.GetProperties(device.Key); - if (deviceProperties == null || deviceProperties.ToLower().Contains("no device")) - { - context.Response.StatusCode = 404; - context.Response.StatusDescription = "Not Found"; - context.Response.End(); + if (device == null) + { + context.Response.StatusCode = 404; + context.Response.StatusDescription = "Device Not Found"; + context.Response.End(); - return; - } + return; + } - context.Response.StatusCode = 200; - context.Response.StatusDescription = "OK"; - context.Response.ContentType = "application/json"; - context.Response.ContentEncoding = Encoding.UTF8; - context.Response.Write(deviceProperties, false); + var deviceProperties = DeviceJsonApi.GetProperties(device.Key); + if (deviceProperties == null || deviceProperties.ToLower().Contains("no device")) + { + context.Response.StatusCode = 404; + context.Response.StatusDescription = "Not Found"; context.Response.End(); + + return; } + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = Encoding.UTF8; + context.Response.Write(deviceProperties, false); + context.Response.End(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs index 0e682d6ca..db40603c6 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DisableAllStreamDebugRequestHandler.cs @@ -1,8 +1,8 @@ using Crestron.SimplSharp.WebScripting; using PepperDash.Core.Web.RequestHandlers; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class DisableAllStreamDebugRequestHandler : WebApiBaseRequestHandler { /// @@ -28,5 +28,4 @@ protected override void HandlePost(HttpCwsContext context) context.Response.StatusDescription = "OK"; context.Response.End(); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DoNotLoadConfigOnNextBootRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DoNotLoadConfigOnNextBootRequestHandler.cs index fdcad73c0..d5dee2ddd 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/DoNotLoadConfigOnNextBootRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/DoNotLoadConfigOnNextBootRequestHandler.cs @@ -3,8 +3,8 @@ using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class DoNotLoadConfigOnNextBootRequestHandler : WebApiBaseRequestHandler { /// @@ -27,7 +27,7 @@ protected override void HandleGet(HttpCwsContext context) var data = new Data { DoNotLoadConfigOnNextBoot = Debug.DoNotLoadConfigOnNextBoot - }; + }; var body = JsonConvert.SerializeObject(data, Formatting.Indented); @@ -80,5 +80,4 @@ public class Data { [JsonProperty("doNotLoadConfigOnNextBoot", NullValueHandling = NullValueHandling.Ignore)] public bool DoNotLoadConfigOnNextBoot { get; set; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs index 5dd5495c0..2cc40c268 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetFeedbacksForDeviceRequestHandler.cs @@ -3,8 +3,8 @@ using Newtonsoft.Json; using PepperDash.Core.Web.RequestHandlers; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class GetFeedbacksForDeviceRequestHandler : WebApiBaseRequestHandler { /// @@ -98,5 +98,4 @@ from feedback in device.Feedbacks.OfType() context.Response.Write(js, false); context.Response.End(); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs index f2362f4b7..2504d3d97 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetJoinMapForBridgeKeyRequestHandler.cs @@ -4,8 +4,8 @@ using PepperDash.Core.Web.RequestHandlers; using PepperDash.Essentials.Core.Bridges; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class GetJoinMapForBridgeKeyRequestHandler : WebApiBaseRequestHandler { /// @@ -74,5 +74,4 @@ protected override void HandleGet(HttpCwsContext context) context.Response.Write(js, false); context.Response.End(); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs index 6c6691891..228d6c2e9 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetJoinMapForDeviceKeyRequestHandler.cs @@ -3,8 +3,8 @@ using PepperDash.Core.Web.RequestHandlers; using PepperDash.Essentials.Core.Bridges; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class GetJoinMapForDeviceKeyRequestHandler : WebApiBaseRequestHandler { /// @@ -91,5 +91,4 @@ protected override void HandleGet(HttpCwsContext context) context.Response.Write(js, false); context.Response.End(); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetRoutesHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetRoutesHandler.cs index 2ba9cb337..c86777b37 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetRoutesHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetRoutesHandler.cs @@ -3,50 +3,49 @@ using Newtonsoft.Json; using PepperDash.Core.Web.RequestHandlers; -namespace PepperDash.Essentials.Core.Web.RequestHandlers +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + +public class GetRoutesHandler:WebApiBaseRequestHandler { - public class GetRoutesHandler:WebApiBaseRequestHandler + private HttpCwsRouteCollection routeCollection; + private string basePath; + + public GetRoutesHandler(HttpCwsRouteCollection routeCollection, string basePath) { + this.routeCollection = routeCollection; + this.basePath = basePath; + } + + protected override void HandleGet(HttpCwsContext context) { - private HttpCwsRouteCollection routeCollection; - private string basePath; + var currentIp = CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0); + + var hostname = CrestronEthernetHelper.GetEthernetParameter( + CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0); - public GetRoutesHandler(HttpCwsRouteCollection routeCollection, string basePath) { - this.routeCollection = routeCollection; - this.basePath = basePath; - } + var path = CrestronEnvironment.DevicePlatform == eDevicePlatform.Server + ? $"https://{hostname}/VirtualControl/Rooms/{InitialParametersClass.RoomId}/cws{basePath}" + : $"https://{currentIp}/cws{basePath}"; - protected override void HandleGet(HttpCwsContext context) + var response = JsonConvert.SerializeObject(new RoutesResponseObject() { - var currentIp = CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0); - - var hostname = CrestronEthernetHelper.GetEthernetParameter( - CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0); - - var path = CrestronEnvironment.DevicePlatform == eDevicePlatform.Server - ? $"https://{hostname}/VirtualControl/Rooms/{InitialParametersClass.RoomId}/cws{basePath}" - : $"https://{currentIp}/cws{basePath}"; - - var response = JsonConvert.SerializeObject(new RoutesResponseObject() - { - Url = path, - Routes = routeCollection - }); - - context.Response.StatusCode = 200; - context.Response.ContentType = "application/json"; - context.Response.Headers.Add("Content-Type", "application/json"); - context.Response.Write(response, false); - context.Response.End(); - } + Url = path, + Routes = routeCollection + }); + + context.Response.StatusCode = 200; + context.Response.ContentType = "application/json"; + context.Response.Headers.Add("Content-Type", "application/json"); + context.Response.Write(response, false); + context.Response.End(); } +} - public class RoutesResponseObject - { - [JsonProperty("url")] - public string Url { set; get; } +public class RoutesResponseObject +{ + [JsonProperty("url")] + public string Url { set; get; } - [JsonProperty("routes")] - public HttpCwsRouteCollection Routes { get; set; } - } + [JsonProperty("routes")] + public HttpCwsRouteCollection Routes { get; set; } } diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetRoutingPortsHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetRoutingPortsHandler.cs index 6e033f06f..2350fe5a6 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetRoutingPortsHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetRoutingPortsHandler.cs @@ -5,66 +5,65 @@ using System.Linq; using System.Text; -namespace PepperDash.Essentials.Core.Web.RequestHandlers +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + +public class GetRoutingPortsHandler : WebApiBaseRequestHandler { - public class GetRoutingPortsHandler : WebApiBaseRequestHandler + public GetRoutingPortsHandler() : base(true) { } + + protected override void HandleGet(HttpCwsContext context) { - public GetRoutingPortsHandler() : base(true) { } + var routeData = context.Request.RouteData; - protected override void HandleGet(HttpCwsContext context) + if (routeData == null) { - var routeData = context.Request.RouteData; - - if (routeData == null) - { - context.Response.StatusCode = 400; - context.Response.StatusDescription = "Bad Request"; - context.Response.End(); - return; - } + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + return; + } - if(!routeData.Values.TryGetValue("deviceKey", out var deviceKey)) - { - context.Response.StatusCode = 400; - context.Response.StatusDescription = "Bad Request"; - context.Response.End(); - return; - } + if(!routeData.Values.TryGetValue("deviceKey", out var deviceKey)) + { + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Bad Request"; + context.Response.End(); + return; + } - var device = DeviceManager.GetDeviceForKey(deviceKey.ToString()); + var device = DeviceManager.GetDeviceForKey(deviceKey.ToString()); - if (device == null) - { - context.Response.StatusCode = 404; - context.Response.StatusDescription = "Device Not Found"; - context.Response.End(); - return; - } + if (device == null) + { + context.Response.StatusCode = 404; + context.Response.StatusDescription = "Device Not Found"; + context.Response.End(); + return; + } - var inputPorts = (device as IRoutingInputs)?.InputPorts; - var outputPorts = (device as IRoutingOutputs)?.OutputPorts; - - var response = JsonConvert.SerializeObject( new ReturnValue - { - InputPorts = inputPorts?.Select(p => p.Key).ToList(), - OutputPorts = outputPorts?.Select(p => p.Key).ToList() - }); + var inputPorts = (device as IRoutingInputs)?.InputPorts; + var outputPorts = (device as IRoutingOutputs)?.OutputPorts; + + var response = JsonConvert.SerializeObject( new ReturnValue + { + InputPorts = inputPorts?.Select(p => p.Key).ToList(), + OutputPorts = outputPorts?.Select(p => p.Key).ToList() + }); - context.Response.StatusCode = 200; - context.Response.StatusDescription = "OK"; - context.Response.ContentType = "application/json"; - context.Response.ContentEncoding = Encoding.UTF8; - context.Response.Write(response, false); - context.Response.End(); + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = Encoding.UTF8; + context.Response.Write(response, false); + context.Response.End(); - } } +} - internal class ReturnValue { - [JsonProperty("inputPorts", NullValueHandling = NullValueHandling.Ignore)] - public List InputPorts { get; set; } +internal class ReturnValue { + [JsonProperty("inputPorts", NullValueHandling = NullValueHandling.Ignore)] + public List InputPorts { get; set; } - [JsonProperty("outputPorts", NullValueHandling = NullValueHandling.Ignore)] - public List OutputPorts { get; set; } - } + [JsonProperty("outputPorts", NullValueHandling = NullValueHandling.Ignore)] + public List OutputPorts { get; set; } } diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTieLinesRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTieLinesRequestHandler.cs index fb1db4e76..c1eabdaca 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTieLinesRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTieLinesRequestHandler.cs @@ -4,30 +4,29 @@ using System.Linq; using System.Text; -namespace PepperDash.Essentials.Core.Web.RequestHandlers +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + +public class GetTieLinesRequestHandler : WebApiBaseRequestHandler { - public class GetTieLinesRequestHandler : WebApiBaseRequestHandler - { - public GetTieLinesRequestHandler() : base(true) { } + public GetTieLinesRequestHandler() : base(true) { } - protected override void HandleGet(HttpCwsContext context) + protected override void HandleGet(HttpCwsContext context) + { + var tieLineString = JsonConvert.SerializeObject(TieLineCollection.Default.Select((tl) => new { - var tieLineString = JsonConvert.SerializeObject(TieLineCollection.Default.Select((tl) => new - { - sourceKey = tl.SourcePort.ParentDevice.Key, - sourcePort = tl.SourcePort.Key, - destinationKey = tl.DestinationPort.ParentDevice.Key, - destinationPort = tl.DestinationPort.Key, - type = tl.Type.ToString(), - })); + sourceKey = tl.SourcePort.ParentDevice.Key, + sourcePort = tl.SourcePort.Key, + destinationKey = tl.DestinationPort.ParentDevice.Key, + destinationPort = tl.DestinationPort.Key, + type = tl.Type.ToString(), + })); - context.Response.StatusCode = 200; - context.Response.StatusDescription = "OK"; - context.Response.ContentType = "application/json"; - context.Response.ContentEncoding = Encoding.UTF8; - context.Response.Write(tieLineString, false); - context.Response.End(); + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; + context.Response.ContentType = "application/json"; + context.Response.ContentEncoding = Encoding.UTF8; + context.Response.Write(tieLineString, false); + context.Response.End(); - } } } diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs index 637c533c9..3a8159fdd 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTypesByFilterRequestHandler.cs @@ -3,8 +3,8 @@ using Newtonsoft.Json; using PepperDash.Core.Web.RequestHandlers; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class GetTypesByFilterRequestHandler : WebApiBaseRequestHandler { /// @@ -64,5 +64,4 @@ protected override void HandleGet(HttpCwsContext context) context.Response.Write(js, false); context.Response.End(); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTypesRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTypesRequestHandler.cs index 564cb00d5..d1a200985 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTypesRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/GetTypesRequestHandler.cs @@ -3,8 +3,8 @@ using Newtonsoft.Json; using PepperDash.Core.Web.RequestHandlers; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class GetTypesRequestHandler : WebApiBaseRequestHandler { /// @@ -54,5 +54,4 @@ protected override void HandleGet(HttpCwsContext context) context.Response.Write(js, false); context.Response.End(); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/LoadConfigRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/LoadConfigRequestHandler.cs index 61932f30b..c5789166d 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/LoadConfigRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/LoadConfigRequestHandler.cs @@ -4,8 +4,8 @@ using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class LoadConfigRequestHandler : WebApiBaseRequestHandler { /// @@ -28,12 +28,11 @@ protected override void HandlePost(HttpCwsContext context) var message = ""; var cs = Global.ControlSystem as ILoadConfig; if(cs != null) - cs.GoWithLoad(); - - context.Response.StatusCode = 200; - context.Response.StatusDescription = "OK"; + cs.GoWithLoad(); + + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; context.Response.Write(message, false); - context.Response.End(); - } - } -} \ No newline at end of file + context.Response.End(); + } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/ReportVersionsRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/ReportVersionsRequestHandler.cs index 3447a1eb3..8e4c0a56f 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/ReportVersionsRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/ReportVersionsRequestHandler.cs @@ -3,8 +3,8 @@ using Newtonsoft.Json; using PepperDash.Core.Web.RequestHandlers; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class ReportVersionsRequestHandler : WebApiBaseRequestHandler { /// @@ -45,5 +45,4 @@ protected override void HandleGet(HttpCwsContext context) context.Response.Write(js, false); context.Response.End(); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/RestartProgramRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/RestartProgramRequestHandler.cs index 0bb568f6a..baeeace52 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/RestartProgramRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/RestartProgramRequestHandler.cs @@ -4,8 +4,8 @@ using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class RestartProgramRequestHandler : WebApiBaseRequestHandler { /// @@ -29,10 +29,9 @@ protected override void HandlePost(HttpCwsContext context) if(CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance) CrestronConsole.SendControlSystemCommand($"progres -p:{InitialParametersClass.ApplicationNumber}", ref message); - context.Response.StatusCode = 200; - context.Response.StatusDescription = "OK"; + context.Response.StatusCode = 200; + context.Response.StatusDescription = "OK"; context.Response.Write(message, false); - context.Response.End(); - } - } -} \ No newline at end of file + context.Response.End(); + } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs index fa20145cf..11ea1cc4d 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs @@ -4,8 +4,8 @@ using PepperDash.Core; using PepperDash.Core.Web.RequestHandlers; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class SetDeviceStreamDebugRequestHandler : WebApiBaseRequestHandler { /// @@ -119,23 +119,23 @@ protected override void HandlePost(HttpCwsContext context) return; } - if (!(DeviceManager.GetDeviceForKey(body.DeviceKey) is IStreamDebugging device)) - { - context.Response.StatusCode = 404; - context.Response.StatusDescription = "Not Found"; - context.Response.End(); + if (!(DeviceManager.GetDeviceForKey(body.DeviceKey) is IStreamDebugging device)) + { + context.Response.StatusCode = 404; + context.Response.StatusDescription = "Not Found"; + context.Response.End(); - return; - } + return; + } - eStreamDebuggingSetting debugSetting; + eStreamDebuggingSetting debugSetting; try { debugSetting = (eStreamDebuggingSetting) Enum.Parse(typeof (eStreamDebuggingSetting), body.Setting, true); } catch (Exception ex) { - Debug.LogMessage(ex, "Exception handling set debug request"); + Debug.LogMessage(ex, "Exception handling set debug request"); context.Response.StatusCode = 500; context.Response.StatusDescription = "Internal Server Error"; context.Response.End(); @@ -161,7 +161,7 @@ protected override void HandlePost(HttpCwsContext context) } catch (Exception ex) { - Debug.LogMessage(ex, "Exception handling set debug request"); + Debug.LogMessage(ex, "Exception handling set debug request"); context.Response.StatusCode = 500; context.Response.StatusDescription = "Internal Server Error"; context.Response.End(); @@ -209,5 +209,4 @@ public SetDeviceStreamDebugConfig() Setting = null; Timeout = 15; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/ShowConfigRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/ShowConfigRequestHandler.cs index 65af1d066..0395e34fd 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/ShowConfigRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/ShowConfigRequestHandler.cs @@ -3,8 +3,8 @@ using PepperDash.Core.Web.RequestHandlers; using PepperDash.Essentials.Core.Config; -namespace PepperDash.Essentials.Core.Web.RequestHandlers -{ +namespace PepperDash.Essentials.Core.Web.RequestHandlers; + public class ShowConfigRequestHandler : WebApiBaseRequestHandler { /// @@ -33,5 +33,4 @@ protected override void HandleGet(HttpCwsContext context) context.Response.Write(config, false); context.Response.End(); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Audio/GenericAudioOut.cs b/src/PepperDash.Essentials.Devices.Common/Audio/GenericAudioOut.cs index 150b78186..289e03565 100644 --- a/src/PepperDash.Essentials.Devices.Common/Audio/GenericAudioOut.cs +++ b/src/PepperDash.Essentials.Devices.Common/Audio/GenericAudioOut.cs @@ -10,40 +10,40 @@ using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common -{ +namespace PepperDash.Essentials.Devices.Common; + /// /// Represents and audio endpoint /// public class GenericAudioOut : EssentialsDevice, IRoutingSink { - public RoutingInputPort CurrentInputPort => AnyAudioIn; + public RoutingInputPort CurrentInputPort => AnyAudioIn; - public event SourceInfoChangeHandler CurrentSourceChange; + public event SourceInfoChangeHandler CurrentSourceChange; - public string CurrentSourceInfoKey { get; set; } - public SourceListItem CurrentSourceInfo + public string CurrentSourceInfoKey { get; set; } + public SourceListItem CurrentSourceInfo + { + get { - get - { - return _CurrentSourceInfo; - } - set - { - if (value == _CurrentSourceInfo) return; + return _CurrentSourceInfo; + } + set + { + if (value == _CurrentSourceInfo) return; - var handler = CurrentSourceChange; + var handler = CurrentSourceChange; - if (handler != null) - handler(_CurrentSourceInfo, ChangeType.WillChange); + if (handler != null) + handler(_CurrentSourceInfo, ChangeType.WillChange); - _CurrentSourceInfo = value; + _CurrentSourceInfo = value; - if (handler != null) - handler(_CurrentSourceInfo, ChangeType.DidChange); - } + if (handler != null) + handler(_CurrentSourceInfo, ChangeType.DidChange); } - SourceListItem _CurrentSourceInfo; + } + SourceListItem _CurrentSourceInfo; public RoutingInputPort AnyAudioIn { get; private set; } @@ -102,20 +102,18 @@ public GenericAudioOutWithVolume(string key, string name, string audioDevice, ui } - public class GenericAudioOutWithVolumeFactory : EssentialsDeviceFactory +public class GenericAudioOutWithVolumeFactory : EssentialsDeviceFactory +{ + public GenericAudioOutWithVolumeFactory() { - public GenericAudioOutWithVolumeFactory() - { - TypeNames = new List() { "genericaudiooutwithvolume" }; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new GenericAudioOutWithVolumeFactory Device"); - var zone = dc.Properties.Value("zone"); - return new GenericAudioOutWithVolume(dc.Key, dc.Name, - dc.Properties.Value("volumeDeviceKey"), zone); - } + TypeNames = new List() { "genericaudiooutwithvolume" }; } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new GenericAudioOutWithVolumeFactory Device"); + var zone = dc.Properties.Value("zone"); + return new GenericAudioOutWithVolume(dc.Key, dc.Name, + dc.Properties.Value("volumeDeviceKey"), zone); + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/AudioCodec/AudioCodecBase.cs b/src/PepperDash.Essentials.Devices.Common/AudioCodec/AudioCodecBase.cs index 56998d46b..4668f7548 100644 --- a/src/PepperDash.Essentials.Devices.Common/AudioCodec/AudioCodecBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/AudioCodec/AudioCodecBase.cs @@ -8,97 +8,96 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Devices.Common.Codec; -namespace PepperDash.Essentials.Devices.Common.AudioCodec +namespace PepperDash.Essentials.Devices.Common.AudioCodec; + +public abstract class AudioCodecBase : EssentialsDevice, IHasDialer, IUsageTracking, IAudioCodecInfo { - public abstract class AudioCodecBase : EssentialsDevice, IHasDialer, IUsageTracking, IAudioCodecInfo - { - public event EventHandler CallStatusChange; + public event EventHandler CallStatusChange; - public AudioCodecInfo CodecInfo { get; protected set; } + public AudioCodecInfo CodecInfo { get; protected set; } - #region IUsageTracking Members + #region IUsageTracking Members - /// - /// This object can be added by outside users of this class to provide usage tracking - /// for various services - /// - public UsageTracking UsageTracker { get; set; } + /// + /// This object can be added by outside users of this class to provide usage tracking + /// for various services + /// + public UsageTracking UsageTracker { get; set; } - #endregion + #endregion - /// - /// Returns true when any call is not in state Unknown, Disconnecting, Disconnected - /// - public bool IsInCall + /// + /// Returns true when any call is not in state Unknown, Disconnecting, Disconnected + /// + public bool IsInCall + { + get { - get - { - bool value; - - if (ActiveCalls != null) - value = ActiveCalls.Any(c => c.IsActiveCall); - else - value = false; - return value; - } + bool value; + + if (ActiveCalls != null) + value = ActiveCalls.Any(c => c.IsActiveCall); + else + value = false; + return value; } + } - // In most cases only a single call can be active - public List ActiveCalls { get; set; } + // In most cases only a single call can be active + public List ActiveCalls { get; set; } - public AudioCodecBase(string key, string name) - : base(key, name) - { - ActiveCalls = new List(); - } + public AudioCodecBase(string key, string name) + : base(key, name) + { + ActiveCalls = new List(); + } - /// - /// Helper method to fire CallStatusChange event with old and new status - /// - protected void SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus newStatus, CodecActiveCallItem call) - { - call.Status = newStatus; + /// + /// Helper method to fire CallStatusChange event with old and new status + /// + protected void SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus newStatus, CodecActiveCallItem call) + { + call.Status = newStatus; - OnCallStatusChange(call); + OnCallStatusChange(call); - } + } - /// - /// - /// - /// - /// - /// - protected void OnCallStatusChange(CodecActiveCallItem item) + /// + /// + /// + /// + /// + /// + protected void OnCallStatusChange(CodecActiveCallItem item) + { + var handler = CallStatusChange; + if (handler != null) + handler(this, new CodecCallStatusItemChangeEventArgs(item)); + + if (UsageTracker != null) { - var handler = CallStatusChange; - if (handler != null) - handler(this, new CodecCallStatusItemChangeEventArgs(item)); - - if (UsageTracker != null) - { - if (IsInCall && !UsageTracker.UsageTrackingStarted) - UsageTracker.StartDeviceUsage(); - else if (UsageTracker.UsageTrackingStarted && !IsInCall) - UsageTracker.EndDeviceUsage(); - } + if (IsInCall && !UsageTracker.UsageTrackingStarted) + UsageTracker.StartDeviceUsage(); + else if (UsageTracker.UsageTrackingStarted && !IsInCall) + UsageTracker.EndDeviceUsage(); } + } - #region IHasDialer Members + #region IHasDialer Members - public abstract void Dial(string number); + public abstract void Dial(string number); - public abstract void EndCall(CodecActiveCallItem activeCall); + public abstract void EndCall(CodecActiveCallItem activeCall); - public abstract void EndAllCalls(); + public abstract void EndAllCalls(); - public abstract void AcceptCall(CodecActiveCallItem item); + public abstract void AcceptCall(CodecActiveCallItem item); - public abstract void RejectCall(CodecActiveCallItem item); + public abstract void RejectCall(CodecActiveCallItem item); - public abstract void SendDtmf(string digit); + public abstract void SendDtmf(string digit); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/AudioCodec/Interfaces/IAudioCodecInfo.cs b/src/PepperDash.Essentials.Devices.Common/AudioCodec/Interfaces/IAudioCodecInfo.cs index e853c8981..8d6a17784 100644 --- a/src/PepperDash.Essentials.Devices.Common/AudioCodec/Interfaces/IAudioCodecInfo.cs +++ b/src/PepperDash.Essentials.Devices.Common/AudioCodec/Interfaces/IAudioCodecInfo.cs @@ -4,21 +4,20 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Devices.Common.AudioCodec +namespace PepperDash.Essentials.Devices.Common.AudioCodec; + +/// +/// Implements a common set of data about a codec +/// +public interface IAudioCodecInfo { - /// - /// Implements a common set of data about a codec - /// - public interface IAudioCodecInfo - { - AudioCodecInfo CodecInfo { get; } - } + AudioCodecInfo CodecInfo { get; } +} - /// - /// Stores general information about a codec - /// - public abstract class AudioCodecInfo - { - public abstract string PhoneNumber { get; set; } - } +/// +/// Stores general information about a codec +/// +public abstract class AudioCodecInfo +{ + public abstract string PhoneNumber { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/AudioCodec/Interfaces/IHasAudioCodec.cs b/src/PepperDash.Essentials.Devices.Common/AudioCodec/Interfaces/IHasAudioCodec.cs index b6fa079d2..edefe5e1e 100644 --- a/src/PepperDash.Essentials.Devices.Common/AudioCodec/Interfaces/IHasAudioCodec.cs +++ b/src/PepperDash.Essentials.Devices.Common/AudioCodec/Interfaces/IHasAudioCodec.cs @@ -6,18 +6,17 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Devices.Common.AudioCodec +namespace PepperDash.Essentials.Devices.Common.AudioCodec; + +/// +/// For rooms that have audio codec +/// +public interface IHasAudioCodec:IHasInCallFeedback { - /// - /// For rooms that have audio codec - /// - public interface IHasAudioCodec:IHasInCallFeedback - { - AudioCodecBase AudioCodec { get; } + AudioCodecBase AudioCodec { get; } - ///// - ///// Make this more specific - ///// - //List ActiveCalls { get; } - } + ///// + ///// Make this more specific + ///// + //List ActiveCalls { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAC.cs b/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAC.cs index 502902b92..799154473 100644 --- a/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAC.cs +++ b/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAC.cs @@ -10,123 +10,121 @@ using PepperDash.Essentials.Devices.Common.Codec; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common.AudioCodec +namespace PepperDash.Essentials.Devices.Common.AudioCodec; + +public class MockAC : AudioCodecBase { - public class MockAC : AudioCodecBase + public MockAC(string key, string name, MockAcPropertiesConfig props) + : base(key, name) { - public MockAC(string key, string name, MockAcPropertiesConfig props) - : base(key, name) - { - CodecInfo = new MockAudioCodecInfo(); + CodecInfo = new MockAudioCodecInfo(); - CodecInfo.PhoneNumber = props.PhoneNumber; - } + CodecInfo.PhoneNumber = props.PhoneNumber; + } - public override void Dial(string number) + public override void Dial(string number) + { + if (!IsInCall) { - if (!IsInCall) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Dial: {0}", number); - var call = new CodecActiveCallItem() - { - Name = "Mock Outgoing Call", - Number = number, - Type = eCodecCallType.Audio, - Status = eCodecCallStatus.Connected, - Direction = eCodecCallDirection.Outgoing, - Id = "mockAudioCall-1" - }; - - ActiveCalls.Add(call); - - OnCallStatusChange(call); - } - else + Debug.LogMessage(LogEventLevel.Debug, this, "Dial: {0}", number); + var call = new CodecActiveCallItem() { - Debug.LogMessage(LogEventLevel.Debug, this, "Already in call. Cannot dial new call."); - } - } + Name = "Mock Outgoing Call", + Number = number, + Type = eCodecCallType.Audio, + Status = eCodecCallStatus.Connected, + Direction = eCodecCallDirection.Outgoing, + Id = "mockAudioCall-1" + }; - public override void EndCall(CodecActiveCallItem call) - { - Debug.LogMessage(LogEventLevel.Debug, this, "EndCall"); - ActiveCalls.Remove(call); - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call); - } + ActiveCalls.Add(call); - public override void EndAllCalls() - { - Debug.LogMessage(LogEventLevel.Debug, this, "EndAllCalls"); - for (int i = ActiveCalls.Count - 1; i >= 0; i--) - { - var call = ActiveCalls[i]; - ActiveCalls.Remove(call); - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call); - } + OnCallStatusChange(call); } - - public override void AcceptCall(CodecActiveCallItem call) + else { - Debug.LogMessage(LogEventLevel.Debug, this, "AcceptCall"); - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connecting, call); + Debug.LogMessage(LogEventLevel.Debug, this, "Already in call. Cannot dial new call."); } + } - public override void RejectCall(CodecActiveCallItem call) + public override void EndCall(CodecActiveCallItem call) + { + Debug.LogMessage(LogEventLevel.Debug, this, "EndCall"); + ActiveCalls.Remove(call); + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call); + } + + public override void EndAllCalls() + { + Debug.LogMessage(LogEventLevel.Debug, this, "EndAllCalls"); + for (int i = ActiveCalls.Count - 1; i >= 0; i--) { - Debug.LogMessage(LogEventLevel.Debug, this, "RejectCall"); + var call = ActiveCalls[i]; ActiveCalls.Remove(call); SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call); } + } - public override void SendDtmf(string s) - { - Debug.LogMessage(LogEventLevel.Debug, this, "BEEP BOOP SendDTMF: {0}", s); - } - - /// - /// - /// - /// - public void TestIncomingAudioCall(string number) - { - Debug.LogMessage(LogEventLevel.Debug, this, "TestIncomingAudioCall from {0}", number); - var call = new CodecActiveCallItem() { Name = number, Id = number, Number = number, Type = eCodecCallType.Audio, Direction = eCodecCallDirection.Incoming }; - ActiveCalls.Add(call); - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Ringing, call); - } + public override void AcceptCall(CodecActiveCallItem call) + { + Debug.LogMessage(LogEventLevel.Debug, this, "AcceptCall"); + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connecting, call); + } + public override void RejectCall(CodecActiveCallItem call) + { + Debug.LogMessage(LogEventLevel.Debug, this, "RejectCall"); + ActiveCalls.Remove(call); + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call); } - public class MockAudioCodecInfo : AudioCodecInfo + public override void SendDtmf(string s) { - string _phoneNumber; + Debug.LogMessage(LogEventLevel.Debug, this, "BEEP BOOP SendDTMF: {0}", s); + } - public override string PhoneNumber - { - get - { - return _phoneNumber; - } - set - { - _phoneNumber = value; - } - } + /// + /// + /// + /// + public void TestIncomingAudioCall(string number) + { + Debug.LogMessage(LogEventLevel.Debug, this, "TestIncomingAudioCall from {0}", number); + var call = new CodecActiveCallItem() { Name = number, Id = number, Number = number, Type = eCodecCallType.Audio, Direction = eCodecCallDirection.Incoming }; + ActiveCalls.Add(call); + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Ringing, call); } - public class MockACFactory : EssentialsDeviceFactory +} + +public class MockAudioCodecInfo : AudioCodecInfo +{ + string _phoneNumber; + + public override string PhoneNumber { - public MockACFactory() + get { - TypeNames = new List() { "mockac" }; + return _phoneNumber; } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) + set { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new MockAc Device"); - var props = Newtonsoft.Json.JsonConvert.DeserializeObject(dc.Properties.ToString()); - return new AudioCodec.MockAC(dc.Key, dc.Name, props); + _phoneNumber = value; } } +} +public class MockACFactory : EssentialsDeviceFactory +{ + public MockACFactory() + { + TypeNames = new List() { "mockac" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new MockAc Device"); + var props = Newtonsoft.Json.JsonConvert.DeserializeObject(dc.Properties.ToString()); + return new AudioCodec.MockAC(dc.Key, dc.Name, props); + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAcPropertiesConfig.cs b/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAcPropertiesConfig.cs index c9d041ebb..387d3bc11 100644 --- a/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAcPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAcPropertiesConfig.cs @@ -8,11 +8,10 @@ using Newtonsoft.Json; -namespace PepperDash.Essentials.Devices.Common.AudioCodec +namespace PepperDash.Essentials.Devices.Common.AudioCodec; + +public class MockAcPropertiesConfig { - public class MockAcPropertiesConfig - { - [JsonProperty("phoneNumber")] - public string PhoneNumber { get; set; } - } + [JsonProperty("phoneNumber")] + public string PhoneNumber { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraBase.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraBase.cs index c008e9693..fe9015aa9 100644 --- a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraBase.cs @@ -19,64 +19,64 @@ using Newtonsoft.Json; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common.Cameras -{ - public enum eCameraCapabilities - { - None = 0, - Pan = 1, - Tilt = 2, - Zoom = 4, - Focus = 8 - } +namespace PepperDash.Essentials.Devices.Common.Cameras; - public abstract class CameraBase : ReconfigurableDevice, IRoutingOutputs +public enum eCameraCapabilities +{ + None = 0, + Pan = 1, + Tilt = 2, + Zoom = 4, + Focus = 8 +} + +public abstract class CameraBase : ReconfigurableDevice, IRoutingOutputs { - [JsonProperty("controlMode", NullValueHandling = NullValueHandling.Ignore)] - public eCameraControlMode ControlMode { get; protected set; } + [JsonProperty("controlMode", NullValueHandling = NullValueHandling.Ignore)] + public eCameraControlMode ControlMode { get; protected set; } - #region IRoutingOutputs Members + #region IRoutingOutputs Members - [JsonIgnore] - public RoutingPortCollection OutputPorts { get; protected set; } + [JsonIgnore] + public RoutingPortCollection OutputPorts { get; protected set; } - #endregion + #endregion - [JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)] - public bool CanPan + [JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)] + public bool CanPan + { + get { - get - { - return (Capabilities & eCameraCapabilities.Pan) == eCameraCapabilities.Pan; - } + return (Capabilities & eCameraCapabilities.Pan) == eCameraCapabilities.Pan; } - [JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)] - public bool CanTilt + } + [JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)] + public bool CanTilt + { + get { - get - { - return (Capabilities & eCameraCapabilities.Tilt) == eCameraCapabilities.Tilt; - } + return (Capabilities & eCameraCapabilities.Tilt) == eCameraCapabilities.Tilt; } - [JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)] - public bool CanZoom + } + [JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)] + public bool CanZoom + { + get { - get - { - return (Capabilities & eCameraCapabilities.Zoom) == eCameraCapabilities.Zoom; - } + return (Capabilities & eCameraCapabilities.Zoom) == eCameraCapabilities.Zoom; } - [JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)] - public bool CanFocus + } + [JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)] + public bool CanFocus + { + get { - get - { - return (Capabilities & eCameraCapabilities.Focus) == eCameraCapabilities.Focus; - } + return (Capabilities & eCameraCapabilities.Focus) == eCameraCapabilities.Focus; } + } - // A bitmasked value to indicate the movement capabilites of this camera - protected eCameraCapabilities Capabilities { get; set; } + // A bitmasked value to indicate the movement capabilites of this camera + protected eCameraCapabilities Capabilities { get; set; } protected CameraBase(DeviceConfig config) : base(config) { @@ -86,199 +86,199 @@ protected CameraBase(DeviceConfig config) : base(config) } - protected CameraBase(string key, string name) : + protected CameraBase(string key, string name) : this (new DeviceConfig{Name = name, Key = key}) - { + { - } + } - protected void LinkCameraToApi(CameraBase cameraDevice, BasicTriList trilist, uint joinStart, string joinMapKey, - EiscApiAdvanced bridge) - { - CameraControllerJoinMap joinMap = new CameraControllerJoinMap(joinStart); + protected void LinkCameraToApi(CameraBase cameraDevice, BasicTriList trilist, uint joinStart, string joinMapKey, + EiscApiAdvanced bridge) + { + CameraControllerJoinMap joinMap = new CameraControllerJoinMap(joinStart); - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } - var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); + var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); - if (customJoins != null) - { - joinMap.SetCustomJoinData(customJoins); - } + if (customJoins != null) + { + joinMap.SetCustomJoinData(customJoins); + } - Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - Debug.LogMessage(LogEventLevel.Information, "Linking to Bridge Type {0}", cameraDevice.GetType().Name.ToString()); + Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + Debug.LogMessage(LogEventLevel.Information, "Linking to Bridge Type {0}", cameraDevice.GetType().Name.ToString()); - var commMonitor = cameraDevice as ICommunicationMonitor; - commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig( - trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + var commMonitor = cameraDevice as ICommunicationMonitor; + commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig( + trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); - var ptzCamera = cameraDevice as IHasCameraPtzControl; + var ptzCamera = cameraDevice as IHasCameraPtzControl; - if (ptzCamera != null) + if (ptzCamera != null) + { + trilist.SetBoolSigAction(joinMap.PanLeft.JoinNumber, (b) => { - trilist.SetBoolSigAction(joinMap.PanLeft.JoinNumber, (b) => + if (b) { - if (b) - { - ptzCamera.PanLeft(); - } - else - { - ptzCamera.PanStop(); - } - }); - trilist.SetBoolSigAction(joinMap.PanRight.JoinNumber, (b) => + ptzCamera.PanLeft(); + } + else { - if (b) - { - ptzCamera.PanRight(); - } - else - { - ptzCamera.PanStop(); - } - }); - - trilist.SetBoolSigAction(joinMap.TiltUp.JoinNumber, (b) => + ptzCamera.PanStop(); + } + }); + trilist.SetBoolSigAction(joinMap.PanRight.JoinNumber, (b) => + { + if (b) { - if (b) - { - ptzCamera.TiltUp(); - } - else - { - ptzCamera.TiltStop(); - } - }); - trilist.SetBoolSigAction(joinMap.TiltDown.JoinNumber, (b) => + ptzCamera.PanRight(); + } + else { - if (b) - { - ptzCamera.TiltDown(); - } - else - { - ptzCamera.TiltStop(); - } - }); + ptzCamera.PanStop(); + } + }); - trilist.SetBoolSigAction(joinMap.ZoomIn.JoinNumber, (b) => + trilist.SetBoolSigAction(joinMap.TiltUp.JoinNumber, (b) => + { + if (b) { - if (b) - { - ptzCamera.ZoomIn(); - } - else - { - ptzCamera.ZoomStop(); - } - }); - - trilist.SetBoolSigAction(joinMap.ZoomOut.JoinNumber, (b) => + ptzCamera.TiltUp(); + } + else { - if (b) - { - ptzCamera.ZoomOut(); - } - else - { - ptzCamera.ZoomStop(); - } - }); - } + ptzCamera.TiltStop(); + } + }); + trilist.SetBoolSigAction(joinMap.TiltDown.JoinNumber, (b) => + { + if (b) + { + ptzCamera.TiltDown(); + } + else + { + ptzCamera.TiltStop(); + } + }); - var powerCamera = cameraDevice as IHasPowerControl; - if (powerCamera != null) + trilist.SetBoolSigAction(joinMap.ZoomIn.JoinNumber, (b) => { - trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () => powerCamera.PowerOn()); - trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () => powerCamera.PowerOff()); + if (b) + { + ptzCamera.ZoomIn(); + } + else + { + ptzCamera.ZoomStop(); + } + }); - var powerFbCamera = powerCamera as IHasPowerControlWithFeedback; - if (powerFbCamera != null) + trilist.SetBoolSigAction(joinMap.ZoomOut.JoinNumber, (b) => + { + if (b) { - powerFbCamera.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]); - powerFbCamera.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]); + ptzCamera.ZoomOut(); } - } + else + { + ptzCamera.ZoomStop(); + } + }); + } - if (cameraDevice is ICommunicationMonitor) + var powerCamera = cameraDevice as IHasPowerControl; + if (powerCamera != null) + { + trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () => powerCamera.PowerOn()); + trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () => powerCamera.PowerOff()); + + var powerFbCamera = powerCamera as IHasPowerControlWithFeedback; + if (powerFbCamera != null) { - var monitoredCamera = cameraDevice as ICommunicationMonitor; - monitoredCamera.CommunicationMonitor.IsOnlineFeedback.LinkInputSig( - trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + powerFbCamera.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]); + powerFbCamera.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]); } + } - if (cameraDevice is IHasCameraPresets) - { - // Set the preset lables when they change - var presetsCamera = cameraDevice as IHasCameraPresets; - presetsCamera.PresetsListHasChanged += new EventHandler((o, a) => - { - SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist); - }); + if (cameraDevice is ICommunicationMonitor) + { + var monitoredCamera = cameraDevice as ICommunicationMonitor; + monitoredCamera.CommunicationMonitor.IsOnlineFeedback.LinkInputSig( + trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + } + if (cameraDevice is IHasCameraPresets) + { + // Set the preset lables when they change + var presetsCamera = cameraDevice as IHasCameraPresets; + presetsCamera.PresetsListHasChanged += new EventHandler((o, a) => + { SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist); + }); + + SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist); - for (int i = 0; i < joinMap.PresetRecallStart.JoinSpan; i++) + for (int i = 0; i < joinMap.PresetRecallStart.JoinSpan; i++) + { + int tempNum = i; + + trilist.SetSigTrueAction((ushort) (joinMap.PresetRecallStart.JoinNumber + tempNum), () => { - int tempNum = i; - - trilist.SetSigTrueAction((ushort) (joinMap.PresetRecallStart.JoinNumber + tempNum), () => - { - presetsCamera.PresetSelect(tempNum); - }); - trilist.SetSigTrueAction((ushort) (joinMap.PresetSaveStart.JoinNumber + tempNum), () => - { - var label = trilist.GetString((ushort) (joinMap.PresetLabelStart.JoinNumber + tempNum)); - - presetsCamera.PresetStore(tempNum, label); - }); - } - trilist.OnlineStatusChange += (sender, args) => + presetsCamera.PresetSelect(tempNum); + }); + trilist.SetSigTrueAction((ushort) (joinMap.PresetSaveStart.JoinNumber + tempNum), () => { - if (!args.DeviceOnLine) - { return; } - - SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist); - }; + var label = trilist.GetString((ushort) (joinMap.PresetLabelStart.JoinNumber + tempNum)); + presetsCamera.PresetStore(tempNum, label); + }); } + trilist.OnlineStatusChange += (sender, args) => + { + if (!args.DeviceOnLine) + { return; } + + SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist); + }; + } - private void SendCameraPresetNamesToApi(IHasCameraPresets presetsCamera, CameraControllerJoinMap joinMap, BasicTriList trilist) + } + private void SendCameraPresetNamesToApi(IHasCameraPresets presetsCamera, CameraControllerJoinMap joinMap, BasicTriList trilist) + { + for (int i = 1; i <= joinMap.NumberOfPresets.JoinNumber; i++) { - for (int i = 1; i <= joinMap.NumberOfPresets.JoinNumber; i++) - { - int tempNum = i - 1; + int tempNum = i - 1; - string label = ""; + string label = ""; - var preset = presetsCamera.Presets.FirstOrDefault(p => p.ID.Equals(i)); + var preset = presetsCamera.Presets.FirstOrDefault(p => p.ID.Equals(i)); - if (preset != null) - label = preset.Description; + if (preset != null) + label = preset.Description; - trilist.SetString((ushort)(joinMap.PresetLabelStart.JoinNumber + tempNum), label); - } + trilist.SetString((ushort)(joinMap.PresetLabelStart.JoinNumber + tempNum), label); } + } } - public class CameraPreset : PresetBase +public class CameraPreset : PresetBase +{ + public CameraPreset(int id, string description, bool isDefined, bool isDefinable) + : base(id, description, isDefined, isDefinable) { - public CameraPreset(int id, string description, bool isDefined, bool isDefinable) - : base(id, description, isDefined, isDefinable) - { - } } +} public class CameraPropertiesConfig @@ -287,13 +287,12 @@ public class CameraPropertiesConfig public ControlPropertiesConfig Control { get; set; } - [JsonProperty("supportsAutoMode")] - public bool SupportsAutoMode { get; set; } + [JsonProperty("supportsAutoMode")] + public bool SupportsAutoMode { get; set; } - [JsonProperty("supportsOffMode")] - public bool SupportsOffMode { get; set; } + [JsonProperty("supportsOffMode")] + public bool SupportsOffMode { get; set; } - [JsonProperty("presets")] - public List Presets { get; set; } - } -} \ No newline at end of file + [JsonProperty("presets")] + public List Presets { get; set; } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraControl.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraControl.cs index cbf53476d..1f97f1915 100644 --- a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraControl.cs +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraControl.cs @@ -6,161 +6,156 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Devices.Common.Cameras -{ - public enum eCameraControlMode - { - Manual = 0, - Off, - Auto - } +namespace PepperDash.Essentials.Devices.Common.Cameras; +public enum eCameraControlMode +{ + Manual = 0, + Off, + Auto +} - public interface IHasCameras - { - event EventHandler CameraSelected; - List Cameras { get; } +public interface IHasCameras +{ + event EventHandler CameraSelected; - CameraBase SelectedCamera { get; } + List Cameras { get; } - StringFeedback SelectedCameraFeedback { get; } + CameraBase SelectedCamera { get; } - void SelectCamera(string key); - } - - /// - /// Aggregates far end cameras with near end cameras - /// - public interface IHasCodecCameras : IHasCameras, IHasFarEndCameraControl - { + StringFeedback SelectedCameraFeedback { get; } - } + void SelectCamera(string key); +} - /// - /// To be implmented on codecs that can disable their camera(s) to blank the near end video - /// - public interface IHasCameraOff - { - BoolFeedback CameraIsOffFeedback { get; } - void CameraOff(); - } +/// +/// Aggregates far end cameras with near end cameras +/// +public interface IHasCodecCameras : IHasCameras, IHasFarEndCameraControl +{ - /// - /// Describes the ability to mute and unmute camera video - /// - public interface IHasCameraMute - { - BoolFeedback CameraIsMutedFeedback { get; } - void CameraMuteOn(); - void CameraMuteOff(); - void CameraMuteToggle(); - } +} - public interface IHasCameraMuteWithUnmuteReqeust : IHasCameraMute - { - event EventHandler VideoUnmuteRequested; - } +/// +/// To be implmented on codecs that can disable their camera(s) to blank the near end video +/// +public interface IHasCameraOff +{ + BoolFeedback CameraIsOffFeedback { get; } + void CameraOff(); +} + +/// +/// Describes the ability to mute and unmute camera video +/// +public interface IHasCameraMute +{ + BoolFeedback CameraIsMutedFeedback { get; } + void CameraMuteOn(); + void CameraMuteOff(); + void CameraMuteToggle(); +} - public class CameraSelectedEventArgs : EventArgs - { - public CameraBase SelectedCamera { get; private set; } +public interface IHasCameraMuteWithUnmuteReqeust : IHasCameraMute +{ + event EventHandler VideoUnmuteRequested; +} - public CameraSelectedEventArgs(CameraBase camera) - { - SelectedCamera = camera; - } - } +public class CameraSelectedEventArgs : EventArgs +{ + public CameraBase SelectedCamera { get; private set; } - public interface IHasFarEndCameraControl + public CameraSelectedEventArgs(CameraBase camera) { - CameraBase FarEndCamera { get; } - - BoolFeedback ControllingFarEndCameraFeedback { get; } - + SelectedCamera = camera; } +} - /// - /// Used to decorate a camera as a far end - /// - public interface IAmFarEndCamera - { +public interface IHasFarEndCameraControl +{ + CameraBase FarEndCamera { get; } - } + BoolFeedback ControllingFarEndCameraFeedback { get; } - public interface IHasCameraControls - { - } +} - /// - /// Aggregates the pan, tilt and zoom interfaces - /// - public interface IHasCameraPtzControl : IHasCameraPanControl, IHasCameraTiltControl, IHasCameraZoomControl - { - /// - /// Resets the camera position - /// - void PositionHome(); - } - - /// - /// Interface for camera pan control - /// - public interface IHasCameraPanControl : IHasCameraControls - { - void PanLeft(); - void PanRight(); - void PanStop(); - } +/// +/// Used to decorate a camera as a far end +/// +public interface IAmFarEndCamera +{ - /// - /// Interface for camera tilt control - /// - public interface IHasCameraTiltControl : IHasCameraControls - { - void TiltDown(); - void TiltUp(); - void TiltStop(); - } +} - /// - /// Interface for camera zoom control - /// - public interface IHasCameraZoomControl : IHasCameraControls - { - void ZoomIn(); - void ZoomOut(); - void ZoomStop(); - } +public interface IHasCameraControls +{ +} +/// +/// Aggregates the pan, tilt and zoom interfaces +/// +public interface IHasCameraPtzControl : IHasCameraPanControl, IHasCameraTiltControl, IHasCameraZoomControl +{ /// - /// Interface for camera focus control + /// Resets the camera position /// - public interface IHasCameraFocusControl : IHasCameraControls - { - void FocusNear(); - void FocusFar(); - void FocusStop(); - - void TriggerAutoFocus(); - } - - public interface IHasAutoFocusMode - { - void SetFocusModeAuto(); - void SetFocusModeManual(); - void ToggleFocusMode(); - } - - public interface IHasCameraAutoMode : IHasCameraControls - { - void CameraAutoModeOn(); - void CameraAutoModeOff(); - void CameraAutoModeToggle(); - BoolFeedback CameraAutoModeIsOnFeedback { get; } - } + void PositionHome(); +} +/// +/// Interface for camera pan control +/// +public interface IHasCameraPanControl : IHasCameraControls +{ + void PanLeft(); + void PanRight(); + void PanStop(); +} + +/// +/// Interface for camera tilt control +/// +public interface IHasCameraTiltControl : IHasCameraControls +{ + void TiltDown(); + void TiltUp(); + void TiltStop(); +} + +/// +/// Interface for camera zoom control +/// +public interface IHasCameraZoomControl : IHasCameraControls +{ + void ZoomIn(); + void ZoomOut(); + void ZoomStop(); +} + +/// +/// Interface for camera focus control +/// +public interface IHasCameraFocusControl : IHasCameraControls +{ + void FocusNear(); + void FocusFar(); + void FocusStop(); + void TriggerAutoFocus(); +} +public interface IHasAutoFocusMode +{ + void SetFocusModeAuto(); + void SetFocusModeManual(); + void ToggleFocusMode(); +} +public interface IHasCameraAutoMode : IHasCameraControls +{ + void CameraAutoModeOn(); + void CameraAutoModeOff(); + void CameraAutoModeToggle(); + BoolFeedback CameraAutoModeIsOnFeedback { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraVisca.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraVisca.cs index 384d60a34..9c07a1eae 100644 --- a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraVisca.cs +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraVisca.cs @@ -17,103 +17,103 @@ using Newtonsoft.Json; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common.Cameras -{ +namespace PepperDash.Essentials.Devices.Common.Cameras; + public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IHasPowerControlWithFeedback, IBridgeAdvanced, IHasCameraFocusControl, IHasAutoFocusMode { - private readonly CameraViscaPropertiesConfig PropertiesConfig; + private readonly CameraViscaPropertiesConfig PropertiesConfig; public IBasicCommunication Communication { get; private set; } public StatusMonitorBase CommunicationMonitor { get; private set; } - /// - /// Used to store the actions to parse inquiry responses as the inquiries are sent - /// - private readonly CrestronQueue> InquiryResponseQueue; + /// + /// Used to store the actions to parse inquiry responses as the inquiries are sent + /// + private readonly CrestronQueue> InquiryResponseQueue; - /// - /// Camera ID (Default 1) - /// - public byte ID = 0x01; - public byte ResponseID; + /// + /// Camera ID (Default 1) + /// + public byte ID = 0x01; + public byte ResponseID; public byte PanSpeedSlow = 0x10; public byte TiltSpeedSlow = 0x10; - public byte PanSpeedFast = 0x13; - public byte TiltSpeedFast = 0x13; + public byte PanSpeedFast = 0x13; + public byte TiltSpeedFast = 0x13; - // private bool IsMoving; + // private bool IsMoving; private bool IsZooming; - bool _powerIsOn; + bool _powerIsOn; public bool PowerIsOn + { + get { - get - { - return _powerIsOn; - } - private set + return _powerIsOn; + } + private set + { + if (value != _powerIsOn) { - if (value != _powerIsOn) - { - _powerIsOn = value; - PowerIsOnFeedback.FireUpdate(); - CameraIsOffFeedback.FireUpdate(); - } + _powerIsOn = value; + PowerIsOnFeedback.FireUpdate(); + CameraIsOffFeedback.FireUpdate(); } } + } - const byte ZoomInCmd = 0x02; - const byte ZoomOutCmd = 0x03; - const byte ZoomStopCmd = 0x00; + const byte ZoomInCmd = 0x02; + const byte ZoomOutCmd = 0x03; + const byte ZoomStopCmd = 0x00; - /// - /// Used to determine when to move the camera at a faster speed if a direction is held - /// - CTimer SpeedTimer; - // TODO: Implment speed timer for PTZ controls + /// + /// Used to determine when to move the camera at a faster speed if a direction is held + /// + CTimer SpeedTimer; + // TODO: Implment speed timer for PTZ controls - long FastSpeedHoldTimeMs = 2000; + long FastSpeedHoldTimeMs = 2000; byte[] IncomingBuffer = new byte[] { }; public BoolFeedback PowerIsOnFeedback { get; private set; } - public CameraVisca(string key, string name, IBasicCommunication comm, CameraViscaPropertiesConfig props) : + public CameraVisca(string key, string name, IBasicCommunication comm, CameraViscaPropertiesConfig props) : base(key, name) { - InquiryResponseQueue = new CrestronQueue>(15); + InquiryResponseQueue = new CrestronQueue>(15); - Presets = props.Presets; + Presets = props.Presets; - PropertiesConfig = props; + PropertiesConfig = props; - ID = (byte)(props.Id + 0x80); - ResponseID = (byte)((props.Id * 0x10) + 0x80); + ID = (byte)(props.Id + 0x80); + ResponseID = (byte)((props.Id * 0x10) + 0x80); - SetupCameraSpeeds(); + SetupCameraSpeeds(); - OutputPorts.Add(new RoutingOutputPort("videoOut", eRoutingSignalType.Video, eRoutingPortConnectionType.None, null, this, true)); + OutputPorts.Add(new RoutingOutputPort("videoOut", eRoutingSignalType.Video, eRoutingPortConnectionType.None, null, this, true)); - // Default to all capabilties - Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom | eCameraCapabilities.Focus; - - Communication = comm; - if (comm is ISocketStatus socket) - { - // This instance uses IP control - socket.ConnectionChange += new EventHandler(Socket_ConnectionChange); - } - else - { - // This instance uses RS-232 control - } + // Default to all capabilties + Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom | eCameraCapabilities.Focus; + + Communication = comm; + if (comm is ISocketStatus socket) + { + // This instance uses IP control + socket.ConnectionChange += new EventHandler(Socket_ConnectionChange); + } + else + { + // This instance uses RS-232 control + } - Communication.BytesReceived += new EventHandler(Communication_BytesReceived); + Communication.BytesReceived += new EventHandler(Communication_BytesReceived); PowerIsOnFeedback = new BoolFeedback(() => { return PowerIsOn; }); - CameraIsOffFeedback = new BoolFeedback(() => { return !PowerIsOn; }); + CameraIsOffFeedback = new BoolFeedback(() => { return !PowerIsOn; }); if (props.CommunicationMonitorProperties != null) { @@ -127,34 +127,34 @@ public CameraVisca(string key, string name, IBasicCommunication comm, CameraVisc } - /// - /// Sets up camera speed values based on config - /// - void SetupCameraSpeeds() + /// + /// Sets up camera speed values based on config + /// + void SetupCameraSpeeds() + { + if (PropertiesConfig.FastSpeedHoldTimeMs > 0) { - if (PropertiesConfig.FastSpeedHoldTimeMs > 0) - { - FastSpeedHoldTimeMs = PropertiesConfig.FastSpeedHoldTimeMs; - } + FastSpeedHoldTimeMs = PropertiesConfig.FastSpeedHoldTimeMs; + } - if (PropertiesConfig.PanSpeedSlow > 0) - { - PanSpeedSlow = (byte)PropertiesConfig.PanSpeedSlow; - } - if (PropertiesConfig.PanSpeedFast > 0) - { - PanSpeedFast = (byte)PropertiesConfig.PanSpeedFast; - } + if (PropertiesConfig.PanSpeedSlow > 0) + { + PanSpeedSlow = (byte)PropertiesConfig.PanSpeedSlow; + } + if (PropertiesConfig.PanSpeedFast > 0) + { + PanSpeedFast = (byte)PropertiesConfig.PanSpeedFast; + } - if (PropertiesConfig.TiltSpeedSlow > 0) - { - TiltSpeedSlow = (byte)PropertiesConfig.TiltSpeedSlow; - } - if (PropertiesConfig.TiltSpeedFast > 0) - { - TiltSpeedFast = (byte)PropertiesConfig.TiltSpeedFast; - } + if (PropertiesConfig.TiltSpeedSlow > 0) + { + TiltSpeedSlow = (byte)PropertiesConfig.TiltSpeedSlow; + } + if (PropertiesConfig.TiltSpeedFast > 0) + { + TiltSpeedFast = (byte)PropertiesConfig.TiltSpeedFast; } + } public override bool CustomActivate() { @@ -200,250 +200,250 @@ void SendBytes(byte[] b) void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e) { - var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length]; + var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length]; - try - { - // This is probably not thread-safe buffering - // Append the incoming bytes with whatever is in the buffer - IncomingBuffer.CopyTo(newBytes, 0); - e.Bytes.CopyTo(newBytes, IncomingBuffer.Length); - if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1 - Debug.LogMessage(LogEventLevel.Verbose, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes)); + try + { + // This is probably not thread-safe buffering + // Append the incoming bytes with whatever is in the buffer + IncomingBuffer.CopyTo(newBytes, 0); + e.Bytes.CopyTo(newBytes, IncomingBuffer.Length); + if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1 + Debug.LogMessage(LogEventLevel.Verbose, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes)); - byte[] message = new byte[] { }; + byte[] message = new byte[] { }; - // Search for the delimiter 0xFF character - for (int i = 0; i < newBytes.Length; i++) + // Search for the delimiter 0xFF character + for (int i = 0; i < newBytes.Length; i++) + { + if (newBytes[i] == 0xFF) { - if (newBytes[i] == 0xFF) - { - // i will be the index of the delmiter character - message = newBytes.Take(i).ToArray(); - // Skip over what we just took and save the rest for next time - newBytes = newBytes.Skip(i).ToArray(); - } + // i will be the index of the delmiter character + message = newBytes.Take(i).ToArray(); + // Skip over what we just took and save the rest for next time + newBytes = newBytes.Skip(i).ToArray(); } + } - if (message.Length > 0) + if (message.Length > 0) + { + // Check for matching ID + if (message[0] != ResponseID) { - // Check for matching ID - if (message[0] != ResponseID) - { - return; - } - - switch (message[1]) - { - case 0x40: + return; + } + + switch (message[1]) + { + case 0x40: + { + // ACK received + Debug.LogMessage(LogEventLevel.Verbose, this, "ACK Received"); + break; + } + case 0x50: + { + + if (message[2] == 0xFF) { - // ACK received - Debug.LogMessage(LogEventLevel.Verbose, this, "ACK Received"); - break; + // Completion received + Debug.LogMessage(LogEventLevel.Verbose, this, "Completion Received"); } - case 0x50: + else { - - if (message[2] == 0xFF) + // Inquiry response received. Dequeue the next response handler and invoke it + if (InquiryResponseQueue.Count > 0) { - // Completion received - Debug.LogMessage(LogEventLevel.Verbose, this, "Completion Received"); + var inquiryAction = InquiryResponseQueue.Dequeue(); + + inquiryAction.Invoke(message.Skip(2).ToArray()); } else { - // Inquiry response received. Dequeue the next response handler and invoke it - if (InquiryResponseQueue.Count > 0) - { - var inquiryAction = InquiryResponseQueue.Dequeue(); + Debug.LogMessage(LogEventLevel.Verbose, this, "Response Queue is empty. Nothing to dequeue."); + } + } + + break; + } + case 0x60: + { + // Error message - inquiryAction.Invoke(message.Skip(2).ToArray()); + switch (message[2]) + { + case 0x01: + { + // Message Length Error + Debug.LogMessage(LogEventLevel.Verbose, this, "Error from device: Message Length Error"); + break; } - else + case 0x02: { - Debug.LogMessage(LogEventLevel.Verbose, this, "Response Queue is empty. Nothing to dequeue."); + // Syntax Error + Debug.LogMessage(LogEventLevel.Verbose, this, "Error from device: Syntax Error"); + break; + } + case 0x03: + { + // Command Buffer Full + Debug.LogMessage(LogEventLevel.Verbose, this, "Error from device: Command Buffer Full"); + break; + } + case 0x04: + { + // Command Cancelled + Debug.LogMessage(LogEventLevel.Verbose, this, "Error from device: Command Cancelled"); + break; + } + case 0x05: + { + // No Socket + Debug.LogMessage(LogEventLevel.Verbose, this, "Error from device: No Socket"); + break; + } + case 0x41: + { + // Command not executable + Debug.LogMessage(LogEventLevel.Verbose, this, "Error from device: Command not executable"); + break; } - } - - break; - } - case 0x60: - { - // Error message - - switch (message[2]) - { - case 0x01: - { - // Message Length Error - Debug.LogMessage(LogEventLevel.Verbose, this, "Error from device: Message Length Error"); - break; - } - case 0x02: - { - // Syntax Error - Debug.LogMessage(LogEventLevel.Verbose, this, "Error from device: Syntax Error"); - break; - } - case 0x03: - { - // Command Buffer Full - Debug.LogMessage(LogEventLevel.Verbose, this, "Error from device: Command Buffer Full"); - break; - } - case 0x04: - { - // Command Cancelled - Debug.LogMessage(LogEventLevel.Verbose, this, "Error from device: Command Cancelled"); - break; - } - case 0x05: - { - // No Socket - Debug.LogMessage(LogEventLevel.Verbose, this, "Error from device: No Socket"); - break; - } - case 0x41: - { - // Command not executable - Debug.LogMessage(LogEventLevel.Verbose, this, "Error from device: Command not executable"); - break; - } - } - break; } - } - - if (message == new byte[] { ResponseID, 0x50, 0x02, 0xFF }) - { - PowerIsOn = true; - } - else if (message == new byte[] { ResponseID, 0x50, 0x03, 0xFF }) - { - PowerIsOn = false; - } + break; + } + } + if (message == new byte[] { ResponseID, 0x50, 0x02, 0xFF }) + { + PowerIsOn = true; + } + else if (message == new byte[] { ResponseID, 0x50, 0x03, 0xFF }) + { + PowerIsOn = false; } } - catch (Exception err) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Error parsing feedback: {0}", err); - } - finally - { - // Save whatever partial message is here - IncomingBuffer = newBytes; - } + } + catch (Exception err) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Error parsing feedback: {0}", err); + } + finally + { + // Save whatever partial message is here + IncomingBuffer = newBytes; + } + } - /// - /// Sends a pan/tilt command. If the command is not for fastSpeed then it starts a timer to initiate fast speed. - /// - /// - /// + /// + /// Sends a pan/tilt command. If the command is not for fastSpeed then it starts a timer to initiate fast speed. + /// + /// + /// private void SendPanTiltCommand (byte[] cmd, bool fastSpeedEnabled) { - SendBytes(GetPanTiltCommand(cmd, fastSpeedEnabled)); + SendBytes(GetPanTiltCommand(cmd, fastSpeedEnabled)); - if (!fastSpeedEnabled) + if (!fastSpeedEnabled) + { + if (SpeedTimer != null) { - if (SpeedTimer != null) - { - StopSpeedTimer(); - } - - // Start the timer to send fast speed if still moving after FastSpeedHoldTime elapses - SpeedTimer = new CTimer((o) => SendPanTiltCommand(GetPanTiltCommand(cmd, true), true), FastSpeedHoldTimeMs); + StopSpeedTimer(); } + // Start the timer to send fast speed if still moving after FastSpeedHoldTime elapses + SpeedTimer = new CTimer((o) => SendPanTiltCommand(GetPanTiltCommand(cmd, true), true), FastSpeedHoldTimeMs); + } + } - private void StopSpeedTimer() + private void StopSpeedTimer() + { + if (SpeedTimer != null) { - if (SpeedTimer != null) - { - SpeedTimer.Stop(); - SpeedTimer.Dispose(); - SpeedTimer = null; - } - } + SpeedTimer.Stop(); + SpeedTimer.Dispose(); + SpeedTimer = null; + } + } - /// - /// Generates the pan/tilt command with either slow or fast speed - /// - /// - /// - /// - private byte[] GetPanTiltCommand(byte[] cmd, bool fastSpeed) - { - byte panSpeed; - byte tiltSpeed; + /// + /// Generates the pan/tilt command with either slow or fast speed + /// + /// + /// + /// + private byte[] GetPanTiltCommand(byte[] cmd, bool fastSpeed) + { + byte panSpeed; + byte tiltSpeed; - if (!fastSpeed) - { - panSpeed = PanSpeedSlow; - tiltSpeed = TiltSpeedSlow; - } - else - { - panSpeed = PanSpeedFast; - tiltSpeed = TiltSpeedFast; - } + if (!fastSpeed) + { + panSpeed = PanSpeedSlow; + tiltSpeed = TiltSpeedSlow; + } + else + { + panSpeed = PanSpeedFast; + tiltSpeed = TiltSpeedFast; + } - var temp = new byte[] { ID, 0x01, 0x06, 0x01, panSpeed, tiltSpeed }; - int length = temp.Length + cmd.Length + 1; + var temp = new byte[] { ID, 0x01, 0x06, 0x01, panSpeed, tiltSpeed }; + int length = temp.Length + cmd.Length + 1; - byte[] sum = new byte[length]; - temp.CopyTo(sum, 0); - cmd.CopyTo(sum, temp.Length); - sum[length - 1] = 0xFF; + byte[] sum = new byte[length]; + temp.CopyTo(sum, 0); + cmd.CopyTo(sum, temp.Length); + sum[length - 1] = 0xFF; - return sum; - } + return sum; + } - void SendPowerQuery() - { - SendBytes(new byte[] { ID, 0x09, 0x04, 0x00, 0xFF }); - InquiryResponseQueue.Enqueue(HandlePowerResponse); - } + void SendPowerQuery() + { + SendBytes(new byte[] { ID, 0x09, 0x04, 0x00, 0xFF }); + InquiryResponseQueue.Enqueue(HandlePowerResponse); + } public void PowerOn() { SendBytes(new byte[] { ID, 0x01, 0x04, 0x00, 0x02, 0xFF }); - SendPowerQuery(); + SendPowerQuery(); } - void HandlePowerResponse(byte[] response) + void HandlePowerResponse(byte[] response) + { + switch (response[0]) { - switch (response[0]) - { - case 0x02: - { - PowerIsOn = true; - break; - } - case 0x03: - { - PowerIsOn = false; - break; - } - } + case 0x02: + { + PowerIsOn = true; + break; + } + case 0x03: + { + PowerIsOn = false; + break; + } } + } public void PowerOff() { SendBytes(new byte[] {ID, 0x01, 0x04, 0x00, 0x03, 0xFF}); - SendPowerQuery(); - } + SendPowerQuery(); + } - public void PowerToggle() - { - if (PowerIsOnFeedback.BoolValue) - PowerOff(); - else - PowerOn(); - } + public void PowerToggle() + { + if (PowerIsOnFeedback.BoolValue) + PowerOff(); + else + PowerOn(); + } public void PanLeft() { @@ -452,27 +452,27 @@ public void PanLeft() } public void PanRight() { - SendPanTiltCommand(new byte[] { 0x02, 0x03 }, false); + SendPanTiltCommand(new byte[] { 0x02, 0x03 }, false); // IsMoving = true; } - public void PanStop() - { - Stop(); - } + public void PanStop() + { + Stop(); + } public void TiltDown() { - SendPanTiltCommand(new byte[] { 0x03, 0x02 }, false); + SendPanTiltCommand(new byte[] { 0x03, 0x02 }, false); // IsMoving = true; } public void TiltUp() { - SendPanTiltCommand(new byte[] { 0x03, 0x01 }, false); + SendPanTiltCommand(new byte[] { 0x03, 0x01 }, false); // IsMoving = true; } - public void TiltStop() - { - Stop(); - } + public void TiltStop() + { + Stop(); + } private void SendZoomCommand (byte cmd) { @@ -482,38 +482,38 @@ private void SendZoomCommand (byte cmd) public void ZoomIn() { - SendZoomCommand(ZoomInCmd); + SendZoomCommand(ZoomInCmd); IsZooming = true; } public void ZoomOut() { - SendZoomCommand(ZoomOutCmd); + SendZoomCommand(ZoomOutCmd); IsZooming = true; } - public void ZoomStop() - { - Stop(); - } + public void ZoomStop() + { + Stop(); + } public void Stop() { if (IsZooming) { - SendZoomCommand(ZoomStopCmd); + SendZoomCommand(ZoomStopCmd); IsZooming = false; } else { - StopSpeedTimer(); - SendPanTiltCommand(new byte[] { 0x03, 0x03 }, false); + StopSpeedTimer(); + SendPanTiltCommand(new byte[] { 0x03, 0x03 }, false); // IsMoving = false; } } - public void PositionHome() - { - SendBytes(new byte[] { ID, 0x01, 0x06, 0x02, PanSpeedFast, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }); - SendBytes(new byte[] { ID, 0x01, 0x04, 0x47, 0x00, 0x00, 0x00, 0x00, 0xFF }); - } + public void PositionHome() + { + SendBytes(new byte[] { ID, 0x01, 0x06, 0x02, PanSpeedFast, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }); + SendBytes(new byte[] { ID, 0x01, 0x04, 0x47, 0x00, 0x00, 0x00, 0x00, 0xFF }); + } public void RecallPreset(int presetNumber) { SendBytes(new byte[] {ID, 0x01, 0x04, 0x3F, 0x02, (byte)presetNumber, 0xFF} ); @@ -523,9 +523,9 @@ public void SavePreset(int presetNumber) SendBytes(new byte[] { ID, 0x01, 0x04, 0x3F, 0x01, (byte)presetNumber, 0xFF }); } - #region IHasCameraPresets Members + #region IHasCameraPresets Members - public event EventHandler PresetsListHasChanged; + public event EventHandler PresetsListHasChanged; protected void OnPresetsListHasChanged() { @@ -536,162 +536,160 @@ protected void OnPresetsListHasChanged() handler.Invoke(this, EventArgs.Empty); } - public List Presets { get; private set; } + public List Presets { get; private set; } - public void PresetSelect(int preset) - { - RecallPreset(preset); - } + public void PresetSelect(int preset) + { + RecallPreset(preset); + } - public void PresetStore(int preset, string description) - { - SavePreset(preset); - } + public void PresetStore(int preset, string description) + { + SavePreset(preset); + } - #endregion + #endregion - #region IHasCameraFocusControl Members + #region IHasCameraFocusControl Members - public void FocusNear() - { - SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x03, 0xFF }); - } + public void FocusNear() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x03, 0xFF }); + } - public void FocusFar() - { - SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x02, 0xFF }); - } + public void FocusFar() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x02, 0xFF }); + } - public void FocusStop() - { - SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x00, 0xFF }); - } + public void FocusStop() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x00, 0xFF }); + } - public void TriggerAutoFocus() - { - SendBytes(new byte[] { ID, 0x01, 0x04, 0x18, 0x01, 0xFF }); - SendAutoFocusQuery(); - } + public void TriggerAutoFocus() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x18, 0x01, 0xFF }); + SendAutoFocusQuery(); + } - #endregion + #endregion - #region IHasAutoFocus Members + #region IHasAutoFocus Members - public void SetFocusModeAuto() - { - SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x02, 0xFF }); - SendAutoFocusQuery(); - } + public void SetFocusModeAuto() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x02, 0xFF }); + SendAutoFocusQuery(); + } - public void SetFocusModeManual() - { - SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x03, 0xFF }); - SendAutoFocusQuery(); - } + public void SetFocusModeManual() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x03, 0xFF }); + SendAutoFocusQuery(); + } - public void ToggleFocusMode() - { - SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x10, 0xFF }); - SendAutoFocusQuery(); - } + public void ToggleFocusMode() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x10, 0xFF }); + SendAutoFocusQuery(); + } - #endregion + #endregion - void SendAutoFocusQuery() - { - SendBytes(new byte[] { ID, 0x09, 0x04, 0x38, 0xFF }); - InquiryResponseQueue.Enqueue(HandleAutoFocusResponse); - } + void SendAutoFocusQuery() + { + SendBytes(new byte[] { ID, 0x09, 0x04, 0x38, 0xFF }); + InquiryResponseQueue.Enqueue(HandleAutoFocusResponse); + } - void HandleAutoFocusResponse(byte[] response) + void HandleAutoFocusResponse(byte[] response) + { + switch (response[0]) { - switch (response[0]) - { - case 0x02: - { - // Auto Mode - PowerIsOn = true; - break; - } - case 0x03: - { - // Manual Mode - PowerIsOn = false; - break; - } - } + case 0x02: + { + // Auto Mode + PowerIsOn = true; + break; + } + case 0x03: + { + // Manual Mode + PowerIsOn = false; + break; + } } + } - #region IHasCameraOff Members - - public BoolFeedback CameraIsOffFeedback { get; private set; } - + #region IHasCameraOff Members - public void CameraOff() - { - PowerOff(); - } + public BoolFeedback CameraIsOffFeedback { get; private set; } - #endregion - } - public class CameraViscaFactory : EssentialsDeviceFactory + public void CameraOff() { - public CameraViscaFactory() - { - TypeNames = new List() { "cameravisca" }; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new CameraVisca Device"); - var comm = CommFactory.CreateCommForDevice(dc); - var props = Newtonsoft.Json.JsonConvert.DeserializeObject( - dc.Properties.ToString()); - return new Cameras.CameraVisca(dc.Key, dc.Name, comm, props); - } + PowerOff(); } + #endregion +} - public class CameraViscaPropertiesConfig : CameraPropertiesConfig +public class CameraViscaFactory : EssentialsDeviceFactory +{ + public CameraViscaFactory() { - /// - /// Control ID of the camera (1-7) - /// - [JsonProperty("id")] - public uint Id { get; set; } - - /// - /// Slow Pan speed (0-18) - /// - [JsonProperty("panSpeedSlow")] - public uint PanSpeedSlow { get; set; } - - /// - /// Fast Pan speed (0-18) - /// - [JsonProperty("panSpeedFast")] - public uint PanSpeedFast { get; set; } - - /// - /// Slow tilt speed (0-18) - /// - [JsonProperty("tiltSpeedSlow")] - public uint TiltSpeedSlow { get; set; } - - /// - /// Fast tilt speed (0-18) - /// - [JsonProperty("tiltSpeedFast")] - public uint TiltSpeedFast { get; set; } - - /// - /// Time a button must be held before fast speed is engaged (Milliseconds) - /// - [JsonProperty("fastSpeedHoldTimeMs")] - public uint FastSpeedHoldTimeMs { get; set; } + TypeNames = new List() { "cameravisca" }; + } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new CameraVisca Device"); + var comm = CommFactory.CreateCommForDevice(dc); + var props = Newtonsoft.Json.JsonConvert.DeserializeObject( + dc.Properties.ToString()); + return new Cameras.CameraVisca(dc.Key, dc.Name, comm, props); } +} + + +public class CameraViscaPropertiesConfig : CameraPropertiesConfig +{ + /// + /// Control ID of the camera (1-7) + /// + [JsonProperty("id")] + public uint Id { get; set; } + + /// + /// Slow Pan speed (0-18) + /// + [JsonProperty("panSpeedSlow")] + public uint PanSpeedSlow { get; set; } + + /// + /// Fast Pan speed (0-18) + /// + [JsonProperty("panSpeedFast")] + public uint PanSpeedFast { get; set; } + + /// + /// Slow tilt speed (0-18) + /// + [JsonProperty("tiltSpeedSlow")] + public uint TiltSpeedSlow { get; set; } + + /// + /// Fast tilt speed (0-18) + /// + [JsonProperty("tiltSpeedFast")] + public uint TiltSpeedFast { get; set; } + + /// + /// Time a button must be held before fast speed is engaged (Milliseconds) + /// + [JsonProperty("fastSpeedHoldTimeMs")] + public uint FastSpeedHoldTimeMs { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/IHasCameraPresets.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/IHasCameraPresets.cs index a8e8983de..2f973c3f1 100644 --- a/src/PepperDash.Essentials.Devices.Common/Cameras/IHasCameraPresets.cs +++ b/src/PepperDash.Essentials.Devices.Common/Cameras/IHasCameraPresets.cs @@ -4,19 +4,18 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Devices.Common.Cameras +namespace PepperDash.Essentials.Devices.Common.Cameras; + +/// +/// Describes a camera with preset functionality +/// +public interface IHasCameraPresets { - /// - /// Describes a camera with preset functionality - /// - public interface IHasCameraPresets - { - event EventHandler PresetsListHasChanged; + event EventHandler PresetsListHasChanged; - List Presets { get; } + List Presets { get; } - void PresetSelect(int preset); + void PresetSelect(int preset); - void PresetStore(int preset, string description); - } + void PresetStore(int preset, string description); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/Cisco/IPresenterTrack.cs b/src/PepperDash.Essentials.Devices.Common/Codec/Cisco/IPresenterTrack.cs index f3f164bd0..6ec7de16d 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/Cisco/IPresenterTrack.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/Cisco/IPresenterTrack.cs @@ -6,90 +6,89 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Devices.Common.Codec.Cisco +namespace PepperDash.Essentials.Devices.Common.Codec.Cisco; + +/// +/// Describes the available tracking modes for a Cisco codec's Presenter Track feature. +/// +public enum ePresenterTrackMode { /// - /// Describes the available tracking modes for a Cisco codec's Presenter Track feature. + /// Presenter Track is turned off. + /// + Off, + /// + /// Presenter Track follows the speaker's movements. + /// + Follow, + /// + /// Presenter Track is set to background mode, where it tracks the speaker but does not actively follow. + /// + Background, + /// + /// Presenter Track is set to persistent mode, where it maintains a fixed position or focus on the speaker. /// - public enum ePresenterTrackMode - { - /// - /// Presenter Track is turned off. - /// - Off, - /// - /// Presenter Track follows the speaker's movements. - /// - Follow, - /// - /// Presenter Track is set to background mode, where it tracks the speaker but does not actively follow. - /// - Background, - /// - /// Presenter Track is set to persistent mode, where it maintains a fixed position or focus on the speaker. - /// - Persistent - } + Persistent +} +/// +/// Describes the Presenter Track controls for a Cisco codec. +/// +public interface IPresenterTrack : IKeyed +{ /// - /// Describes the Presenter Track controls for a Cisco codec. + /// /// - public interface IPresenterTrack : IKeyed - { - /// - /// - /// - bool PresenterTrackAvailability { get; } + bool PresenterTrackAvailability { get; } - /// - /// Feedback indicating whether Presenter Track is available. - /// - BoolFeedback PresenterTrackAvailableFeedback { get; } + /// + /// Feedback indicating whether Presenter Track is available. + /// + BoolFeedback PresenterTrackAvailableFeedback { get; } - /// - /// Feedback indicating the current status of Presenter Track is off - /// - BoolFeedback PresenterTrackStatusOffFeedback { get; } + /// + /// Feedback indicating the current status of Presenter Track is off + /// + BoolFeedback PresenterTrackStatusOffFeedback { get; } - /// - /// Feedback indicating the current status of Presenter Track is follow - /// - BoolFeedback PresenterTrackStatusFollowFeedback { get; } + /// + /// Feedback indicating the current status of Presenter Track is follow + /// + BoolFeedback PresenterTrackStatusFollowFeedback { get; } - /// - /// Feedback indicating the current status of Presenter Track is background - /// - BoolFeedback PresenterTrackStatusBackgroundFeedback { get; } + /// + /// Feedback indicating the current status of Presenter Track is background + /// + BoolFeedback PresenterTrackStatusBackgroundFeedback { get; } - /// - /// Feedback indicating the current status of Presenter Track is persistent - /// - BoolFeedback PresenterTrackStatusPersistentFeedback { get; } + /// + /// Feedback indicating the current status of Presenter Track is persistent + /// + BoolFeedback PresenterTrackStatusPersistentFeedback { get; } - /// - /// Indicates the current status of Presenter Track. - /// - bool PresenterTrackStatus { get; } + /// + /// Indicates the current status of Presenter Track. + /// + bool PresenterTrackStatus { get; } - /// - /// Turns off Presenter Track. - /// - void PresenterTrackOff(); + /// + /// Turns off Presenter Track. + /// + void PresenterTrackOff(); - /// - /// Turns on Presenter Track in follow mode. - /// - void PresenterTrackFollow(); + /// + /// Turns on Presenter Track in follow mode. + /// + void PresenterTrackFollow(); - /// - /// Turns on Presenter Track in background mode. - /// - void PresenterTrackBackground(); + /// + /// Turns on Presenter Track in background mode. + /// + void PresenterTrackBackground(); - /// - /// Turns on Presenter Track in persistent mode. - /// - void PresenterTrackPersistent(); - } + /// + /// Turns on Presenter Track in persistent mode. + /// + void PresenterTrackPersistent(); } diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/Cisco/ISpeakerTrack.cs b/src/PepperDash.Essentials.Devices.Common/Codec/Cisco/ISpeakerTrack.cs index 83735183d..f00af25b2 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/Cisco/ISpeakerTrack.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/Cisco/ISpeakerTrack.cs @@ -6,35 +6,34 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Devices.Common.Codec.Cisco +namespace PepperDash.Essentials.Devices.Common.Codec.Cisco; + +/// +/// Describes the available tracking modes for a Cisco codec +/// +public interface ISpeakerTrack : IKeyed { /// - /// Describes the available tracking modes for a Cisco codec + /// Indicates whether Speaker Track is available on the codec. /// - public interface ISpeakerTrack : IKeyed - { - /// - /// Indicates whether Speaker Track is available on the codec. - /// - bool SpeakerTrackAvailability { get; } + bool SpeakerTrackAvailability { get; } - /// - /// - /// - BoolFeedback SpeakerTrackAvailableFeedback { get; } + /// + /// + /// + BoolFeedback SpeakerTrackAvailableFeedback { get; } - /// - /// Feedback indicating the current status of Speaker Track is off - /// - bool SpeakerTrackStatus { get; } + /// + /// Feedback indicating the current status of Speaker Track is off + /// + bool SpeakerTrackStatus { get; } - /// - /// Turns Speaker Track off - /// - void SpeakerTrackOff(); - /// - /// Turns Speaker Track on - /// - void SpeakerTrackOn(); - } + /// + /// Turns Speaker Track off + /// + void SpeakerTrackOff(); + /// + /// Turns Speaker Track on + /// + void SpeakerTrackOn(); } diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/CodecActiveCallItem.cs b/src/PepperDash.Essentials.Devices.Common/Codec/CodecActiveCallItem.cs index a8b8d563a..1a034c8e7 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/CodecActiveCallItem.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/CodecActiveCallItem.cs @@ -9,67 +9,66 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec; + +public class CodecActiveCallItem { - public class CodecActiveCallItem - { [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] - public string Name { get; set; } + public string Name { get; set; } - [JsonProperty("number", NullValueHandling = NullValueHandling.Ignore)] - public string Number { get; set; } + [JsonProperty("number", NullValueHandling = NullValueHandling.Ignore)] + public string Number { get; set; } - [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] + [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] [JsonConverter(typeof(StringEnumConverter))] - public eCodecCallType Type { get; set; } + public eCodecCallType Type { get; set; } - [JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)] + [JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)] [JsonConverter(typeof(StringEnumConverter))] - public eCodecCallStatus Status { get; set; } + public eCodecCallStatus Status { get; set; } - [JsonProperty("direction", NullValueHandling = NullValueHandling.Ignore)] + [JsonProperty("direction", NullValueHandling = NullValueHandling.Ignore)] [JsonConverter(typeof(StringEnumConverter))] - public eCodecCallDirection Direction { get; set; } + public eCodecCallDirection Direction { get; set; } - [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] - public string Id { get; set; } + [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] + public string Id { get; set; } - [JsonProperty("isOnHold", NullValueHandling = NullValueHandling.Ignore)] - public bool IsOnHold { get; set; } + [JsonProperty("isOnHold", NullValueHandling = NullValueHandling.Ignore)] + public bool IsOnHold { get; set; } - [JsonProperty("duration", NullValueHandling = NullValueHandling.Ignore)] - public TimeSpan Duration { get; set; } + [JsonProperty("duration", NullValueHandling = NullValueHandling.Ignore)] + public TimeSpan Duration { get; set; } - //public object CallMetaData { get; set; } + //public object CallMetaData { get; set; } - /// - /// Returns true when this call is any status other than - /// Unknown, Disconnected, Disconnecting - /// - [JsonProperty("isActiveCall", NullValueHandling = NullValueHandling.Ignore)] - public bool IsActiveCall + /// + /// Returns true when this call is any status other than + /// Unknown, Disconnected, Disconnecting + /// + [JsonProperty("isActiveCall", NullValueHandling = NullValueHandling.Ignore)] + public bool IsActiveCall + { + get { - get - { - return !(Status == eCodecCallStatus.Disconnected - || Status == eCodecCallStatus.Disconnecting + return !(Status == eCodecCallStatus.Disconnected + || Status == eCodecCallStatus.Disconnecting || Status == eCodecCallStatus.Idle - || Status == eCodecCallStatus.Unknown); - } + || Status == eCodecCallStatus.Unknown); } } +} - /// - /// - /// - public class CodecCallStatusItemChangeEventArgs : EventArgs - { - public CodecActiveCallItem CallItem { get; private set; } +/// +/// +/// +public class CodecCallStatusItemChangeEventArgs : EventArgs +{ + public CodecActiveCallItem CallItem { get; private set; } - public CodecCallStatusItemChangeEventArgs(CodecActiveCallItem item) - { - CallItem = item; - } + public CodecCallStatusItemChangeEventArgs(CodecActiveCallItem item) + { + CallItem = item; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/ICiscoCodecCameraConfig.cs b/src/PepperDash.Essentials.Devices.Common/Codec/ICiscoCodecCameraConfig.cs index fefb4b098..a9fcdf94e 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/ICiscoCodecCameraConfig.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/ICiscoCodecCameraConfig.cs @@ -5,27 +5,26 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Devices.Common.Codec -{ - /// - /// Describes a cisco codec device that can allow configuration of cameras - /// - public interface ICiscoCodecCameraConfig - { - void SetCameraAssignedSerialNumber(uint cameraId, string serialNumber); +namespace PepperDash.Essentials.Devices.Common.Codec; - void SetCameraName(uint videoConnectorId, string name); +/// +/// Describes a cisco codec device that can allow configuration of cameras +/// +public interface ICiscoCodecCameraConfig +{ + void SetCameraAssignedSerialNumber(uint cameraId, string serialNumber); - void SetInputSourceType(uint videoConnectorId, eCiscoCodecInputSourceType sourceType); - } + void SetCameraName(uint videoConnectorId, string name); - public enum eCiscoCodecInputSourceType - { - PC, - camera, - document_camera, - mediaplayer, - other, - whiteboard - } + void SetInputSourceType(uint videoConnectorId, eCiscoCodecInputSourceType sourceType); +} + +public enum eCiscoCodecInputSourceType +{ + PC, + camera, + document_camera, + mediaplayer, + other, + whiteboard } diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/IHasCallHold.cs b/src/PepperDash.Essentials.Devices.Common/Codec/IHasCallHold.cs index 782118411..a29215b7b 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/IHasCallHold.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/IHasCallHold.cs @@ -4,20 +4,19 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec; + +public interface IHasCallHold { - public interface IHasCallHold - { - /// - /// Put the specified call on hold - /// - /// - void HoldCall(CodecActiveCallItem activeCall); + /// + /// Put the specified call on hold + /// + /// + void HoldCall(CodecActiveCallItem activeCall); - /// - /// Resume the specified call - /// - /// - void ResumeCall(CodecActiveCallItem activeCall); - } + /// + /// Resume the specified call + /// + /// + void ResumeCall(CodecActiveCallItem activeCall); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/IHasDoNotDisturb.cs b/src/PepperDash.Essentials.Devices.Common/Codec/IHasDoNotDisturb.cs index 7bb9b9242..70d96e9b9 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/IHasDoNotDisturb.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/IHasDoNotDisturb.cs @@ -6,40 +6,39 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec; + +/// +/// Describes a device that has Do Not Disturb mode capability +/// +public interface IHasDoNotDisturbMode { /// - /// Describes a device that has Do Not Disturb mode capability + /// Indictes whether Do Not Disturb mode is on (Activated) /// - public interface IHasDoNotDisturbMode - { - /// - /// Indictes whether Do Not Disturb mode is on (Activated) - /// - BoolFeedback DoNotDisturbModeIsOnFeedback { get; } + BoolFeedback DoNotDisturbModeIsOnFeedback { get; } - /// - /// Activates Do Not Disturb mode - /// - void ActivateDoNotDisturbMode(); + /// + /// Activates Do Not Disturb mode + /// + void ActivateDoNotDisturbMode(); - /// - /// Deactivates Do Not Disturb mode - /// - void DeactivateDoNotDisturbMode(); + /// + /// Deactivates Do Not Disturb mode + /// + void DeactivateDoNotDisturbMode(); - /// - /// Toggles Do Not Disturb mode - /// - void ToggleDoNotDisturbMode(); - } + /// + /// Toggles Do Not Disturb mode + /// + void ToggleDoNotDisturbMode(); +} - public interface IHasDoNotDisturbModeWithTimeout : IHasDoNotDisturbMode - { - /// - /// Activates Do Not Disturb mode with a timeout - /// - /// - void ActivateDoNotDisturbMode(int timeout); - } +public interface IHasDoNotDisturbModeWithTimeout : IHasDoNotDisturbMode +{ + /// + /// Activates Do Not Disturb mode with a timeout + /// + /// + void ActivateDoNotDisturbMode(int timeout); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/IHasExternalSourceSwitching.cs b/src/PepperDash.Essentials.Devices.Common/Codec/IHasExternalSourceSwitching.cs index 1ea6b09b2..b13bce1e5 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/IHasExternalSourceSwitching.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/IHasExternalSourceSwitching.cs @@ -6,17 +6,15 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco; -namespace PepperDash.Essentials.Devices.Common.Codec -{ +namespace PepperDash.Essentials.Devices.Common.Codec; + public interface IHasExternalSourceSwitching { bool ExternalSourceListEnabled { get; } - string ExternalSourceInputPort { get; } + string ExternalSourceInputPort { get; } void AddExternalSource(string connectorId, string key, string name, eExternalSourceType type); void SetExternalSourceState(string key, eExternalSourceMode mode); void ClearExternalSources(); - void SetSelectedSource(string key); + void SetSelectedSource(string key); Action RunRouteAction { set;} - } - -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallDirection.cs b/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallDirection.cs index a5e118dfa..f705fc50e 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallDirection.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallDirection.cs @@ -4,38 +4,37 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec; + +public enum eCodecCallDirection { - public enum eCodecCallDirection - { - Unknown = 0, Incoming, Outgoing - } + Unknown = 0, Incoming, Outgoing +} - public class CodecCallDirection +public class CodecCallDirection +{ + /// + /// Takes the Cisco call type and converts to the matching enum + /// + /// + /// + public static eCodecCallDirection ConvertToDirectionEnum(string s) { - /// - /// Takes the Cisco call type and converts to the matching enum - /// - /// - /// - public static eCodecCallDirection ConvertToDirectionEnum(string s) + switch (s.ToLower()) { - switch (s.ToLower()) - { - case "incoming": - { - return eCodecCallDirection.Incoming; - } - case "outgoing": - { - return eCodecCallDirection.Outgoing; - } - default: - return eCodecCallDirection.Unknown; - } - + case "incoming": + { + return eCodecCallDirection.Incoming; + } + case "outgoing": + { + return eCodecCallDirection.Outgoing; + } + default: + return eCodecCallDirection.Unknown; } } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallStatus.cs b/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallStatus.cs index 610d928ba..2a4627751 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallStatus.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallStatus.cs @@ -4,86 +4,85 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec; + +public enum eCodecCallStatus { - public enum eCodecCallStatus - { - Unknown = 0, - Connected, - Connecting, - Dialing, - Disconnected, - Disconnecting, - EarlyMedia, - Idle, - OnHold, - Ringing, - Preserved, - RemotePreserved, - } + Unknown = 0, + Connected, + Connecting, + Dialing, + Disconnected, + Disconnecting, + EarlyMedia, + Idle, + OnHold, + Ringing, + Preserved, + RemotePreserved, +} - public class CodecCallStatus - { +public class CodecCallStatus +{ - /// - /// Takes the Cisco call type and converts to the matching enum - /// - /// - /// - public static eCodecCallStatus ConvertToStatusEnum(string s) + /// + /// Takes the Cisco call type and converts to the matching enum + /// + /// + /// + public static eCodecCallStatus ConvertToStatusEnum(string s) + { + switch (s) { - switch (s) - { - case "Connected": - { - return eCodecCallStatus.Connected; - } - case "Connecting": - { - return eCodecCallStatus.Connecting; - } - case "Dialling": - { - return eCodecCallStatus.Dialing; - } - case "Disconnected": - { - return eCodecCallStatus.Disconnected; - } - case "Disconnecting": - { - return eCodecCallStatus.Disconnecting; - } - case "EarlyMedia": - { - return eCodecCallStatus.EarlyMedia; - } - case "Idle": - { - return eCodecCallStatus.Idle; - } - case "OnHold": - { - return eCodecCallStatus.OnHold; - } - case "Ringing": - { - return eCodecCallStatus.Ringing; - } - case "Preserved": - { - return eCodecCallStatus.Preserved; - } - case "RemotePreserved": - { - return eCodecCallStatus.RemotePreserved; - } - default: - return eCodecCallStatus.Unknown; - } - + case "Connected": + { + return eCodecCallStatus.Connected; + } + case "Connecting": + { + return eCodecCallStatus.Connecting; + } + case "Dialling": + { + return eCodecCallStatus.Dialing; + } + case "Disconnected": + { + return eCodecCallStatus.Disconnected; + } + case "Disconnecting": + { + return eCodecCallStatus.Disconnecting; + } + case "EarlyMedia": + { + return eCodecCallStatus.EarlyMedia; + } + case "Idle": + { + return eCodecCallStatus.Idle; + } + case "OnHold": + { + return eCodecCallStatus.OnHold; + } + case "Ringing": + { + return eCodecCallStatus.Ringing; + } + case "Preserved": + { + return eCodecCallStatus.Preserved; + } + case "RemotePreserved": + { + return eCodecCallStatus.RemotePreserved; + } + default: + return eCodecCallStatus.Unknown; } } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallType.cs b/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallType.cs index dbab015bd..ccadae104 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallType.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/eCodecCallType.cs @@ -4,51 +4,50 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec; + +public enum eCodecCallType { - public enum eCodecCallType - { - Unknown = 0, - Audio, - Video, - AudioCanEscalate, - ForwardAllCall - } + Unknown = 0, + Audio, + Video, + AudioCanEscalate, + ForwardAllCall +} - public class CodecCallType - { +public class CodecCallType +{ - /// - /// Takes the Cisco call type and converts to the matching enum - /// - /// - /// - public static eCodecCallType ConvertToTypeEnum(string s) + /// + /// Takes the Cisco call type and converts to the matching enum + /// + /// + /// + public static eCodecCallType ConvertToTypeEnum(string s) + { + switch (s) { - switch (s) - { - case "Audio": - { - return eCodecCallType.Audio; - } - case "Video": - { - return eCodecCallType.Video; - } - case "AudioCanEscalate": - { - return eCodecCallType.AudioCanEscalate; - } - case "ForwardAllCall": - { - return eCodecCallType.ForwardAllCall; - } - default: - return eCodecCallType.Unknown; - } - + case "Audio": + { + return eCodecCallType.Audio; + } + case "Video": + { + return eCodecCallType.Video; + } + case "AudioCanEscalate": + { + return eCodecCallType.AudioCanEscalate; + } + case "ForwardAllCall": + { + return eCodecCallType.ForwardAllCall; + } + default: + return eCodecCallType.Unknown; } } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/eMeetingPrivacy.cs b/src/PepperDash.Essentials.Devices.Common/Codec/eMeetingPrivacy.cs index f163a8646..5885adb5e 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/eMeetingPrivacy.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/eMeetingPrivacy.cs @@ -4,39 +4,38 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec; + +public enum eMeetingPrivacy { - public enum eMeetingPrivacy - { - Unknown = 0, - Public, - Private - } + Unknown = 0, + Public, + Private +} - public class CodecCallPrivacy +public class CodecCallPrivacy +{ + /// + /// Takes the Cisco privacy type and converts to the matching enum + /// + /// + /// + public static eMeetingPrivacy ConvertToDirectionEnum(string s) { - /// - /// Takes the Cisco privacy type and converts to the matching enum - /// - /// - /// - public static eMeetingPrivacy ConvertToDirectionEnum(string s) + switch (s.ToLower()) { - switch (s.ToLower()) - { - case "public": - { - return eMeetingPrivacy.Public; - } - case "private": - { - return eMeetingPrivacy.Private; - } - default: - return eMeetingPrivacy.Unknown; - } - + case "public": + { + return eMeetingPrivacy.Public; + } + case "private": + { + return eMeetingPrivacy.Private; + } + default: + return eMeetingPrivacy.Unknown; } } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/iCodecAudio.cs b/src/PepperDash.Essentials.Devices.Common/Codec/iCodecAudio.cs index d61f7d26a..654d3d6e2 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/iCodecAudio.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/iCodecAudio.cs @@ -6,13 +6,12 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec; + +/// +/// Defines minimum volume controls for a codec device with dialing capabilities +/// +public interface ICodecAudio : IBasicVolumeWithFeedback, IPrivacy { - /// - /// Defines minimum volume controls for a codec device with dialing capabilities - /// - public interface ICodecAudio : IBasicVolumeWithFeedback, IPrivacy - { - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/iHasCallFavorites.cs b/src/PepperDash.Essentials.Devices.Common/Codec/iHasCallFavorites.cs index 50c1b2c9e..73cdd49c5 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/iHasCallFavorites.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/iHasCallFavorites.cs @@ -4,23 +4,22 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec; + +public interface IHasCallFavorites { - public interface IHasCallFavorites - { - CodecCallFavorites CallFavorites { get; } - } + CodecCallFavorites CallFavorites { get; } +} - /// - /// Represents favorites entries for a codec device - /// - public class CodecCallFavorites - { - public List Favorites { get; set; } +/// +/// Represents favorites entries for a codec device +/// +public class CodecCallFavorites +{ + public List Favorites { get; set; } - public CodecCallFavorites() - { - Favorites = new List(); - } + public CodecCallFavorites() + { + Favorites = new List(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/iHasCallHistory.cs b/src/PepperDash.Essentials.Devices.Common/Codec/iHasCallHistory.cs index 5291a3931..2a3e9bbf1 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/iHasCallHistory.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/iHasCallHistory.cs @@ -7,132 +7,131 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec; + + +public interface IHasCallHistory { + CodecCallHistory CallHistory { get; } - public interface IHasCallHistory - { - CodecCallHistory CallHistory { get; } + void RemoveCallHistoryEntry(CodecCallHistory.CallHistoryEntry entry); +} - void RemoveCallHistoryEntry(CodecCallHistory.CallHistoryEntry entry); - } +public enum eCodecOccurrenceType +{ + Unknown = 0, + Placed = 1, + Received = 2, + NoAnswer = 3, +} + +/// +/// Represents the recent call history for a codec device +/// +public class CodecCallHistory +{ + public event EventHandler RecentCallsListHasChanged; - public enum eCodecOccurrenceType - { - Unknown = 0, - Placed = 1, - Received = 2, - NoAnswer = 3, - } + public List RecentCalls { get; private set; } /// - /// Represents the recent call history for a codec device + /// Item that gets added to the list when there are no recent calls in history /// - public class CodecCallHistory + CallHistoryEntry ListEmptyEntry; + + public CodecCallHistory() { - public event EventHandler RecentCallsListHasChanged; + ListEmptyEntry = new CallHistoryEntry() { Name = "No Recent Calls" }; - public List RecentCalls { get; private set; } + RecentCalls = new List(); - /// - /// Item that gets added to the list when there are no recent calls in history - /// - CallHistoryEntry ListEmptyEntry; + RecentCalls.Add(ListEmptyEntry); + } - public CodecCallHistory() + void OnRecentCallsListChange() + { + var handler = RecentCallsListHasChanged; + if (handler != null) { - ListEmptyEntry = new CallHistoryEntry() { Name = "No Recent Calls" }; - - RecentCalls = new List(); - - RecentCalls.Add(ListEmptyEntry); + handler(this, new EventArgs()); } + } - void OnRecentCallsListChange() - { - var handler = RecentCallsListHasChanged; - if (handler != null) - { - handler(this, new EventArgs()); - } - } + public void RemoveEntry(CallHistoryEntry entry) + { + RecentCalls.Remove(entry); + OnRecentCallsListChange(); + } - public void RemoveEntry(CallHistoryEntry entry) - { - RecentCalls.Remove(entry); - OnRecentCallsListChange(); - } + /// + /// Generic call history entry, not device specific + /// + public class CallHistoryEntry : CodecActiveCallItem + { + [JsonConverter(typeof(IsoDateTimeConverter))] + [JsonProperty("startTime")] + public DateTime StartTime { get; set; } + [JsonConverter(typeof(StringEnumConverter))] + [JsonProperty("occurrenceType")] + public eCodecOccurrenceType OccurrenceType { get; set; } + [JsonProperty("occurrenceHistoryId")] + public string OccurrenceHistoryId { get; set; } + } - /// - /// Generic call history entry, not device specific - /// - public class CallHistoryEntry : CodecActiveCallItem - { - [JsonConverter(typeof(IsoDateTimeConverter))] - [JsonProperty("startTime")] - public DateTime StartTime { get; set; } - [JsonConverter(typeof(StringEnumConverter))] - [JsonProperty("occurrenceType")] - public eCodecOccurrenceType OccurrenceType { get; set; } - [JsonProperty("occurrenceHistoryId")] - public string OccurrenceHistoryId { get; set; } - } + /// + /// Converts a list of call history entries returned by a Cisco codec to the generic list type + /// + /// + /// + public void ConvertCiscoCallHistoryToGeneric(List entries) + { + var genericEntries = new List(); - /// - /// Converts a list of call history entries returned by a Cisco codec to the generic list type - /// - /// - /// - public void ConvertCiscoCallHistoryToGeneric(List entries) + foreach (CiscoCallHistory.Entry entry in entries) { - var genericEntries = new List(); - foreach (CiscoCallHistory.Entry entry in entries) + genericEntries.Add(new CallHistoryEntry() { - - genericEntries.Add(new CallHistoryEntry() - { - Name = entry.DisplayName.Value, - Number = entry.CallbackNumber.Value, - StartTime = entry.LastOccurrenceStartTime.Value, - OccurrenceHistoryId = entry.LastOccurrenceHistoryId.Value, - OccurrenceType = ConvertToOccurenceTypeEnum(entry.OccurrenceType.Value) - }); - } - - // Check if list is empty and if so, add an item to display No Recent Calls - if(genericEntries.Count == 0) - genericEntries.Add(ListEmptyEntry); - - RecentCalls = genericEntries; - OnRecentCallsListChange(); + Name = entry.DisplayName.Value, + Number = entry.CallbackNumber.Value, + StartTime = entry.LastOccurrenceStartTime.Value, + OccurrenceHistoryId = entry.LastOccurrenceHistoryId.Value, + OccurrenceType = ConvertToOccurenceTypeEnum(entry.OccurrenceType.Value) + }); } - /// - /// Takes the Cisco occurence type and converts it to the matching enum - /// - /// - public eCodecOccurrenceType ConvertToOccurenceTypeEnum(string s) - { - switch (s) - { - case "Placed": - { - return eCodecOccurrenceType.Placed; - } - case "Received": - { - return eCodecOccurrenceType.Received; - } - case "NoAnswer": - { - return eCodecOccurrenceType.NoAnswer; - } - default: - return eCodecOccurrenceType.Unknown; - } + // Check if list is empty and if so, add an item to display No Recent Calls + if(genericEntries.Count == 0) + genericEntries.Add(ListEmptyEntry); + + RecentCalls = genericEntries; + OnRecentCallsListChange(); + } + /// + /// Takes the Cisco occurence type and converts it to the matching enum + /// + /// + public eCodecOccurrenceType ConvertToOccurenceTypeEnum(string s) + { + switch (s) + { + case "Placed": + { + return eCodecOccurrenceType.Placed; + } + case "Received": + { + return eCodecOccurrenceType.Received; + } + case "NoAnswer": + { + return eCodecOccurrenceType.NoAnswer; + } + default: + return eCodecOccurrenceType.Unknown; } } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/iHasContentSharing.cs b/src/PepperDash.Essentials.Devices.Common/Codec/iHasContentSharing.cs index f3c28243d..cdbdc7668 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/iHasContentSharing.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/iHasContentSharing.cs @@ -8,17 +8,15 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Devices.Common.Codec -{ - public interface IHasContentSharing - { - BoolFeedback SharingContentIsOnFeedback { get; } - StringFeedback SharingSourceFeedback { get; } +namespace PepperDash.Essentials.Devices.Common.Codec; - bool AutoShareContentWhileInCall { get; } +public interface IHasContentSharing +{ + BoolFeedback SharingContentIsOnFeedback { get; } + StringFeedback SharingSourceFeedback { get; } - void StartSharing(); - void StopSharing(); - } + bool AutoShareContentWhileInCall { get; } + void StartSharing(); + void StopSharing(); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/iHasDialer.cs b/src/PepperDash.Essentials.Devices.Common/Codec/iHasDialer.cs index bce2dee36..7668e1202 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/iHasDialer.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/iHasDialer.cs @@ -6,25 +6,23 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Devices.Common.Codec -{ - /// - /// Requirements for a device that has dialing capabilities - /// - public interface IHasDialer - { - // Add requirements for Dialer functionality +namespace PepperDash.Essentials.Devices.Common.Codec; - event EventHandler CallStatusChange; +/// +/// Requirements for a device that has dialing capabilities +/// +public interface IHasDialer +{ + // Add requirements for Dialer functionality - void Dial(string number); - void EndCall(CodecActiveCallItem activeCall); - void EndAllCalls(); - void AcceptCall(CodecActiveCallItem item); - void RejectCall(CodecActiveCallItem item); - void SendDtmf(string digit); + event EventHandler CallStatusChange; - bool IsInCall { get; } - } + void Dial(string number); + void EndCall(CodecActiveCallItem activeCall); + void EndAllCalls(); + void AcceptCall(CodecActiveCallItem item); + void RejectCall(CodecActiveCallItem item); + void SendDtmf(string digit); + bool IsInCall { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/iHasDirectory.cs b/src/PepperDash.Essentials.Devices.Common/Codec/iHasDirectory.cs index 6a4e62fe4..1c0218151 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/iHasDirectory.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/iHasDirectory.cs @@ -14,233 +14,233 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Devices.Common.VideoCodec; -namespace PepperDash.Essentials.Devices.Common.Codec -{ +namespace PepperDash.Essentials.Devices.Common.Codec; + /// /// Defines the API for codecs with a directory /// - public interface IHasDirectory - { - event EventHandler DirectoryResultReturned; +public interface IHasDirectory +{ + event EventHandler DirectoryResultReturned; - CodecDirectory DirectoryRoot { get; } + CodecDirectory DirectoryRoot { get; } - CodecDirectory CurrentDirectoryResult { get; } + CodecDirectory CurrentDirectoryResult { get; } - CodecPhonebookSyncState PhonebookSyncState { get; } + CodecPhonebookSyncState PhonebookSyncState { get; } - void SearchDirectory(string searchString); + void SearchDirectory(string searchString); - void GetDirectoryFolderContents(string folderId); + void GetDirectoryFolderContents(string folderId); - void SetCurrentDirectoryToRoot(); + void SetCurrentDirectoryToRoot(); - void GetDirectoryParentFolderContents(); + void GetDirectoryParentFolderContents(); - BoolFeedback CurrentDirectoryResultIsNotDirectoryRoot { get; } - } + BoolFeedback CurrentDirectoryResultIsNotDirectoryRoot { get; } +} - public interface IHasDirectoryHistoryStack : IHasDirectory - { - Stack DirectoryBrowseHistoryStack { get; } - } +public interface IHasDirectoryHistoryStack : IHasDirectory +{ + Stack DirectoryBrowseHistoryStack { get; } +} /// /// /// - public class DirectoryEventArgs : EventArgs - { - public CodecDirectory Directory { get; set; } - public bool DirectoryIsOnRoot { get; set; } - } +public class DirectoryEventArgs : EventArgs +{ + public CodecDirectory Directory { get; set; } + public bool DirectoryIsOnRoot { get; set; } +} /// /// Represents a codec directory /// - public class CodecDirectory - { - /// - /// Represents the contents of the directory - /// We don't want to serialize this for messages to MobileControl. MC can combine Contacts and Folders to get the same data - /// +public class CodecDirectory +{ + /// + /// Represents the contents of the directory + /// We don't want to serialize this for messages to MobileControl. MC can combine Contacts and Folders to get the same data + /// [JsonIgnore] - public List CurrentDirectoryResults { get; private set; } + public List CurrentDirectoryResults { get; private set; } - [JsonProperty("contacts")] - public List Contacts + [JsonProperty("contacts")] + public List Contacts + { + get { - get - { - return CurrentDirectoryResults.OfType().Cast().ToList(); - } + return CurrentDirectoryResults.OfType().Cast().ToList(); } + } - [JsonProperty("folders")] - public List Folders + [JsonProperty("folders")] + public List Folders + { + get { - get - { - return CurrentDirectoryResults.OfType().Cast().ToList(); - } + return CurrentDirectoryResults.OfType().Cast().ToList(); } + } - /// - /// Used to store the ID of the current folder for CurrentDirectoryResults - /// + /// + /// Used to store the ID of the current folder for CurrentDirectoryResults + /// [JsonProperty("resultsFolderId")] - public string ResultsFolderId { get; set; } + public string ResultsFolderId { get; set; } - public CodecDirectory() - { - CurrentDirectoryResults = new List(); - } - - /// - /// Adds folders to the directory - /// - /// - public void AddFoldersToDirectory(List folders) - { - if(folders != null) - CurrentDirectoryResults.AddRange(folders); + public CodecDirectory() + { + CurrentDirectoryResults = new List(); + } - SortDirectory(); - } + /// + /// Adds folders to the directory + /// + /// + public void AddFoldersToDirectory(List folders) + { + if(folders != null) + CurrentDirectoryResults.AddRange(folders); - /// - /// Adds contacts to the directory - /// - /// - public void AddContactsToDirectory(List contacts) - { - if(contacts != null) - CurrentDirectoryResults.AddRange(contacts); + SortDirectory(); + } - SortDirectory(); - } + /// + /// Adds contacts to the directory + /// + /// + public void AddContactsToDirectory(List contacts) + { + if(contacts != null) + CurrentDirectoryResults.AddRange(contacts); - /// - /// Filters the CurrentDirectoryResults by the predicate - /// - /// - public void FilterContacts(Func predicate) - { - CurrentDirectoryResults = CurrentDirectoryResults.Where(predicate).ToList(); - } + SortDirectory(); + } - /// - /// Sorts the DirectoryResults list to display all folders alphabetically, then all contacts alphabetically - /// - private void SortDirectory() - { - var sortedFolders = new List(); + /// + /// Filters the CurrentDirectoryResults by the predicate + /// + /// + public void FilterContacts(Func predicate) + { + CurrentDirectoryResults = CurrentDirectoryResults.Where(predicate).ToList(); + } - sortedFolders.AddRange(CurrentDirectoryResults.Where(f => f is DirectoryFolder)); + /// + /// Sorts the DirectoryResults list to display all folders alphabetically, then all contacts alphabetically + /// + private void SortDirectory() + { + var sortedFolders = new List(); - sortedFolders.OrderBy(f => f.Name); + sortedFolders.AddRange(CurrentDirectoryResults.Where(f => f is DirectoryFolder)); - var sortedContacts = new List(); + sortedFolders.OrderBy(f => f.Name); - sortedContacts.AddRange(CurrentDirectoryResults.Where(c => c is DirectoryContact)); + var sortedContacts = new List(); - sortedFolders.OrderBy(c => c.Name); + sortedContacts.AddRange(CurrentDirectoryResults.Where(c => c is DirectoryContact)); - CurrentDirectoryResults.Clear(); + sortedFolders.OrderBy(c => c.Name); - CurrentDirectoryResults.AddRange(sortedFolders); + CurrentDirectoryResults.Clear(); - CurrentDirectoryResults.AddRange(sortedContacts); - } + CurrentDirectoryResults.AddRange(sortedFolders); + CurrentDirectoryResults.AddRange(sortedContacts); } - /// - /// Used to decorate a contact to indicate it can be invided to a meeting - /// - public interface IInvitableContact - { - bool IsInvitableContact { get; } - } +} + +/// +/// Used to decorate a contact to indicate it can be invided to a meeting +/// +public interface IInvitableContact +{ + bool IsInvitableContact { get; } +} - public class InvitableDirectoryContact : DirectoryContact, IInvitableContact +public class InvitableDirectoryContact : DirectoryContact, IInvitableContact +{ + [JsonProperty("isInvitableContact")] + public bool IsInvitableContact { - [JsonProperty("isInvitableContact")] - public bool IsInvitableContact + get { - get - { - return this is IInvitableContact; - } + return this is IInvitableContact; } } +} /// /// Represents an item in the directory /// - public class DirectoryItem : ICloneable +public class DirectoryItem : ICloneable +{ + public object Clone() { - public object Clone() - { - return this.MemberwiseClone(); - } + return this.MemberwiseClone(); + } - [JsonProperty("folderId")] - public string FolderId { get; set; } + [JsonProperty("folderId")] + public string FolderId { get; set; } [JsonProperty("name")] - public string Name { get; set; } + public string Name { get; set; } - [JsonProperty("parentFolderId")] - public string ParentFolderId { get; set; } - } + [JsonProperty("parentFolderId")] + public string ParentFolderId { get; set; } +} /// /// Represents a folder type DirectoryItem /// - public class DirectoryFolder : DirectoryItem - { +public class DirectoryFolder : DirectoryItem +{ [JsonProperty("contacts")] - public List Contacts { get; set; } + public List Contacts { get; set; } - public DirectoryFolder() - { - Contacts = new List(); - } + public DirectoryFolder() + { + Contacts = new List(); } +} /// /// Represents a contact type DirectoryItem /// - public class DirectoryContact : DirectoryItem - { +public class DirectoryContact : DirectoryItem +{ [JsonProperty("contactId")] - public string ContactId { get; set; } + public string ContactId { get; set; } [JsonProperty("title")] - public string Title { get; set; } + public string Title { get; set; } [JsonProperty("contactMethods")] - public List ContactMethods { get; set; } + public List ContactMethods { get; set; } - public DirectoryContact() - { - ContactMethods = new List(); - } + public DirectoryContact() + { + ContactMethods = new List(); } +} /// /// Represents a method of contact for a contact /// - public class ContactMethod - { +public class ContactMethod +{ [JsonProperty("contactMethodId")] - public string ContactMethodId { get; set; } + public string ContactMethodId { get; set; } [JsonProperty("number")] - public string Number { get; set; } - + public string Number { get; set; } + [JsonProperty("device")] [JsonConverter(typeof(StringEnumConverter))] public eContactMethodDevice Device { get; set; } @@ -248,27 +248,26 @@ public class ContactMethod [JsonProperty("callType")] [JsonConverter(typeof(StringEnumConverter))] public eContactMethodCallType CallType { get; set; } - } +} /// /// /// - public enum eContactMethodDevice - { - Unknown = 0, - Mobile, - Other, - Telephone, - Video - } +public enum eContactMethodDevice +{ + Unknown = 0, + Mobile, + Other, + Telephone, + Video +} /// /// /// - public enum eContactMethodCallType - { - Unknown = 0, - Audio, - Video - } +public enum eContactMethodCallType +{ + Unknown = 0, + Audio, + Video } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Codec/iHasScheduleAwareness.cs b/src/PepperDash.Essentials.Devices.Common/Codec/iHasScheduleAwareness.cs index 602d65e3e..dff7203f3 100644 --- a/src/PepperDash.Essentials.Devices.Common/Codec/iHasScheduleAwareness.cs +++ b/src/PepperDash.Essentials.Devices.Common/Codec/iHasScheduleAwareness.cs @@ -11,262 +11,260 @@ using Newtonsoft.Json; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec; + +[Flags] +public enum eMeetingEventChangeType { - [Flags] - public enum eMeetingEventChangeType - { - Unknown = 0, - MeetingStartWarning = 1, - MeetingStart = 2, - MeetingEndWarning = 4, - MeetingEnd = 8 - } + Unknown = 0, + MeetingStartWarning = 1, + MeetingStart = 2, + MeetingEndWarning = 4, + MeetingEnd = 8 +} - public interface IHasScheduleAwareness - { - CodecScheduleAwareness CodecSchedule { get; } +public interface IHasScheduleAwareness +{ + CodecScheduleAwareness CodecSchedule { get; } - void GetSchedule(); - } + void GetSchedule(); +} - public class CodecScheduleAwareness - { - List _meetings; +public class CodecScheduleAwareness +{ + List _meetings; - public event EventHandler MeetingEventChange; + public event EventHandler MeetingEventChange; - public event EventHandler MeetingsListHasChanged; + public event EventHandler MeetingsListHasChanged; - private int _meetingWarningMinutes = 5; + private int _meetingWarningMinutes = 5; - //private Meeting _previousChangedMeeting; + //private Meeting _previousChangedMeeting; - //private eMeetingEventChangeType _previousChangeType = eMeetingEventChangeType.Unknown; + //private eMeetingEventChangeType _previousChangeType = eMeetingEventChangeType.Unknown; - public int MeetingWarningMinutes - { - get { return _meetingWarningMinutes; } - set { _meetingWarningMinutes = value; } - } + public int MeetingWarningMinutes + { + get { return _meetingWarningMinutes; } + set { _meetingWarningMinutes = value; } + } - /// + /// /// Setter triggers MeetingsListHasChanged event /// - public List Meetings + public List Meetings + { + get { - get - { - return _meetings; - } - set - { - _meetings = value; - MeetingsListHasChanged?.Invoke(this, new EventArgs()); - } + return _meetings; + } + set + { + _meetings = value; + MeetingsListHasChanged?.Invoke(this, new EventArgs()); } + } - private readonly CTimer _scheduleChecker; + private readonly CTimer _scheduleChecker; - public CodecScheduleAwareness() - { - Meetings = new List(); + public CodecScheduleAwareness() + { + Meetings = new List(); - _scheduleChecker = new CTimer(CheckSchedule, null, 1000, 1000); - } + _scheduleChecker = new CTimer(CheckSchedule, null, 1000, 1000); + } - public CodecScheduleAwareness(long pollTime) - { - Meetings = new List(); + public CodecScheduleAwareness(long pollTime) + { + Meetings = new List(); - _scheduleChecker = new CTimer(CheckSchedule, null, pollTime, pollTime); - } + _scheduleChecker = new CTimer(CheckSchedule, null, pollTime, pollTime); + } - /// - /// Helper method to fire MeetingEventChange. Should only fire once for each changeType on each meeting - /// - /// - /// - private void OnMeetingChange(eMeetingEventChangeType changeType, Meeting meeting) + /// + /// Helper method to fire MeetingEventChange. Should only fire once for each changeType on each meeting + /// + /// + /// + private void OnMeetingChange(eMeetingEventChangeType changeType, Meeting meeting) + { + Debug.LogMessage(LogEventLevel.Verbose, "*****************OnMeetingChange. id: {0} changeType: {1}**********************", meeting.Id, changeType); + if (changeType != (changeType & meeting.NotifiedChangeTypes)) { - Debug.LogMessage(LogEventLevel.Verbose, "*****************OnMeetingChange. id: {0} changeType: {1}**********************", meeting.Id, changeType); - if (changeType != (changeType & meeting.NotifiedChangeTypes)) - { - // Add this change type to the NotifiedChangeTypes - meeting.NotifiedChangeTypes |= changeType; - MeetingEventChange?.Invoke(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting }); - } - else - { - Debug.LogMessage(LogEventLevel.Verbose, "Meeting: {0} already notified of changeType: {1}", meeting.Id, changeType); - } + // Add this change type to the NotifiedChangeTypes + meeting.NotifiedChangeTypes |= changeType; + MeetingEventChange?.Invoke(this, new MeetingEventArgs() { ChangeType = changeType, Meeting = meeting }); } + else + { + Debug.LogMessage(LogEventLevel.Verbose, "Meeting: {0} already notified of changeType: {1}", meeting.Id, changeType); + } + } - /// - /// Checks the schedule to see if any MeetingEventChange updates should be fired - /// - /// - private void CheckSchedule(object o) + /// + /// Checks the schedule to see if any MeetingEventChange updates should be fired + /// + /// + private void CheckSchedule(object o) + { + // Iterate the meeting list and check if any meeting need to do anything + + const double meetingTimeEpsilon = 0.05; + foreach (var m in Meetings) { - // Iterate the meeting list and check if any meeting need to do anything + var changeType = eMeetingEventChangeType.Unknown; - const double meetingTimeEpsilon = 0.05; - foreach (var m in Meetings) + if (eMeetingEventChangeType.MeetingStartWarning != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStartWarning) && m.TimeToMeetingStart.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingStart.Seconds > 0) // Meeting is about to start + { + Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingStartWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingStart.TotalMinutes, m.TimeToMeetingStart.Seconds); + changeType = eMeetingEventChangeType.MeetingStartWarning; + } + else if (eMeetingEventChangeType.MeetingStart != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStart) && Math.Abs(m.TimeToMeetingStart.TotalMinutes) < meetingTimeEpsilon) // Meeting Start { - var changeType = eMeetingEventChangeType.Unknown; - - if (eMeetingEventChangeType.MeetingStartWarning != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStartWarning) && m.TimeToMeetingStart.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingStart.Seconds > 0) // Meeting is about to start - { - Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingStartWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingStart.TotalMinutes, m.TimeToMeetingStart.Seconds); - changeType = eMeetingEventChangeType.MeetingStartWarning; - } - else if (eMeetingEventChangeType.MeetingStart != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingStart) && Math.Abs(m.TimeToMeetingStart.TotalMinutes) < meetingTimeEpsilon) // Meeting Start - { - Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingStart"); - changeType = eMeetingEventChangeType.MeetingStart; - } - else if (eMeetingEventChangeType.MeetingEndWarning != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingEndWarning) && m.TimeToMeetingEnd.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingEnd.Seconds > 0) // Meeting is about to end - { - Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingEndWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingEnd.TotalMinutes, m.TimeToMeetingEnd.Seconds); - changeType = eMeetingEventChangeType.MeetingEndWarning; - } - else if (eMeetingEventChangeType.MeetingEnd != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingEnd) && Math.Abs(m.TimeToMeetingEnd.TotalMinutes) < meetingTimeEpsilon) // Meeting has ended - { - Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingEnd"); - changeType = eMeetingEventChangeType.MeetingEnd; - } - - if (changeType != eMeetingEventChangeType.Unknown) - { - OnMeetingChange(changeType, m); - } + Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingStart"); + changeType = eMeetingEventChangeType.MeetingStart; + } + else if (eMeetingEventChangeType.MeetingEndWarning != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingEndWarning) && m.TimeToMeetingEnd.TotalMinutes <= m.MeetingWarningMinutes.TotalMinutes && m.TimeToMeetingEnd.Seconds > 0) // Meeting is about to end + { + Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingEndWarning. TotalMinutes: {0} Seconds: {1}", m.TimeToMeetingEnd.TotalMinutes, m.TimeToMeetingEnd.Seconds); + changeType = eMeetingEventChangeType.MeetingEndWarning; + } + else if (eMeetingEventChangeType.MeetingEnd != (m.NotifiedChangeTypes & eMeetingEventChangeType.MeetingEnd) && Math.Abs(m.TimeToMeetingEnd.TotalMinutes) < meetingTimeEpsilon) // Meeting has ended + { + Debug.LogMessage(LogEventLevel.Verbose, "********************* MeetingEnd"); + changeType = eMeetingEventChangeType.MeetingEnd; } + if (changeType != eMeetingEventChangeType.Unknown) + { + OnMeetingChange(changeType, m); + } } + } +} - /// - /// Generic class to represent a meeting (Cisco or Polycom OBTP or Fusion) - /// - public class Meeting +/// +/// Generic class to represent a meeting (Cisco or Polycom OBTP or Fusion) +/// +public class Meeting +{ + [JsonProperty("minutesBeforeMeeting")] + public int MinutesBeforeMeeting; + + [JsonProperty("id")] + public string Id { get; set; } + [JsonProperty("organizer")] + public string Organizer { get; set; } + [JsonProperty("title")] + public string Title { get; set; } + [JsonProperty("agenda")] + public string Agenda { get; set; } + + [JsonProperty("meetingWarningMinutes")] + public TimeSpan MeetingWarningMinutes + { + get { return TimeSpan.FromMinutes(MinutesBeforeMeeting); } + } + [JsonProperty("timeToMeetingStart")] + public TimeSpan TimeToMeetingStart { - [JsonProperty("minutesBeforeMeeting")] - public int MinutesBeforeMeeting; - - [JsonProperty("id")] - public string Id { get; set; } - [JsonProperty("organizer")] - public string Organizer { get; set; } - [JsonProperty("title")] - public string Title { get; set; } - [JsonProperty("agenda")] - public string Agenda { get; set; } - - [JsonProperty("meetingWarningMinutes")] - public TimeSpan MeetingWarningMinutes + get { - get { return TimeSpan.FromMinutes(MinutesBeforeMeeting); } + return StartTime - DateTime.Now; } - [JsonProperty("timeToMeetingStart")] - public TimeSpan TimeToMeetingStart + } + [JsonProperty("timeToMeetingEnd")] + public TimeSpan TimeToMeetingEnd + { + get { - get - { - return StartTime - DateTime.Now; - } + return EndTime - DateTime.Now; } - [JsonProperty("timeToMeetingEnd")] - public TimeSpan TimeToMeetingEnd + } + [JsonProperty("startTime")] + public DateTime StartTime { get; set; } + [JsonProperty("endTime")] + public DateTime EndTime { get; set; } + [JsonProperty("duration")] + public TimeSpan Duration + { + get { - get - { - return EndTime - DateTime.Now; - } + return EndTime - StartTime; } - [JsonProperty("startTime")] - public DateTime StartTime { get; set; } - [JsonProperty("endTime")] - public DateTime EndTime { get; set; } - [JsonProperty("duration")] - public TimeSpan Duration + } + [JsonProperty("privacy")] + public eMeetingPrivacy Privacy { get; set; } + [JsonProperty("joinable")] + public bool Joinable + { + get { - get - { - return EndTime - StartTime; - } - } - [JsonProperty("privacy")] - public eMeetingPrivacy Privacy { get; set; } - [JsonProperty("joinable")] - public bool Joinable - { - get - { - var joinable = StartTime.AddMinutes(-MinutesBeforeMeeting) <= DateTime.Now - && DateTime.Now <= EndTime.AddSeconds(-_joinableCooldownSeconds); - //Debug.LogMessage(LogEventLevel.Verbose, "Meeting Id: {0} joinable: {1}", Id, joinable); - return joinable; - } + var joinable = StartTime.AddMinutes(-MinutesBeforeMeeting) <= DateTime.Now + && DateTime.Now <= EndTime.AddSeconds(-_joinableCooldownSeconds); + //Debug.LogMessage(LogEventLevel.Verbose, "Meeting Id: {0} joinable: {1}", Id, joinable); + return joinable; } + } [JsonProperty("dialable")] public bool Dialable { get; set; } - //public string ConferenceNumberToDial { get; set; } - [JsonProperty("conferencePassword")] - public string ConferencePassword { get; set; } - [JsonProperty("isOneButtonToPushMeeting")] - public bool IsOneButtonToPushMeeting { get; set; } - - [JsonProperty("calls")] - public List Calls { get; private set; } + //public string ConferenceNumberToDial { get; set; } + [JsonProperty("conferencePassword")] + public string ConferencePassword { get; set; } + [JsonProperty("isOneButtonToPushMeeting")] + public bool IsOneButtonToPushMeeting { get; set; } - /// - /// Tracks the change types that have already been notified for - /// - [JsonIgnore] - public eMeetingEventChangeType NotifiedChangeTypes { get; set; } - - [JsonIgnore] private readonly int _joinableCooldownSeconds; + [JsonProperty("calls")] + public List Calls { get; private set; } + /// + /// Tracks the change types that have already been notified for + /// + [JsonIgnore] + public eMeetingEventChangeType NotifiedChangeTypes { get; set; } - public Meeting() - { - Calls = new List(); - _joinableCooldownSeconds = 300; - } + [JsonIgnore] private readonly int _joinableCooldownSeconds; - public Meeting(int joinableCooldownSeconds) - { - Calls = new List(); - _joinableCooldownSeconds = joinableCooldownSeconds; - } + public Meeting() + { + Calls = new List(); + _joinableCooldownSeconds = 300; + } + public Meeting(int joinableCooldownSeconds) + { + Calls = new List(); + _joinableCooldownSeconds = joinableCooldownSeconds; + } - #region Overrides of Object - public override string ToString() - { - return String.Format("{0}:{1}: {2}-{3}", Title, Agenda, StartTime, EndTime); - } - #endregion - } + #region Overrides of Object - public class Call + public override string ToString() { - public string Number { get; set; } - public string Protocol { get; set; } - public string CallRate { get; set; } - public string CallType { get; set; } + return String.Format("{0}:{1}: {2}-{3}", Title, Agenda, StartTime, EndTime); } - public class MeetingEventArgs : EventArgs - { - public eMeetingEventChangeType ChangeType { get; set; } - public Meeting Meeting { get; set; } - } + #endregion +} + +public class Call +{ + public string Number { get; set; } + public string Protocol { get; set; } + public string CallRate { get; set; } + public string CallType { get; set; } +} +public class MeetingEventArgs : EventArgs +{ + public eMeetingEventChangeType ChangeType { get; set; } + public Meeting Meeting { get; set; } } diff --git a/src/PepperDash.Essentials.Devices.Common/DSP/DspBase.cs b/src/PepperDash.Essentials.Devices.Common/DSP/DspBase.cs index 078dc9e70..ff9ccac05 100644 --- a/src/PepperDash.Essentials.Devices.Common/DSP/DspBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/DSP/DspBase.cs @@ -8,15 +8,15 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.DeviceTypeInterfaces; -namespace PepperDash.Essentials.Devices.Common.DSP -{ +namespace PepperDash.Essentials.Devices.Common.DSP; + public abstract class DspBase : EssentialsDevice, ILevelControls { public Dictionary LevelControlPoints { get; private set; } - public Dictionary DialerControlPoints { get; private set; } + public Dictionary DialerControlPoints { get; private set; } - public Dictionary SwitcherControlPoints { get; private set; } + public Dictionary SwitcherControlPoints { get; private set; } public DspBase(string key, string name) : base(key, name) @@ -47,40 +47,38 @@ public DspBase(string key, string name) : public abstract class DspControlPoint :IKeyed { - public string Key { get; } + public string Key { get; } - protected DspControlPoint(string key) => Key = key; + protected DspControlPoint(string key) => Key = key; } - public abstract class DspLevelControlPoint :DspControlPoint, IBasicVolumeWithFeedback +public abstract class DspLevelControlPoint :DspControlPoint, IBasicVolumeWithFeedback +{ + public BoolFeedback MuteFeedback { get; } + public IntFeedback VolumeLevelFeedback { get; } + + protected DspLevelControlPoint(string key, Func muteFeedbackFunc, Func volumeLevelFeedbackFunc) : base(key) { - public BoolFeedback MuteFeedback { get; } - public IntFeedback VolumeLevelFeedback { get; } - - protected DspLevelControlPoint(string key, Func muteFeedbackFunc, Func volumeLevelFeedbackFunc) : base(key) - { - MuteFeedback = new BoolFeedback(muteFeedbackFunc); - VolumeLevelFeedback = new IntFeedback(volumeLevelFeedbackFunc); - } - - public abstract void MuteOff(); - public abstract void MuteOn(); - public abstract void MuteToggle(); - public abstract void SetVolume(ushort level); - public abstract void VolumeDown(bool pressRelease); - public abstract void VolumeUp(bool pressRelease); + MuteFeedback = new BoolFeedback(muteFeedbackFunc); + VolumeLevelFeedback = new IntFeedback(volumeLevelFeedbackFunc); } + public abstract void MuteOff(); + public abstract void MuteOn(); + public abstract void MuteToggle(); + public abstract void SetVolume(ushort level); + public abstract void VolumeDown(bool pressRelease); + public abstract void VolumeUp(bool pressRelease); +} + - public abstract class DspDialerBase:DspControlPoint +public abstract class DspDialerBase:DspControlPoint { - protected DspDialerBase(string key) : base(key) { } + protected DspDialerBase(string key) : base(key) { } } // Main program // VTC // ATC - // Mics, unusual - -} \ No newline at end of file + // Mics, unusual \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/DeviceFactory.cs b/src/PepperDash.Essentials.Devices.Common/DeviceFactory.cs index 0f1f973f4..778ba56fe 100644 --- a/src/PepperDash.Essentials.Devices.Common/DeviceFactory.cs +++ b/src/PepperDash.Essentials.Devices.Common/DeviceFactory.cs @@ -7,33 +7,51 @@ using PepperDash.Essentials.Core; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common +namespace PepperDash.Essentials.Devices.Common; + +public class DeviceFactory { - public class DeviceFactory + + public DeviceFactory() { + var assy = Assembly.GetExecutingAssembly(); + PluginLoader.AddLoadedAssembly(assy.GetName().Name, assy); + + var types = assy.GetTypes().Where(ct => typeof(IDeviceFactory).IsAssignableFrom(ct) && !ct.IsInterface && !ct.IsAbstract); - public DeviceFactory() + if (types != null) { - var assy = Assembly.GetExecutingAssembly(); - PluginLoader.SetEssentialsAssembly(assy.GetName().Name, assy); - - var types = assy.GetTypes().Where(ct => typeof(IDeviceFactory).IsAssignableFrom(ct) && !ct.IsInterface && !ct.IsAbstract); - - if (types != null) + foreach (var type in types) { - foreach (var type in types) + try + { + var factory = (IDeviceFactory)Activator.CreateInstance(type); + LoadDeviceFactories(factory); + } + catch (Exception e) { - try - { - var factory = (IDeviceFactory)Activator.CreateInstance(type); - factory.LoadTypeFactories(); - } - catch (Exception e) - { - Debug.LogMessage(LogEventLevel.Information, "Unable to load type: '{1}' DeviceFactory: {0}", e, type.Name); - } + Debug.LogMessage(LogEventLevel.Information, "Unable to load type: '{1}' DeviceFactory: {0}", e, type.Name); } } } + } + + /// + /// Loads device factories from the specified plugin device factory and registers them for use. + /// + /// This method retrieves metadata from the provided , including + /// type names, descriptions, and configuration snippets, and registers the factory for each device type. The type + /// names are converted to lowercase for registration. + /// The plugin device factory that provides the device types, descriptions, and factory methods to be registered. + private static void LoadDeviceFactories(IDeviceFactory deviceFactory) + { + foreach (var typeName in deviceFactory.TypeNames) + { + //Debug.LogMessage(LogEventLevel.Verbose, "Getting Description Attribute from class: '{0}'", typeof(T).FullName); + var descriptionAttribute = deviceFactory.FactoryType.GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[]; + string description = descriptionAttribute[0].Description; + var snippetAttribute = deviceFactory.FactoryType.GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[]; + Core.DeviceFactory.AddFactoryForType(typeName.ToLower(), description, deviceFactory.FactoryType, deviceFactory.BuildDevice); + } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/BasicIrDisplay.cs b/src/PepperDash.Essentials.Devices.Common/Displays/BasicIrDisplay.cs index d7e19d003..3308bc0ea 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/BasicIrDisplay.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/BasicIrDisplay.cs @@ -9,17 +9,17 @@ using PepperDash.Essentials.Core.Config; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common.Displays -{ - public class BasicIrDisplay : DisplayBase, IBasicVolumeControls, IBridgeAdvanced +namespace PepperDash.Essentials.Devices.Common.Displays; + +public class BasicIrDisplay : DisplayBase, IBasicVolumeControls, IBridgeAdvanced { public IrOutputPortController IrPort { get; private set; } public ushort IrPulseTime { get; set; } - protected Func PowerIsOnFeedbackFunc - { - get { return () => _PowerIsOn; } - } + protected Func PowerIsOnFeedbackFunc + { + get { return () => _PowerIsOn; } + } protected override Func IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } @@ -29,7 +29,7 @@ protected override Func IsWarmingUpFeedbackFunc get { return () => _IsWarmingUp; } } - bool _PowerIsOn; + bool _PowerIsOn; bool _IsWarmingUp; bool _IsCoolingDown; @@ -101,18 +101,18 @@ public void Antenna() public override void PowerOn() { IrPort.Pulse(IROutputStandardCommands.IROut_POWER_ON, IrPulseTime); - _PowerIsOn = true; + _PowerIsOn = true; } public override void PowerOff() { - _PowerIsOn = false; + _PowerIsOn = false; IrPort.Pulse(IROutputStandardCommands.IROut_POWER_OFF, IrPulseTime); } public override void PowerToggle() { - _PowerIsOn = false; + _PowerIsOn = false; IrPort.Pulse(IROutputStandardCommands.IROut_POWER, IrPulseTime); } @@ -166,7 +166,7 @@ void StartCoolingTimer() /// A delegate containing the input selector method to call public override void ExecuteSwitch(object inputSelector) { - Debug.LogMessage(LogEventLevel.Verbose, this, "Switching to input '{0}'", (inputSelector as Action).ToString()); + Debug.LogMessage(LogEventLevel.Verbose, this, "Switching to input '{0}'", (inputSelector as Action).ToString()); Action finishSwitch = () => { @@ -199,26 +199,24 @@ public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, E } } - public class BasicIrDisplayFactory : EssentialsDeviceFactory +public class BasicIrDisplayFactory : EssentialsDeviceFactory +{ + public BasicIrDisplayFactory() { - public BasicIrDisplayFactory() - { - TypeNames = new List() { "basicirdisplay" }; - } + TypeNames = new List() { "basicirdisplay" }; + } - public override EssentialsDevice BuildDevice(DeviceConfig dc) + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new BasicIrDisplay Device"); + var ir = IRPortHelper.GetIrPort(dc.Properties); + if (ir != null) { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new BasicIrDisplay Device"); - var ir = IRPortHelper.GetIrPort(dc.Properties); - if (ir != null) - { - var display = new BasicIrDisplay(dc.Key, dc.Name, ir.Port, ir.FileName); - display.IrPulseTime = 200; // Set default pulse time for IR commands. - return display; - } - - return null; + var display = new BasicIrDisplay(dc.Key, dc.Name, ir.Port, ir.FileName); + display.IrPulseTime = 200; // Set default pulse time for IR commands. + return display; } - } + return null; + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/DisplayBase.cs b/src/PepperDash.Essentials.Devices.Common/Displays/DisplayBase.cs index 24d55c2e0..8f1fae45d 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/DisplayBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/DisplayBase.cs @@ -11,60 +11,60 @@ using System.Linq; using Feedback = PepperDash.Essentials.Core.Feedback; -namespace PepperDash.Essentials.Devices.Common.Displays -{ - public abstract class DisplayBase : EssentialsDevice, IDisplay +namespace PepperDash.Essentials.Devices.Common.Displays; + +public abstract class DisplayBase : EssentialsDevice, IDisplay { - private RoutingInputPort _currentInputPort; - public RoutingInputPort CurrentInputPort + private RoutingInputPort _currentInputPort; + public RoutingInputPort CurrentInputPort + { + get { - get - { - return _currentInputPort; - } + return _currentInputPort; + } - protected set - { - if (_currentInputPort == value) return; + protected set + { + if (_currentInputPort == value) return; - _currentInputPort = value; + _currentInputPort = value; - InputChanged?.Invoke(this, _currentInputPort); - } + InputChanged?.Invoke(this, _currentInputPort); } + } - public event InputChangedEventHandler InputChanged; + public event InputChangedEventHandler InputChanged; - public event SourceInfoChangeHandler CurrentSourceChange; + public event SourceInfoChangeHandler CurrentSourceChange; - public string CurrentSourceInfoKey { get; set; } - public SourceListItem CurrentSourceInfo + public string CurrentSourceInfoKey { get; set; } + public SourceListItem CurrentSourceInfo + { + get + { + return _CurrentSourceInfo; + } + set { - get - { - return _CurrentSourceInfo; - } - set - { - if (value == _CurrentSourceInfo) return; + if (value == _CurrentSourceInfo) return; - var handler = CurrentSourceChange; + var handler = CurrentSourceChange; - if (handler != null) - handler(_CurrentSourceInfo, ChangeType.WillChange); + if (handler != null) + handler(_CurrentSourceInfo, ChangeType.WillChange); - _CurrentSourceInfo = value; + _CurrentSourceInfo = value; - if (handler != null) - handler(_CurrentSourceInfo, ChangeType.DidChange); - } + if (handler != null) + handler(_CurrentSourceInfo, ChangeType.DidChange); } - SourceListItem _CurrentSourceInfo; + } + SourceListItem _CurrentSourceInfo; public BoolFeedback IsCoolingDownFeedback { get; protected set; } public BoolFeedback IsWarmingUpFeedback { get; private set; } - public UsageTracking UsageTracker { get; set; } + public UsageTracking UsageTracker { get; set; } public uint WarmupTime { get; set; } public uint CooldownTime { get; set; } @@ -75,7 +75,7 @@ public SourceListItem CurrentSourceInfo /// abstract protected Func IsCoolingDownFeedbackFunc { get; } abstract protected Func IsWarmingUpFeedbackFunc { get; } - + protected CTimer WarmupTimer; protected CTimer CooldownTimer; @@ -100,11 +100,11 @@ protected DisplayBase(string key, string name) public abstract void PowerOff(); public abstract void PowerToggle(); - public virtual FeedbackCollection Feedbacks + public virtual FeedbackCollection Feedbacks { get { - return new FeedbackCollection + return new FeedbackCollection { IsCoolingDownFeedback, IsWarmingUpFeedback @@ -117,12 +117,12 @@ public virtual FeedbackCollection Feedbacks protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { - var joinMap = new DisplayControllerJoinMap(joinStart); + var joinMap = new DisplayControllerJoinMap(joinStart); - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - if (!string.IsNullOrEmpty(joinMapSerialized)) - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); if (bridge != null) { @@ -268,21 +268,21 @@ protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, volumeDisplayWithFeedback.MuteFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.VolumeMuteOff.JoinNumber]); } - } +} - public abstract class TwoWayDisplayBase : DisplayBase, IRoutingFeedback, IHasPowerControlWithFeedback +public abstract class TwoWayDisplayBase : DisplayBase, IRoutingFeedback, IHasPowerControlWithFeedback { - public StringFeedback CurrentInputFeedback { get; private set; } + public StringFeedback CurrentInputFeedback { get; private set; } - abstract protected Func CurrentInputFeedbackFunc { get; } + abstract protected Func CurrentInputFeedbackFunc { get; } - public BoolFeedback PowerIsOnFeedback { get; protected set; } + public BoolFeedback PowerIsOnFeedback { get; protected set; } - abstract protected Func PowerIsOnFeedbackFunc { get; } + abstract protected Func PowerIsOnFeedbackFunc { get; } - public static MockDisplay DefaultDisplay - { + public static MockDisplay DefaultDisplay + { get { if (_DefaultDisplay == null) @@ -295,41 +295,40 @@ public static MockDisplay DefaultDisplay public TwoWayDisplayBase(string key, string name) : base(key, name) { - CurrentInputFeedback = new StringFeedback(CurrentInputFeedbackFunc); + CurrentInputFeedback = new StringFeedback(CurrentInputFeedbackFunc); WarmupTime = 7000; CooldownTime = 15000; - PowerIsOnFeedback = new BoolFeedback("PowerOnFeedback", PowerIsOnFeedbackFunc); + PowerIsOnFeedback = new BoolFeedback("PowerOnFeedback", PowerIsOnFeedbackFunc); - Feedbacks.Add(CurrentInputFeedback); - Feedbacks.Add(PowerIsOnFeedback); + Feedbacks.Add(CurrentInputFeedback); + Feedbacks.Add(PowerIsOnFeedback); - PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange; + PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange; } - void PowerIsOnFeedback_OutputChange(object sender, EventArgs e) + void PowerIsOnFeedback_OutputChange(object sender, EventArgs e) + { + if (UsageTracker != null) { - if (UsageTracker != null) - { - if (PowerIsOnFeedback.BoolValue) - UsageTracker.StartDeviceUsage(); - else - UsageTracker.EndDeviceUsage(); - } + if (PowerIsOnFeedback.BoolValue) + UsageTracker.StartDeviceUsage(); + else + UsageTracker.EndDeviceUsage(); } + } - public event EventHandler NumericSwitchChange; + public event EventHandler NumericSwitchChange; - /// - /// Raise an event when the status of a switch object changes. - /// - /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType - protected void OnSwitchChange(RoutingNumericEventArgs e) - { - var newEvent = NumericSwitchChange; - if (newEvent != null) newEvent(this, e); - } - } -} \ No newline at end of file + /// + /// Raise an event when the status of a switch object changes. + /// + /// Arguments defined as IKeyName sender, output, input, and eRoutingSignalType + protected void OnSwitchChange(RoutingNumericEventArgs e) + { + var newEvent = NumericSwitchChange; + if (newEvent != null) newEvent(this, e); + } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/InputInterfaces.cs b/src/PepperDash.Essentials.Devices.Common/Displays/InputInterfaces.cs index ce7113e13..81540294b 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/InputInterfaces.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/InputInterfaces.cs @@ -4,14 +4,12 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Devices.Displays -{ - public interface IInputHdmi1 { void InputHdmi1(); } - public interface IInputHdmi2 { void InputHdmi2(); } - public interface IInputHdmi3 { void InputHdmi3(); } - public interface IInputHdmi4 { void InputHdmi4(); } - public interface IInputDisplayPort1 { void InputDisplayPort1(); } - public interface IInputDisplayPort2 { void InputDisplayPort2(); } - public interface IInputVga1 { void InputVga1(); } +namespace PepperDash.Essentials.Devices.Displays; -} \ No newline at end of file +public interface IInputHdmi1 { void InputHdmi1(); } +public interface IInputHdmi2 { void InputHdmi2(); } +public interface IInputHdmi3 { void InputHdmi3(); } +public interface IInputHdmi4 { void InputHdmi4(); } +public interface IInputDisplayPort1 { void InputDisplayPort1(); } +public interface IInputDisplayPort2 { void InputDisplayPort2(); } +public interface IInputVga1 { void InputVga1(); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs index f972c1e6d..56bdbc41c 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs @@ -10,58 +10,58 @@ using PepperDash.Essentials.Core.DeviceTypeInterfaces; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common.Displays -{ - public class MockDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, IBridgeAdvanced, IHasInputs, IRoutingSinkWithSwitchingWithInputPort, IHasPowerControlWithFeedback +namespace PepperDash.Essentials.Devices.Common.Displays; + +public class MockDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, IBridgeAdvanced, IHasInputs, IRoutingSinkWithSwitchingWithInputPort, IHasPowerControlWithFeedback { - public ISelectableItems Inputs { get; private set; } + public ISelectableItems Inputs { get; private set; } bool _PowerIsOn; bool _IsWarmingUp; bool _IsCoolingDown; - protected override Func PowerIsOnFeedbackFunc + protected override Func PowerIsOnFeedbackFunc + { + get { - get - { - return () => - { - return _PowerIsOn; - }; - } } + return () => + { + return _PowerIsOn; + }; + } } protected override Func IsCoolingDownFeedbackFunc + { + get { - get + return () => { - return () => - { - return _IsCoolingDown; - }; - } + return _IsCoolingDown; + }; } + } protected override Func IsWarmingUpFeedbackFunc + { + get { - get + return () => { - return () => - { - return _IsWarmingUp; - }; - } + return _IsWarmingUp; + }; } - protected override Func CurrentInputFeedbackFunc { get { return () => Inputs.CurrentItem; } } + } + protected override Func CurrentInputFeedbackFunc { get { return () => Inputs.CurrentItem; } } - int VolumeHeldRepeatInterval = 200; - ushort VolumeInterval = 655; + int VolumeHeldRepeatInterval = 200; + ushort VolumeInterval = 655; ushort _FakeVolumeLevel = 31768; bool _IsMuted; public MockDisplay(string key, string name) : base(key, name) { - Inputs = new MockDisplayInputs - { - Items = new Dictionary + Inputs = new MockDisplayInputs + { + Items = new Dictionary { { "HDMI1", new MockDisplayInput ( "HDMI1", "HDMI 1",this ) }, { "HDMI2", new MockDisplayInput ("HDMI2", "HDMI 2",this ) }, @@ -69,11 +69,11 @@ public MockDisplay(string key, string name) { "HDMI4", new MockDisplayInput ("HDMI4", "HDMI 4",this )}, { "DP", new MockDisplayInput ("DP", "DisplayPort", this ) } } - }; + }; Inputs.CurrentItemChanged += (o, a) => CurrentInputFeedback.FireUpdate(); - - var hdmiIn1 = new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo, + + var hdmiIn1 = new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, "HDMI1", this); var hdmiIn2 = new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, "HDMI2", this); @@ -88,8 +88,8 @@ public MockDisplay(string key, string name) VolumeLevelFeedback = new IntFeedback(() => { return _FakeVolumeLevel; }); MuteFeedback = new BoolFeedback("MuteOn", () => _IsMuted); - WarmupTime = 10000; - CooldownTime = 10000; + WarmupTime = 10000; + CooldownTime = 10000; } public override void PowerOn() @@ -123,8 +123,8 @@ public override void PowerOff() Debug.LogMessage(LogEventLevel.Verbose, "Cooldown timer ending", this); _IsCoolingDown = false; IsCoolingDownFeedback.InvokeFireUpdate(); - _PowerIsOn = false; - PowerIsOnFeedback.InvokeFireUpdate(); + _PowerIsOn = false; + PowerIsOnFeedback.InvokeFireUpdate(); }, CooldownTime); } } @@ -139,43 +139,43 @@ public override void PowerToggle() public override void ExecuteSwitch(object selector) { - try - { - Debug.LogMessage(LogEventLevel.Verbose, "ExecuteSwitch: {0}", this, selector); + try + { + Debug.LogMessage(LogEventLevel.Verbose, "ExecuteSwitch: {0}", this, selector); if (!_PowerIsOn) { PowerOn(); } - if (!Inputs.Items.TryGetValue(selector.ToString(), out var input)) - return; - - Debug.LogMessage(LogEventLevel.Verbose, "Selected input: {input}", this, input.Key); - input.Select(); + if (!Inputs.Items.TryGetValue(selector.ToString(), out var input)) + return; - var inputPort = InputPorts.FirstOrDefault(port => - { - Debug.LogMessage(LogEventLevel.Verbose, "Checking input port {inputPort} with selector {portSelector} against {selector}", this, port, port.Selector, selector); - return port.Selector.ToString() == selector.ToString(); - }); + Debug.LogMessage(LogEventLevel.Verbose, "Selected input: {input}", this, input.Key); + input.Select(); - if (inputPort == null) - { - Debug.LogMessage(LogEventLevel.Verbose, "Unable to find input port for selector {selector}", this, selector); - return; - } + var inputPort = InputPorts.FirstOrDefault(port => + { + Debug.LogMessage(LogEventLevel.Verbose, "Checking input port {inputPort} with selector {portSelector} against {selector}", this, port, port.Selector, selector); + return port.Selector.ToString() == selector.ToString(); + }); - Debug.LogMessage(LogEventLevel.Verbose, "Setting current input port to {inputPort}", this, inputPort); - CurrentInputPort = inputPort; - } catch (Exception ex) + if (inputPort == null) { - Debug.LogMessage(ex, "Error making switch: {Exception}", this, ex); + Debug.LogMessage(LogEventLevel.Verbose, "Unable to find input port for selector {selector}", this, selector); + return; } - } - public void SetInput(string selector) + Debug.LogMessage(LogEventLevel.Verbose, "Setting current input port to {inputPort}", this, inputPort); + CurrentInputPort = inputPort; + } catch (Exception ex) { + Debug.LogMessage(ex, "Error making switch: {Exception}", this, ex); + } + } + + public void SetInput(string selector) + { ISelectableItem currentInput = null; try @@ -185,24 +185,24 @@ public void SetInput(string selector) catch { } - if (currentInput != null) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "SetInput: {0}", selector); - currentInput.IsSelected = false; - } + if (currentInput != null) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "SetInput: {0}", selector); + currentInput.IsSelected = false; + } if (!Inputs.Items.TryGetValue(selector, out var input)) - return; + return; input.IsSelected = true; Inputs.CurrentItem = selector; - } + } - #region IBasicVolumeWithFeedback Members + #region IBasicVolumeWithFeedback Members - public IntFeedback VolumeLevelFeedback { get; private set; } + public IntFeedback VolumeLevelFeedback { get; private set; } public void SetVolume(ushort level) { @@ -225,36 +225,36 @@ public void MuteOff() public BoolFeedback MuteFeedback { get; private set; } - #endregion + #endregion - #region IBasicVolumeControls Members + #region IBasicVolumeControls Members - public void VolumeUp(bool pressRelease) + public void VolumeUp(bool pressRelease) { - //while (pressRelease) - //{ - Debug.LogMessage(LogEventLevel.Verbose, this, "Volume Down {0}", pressRelease); - if (pressRelease) - { - var newLevel = _FakeVolumeLevel + VolumeInterval; - SetVolume((ushort)newLevel); - CrestronEnvironment.Sleep(VolumeHeldRepeatInterval); - } - //} + //while (pressRelease) + //{ + Debug.LogMessage(LogEventLevel.Verbose, this, "Volume Down {0}", pressRelease); + if (pressRelease) + { + var newLevel = _FakeVolumeLevel + VolumeInterval; + SetVolume((ushort)newLevel); + CrestronEnvironment.Sleep(VolumeHeldRepeatInterval); + } + //} } public void VolumeDown(bool pressRelease) { - //while (pressRelease) - //{ - Debug.LogMessage(LogEventLevel.Verbose, this, "Volume Up {0}", pressRelease); - if (pressRelease) - { - var newLevel = _FakeVolumeLevel - VolumeInterval; - SetVolume((ushort)newLevel); - CrestronEnvironment.Sleep(VolumeHeldRepeatInterval); - } - //} + //while (pressRelease) + //{ + Debug.LogMessage(LogEventLevel.Verbose, this, "Volume Up {0}", pressRelease); + if (pressRelease) + { + var newLevel = _FakeVolumeLevel - VolumeInterval; + SetVolume((ushort)newLevel); + CrestronEnvironment.Sleep(VolumeHeldRepeatInterval); + } + //} } public void MuteToggle() @@ -269,7 +269,7 @@ public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, E { LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge); } - } +} public class MockDisplayFactory : EssentialsDeviceFactory { @@ -283,5 +283,4 @@ public override EssentialsDevice BuildDevice(DeviceConfig dc) Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Mock Display Device"); return new MockDisplay(dc.Key, dc.Name); } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs index 0380085fd..2b7232304 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs @@ -6,96 +6,95 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Devices.Common.Displays +namespace PepperDash.Essentials.Devices.Common.Displays; + +public class MockDisplayInputs : ISelectableItems { - public class MockDisplayInputs : ISelectableItems - { - private Dictionary _items; + private Dictionary _items; - public Dictionary Items + public Dictionary Items + { + get { - get - { - return _items; - } - set - { - if (_items == value) - return; - - _items = value; - - ItemsUpdated?.Invoke(this, null); - } + return _items; } + set + { + if (_items == value) + return; - private string _currentItem; + _items = value; - public string CurrentItem - { - get - { - return _currentItem; - } - set - { - if (_currentItem == value) - return; + ItemsUpdated?.Invoke(this, null); + } + } - _currentItem = value; + private string _currentItem; - CurrentItemChanged?.Invoke(this, null); - } + public string CurrentItem + { + get + { + return _currentItem; } + set + { + if (_currentItem == value) + return; + + _currentItem = value; - public event EventHandler ItemsUpdated; - public event EventHandler CurrentItemChanged; + CurrentItemChanged?.Invoke(this, null); + } } - public class MockDisplayInput : ISelectableItem - { - private MockDisplay _parent; + public event EventHandler ItemsUpdated; + public event EventHandler CurrentItemChanged; +} + +public class MockDisplayInput : ISelectableItem +{ + private MockDisplay _parent; - private bool _isSelected; - - public bool IsSelected + private bool _isSelected; + + public bool IsSelected + { + get { - get - { - return _isSelected; - } - set - { - if (_isSelected == value) - return; - - _isSelected = value; - - ItemUpdated?.Invoke(this, null); - } + return _isSelected; } + set + { + if (_isSelected == value) + return; - public string Name { get; set; } + _isSelected = value; - public string Key { get; set; } + ItemUpdated?.Invoke(this, null); + } + } - public event EventHandler ItemUpdated; + public string Name { get; set; } - public MockDisplayInput(string key, string name, MockDisplay parent) - { - Key = key; - Name = name; - _parent = parent; - } + public string Key { get; set; } - public void Select() - { - if (!_parent.PowerIsOnFeedback.BoolValue) _parent.PowerOn(); + public event EventHandler ItemUpdated; - foreach(var input in _parent.Inputs.Items) - { - input.Value.IsSelected = input.Key == this.Key; - } + public MockDisplayInput(string key, string name, MockDisplay parent) + { + Key = key; + Name = name; + _parent = parent; + } + + public void Select() + { + if (!_parent.PowerIsOnFeedback.BoolValue) _parent.PowerOn(); + + foreach(var input in _parent.Inputs.Items) + { + input.Value.IsSelected = input.Key == this.Key; } } } diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs b/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs index 1bb7f503c..825988e61 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs @@ -11,256 +11,255 @@ using PepperDash.Essentials.Devices.Common; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common.Shades +namespace PepperDash.Essentials.Devices.Common.Shades; + +/// +/// Controls a single shade using three relays +/// +public class ScreenLiftController : EssentialsDevice, IProjectorScreenLiftControl { - /// - /// Controls a single shade using three relays - /// - public class ScreenLiftController : EssentialsDevice, IProjectorScreenLiftControl - { - readonly ScreenLiftControllerConfigProperties Config; - readonly ScreenLiftRelaysConfig RaiseRelayConfig; - readonly ScreenLiftRelaysConfig LowerRelayConfig; - readonly ScreenLiftRelaysConfig LatchedRelayConfig; + readonly ScreenLiftControllerConfigProperties Config; + readonly ScreenLiftRelaysConfig RaiseRelayConfig; + readonly ScreenLiftRelaysConfig LowerRelayConfig; + readonly ScreenLiftRelaysConfig LatchedRelayConfig; - Displays.DisplayBase DisplayDevice; - ISwitchedOutput RaiseRelay; - ISwitchedOutput LowerRelay; - ISwitchedOutput LatchedRelay; + Displays.DisplayBase DisplayDevice; + ISwitchedOutput RaiseRelay; + ISwitchedOutput LowerRelay; + ISwitchedOutput LatchedRelay; - public bool InUpPosition + public bool InUpPosition + { + get { return _isInUpPosition; } + set { - get { return _isInUpPosition; } - set - { - if (value == _isInUpPosition) return; - _isInUpPosition = value; - IsInUpPosition.FireUpdate(); - PositionChanged?.Invoke(this, new EventArgs()); - } + if (value == _isInUpPosition) return; + _isInUpPosition = value; + IsInUpPosition.FireUpdate(); + PositionChanged?.Invoke(this, new EventArgs()); } + } - private bool _isInUpPosition { get; set; } - public eScreenLiftControlType Type { get; private set; } - public eScreenLiftControlMode Mode { get; private set; } + private bool _isInUpPosition { get; set; } + public eScreenLiftControlType Type { get; private set; } + public eScreenLiftControlMode Mode { get; private set; } - public string DisplayDeviceKey { get; private set; } - public BoolFeedback IsInUpPosition { get; private set; } + public string DisplayDeviceKey { get; private set; } + public BoolFeedback IsInUpPosition { get; private set; } - public event EventHandler PositionChanged; + public event EventHandler PositionChanged; - public ScreenLiftController(string key, string name, ScreenLiftControllerConfigProperties config) - : base(key, name) - { - Config = config; - DisplayDeviceKey = Config.DisplayDeviceKey; - Mode = Config.Mode; - Type = Config.Type; - - IsInUpPosition = new BoolFeedback(() => _isInUpPosition); - - switch (Mode) - { - case eScreenLiftControlMode.momentary: - { - RaiseRelayConfig = Config.Relays["raise"]; - LowerRelayConfig = Config.Relays["lower"]; - break; - } - case eScreenLiftControlMode.latched: - { - LatchedRelayConfig = Config.Relays["latched"]; - break; - } - } - } + public ScreenLiftController(string key, string name, ScreenLiftControllerConfigProperties config) + : base(key, name) + { + Config = config; + DisplayDeviceKey = Config.DisplayDeviceKey; + Mode = Config.Mode; + Type = Config.Type; - private void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e) - { - if (!DisplayDevice.IsCoolingDownFeedback.BoolValue && Type == eScreenLiftControlType.lift) - { - Raise(); - return; - } - if (DisplayDevice.IsCoolingDownFeedback.BoolValue && Type == eScreenLiftControlType.screen) - { - Raise(); - return; - } - } + IsInUpPosition = new BoolFeedback(() => _isInUpPosition); - private void IsWarmingUpFeedback_OutputChange(object sender, FeedbackEventArgs e) + switch (Mode) { - if (DisplayDevice.IsWarmingUpFeedback.BoolValue) - { - Lower(); - } + case eScreenLiftControlMode.momentary: + { + RaiseRelayConfig = Config.Relays["raise"]; + LowerRelayConfig = Config.Relays["lower"]; + break; + } + case eScreenLiftControlMode.latched: + { + LatchedRelayConfig = Config.Relays["latched"]; + break; + } } + } - public override bool CustomActivate() + private void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + if (!DisplayDevice.IsCoolingDownFeedback.BoolValue && Type == eScreenLiftControlType.lift) { - //Create ISwitchedOutput objects based on props - switch (Mode) - { - case eScreenLiftControlMode.momentary: - { - Debug.LogMessage(LogEventLevel.Debug, this, $"Getting relays for {Mode}"); - RaiseRelay = GetSwitchedOutputFromDevice(RaiseRelayConfig.DeviceKey); - LowerRelay = GetSwitchedOutputFromDevice(LowerRelayConfig.DeviceKey); - break; - } - case eScreenLiftControlMode.latched: - { - Debug.LogMessage(LogEventLevel.Debug, this, $"Getting relays for {Mode}"); - LatchedRelay = GetSwitchedOutputFromDevice(LatchedRelayConfig.DeviceKey); - break; - } - } - - Debug.LogMessage(LogEventLevel.Debug, this, $"Getting display with key {DisplayDeviceKey}"); - DisplayDevice = GetDisplayBaseFromDevice(DisplayDeviceKey); - - if (DisplayDevice != null) - { - Debug.LogMessage(LogEventLevel.Debug, this, $"Subscribing to {DisplayDeviceKey} feedbacks"); - - DisplayDevice.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange; - DisplayDevice.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange; - } - - return base.CustomActivate(); + Raise(); + return; } - - public void Raise() + if (DisplayDevice.IsCoolingDownFeedback.BoolValue && Type == eScreenLiftControlType.screen) { - if (RaiseRelay == null && LatchedRelay == null) return; - - Debug.LogMessage(LogEventLevel.Debug, this, $"Raising {Type}"); - - switch (Mode) - { - case eScreenLiftControlMode.momentary: - { - PulseOutput(RaiseRelay, RaiseRelayConfig.PulseTimeInMs); - break; - } - case eScreenLiftControlMode.latched: - { - LatchedRelay.Off(); - break; - } - } - InUpPosition = true; + Raise(); + return; } + } - public void Lower() + private void IsWarmingUpFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + if (DisplayDevice.IsWarmingUpFeedback.BoolValue) { - if (LowerRelay == null && LatchedRelay == null) return; - - Debug.LogMessage(LogEventLevel.Debug, this, $"Lowering {Type}"); - - switch (Mode) - { - case eScreenLiftControlMode.momentary: - { - PulseOutput(LowerRelay, LowerRelayConfig.PulseTimeInMs); - break; - } - case eScreenLiftControlMode.latched: - { - LatchedRelay.On(); - break; - } - } - InUpPosition = false; + Lower(); } + } - void PulseOutput(ISwitchedOutput output, int pulseTime) + public override bool CustomActivate() + { + //Create ISwitchedOutput objects based on props + switch (Mode) { - output.On(); - CTimer pulseTimer = new CTimer(new CTimerCallbackFunction((o) => output.Off()), pulseTime); + case eScreenLiftControlMode.momentary: + { + Debug.LogMessage(LogEventLevel.Debug, this, $"Getting relays for {Mode}"); + RaiseRelay = GetSwitchedOutputFromDevice(RaiseRelayConfig.DeviceKey); + LowerRelay = GetSwitchedOutputFromDevice(LowerRelayConfig.DeviceKey); + break; + } + case eScreenLiftControlMode.latched: + { + Debug.LogMessage(LogEventLevel.Debug, this, $"Getting relays for {Mode}"); + LatchedRelay = GetSwitchedOutputFromDevice(LatchedRelayConfig.DeviceKey); + break; + } } - /// - /// Attempts to get the port on teh specified device from config - /// - /// - /// - ISwitchedOutput GetSwitchedOutputFromDevice(string relayKey) - { - var portDevice = DeviceManager.GetDeviceForKey(relayKey); - if (portDevice != null) - { - return (portDevice as ISwitchedOutput); - } - else - { - Debug.LogMessage(LogEventLevel.Debug, this, "Error: Unable to get relay device with key '{0}'", relayKey); - return null; - } - } + Debug.LogMessage(LogEventLevel.Debug, this, $"Getting display with key {DisplayDeviceKey}"); + DisplayDevice = GetDisplayBaseFromDevice(DisplayDeviceKey); - Displays.DisplayBase GetDisplayBaseFromDevice(string displayKey) + if (DisplayDevice != null) { - var displayDevice = DeviceManager.GetDeviceForKey(displayKey); - if (displayDevice != null) - { - return displayDevice as Displays.DisplayBase; - } - else - { - Debug.LogMessage(LogEventLevel.Debug, this, "Error: Unable to get display device with key '{0}'", displayKey); - return null; - } + Debug.LogMessage(LogEventLevel.Debug, this, $"Subscribing to {DisplayDeviceKey} feedbacks"); + + DisplayDevice.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange; + DisplayDevice.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange; } + return base.CustomActivate(); } - public class ScreenLiftControllerConfigProperties + public void Raise() { - [JsonProperty("displayDeviceKey")] - public string DisplayDeviceKey { get; set; } + if (RaiseRelay == null && LatchedRelay == null) return; - [JsonProperty("type")] - [JsonConverter(typeof(StringEnumConverter))] - public eScreenLiftControlType Type { get; set; } + Debug.LogMessage(LogEventLevel.Debug, this, $"Raising {Type}"); - [JsonProperty("mode")] - [JsonConverter(typeof(StringEnumConverter))] - public eScreenLiftControlMode Mode { get; set; } + switch (Mode) + { + case eScreenLiftControlMode.momentary: + { + PulseOutput(RaiseRelay, RaiseRelayConfig.PulseTimeInMs); + break; + } + case eScreenLiftControlMode.latched: + { + LatchedRelay.Off(); + break; + } + } + InUpPosition = true; + } - [JsonProperty("relays")] - public Dictionary Relays { get; set; } + public void Lower() + { + if (LowerRelay == null && LatchedRelay == null) return; + Debug.LogMessage(LogEventLevel.Debug, this, $"Lowering {Type}"); + + switch (Mode) + { + case eScreenLiftControlMode.momentary: + { + PulseOutput(LowerRelay, LowerRelayConfig.PulseTimeInMs); + break; + } + case eScreenLiftControlMode.latched: + { + LatchedRelay.On(); + break; + } + } + InUpPosition = false; } - public class ScreenLiftRelaysConfig - { - [JsonProperty("deviceKey")] - public string DeviceKey { get; set; } - [JsonProperty("pulseTimeInMs")] - public int PulseTimeInMs { get; set; } + void PulseOutput(ISwitchedOutput output, int pulseTime) + { + output.On(); + CTimer pulseTimer = new CTimer(new CTimerCallbackFunction((o) => output.Off()), pulseTime); } - public class ScreenLiftControllerFactory : EssentialsDeviceFactory + /// + /// Attempts to get the port on teh specified device from config + /// + /// + /// + ISwitchedOutput GetSwitchedOutputFromDevice(string relayKey) { - public ScreenLiftControllerFactory() + var portDevice = DeviceManager.GetDeviceForKey(relayKey); + if (portDevice != null) { - TypeNames = new List() { "screenliftcontroller" }; + return (portDevice as ISwitchedOutput); } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) + else { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Comm Device"); - var props = Newtonsoft.Json.JsonConvert.DeserializeObject(dc.Properties.ToString()); + Debug.LogMessage(LogEventLevel.Debug, this, "Error: Unable to get relay device with key '{0}'", relayKey); + return null; + } + } - return new ScreenLiftController(dc.Key, dc.Name, props); + Displays.DisplayBase GetDisplayBaseFromDevice(string displayKey) + { + var displayDevice = DeviceManager.GetDeviceForKey(displayKey); + if (displayDevice != null) + { + return displayDevice as Displays.DisplayBase; + } + else + { + Debug.LogMessage(LogEventLevel.Debug, this, "Error: Unable to get display device with key '{0}'", displayKey); + return null; } } - public enum eScreenLiftControlMode +} + +public class ScreenLiftControllerConfigProperties +{ + [JsonProperty("displayDeviceKey")] + public string DisplayDeviceKey { get; set; } + + [JsonProperty("type")] + [JsonConverter(typeof(StringEnumConverter))] + public eScreenLiftControlType Type { get; set; } + + [JsonProperty("mode")] + [JsonConverter(typeof(StringEnumConverter))] + public eScreenLiftControlMode Mode { get; set; } + + [JsonProperty("relays")] + public Dictionary Relays { get; set; } + +} +public class ScreenLiftRelaysConfig +{ + [JsonProperty("deviceKey")] + public string DeviceKey { get; set; } + + [JsonProperty("pulseTimeInMs")] + public int PulseTimeInMs { get; set; } +} + +public class ScreenLiftControllerFactory : EssentialsDeviceFactory +{ + public ScreenLiftControllerFactory() { - momentary, - latched + TypeNames = new List() { "screenliftcontroller" }; } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Comm Device"); + var props = Newtonsoft.Json.JsonConvert.DeserializeObject(dc.Properties.ToString()); + + return new ScreenLiftController(dc.Key, dc.Name, props); + } +} + +public enum eScreenLiftControlMode +{ + momentary, + latched } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Generic/GenericSink.cs b/src/PepperDash.Essentials.Devices.Common/Generic/GenericSink.cs index 618924cd7..f6b99b094 100644 --- a/src/PepperDash.Essentials.Devices.Common/Generic/GenericSink.cs +++ b/src/PepperDash.Essentials.Devices.Common/Generic/GenericSink.cs @@ -5,56 +5,55 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.Devices.Common.Generic +namespace PepperDash.Essentials.Devices.Common.Generic; + +public class GenericSink : EssentialsDevice, IRoutingSinkWithInputPort { - public class GenericSink : EssentialsDevice, IRoutingSinkWithInputPort + public GenericSink(string key, string name) : base(key, name) { - public GenericSink(string key, string name) : base(key, name) - { - InputPorts = new RoutingPortCollection(); + InputPorts = new RoutingPortCollection(); - var inputPort = new RoutingInputPort(RoutingPortNames.AnyVideoIn, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this); + var inputPort = new RoutingInputPort(RoutingPortNames.AnyVideoIn, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this); - InputPorts.Add(inputPort); - } + InputPorts.Add(inputPort); + } - public RoutingPortCollection InputPorts { get; private set; } + public RoutingPortCollection InputPorts { get; private set; } - public string CurrentSourceInfoKey { get; set; } + public string CurrentSourceInfoKey { get; set; } - private SourceListItem _currentSource; - public SourceListItem CurrentSourceInfo { - get => _currentSource; - set { - if(value == _currentSource) - { - return; - } + private SourceListItem _currentSource; + public SourceListItem CurrentSourceInfo { + get => _currentSource; + set { + if(value == _currentSource) + { + return; + } - CurrentSourceChange?.Invoke(_currentSource, ChangeType.WillChange); + CurrentSourceChange?.Invoke(_currentSource, ChangeType.WillChange); - _currentSource = value; + _currentSource = value; - CurrentSourceChange?.Invoke(_currentSource, ChangeType.DidChange); - } + CurrentSourceChange?.Invoke(_currentSource, ChangeType.DidChange); } + } - public RoutingInputPort CurrentInputPort => InputPorts[0]; + public RoutingInputPort CurrentInputPort => InputPorts[0]; - public event SourceInfoChangeHandler CurrentSourceChange; - } + public event SourceInfoChangeHandler CurrentSourceChange; +} - public class GenericSinkFactory : EssentialsDeviceFactory +public class GenericSinkFactory : EssentialsDeviceFactory +{ + public GenericSinkFactory() { - public GenericSinkFactory() - { - TypeNames = new List() { "genericsink", "genericdestination" }; - } + TypeNames = new List() { "genericsink", "genericdestination" }; + } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Sink Device"); - return new GenericSink(dc.Key, dc.Name); - } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Sink Device"); + return new GenericSink(dc.Key, dc.Name); } } diff --git a/src/PepperDash.Essentials.Devices.Common/Generic/GenericSource.cs b/src/PepperDash.Essentials.Devices.Common/Generic/GenericSource.cs index 3c6e57d29..ea5f497e8 100644 --- a/src/PepperDash.Essentials.Devices.Common/Generic/GenericSource.cs +++ b/src/PepperDash.Essentials.Devices.Common/Generic/GenericSource.cs @@ -11,18 +11,18 @@ using PepperDash.Essentials.Core.Config; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common -{ +namespace PepperDash.Essentials.Devices.Common; + public class GenericSource : EssentialsDevice, IUiDisplayInfo, IRoutingSource, IUsageTracking { public uint DisplayUiType { get { return DisplayUiConstants.TypeNoControls; } } - public GenericSource(string key, string name) + public GenericSource(string key, string name) : base(key, name) { - AnyOut = new RoutingOutputPort(RoutingPortNames.AnyOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, + AnyOut = new RoutingOutputPort(RoutingPortNames.AnyOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, null, this); OutputPorts = new RoutingPortCollection { AnyOut }; } @@ -34,24 +34,23 @@ public GenericSource(string key, string name) #endregion - #region IUsageTracking Members + #region IUsageTracking Members - public UsageTracking UsageTracker { get; set; } + public UsageTracking UsageTracker { get; set; } - #endregion + #endregion } - public class GenericSourceFactory : EssentialsDeviceFactory +public class GenericSourceFactory : EssentialsDeviceFactory +{ + public GenericSourceFactory() + { + TypeNames = new List() { "genericsource" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) { - public GenericSourceFactory() - { - TypeNames = new List() { "genericsource" }; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Source Device"); - return new GenericSource(dc.Key, dc.Name); - } + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Source Device"); + return new GenericSource(dc.Key, dc.Name); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Lighting/LightingBase.cs b/src/PepperDash.Essentials.Devices.Common/Lighting/LightingBase.cs index 6e1dc506f..565f90ed2 100644 --- a/src/PepperDash.Essentials.Devices.Common/Lighting/LightingBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/Lighting/LightingBase.cs @@ -14,61 +14,61 @@ using PepperDash.Essentials.Core.Lighting; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common.Lighting +namespace PepperDash.Essentials.Devices.Common.Lighting; + +public abstract class LightingBase : EssentialsBridgeableDevice, ILightingScenes { - public abstract class LightingBase : EssentialsBridgeableDevice, ILightingScenes - { - #region ILightingScenes Members + #region ILightingScenes Members - public event EventHandler LightingSceneChange; + public event EventHandler LightingSceneChange; - public List LightingScenes { get; protected set; } + public List LightingScenes { get; protected set; } - public LightingScene CurrentLightingScene { get; protected set; } + public LightingScene CurrentLightingScene { get; protected set; } public IntFeedback CurrentLightingSceneFeedback { get; protected set; } - #endregion + #endregion - protected LightingBase(string key, string name) - : base(key, name) - { - LightingScenes = new List(); + protected LightingBase(string key, string name) + : base(key, name) + { + LightingScenes = new List(); - CurrentLightingScene = new LightingScene(); + CurrentLightingScene = new LightingScene(); //CurrentLightingSceneFeedback = new IntFeedback(() => { return int.Parse(this.CurrentLightingScene.ID); }); - } + } - public abstract void SelectScene(LightingScene scene); + public abstract void SelectScene(LightingScene scene); - public void SimulateSceneSelect(string sceneName) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Simulating selection of scene '{0}'", sceneName); + public void SimulateSceneSelect(string sceneName) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Simulating selection of scene '{0}'", sceneName); - var scene = LightingScenes.FirstOrDefault(s => s.Name.Equals(sceneName)); + var scene = LightingScenes.FirstOrDefault(s => s.Name.Equals(sceneName)); - if (scene != null) - { - CurrentLightingScene = scene; - OnLightingSceneChange(); - } + if (scene != null) + { + CurrentLightingScene = scene; + OnLightingSceneChange(); } + } - /// - /// Sets the IsActive property on each scene and fires the LightingSceneChange event - /// - protected void OnLightingSceneChange() + /// + /// Sets the IsActive property on each scene and fires the LightingSceneChange event + /// + protected void OnLightingSceneChange() + { + foreach (var scene in LightingScenes) { - foreach (var scene in LightingScenes) - { - if (scene == CurrentLightingScene) - scene.IsActive = true; + if (scene == CurrentLightingScene) + scene.IsActive = true; - else - scene.IsActive = false; - } - LightingSceneChange?.Invoke(this, new LightingSceneChangeEventArgs(CurrentLightingScene)); + else + scene.IsActive = false; } + LightingSceneChange?.Invoke(this, new LightingSceneChangeEventArgs(CurrentLightingScene)); + } protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) @@ -92,46 +92,45 @@ protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, return LinkLightingToApi(lightingDevice, trilist, joinMap); } - protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, GenericLightingJoinMap joinMap) - { - Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - - Debug.LogMessage(LogEventLevel.Information, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString()); + protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, GenericLightingJoinMap joinMap) + { + Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - // GenericLighitng Actions & FeedBack - trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u])); + Debug.LogMessage(LogEventLevel.Information, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString()); - var sceneIndex = 0; - foreach (var scene in lightingDevice.LightingScenes) - { - var index = sceneIndex; + // GenericLighitng Actions & FeedBack + trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u])); - trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + index), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[index])); - scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)]); - trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name; - trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true; + var sceneIndex = 0; + foreach (var scene in lightingDevice.LightingScenes) + { + var index = sceneIndex; - sceneIndex++; - } + trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + index), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[index])); + scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)]); + trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name; + trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true; - trilist.OnlineStatusChange += (sender, args) => - { - if (!args.DeviceOnLine) return; + sceneIndex++; + } - sceneIndex = 0; - foreach (var scene in lightingDevice.LightingScenes) - { - var index = sceneIndex; + trilist.OnlineStatusChange += (sender, args) => + { + if (!args.DeviceOnLine) return; - trilist.StringInput[(uint) (joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name; - trilist.BooleanInput[(uint) (joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true; - scene.IsActiveFeedback.FireUpdate(); + sceneIndex = 0; + foreach (var scene in lightingDevice.LightingScenes) + { + var index = sceneIndex; - sceneIndex++; - } - }; + trilist.StringInput[(uint) (joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name; + trilist.BooleanInput[(uint) (joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true; + scene.IsActiveFeedback.FireUpdate(); - return joinMap; + sceneIndex++; } - } + }; + + return joinMap; + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj b/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj index 49c057627..0fb34fcf7 100644 --- a/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj +++ b/src/PepperDash.Essentials.Devices.Common/PepperDash.Essentials.Devices.Common.csproj @@ -3,7 +3,7 @@ Debug;Release;Debug 4.7.2 - net472 + net8 true bin\$(Configuration)\ Essentials Devices Common @@ -28,6 +28,7 @@ - + + \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsHuddleSpaceRoom.cs b/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsHuddleSpaceRoom.cs index 1af09f1c1..19ee9410a 100644 --- a/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsHuddleSpaceRoom.cs +++ b/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsHuddleSpaceRoom.cs @@ -1,15 +1,14 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Room.Config; -namespace PepperDash.Essentials.Devices.Common.Room +namespace PepperDash.Essentials.Devices.Common.Room; + +public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IHasDefaultDisplay, IHasCurrentVolumeControls, IRoomOccupancy, + IEmergency, IMicrophonePrivacy { - public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IHasDefaultDisplay, IHasCurrentVolumeControls, IRoomOccupancy, - IEmergency, IMicrophonePrivacy - { - bool ExcludeFromGlobalFunctions { get; } + bool ExcludeFromGlobalFunctions { get; } - void RunRouteAction(string routeKey); + void RunRouteAction(string routeKey); - EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; } - } + EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsHuddleVtc1Room.cs b/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsHuddleVtc1Room.cs index b7f1a6199..fd80010cb 100644 --- a/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsHuddleVtc1Room.cs +++ b/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsHuddleVtc1Room.cs @@ -4,23 +4,22 @@ using PepperDash.Essentials.Devices.Common.VideoCodec; using PepperDash.Essentials.Room.Config; -namespace PepperDash.Essentials.Devices.Common.Room +namespace PepperDash.Essentials.Devices.Common.Room; + +public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback, + IRoomOccupancy, IEmergency, IMicrophonePrivacy { - public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback, - IRoomOccupancy, IEmergency, IMicrophonePrivacy - { - EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; } + EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; } - bool ExcludeFromGlobalFunctions { get; } + bool ExcludeFromGlobalFunctions { get; } - void RunRouteAction(string routeKey); + void RunRouteAction(string routeKey); - IHasScheduleAwareness ScheduleSource { get; } + IHasScheduleAwareness ScheduleSource { get; } - new BoolFeedback InCallFeedback { get; } + new BoolFeedback InCallFeedback { get; } - new BoolFeedback PrivacyModeIsOnFeedback { get; } + new BoolFeedback PrivacyModeIsOnFeedback { get; } - string DefaultCodecRouteString { get; } - } + string DefaultCodecRouteString { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsRoomPropertiesConfig.cs b/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsRoomPropertiesConfig.cs index e32be4c47..69f15d835 100644 --- a/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsRoomPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsRoomPropertiesConfig.cs @@ -5,10 +5,9 @@ using System.Text; using System.Threading.Tasks; -namespace PepperDash.Essentials.Devices.Common.Room +namespace PepperDash.Essentials.Devices.Common.Room; + +public interface IEssentialsRoomPropertiesConfig { - public interface IEssentialsRoomPropertiesConfig - { - EssentialsRoomPropertiesConfig PropertiesConfig { get; } - } + EssentialsRoomPropertiesConfig PropertiesConfig { get; } } diff --git a/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsTechRoom.cs b/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsTechRoom.cs index 947be5d96..00b0348eb 100644 --- a/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsTechRoom.cs +++ b/src/PepperDash.Essentials.Devices.Common/Room/IEssentialsTechRoom.cs @@ -6,17 +6,16 @@ using TwoWayDisplayBase = PepperDash.Essentials.Devices.Common.Displays.TwoWayDisplayBase; -namespace PepperDash.Essentials.Devices.Common.Room +namespace PepperDash.Essentials.Devices.Common.Room; + +public interface IEssentialsTechRoom:IEssentialsRoom, ITvPresetsProvider,IBridgeAdvanced,IRunDirectRouteAction { - public interface IEssentialsTechRoom:IEssentialsRoom, ITvPresetsProvider,IBridgeAdvanced,IRunDirectRouteAction - { - EssentialsTechRoomConfig PropertiesConfig { get; } - Dictionary Tuners { get; } + EssentialsTechRoomConfig PropertiesConfig { get; } + Dictionary Tuners { get; } - Dictionary Displays { get; } + Dictionary Displays { get; } - void RoomPowerOn(); + void RoomPowerOn(); - void RoomPowerOff(); - } + void RoomPowerOff(); } diff --git a/src/PepperDash.Essentials.Devices.Common/SetTopBox/IRSetTopBoxBase.cs b/src/PepperDash.Essentials.Devices.Common/SetTopBox/IRSetTopBoxBase.cs index 32885aec6..808568de2 100644 --- a/src/PepperDash.Essentials.Devices.Common/SetTopBox/IRSetTopBoxBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/SetTopBox/IRSetTopBoxBase.cs @@ -16,41 +16,41 @@ using PepperDash.Essentials.Core.DeviceTypeInterfaces; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common -{ - [Description("Wrapper class for an IR Set Top Box")] - public class IRSetTopBoxBase : EssentialsBridgeableDevice, ISetTopBoxControls, IRoutingSource, IRoutingOutputs, IUsageTracking, IHasPowerControl, ITvPresetsProvider +namespace PepperDash.Essentials.Devices.Common; + +[Description("Wrapper class for an IR Set Top Box")] +public class IRSetTopBoxBase : EssentialsBridgeableDevice, ISetTopBoxControls, IRoutingSource, IRoutingOutputs, IUsageTracking, IHasPowerControl, ITvPresetsProvider { public IrOutputPortController IrPort { get; private set; } public uint DisplayUiType { get { return DisplayUiConstants.TypeDirecTv; } } - public ushort IrPulseTime { get; set; } + public ushort IrPulseTime { get; set; } - public bool HasPresets { get; set; } - public bool HasDvr { get; set; } - public bool HasDpad { get; set; } - public bool HasNumeric { get; set; } + public bool HasPresets { get; set; } + public bool HasDvr { get; set; } + public bool HasDpad { get; set; } + public bool HasNumeric { get; set; } - public DevicePresetsModel TvPresets { get; private set; } + public DevicePresetsModel TvPresets { get; private set; } public IRSetTopBoxBase(string key, string name, IrOutputPortController portCont, - SetTopBoxPropertiesConfig props) + SetTopBoxPropertiesConfig props) : base(key, name) { IrPort = portCont; - IrPulseTime = 200; + IrPulseTime = 200; - if (props.IrPulseTime > 0) - { - IrPulseTime = (ushort)props.IrPulseTime; - } + if (props.IrPulseTime > 0) + { + IrPulseTime = (ushort)props.IrPulseTime; + } DeviceManager.AddDevice(portCont); - HasPresets = props.HasPresets; - HasDvr = props.HasDvr; - HasDpad = props.HasDpad; - HasNumeric = props.HasNumeric; + HasPresets = props.HasPresets; + HasDvr = props.HasDvr; + HasDpad = props.HasDpad; + HasNumeric = props.HasNumeric; HasKeypadAccessoryButton1 = true; KeypadAccessoryButton1Command = "Dash"; @@ -347,174 +347,172 @@ public void Stop(bool pressRelease) #endregion - #region IUsageTracking Members + #region IUsageTracking Members - public UsageTracking UsageTracker { get; set; } + public UsageTracking UsageTracker { get; set; } - #endregion + #endregion - #region IPower Members + #region IPower Members - public void PowerOn() - { - IrPort.Pulse(IROutputStandardCommands.IROut_POWER_ON, IrPulseTime); - } + public void PowerOn() + { + IrPort.Pulse(IROutputStandardCommands.IROut_POWER_ON, IrPulseTime); + } - public void PowerOff() - { - IrPort.Pulse(IROutputStandardCommands.IROut_POWER_OFF, IrPulseTime); - } + public void PowerOff() + { + IrPort.Pulse(IROutputStandardCommands.IROut_POWER_OFF, IrPulseTime); + } - public void PowerToggle() - { - IrPort.Pulse(IROutputStandardCommands.IROut_POWER, IrPulseTime); - } + public void PowerToggle() + { + IrPort.Pulse(IROutputStandardCommands.IROut_POWER, IrPulseTime); + } - #endregion + #endregion public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { - var joinMap = new SetTopBoxControllerJoinMap(joinStart); - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + var joinMap = new SetTopBoxControllerJoinMap(joinStart); + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - if (!string.IsNullOrEmpty(joinMapSerialized)) - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); + } - Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - Debug.LogMessage(LogEventLevel.Information, "Linking to SetTopBox: {0}", Name); + Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + Debug.LogMessage(LogEventLevel.Information, "Linking to SetTopBox: {0}", Name); - trilist.OnlineStatusChange += new OnlineStatusChangeEventHandler((o, a) => + trilist.OnlineStatusChange += new OnlineStatusChangeEventHandler((o, a) => + { + if (a.DeviceOnLine) { - if (a.DeviceOnLine) - { - trilist.StringInput[joinMap.Name.JoinNumber].StringValue = Name; - } - }); + trilist.StringInput[joinMap.Name.JoinNumber].StringValue = Name; + } + }); - var stbBase = this as ISetTopBoxControls; - if (stbBase != null) - { - trilist.BooleanInput[joinMap.HasDpad.JoinNumber].BoolValue = stbBase.HasDpad; - trilist.BooleanInput[joinMap.HasNumeric.JoinNumber].BoolValue = stbBase.HasNumeric; - trilist.BooleanInput[joinMap.HasDvr.JoinNumber].BoolValue = stbBase.HasDvr; - trilist.BooleanInput[joinMap.HasPresets.JoinNumber].BoolValue = stbBase.HasPresets; + var stbBase = this as ISetTopBoxControls; + if (stbBase != null) + { + trilist.BooleanInput[joinMap.HasDpad.JoinNumber].BoolValue = stbBase.HasDpad; + trilist.BooleanInput[joinMap.HasNumeric.JoinNumber].BoolValue = stbBase.HasNumeric; + trilist.BooleanInput[joinMap.HasDvr.JoinNumber].BoolValue = stbBase.HasDvr; + trilist.BooleanInput[joinMap.HasPresets.JoinNumber].BoolValue = stbBase.HasPresets; - trilist.SetBoolSigAction(joinMap.DvrList.JoinNumber, stbBase.DvrList); - trilist.SetBoolSigAction(joinMap.Replay.JoinNumber, stbBase.Replay); + trilist.SetBoolSigAction(joinMap.DvrList.JoinNumber, stbBase.DvrList); + trilist.SetBoolSigAction(joinMap.Replay.JoinNumber, stbBase.Replay); - trilist.SetStringSigAction(joinMap.LoadPresets.JoinNumber, stbBase.LoadPresets); - } + trilist.SetStringSigAction(joinMap.LoadPresets.JoinNumber, stbBase.LoadPresets); + } var stbPower = this as IHasPowerControl; - if (stbPower != null) - { - trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, stbPower.PowerOn); - trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, stbPower.PowerOff); - trilist.SetSigTrueAction(joinMap.PowerToggle.JoinNumber, stbPower.PowerToggle); - } + if (stbPower != null) + { + trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, stbPower.PowerOn); + trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, stbPower.PowerOff); + trilist.SetSigTrueAction(joinMap.PowerToggle.JoinNumber, stbPower.PowerToggle); + } var stbDPad = this as IDPad; - if (stbDPad != null) - { - trilist.SetBoolSigAction(joinMap.Up.JoinNumber, stbDPad.Up); - trilist.SetBoolSigAction(joinMap.Down.JoinNumber, stbDPad.Down); - trilist.SetBoolSigAction(joinMap.Left.JoinNumber, stbDPad.Left); - trilist.SetBoolSigAction(joinMap.Right.JoinNumber, stbDPad.Right); - trilist.SetBoolSigAction(joinMap.Select.JoinNumber, stbDPad.Select); - trilist.SetBoolSigAction(joinMap.Menu.JoinNumber, stbDPad.Menu); - trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbDPad.Exit); - } + if (stbDPad != null) + { + trilist.SetBoolSigAction(joinMap.Up.JoinNumber, stbDPad.Up); + trilist.SetBoolSigAction(joinMap.Down.JoinNumber, stbDPad.Down); + trilist.SetBoolSigAction(joinMap.Left.JoinNumber, stbDPad.Left); + trilist.SetBoolSigAction(joinMap.Right.JoinNumber, stbDPad.Right); + trilist.SetBoolSigAction(joinMap.Select.JoinNumber, stbDPad.Select); + trilist.SetBoolSigAction(joinMap.Menu.JoinNumber, stbDPad.Menu); + trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbDPad.Exit); + } var stbChannel = this as IChannel; - if (stbChannel != null) - { - trilist.SetBoolSigAction(joinMap.ChannelUp.JoinNumber, stbChannel.ChannelUp); - trilist.SetBoolSigAction(joinMap.ChannelDown.JoinNumber, stbChannel.ChannelDown); - trilist.SetBoolSigAction(joinMap.LastChannel.JoinNumber, stbChannel.LastChannel); - trilist.SetBoolSigAction(joinMap.Guide.JoinNumber, stbChannel.Guide); - trilist.SetBoolSigAction(joinMap.Info.JoinNumber, stbChannel.Info); - trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbChannel.Exit); - } + if (stbChannel != null) + { + trilist.SetBoolSigAction(joinMap.ChannelUp.JoinNumber, stbChannel.ChannelUp); + trilist.SetBoolSigAction(joinMap.ChannelDown.JoinNumber, stbChannel.ChannelDown); + trilist.SetBoolSigAction(joinMap.LastChannel.JoinNumber, stbChannel.LastChannel); + trilist.SetBoolSigAction(joinMap.Guide.JoinNumber, stbChannel.Guide); + trilist.SetBoolSigAction(joinMap.Info.JoinNumber, stbChannel.Info); + trilist.SetBoolSigAction(joinMap.Exit.JoinNumber, stbChannel.Exit); + } var stbColor = this as IColor; - if (stbColor != null) - { - trilist.SetBoolSigAction(joinMap.Red.JoinNumber, stbColor.Red); - trilist.SetBoolSigAction(joinMap.Green.JoinNumber, stbColor.Green); - trilist.SetBoolSigAction(joinMap.Yellow.JoinNumber, stbColor.Yellow); - trilist.SetBoolSigAction(joinMap.Blue.JoinNumber, stbColor.Blue); - } + if (stbColor != null) + { + trilist.SetBoolSigAction(joinMap.Red.JoinNumber, stbColor.Red); + trilist.SetBoolSigAction(joinMap.Green.JoinNumber, stbColor.Green); + trilist.SetBoolSigAction(joinMap.Yellow.JoinNumber, stbColor.Yellow); + trilist.SetBoolSigAction(joinMap.Blue.JoinNumber, stbColor.Blue); + } var stbKeypad = this as ISetTopBoxNumericKeypad; - if (stbKeypad != null) - { - trilist.StringInput[joinMap.KeypadAccessoryButton1Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton1Label; - trilist.StringInput[joinMap.KeypadAccessoryButton2Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton2Label; - - trilist.BooleanInput[joinMap.HasKeypadAccessoryButton1.JoinNumber].BoolValue = stbKeypad.HasKeypadAccessoryButton1; - trilist.BooleanInput[joinMap.HasKeypadAccessoryButton2.JoinNumber].BoolValue = stbKeypad.HasKeypadAccessoryButton2; - - trilist.SetBoolSigAction(joinMap.Digit0.JoinNumber, stbKeypad.Digit0); - trilist.SetBoolSigAction(joinMap.Digit1.JoinNumber, stbKeypad.Digit1); - trilist.SetBoolSigAction(joinMap.Digit2.JoinNumber, stbKeypad.Digit2); - trilist.SetBoolSigAction(joinMap.Digit3.JoinNumber, stbKeypad.Digit3); - trilist.SetBoolSigAction(joinMap.Digit4.JoinNumber, stbKeypad.Digit4); - trilist.SetBoolSigAction(joinMap.Digit5.JoinNumber, stbKeypad.Digit5); - trilist.SetBoolSigAction(joinMap.Digit6.JoinNumber, stbKeypad.Digit6); - trilist.SetBoolSigAction(joinMap.Digit7.JoinNumber, stbKeypad.Digit7); - trilist.SetBoolSigAction(joinMap.Digit8.JoinNumber, stbKeypad.Digit8); - trilist.SetBoolSigAction(joinMap.Digit9.JoinNumber, stbKeypad.Digit9); - trilist.SetBoolSigAction(joinMap.KeypadAccessoryButton1Press.JoinNumber, stbKeypad.KeypadAccessoryButton1); - trilist.SetBoolSigAction(joinMap.KeypadAccessoryButton2Press.JoinNumber, stbKeypad.KeypadAccessoryButton1); - trilist.SetBoolSigAction(joinMap.Dash.JoinNumber, stbKeypad.Dash); - trilist.SetBoolSigAction(joinMap.KeypadEnter.JoinNumber, stbKeypad.KeypadEnter); - } + if (stbKeypad != null) + { + trilist.StringInput[joinMap.KeypadAccessoryButton1Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton1Label; + trilist.StringInput[joinMap.KeypadAccessoryButton2Label.JoinNumber].StringValue = stbKeypad.KeypadAccessoryButton2Label; + + trilist.BooleanInput[joinMap.HasKeypadAccessoryButton1.JoinNumber].BoolValue = stbKeypad.HasKeypadAccessoryButton1; + trilist.BooleanInput[joinMap.HasKeypadAccessoryButton2.JoinNumber].BoolValue = stbKeypad.HasKeypadAccessoryButton2; + + trilist.SetBoolSigAction(joinMap.Digit0.JoinNumber, stbKeypad.Digit0); + trilist.SetBoolSigAction(joinMap.Digit1.JoinNumber, stbKeypad.Digit1); + trilist.SetBoolSigAction(joinMap.Digit2.JoinNumber, stbKeypad.Digit2); + trilist.SetBoolSigAction(joinMap.Digit3.JoinNumber, stbKeypad.Digit3); + trilist.SetBoolSigAction(joinMap.Digit4.JoinNumber, stbKeypad.Digit4); + trilist.SetBoolSigAction(joinMap.Digit5.JoinNumber, stbKeypad.Digit5); + trilist.SetBoolSigAction(joinMap.Digit6.JoinNumber, stbKeypad.Digit6); + trilist.SetBoolSigAction(joinMap.Digit7.JoinNumber, stbKeypad.Digit7); + trilist.SetBoolSigAction(joinMap.Digit8.JoinNumber, stbKeypad.Digit8); + trilist.SetBoolSigAction(joinMap.Digit9.JoinNumber, stbKeypad.Digit9); + trilist.SetBoolSigAction(joinMap.KeypadAccessoryButton1Press.JoinNumber, stbKeypad.KeypadAccessoryButton1); + trilist.SetBoolSigAction(joinMap.KeypadAccessoryButton2Press.JoinNumber, stbKeypad.KeypadAccessoryButton1); + trilist.SetBoolSigAction(joinMap.Dash.JoinNumber, stbKeypad.Dash); + trilist.SetBoolSigAction(joinMap.KeypadEnter.JoinNumber, stbKeypad.KeypadEnter); + } var stbTransport = this as ITransport; - if (stbTransport != null) - { - trilist.SetBoolSigAction(joinMap.Play.JoinNumber, stbTransport.Play); - trilist.SetBoolSigAction(joinMap.Pause.JoinNumber, stbTransport.Pause); - trilist.SetBoolSigAction(joinMap.Rewind.JoinNumber, stbTransport.Rewind); - trilist.SetBoolSigAction(joinMap.FFwd.JoinNumber, stbTransport.FFwd); - trilist.SetBoolSigAction(joinMap.ChapMinus.JoinNumber, stbTransport.ChapMinus); - trilist.SetBoolSigAction(joinMap.ChapPlus.JoinNumber, stbTransport.ChapPlus); - trilist.SetBoolSigAction(joinMap.Stop.JoinNumber, stbTransport.Stop); - trilist.SetBoolSigAction(joinMap.Record.JoinNumber, stbTransport.Record); - } + if (stbTransport != null) + { + trilist.SetBoolSigAction(joinMap.Play.JoinNumber, stbTransport.Play); + trilist.SetBoolSigAction(joinMap.Pause.JoinNumber, stbTransport.Pause); + trilist.SetBoolSigAction(joinMap.Rewind.JoinNumber, stbTransport.Rewind); + trilist.SetBoolSigAction(joinMap.FFwd.JoinNumber, stbTransport.FFwd); + trilist.SetBoolSigAction(joinMap.ChapMinus.JoinNumber, stbTransport.ChapMinus); + trilist.SetBoolSigAction(joinMap.ChapPlus.JoinNumber, stbTransport.ChapPlus); + trilist.SetBoolSigAction(joinMap.Stop.JoinNumber, stbTransport.Stop); + trilist.SetBoolSigAction(joinMap.Record.JoinNumber, stbTransport.Record); + } } } - public class IRSetTopBoxBaseFactory : EssentialsDeviceFactory +public class IRSetTopBoxBaseFactory : EssentialsDeviceFactory +{ + public IRSetTopBoxBaseFactory() { - public IRSetTopBoxBaseFactory() - { - TypeNames = new List() { "settopbox" }; - } + TypeNames = new List() { "settopbox" }; + } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new SetTopBox Device"); - var irCont = IRPortHelper.GetIrOutputPortController(dc); - var config = dc.Properties.ToObject(); - var stb = new IRSetTopBoxBase(dc.Key, dc.Name, irCont, config); + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new SetTopBox Device"); + var irCont = IRPortHelper.GetIrOutputPortController(dc); + var config = dc.Properties.ToObject(); + var stb = new IRSetTopBoxBase(dc.Key, dc.Name, irCont, config); - var listName = dc.Properties.Value("presetsList"); - if (listName != null) - stb.LoadPresets(listName); - return stb; + var listName = dc.Properties.Value("presetsList"); + if (listName != null) + stb.LoadPresets(listName); + return stb; - } } - } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/SetTopBox/SetTopBoxPropertiesConfig.cs b/src/PepperDash.Essentials.Devices.Common/SetTopBox/SetTopBoxPropertiesConfig.cs index 8faac507b..35cfbf411 100644 --- a/src/PepperDash.Essentials.Devices.Common/SetTopBox/SetTopBoxPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Devices.Common/SetTopBox/SetTopBoxPropertiesConfig.cs @@ -6,16 +6,15 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Devices.Common +namespace PepperDash.Essentials.Devices.Common; + +public class SetTopBoxPropertiesConfig : PepperDash.Essentials.Core.Config.SourceDevicePropertiesConfigBase { - public class SetTopBoxPropertiesConfig : PepperDash.Essentials.Core.Config.SourceDevicePropertiesConfigBase - { - public bool HasPresets { get; set; } - public bool HasDvr { get; set; } - public bool HasDpad { get; set; } - public bool HasNumeric { get; set; } - public int IrPulseTime { get; set; } + public bool HasPresets { get; set; } + public bool HasDvr { get; set; } + public bool HasDpad { get; set; } + public bool HasNumeric { get; set; } + public int IrPulseTime { get; set; } - public ControlPropertiesConfig Control { get; set; } - } + public ControlPropertiesConfig Control { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Shades/RelayControlledShade.cs b/src/PepperDash.Essentials.Devices.Common/Shades/RelayControlledShade.cs index 085517b27..582759540 100644 --- a/src/PepperDash.Essentials.Devices.Common/Shades/RelayControlledShade.cs +++ b/src/PepperDash.Essentials.Devices.Common/Shades/RelayControlledShade.cs @@ -7,122 +7,120 @@ using PepperDash.Essentials.Core.Shades; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common.Shades +namespace PepperDash.Essentials.Devices.Common.Shades; + +/// +/// Controls a single shade using three relays +/// +public class RelayControlledShade : ShadeBase, IShadesOpenCloseStop { - /// - /// Controls a single shade using three relays - /// - public class RelayControlledShade : ShadeBase, IShadesOpenCloseStop - { - RelayControlledShadeConfigProperties Config; + RelayControlledShadeConfigProperties Config; - ISwitchedOutput OpenRelay; - ISwitchedOutput StopOrPresetRelay; - ISwitchedOutput CloseRelay; + ISwitchedOutput OpenRelay; + ISwitchedOutput StopOrPresetRelay; + ISwitchedOutput CloseRelay; - int RelayPulseTime; + int RelayPulseTime; - public string StopOrPresetButtonLabel { get; set; } + public string StopOrPresetButtonLabel { get; set; } - public RelayControlledShade(string key, string name, RelayControlledShadeConfigProperties config) - : base(key, name) - { - Config = config; + public RelayControlledShade(string key, string name, RelayControlledShadeConfigProperties config) + : base(key, name) + { + Config = config; - RelayPulseTime = Config.RelayPulseTime; + RelayPulseTime = Config.RelayPulseTime; - StopOrPresetButtonLabel = Config.StopOrPresetLabel; + StopOrPresetButtonLabel = Config.StopOrPresetLabel; - } + } - public override bool CustomActivate() - { - //Create ISwitchedOutput objects based on props - OpenRelay = GetSwitchedOutputFromDevice(Config.Relays.Open); - StopOrPresetRelay = GetSwitchedOutputFromDevice(Config.Relays.StopOrPreset); - CloseRelay = GetSwitchedOutputFromDevice(Config.Relays.Close); + public override bool CustomActivate() + { + //Create ISwitchedOutput objects based on props + OpenRelay = GetSwitchedOutputFromDevice(Config.Relays.Open); + StopOrPresetRelay = GetSwitchedOutputFromDevice(Config.Relays.StopOrPreset); + CloseRelay = GetSwitchedOutputFromDevice(Config.Relays.Close); - return base.CustomActivate(); - } + return base.CustomActivate(); + } - public override void Open() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Opening Shade: '{0}'", this.Name); + public override void Open() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Opening Shade: '{0}'", this.Name); - PulseOutput(OpenRelay, RelayPulseTime); - } + PulseOutput(OpenRelay, RelayPulseTime); + } - public override void Stop() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Shade: '{0}'", this.Name); + public override void Stop() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Shade: '{0}'", this.Name); - PulseOutput(StopOrPresetRelay, RelayPulseTime); - } + PulseOutput(StopOrPresetRelay, RelayPulseTime); + } - public override void Close() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Closing Shade: '{0}'", this.Name); + public override void Close() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Closing Shade: '{0}'", this.Name); - PulseOutput(CloseRelay, RelayPulseTime); - } + PulseOutput(CloseRelay, RelayPulseTime); + } - void PulseOutput(ISwitchedOutput output, int pulseTime) + void PulseOutput(ISwitchedOutput output, int pulseTime) + { + output.On(); + CTimer pulseTimer = new CTimer(new CTimerCallbackFunction((o) => output.Off()), pulseTime); + } + + /// + /// Attempts to get the port on teh specified device from config + /// + /// + /// + ISwitchedOutput GetSwitchedOutputFromDevice(IOPortConfig relayConfig) + { + var portDevice = DeviceManager.GetDeviceForKey(relayConfig.PortDeviceKey); + + if (portDevice != null) { - output.On(); - CTimer pulseTimer = new CTimer(new CTimerCallbackFunction((o) => output.Off()), pulseTime); + return (portDevice as ISwitchedOutputCollection).SwitchedOutputs[relayConfig.PortNumber]; } - - /// - /// Attempts to get the port on teh specified device from config - /// - /// - /// - ISwitchedOutput GetSwitchedOutputFromDevice(IOPortConfig relayConfig) + else { - var portDevice = DeviceManager.GetDeviceForKey(relayConfig.PortDeviceKey); - - if (portDevice != null) - { - return (portDevice as ISwitchedOutputCollection).SwitchedOutputs[relayConfig.PortNumber]; - } - else - { - Debug.LogMessage(LogEventLevel.Debug, this, "Error: Unable to get relay on port '{0}' from device with key '{1}'", relayConfig.PortNumber, relayConfig.PortDeviceKey); - return null; - } + Debug.LogMessage(LogEventLevel.Debug, this, "Error: Unable to get relay on port '{0}' from device with key '{1}'", relayConfig.PortNumber, relayConfig.PortDeviceKey); + return null; } - } - public class RelayControlledShadeConfigProperties - { - public int RelayPulseTime { get; set; } - public ShadeRelaysConfig Relays { get; set; } - public string StopOrPresetLabel { get; set; } +} - public class ShadeRelaysConfig - { - public IOPortConfig Open { get; set; } - public IOPortConfig StopOrPreset { get; set; } - public IOPortConfig Close { get; set; } - } +public class RelayControlledShadeConfigProperties +{ + public int RelayPulseTime { get; set; } + public ShadeRelaysConfig Relays { get; set; } + public string StopOrPresetLabel { get; set; } + + public class ShadeRelaysConfig + { + public IOPortConfig Open { get; set; } + public IOPortConfig StopOrPreset { get; set; } + public IOPortConfig Close { get; set; } } +} - public class RelayControlledShadeFactory : EssentialsDeviceFactory +public class RelayControlledShadeFactory : EssentialsDeviceFactory +{ + public RelayControlledShadeFactory() { - public RelayControlledShadeFactory() - { - TypeNames = new List() { "relaycontrolledshade" }; - } + TypeNames = new List() { "relaycontrolledshade" }; + } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Comm Device"); - var props = Newtonsoft.Json.JsonConvert.DeserializeObject(dc.Properties.ToString()); + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Comm Device"); + var props = Newtonsoft.Json.JsonConvert.DeserializeObject(dc.Properties.ToString()); - return new RelayControlledShade(dc.Key, dc.Name, props); - } + return new RelayControlledShade(dc.Key, dc.Name, props); } - } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Shades/ShadeBase.cs b/src/PepperDash.Essentials.Devices.Common/Shades/ShadeBase.cs index 2c506750d..f4a64a135 100644 --- a/src/PepperDash.Essentials.Devices.Common/Shades/ShadeBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/Shades/ShadeBase.cs @@ -1,22 +1,21 @@ using PepperDash.Essentials.Core.Shades; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Devices.Common.Shades +namespace PepperDash.Essentials.Devices.Common.Shades; + +public abstract class ShadeBase : EssentialsDevice, IShadesOpenCloseStop { - public abstract class ShadeBase : EssentialsDevice, IShadesOpenCloseStop + public ShadeBase(string key, string name) + : base(key, name) { - public ShadeBase(string key, string name) - : base(key, name) - { - } + } - #region iShadesOpenClose Members + #region iShadesOpenClose Members - public abstract void Open(); - public abstract void Stop(); - public abstract void Close(); + public abstract void Open(); + public abstract void Stop(); + public abstract void Close(); - #endregion - } + #endregion } diff --git a/src/PepperDash.Essentials.Devices.Common/Shades/ShadeController.cs b/src/PepperDash.Essentials.Devices.Common/Shades/ShadeController.cs index 43ce0abc8..623d1751b 100644 --- a/src/PepperDash.Essentials.Devices.Common/Shades/ShadeController.cs +++ b/src/PepperDash.Essentials.Devices.Common/Shades/ShadeController.cs @@ -5,70 +5,68 @@ using PepperDash.Essentials.Core.Shades; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common.Shades +namespace PepperDash.Essentials.Devices.Common.Shades; + +/// +/// Class that contains the shades to be controlled in a room +/// +public class ShadeController : EssentialsDevice, IShades { - /// - /// Class that contains the shades to be controlled in a room - /// - public class ShadeController : EssentialsDevice, IShades - { - ShadeControllerConfigProperties Config; + ShadeControllerConfigProperties Config; - public List Shades { get; private set; } + public List Shades { get; private set; } - public ShadeController(string key, string name, ShadeControllerConfigProperties config) - : base(key, name) - { - Config = config; + public ShadeController(string key, string name, ShadeControllerConfigProperties config) + : base(key, name) + { + Config = config; - Shades = new List(); - } + Shades = new List(); + } - public override bool CustomActivate() + public override bool CustomActivate() + { + foreach (var shadeConfig in Config.Shades) { - foreach (var shadeConfig in Config.Shades) - { - var shade = DeviceManager.GetDeviceForKey(shadeConfig.Key) as ShadeBase; + var shade = DeviceManager.GetDeviceForKey(shadeConfig.Key) as ShadeBase; - if (shade != null) - { - AddShade(shade); - } + if (shade != null) + { + AddShade(shade); } - return base.CustomActivate(); - } - - void AddShade(IShadesOpenCloseStop shade) - { - Shades.Add(shade); } + return base.CustomActivate(); } - public class ShadeControllerConfigProperties + void AddShade(IShadesOpenCloseStop shade) { - public List Shades { get; set; } + Shades.Add(shade); + } +} +public class ShadeControllerConfigProperties +{ + public List Shades { get; set; } - public class ShadeConfig - { - public string Key { get; set; } - } + + public class ShadeConfig + { + public string Key { get; set; } } +} - public class ShadeControllerFactory : EssentialsDeviceFactory +public class ShadeControllerFactory : EssentialsDeviceFactory +{ + public ShadeControllerFactory() { - public ShadeControllerFactory() - { - TypeNames = new List() { "shadecontroller" }; - } + TypeNames = new List() { "shadecontroller" }; + } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new ShadeController Device"); - var props = Newtonsoft.Json.JsonConvert.DeserializeObject(dc.Properties.ToString()); + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new ShadeController Device"); + var props = Newtonsoft.Json.JsonConvert.DeserializeObject(dc.Properties.ToString()); - return new ShadeController(dc.Key, dc.Name, props); - } + return new ShadeController(dc.Key, dc.Name, props); } - } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/SoftCodec/BlueJeansPc.cs b/src/PepperDash.Essentials.Devices.Common/SoftCodec/BlueJeansPc.cs index 891f92b11..9bdec0a8c 100644 --- a/src/PepperDash.Essentials.Devices.Common/SoftCodec/BlueJeansPc.cs +++ b/src/PepperDash.Essentials.Devices.Common/SoftCodec/BlueJeansPc.cs @@ -9,173 +9,171 @@ using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common.SoftCodec +namespace PepperDash.Essentials.Devices.Common.SoftCodec; + +public class BlueJeansPc : InRoomPc, IRunRouteAction, IRoutingSink { - public class BlueJeansPc : InRoomPc, IRunRouteAction, IRoutingSink - { - public RoutingInputPort AnyVideoIn { get; private set; } + public RoutingInputPort AnyVideoIn { get; private set; } - public RoutingInputPort CurrentInputPort => AnyVideoIn; + public RoutingInputPort CurrentInputPort => AnyVideoIn; - #region IRoutingInputs Members + #region IRoutingInputs Members - public RoutingPortCollection InputPorts { get; private set; } + public RoutingPortCollection InputPorts { get; private set; } - #endregion + #endregion - public BlueJeansPc(string key, string name) - : base(key, name) + public BlueJeansPc(string key, string name) + : base(key, name) + { + InputPorts = new RoutingPortCollection { - InputPorts = new RoutingPortCollection + (AnyVideoIn = new RoutingInputPort(RoutingPortNames.AnyVideoIn, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.None, 0, this)) + }; + } + + #region IRunRouteAction Members + + public void RunRouteAction(string routeKey, string sourceListKey) + { + RunRouteAction(routeKey, sourceListKey, null); + } + + public void RunRouteAction(string routeKey, string sourceListKey, Action successCallback) + { + CrestronInvoke.BeginInvoke(o => { - (AnyVideoIn = new RoutingInputPort(RoutingPortNames.AnyVideoIn, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.None, 0, this)) - }; - } + Debug.LogMessage(LogEventLevel.Debug, this, "Run route action '{0}' on SourceList: {1}", routeKey, sourceListKey); - #region IRunRouteAction Members + var dict = ConfigReader.ConfigObject.GetSourceListForKey(sourceListKey); + if (dict == null) + { + Debug.LogMessage(LogEventLevel.Debug, this, "WARNING: Config source list '{0}' not found", sourceListKey); + return; + } - public void RunRouteAction(string routeKey, string sourceListKey) - { - RunRouteAction(routeKey, sourceListKey, null); - } + // Try to get the list item by it's string key + if (!dict.ContainsKey(routeKey)) + { + Debug.LogMessage(LogEventLevel.Debug, this, "WARNING: No item '{0}' found on config list '{1}'", + routeKey, sourceListKey); + return; + } - public void RunRouteAction(string routeKey, string sourceListKey, Action successCallback) - { - CrestronInvoke.BeginInvoke(o => + var item = dict[routeKey]; + + foreach (var route in item.RouteList) { - Debug.LogMessage(LogEventLevel.Debug, this, "Run route action '{0}' on SourceList: {1}", routeKey, sourceListKey); - - var dict = ConfigReader.ConfigObject.GetSourceListForKey(sourceListKey); - if (dict == null) - { - Debug.LogMessage(LogEventLevel.Debug, this, "WARNING: Config source list '{0}' not found", sourceListKey); - return; - } - - // Try to get the list item by it's string key - if (!dict.ContainsKey(routeKey)) - { - Debug.LogMessage(LogEventLevel.Debug, this, "WARNING: No item '{0}' found on config list '{1}'", - routeKey, sourceListKey); - return; - } - - var item = dict[routeKey]; - - foreach (var route in item.RouteList) - { - DoRoute(route); - } - - // store the name and UI info for routes - if (item.SourceKey == "none") - { - CurrentSourceInfoKey = routeKey; - CurrentSourceInfo = null; - } - else if (item.SourceKey != null) - { - CurrentSourceInfoKey = routeKey; - CurrentSourceInfo = item; - } - - // report back when done - if (successCallback != null) - successCallback(); - }); - } + DoRoute(route); + } - #endregion + // store the name and UI info for routes + if (item.SourceKey == "none") + { + CurrentSourceInfoKey = routeKey; + CurrentSourceInfo = null; + } + else if (item.SourceKey != null) + { + CurrentSourceInfoKey = routeKey; + CurrentSourceInfo = item; + } - /// - /// - /// - /// - /// - bool DoRoute(SourceRouteListItem route) - { - IRoutingSink dest = null; + // report back when done + if (successCallback != null) + successCallback(); + }); + } - dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSink; + #endregion - if (dest == null) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Cannot route, unknown destination '{0}'", route.DestinationKey); - return false; - } + /// + /// + /// + /// + /// + bool DoRoute(SourceRouteListItem route) + { + IRoutingSink dest = null; - if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase)) - { - dest.ReleaseRoute(); - if (dest is IHasPowerControl) - (dest as IHasPowerControl).PowerOff(); - } - else + dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSink; + + if (dest == null) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Cannot route, unknown destination '{0}'", route.DestinationKey); + return false; + } + + if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase)) + { + dest.ReleaseRoute(); + if (dest is IHasPowerControl) + (dest as IHasPowerControl).PowerOff(); + } + else + { + var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs; + if (source == null) { - var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs; - if (source == null) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey); - return false; - } - dest.ReleaseAndMakeRoute(source, route.Type); + Debug.LogMessage(LogEventLevel.Debug, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey); + return false; } - return true; + dest.ReleaseAndMakeRoute(source, route.Type); } + return true; + } - #region IHasCurrentSourceInfoChange Members + #region IHasCurrentSourceInfoChange Members - public string CurrentSourceInfoKey { get; set; } + public string CurrentSourceInfoKey { get; set; } - /// - /// The SourceListItem last run - containing names and icons - /// - public SourceListItem CurrentSourceInfo + /// + /// The SourceListItem last run - containing names and icons + /// + public SourceListItem CurrentSourceInfo + { + get { return _CurrentSourceInfo; } + set { - get { return _CurrentSourceInfo; } - set - { - if (value == _CurrentSourceInfo) return; + if (value == _CurrentSourceInfo) return; - var handler = CurrentSourceChange; - // remove from in-use tracker, if so equipped - if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking) - (_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control"); + var handler = CurrentSourceChange; + // remove from in-use tracker, if so equipped + if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking) + (_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control"); - if (handler != null) - handler(_CurrentSourceInfo, ChangeType.WillChange); + if (handler != null) + handler(_CurrentSourceInfo, ChangeType.WillChange); - _CurrentSourceInfo = value; + _CurrentSourceInfo = value; - // add to in-use tracking - if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking) - (_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control"); - if (handler != null) - handler(_CurrentSourceInfo, ChangeType.DidChange); - } + // add to in-use tracking + if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking) + (_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control"); + if (handler != null) + handler(_CurrentSourceInfo, ChangeType.DidChange); } - SourceListItem _CurrentSourceInfo; + } + SourceListItem _CurrentSourceInfo; - public event SourceInfoChangeHandler CurrentSourceChange; + public event SourceInfoChangeHandler CurrentSourceChange; - #endregion - } + #endregion +} - public class BlueJeansPcFactory : EssentialsDeviceFactory +public class BlueJeansPcFactory : EssentialsDeviceFactory +{ + public BlueJeansPcFactory() { - public BlueJeansPcFactory() - { - TypeNames = new List() { "bluejeanspc" }; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new BlueJeansPc Device"); - return new SoftCodec.BlueJeansPc(dc.Key, dc.Name); - } + TypeNames = new List() { "bluejeanspc" }; } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new BlueJeansPc Device"); + return new SoftCodec.BlueJeansPc(dc.Key, dc.Name); + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodec.cs b/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodec.cs index 84847f354..ba6e22c7a 100644 --- a/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodec.cs +++ b/src/PepperDash.Essentials.Devices.Common/SoftCodec/GenericSoftCodec.cs @@ -6,128 +6,127 @@ using System.Collections.Generic; using System.Linq; -namespace PepperDash.Essentials.Devices.Common.SoftCodec +namespace PepperDash.Essentials.Devices.Common.SoftCodec; + +public class GenericSoftCodec : EssentialsDevice, IRoutingSource, IRoutingSinkWithSwitchingWithInputPort { - public class GenericSoftCodec : EssentialsDevice, IRoutingSource, IRoutingSinkWithSwitchingWithInputPort - { - private RoutingInputPort _currentInputPort; + private RoutingInputPort _currentInputPort; - public RoutingInputPort CurrentInputPort { - get => _currentInputPort; - set - { - _currentInputPort = value; + public RoutingInputPort CurrentInputPort { + get => _currentInputPort; + set + { + _currentInputPort = value; - InputChanged?.Invoke(this, _currentInputPort); - } + InputChanged?.Invoke(this, _currentInputPort); } + } - public GenericSoftCodec(string key, string name, GenericSoftCodecProperties props) : base(key, name) - { - InputPorts = new RoutingPortCollection(); - OutputPorts = new RoutingPortCollection(); + public GenericSoftCodec(string key, string name, GenericSoftCodecProperties props) : base(key, name) + { + InputPorts = new RoutingPortCollection(); + OutputPorts = new RoutingPortCollection(); - for(var i = 1; i <= props.OutputCount; i++) - { - var outputPort = new RoutingOutputPort($"output{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this); + for(var i = 1; i <= props.OutputCount; i++) + { + var outputPort = new RoutingOutputPort($"output{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this); - OutputPorts.Add(outputPort); - } + OutputPorts.Add(outputPort); + } - for(var i = 1; i<= props.ContentInputCount; i++) - { - var inputPort = new RoutingInputPort($"contentInput{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, $"contentInput{i}", this); + for(var i = 1; i<= props.ContentInputCount; i++) + { + var inputPort = new RoutingInputPort($"contentInput{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, $"contentInput{i}", this); - InputPorts.Add(inputPort); - } + InputPorts.Add(inputPort); + } - if (!props.HasCameraInputs) - { - return; - } + if (!props.HasCameraInputs) + { + return; + } - for(var i = 1; i <=props.CameraInputCount; i++) - { - var cameraPort = new RoutingInputPort($"cameraInput{i}", eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, $"cameraInput{i}", this); + for(var i = 1; i <=props.CameraInputCount; i++) + { + var cameraPort = new RoutingInputPort($"cameraInput{i}", eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, $"cameraInput{i}", this); - InputPorts.Add(cameraPort); - } + InputPorts.Add(cameraPort); } + } - public RoutingPortCollection InputPorts { get; private set; } + public RoutingPortCollection InputPorts { get; private set; } - public RoutingPortCollection OutputPorts { get; private set; } - public string CurrentSourceInfoKey { get ; set; } - public SourceListItem CurrentSourceInfo + public RoutingPortCollection OutputPorts { get; private set; } + public string CurrentSourceInfoKey { get ; set; } + public SourceListItem CurrentSourceInfo + { + get + { + return _CurrentSourceInfo; + } + set { - get - { - return _CurrentSourceInfo; - } - set - { - if (value == _CurrentSourceInfo) return; + if (value == _CurrentSourceInfo) return; - var handler = CurrentSourceChange; + var handler = CurrentSourceChange; - if (handler != null) - handler(_CurrentSourceInfo, ChangeType.WillChange); + if (handler != null) + handler(_CurrentSourceInfo, ChangeType.WillChange); - _CurrentSourceInfo = value; + _CurrentSourceInfo = value; - if (handler != null) - handler(_CurrentSourceInfo, ChangeType.DidChange); - } + if (handler != null) + handler(_CurrentSourceInfo, ChangeType.DidChange); } + } - SourceListItem _CurrentSourceInfo; - - public event SourceInfoChangeHandler CurrentSourceChange; - public event InputChangedEventHandler InputChanged; + SourceListItem _CurrentSourceInfo; - public void ExecuteSwitch(object inputSelector) - { - var inputPort = InputPorts.FirstOrDefault(p => p.Selector == inputSelector); + public event SourceInfoChangeHandler CurrentSourceChange; + public event InputChangedEventHandler InputChanged; - if(inputPort == null) - { - Debug.LogMessage(LogEventLevel.Warning, "No input port found for selector {inputSelector}", inputSelector); - return; - } + public void ExecuteSwitch(object inputSelector) + { + var inputPort = InputPorts.FirstOrDefault(p => p.Selector == inputSelector); - CurrentInputPort = inputPort; + if(inputPort == null) + { + Debug.LogMessage(LogEventLevel.Warning, "No input port found for selector {inputSelector}", inputSelector); + return; } + + CurrentInputPort = inputPort; } +} - public class GenericSoftCodecProperties - { - [JsonProperty("hasCameraInputs")] - public bool HasCameraInputs { get; set; } +public class GenericSoftCodecProperties +{ + [JsonProperty("hasCameraInputs")] + public bool HasCameraInputs { get; set; } - [JsonProperty("cameraInputCount")] - public int CameraInputCount { get; set; } + [JsonProperty("cameraInputCount")] + public int CameraInputCount { get; set; } - [JsonProperty("contentInputCount")] - public int ContentInputCount { get; set; } + [JsonProperty("contentInputCount")] + public int ContentInputCount { get; set; } - [JsonProperty("contentOutputCount")] - public int OutputCount { get; set; } - } + [JsonProperty("contentOutputCount")] + public int OutputCount { get; set; } +} - public class GenericSoftCodecFactory: EssentialsDeviceFactory +public class GenericSoftCodecFactory: EssentialsDeviceFactory +{ + public GenericSoftCodecFactory() { - public GenericSoftCodecFactory() - { - TypeNames = new List { "genericsoftcodec" }; - } + TypeNames = new List { "genericsoftcodec" }; + } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Attempting to create new Generic SoftCodec Device"); + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Attempting to create new Generic SoftCodec Device"); - var props = dc.Properties.ToObject(); + var props = dc.Properties.ToObject(); - return new GenericSoftCodec(dc.Key, dc.Name, props); - } + return new GenericSoftCodec(dc.Key, dc.Name, props); } } diff --git a/src/PepperDash.Essentials.Devices.Common/SomeOtherWebSocketClass.cs b/src/PepperDash.Essentials.Devices.Common/SomeOtherWebSocketClass.cs new file mode 100644 index 000000000..675775a42 --- /dev/null +++ b/src/PepperDash.Essentials.Devices.Common/SomeOtherWebSocketClass.cs @@ -0,0 +1,37 @@ +using System; +using System.Net.WebSockets; +using System.Threading; +using System.Threading.Tasks; + +public class SomeOtherWebSocketClass +{ + private ClientWebSocket _webSocket; + + public SomeOtherWebSocketClass() + { + _webSocket = new ClientWebSocket(); + } + + public async Task ConnectAsync(Uri uri) + { + await _webSocket.ConnectAsync(uri, CancellationToken.None); + } + + public async Task SendAsync(string message) + { + var buffer = System.Text.Encoding.UTF8.GetBytes(message); + await _webSocket.SendAsync(new ArraySegment(buffer), WebSocketMessageType.Text, true, CancellationToken.None); + } + + public async Task ReceiveAsync() + { + var buffer = new byte[1024]; + var result = await _webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); + return System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count); + } + + public async Task CloseAsync() + { + await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); + } +} diff --git a/src/PepperDash.Essentials.Devices.Common/Sources/InRoomPc.cs b/src/PepperDash.Essentials.Devices.Common/Sources/InRoomPc.cs index 41ad7a43a..ed9068436 100644 --- a/src/PepperDash.Essentials.Devices.Common/Sources/InRoomPc.cs +++ b/src/PepperDash.Essentials.Devices.Common/Sources/InRoomPc.cs @@ -5,8 +5,8 @@ using PepperDash.Essentials.Core.Config; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common.Sources -{ +namespace PepperDash.Essentials.Devices.Common.Sources; + public class InRoomPc : EssentialsDevice, IHasFeedback, IRoutingSource, IRoutingOutputs, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking { public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } } @@ -40,37 +40,35 @@ public InRoomPc(string key, string name) /// /// Passes through the VideoStatuses list /// - public FeedbackCollection Feedbacks + public FeedbackCollection Feedbacks { get - { - var newList = new FeedbackCollection(); - newList.AddRange(this.GetVideoStatuses().ToList()); - return newList; - } + { + var newList = new FeedbackCollection(); + newList.AddRange(this.GetVideoStatuses().ToList()); + return newList; + } } #endregion - #region IUsageTracking Members + #region IUsageTracking Members - public UsageTracking UsageTracker { get; set; } + public UsageTracking UsageTracker { get; set; } - #endregion + #endregion } - public class InRoomPcFactory : EssentialsDeviceFactory +public class InRoomPcFactory : EssentialsDeviceFactory +{ + public InRoomPcFactory() { - public InRoomPcFactory() - { - TypeNames = new List() { "inroompc" }; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new InRoomPc Device"); - return new InRoomPc(dc.Key, dc.Name); - } + TypeNames = new List() { "inroompc" }; } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new InRoomPc Device"); + return new InRoomPc(dc.Key, dc.Name); + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Sources/Laptop.cs b/src/PepperDash.Essentials.Devices.Common/Sources/Laptop.cs index 38898209b..c9fa19d8a 100644 --- a/src/PepperDash.Essentials.Devices.Common/Sources/Laptop.cs +++ b/src/PepperDash.Essentials.Devices.Common/Sources/Laptop.cs @@ -5,9 +5,9 @@ using PepperDash.Essentials.Core.Config; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common.Sources -{ - public class Laptop : EssentialsDevice, IHasFeedback, IRoutingSource, IRoutingOutputs, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking +namespace PepperDash.Essentials.Devices.Common.Sources; + +public class Laptop : EssentialsDevice, IHasFeedback, IRoutingSource, IRoutingOutputs, IAttachVideoStatus, IUiDisplayInfo, IUsageTracking { public uint DisplayUiType { get { return DisplayUiConstants.TypeLaptop; } } public string IconName { get; set; } @@ -33,10 +33,10 @@ public Laptop(string key, string name) () => this.GetVideoStatuses() != VideoStatusOutputs.NoStatus); OutputPorts = new RoutingPortCollection - { - (AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, - eRoutingPortConnectionType.None, 0, this)) - }; + { + (AnyVideoOut = new RoutingOutputPort(RoutingPortNames.AnyOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, + eRoutingPortConnectionType.None, 0, this)) + }; } #region IHasFeedback Members @@ -44,36 +44,35 @@ public Laptop(string key, string name) /// /// Passes through the VideoStatuses list /// - public FeedbackCollection Feedbacks + public FeedbackCollection Feedbacks + { + get { - get - { - var newList = new FeedbackCollection(); - newList.AddRange(this.GetVideoStatuses().ToList()); - return newList; - } + var newList = new FeedbackCollection(); + newList.AddRange(this.GetVideoStatuses().ToList()); + return newList; } + } #endregion - #region IUsageTracking Members + #region IUsageTracking Members - public UsageTracking UsageTracker { get; set; } + public UsageTracking UsageTracker { get; set; } - #endregion + #endregion } - public class LaptopFactory : EssentialsDeviceFactory +public class LaptopFactory : EssentialsDeviceFactory +{ + public LaptopFactory() { - public LaptopFactory() - { - TypeNames = new List() { "laptop" }; - } + TypeNames = new List() { "laptop" }; + } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Laptop Device"); - return new Laptop(dc.Key, dc.Name); - } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Laptop Device"); + return new Laptop(dc.Key, dc.Name); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTV.cs b/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTV.cs index a00fb5a21..ddd24c054 100644 --- a/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTV.cs +++ b/src/PepperDash.Essentials.Devices.Common/Streaming/AppleTV.cs @@ -15,14 +15,14 @@ using PepperDash.Essentials.Core.Bridges; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common -{ - [Description("Wrapper class for an IR-Controlled AppleTV")] +namespace PepperDash.Essentials.Devices.Common; + +[Description("Wrapper class for an IR-Controlled AppleTV")] public class AppleTV : EssentialsBridgeableDevice, IDPad, ITransport, IUiDisplayInfo, IRoutingSource, IRoutingOutputs - { +{ public IrOutputPortController IrPort { get; private set; } - public const string StandardDriverName = "Apple_AppleTV_4th_Gen_Essentials.ir"; + public const string StandardDriverName = "Apple_AppleTV_4th_Gen_Essentials.ir"; public uint DisplayUiType { get { return DisplayUiConstants.TypeAppleTv; } } public AppleTV(string key, string name, IrOutputPortController portCont) @@ -37,20 +37,20 @@ public AppleTV(string key, string name, IrOutputPortController portCont) eRoutingPortConnectionType.DigitalAudio, null, this); OutputPorts = new RoutingPortCollection { HdmiOut, AnyAudioOut }; - PrintExpectedIrCommands(); + PrintExpectedIrCommands(); } - public void PrintExpectedIrCommands() - { - var cmds = typeof (AppleTvIrCommands).GetFields(BindingFlags.Public | BindingFlags.Static); + public void PrintExpectedIrCommands() + { + var cmds = typeof (AppleTvIrCommands).GetFields(BindingFlags.Public | BindingFlags.Static); - foreach (var value in cmds.Select(cmd => cmd.GetValue(null)).OfType()) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Expected IR Function Name: {0}", value); - } + foreach (var value in cmds.Select(cmd => cmd.GetValue(null)).OfType()) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Expected IR Function Name: {0}", value); } + } - #region IDPad Members + #region IDPad Members public void Up(bool pressRelease) { @@ -98,7 +98,7 @@ public void Play(bool pressRelease) public void Pause(bool pressRelease) { - IrPort.PressRelease(AppleTvIrCommands.PlayPause, pressRelease); + IrPort.PressRelease(AppleTvIrCommands.PlayPause, pressRelease); } /// @@ -161,61 +161,60 @@ public void Record(bool pressRelease) public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { - var joinMap = new AppleTvJoinMap(joinStart); - - var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); - - if (!string.IsNullOrEmpty(joinMapSerialized)) - joinMap = JsonConvert.DeserializeObject(joinMapSerialized); - - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } - - Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); - Debug.LogMessage(LogEventLevel.Information, "Linking to Bridge Type {0}", GetType().Name); - - trilist.SetBoolSigAction(joinMap.UpArrow.JoinNumber, Up); - trilist.SetBoolSigAction(joinMap.DnArrow.JoinNumber, Down); - trilist.SetBoolSigAction(joinMap.LeftArrow.JoinNumber, Left); - trilist.SetBoolSigAction(joinMap.RightArrow.JoinNumber, Right); - trilist.SetBoolSigAction(joinMap.Select.JoinNumber, Select); - trilist.SetBoolSigAction(joinMap.Menu.JoinNumber, Menu); - trilist.SetBoolSigAction(joinMap.PlayPause.JoinNumber, Play); - } - } + var joinMap = new AppleTvJoinMap(joinStart); - public class AppleTVFactory : EssentialsDeviceFactory - { - public AppleTVFactory() + var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); + + if (!string.IsNullOrEmpty(joinMapSerialized)) + joinMap = JsonConvert.DeserializeObject(joinMapSerialized); + + if (bridge != null) { - TypeNames = new List() { "appletv" }; + bridge.AddJoinMap(Key, joinMap); } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) + else { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new AppleTV Device"); - var irCont = IRPortHelper.GetIrOutputPortController(dc); - return new AppleTV(dc.Key, dc.Name, irCont); + Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); } + + Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); + Debug.LogMessage(LogEventLevel.Information, "Linking to Bridge Type {0}", GetType().Name); + + trilist.SetBoolSigAction(joinMap.UpArrow.JoinNumber, Up); + trilist.SetBoolSigAction(joinMap.DnArrow.JoinNumber, Down); + trilist.SetBoolSigAction(joinMap.LeftArrow.JoinNumber, Left); + trilist.SetBoolSigAction(joinMap.RightArrow.JoinNumber, Right); + trilist.SetBoolSigAction(joinMap.Select.JoinNumber, Select); + trilist.SetBoolSigAction(joinMap.Menu.JoinNumber, Menu); + trilist.SetBoolSigAction(joinMap.PlayPause.JoinNumber, Play); + } + } + +public class AppleTVFactory : EssentialsDeviceFactory +{ + public AppleTVFactory() + { + TypeNames = new List() { "appletv" }; } - public static class AppleTvIrCommands + public override EssentialsDevice BuildDevice(DeviceConfig dc) { - - public static string Up = "+"; - public static string Down = "-"; - public static string Left = IROutputStandardCommands.IROut_TRACK_MINUS; - public static string Right = IROutputStandardCommands.IROut_TRACK_PLUS; - public static string Enter = IROutputStandardCommands.IROut_ENTER; - public static string PlayPause = "PLAY/PAUSE"; - public static string Rewind = "REWIND"; - public static string Menu = "Menu"; - public static string FastForward = "FASTFORWARD"; + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new AppleTV Device"); + var irCont = IRPortHelper.GetIrOutputPortController(dc); + return new AppleTV(dc.Key, dc.Name, irCont); } +} + +public static class AppleTvIrCommands +{ + + public static string Up = "+"; + public static string Down = "-"; + public static string Left = IROutputStandardCommands.IROut_TRACK_MINUS; + public static string Right = IROutputStandardCommands.IROut_TRACK_PLUS; + public static string Enter = IROutputStandardCommands.IROut_ENTER; + public static string PlayPause = "PLAY/PAUSE"; + public static string Rewind = "REWIND"; + public static string Menu = "Menu"; + public static string FastForward = "FASTFORWARD"; } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/Streaming/Roku.cs b/src/PepperDash.Essentials.Devices.Common/Streaming/Roku.cs index 213e5835a..e607f3825 100644 --- a/src/PepperDash.Essentials.Devices.Common/Streaming/Roku.cs +++ b/src/PepperDash.Essentials.Devices.Common/Streaming/Roku.cs @@ -11,9 +11,9 @@ using PepperDash.Essentials.Core.Config; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common -{ - [Description("Wrapper class for an IR-Controlled Roku")] +namespace PepperDash.Essentials.Devices.Common; + +[Description("Wrapper class for an IR-Controlled Roku")] public class Roku2 : EssentialsDevice, IDPad, ITransport, IUiDisplayInfo, IRoutingSource, IRoutingOutputs { [Api] @@ -148,20 +148,18 @@ public void Record(bool pressRelease) } - public class Roku2Factory : EssentialsDeviceFactory +public class Roku2Factory : EssentialsDeviceFactory +{ + public Roku2Factory() { - public Roku2Factory() - { - TypeNames = new List() { "roku" }; - } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Roku Device"); - var irCont = IRPortHelper.GetIrOutputPortController(dc); - return new Roku2(dc.Key, dc.Name, irCont); - - } + TypeNames = new List() { "roku" }; } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Roku Device"); + var irCont = IRPortHelper.GetIrOutputPortController(dc); + return new Roku2(dc.Key, dc.Name, irCont); + + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/CallHistoryDataClasses.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/CallHistoryDataClasses.cs index 4fc07bd20..392f65553 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/CallHistoryDataClasses.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/CallHistoryDataClasses.cs @@ -4,94 +4,93 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Devices.Common.VideoCodec +namespace PepperDash.Essentials.Devices.Common.VideoCodec; + +public class CiscoCallHistory { - public class CiscoCallHistory + public class CallbackNumber + { + public string Value { get; set; } + } + + public class DisplayName + { + public string Value { get; set; } + } + + public class LastOccurrenceStartTime + { + public DateTime Value { get; set; } + } + + public class LastOccurrenceDaysAgo + { + public string Value { get; set; } + } + + public class LastOccurrenceHistoryId + { + public string Value { get; set; } + } + + public class OccurrenceType + { + public string Value { get; set; } + } + + public class IsAcknowledged + { + public string Value { get; set; } + } + + public class OccurrenceCount + { + public string Value { get; set; } + } + + public class Entry + { + public string id { get; set; } + public CallbackNumber CallbackNumber { get; set; } + public DisplayName DisplayName { get; set; } + public LastOccurrenceStartTime LastOccurrenceStartTime { get; set; } + public LastOccurrenceDaysAgo LastOccurrenceDaysAgo { get; set; } + public LastOccurrenceHistoryId LastOccurrenceHistoryId { get; set; } + public OccurrenceType OccurrenceType { get; set; } + public IsAcknowledged IsAcknowledged { get; set; } + public OccurrenceCount OccurrenceCount { get; set; } + } + + public class Offset + { + public string Value { get; set; } + } + + public class Limit + { + public string Value { get; set; } + } + + public class ResultInfo + { + public Offset Offset { get; set; } + public Limit Limit { get; set; } + } + + public class CallHistoryRecentsResult + { + public string status { get; set; } + public List Entry { get; set; } + public ResultInfo ResultInfo { get; set; } + } + + public class CommandResponse + { + public CallHistoryRecentsResult CallHistoryRecentsResult { get; set; } + } + + public class RootObject { - public class CallbackNumber - { - public string Value { get; set; } - } - - public class DisplayName - { - public string Value { get; set; } - } - - public class LastOccurrenceStartTime - { - public DateTime Value { get; set; } - } - - public class LastOccurrenceDaysAgo - { - public string Value { get; set; } - } - - public class LastOccurrenceHistoryId - { - public string Value { get; set; } - } - - public class OccurrenceType - { - public string Value { get; set; } - } - - public class IsAcknowledged - { - public string Value { get; set; } - } - - public class OccurrenceCount - { - public string Value { get; set; } - } - - public class Entry - { - public string id { get; set; } - public CallbackNumber CallbackNumber { get; set; } - public DisplayName DisplayName { get; set; } - public LastOccurrenceStartTime LastOccurrenceStartTime { get; set; } - public LastOccurrenceDaysAgo LastOccurrenceDaysAgo { get; set; } - public LastOccurrenceHistoryId LastOccurrenceHistoryId { get; set; } - public OccurrenceType OccurrenceType { get; set; } - public IsAcknowledged IsAcknowledged { get; set; } - public OccurrenceCount OccurrenceCount { get; set; } - } - - public class Offset - { - public string Value { get; set; } - } - - public class Limit - { - public string Value { get; set; } - } - - public class ResultInfo - { - public Offset Offset { get; set; } - public Limit Limit { get; set; } - } - - public class CallHistoryRecentsResult - { - public string status { get; set; } - public List Entry { get; set; } - public ResultInfo ResultInfo { get; set; } - } - - public class CommandResponse - { - public CallHistoryRecentsResult CallHistoryRecentsResult { get; set; } - } - - public class RootObject - { - public CommandResponse CommandResponse { get; set; } - } + public CommandResponse CommandResponse { get; set; } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/RoomPresets.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/RoomPresets.cs index a6531a40f..c66f9fce6 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/RoomPresets.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/RoomPresets.cs @@ -5,84 +5,83 @@ using PepperDash.Core; using PepperDash.Essentials.Core.Presets; -namespace PepperDash.Essentials.Devices.Common.VideoCodec +namespace PepperDash.Essentials.Devices.Common.VideoCodec; + +/// +/// Interface for camera presets +/// +public interface IHasCodecRoomPresets { /// - /// Interface for camera presets + /// Event that is raised when the list of room presets has changed. /// - public interface IHasCodecRoomPresets - { - /// - /// Event that is raised when the list of room presets has changed. - /// - event EventHandler CodecRoomPresetsListHasChanged; + event EventHandler CodecRoomPresetsListHasChanged; - /// - /// List of near end presets that can be recalled. - /// - List NearEndPresets { get; } + /// + /// List of near end presets that can be recalled. + /// + List NearEndPresets { get; } - /// - /// List of far end presets that can be recalled. - /// - List FarEndRoomPresets { get; } + /// + /// List of far end presets that can be recalled. + /// + List FarEndRoomPresets { get; } - /// - /// Selects a near end preset by its ID. - /// - /// - void CodecRoomPresetSelect(int preset); + /// + /// Selects a near end preset by its ID. + /// + /// + void CodecRoomPresetSelect(int preset); - /// - /// Stores a near end preset with the given ID and description. - /// - /// - /// - void CodecRoomPresetStore(int preset, string description); + /// + /// Stores a near end preset with the given ID and description. + /// + /// + /// + void CodecRoomPresetStore(int preset, string description); - /// - /// Selects a far end preset by its ID. This is typically used to recall a preset that has been defined on the far end codec. - /// - /// - void SelectFarEndPreset(int preset); - } + /// + /// Selects a far end preset by its ID. This is typically used to recall a preset that has been defined on the far end codec. + /// + /// + void SelectFarEndPreset(int preset); +} +/// +/// Static class for converting non-generic RoomPresets to generic CameraPresets. +/// +public static class RoomPresets +{ /// - /// Static class for converting non-generic RoomPresets to generic CameraPresets. + /// Converts non-generic RoomPresets to generic CameraPresets /// - public static class RoomPresets + /// + /// + public static List GetGenericPresets(this List presets) where TSource : ConvertiblePreset where TDestination : PresetBase { - /// - /// Converts non-generic RoomPresets to generic CameraPresets - /// - /// - /// - public static List GetGenericPresets(this List presets) where TSource : ConvertiblePreset where TDestination : PresetBase - { - return - presets.Select(preset => preset.ConvertCodecPreset()) - .Where(newPreset => newPreset != null) - .Cast() - .ToList(); - } + return + presets.Select(preset => preset.ConvertCodecPreset()) + .Where(newPreset => newPreset != null) + .Cast() + .ToList(); } +} +/// +/// Represents a room preset on a video codec. Typically stores camera position(s) and video routing. Can be recalled by Far End if enabled. +/// +public class CodecRoomPreset : PresetBase +{ /// - /// Represents a room preset on a video codec. Typically stores camera position(s) and video routing. Can be recalled by Far End if enabled. + /// /// - public class CodecRoomPreset : PresetBase + /// + /// + /// + /// + public CodecRoomPreset(int id, string description, bool def, bool isDef) + : base(id, description, def, isDef) { - /// - /// - /// - /// - /// - /// - /// - public CodecRoomPreset(int id, string description, bool def, bool isDef) - : base(id, description, def, isDef) - { - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eCommandType.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eCommandType.cs index b68f280db..d33ec5c53 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eCommandType.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eCommandType.cs @@ -1,4 +1,3 @@ -namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco -{ - enum eCommandType { SessionStart, SessionEnd, Command, GetStatus, GetConfiguration }; -} \ No newline at end of file +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco; + +enum eCommandType { SessionStart, SessionEnd, Command, GetStatus, GetConfiguration }; \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eExternalSourceMode.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eExternalSourceMode.cs index 1f96f5e1d..5cff4cd6e 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eExternalSourceMode.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eExternalSourceMode.cs @@ -1,4 +1,3 @@ -namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco -{ - public enum eExternalSourceMode {Ready, NotReady, Hidden, Error} -} \ No newline at end of file +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco; + +public enum eExternalSourceMode {Ready, NotReady, Hidden, Error} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eExternalSourceType.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eExternalSourceType.cs index 66ebe3900..4bce7e273 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eExternalSourceType.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/CiscoCodec/eExternalSourceType.cs @@ -1,4 +1,3 @@ -namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco -{ - public enum eExternalSourceType {camera, desktop, document_camera, mediaplayer, PC, whiteboard, other} -} \ No newline at end of file +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco; + +public enum eExternalSourceType {camera, desktop, document_camera, mediaplayer, PC, whiteboard, other} \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ConvertiblePreset.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/ConvertiblePreset.cs index 4c01d94e5..90cdcb71e 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/ConvertiblePreset.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/ConvertiblePreset.cs @@ -1,9 +1,8 @@ using PepperDash.Essentials.Core.Presets; -namespace PepperDash.Essentials.Devices.Common.VideoCodec +namespace PepperDash.Essentials.Devices.Common.VideoCodec; + +public abstract class ConvertiblePreset { - public abstract class ConvertiblePreset - { - public abstract PresetBase ConvertCodecPreset(); - } + public abstract PresetBase ConvertCodecPreset(); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecLayouts.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecLayouts.cs index 98a8e4f43..42f4b1357 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecLayouts.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecLayouts.cs @@ -10,17 +10,16 @@ using Newtonsoft.Json; -namespace PepperDash.Essentials.Devices.Common.VideoCodec +namespace PepperDash.Essentials.Devices.Common.VideoCodec; + +/// +/// Defines the required elements for layout control +/// +public interface IHasCodecLayouts { - /// - /// Defines the required elements for layout control - /// - public interface IHasCodecLayouts - { - StringFeedback LocalLayoutFeedback { get; } + StringFeedback LocalLayoutFeedback { get; } - void LocalLayoutToggle(); + void LocalLayoutToggle(); void LocalLayoutToggleSingleProminent(); void MinMaxLayoutToggle(); - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecSelfview.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecSelfview.cs index 3b079b7da..36116fb2f 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecSelfview.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasCodecSelfview.cs @@ -6,21 +6,20 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Devices.Common.VideoCodec +namespace PepperDash.Essentials.Devices.Common.VideoCodec; + +/// +/// Defines the requred elements for selfview control +/// +public interface IHasCodecSelfView { - /// - /// Defines the requred elements for selfview control - /// - public interface IHasCodecSelfView - { - BoolFeedback SelfviewIsOnFeedback { get; } + BoolFeedback SelfviewIsOnFeedback { get; } - bool ShowSelfViewByDefault { get; } + bool ShowSelfViewByDefault { get; } - void SelfViewModeOn(); + void SelfViewModeOn(); - void SelfViewModeOff(); + void SelfViewModeOff(); - void SelfViewModeToggle(); - } + void SelfViewModeToggle(); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingInfo.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingInfo.cs index bde88b610..dfc558183 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingInfo.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingInfo.cs @@ -8,72 +8,71 @@ using Newtonsoft.Json; -namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; + +/// +/// Describes a device that provides meeting information (like a ZoomRoom) +/// +public interface IHasMeetingInfo { - /// - /// Describes a device that provides meeting information (like a ZoomRoom) - /// - public interface IHasMeetingInfo - { - event EventHandler MeetingInfoChanged; + event EventHandler MeetingInfoChanged; - MeetingInfo MeetingInfo { get; } - } + MeetingInfo MeetingInfo { get; } +} - /// - /// Represents the information about a meeting in progress - /// Currently used for Zoom meetings - /// - public class MeetingInfo - { - [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] - public string Id { get; private set; } - [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] - public string Name { get; private set; } - [JsonProperty("host", NullValueHandling = NullValueHandling.Ignore)] - public string Host { get; private set; } - [JsonProperty("password", NullValueHandling = NullValueHandling.Ignore)] - public string Password { get; private set; } - [JsonProperty("shareStatus", NullValueHandling = NullValueHandling.Ignore)] - public string ShareStatus { get; private set; } - [JsonProperty("isHost", NullValueHandling = NullValueHandling.Ignore)] - public Boolean IsHost { get; private set; } - [JsonProperty("isSharingMeeting", NullValueHandling = NullValueHandling.Ignore)] - public Boolean IsSharingMeeting { get; private set; } - [JsonProperty("waitingForHost", NullValueHandling = NullValueHandling.Ignore)] - public Boolean WaitingForHost { get; private set; } - [JsonProperty("isLocked", NullValueHandling = NullValueHandling.Ignore)] - public Boolean IsLocked { get; private set; } - [JsonProperty("isRecording", NullValueHandling = NullValueHandling.Ignore)] - public Boolean IsRecording { get; private set; } - [JsonProperty("canRecord", NullValueHandling = NullValueHandling.Ignore)] - public Boolean CanRecord { get; private set; } +/// +/// Represents the information about a meeting in progress +/// Currently used for Zoom meetings +/// +public class MeetingInfo +{ + [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] + public string Id { get; private set; } + [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] + public string Name { get; private set; } + [JsonProperty("host", NullValueHandling = NullValueHandling.Ignore)] + public string Host { get; private set; } + [JsonProperty("password", NullValueHandling = NullValueHandling.Ignore)] + public string Password { get; private set; } + [JsonProperty("shareStatus", NullValueHandling = NullValueHandling.Ignore)] + public string ShareStatus { get; private set; } + [JsonProperty("isHost", NullValueHandling = NullValueHandling.Ignore)] + public Boolean IsHost { get; private set; } + [JsonProperty("isSharingMeeting", NullValueHandling = NullValueHandling.Ignore)] + public Boolean IsSharingMeeting { get; private set; } + [JsonProperty("waitingForHost", NullValueHandling = NullValueHandling.Ignore)] + public Boolean WaitingForHost { get; private set; } + [JsonProperty("isLocked", NullValueHandling = NullValueHandling.Ignore)] + public Boolean IsLocked { get; private set; } + [JsonProperty("isRecording", NullValueHandling = NullValueHandling.Ignore)] + public Boolean IsRecording { get; private set; } + [JsonProperty("canRecord", NullValueHandling = NullValueHandling.Ignore)] + public Boolean CanRecord { get; private set; } - public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked, bool isRecording, bool canRecord) - { - Id = id; - Name = name; - Host = host; - Password = password; - ShareStatus = shareStatus; - IsHost = isHost; - IsSharingMeeting = isSharingMeeting; - WaitingForHost = waitingForHost; - IsLocked = isLocked; - IsRecording = isRecording; - CanRecord = CanRecord; - } - } - - public class MeetingInfoEventArgs : EventArgs + public MeetingInfo(string id, string name, string host, string password, string shareStatus, bool isHost, bool isSharingMeeting, bool waitingForHost, bool isLocked, bool isRecording, bool canRecord) { - public MeetingInfo Info { get; private set; } + Id = id; + Name = name; + Host = host; + Password = password; + ShareStatus = shareStatus; + IsHost = isHost; + IsSharingMeeting = isSharingMeeting; + WaitingForHost = waitingForHost; + IsLocked = isLocked; + IsRecording = isRecording; + CanRecord = CanRecord; + } +} - public MeetingInfoEventArgs(MeetingInfo info) - { - Info = info; - } +public class MeetingInfoEventArgs : EventArgs +{ + public MeetingInfo Info { get; private set; } + public MeetingInfoEventArgs(MeetingInfo info) + { + Info = info; } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingLock.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingLock.cs index 97fcb7251..abdd69863 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingLock.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingLock.cs @@ -5,14 +5,13 @@ using Crestron.SimplSharp; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; + +public interface IHasMeetingLock { - public interface IHasMeetingLock - { - BoolFeedback MeetingIsLockedFeedback { get; } + BoolFeedback MeetingIsLockedFeedback { get; } - void LockMeeting(); - void UnLockMeeting(); - void ToggleMeetingLock(); - } + void LockMeeting(); + void UnLockMeeting(); + void ToggleMeetingLock(); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingRecording.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingRecording.cs index b05362c3e..daa3a4a43 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingRecording.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasMeetingRecording.cs @@ -5,25 +5,24 @@ using Crestron.SimplSharp; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; + +public interface IHasMeetingRecording { - public interface IHasMeetingRecording - { - BoolFeedback MeetingIsRecordingFeedback { get; } + BoolFeedback MeetingIsRecordingFeedback { get; } - void StartRecording(); - void StopRecording(); - void ToggleRecording(); - } + void StartRecording(); + void StopRecording(); + void ToggleRecording(); +} - public interface IHasMeetingRecordingWithPrompt : IHasMeetingRecording - { - BoolFeedback RecordConsentPromptIsVisible { get; } +public interface IHasMeetingRecordingWithPrompt : IHasMeetingRecording +{ + BoolFeedback RecordConsentPromptIsVisible { get; } - /// - /// Used to agree or disagree to the meeting being recorded when prompted - /// - /// - void RecordingPromptAcknowledgement(bool agree); - } + /// + /// Used to agree or disagree to the meeting being recorded when prompted + /// + /// + void RecordingPromptAcknowledgement(bool agree); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipants.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipants.cs index 98c94bdcf..8b8d6d25d 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipants.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasParticipants.cs @@ -4,8 +4,8 @@ using PepperDash.Core; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces -{ +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; + /// /// Describes a device that has call participants /// @@ -13,23 +13,23 @@ public interface IHasParticipants { CodecParticipants Participants { get; } - /// - /// Removes the participant from the meeting - /// - /// - void RemoveParticipant(int userId); - - /// - /// Sets the participant as the new host - /// - /// - void SetParticipantAsHost(int userId); - - /// - /// Admits a participant from the waiting room - /// - /// - void AdmitParticipantFromWaitingRoom(int userId); + /// + /// Removes the participant from the meeting + /// + /// + void RemoveParticipant(int userId); + + /// + /// Sets the participant as the new host + /// + /// + void SetParticipantAsHost(int userId); + + /// + /// Admits a participant from the waiting room + /// + /// + void AdmitParticipantFromWaitingRoom(int userId); } /// @@ -47,10 +47,10 @@ public interface IHasParticipantVideoMute : IHasParticipants /// public interface IHasParticipantAudioMute : IHasParticipantVideoMute { - /// - /// Mute audio of all participants - /// - void MuteAudioForAllParticipants(); + /// + /// Mute audio of all participants + /// + void MuteAudioForAllParticipants(); void MuteAudioForParticipant(int userId); void UnmuteAudioForParticipant(int userId); @@ -84,13 +84,13 @@ public List CurrentParticipants } } - public Participant Host + public Participant Host + { + get { - get - { - return _currentParticipants.FirstOrDefault(p => p.IsHost); - } + return _currentParticipants.FirstOrDefault(p => p.IsHost); } + } public event EventHandler ParticipantsListHasChanged; @@ -116,7 +116,7 @@ public class Participant { public int UserId { get; set; } public bool IsHost { get; set; } - public bool IsMyself { get; set; } + public bool IsMyself { get; set; } public string Name { get; set; } public bool CanMuteVideo { get; set; } public bool CanUnmuteVideo { get; set; } @@ -131,5 +131,4 @@ public Participant() // Initialize to -1 (no screen) ScreenIndexIsPinnedToFb = -1; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs index a620af1e2..0c8b523ba 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasPresentationOnlyMeeting.cs @@ -1,18 +1,17 @@ -namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; + +public interface IHasPresentationOnlyMeeting { - public interface IHasPresentationOnlyMeeting - { - void StartSharingOnlyMeeting(); - void StartSharingOnlyMeeting(eSharingMeetingMode displayMode); - void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, uint duration); - void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, uint duration, string password); - void StartNormalMeetingFromSharingOnlyMeeting(); - } + void StartSharingOnlyMeeting(); + void StartSharingOnlyMeeting(eSharingMeetingMode displayMode); + void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, uint duration); + void StartSharingOnlyMeeting(eSharingMeetingMode displayMode, uint duration, string password); + void StartNormalMeetingFromSharingOnlyMeeting(); +} - public enum eSharingMeetingMode - { - None, - Laptop, - Ios, - } +public enum eSharingMeetingMode +{ + None, + Laptop, + Ios, } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs index d0ba25fde..3e88917a8 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasSelfviewPosition.cs @@ -1,14 +1,13 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Devices.Common.VideoCodec; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + +public interface IHasSelfviewPosition { - public interface IHasSelfviewPosition - { - StringFeedback SelfviewPipPositionFeedback { get; } + StringFeedback SelfviewPipPositionFeedback { get; } - void SelfviewPipPositionSet(CodecCommandWithLabel position); + void SelfviewPipPositionSet(CodecCommandWithLabel position); - void SelfviewPipPositionToggle(); - } + void SelfviewPipPositionToggle(); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasSelfviewSize.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasSelfviewSize.cs index 4103fa0ec..b00bc0b9d 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasSelfviewSize.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasSelfviewSize.cs @@ -1,7 +1,7 @@ using PepperDash.Essentials.Devices.Common.VideoCodec; -namespace PepperDash.Essentials.Core.DeviceTypeInterfaces -{ +namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; + public interface IHasSelfviewSize { StringFeedback SelfviewPipSizeFeedback { get; } @@ -9,5 +9,4 @@ public interface IHasSelfviewSize void SelfviewPipSizeSet(CodecCommandWithLabel size); void SelfviewPipSizeToggle(); - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasStandbyMode.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasStandbyMode.cs index cc9dcd3dc..22bdba574 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasStandbyMode.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasStandbyMode.cs @@ -6,29 +6,28 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Devices.Common.VideoCodec +namespace PepperDash.Essentials.Devices.Common.VideoCodec; + +/// +/// Describes a device that has Standby Mode capability +/// +public interface IHasStandbyMode { - /// - /// Describes a device that has Standby Mode capability - /// - public interface IHasStandbyMode - { - BoolFeedback StandbyIsOnFeedback { get; } + BoolFeedback StandbyIsOnFeedback { get; } - void StandbyActivate(); + void StandbyActivate(); - void StandbyDeactivate(); - } + void StandbyDeactivate(); +} - /// - /// Describes a device that has Half Waek Mode capability - /// - public interface IHasHalfWakeMode : IHasStandbyMode - { - BoolFeedback HalfWakeModeIsOnFeedback { get; } +/// +/// Describes a device that has Half Waek Mode capability +/// +public interface IHasHalfWakeMode : IHasStandbyMode +{ + BoolFeedback HalfWakeModeIsOnFeedback { get; } - BoolFeedback EnteringStandbyModeFeedback { get; } + BoolFeedback EnteringStandbyModeFeedback { get; } - void HalfwakeActivate(); - } + void HalfwakeActivate(); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasStartMeeting.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasStartMeeting.cs index 6af59534e..ee160cb45 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasStartMeeting.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasStartMeeting.cs @@ -4,27 +4,26 @@ using System.Text; using Crestron.SimplSharp; -namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces +namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; + +/// +/// Describes the ability to start an ad-hoc meeting +/// +public interface IHasStartMeeting { /// - /// Describes the ability to start an ad-hoc meeting + /// The default meeting duration in minutes /// - public interface IHasStartMeeting - { - /// - /// The default meeting duration in minutes - /// - uint DefaultMeetingDurationMin { get; } + uint DefaultMeetingDurationMin { get; } - /// - /// Start an ad-hoc meeting for the specified duration - /// - /// - void StartMeeting(uint duration); + /// + /// Start an ad-hoc meeting for the specified duration + /// + /// + void StartMeeting(uint duration); - /// - /// Leaves a meeting without ending it - /// - void LeaveMeeting(); - } + /// + /// Leaves a meeting without ending it + /// + void LeaveMeeting(); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasVideoCodec.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasVideoCodec.cs index d8494334d..11817a940 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasVideoCodec.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IHasVideoCodec.cs @@ -6,8 +6,8 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Devices.Common.VideoCodec -{ +namespace PepperDash.Essentials.Devices.Common.VideoCodec; + /// /// For rooms that have video codec /// @@ -15,10 +15,10 @@ public interface IHasVideoCodec:IHasInCallFeedback,IPrivacy { VideoCodecBase VideoCodec { get; } - ///// - ///// Make this more specific - ///// - //List ActiveCalls { get; } + ///// + ///// Make this more specific + ///// + //List ActiveCalls { get; } /// /// States: 0 for on hook, 1 for video, 2 for audio, 3 for telekenesis @@ -30,5 +30,4 @@ public interface IHasVideoCodec:IHasInCallFeedback,IPrivacy /// BoolFeedback IsSharingFeedback { get; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IJoinCalls.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IJoinCalls.cs index b84db1e9c..6b5fdecb9 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IJoinCalls.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/IJoinCalls.cs @@ -6,11 +6,10 @@ using PepperDash.Essentials.Devices.Common.Codec; -namespace PepperDash.Essentials.Devices.Common.VideoCodec +namespace PepperDash.Essentials.Devices.Common.VideoCodec; + +public interface IJoinCalls { - public interface IJoinCalls - { - void JoinCall(CodecActiveCallItem activeCall); - void JoinAllCalls(); - } + void JoinCall(CodecActiveCallItem activeCall); + void JoinAllCalls(); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/iVideoCodecInfo.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/iVideoCodecInfo.cs index 8f004086e..39cbb46f3 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/iVideoCodecInfo.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/Interfaces/iVideoCodecInfo.cs @@ -8,34 +8,33 @@ using Newtonsoft.Json; -namespace PepperDash.Essentials.Devices.Common.Codec +namespace PepperDash.Essentials.Devices.Common.Codec; + +/// +/// Implements a common set of data about a codec +/// +public interface iVideoCodecInfo { - /// - /// Implements a common set of data about a codec - /// - public interface iVideoCodecInfo - { - VideoCodecInfo CodecInfo { get; } - } + VideoCodecInfo CodecInfo { get; } +} - /// - /// Stores general information about a codec - /// - public abstract class VideoCodecInfo - { - [JsonProperty("multiSiteOptionIsEnabled", NullValueHandling = NullValueHandling.Ignore)] - public abstract bool MultiSiteOptionIsEnabled { get; } - [JsonProperty("ipAddress", NullValueHandling = NullValueHandling.Ignore)] - public abstract string IpAddress { get; } - [JsonProperty("sipPhoneNumber", NullValueHandling = NullValueHandling.Ignore)] - public abstract string SipPhoneNumber { get; } - [JsonProperty("e164Alias", NullValueHandling = NullValueHandling.Ignore)] - public abstract string E164Alias { get; } - [JsonProperty("h323Id", NullValueHandling = NullValueHandling.Ignore)] - public abstract string H323Id { get; } - [JsonProperty("sipUri", NullValueHandling = NullValueHandling.Ignore)] - public abstract string SipUri { get; } - [JsonProperty("autoAnswerEnabled", NullValueHandling = NullValueHandling.Ignore)] - public abstract bool AutoAnswerEnabled { get; } - } +/// +/// Stores general information about a codec +/// +public abstract class VideoCodecInfo +{ + [JsonProperty("multiSiteOptionIsEnabled", NullValueHandling = NullValueHandling.Ignore)] + public abstract bool MultiSiteOptionIsEnabled { get; } + [JsonProperty("ipAddress", NullValueHandling = NullValueHandling.Ignore)] + public abstract string IpAddress { get; } + [JsonProperty("sipPhoneNumber", NullValueHandling = NullValueHandling.Ignore)] + public abstract string SipPhoneNumber { get; } + [JsonProperty("e164Alias", NullValueHandling = NullValueHandling.Ignore)] + public abstract string E164Alias { get; } + [JsonProperty("h323Id", NullValueHandling = NullValueHandling.Ignore)] + public abstract string H323Id { get; } + [JsonProperty("sipUri", NullValueHandling = NullValueHandling.Ignore)] + public abstract string SipUri { get; } + [JsonProperty("autoAnswerEnabled", NullValueHandling = NullValueHandling.Ignore)] + public abstract bool AutoAnswerEnabled { get; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockCodecDirectory.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockCodecDirectory.cs index 41b706614..32eded616 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockCodecDirectory.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockCodecDirectory.cs @@ -9,411 +9,410 @@ using PepperDash.Essentials.Devices.Common.Codec; -namespace PepperDash.Essentials.Devices.Common.VideoCodec +namespace PepperDash.Essentials.Devices.Common.VideoCodec; + +public static class MockVideoCodecDirectory { - public static class MockVideoCodecDirectory + public enum eFolderId { - public enum eFolderId - { - UnitedStates, - Canada, - NewYork, - Boston, - SanFrancisco, - Denver, - Austin, - Calgary - } + UnitedStates, + Canada, + NewYork, + Boston, + SanFrancisco, + Denver, + Austin, + Calgary + } - /// - /// Aggregates the directory items for all directories into a single directory for searching purposes - /// - public static CodecDirectory CompleteDirectory + /// + /// Aggregates the directory items for all directories into a single directory for searching purposes + /// + public static CodecDirectory CompleteDirectory + { + get { - get - { - var completeDirectory = new CodecDirectory(); - - completeDirectory.AddContactsToDirectory(DirectoryRoot.CurrentDirectoryResults); - completeDirectory.AddContactsToDirectory(UnitedStatesFolderContents.CurrentDirectoryResults); - completeDirectory.AddContactsToDirectory(CanadaFolderContents.CurrentDirectoryResults); - completeDirectory.AddContactsToDirectory(NewYorkFolderContents.CurrentDirectoryResults); - completeDirectory.AddContactsToDirectory(BostonFolderContents.CurrentDirectoryResults); - completeDirectory.AddContactsToDirectory(DenverFolderContents.CurrentDirectoryResults); - completeDirectory.AddContactsToDirectory(AustinFolderContents.CurrentDirectoryResults); - completeDirectory.AddContactsToDirectory(CalgaryFolderContents.CurrentDirectoryResults); - - return completeDirectory; - } + var completeDirectory = new CodecDirectory(); + + completeDirectory.AddContactsToDirectory(DirectoryRoot.CurrentDirectoryResults); + completeDirectory.AddContactsToDirectory(UnitedStatesFolderContents.CurrentDirectoryResults); + completeDirectory.AddContactsToDirectory(CanadaFolderContents.CurrentDirectoryResults); + completeDirectory.AddContactsToDirectory(NewYorkFolderContents.CurrentDirectoryResults); + completeDirectory.AddContactsToDirectory(BostonFolderContents.CurrentDirectoryResults); + completeDirectory.AddContactsToDirectory(DenverFolderContents.CurrentDirectoryResults); + completeDirectory.AddContactsToDirectory(AustinFolderContents.CurrentDirectoryResults); + completeDirectory.AddContactsToDirectory(CalgaryFolderContents.CurrentDirectoryResults); + + return completeDirectory; } + } - public static CodecDirectory DirectoryRoot + public static CodecDirectory DirectoryRoot + { + get { - get - { - var directory = new CodecDirectory(); - - directory.AddFoldersToDirectory - ( - new List() - { - new DirectoryFolder() - { - FolderId = eFolderId.UnitedStates.ToString(), - Name = "United States", - ParentFolderId = "", - Contacts = null - }, - new DirectoryFolder() - { - FolderId = eFolderId.Canada.ToString(), - Name = "Canada", - ParentFolderId = "", - Contacts = null - } + var directory = new CodecDirectory(); + + directory.AddFoldersToDirectory + ( + new List() + { + new DirectoryFolder() + { + FolderId = eFolderId.UnitedStates.ToString(), + Name = "United States", + ParentFolderId = "", + Contacts = null + }, + new DirectoryFolder() + { + FolderId = eFolderId.Canada.ToString(), + Name = "Canada", + ParentFolderId = "", + Contacts = null } - ); - - directory.AddContactsToDirectory - ( - new List() + } + ); + + directory.AddContactsToDirectory + ( + new List() + { + new DirectoryContact() { - new DirectoryContact() + Name = "Corporate Bridge", + ContactMethods = new List() { - Name = "Corporate Bridge", - ContactMethods = new List() + new ContactMethod() { - new ContactMethod() - { - ContactMethodId = "c_1", - Number = "site.corp.com", - Device = eContactMethodDevice.Video, - CallType = eContactMethodCallType.Video - } + ContactMethodId = "c_1", + Number = "site.corp.com", + Device = eContactMethodDevice.Video, + CallType = eContactMethodCallType.Video } } } - ); - - return directory; - } - } + } + ); + + return directory; + } + } - public static CodecDirectory UnitedStatesFolderContents + public static CodecDirectory UnitedStatesFolderContents + { + get { - get - { - var directory = new CodecDirectory(); - - directory.ResultsFolderId = eFolderId.UnitedStates.ToString(); - directory.AddFoldersToDirectory - ( - new List() - { - new DirectoryFolder() - { - FolderId = eFolderId.NewYork.ToString(), - Name = "New York", - ParentFolderId = eFolderId.UnitedStates.ToString(), - Contacts = null - }, - new DirectoryFolder() - { - FolderId = eFolderId.Boston.ToString(), - Name = "Boston", - ParentFolderId = eFolderId.UnitedStates.ToString(), - Contacts = null - }, - new DirectoryFolder() - { - FolderId = eFolderId.SanFrancisco.ToString(), - Name = "San Francisco", - ParentFolderId = eFolderId.UnitedStates.ToString(), - Contacts = null - }, - new DirectoryFolder() - { - FolderId = eFolderId.Denver.ToString(), - Name = "Denver", - ParentFolderId = eFolderId.UnitedStates.ToString(), - Contacts = null - }, - new DirectoryFolder() - { - FolderId = eFolderId.Austin.ToString(), - Name = "Austin", - ParentFolderId = eFolderId.UnitedStates.ToString(), - Contacts = null - } + var directory = new CodecDirectory(); + + directory.ResultsFolderId = eFolderId.UnitedStates.ToString(); + directory.AddFoldersToDirectory + ( + new List() + { + new DirectoryFolder() + { + FolderId = eFolderId.NewYork.ToString(), + Name = "New York", + ParentFolderId = eFolderId.UnitedStates.ToString(), + Contacts = null + }, + new DirectoryFolder() + { + FolderId = eFolderId.Boston.ToString(), + Name = "Boston", + ParentFolderId = eFolderId.UnitedStates.ToString(), + Contacts = null + }, + new DirectoryFolder() + { + FolderId = eFolderId.SanFrancisco.ToString(), + Name = "San Francisco", + ParentFolderId = eFolderId.UnitedStates.ToString(), + Contacts = null + }, + new DirectoryFolder() + { + FolderId = eFolderId.Denver.ToString(), + Name = "Denver", + ParentFolderId = eFolderId.UnitedStates.ToString(), + Contacts = null + }, + new DirectoryFolder() + { + FolderId = eFolderId.Austin.ToString(), + Name = "Austin", + ParentFolderId = eFolderId.UnitedStates.ToString(), + Contacts = null } - ); + } + ); - return directory; - } + return directory; } + } - public static CodecDirectory NewYorkFolderContents + public static CodecDirectory NewYorkFolderContents + { + get { - get - { - var directory = new CodecDirectory(); - - directory.ResultsFolderId = eFolderId.NewYork.ToString(); - directory.AddContactsToDirectory - ( - new List() + var directory = new CodecDirectory(); + + directory.ResultsFolderId = eFolderId.NewYork.ToString(); + directory.AddContactsToDirectory + ( + new List() + { + new DirectoryContact() { - new DirectoryContact() + ContactId = "nyc_1", + Name = "Meeting Room", + Title = @"", + ContactMethods = new List() { - ContactId = "nyc_1", - Name = "Meeting Room", - Title = @"", - ContactMethods = new List() + new ContactMethod() { - new ContactMethod() - { - ContactMethodId = "cid_1", - Number = "nycmeetingroom.pepperdash.com", - Device = eContactMethodDevice.Video, - CallType = eContactMethodCallType.Video - } + ContactMethodId = "cid_1", + Number = "nycmeetingroom.pepperdash.com", + Device = eContactMethodDevice.Video, + CallType = eContactMethodCallType.Video } - }, - new DirectoryContact() + } + }, + new DirectoryContact() + { + ContactId = "nyc_2", + Name = "Sumanth Rayancha", + Title = @"CTO", + ContactMethods = new List() { - ContactId = "nyc_2", - Name = "Sumanth Rayancha", - Title = @"CTO", - ContactMethods = new List() + new ContactMethod() { - new ContactMethod() - { - ContactMethodId = "cid_1", - Number = "srayancha.pepperdash.com", - Device = eContactMethodDevice.Video, - CallType = eContactMethodCallType.Video - } + ContactMethodId = "cid_1", + Number = "srayancha.pepperdash.com", + Device = eContactMethodDevice.Video, + CallType = eContactMethodCallType.Video } - }, - new DirectoryContact() + } + }, + new DirectoryContact() + { + ContactId = "nyc_3", + Name = "Justin Gordon", + Title = @"Software Developer", + ContactMethods = new List() { - ContactId = "nyc_3", - Name = "Justin Gordon", - Title = @"Software Developer", - ContactMethods = new List() + new ContactMethod() { - new ContactMethod() - { - ContactMethodId = "cid_1", - Number = "jgordon.pepperdash.com", - Device = eContactMethodDevice.Video, - CallType = eContactMethodCallType.Video - } + ContactMethodId = "cid_1", + Number = "jgordon.pepperdash.com", + Device = eContactMethodDevice.Video, + CallType = eContactMethodCallType.Video } } } - ); + } + ); - return directory; - } + return directory; } + } - public static CodecDirectory BostonFolderContents + public static CodecDirectory BostonFolderContents + { + get { - get - { - var directory = new CodecDirectory(); - - directory.ResultsFolderId = eFolderId.Boston.ToString(); - directory.AddContactsToDirectory - ( - new List() + var directory = new CodecDirectory(); + + directory.ResultsFolderId = eFolderId.Boston.ToString(); + directory.AddContactsToDirectory + ( + new List() + { + new DirectoryContact() { - new DirectoryContact() + ContactId = "bos_1", + Name = "Board Room", + Title = @"", + ContactMethods = new List() { - ContactId = "bos_1", - Name = "Board Room", - Title = @"", - ContactMethods = new List() + new ContactMethod() { - new ContactMethod() - { - ContactMethodId = "cid_1", - Number = "bosboardroom.pepperdash.com", - Device = eContactMethodDevice.Video, - CallType = eContactMethodCallType.Video - } + ContactMethodId = "cid_1", + Number = "bosboardroom.pepperdash.com", + Device = eContactMethodDevice.Video, + CallType = eContactMethodCallType.Video } } } - ); + } + ); - return directory; - } + return directory; } + } - public static CodecDirectory SanFranciscoFolderContents + public static CodecDirectory SanFranciscoFolderContents + { + get { - get - { - var directory = new CodecDirectory(); - - directory.ResultsFolderId = eFolderId.SanFrancisco.ToString(); - directory.AddContactsToDirectory - ( - new List() + var directory = new CodecDirectory(); + + directory.ResultsFolderId = eFolderId.SanFrancisco.ToString(); + directory.AddContactsToDirectory + ( + new List() + { + new DirectoryContact() { - new DirectoryContact() + ContactId = "sfo_1", + Name = "David Huselid", + Title = @"Cive President, COO", + ContactMethods = new List() { - ContactId = "sfo_1", - Name = "David Huselid", - Title = @"Cive President, COO", - ContactMethods = new List() + new ContactMethod() { - new ContactMethod() - { - ContactMethodId = "cid_1", - Number = "dhuselid.pepperdash.com", - Device = eContactMethodDevice.Video, - CallType = eContactMethodCallType.Video - } + ContactMethodId = "cid_1", + Number = "dhuselid.pepperdash.com", + Device = eContactMethodDevice.Video, + CallType = eContactMethodCallType.Video } - } - } - ); + } + } + } + ); - return directory; - } + return directory; } + } - public static CodecDirectory DenverFolderContents + public static CodecDirectory DenverFolderContents + { + get { - get - { - var directory = new CodecDirectory(); - - directory.ResultsFolderId = eFolderId.Denver.ToString(); - directory.AddContactsToDirectory - ( - new List() + var directory = new CodecDirectory(); + + directory.ResultsFolderId = eFolderId.Denver.ToString(); + directory.AddContactsToDirectory + ( + new List() + { + new DirectoryContact() { - new DirectoryContact() + ContactId = "den_1", + Name = "Heath Volmer", + Title = @"Software Developer", + ContactMethods = new List() { - ContactId = "den_1", - Name = "Heath Volmer", - Title = @"Software Developer", - ContactMethods = new List() + new ContactMethod() { - new ContactMethod() - { - ContactMethodId = "cid_1", - Number = "hvolmer.pepperdash.com", - Device = eContactMethodDevice.Video, - CallType = eContactMethodCallType.Video - } + ContactMethodId = "cid_1", + Number = "hvolmer.pepperdash.com", + Device = eContactMethodDevice.Video, + CallType = eContactMethodCallType.Video } - } - } - ); + } + } + } + ); - return directory; - } + return directory; } + } - public static CodecDirectory AustinFolderContents + public static CodecDirectory AustinFolderContents + { + get { - get - { - var directory = new CodecDirectory(); - - directory.ResultsFolderId = eFolderId.Austin.ToString(); - directory.AddContactsToDirectory - ( - new List() + var directory = new CodecDirectory(); + + directory.ResultsFolderId = eFolderId.Austin.ToString(); + directory.AddContactsToDirectory + ( + new List() + { + new DirectoryContact() { - new DirectoryContact() + ContactId = "atx_1", + Name = "Vincent Longano", + Title = @"Product Development Manager", + ContactMethods = new List() { - ContactId = "atx_1", - Name = "Vincent Longano", - Title = @"Product Development Manager", - ContactMethods = new List() + new ContactMethod() { - new ContactMethod() - { - ContactMethodId = "cid_1", - Number = "vlongano.pepperdash.com", - Device = eContactMethodDevice.Video, - CallType = eContactMethodCallType.Video - } + ContactMethodId = "cid_1", + Number = "vlongano.pepperdash.com", + Device = eContactMethodDevice.Video, + CallType = eContactMethodCallType.Video } - } - } - ); + } + } + } + ); - return directory; - } + return directory; } + } - public static CodecDirectory CanadaFolderContents + public static CodecDirectory CanadaFolderContents + { + get { - get - { - var directory = new CodecDirectory(); - - directory.ResultsFolderId = eFolderId.Canada.ToString(); - directory.AddFoldersToDirectory - ( - new List() - { - new DirectoryFolder() - { - FolderId = eFolderId.Calgary.ToString(), - Name = "Calgary", - ParentFolderId = eFolderId.Canada.ToString(), - Contacts = null - } + var directory = new CodecDirectory(); + + directory.ResultsFolderId = eFolderId.Canada.ToString(); + directory.AddFoldersToDirectory + ( + new List() + { + new DirectoryFolder() + { + FolderId = eFolderId.Calgary.ToString(), + Name = "Calgary", + ParentFolderId = eFolderId.Canada.ToString(), + Contacts = null } - ); + } + ); - return directory; - } + return directory; } + } - public static CodecDirectory CalgaryFolderContents + public static CodecDirectory CalgaryFolderContents + { + get { - get - { - var directory = new CodecDirectory(); - - directory.ResultsFolderId = eFolderId.Calgary.ToString(); - directory.AddContactsToDirectory - ( - new List() + var directory = new CodecDirectory(); + + directory.ResultsFolderId = eFolderId.Calgary.ToString(); + directory.AddContactsToDirectory + ( + new List() + { + new DirectoryContact() { - new DirectoryContact() + ContactId = "cdn_1", + Name = "Neil Dorin", + Title = @"Software Developer /SC", + ContactMethods = new List() { - ContactId = "cdn_1", - Name = "Neil Dorin", - Title = @"Software Developer /SC", - ContactMethods = new List() + new ContactMethod() { - new ContactMethod() - { - ContactMethodId = "cid_1", - Number = "ndorin@pepperdash.com", - Device = eContactMethodDevice.Video, - CallType = eContactMethodCallType.Video - } + ContactMethodId = "cid_1", + Number = "ndorin@pepperdash.com", + Device = eContactMethodDevice.Video, + CallType = eContactMethodCallType.Video } - } - } - ); + } + } + } + ); - return directory; - } + return directory; } + } - } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVC.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVC.cs index 230238579..a607ab602 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVC.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVC.cs @@ -18,407 +18,407 @@ using Newtonsoft.Json.Linq; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common.VideoCodec +namespace PepperDash.Essentials.Devices.Common.VideoCodec; + +public class MockVC : VideoCodecBase, IRoutingSource, IHasCallHistory, IHasScheduleAwareness, IHasCallFavorites, IHasDirectory, IHasCodecCameras, IHasCameraAutoMode, IHasCodecRoomPresets { - public class MockVC : VideoCodecBase, IRoutingSource, IHasCallHistory, IHasScheduleAwareness, IHasCallFavorites, IHasDirectory, IHasCodecCameras, IHasCameraAutoMode, IHasCodecRoomPresets - { - public MockVcPropertiesConfig PropertiesConfig; + public MockVcPropertiesConfig PropertiesConfig; - public RoutingInputPort CodecOsdIn { get; private set; } - public RoutingInputPort HdmiIn1 { get; private set; } - public RoutingInputPort HdmiIn2 { get; private set; } - public RoutingOutputPort HdmiOut { get; private set; } + public RoutingInputPort CodecOsdIn { get; private set; } + public RoutingInputPort HdmiIn1 { get; private set; } + public RoutingInputPort HdmiIn2 { get; private set; } + public RoutingOutputPort HdmiOut { get; private set; } public CodecCallFavorites CallFavorites { get; private set; } - /// - /// - /// - public MockVC(DeviceConfig config) - : base(config) - { - PropertiesConfig = JsonConvert.DeserializeObject(config.Properties.ToString()); + /// + /// + /// + public MockVC(DeviceConfig config) + : base(config) + { + PropertiesConfig = JsonConvert.DeserializeObject(config.Properties.ToString()); - CodecInfo = new MockCodecInfo(); + CodecInfo = new MockCodecInfo(); // Get favoritesw - if (PropertiesConfig.Favorites != null) + if (PropertiesConfig.Favorites != null) { CallFavorites = new CodecCallFavorites(); CallFavorites.Favorites = PropertiesConfig.Favorites; } - DirectoryBrowseHistory = new List(); + DirectoryBrowseHistory = new List(); - // Debug helpers - MuteFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Debug, this, "Mute={0}", _IsMuted); - PrivacyModeIsOnFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Debug, this, "Privacy={0}", _PrivacyModeIsOn); - SharingSourceFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Debug, this, "SharingSource={0}", _SharingSource); - VolumeLevelFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Debug, this, "Volume={0}", _VolumeLevel); - - CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => DirectoryBrowseHistory.Count > 0); - - CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); - - CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, 0, this); - InputPorts.Add(CodecOsdIn); - HdmiIn1 = new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, 1, this); - InputPorts.Add(HdmiIn1); - HdmiIn2 = new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, 2, this); - InputPorts.Add(HdmiIn2); - HdmiOut = new RoutingOutputPort(RoutingPortNames.HdmiOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, null, this); - OutputPorts.Add(HdmiOut); - - CallHistory = new CodecCallHistory(); - for (int i = 0; i < 10; i++) - { - var call = new CodecCallHistory.CallHistoryEntry(); - call.Name = "Call " + i; - call.Number = i + "@call.com"; - CallHistory.RecentCalls.Add(call); - } - // eventually fire history event here + // Debug helpers + MuteFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Debug, this, "Mute={0}", _IsMuted); + PrivacyModeIsOnFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Debug, this, "Privacy={0}", _PrivacyModeIsOn); + SharingSourceFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Debug, this, "SharingSource={0}", _SharingSource); + VolumeLevelFeedback.OutputChange += (o, a) => Debug.LogMessage(LogEventLevel.Debug, this, "Volume={0}", _VolumeLevel); - SetupCameras(); + CurrentDirectoryResultIsNotDirectoryRoot = new BoolFeedback(() => DirectoryBrowseHistory.Count > 0); - CreateOsdSource(); + CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); - SetIsReady(); - } + CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, 0, this); + InputPorts.Add(CodecOsdIn); + HdmiIn1 = new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, 1, this); + InputPorts.Add(HdmiIn1); + HdmiIn2 = new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, 2, this); + InputPorts.Add(HdmiIn2); + HdmiOut = new RoutingOutputPort(RoutingPortNames.HdmiOut, eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, null, this); + OutputPorts.Add(HdmiOut); - protected override Func MuteFeedbackFunc + CallHistory = new CodecCallHistory(); + for (int i = 0; i < 10; i++) { - get { return () => _IsMuted; } + var call = new CodecCallHistory.CallHistoryEntry(); + call.Name = "Call " + i; + call.Number = i + "@call.com"; + CallHistory.RecentCalls.Add(call); } - bool _IsMuted; + // eventually fire history event here - protected override Func PrivacyModeIsOnFeedbackFunc - { - get { return () => _PrivacyModeIsOn; } - } - bool _PrivacyModeIsOn; - - protected override Func SharingSourceFeedbackFunc - { - get { return () => _SharingSource; } - } - string _SharingSource; + SetupCameras(); - protected override Func SharingContentIsOnFeedbackFunc - { - get { return () => _SharingIsOn; } - } - bool _SharingIsOn; + CreateOsdSource(); - protected override Func VolumeLevelFeedbackFunc - { - get { return () => _VolumeLevel; } - } - int _VolumeLevel; + SetIsReady(); + } - protected override Func StandbyIsOnFeedbackFunc - { - get { return () => _StandbyIsOn; } - } - bool _StandbyIsOn; + protected override Func MuteFeedbackFunc + { + get { return () => _IsMuted; } + } + bool _IsMuted; - /// - /// Creates the fake OSD source, and connects it's AudioVideo output to the CodecOsdIn input - /// to enable routing - /// - private void CreateOsdSource() - { - OsdSource = new DummyRoutingInputsDevice(Key + "[osd]"); - DeviceManager.AddDevice(OsdSource); - var tl = new TieLine(OsdSource.AudioVideoOutputPort, CodecOsdIn); - TieLineCollection.Default.Add(tl); + protected override Func PrivacyModeIsOnFeedbackFunc + { + get { return () => _PrivacyModeIsOn; } + } + bool _PrivacyModeIsOn; + + protected override Func SharingSourceFeedbackFunc + { + get { return () => _SharingSource; } + } + string _SharingSource; - //foreach(var input in Status.Video. - } + protected override Func SharingContentIsOnFeedbackFunc + { + get { return () => _SharingIsOn; } + } + bool _SharingIsOn; - /// - /// Dials, yo! - /// - public override void Dial(string number) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Dial: {0}", number); - var call = new CodecActiveCallItem() { Name = number, Number = number, Id = number, Status = eCodecCallStatus.Dialing, Direction = eCodecCallDirection.Outgoing, Type = eCodecCallType.Video }; - ActiveCalls.Add(call); - OnCallStatusChange(call); - //ActiveCallCountFeedback.FireUpdate(); - // Simulate 2-second ring, then connecting, then connected - new CTimer(o => - { - call.Type = eCodecCallType.Video; - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connecting, call); - new CTimer(oo => SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connected, call), 1000); - }, 2000); - } + protected override Func VolumeLevelFeedbackFunc + { + get { return () => _VolumeLevel; } + } + int _VolumeLevel; - public override void Dial(Meeting meeting) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Dial Meeting: {0}", meeting.Id); - var call = new CodecActiveCallItem() { Name = meeting.Title, Number = meeting.Id, Id = meeting.Id, Status = eCodecCallStatus.Dialing, Direction = eCodecCallDirection.Outgoing, Type = eCodecCallType.Video }; - ActiveCalls.Add(call); - OnCallStatusChange(call); - - //ActiveCallCountFeedback.FireUpdate(); - // Simulate 2-second ring, then connecting, then connected - new CTimer(o => - { - call.Type = eCodecCallType.Video; - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connecting, call); - new CTimer(oo => SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connected, call), 1000); - }, 2000); + protected override Func StandbyIsOnFeedbackFunc + { + get { return () => _StandbyIsOn; } + } + bool _StandbyIsOn; - } + /// + /// Creates the fake OSD source, and connects it's AudioVideo output to the CodecOsdIn input + /// to enable routing + /// + private void CreateOsdSource() + { + OsdSource = new DummyRoutingInputsDevice(Key + "[osd]"); + DeviceManager.AddDevice(OsdSource); + var tl = new TieLine(OsdSource.AudioVideoOutputPort, CodecOsdIn); + TieLineCollection.Default.Add(tl); - /// - /// - /// - public override void EndCall(CodecActiveCallItem call) - { - Debug.LogMessage(LogEventLevel.Debug, this, "EndCall"); - ActiveCalls.Remove(call); - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call); - //ActiveCallCountFeedback.FireUpdate(); - } + //foreach(var input in Status.Video. + } - /// - /// - /// - public override void EndAllCalls() - { - Debug.LogMessage(LogEventLevel.Debug, this, "EndAllCalls"); - for(int i = ActiveCalls.Count - 1; i >= 0; i--) - { - var call = ActiveCalls[i]; - ActiveCalls.Remove(call); - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call); - } - //ActiveCallCountFeedback.FireUpdate(); - } + /// + /// Dials, yo! + /// + public override void Dial(string number) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Dial: {0}", number); + var call = new CodecActiveCallItem() { Name = number, Number = number, Id = number, Status = eCodecCallStatus.Dialing, Direction = eCodecCallDirection.Outgoing, Type = eCodecCallType.Video }; + ActiveCalls.Add(call); + OnCallStatusChange(call); + //ActiveCallCountFeedback.FireUpdate(); + // Simulate 2-second ring, then connecting, then connected + new CTimer(o => + { + call.Type = eCodecCallType.Video; + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connecting, call); + new CTimer(oo => SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connected, call), 1000); + }, 2000); + } + + public override void Dial(Meeting meeting) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Dial Meeting: {0}", meeting.Id); + var call = new CodecActiveCallItem() { Name = meeting.Title, Number = meeting.Id, Id = meeting.Id, Status = eCodecCallStatus.Dialing, Direction = eCodecCallDirection.Outgoing, Type = eCodecCallType.Video }; + ActiveCalls.Add(call); + OnCallStatusChange(call); - /// - /// For a call from the test methods below - /// - public override void AcceptCall(CodecActiveCallItem call) + //ActiveCallCountFeedback.FireUpdate(); + // Simulate 2-second ring, then connecting, then connected + new CTimer(o => { - Debug.LogMessage(LogEventLevel.Debug, this, "AcceptCall"); + call.Type = eCodecCallType.Video; SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connecting, call); - new CTimer(o => SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connected, call), 1000); - // should already be in active list - } + new CTimer(oo => SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connected, call), 1000); + }, 2000); + + } + + /// + /// + /// + public override void EndCall(CodecActiveCallItem call) + { + Debug.LogMessage(LogEventLevel.Debug, this, "EndCall"); + ActiveCalls.Remove(call); + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call); + //ActiveCallCountFeedback.FireUpdate(); + } - /// - /// For a call from the test methods below - /// - public override void RejectCall(CodecActiveCallItem call) + /// + /// + /// + public override void EndAllCalls() + { + Debug.LogMessage(LogEventLevel.Debug, this, "EndAllCalls"); + for(int i = ActiveCalls.Count - 1; i >= 0; i--) { - Debug.LogMessage(LogEventLevel.Debug, this, "RejectCall"); + var call = ActiveCalls[i]; ActiveCalls.Remove(call); SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call); - //ActiveCallCountFeedback.FireUpdate(); } + //ActiveCallCountFeedback.FireUpdate(); + } - /// - /// Makes horrible tones go out on the wire! - /// - /// - public override void SendDtmf(string s) - { - Debug.LogMessage(LogEventLevel.Debug, this, "SendDTMF: {0}", s); - } + /// + /// For a call from the test methods below + /// + public override void AcceptCall(CodecActiveCallItem call) + { + Debug.LogMessage(LogEventLevel.Debug, this, "AcceptCall"); + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connecting, call); + new CTimer(o => SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Connected, call), 1000); + // should already be in active list + } - /// - /// - /// - public override void StartSharing() - { - _SharingIsOn = true; - SharingContentIsOnFeedback.FireUpdate(); - } + /// + /// For a call from the test methods below + /// + public override void RejectCall(CodecActiveCallItem call) + { + Debug.LogMessage(LogEventLevel.Debug, this, "RejectCall"); + ActiveCalls.Remove(call); + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Disconnected, call); + //ActiveCallCountFeedback.FireUpdate(); + } - /// - /// - /// - public override void StopSharing() - { - _SharingIsOn = false; - SharingContentIsOnFeedback.FireUpdate(); - } + /// + /// Makes horrible tones go out on the wire! + /// + /// + public override void SendDtmf(string s) + { + Debug.LogMessage(LogEventLevel.Debug, this, "SendDTMF: {0}", s); + } - public override void StandbyActivate() - { - _StandbyIsOn = true; - } + /// + /// + /// + public override void StartSharing() + { + _SharingIsOn = true; + SharingContentIsOnFeedback.FireUpdate(); + } - public override void StandbyDeactivate() - { - _StandbyIsOn = false; - } + /// + /// + /// + public override void StopSharing() + { + _SharingIsOn = false; + SharingContentIsOnFeedback.FireUpdate(); + } - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - throw new NotImplementedException(); - } + public override void StandbyActivate() + { + _StandbyIsOn = true; + } - /// - /// Called by routing to make it happen - /// - /// - public override void ExecuteSwitch(object selector) - { - Debug.LogMessage(LogEventLevel.Debug, this, "ExecuteSwitch: {0}", selector); - _SharingSource = selector.ToString(); - } + public override void StandbyDeactivate() + { + _StandbyIsOn = false; + } - /// - /// - /// - public override void MuteOff() - { - _IsMuted = false; - MuteFeedback.FireUpdate(); - } + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + throw new NotImplementedException(); + } - /// - /// - /// - public override void MuteOn() - { - _IsMuted = true; - MuteFeedback.FireUpdate(); - } + /// + /// Called by routing to make it happen + /// + /// + public override void ExecuteSwitch(object selector) + { + Debug.LogMessage(LogEventLevel.Debug, this, "ExecuteSwitch: {0}", selector); + _SharingSource = selector.ToString(); + } - /// - /// - /// - public override void MuteToggle() - { - _IsMuted = !_IsMuted; - MuteFeedback.FireUpdate(); - } - - /// - /// - /// - /// - public override void SetVolume(ushort level) - { - _VolumeLevel = level; - VolumeLevelFeedback.FireUpdate(); - } + /// + /// + /// + public override void MuteOff() + { + _IsMuted = false; + MuteFeedback.FireUpdate(); + } - /// - /// - /// - /// - public override void VolumeDown(bool pressRelease) - { - } + /// + /// + /// + public override void MuteOn() + { + _IsMuted = true; + MuteFeedback.FireUpdate(); + } - /// - /// - /// - /// - public override void VolumeUp(bool pressRelease) - { - } + /// + /// + /// + public override void MuteToggle() + { + _IsMuted = !_IsMuted; + MuteFeedback.FireUpdate(); + } + + /// + /// + /// + /// + public override void SetVolume(ushort level) + { + _VolumeLevel = level; + VolumeLevelFeedback.FireUpdate(); + } - /// - /// - /// - public override void PrivacyModeOn() - { - Debug.LogMessage(LogEventLevel.Debug, this, "PrivacyMuteOn"); - if (_PrivacyModeIsOn) - return; - _PrivacyModeIsOn = true; - PrivacyModeIsOnFeedback.FireUpdate(); - } + /// + /// + /// + /// + public override void VolumeDown(bool pressRelease) + { + } - /// - /// - /// - public override void PrivacyModeOff() - { - Debug.LogMessage(LogEventLevel.Debug, this, "PrivacyMuteOff"); - if (!_PrivacyModeIsOn) - return; - _PrivacyModeIsOn = false; - PrivacyModeIsOnFeedback.FireUpdate(); - } + /// + /// + /// + /// + public override void VolumeUp(bool pressRelease) + { + } - /// - /// - /// - public override void PrivacyModeToggle() - { - _PrivacyModeIsOn = !_PrivacyModeIsOn; - Debug.LogMessage(LogEventLevel.Debug, this, "PrivacyMuteToggle: {0}", _PrivacyModeIsOn); - PrivacyModeIsOnFeedback.FireUpdate(); - } + /// + /// + /// + public override void PrivacyModeOn() + { + Debug.LogMessage(LogEventLevel.Debug, this, "PrivacyMuteOn"); + if (_PrivacyModeIsOn) + return; + _PrivacyModeIsOn = true; + PrivacyModeIsOnFeedback.FireUpdate(); + } - //******************************************************** - // SIMULATION METHODS + /// + /// + /// + public override void PrivacyModeOff() + { + Debug.LogMessage(LogEventLevel.Debug, this, "PrivacyMuteOff"); + if (!_PrivacyModeIsOn) + return; + _PrivacyModeIsOn = false; + PrivacyModeIsOnFeedback.FireUpdate(); + } - /// - /// - /// - /// - public void TestIncomingVideoCall(string url) - { - Debug.LogMessage(LogEventLevel.Debug, this, "TestIncomingVideoCall from {0}", url); - var call = new CodecActiveCallItem() { Name = url, Id = url, Number = url, Type= eCodecCallType.Video, Direction = eCodecCallDirection.Incoming }; - ActiveCalls.Add(call); - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Ringing, call); + /// + /// + /// + public override void PrivacyModeToggle() + { + _PrivacyModeIsOn = !_PrivacyModeIsOn; + Debug.LogMessage(LogEventLevel.Debug, this, "PrivacyMuteToggle: {0}", _PrivacyModeIsOn); + PrivacyModeIsOnFeedback.FireUpdate(); + } - //OnCallStatusChange(eCodecCallStatus.Unknown, eCodecCallStatus.Ringing, call); - - } + //******************************************************** + // SIMULATION METHODS - /// - /// - /// - /// - public void TestIncomingAudioCall(string url) - { - Debug.LogMessage(LogEventLevel.Debug, this, "TestIncomingAudioCall from {0}", url); - var call = new CodecActiveCallItem() { Name = url, Id = url, Number = url, Type = eCodecCallType.Audio, Direction = eCodecCallDirection.Incoming }; - ActiveCalls.Add(call); - SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Ringing, call); + /// + /// + /// + /// + public void TestIncomingVideoCall(string url) + { + Debug.LogMessage(LogEventLevel.Debug, this, "TestIncomingVideoCall from {0}", url); + var call = new CodecActiveCallItem() { Name = url, Id = url, Number = url, Type= eCodecCallType.Video, Direction = eCodecCallDirection.Incoming }; + ActiveCalls.Add(call); + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Ringing, call); - //OnCallStatusChange(eCodecCallStatus.Unknown, eCodecCallStatus.Ringing, call); - } - - /// - /// - /// - public void TestFarEndHangup() - { - Debug.LogMessage(LogEventLevel.Debug, this, "TestFarEndHangup"); + //OnCallStatusChange(eCodecCallStatus.Unknown, eCodecCallStatus.Ringing, call); + + } - } + /// + /// + /// + /// + public void TestIncomingAudioCall(string url) + { + Debug.LogMessage(LogEventLevel.Debug, this, "TestIncomingAudioCall from {0}", url); + var call = new CodecActiveCallItem() { Name = url, Id = url, Number = url, Type = eCodecCallType.Audio, Direction = eCodecCallDirection.Incoming }; + ActiveCalls.Add(call); + SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus.Ringing, call); + //OnCallStatusChange(eCodecCallStatus.Unknown, eCodecCallStatus.Ringing, call); + } + + /// + /// + /// + public void TestFarEndHangup() + { + Debug.LogMessage(LogEventLevel.Debug, this, "TestFarEndHangup"); - #region IHasCallHistory Members + } - public CodecCallHistory CallHistory { get; private set; } - public void RemoveCallHistoryEntry(CodecCallHistory.CallHistoryEntry entry) - { - - } + #region IHasCallHistory Members - #endregion + public CodecCallHistory CallHistory { get; private set; } + + public void RemoveCallHistoryEntry(CodecCallHistory.CallHistoryEntry entry) + { + + } + + #endregion #region IHasScheduleAwareness Members - public void GetSchedule() - { + public void GetSchedule() + { - } + } public CodecScheduleAwareness CodecSchedule { @@ -431,13 +431,13 @@ public CodecScheduleAwareness CodecSchedule for (int i = 0; i < 5; i++) { var m = new Meeting(); - m.MinutesBeforeMeeting = 5; - m.Id = i.ToString(); - m.Organizer = "Employee " + 1; + m.MinutesBeforeMeeting = 5; + m.Id = i.ToString(); + m.Organizer = "Employee " + 1; m.StartTime = DateTime.Now.AddMinutes(5).AddHours(i); m.EndTime = DateTime.Now.AddHours(i).AddMinutes(50); m.Title = "Meeting " + i; - m.Calls.Add(new Call() { Number = i + "meeting@fake.com"}); + m.Calls.Add(new Call() { Number = i + "meeting@fake.com"}); _CodecSchedule.Meetings.Add(m); } } @@ -448,403 +448,401 @@ public CodecScheduleAwareness CodecSchedule #endregion - #region IHasDirectory Members + #region IHasDirectory Members - public event EventHandler DirectoryResultReturned; + public event EventHandler DirectoryResultReturned; - public CodecDirectory DirectoryRoot + public CodecDirectory DirectoryRoot + { + get { - get - { - return MockVideoCodecDirectory.DirectoryRoot; - } + return MockVideoCodecDirectory.DirectoryRoot; } + } - public CodecDirectory CurrentDirectoryResult + public CodecDirectory CurrentDirectoryResult + { + get { - get - { - if (DirectoryBrowseHistory.Count > 0) - return DirectoryBrowseHistory[DirectoryBrowseHistory.Count - 1]; - else - return DirectoryRoot; - } + if (DirectoryBrowseHistory.Count > 0) + return DirectoryBrowseHistory[DirectoryBrowseHistory.Count - 1]; + else + return DirectoryRoot; } + } - public CodecPhonebookSyncState PhonebookSyncState + public CodecPhonebookSyncState PhonebookSyncState + { + get { - get - { - var syncState = new CodecPhonebookSyncState(Key + "PhonebookSync"); + var syncState = new CodecPhonebookSyncState(Key + "PhonebookSync"); - syncState.InitialPhonebookFoldersReceived(); - syncState.PhonebookRootEntriesReceived(); - syncState.SetPhonebookHasFolders(true); - syncState.SetNumberOfContacts(0); // just need to call this method for the sync to complete + syncState.InitialPhonebookFoldersReceived(); + syncState.PhonebookRootEntriesReceived(); + syncState.SetPhonebookHasFolders(true); + syncState.SetNumberOfContacts(0); // just need to call this method for the sync to complete - return syncState; - } + return syncState; } + } - public void SearchDirectory(string searchString) - { - var searchResults = new CodecDirectory(); - - searchResults.ResultsFolderId = "searchResult"; + public void SearchDirectory(string searchString) + { + var searchResults = new CodecDirectory(); - // Search mock directory for contacts that contain the search string, ignoring case - List matches = MockVideoCodecDirectory.CompleteDirectory.CurrentDirectoryResults.FindAll( - s => s is DirectoryContact && s.Name.ToLower().Contains(searchString.ToLower())); + searchResults.ResultsFolderId = "searchResult"; - if (matches != null) - { - searchResults.AddContactsToDirectory(matches); + // Search mock directory for contacts that contain the search string, ignoring case + List matches = MockVideoCodecDirectory.CompleteDirectory.CurrentDirectoryResults.FindAll( + s => s is DirectoryContact && s.Name.ToLower().Contains(searchString.ToLower())); - DirectoryBrowseHistory.Add(searchResults); - } + if (matches != null) + { + searchResults.AddContactsToDirectory(matches); - OnDirectoryResultReturned(searchResults); + DirectoryBrowseHistory.Add(searchResults); } - public void GetDirectoryFolderContents(string folderId) - { - var folderDirectory = new CodecDirectory(); - - if (folderId == MockVideoCodecDirectory.eFolderId.UnitedStates.ToString()) - folderDirectory = MockVideoCodecDirectory.UnitedStatesFolderContents; - else if (folderId == MockVideoCodecDirectory.eFolderId.Canada.ToString()) - folderDirectory = MockVideoCodecDirectory.CanadaFolderContents; - else if (folderId == MockVideoCodecDirectory.eFolderId.NewYork.ToString()) - folderDirectory = MockVideoCodecDirectory.NewYorkFolderContents; - else if (folderId == MockVideoCodecDirectory.eFolderId.Boston.ToString()) - folderDirectory = MockVideoCodecDirectory.BostonFolderContents; - else if (folderId == MockVideoCodecDirectory.eFolderId.SanFrancisco.ToString()) - folderDirectory = MockVideoCodecDirectory.SanFranciscoFolderContents; - else if (folderId == MockVideoCodecDirectory.eFolderId.Denver.ToString()) - folderDirectory = MockVideoCodecDirectory.DenverFolderContents; - else if (folderId == MockVideoCodecDirectory.eFolderId.Austin.ToString()) - folderDirectory = MockVideoCodecDirectory.AustinFolderContents; - else if (folderId == MockVideoCodecDirectory.eFolderId.Calgary.ToString()) - folderDirectory = MockVideoCodecDirectory.CalgaryFolderContents; - - DirectoryBrowseHistory.Add(folderDirectory); - - OnDirectoryResultReturned(folderDirectory); - } + OnDirectoryResultReturned(searchResults); + } - public void SetCurrentDirectoryToRoot() - { - DirectoryBrowseHistory.Clear(); + public void GetDirectoryFolderContents(string folderId) + { + var folderDirectory = new CodecDirectory(); + + if (folderId == MockVideoCodecDirectory.eFolderId.UnitedStates.ToString()) + folderDirectory = MockVideoCodecDirectory.UnitedStatesFolderContents; + else if (folderId == MockVideoCodecDirectory.eFolderId.Canada.ToString()) + folderDirectory = MockVideoCodecDirectory.CanadaFolderContents; + else if (folderId == MockVideoCodecDirectory.eFolderId.NewYork.ToString()) + folderDirectory = MockVideoCodecDirectory.NewYorkFolderContents; + else if (folderId == MockVideoCodecDirectory.eFolderId.Boston.ToString()) + folderDirectory = MockVideoCodecDirectory.BostonFolderContents; + else if (folderId == MockVideoCodecDirectory.eFolderId.SanFrancisco.ToString()) + folderDirectory = MockVideoCodecDirectory.SanFranciscoFolderContents; + else if (folderId == MockVideoCodecDirectory.eFolderId.Denver.ToString()) + folderDirectory = MockVideoCodecDirectory.DenverFolderContents; + else if (folderId == MockVideoCodecDirectory.eFolderId.Austin.ToString()) + folderDirectory = MockVideoCodecDirectory.AustinFolderContents; + else if (folderId == MockVideoCodecDirectory.eFolderId.Calgary.ToString()) + folderDirectory = MockVideoCodecDirectory.CalgaryFolderContents; + + DirectoryBrowseHistory.Add(folderDirectory); + + OnDirectoryResultReturned(folderDirectory); + } - OnDirectoryResultReturned(DirectoryRoot); - } + public void SetCurrentDirectoryToRoot() + { + DirectoryBrowseHistory.Clear(); - public void GetDirectoryParentFolderContents() - { - var currentDirectory = new CodecDirectory(); + OnDirectoryResultReturned(DirectoryRoot); + } - if (DirectoryBrowseHistory.Count > 0) - { - var lastItemIndex = DirectoryBrowseHistory.Count - 1; - var parentDirectoryContents = DirectoryBrowseHistory[lastItemIndex]; + public void GetDirectoryParentFolderContents() + { + var currentDirectory = new CodecDirectory(); - DirectoryBrowseHistory.Remove(DirectoryBrowseHistory[lastItemIndex]); + if (DirectoryBrowseHistory.Count > 0) + { + var lastItemIndex = DirectoryBrowseHistory.Count - 1; + var parentDirectoryContents = DirectoryBrowseHistory[lastItemIndex]; - currentDirectory = parentDirectoryContents; + DirectoryBrowseHistory.Remove(DirectoryBrowseHistory[lastItemIndex]); - } - else - { - currentDirectory = DirectoryRoot; - } + currentDirectory = parentDirectoryContents; - OnDirectoryResultReturned(currentDirectory); + } + else + { + currentDirectory = DirectoryRoot; } - public BoolFeedback CurrentDirectoryResultIsNotDirectoryRoot { get; private set; } + OnDirectoryResultReturned(currentDirectory); + } - public List DirectoryBrowseHistory { get; private set; } + public BoolFeedback CurrentDirectoryResultIsNotDirectoryRoot { get; private set; } - public void OnDirectoryResultReturned(CodecDirectory result) - { - CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); + public List DirectoryBrowseHistory { get; private set; } - var handler = DirectoryResultReturned; - if (handler != null) + public void OnDirectoryResultReturned(CodecDirectory result) + { + CurrentDirectoryResultIsNotDirectoryRoot.FireUpdate(); + + var handler = DirectoryResultReturned; + if (handler != null) + { + handler(this, new DirectoryEventArgs() { - handler(this, new DirectoryEventArgs() - { - Directory = result, - DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue - }); - } + Directory = result, + DirectoryIsOnRoot = !CurrentDirectoryResultIsNotDirectoryRoot.BoolValue + }); } + } - #endregion + #endregion - void SetupCameras() - { - SupportsCameraAutoMode = true; + void SetupCameras() + { + SupportsCameraAutoMode = true; - SupportsCameraOff = false; + SupportsCameraOff = false; - Cameras = new List(); + Cameras = new List(); - var internalCamera = new MockVCCamera(Key + "-camera1", "Near End", this); + var internalCamera = new MockVCCamera(Key + "-camera1", "Near End", this); - Cameras.Add(internalCamera); + Cameras.Add(internalCamera); - var farEndCamera = new MockFarEndVCCamera(Key + "-cameraFar", "Far End", this); + var farEndCamera = new MockFarEndVCCamera(Key + "-cameraFar", "Far End", this); - Cameras.Add(farEndCamera); + Cameras.Add(farEndCamera); - SelectedCameraFeedback = new StringFeedback(() => SelectedCamera.Key); + SelectedCameraFeedback = new StringFeedback(() => SelectedCamera.Key); - ControllingFarEndCameraFeedback = new BoolFeedback(() => SelectedCamera is IAmFarEndCamera); + ControllingFarEndCameraFeedback = new BoolFeedback(() => SelectedCamera is IAmFarEndCamera); - CameraAutoModeIsOnFeedback = new BoolFeedback(() => _CameraAutoModeIsOn); + CameraAutoModeIsOnFeedback = new BoolFeedback(() => _CameraAutoModeIsOn); - SupportsCameraAutoMode = true; + SupportsCameraAutoMode = true; - CameraAutoModeIsOnFeedback.FireUpdate(); + CameraAutoModeIsOnFeedback.FireUpdate(); - DeviceManager.AddDevice(internalCamera); - DeviceManager.AddDevice(farEndCamera); + DeviceManager.AddDevice(internalCamera); + DeviceManager.AddDevice(farEndCamera); - NearEndPresets = new List(15); // Fix the capacity to emulate Cisco + NearEndPresets = new List(15); // Fix the capacity to emulate Cisco - if (PropertiesConfig.Presets != null && PropertiesConfig.Presets.Count > 0) - { - NearEndPresets = PropertiesConfig.Presets; - } - else + if (PropertiesConfig.Presets != null && PropertiesConfig.Presets.Count > 0) + { + NearEndPresets = PropertiesConfig.Presets; + } + else + { + for (int i = 1; i <= NearEndPresets.Capacity; i++) { - for (int i = 1; i <= NearEndPresets.Capacity; i++) - { - var label = string.Format("Near End Preset {0}", i); - NearEndPresets.Add(new CodecRoomPreset(i, label, true, false)); - } + var label = string.Format("Near End Preset {0}", i); + NearEndPresets.Add(new CodecRoomPreset(i, label, true, false)); } + } - FarEndRoomPresets = new List(15); // Fix the capacity to emulate Cisco - - // Add the far end presets - for (int i = 1; i <= FarEndRoomPresets.Capacity; i++) - { - var label = string.Format("Far End Preset {0}", i); - FarEndRoomPresets.Add(new CodecRoomPreset(i, label, true, false)); - } + FarEndRoomPresets = new List(15); // Fix the capacity to emulate Cisco - SelectedCamera = internalCamera; ; // call the method to select the camera and ensure the feedbacks get updated. + // Add the far end presets + for (int i = 1; i <= FarEndRoomPresets.Capacity; i++) + { + var label = string.Format("Far End Preset {0}", i); + FarEndRoomPresets.Add(new CodecRoomPreset(i, label, true, false)); } - #region IHasCameras Members + SelectedCamera = internalCamera; ; // call the method to select the camera and ensure the feedbacks get updated. + } + + #region IHasCameras Members - public event EventHandler CameraSelected; + public event EventHandler CameraSelected; - public List Cameras { get; private set; } + public List Cameras { get; private set; } - private CameraBase _selectedCamera; + private CameraBase _selectedCamera; - /// - /// Returns the selected camera - /// - public CameraBase SelectedCamera + /// + /// Returns the selected camera + /// + public CameraBase SelectedCamera + { + get { - get - { - return _selectedCamera; - } - private set + return _selectedCamera; + } + private set + { + _selectedCamera = value; + SelectedCameraFeedback.FireUpdate(); + ControllingFarEndCameraFeedback.FireUpdate(); + + var handler = CameraSelected; + if (handler != null) { - _selectedCamera = value; - SelectedCameraFeedback.FireUpdate(); - ControllingFarEndCameraFeedback.FireUpdate(); - - var handler = CameraSelected; - if (handler != null) - { - handler(this, new CameraSelectedEventArgs(SelectedCamera)); - } + handler(this, new CameraSelectedEventArgs(SelectedCamera)); } } + } - public StringFeedback SelectedCameraFeedback { get; private set; } + public StringFeedback SelectedCameraFeedback { get; private set; } - public void SelectCamera(string key) + public void SelectCamera(string key) + { + var camera = Cameras.FirstOrDefault(c => c.Key.ToLower().IndexOf(key.ToLower()) > -1); + if (camera != null) { - var camera = Cameras.FirstOrDefault(c => c.Key.ToLower().IndexOf(key.ToLower()) > -1); - if (camera != null) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Selected Camera with key: '{0}'", camera.Key); - SelectedCamera = camera; - } - else - Debug.LogMessage(LogEventLevel.Verbose, this, "Unable to select camera with key: '{0}'", key); + Debug.LogMessage(LogEventLevel.Verbose, this, "Selected Camera with key: '{0}'", camera.Key); + SelectedCamera = camera; } + else + Debug.LogMessage(LogEventLevel.Verbose, this, "Unable to select camera with key: '{0}'", key); + } - #endregion + #endregion - #region IHasFarEndCameraControl Members + #region IHasFarEndCameraControl Members - public CameraBase FarEndCamera { get; private set; } - - public BoolFeedback ControllingFarEndCameraFeedback { get; private set; } + public CameraBase FarEndCamera { get; private set; } + + public BoolFeedback ControllingFarEndCameraFeedback { get; private set; } - #endregion + #endregion - #region IHasCameraAutoMode Members + #region IHasCameraAutoMode Members - private bool _CameraAutoModeIsOn; + private bool _CameraAutoModeIsOn; - public void CameraAutoModeOn() - { - _CameraAutoModeIsOn = true; - CameraAutoModeIsOnFeedback.FireUpdate(); - } + public void CameraAutoModeOn() + { + _CameraAutoModeIsOn = true; + CameraAutoModeIsOnFeedback.FireUpdate(); + } - public void CameraAutoModeOff() - { - _CameraAutoModeIsOn = false; - CameraAutoModeIsOnFeedback.FireUpdate(); - } + public void CameraAutoModeOff() + { + _CameraAutoModeIsOn = false; + CameraAutoModeIsOnFeedback.FireUpdate(); + } - public void CameraAutoModeToggle() - { - if(_CameraAutoModeIsOn) - _CameraAutoModeIsOn = false; - else - _CameraAutoModeIsOn = true; + public void CameraAutoModeToggle() + { + if(_CameraAutoModeIsOn) + _CameraAutoModeIsOn = false; + else + _CameraAutoModeIsOn = true; - CameraAutoModeIsOnFeedback.FireUpdate(); + CameraAutoModeIsOnFeedback.FireUpdate(); - } + } - public BoolFeedback CameraAutoModeIsOnFeedback {get; private set;} + public BoolFeedback CameraAutoModeIsOnFeedback {get; private set;} - #endregion + #endregion - #region IHasCameraPresets Members + #region IHasCameraPresets Members - public event EventHandler CodecRoomPresetsListHasChanged; + public event EventHandler CodecRoomPresetsListHasChanged; - public List NearEndPresets { get; private set; } + public List NearEndPresets { get; private set; } - public List FarEndRoomPresets { get; private set; } + public List FarEndRoomPresets { get; private set; } - public void CodecRoomPresetSelect(int preset) + public void CodecRoomPresetSelect(int preset) + { + if (SelectedCamera is IAmFarEndCamera) { - if (SelectedCamera is IAmFarEndCamera) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Selecting Far End Preset: {0}", preset); - } - else - { - Debug.LogMessage(LogEventLevel.Debug, this, "Selecting Near End Preset: {0}", preset); - } + Debug.LogMessage(LogEventLevel.Debug, this, "Selecting Far End Preset: {0}", preset); } - - public void CodecRoomPresetStore(int preset, string description) + else { - var editPreset = NearEndPresets.FirstOrDefault(p => p.ID.Equals(preset)); - - if (editPreset != null) - { - editPreset.Defined = true; - editPreset.Description = description; - } - else - NearEndPresets.Add(new CodecRoomPreset(preset, description, true, true)); + Debug.LogMessage(LogEventLevel.Debug, this, "Selecting Near End Preset: {0}", preset); + } + } - var handler = CodecRoomPresetsListHasChanged; - if (handler != null) - { - handler(this, new EventArgs()); - } + public void CodecRoomPresetStore(int preset, string description) + { + var editPreset = NearEndPresets.FirstOrDefault(p => p.ID.Equals(preset)); - // Update the config - SetConfig(Config); + if (editPreset != null) + { + editPreset.Defined = true; + editPreset.Description = description; } + else + NearEndPresets.Add(new CodecRoomPreset(preset, description, true, true)); - public void SelectFarEndPreset(int i) + var handler = CodecRoomPresetsListHasChanged; + if (handler != null) { - Debug.LogMessage(LogEventLevel.Debug, this, "Selecting Far End Preset: {0}", i); + handler(this, new EventArgs()); } - #endregion + // Update the config + SetConfig(Config); + } - protected override void CustomSetConfig(DeviceConfig config) - { - PropertiesConfig.Presets = NearEndPresets; + public void SelectFarEndPreset(int i) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Selecting Far End Preset: {0}", i); + } - Config.Properties = JToken.FromObject(PropertiesConfig); + #endregion - ConfigWriter.UpdateDeviceConfig(config); - } + protected override void CustomSetConfig(DeviceConfig config) + { + PropertiesConfig.Presets = NearEndPresets; + Config.Properties = JToken.FromObject(PropertiesConfig); + + ConfigWriter.UpdateDeviceConfig(config); } - /// - /// Implementation for the mock VC - /// - public class MockCodecInfo : VideoCodecInfo - { +} - public override bool MultiSiteOptionIsEnabled - { - get { return true; } - } +/// +/// Implementation for the mock VC +/// +public class MockCodecInfo : VideoCodecInfo +{ - public override string E164Alias - { - get { return "someE164alias"; } - } + public override bool MultiSiteOptionIsEnabled + { + get { return true; } + } - public override string H323Id - { - get { return "someH323Id"; } - } + public override string E164Alias + { + get { return "someE164alias"; } + } - public override string IpAddress - { - get { return "xxx.xxx.xxx.xxx"; } - } + public override string H323Id + { + get { return "someH323Id"; } + } - public override string SipPhoneNumber - { - get { return "333-444-5555"; } - } + public override string IpAddress + { + get { return "xxx.xxx.xxx.xxx"; } + } - public override string SipUri - { - get { return "mock@someurl.com"; } - } + public override string SipPhoneNumber + { + get { return "333-444-5555"; } + } - public override bool AutoAnswerEnabled - { - get { return _AutoAnswerEnabled; } - } - bool _AutoAnswerEnabled; + public override string SipUri + { + get { return "mock@someurl.com"; } + } - public void SetAutoAnswer(bool value) - { - _AutoAnswerEnabled = value; - } + public override bool AutoAnswerEnabled + { + get { return _AutoAnswerEnabled; } } + bool _AutoAnswerEnabled; - public class MockVCFactory : EssentialsDeviceFactory + public void SetAutoAnswer(bool value) { - public MockVCFactory() - { - TypeNames = new List() { "mockvc" }; - } + _AutoAnswerEnabled = value; + } +} - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new MockVC Device"); - return new VideoCodec.MockVC(dc); - } +public class MockVCFactory : EssentialsDeviceFactory +{ + public MockVCFactory() + { + TypeNames = new List() { "mockvc" }; } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new MockVC Device"); + return new VideoCodec.MockVC(dc); + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVCCamera.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVCCamera.cs index 3b4d5ab90..52c520366 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVCCamera.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVCCamera.cs @@ -9,199 +9,198 @@ using PepperDash.Essentials.Devices.Common.VideoCodec; using Serilog.Events; -namespace PepperDash.Essentials.Devices.Common.Cameras +namespace PepperDash.Essentials.Devices.Common.Cameras; + +public class MockVCCamera : CameraBase, IHasCameraPtzControl, IHasCameraFocusControl, IBridgeAdvanced { - public class MockVCCamera : CameraBase, IHasCameraPtzControl, IHasCameraFocusControl, IBridgeAdvanced - { - protected VideoCodecBase ParentCodec { get; private set; } + protected VideoCodecBase ParentCodec { get; private set; } - public MockVCCamera(string key, string name, VideoCodecBase codec) - : base(key, name) - { - Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom | eCameraCapabilities.Focus; + public MockVCCamera(string key, string name, VideoCodecBase codec) + : base(key, name) + { + Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom | eCameraCapabilities.Focus; - ParentCodec = codec; - } + ParentCodec = codec; + } - #region IHasCameraPtzControl Members + #region IHasCameraPtzControl Members - public void PositionHome() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Resetting to home position"); - } + public void PositionHome() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Resetting to home position"); + } - #endregion + #endregion - #region IHasCameraPanControl Members + #region IHasCameraPanControl Members - public void PanLeft() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Panning Left"); - } + public void PanLeft() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Panning Left"); + } - public void PanRight() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Panning Right"); - } + public void PanRight() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Panning Right"); + } - public void PanStop() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Pan"); - } + public void PanStop() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Pan"); + } - #endregion + #endregion - #region IHasCameraTiltControl Members + #region IHasCameraTiltControl Members - public void TiltDown() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Tilting Down"); - } + public void TiltDown() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Tilting Down"); + } - public void TiltUp() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Tilting Up"); - } + public void TiltUp() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Tilting Up"); + } - public void TiltStop() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Tilt"); - } + public void TiltStop() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Tilt"); + } - #endregion + #endregion - #region IHasCameraZoomControl Members + #region IHasCameraZoomControl Members - public void ZoomIn() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Zooming In"); - } + public void ZoomIn() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Zooming In"); + } - public void ZoomOut() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Zooming Out"); - } + public void ZoomOut() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Zooming Out"); + } - public void ZoomStop() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Zoom"); - } + public void ZoomStop() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Zoom"); + } - #endregion + #endregion - #region IHasCameraFocusControl Members + #region IHasCameraFocusControl Members - public void FocusNear() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Focusing Near"); - } + public void FocusNear() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Focusing Near"); + } - public void FocusFar() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Focusing Far"); - } + public void FocusFar() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Focusing Far"); + } - public void FocusStop() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Focus"); - } + public void FocusStop() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Focus"); + } - public void TriggerAutoFocus() - { - Debug.LogMessage(LogEventLevel.Debug, this, "AutoFocus Triggered"); - } + public void TriggerAutoFocus() + { + Debug.LogMessage(LogEventLevel.Debug, this, "AutoFocus Triggered"); + } - #endregion + #endregion - public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - LinkCameraToApi(this, trilist, joinStart, joinMapKey, bridge); - } + public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + LinkCameraToApi(this, trilist, joinStart, joinMapKey, bridge); } +} - public class MockFarEndVCCamera : CameraBase, IHasCameraPtzControl, IAmFarEndCamera, IBridgeAdvanced - { - protected VideoCodecBase ParentCodec { get; private set; } +public class MockFarEndVCCamera : CameraBase, IHasCameraPtzControl, IAmFarEndCamera, IBridgeAdvanced +{ + protected VideoCodecBase ParentCodec { get; private set; } - public MockFarEndVCCamera(string key, string name, VideoCodecBase codec) - : base(key, name) - { - Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom; + public MockFarEndVCCamera(string key, string name, VideoCodecBase codec) + : base(key, name) + { + Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom; - ParentCodec = codec; - } + ParentCodec = codec; + } - #region IHasCameraPtzControl Members + #region IHasCameraPtzControl Members - public void PositionHome() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Resetting to home position"); - } + public void PositionHome() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Resetting to home position"); + } - #endregion + #endregion - #region IHasCameraPanControl Members + #region IHasCameraPanControl Members - public void PanLeft() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Panning Left"); - } + public void PanLeft() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Panning Left"); + } - public void PanRight() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Panning Right"); - } + public void PanRight() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Panning Right"); + } - public void PanStop() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Pan"); - } + public void PanStop() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Pan"); + } - #endregion + #endregion - #region IHasCameraTiltControl Members + #region IHasCameraTiltControl Members - public void TiltDown() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Tilting Down"); - } + public void TiltDown() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Tilting Down"); + } - public void TiltUp() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Tilting Up"); - } + public void TiltUp() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Tilting Up"); + } - public void TiltStop() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Tilt"); - } + public void TiltStop() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Tilt"); + } - #endregion + #endregion - #region IHasCameraZoomControl Members + #region IHasCameraZoomControl Members - public void ZoomIn() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Zooming In"); - } + public void ZoomIn() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Zooming In"); + } - public void ZoomOut() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Zooming Out"); - } + public void ZoomOut() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Zooming Out"); + } - public void ZoomStop() - { - Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Zoom"); - } + public void ZoomStop() + { + Debug.LogMessage(LogEventLevel.Debug, this, "Stopping Zoom"); + } - #endregion + #endregion - public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - LinkCameraToApi(this, trilist, joinStart, joinMapKey, bridge); - } + public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + LinkCameraToApi(this, trilist, joinStart, joinMapKey, bridge); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVcPropertiesConfig.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVcPropertiesConfig.cs index c1940c3a5..bee6ec35a 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVcPropertiesConfig.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/MockVC/MockVcPropertiesConfig.cs @@ -11,20 +11,19 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Devices.Common.Codec; -namespace PepperDash.Essentials.Devices.Common.VideoCodec +namespace PepperDash.Essentials.Devices.Common.VideoCodec; + +public class MockVcPropertiesConfig { - public class MockVcPropertiesConfig - { - [JsonProperty("favorites")] - public List Favorites { get; set; } + [JsonProperty("favorites")] + public List Favorites { get; set; } - [JsonProperty("presets")] - public List Presets { get; set; } + [JsonProperty("presets")] + public List Presets { get; set; } - public MockVcPropertiesConfig() - { - Favorites = new List(); - Presets = new List(); - } + public MockVcPropertiesConfig() + { + Favorites = new List(); + Presets = new List(); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs b/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs index 236c7ad97..d4974d932 100644 --- a/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs +++ b/src/PepperDash.Essentials.Devices.Common/VideoCodec/VideoCodecBase.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using Crestron.SimplSharp.CrestronIO; -using Crestron.SimplSharp.Reflection; +using System.Reflection; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharp; using PepperDash.Core; @@ -22,20 +22,20 @@ using PepperDash.Essentials.Core.Routing; using System.Text; -namespace PepperDash.Essentials.Devices.Common.VideoCodec -{ +namespace PepperDash.Essentials.Devices.Common.VideoCodec; + public abstract class VideoCodecBase : ReconfigurableDevice, IRoutingInputsOutputs, IUsageTracking, IHasDialer, IHasContentSharing, ICodecAudio, iVideoCodecInfo, IBridgeAdvanced, IHasStandbyMode { private const int XSigEncoding = 28591; - protected const int MaxParticipants = 50; + protected const int MaxParticipants = 50; private readonly byte[] _clearBytes = XSigHelpers.ClearOutputs(); - private readonly IHasDirectory _directoryCodec; - private readonly BasicTriList _directoryTrilist; - private readonly VideoCodecControllerJoinMap _directoryJoinmap; + private readonly IHasDirectory _directoryCodec; + private readonly BasicTriList _directoryTrilist; + private readonly VideoCodecControllerJoinMap _directoryJoinmap; - protected string _timeFormatSpecifier; + protected string _timeFormatSpecifier; protected string _dateFormatSpecifier; @@ -50,8 +50,8 @@ protected VideoCodecBase(DeviceConfig config) SharingSourceFeedback = new StringFeedback(SharingSourceFeedbackFunc); SharingContentIsOnFeedback = new BoolFeedback(SharingContentIsOnFeedbackFunc); - // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set - MeetingsToDisplayFeedback = new IntFeedback(() => MeetingsToDisplay); + // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set + MeetingsToDisplayFeedback = new IntFeedback(() => MeetingsToDisplay); InputPorts = new RoutingPortCollection(); OutputPorts = new RoutingPortCollection(); @@ -77,8 +77,8 @@ protected VideoCodecBase(DeviceConfig config) public bool ShowSelfViewByDefault { get; protected set; } - public bool SupportsCameraOff { get; protected set; } - public bool SupportsCameraAutoMode { get; protected set; } + public bool SupportsCameraOff { get; protected set; } + public bool SupportsCameraAutoMode { get; protected set; } public bool IsReady { get; protected set; } @@ -87,10 +87,10 @@ public virtual List Feedbacks get { return new List - { - PrivacyModeIsOnFeedback, - SharingSourceFeedback - }; + { + PrivacyModeIsOnFeedback, + SharingSourceFeedback + }; } } @@ -161,7 +161,7 @@ public bool IsInCall public abstract void AcceptCall(CodecActiveCallItem call); public abstract void RejectCall(CodecActiveCallItem call); public abstract void SendDtmf(string s); - public virtual void SendDtmf(string s, CodecActiveCallItem call) { } + public virtual void SendDtmf(string s, CodecActiveCallItem call) { } #endregion @@ -216,9 +216,9 @@ protected void SetNewCallStatusAndFireCallStatusChange(eCodecCallStatus newStatu /// protected virtual void OnCallStatusChange(CodecActiveCallItem item) { - CallStatusChange?.Invoke(this, new CodecCallStatusItemChangeEventArgs(item)); + CallStatusChange?.Invoke(this, new CodecCallStatusItemChangeEventArgs(item)); - PrivacyModeIsOnFeedback.FireUpdate(); + PrivacyModeIsOnFeedback.FireUpdate(); if (AutoShareContentWhileInCall) { @@ -248,8 +248,8 @@ protected void SetIsReady() try { IsReady = true; - IsReadyChange?.Invoke(this, new EventArgs()); - } + IsReadyChange?.Invoke(this, new EventArgs()); + } catch (Exception e) { Debug.LogMessage(LogEventLevel.Verbose, this, "Error in SetIsReady() : {0}", e); @@ -263,7 +263,7 @@ protected void SetIsReady() /// public virtual void ListCalls() { - Debug.LogMessage(LogEventLevel.Debug, this, "Active Calls:"); + Debug.LogMessage(LogEventLevel.Debug, this, "Active Calls:"); var sb = new StringBuilder(); foreach (var c in ActiveCalls) @@ -331,16 +331,16 @@ protected void LinkVideoCodecToApi(VideoCodecBase codec, BasicTriList trilist, V LinkVideoCodecVolumeToApi(trilist, joinMap); - LinkVideoCodecInfoToApi(trilist, joinMap); + LinkVideoCodecInfoToApi(trilist, joinMap); - // Register for this event to link any functions that require the codec to be ready first - codec.IsReadyChange += (o, a) => + // Register for this event to link any functions that require the codec to be ready first + codec.IsReadyChange += (o, a) => + { + if (codec is IHasCodecCameras) { - if (codec is IHasCodecCameras) - { - LinkVideoCodecCameraToApi(codec as IHasCodecCameras, trilist, joinMap); - } - }; + LinkVideoCodecCameraToApi(codec as IHasCodecCameras, trilist, joinMap); + } + }; if (codec is ICommunicationMonitor) { @@ -401,10 +401,10 @@ protected void LinkVideoCodecToApi(VideoCodecBase codec, BasicTriList trilist, V LinkVideoCodecPhoneToApi(codec as IHasPhoneDialing, trilist, joinMap); } - if (codec is IHasCallHistory) - { - LinkVideoCodecCallHistoryToApi(codec as IHasCallHistory, trilist, joinMap); - } + if (codec is IHasCallHistory) + { + LinkVideoCodecCallHistoryToApi(codec as IHasCallHistory, trilist, joinMap); + } trilist.OnlineStatusChange += (device, args) => { @@ -452,39 +452,39 @@ protected void LinkVideoCodecToApi(VideoCodecBase codec, BasicTriList trilist, V (codec as IHasPhoneDialing).PhoneOffHookFeedback.FireUpdate(); } - if (codec is IHasCallHistory) - { - UpdateCallHistory((codec as IHasCallHistory), trilist, joinMap); - } + if (codec is IHasCallHistory) + { + UpdateCallHistory((codec as IHasCallHistory), trilist, joinMap); + } SharingContentIsOnFeedback.FireUpdate(); }; } - private void LinkVideoCodecInfoToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + private void LinkVideoCodecInfoToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + trilist.SetBool(joinMap.MultiSiteOptionIsEnabled.JoinNumber, this.CodecInfo.MultiSiteOptionIsEnabled); + trilist.SetBool(joinMap.AutoAnswerEnabled.JoinNumber, this.CodecInfo.AutoAnswerEnabled); + trilist.SetString(joinMap.DeviceIpAddresss.JoinNumber, this.CodecInfo.IpAddress); + trilist.SetString(joinMap.SipPhoneNumber.JoinNumber, this.CodecInfo.SipPhoneNumber); + trilist.SetString(joinMap.E164Alias.JoinNumber, this.CodecInfo.E164Alias); + trilist.SetString(joinMap.H323Id.JoinNumber, this.CodecInfo.H323Id); + trilist.SetString(joinMap.SipUri.JoinNumber, this.CodecInfo.SipUri); + + trilist.OnlineStatusChange += (o, a) => { - trilist.SetBool(joinMap.MultiSiteOptionIsEnabled.JoinNumber, this.CodecInfo.MultiSiteOptionIsEnabled); - trilist.SetBool(joinMap.AutoAnswerEnabled.JoinNumber, this.CodecInfo.AutoAnswerEnabled); - trilist.SetString(joinMap.DeviceIpAddresss.JoinNumber, this.CodecInfo.IpAddress); - trilist.SetString(joinMap.SipPhoneNumber.JoinNumber, this.CodecInfo.SipPhoneNumber); - trilist.SetString(joinMap.E164Alias.JoinNumber, this.CodecInfo.E164Alias); - trilist.SetString(joinMap.H323Id.JoinNumber, this.CodecInfo.H323Id); - trilist.SetString(joinMap.SipUri.JoinNumber, this.CodecInfo.SipUri); - - trilist.OnlineStatusChange += (o, a) => + if (a.DeviceOnLine) { - if (a.DeviceOnLine) - { - trilist.SetBool(joinMap.MultiSiteOptionIsEnabled.JoinNumber, this.CodecInfo.MultiSiteOptionIsEnabled); - trilist.SetBool(joinMap.AutoAnswerEnabled.JoinNumber, this.CodecInfo.AutoAnswerEnabled); - trilist.SetString(joinMap.DeviceIpAddresss.JoinNumber, this.CodecInfo.IpAddress); - trilist.SetString(joinMap.SipPhoneNumber.JoinNumber, this.CodecInfo.SipPhoneNumber); - trilist.SetString(joinMap.E164Alias.JoinNumber, this.CodecInfo.E164Alias); - trilist.SetString(joinMap.H323Id.JoinNumber, this.CodecInfo.H323Id); - trilist.SetString(joinMap.SipUri.JoinNumber, this.CodecInfo.SipUri); - } - }; - } + trilist.SetBool(joinMap.MultiSiteOptionIsEnabled.JoinNumber, this.CodecInfo.MultiSiteOptionIsEnabled); + trilist.SetBool(joinMap.AutoAnswerEnabled.JoinNumber, this.CodecInfo.AutoAnswerEnabled); + trilist.SetString(joinMap.DeviceIpAddresss.JoinNumber, this.CodecInfo.IpAddress); + trilist.SetString(joinMap.SipPhoneNumber.JoinNumber, this.CodecInfo.SipPhoneNumber); + trilist.SetString(joinMap.E164Alias.JoinNumber, this.CodecInfo.E164Alias); + trilist.SetString(joinMap.H323Id.JoinNumber, this.CodecInfo.H323Id); + trilist.SetString(joinMap.SipUri.JoinNumber, this.CodecInfo.SipUri); + } + }; + } private void LinkVideoCodecPhoneToApi(IHasPhoneDialing codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { @@ -520,9 +520,9 @@ private void LinkVideoCodecCameraOffToApi(IHasCameraOff codec, BasicTriList tril trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); - if (!(codec is IHasCameraAutoMode autoCodec)) return; + if (!(codec is IHasCameraAutoMode autoCodec)) return; - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoCodec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoCodec.CameraAutoModeIsOnFeedback.BoolValue); trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !autoCodec.CameraAutoModeIsOnFeedback.BoolValue); }; @@ -537,9 +537,9 @@ private void LinkVideoCodecCameraOffToApi(IHasCameraOff codec, BasicTriList tril trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); - if (!(codec is IHasCameraAutoMode autoModeCodec)) return; + if (!(codec is IHasCameraAutoMode autoModeCodec)) return; - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue); trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !autoModeCodec.CameraAutoModeIsOnFeedback.BoolValue); } @@ -578,35 +578,35 @@ private void LinkVideoCodecCommMonitorToApi(ICommunicationMonitor codec, BasicTr private void LinkVideoCodecParticipantsToApi(IHasParticipants codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { - // make sure to update the values when the EISC comes online - trilist.OnlineStatusChange += (sender, args) => + // make sure to update the values when the EISC comes online + trilist.OnlineStatusChange += (sender, args) => + { + if (sender.IsOnline) { - if (sender.IsOnline) - { - UpdateParticipantsXSig(codec, trilist, joinMap); - } - }; + UpdateParticipantsXSig(codec, trilist, joinMap); + } + }; - // set actions and update the values when the list changes + // set actions and update the values when the list changes codec.Participants.ParticipantsListHasChanged += (sender, args) => { - SetParticipantActions(trilist, joinMap, codec.Participants.CurrentParticipants); + SetParticipantActions(trilist, joinMap, codec.Participants.CurrentParticipants); - UpdateParticipantsXSig(codec, trilist, joinMap); + UpdateParticipantsXSig(codec, trilist, joinMap); }; - trilist.OnlineStatusChange += (device, args) => - { - if (!args.DeviceOnLine) return; + trilist.OnlineStatusChange += (device, args) => + { + if (!args.DeviceOnLine) return; - // TODO [ ] Issue #868 - trilist.SetString(joinMap.CurrentParticipants.JoinNumber, "\xFC"); - UpdateParticipantsXSig(codec, trilist, joinMap); - }; + // TODO [ ] Issue #868 + trilist.SetString(joinMap.CurrentParticipants.JoinNumber, "\xFC"); + UpdateParticipantsXSig(codec, trilist, joinMap); + }; } - private void UpdateParticipantsXSig(IHasParticipants codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) - { + private void UpdateParticipantsXSig(IHasParticipants codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { string participantsXSig; if (codec.Participants.CurrentParticipants.Count == 0) @@ -622,48 +622,48 @@ private void UpdateParticipantsXSig(IHasParticipants codec, BasicTriList trilist trilist.SetString(joinMap.CurrentParticipants.JoinNumber, participantsXSig); trilist.SetUshort(joinMap.ParticipantCount.JoinNumber, (ushort)codec.Participants.CurrentParticipants.Count); - } + } + + /// + /// Sets the actions for each participant in the list + /// + private void SetParticipantActions(BasicTriList trilist, VideoCodecControllerJoinMap joinMap, List currentParticipants) + { + uint index = 0; // track the index of the participant in the - /// - /// Sets the actions for each participant in the list - /// - private void SetParticipantActions(BasicTriList trilist, VideoCodecControllerJoinMap joinMap, List currentParticipants) + foreach (var participant in currentParticipants) { - uint index = 0; // track the index of the participant in the + var p = participant; + if (index > MaxParticipants) break; - foreach (var participant in currentParticipants) + if (this is IHasParticipantAudioMute audioMuteCodec) { - var p = participant; - if (index > MaxParticipants) break; + trilist.SetSigFalseAction(joinMap.ParticipantAudioMuteToggleStart.JoinNumber + index, + () => audioMuteCodec.ToggleAudioForParticipant(p.UserId)); - if (this is IHasParticipantAudioMute audioMuteCodec) - { - trilist.SetSigFalseAction(joinMap.ParticipantAudioMuteToggleStart.JoinNumber + index, - () => audioMuteCodec.ToggleAudioForParticipant(p.UserId)); - - trilist.SetSigFalseAction(joinMap.ParticipantVideoMuteToggleStart.JoinNumber + index, - () => audioMuteCodec.ToggleVideoForParticipant(p.UserId)); - } - - if (this is IHasParticipantPinUnpin pinCodec) - { - trilist.SetSigFalseAction(joinMap.ParticipantPinToggleStart.JoinNumber + index, - () => pinCodec.ToggleParticipantPinState(p.UserId, pinCodec.ScreenIndexToPinUserTo)); - } - - index++; + trilist.SetSigFalseAction(joinMap.ParticipantVideoMuteToggleStart.JoinNumber + index, + () => audioMuteCodec.ToggleVideoForParticipant(p.UserId)); } - // Clear out any previously set actions - while (index < MaxParticipants) + if (this is IHasParticipantPinUnpin pinCodec) { - trilist.ClearBoolSigAction(joinMap.ParticipantAudioMuteToggleStart.JoinNumber + index); - trilist.ClearBoolSigAction(joinMap.ParticipantVideoMuteToggleStart.JoinNumber + index); - trilist.ClearBoolSigAction(joinMap.ParticipantPinToggleStart.JoinNumber + index); - - index++; + trilist.SetSigFalseAction(joinMap.ParticipantPinToggleStart.JoinNumber + index, + () => pinCodec.ToggleParticipantPinState(p.UserId, pinCodec.ScreenIndexToPinUserTo)); } + + index++; + } + + // Clear out any previously set actions + while (index < MaxParticipants) + { + trilist.ClearBoolSigAction(joinMap.ParticipantAudioMuteToggleStart.JoinNumber + index); + trilist.ClearBoolSigAction(joinMap.ParticipantVideoMuteToggleStart.JoinNumber + index); + trilist.ClearBoolSigAction(joinMap.ParticipantPinToggleStart.JoinNumber + index); + + index++; } + } private string UpdateParticipantsXSig(List currentParticipants) { @@ -683,37 +683,37 @@ private string UpdateParticipantsXSig(List currentParticipants) { if (meetingIndex >= maxParticipants * offset) break; - // Debug.LogMessage(LogEventLevel.Verbose, this, - //@"Updating Participant on xsig: - //Name: {0} (s{9}) - //AudioMute: {1} (d{10}) - //VideoMute: {2} (d{11}) - //CanMuteVideo: {3} (d{12}) - //CanUMuteVideo: {4} (d{13}) - //IsHost: {5} (d{14}) - //HandIsRaised: {6} (d{15}) - //IsPinned: {7} (d{16}) - //ScreenIndexIsPinnedTo: {8} (a{17}) - //", - // participant.Name, - // participant.AudioMuteFb, - // participant.VideoMuteFb, - // participant.CanMuteVideo, - // participant.CanUnmuteVideo, - // participant.IsHost, - // participant.HandIsRaisedFb, - // participant.IsPinnedFb, - // participant.ScreenIndexIsPinnedToFb, - // stringIndex + 1, - // digitalIndex + 1, - // digitalIndex + 2, - // digitalIndex + 3, - // digitalIndex + 4, - // digitalIndex + 5, - // digitalIndex + 6, - // digitalIndex + 7, - // analogIndex + 1 - // ); + // Debug.LogMessage(LogEventLevel.Verbose, this, + //@"Updating Participant on xsig: + //Name: {0} (s{9}) + //AudioMute: {1} (d{10}) + //VideoMute: {2} (d{11}) + //CanMuteVideo: {3} (d{12}) + //CanUMuteVideo: {4} (d{13}) + //IsHost: {5} (d{14}) + //HandIsRaised: {6} (d{15}) + //IsPinned: {7} (d{16}) + //ScreenIndexIsPinnedTo: {8} (a{17}) + //", + // participant.Name, + // participant.AudioMuteFb, + // participant.VideoMuteFb, + // participant.CanMuteVideo, + // participant.CanUnmuteVideo, + // participant.IsHost, + // participant.HandIsRaisedFb, + // participant.IsPinnedFb, + // participant.ScreenIndexIsPinnedToFb, + // stringIndex + 1, + // digitalIndex + 1, + // digitalIndex + 2, + // digitalIndex + 3, + // digitalIndex + 4, + // digitalIndex + 5, + // digitalIndex + 6, + // digitalIndex + 7, + // analogIndex + 1 + // ); //digitals @@ -722,10 +722,10 @@ private string UpdateParticipantsXSig(List currentParticipants) tokenArray[digitalIndex + 2] = new XSigDigitalToken(digitalIndex + 3, participant.CanMuteVideo); tokenArray[digitalIndex + 3] = new XSigDigitalToken(digitalIndex + 4, participant.CanUnmuteVideo); tokenArray[digitalIndex + 4] = new XSigDigitalToken(digitalIndex + 5, participant.IsHost); - tokenArray[digitalIndex + 5] = new XSigDigitalToken(digitalIndex + 6, participant.HandIsRaisedFb); - tokenArray[digitalIndex + 6] = new XSigDigitalToken(digitalIndex + 7, participant.IsPinnedFb); + tokenArray[digitalIndex + 5] = new XSigDigitalToken(digitalIndex + 6, participant.HandIsRaisedFb); + tokenArray[digitalIndex + 6] = new XSigDigitalToken(digitalIndex + 7, participant.IsPinnedFb); - Debug.LogMessage(LogEventLevel.Verbose, this, "Index: {0} byte value: {1}", digitalIndex + 7, ComTextHelper.GetEscapedText(tokenArray[digitalIndex + 6].GetBytes())); + Debug.LogMessage(LogEventLevel.Verbose, this, "Index: {0} byte value: {1}", digitalIndex + 7, ComTextHelper.GetEscapedText(tokenArray[digitalIndex + 6].GetBytes())); //serials tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, participant.Name); @@ -762,12 +762,12 @@ private string UpdateParticipantsXSig(List currentParticipants) analogIndex += maxAnalogs; } - var returnString = GetXSigString(tokenArray); + var returnString = GetXSigString(tokenArray); - //Debug.LogMessage(LogEventLevel.Verbose, this, "{0}", ComTextHelper.GetEscapedText(Encoding.GetEncoding(28591).GetBytes(returnString))); + //Debug.LogMessage(LogEventLevel.Verbose, this, "{0}", ComTextHelper.GetEscapedText(Encoding.GetEncoding(28591).GetBytes(returnString))); - return returnString; + return returnString; } private void LinkVideoCodecContentSharingToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) @@ -783,7 +783,7 @@ private void LinkVideoCodecContentSharingToApi(BasicTriList trilist, VideoCodecC trilist.SetBoolSigAction(joinMap.SourceShareAutoStart.JoinNumber, b => AutoShareContentWhileInCall = b); } - private List _currentMeetings = new List(); + private List _currentMeetings = new List(); private void LinkVideoCodecScheduleToApi(IHasScheduleAwareness codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { @@ -795,21 +795,21 @@ private void LinkVideoCodecScheduleToApi(IHasScheduleAwareness codec, BasicTriLi }); - for (uint i = 0; i < joinMap.DialMeetingStart.JoinSpan; i++) - { - Debug.LogMessage(LogEventLevel.Debug, this, "Setting action to Dial Meeting {0} to digital join {1}", i + 1, joinMap.DialMeetingStart.JoinNumber + i); - var joinNumber = joinMap.DialMeetingStart.JoinNumber + i; - var mtg = i + 1; - var index = (int)i; + for (uint i = 0; i < joinMap.DialMeetingStart.JoinSpan; i++) + { + Debug.LogMessage(LogEventLevel.Debug, this, "Setting action to Dial Meeting {0} to digital join {1}", i + 1, joinMap.DialMeetingStart.JoinNumber + i); + var joinNumber = joinMap.DialMeetingStart.JoinNumber + i; + var mtg = i + 1; + var index = (int)i; - trilist.SetSigFalseAction(joinNumber, () => - { - Debug.LogMessage(LogEventLevel.Debug, this, "Meeting {0} Selected (EISC dig-o{1}) > _currentMeetings[{2}].Id: {3}, Title: {4}", - mtg, joinMap.DialMeetingStart.JoinNumber + i, index, _currentMeetings[index].Id, _currentMeetings[index].Title); - if (_currentMeetings[index] != null) - Dial(_currentMeetings[index]); - }); - } + trilist.SetSigFalseAction(joinNumber, () => + { + Debug.LogMessage(LogEventLevel.Debug, this, "Meeting {0} Selected (EISC dig-o{1}) > _currentMeetings[{2}].Id: {3}, Title: {4}", + mtg, joinMap.DialMeetingStart.JoinNumber + i, index, _currentMeetings[index].Id, _currentMeetings[index].Title); + if (_currentMeetings[index] != null) + Dial(_currentMeetings[index]); + }); + } codec.CodecSchedule.MeetingsListHasChanged += (sender, args) => UpdateMeetingsList(codec, trilist, joinMap); codec.CodecSchedule.MeetingEventChange += (sender, args) => @@ -820,20 +820,20 @@ private void LinkVideoCodecScheduleToApi(IHasScheduleAwareness codec, BasicTriLi } }; - trilist.SetUShortSigAction(joinMap.MeetingsToDisplay.JoinNumber, m => MeetingsToDisplay = m); - MeetingsToDisplayFeedback.LinkInputSig(trilist.UShortInput[joinMap.MeetingsToDisplay.JoinNumber]); + trilist.SetUShortSigAction(joinMap.MeetingsToDisplay.JoinNumber, m => MeetingsToDisplay = m); + MeetingsToDisplayFeedback.LinkInputSig(trilist.UShortInput[joinMap.MeetingsToDisplay.JoinNumber]); - trilist.OnlineStatusChange += (device, args) => - { - if (!args.DeviceOnLine) return; + trilist.OnlineStatusChange += (device, args) => + { + if (!args.DeviceOnLine) return; - // TODO [ ] Issue #868 - trilist.SetString(joinMap.Schedule.JoinNumber, "\xFC"); - UpdateMeetingsList(codec, trilist, joinMap); - // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set - MeetingsToDisplayFeedback.LinkInputSig(trilist.UShortInput[joinMap.MeetingsToDisplay.JoinNumber]); - }; - } + // TODO [ ] Issue #868 + trilist.SetString(joinMap.Schedule.JoinNumber, "\xFC"); + UpdateMeetingsList(codec, trilist, joinMap); + // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set + MeetingsToDisplayFeedback.LinkInputSig(trilist.UShortInput[joinMap.MeetingsToDisplay.JoinNumber]); + }; + } private void UpdateMeetingsList(IHasScheduleAwareness codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { @@ -841,50 +841,50 @@ private void UpdateMeetingsList(IHasScheduleAwareness codec, BasicTriList trilis _currentMeetings = codec.CodecSchedule.Meetings.Where(m => m.StartTime >= currentTime || m.EndTime >= currentTime).ToList(); - if (_currentMeetings.Count == 0) - { - var emptyXSigByteArray = XSigHelpers.ClearOutputs(); - var emptyXSigString = Encoding.GetEncoding(XSigEncoding) - .GetString(emptyXSigByteArray, 0, emptyXSigByteArray.Length); + if (_currentMeetings.Count == 0) + { + var emptyXSigByteArray = XSigHelpers.ClearOutputs(); + var emptyXSigString = Encoding.GetEncoding(XSigEncoding) + .GetString(emptyXSigByteArray, 0, emptyXSigByteArray.Length); - trilist.SetString(joinMap.Schedule.JoinNumber, emptyXSigString); - return; - } + trilist.SetString(joinMap.Schedule.JoinNumber, emptyXSigString); + return; + } var meetingsData = UpdateMeetingsListXSig(_currentMeetings); trilist.SetString(joinMap.Schedule.JoinNumber, meetingsData); trilist.SetUshort(joinMap.MeetingCount.JoinNumber, (ushort)_currentMeetings.Count); - trilist.OnlineStatusChange += (device, args) => - { - if (!args.DeviceOnLine) return; + trilist.OnlineStatusChange += (device, args) => + { + if (!args.DeviceOnLine) return; - // TODO [ ] Issue #868 - trilist.SetString(joinMap.Schedule.JoinNumber, "\xFC"); - UpdateMeetingsListXSig(_currentMeetings); - }; + // TODO [ ] Issue #868 + trilist.SetString(joinMap.Schedule.JoinNumber, "\xFC"); + UpdateMeetingsListXSig(_currentMeetings); + }; } - // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set + // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set private int _meetingsToDisplay = 3; - // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set + // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set protected int MeetingsToDisplay { get { return _meetingsToDisplay; } set { - _meetingsToDisplay = (ushort) (value == 0 ? 3 : value); - MeetingsToDisplayFeedback.FireUpdate(); + _meetingsToDisplay = (ushort) (value == 0 ? 3 : value); + MeetingsToDisplayFeedback.FireUpdate(); } } - // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set - public IntFeedback MeetingsToDisplayFeedback { get; set; } + // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set + public IntFeedback MeetingsToDisplayFeedback { get; set; } - private string UpdateMeetingsListXSig(List meetings) - { - // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set - //const int _meetingsToDisplay = 3; + private string UpdateMeetingsListXSig(List meetings) + { + // TODO [ ] hotfix/videocodecbase-max-meeting-xsig-set + //const int _meetingsToDisplay = 3; const int maxDigitals = 2; const int maxStrings = 7; const int offset = maxDigitals + maxStrings; @@ -907,7 +907,7 @@ private string UpdateMeetingsListXSig(List meetings) * End Time - 6 * Id - 7 */ - + foreach (var meeting in meetings) { @@ -928,10 +928,10 @@ private string UpdateMeetingsListXSig(List meetings) //serials tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, meeting.Organizer); tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, meeting.Title); - tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToString(_dateFormatSpecifier.NullIfEmpty() ?? "d", Global.Culture)); + tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, meeting.StartTime.ToString(_dateFormatSpecifier.NullIfEmpty() ?? "d", Global.Culture)); tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, meeting.StartTime.ToString(_timeFormatSpecifier.NullIfEmpty() ?? "t", Global.Culture)); - tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, meeting.EndTime.ToString(_dateFormatSpecifier.NullIfEmpty() ?? "d", Global.Culture)); - tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, meeting.EndTime.ToString(_timeFormatSpecifier.NullIfEmpty() ?? "t", Global.Culture)); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, meeting.EndTime.ToString(_dateFormatSpecifier.NullIfEmpty() ?? "d", Global.Culture)); + tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, meeting.EndTime.ToString(_timeFormatSpecifier.NullIfEmpty() ?? "t", Global.Culture)); tokenArray[stringIndex + 6] = new XSigSerialToken(stringIndex + 7, meeting.Id); digitalIndex += maxDigitals; @@ -963,7 +963,7 @@ private string UpdateMeetingsListXSig(List meetings) } return GetXSigString(tokenArray); - } + } private void LinkVideoCodecDirectoryToApi(IHasDirectory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) @@ -975,9 +975,9 @@ private void LinkVideoCodecDirectoryToApi(IHasDirectory codec, BasicTriList tril trilist.SetUShortSigAction(joinMap.DirectorySelectRow.JoinNumber, (i) => SelectDirectoryEntry(codec, i, trilist, joinMap)); - //Special Change for protected directory clear + //Special Change for protected directory clear - trilist.SetBoolSigAction(joinMap.DirectoryClearSelected.JoinNumber, (b) => SelectDirectoryEntry(_directoryCodec, 0, _directoryTrilist, _directoryJoinmap)); + trilist.SetBoolSigAction(joinMap.DirectoryClearSelected.JoinNumber, (b) => SelectDirectoryEntry(_directoryCodec, 0, _directoryTrilist, _directoryJoinmap)); // Report feedback for number of contact methods for selected contact @@ -988,19 +988,19 @@ private void LinkVideoCodecDirectoryToApi(IHasDirectory codec, BasicTriList tril if (codec.DirectoryRoot != null) { var contactsCount = codec.DirectoryRoot.CurrentDirectoryResults.Where(c => c.ParentFolderId.Equals("root")).ToList().Count; - trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort)contactsCount); + trilist.SetUshort(joinMap.DirectoryRowCount.JoinNumber, (ushort)contactsCount); Debug.LogMessage(LogEventLevel.Verbose, this, ">>> contactsCount: {0}", contactsCount); - var clearBytes = XSigHelpers.ClearOutputs(); + var clearBytes = XSigHelpers.ClearOutputs(); - trilist.SetString(joinMap.DirectoryEntries.JoinNumber, - Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); - var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, - codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, + Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); + var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, + codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); - Debug.LogMessage(LogEventLevel.Verbose, this, "Directory XSig Length: {0}", directoryXSig.Length); + Debug.LogMessage(LogEventLevel.Verbose, this, "Directory XSig Length: {0}", directoryXSig.Length); - trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); } codec.DirectoryResultReturned += (sender, args) => @@ -1017,53 +1017,53 @@ private void LinkVideoCodecDirectoryToApi(IHasDirectory codec, BasicTriList tril trilist.SetString(joinMap.DirectoryEntries.JoinNumber, Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); - var directoryXSig = UpdateDirectoryXSig(args.Directory, - codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); - Debug.LogMessage(LogEventLevel.Verbose, this, "Directory XSig Length: {0}", directoryXSig.Length); + var directoryXSig = UpdateDirectoryXSig(args.Directory, + codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); + Debug.LogMessage(LogEventLevel.Verbose, this, "Directory XSig Length: {0}", directoryXSig.Length); trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); }; - - trilist.OnlineStatusChange += (device, args) => - { - if (!args.DeviceOnLine) return; - - var clearBytes = XSigHelpers.ClearOutputs(); - trilist.SetString(joinMap.DirectoryEntries.JoinNumber, - Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); - var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); - trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); - }; + + trilist.OnlineStatusChange += (device, args) => + { + if (!args.DeviceOnLine) return; + + var clearBytes = XSigHelpers.ClearOutputs(); + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, + Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); + var directoryXSig = UpdateDirectoryXSig(codec.DirectoryRoot, codec.CurrentDirectoryResultIsNotDirectoryRoot.BoolValue == false); + trilist.SetString(joinMap.DirectoryEntries.JoinNumber, directoryXSig); + }; } private void SelectDirectoryEntry(IHasDirectory codec, ushort i, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { - if (i > codec.CurrentDirectoryResult.CurrentDirectoryResults.Count) return; + if (i > codec.CurrentDirectoryResult.CurrentDirectoryResults.Count) return; _selectedDirectoryItem = i == 0 ? null : codec.CurrentDirectoryResult.CurrentDirectoryResults[i - 1]; - trilist.SetUshort(joinMap.DirectorySelectRowFeedback.JoinNumber, i); + trilist.SetUshort(joinMap.DirectorySelectRowFeedback.JoinNumber, i); - if (_selectedDirectoryItem == null) trilist.SetBool(joinMap.DirectoryEntryIsContact.JoinNumber, false); + if (_selectedDirectoryItem == null) trilist.SetBool(joinMap.DirectoryEntryIsContact.JoinNumber, false); if (_selectedDirectoryItem is DirectoryFolder) { codec.GetDirectoryFolderContents(_selectedDirectoryItem.FolderId); - trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0); - trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, _selectedDirectoryItem.Name); - trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, string.Empty); - trilist.ClearUShortSigAction(joinMap.SelectContactMethod.JoinNumber); - trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedLine.JoinNumber); - trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber); + trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0); + trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, _selectedDirectoryItem.Name); + trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, string.Empty); + trilist.ClearUShortSigAction(joinMap.SelectContactMethod.JoinNumber); + trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedLine.JoinNumber); + trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber); trilist.SetBool(joinMap.DirectoryEntryIsContact.JoinNumber, false); - return; + return; } - // not a folder. Clear this value - trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, string.Empty); + // not a folder. Clear this value + trilist.SetString(joinMap.DirectorySelectedFolderName.JoinNumber, string.Empty); - var selectedContact = _selectedDirectoryItem as DirectoryContact; + var selectedContact = _selectedDirectoryItem as DirectoryContact; - if (selectedContact != null && selectedContact.ContactMethods.Count >= 1) + if (selectedContact != null && selectedContact.ContactMethods.Count >= 1) { trilist.SetBool(joinMap.DirectoryEntryIsContact.JoinNumber, true); } @@ -1072,105 +1072,105 @@ private void SelectDirectoryEntry(IHasDirectory codec, ushort i, BasicTriList tr selectedContact != null ? selectedContact.Name : string.Empty); // Allow auto dial of selected line. Always dials first contact method - if (!trilist.GetBool(joinMap.DirectoryDisableAutoDialSelectedLine.JoinNumber)) + if (!trilist.GetBool(joinMap.DirectoryDisableAutoDialSelectedLine.JoinNumber)) + { + if (_selectedDirectoryItem is IInvitableContact invitableEntry) { - if (_selectedDirectoryItem is IInvitableContact invitableEntry) - { - Dial(invitableEntry); - return; - } + Dial(invitableEntry); + return; + } - trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber, - selectedContact != null ? selectedContact.ContactMethods[0].Number : string.Empty); + trilist.SetString(joinMap.DirectoryEntrySelectedNumber.JoinNumber, + selectedContact != null ? selectedContact.ContactMethods[0].Number : string.Empty); - if (!(_selectedDirectoryItem is DirectoryContact entryToDial)) return; + if (!(_selectedDirectoryItem is DirectoryContact entryToDial)) return; - Dial(entryToDial.ContactMethods[0].Number); - } - else - { - // If auto dial is disabled... + Dial(entryToDial.ContactMethods[0].Number); + } + else + { + // If auto dial is disabled... - if (!(_selectedDirectoryItem is DirectoryContact entryToDial)) - { - // Clear out values and actions from last selected item - trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0); - trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, string.Empty); - trilist.ClearUShortSigAction(joinMap.SelectContactMethod.JoinNumber); - trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedLine.JoinNumber); - trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber); - return; - } + if (!(_selectedDirectoryItem is DirectoryContact entryToDial)) + { + // Clear out values and actions from last selected item + trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, 0); + trilist.SetString(joinMap.DirectoryEntrySelectedName.JoinNumber, string.Empty); + trilist.ClearUShortSigAction(joinMap.SelectContactMethod.JoinNumber); + trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedLine.JoinNumber); + trilist.ClearBoolSigAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber); + return; + } - trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, (ushort)entryToDial.ContactMethods.Count); + trilist.SetUshort(joinMap.SelectedContactMethodCount.JoinNumber, (ushort)entryToDial.ContactMethods.Count); - // Update the action to dial the selected contact method - trilist.SetUShortSigAction(joinMap.SelectContactMethod.JoinNumber, (u) => - { - if (u < 1 || u > entryToDial.ContactMethods.Count) return; + // Update the action to dial the selected contact method + trilist.SetUShortSigAction(joinMap.SelectContactMethod.JoinNumber, (u) => + { + if (u < 1 || u > entryToDial.ContactMethods.Count) return; - trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber, () => Dial(entryToDial.ContactMethods[u - 1].Number)); - }); + trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedContactMethod.JoinNumber, () => Dial(entryToDial.ContactMethods[u - 1].Number)); + }); - // Sets DirectoryDialSelectedLine join action to dial first contact method - trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedLine.JoinNumber, () => Dial(entryToDial.ContactMethods[0].Number)); + // Sets DirectoryDialSelectedLine join action to dial first contact method + trilist.SetSigFalseAction(joinMap.DirectoryDialSelectedLine.JoinNumber, () => Dial(entryToDial.ContactMethods[0].Number)); - var clearBytes = XSigHelpers.ClearOutputs(); + var clearBytes = XSigHelpers.ClearOutputs(); - trilist.SetString(joinMap.ContactMethods.JoinNumber, - Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); - var contactMethodsXSig = UpdateContactMethodsXSig(entryToDial); + trilist.SetString(joinMap.ContactMethods.JoinNumber, + Encoding.GetEncoding(XSigEncoding).GetString(clearBytes, 0, clearBytes.Length)); + var contactMethodsXSig = UpdateContactMethodsXSig(entryToDial); - trilist.SetString(joinMap.ContactMethods.JoinNumber, contactMethodsXSig); - } + trilist.SetString(joinMap.ContactMethods.JoinNumber, contactMethodsXSig); + } } - /// - /// Generates the XSig data representing the available contact methods for the selected DirectoryContact - /// - /// - /// - private string UpdateContactMethodsXSig(DirectoryContact contact) + /// + /// Generates the XSig data representing the available contact methods for the selected DirectoryContact + /// + /// + /// + private string UpdateContactMethodsXSig(DirectoryContact contact) + { + const int maxMethods = 10; + const int maxStrings = 3; + const int offset = maxStrings; + var stringIndex = 0; + var arrayIndex = 0; + // Create a new token array and set the size to the number of methods times the total number of signals + var tokenArray = new XSigToken[maxMethods * offset]; + + Debug.LogMessage(LogEventLevel.Verbose, this, "Creating XSIG token array with size {0}", maxMethods * offset); + + // TODO: Add code to generate XSig data + foreach (var method in contact.ContactMethods) { - const int maxMethods = 10; - const int maxStrings = 3; - const int offset = maxStrings; - var stringIndex = 0; - var arrayIndex = 0; - // Create a new token array and set the size to the number of methods times the total number of signals - var tokenArray = new XSigToken[maxMethods * offset]; - - Debug.LogMessage(LogEventLevel.Verbose, this, "Creating XSIG token array with size {0}", maxMethods * offset); - - // TODO: Add code to generate XSig data - foreach (var method in contact.ContactMethods) - { - if (arrayIndex >= maxMethods * offset) - break; + if (arrayIndex >= maxMethods * offset) + break; - //serials - tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, method.Number); - tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, method.ContactMethodId.ToString()); - tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, method.Device.ToString()); + //serials + tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, method.Number); + tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, method.ContactMethodId.ToString()); + tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, method.Device.ToString()); arrayIndex += offset; stringIndex += maxStrings; - } + } - while (arrayIndex < maxMethods) - { - tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, String.Empty); - tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, String.Empty); - tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, String.Empty); + while (arrayIndex < maxMethods) + { + tokenArray[arrayIndex + 1] = new XSigSerialToken(stringIndex + 1, String.Empty); + tokenArray[arrayIndex + 2] = new XSigSerialToken(stringIndex + 2, String.Empty); + tokenArray[arrayIndex + 3] = new XSigSerialToken(stringIndex + 3, String.Empty); arrayIndex += offset; stringIndex += maxStrings; - } - - return GetXSigString(tokenArray); } + return GetXSigString(tokenArray); + } + private string UpdateDirectoryXSig(CodecDirectory directory, bool isRoot) { var xSigMaxIndex = 1023; @@ -1222,31 +1222,31 @@ private void LinkVideoCodecCallControlsToApi(BasicTriList trilist, VideoCodecCon //End All calls trilist.SetSigFalseAction(joinMap.EndAllCalls.JoinNumber, EndAllCalls); - //End a specific call, specified by index. Maximum 8 calls supported - for (int i = 0; i < joinMap.EndCallStart.JoinSpan; i++) - { - var callIndex = i; + //End a specific call, specified by index. Maximum 8 calls supported + for (int i = 0; i < joinMap.EndCallStart.JoinSpan; i++) + { + var callIndex = i; - trilist.SetSigFalseAction((uint)(joinMap.EndCallStart.JoinNumber + i), () => - { + trilist.SetSigFalseAction((uint)(joinMap.EndCallStart.JoinNumber + i), () => + { - if (callIndex < 0 || callIndex >= ActiveCalls.Count) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Cannot end call. No call found at index: {0}", callIndex); - return; - } + if (callIndex < 0 || callIndex >= ActiveCalls.Count) + { + Debug.LogMessage(LogEventLevel.Verbose, this, "Cannot end call. No call found at index: {0}", callIndex); + return; + } - var call = ActiveCalls[callIndex]; - if (call != null) - { - EndCall(call); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "[End Call] Unable to find call at index '{0}'", i); - } - }); - } + var call = ActiveCalls[callIndex]; + if (call != null) + { + EndCall(call); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "[End Call] Unable to find call at index '{0}'", i); + } + }); + } trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); @@ -1258,18 +1258,18 @@ private void LinkVideoCodecCallControlsToApi(BasicTriList trilist, VideoCodecCon Debug.LogMessage(LogEventLevel.Debug, this, "Call is incoming: {0}", args.CallItem.Direction == eCodecCallDirection.Incoming); trilist.SetBool(joinMap.IncomingCall.JoinNumber, args.CallItem.Direction == eCodecCallDirection.Incoming && args.CallItem.Status == eCodecCallStatus.Ringing); - if (args.CallItem.Direction == eCodecCallDirection.Incoming) - { - trilist.SetSigFalseAction(joinMap.IncomingAnswer.JoinNumber, () => AcceptCall(args.CallItem)); - trilist.SetSigFalseAction(joinMap.IncomingReject.JoinNumber, () => RejectCall(args.CallItem)); - trilist.SetString(joinMap.IncomingCallName.JoinNumber, args.CallItem.Name); - trilist.SetString(joinMap.IncomingCallNumber.JoinNumber, args.CallItem.Number); - } - else - { - trilist.SetString(joinMap.IncomingCallName.JoinNumber, string.Empty); - trilist.SetString(joinMap.IncomingCallNumber.JoinNumber, string.Empty); - } + if (args.CallItem.Direction == eCodecCallDirection.Incoming) + { + trilist.SetSigFalseAction(joinMap.IncomingAnswer.JoinNumber, () => AcceptCall(args.CallItem)); + trilist.SetSigFalseAction(joinMap.IncomingReject.JoinNumber, () => RejectCall(args.CallItem)); + trilist.SetString(joinMap.IncomingCallName.JoinNumber, args.CallItem.Name); + trilist.SetString(joinMap.IncomingCallNumber.JoinNumber, args.CallItem.Number); + } + else + { + trilist.SetString(joinMap.IncomingCallName.JoinNumber, string.Empty); + trilist.SetString(joinMap.IncomingCallNumber.JoinNumber, string.Empty); + } trilist.SetString(joinMap.CurrentCallData.JoinNumber, UpdateCallStatusXSig()); @@ -1277,76 +1277,76 @@ private void LinkVideoCodecCallControlsToApi(BasicTriList trilist, VideoCodecCon trilist.SetUshort(joinMap.ConnectedCallCount.JoinNumber, (ushort)ActiveCalls.Count); }; - if (this is IJoinCalls joinCodec) - { - trilist.SetSigFalseAction(joinMap.JoinAllCalls.JoinNumber, () => joinCodec.JoinAllCalls()); + if (this is IJoinCalls joinCodec) + { + trilist.SetSigFalseAction(joinMap.JoinAllCalls.JoinNumber, () => joinCodec.JoinAllCalls()); - for (int i = 0; i < joinMap.JoinCallStart.JoinSpan; i++) - { - trilist.SetSigFalseAction((uint)(joinMap.JoinCallStart.JoinNumber + i), () => + for (int i = 0; i < joinMap.JoinCallStart.JoinSpan; i++) + { + trilist.SetSigFalseAction((uint)(joinMap.JoinCallStart.JoinNumber + i), () => + { + var call = ActiveCalls[i]; + if (call != null) { - var call = ActiveCalls[i]; - if (call != null) - { - joinCodec.JoinCall(call); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "[Join Call] Unable to find call at index '{0}'", i); - } - }); - } + joinCodec.JoinCall(call); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "[Join Call] Unable to find call at index '{0}'", i); + } + }); } + } - if (this is IHasCallHold holdCodec) + if (this is IHasCallHold holdCodec) + { + trilist.SetSigFalseAction(joinMap.HoldAllCalls.JoinNumber, () => { - trilist.SetSigFalseAction(joinMap.HoldAllCalls.JoinNumber, () => + foreach (var call in ActiveCalls) { - foreach (var call in ActiveCalls) - { - holdCodec.HoldCall(call); - } - }); + holdCodec.HoldCall(call); + } + }); - for (int i = 0; i < joinMap.HoldCallsStart.JoinSpan; i++) - { - var index = i; + for (int i = 0; i < joinMap.HoldCallsStart.JoinSpan; i++) + { + var index = i; + + trilist.SetSigFalseAction((uint)(joinMap.HoldCallsStart.JoinNumber + index), () => + { + if (index < 0 || index >= ActiveCalls.Count) return; - trilist.SetSigFalseAction((uint)(joinMap.HoldCallsStart.JoinNumber + index), () => + var call = ActiveCalls[index]; + if (call != null) { - if (index < 0 || index >= ActiveCalls.Count) return; - - var call = ActiveCalls[index]; - if (call != null) - { - holdCodec.HoldCall(call); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "[Hold Call] Unable to find call at index '{0}'", i); - } - }); - - trilist.SetSigFalseAction((uint)(joinMap.ResumeCallsStart.JoinNumber + index), () => + holdCodec.HoldCall(call); + } + else { - if (index < 0 || index >= ActiveCalls.Count) return; - - var call = ActiveCalls[index]; - if (call != null) - { - holdCodec.ResumeCall(call); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "[Resume Call] Unable to find call at index '{0}'", i); - } - }); - } + Debug.LogMessage(LogEventLevel.Information, this, "[Hold Call] Unable to find call at index '{0}'", i); + } + }); + + trilist.SetSigFalseAction((uint)(joinMap.ResumeCallsStart.JoinNumber + index), () => + { + if (index < 0 || index >= ActiveCalls.Count) return; + + var call = ActiveCalls[index]; + if (call != null) + { + holdCodec.ResumeCall(call); + } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "[Resume Call] Unable to find call at index '{0}'", i); + } + }); } + } - trilist.OnlineStatusChange += (device, args) => + trilist.OnlineStatusChange += (device, args) => { if (!args.DeviceOnLine) return; @@ -1362,7 +1362,7 @@ private string UpdateCallStatusXSig() { const int maxCalls = 8; const int maxStrings = 6; - const int maxDigitals = 2; + const int maxDigitals = 2; const int offset = maxStrings + maxDigitals; var stringIndex = 0; var digitalIndex = maxStrings * maxCalls; @@ -1375,40 +1375,40 @@ private string UpdateCallStatusXSig() if (arrayIndex >= maxCalls * offset) break; //digitals - tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, call.IsActiveCall); - tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, call.IsOnHold); + tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, call.IsActiveCall); + tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, call.IsOnHold); //serials - tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, call.Name ?? String.Empty); - tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, call.Number ?? String.Empty); - tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, call.Direction.ToString()); - tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, call.Type.ToString()); - tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, call.Status.ToString()); - if(call.Duration != null) - { - // May need to verify correct string format here - var dur = string.Format("{0:c}", call.Duration); - tokenArray[arrayIndex + 6] = new XSigSerialToken(stringIndex + 6, dur); - } + tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, call.Name ?? String.Empty); + tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, call.Number ?? String.Empty); + tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, call.Direction.ToString()); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, call.Type.ToString()); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, call.Status.ToString()); + if(call.Duration != null) + { + // May need to verify correct string format here + var dur = string.Format("{0:c}", call.Duration); + tokenArray[arrayIndex + 6] = new XSigSerialToken(stringIndex + 6, dur); + } arrayIndex += offset; stringIndex += maxStrings; - digitalIndex += maxDigitals; + digitalIndex += maxDigitals; } - while (arrayIndex < maxCalls * offset) + while (arrayIndex < maxCalls * offset) { //digitals - tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); - tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false); + tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, false); + tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, false); - //serials - tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); - tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, String.Empty); - tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, String.Empty); - tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty); - tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty); - tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty); + //serials + tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, String.Empty); + tokenArray[stringIndex + 1] = new XSigSerialToken(stringIndex + 2, String.Empty); + tokenArray[stringIndex + 2] = new XSigSerialToken(stringIndex + 3, String.Empty); + tokenArray[stringIndex + 3] = new XSigSerialToken(stringIndex + 4, String.Empty); + tokenArray[stringIndex + 4] = new XSigSerialToken(stringIndex + 5, String.Empty); + tokenArray[stringIndex + 5] = new XSigSerialToken(stringIndex + 6, String.Empty); arrayIndex += offset; stringIndex += maxStrings; @@ -1420,55 +1420,55 @@ private string UpdateCallStatusXSig() private void LinkVideoCodecDtmfToApi(BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { - trilist.SetSigFalseAction(joinMap.Dtmf0.JoinNumber, () => SendDtmfAction("0", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf1.JoinNumber, () => SendDtmfAction("1", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf2.JoinNumber, () => SendDtmfAction("2", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf3.JoinNumber, () => SendDtmfAction("3", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf4.JoinNumber, () => SendDtmfAction("4", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf5.JoinNumber, () => SendDtmfAction("5", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf6.JoinNumber, () => SendDtmfAction("6", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf7.JoinNumber, () => SendDtmfAction("7", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf8.JoinNumber, () => SendDtmfAction("8", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.Dtmf9.JoinNumber, () => SendDtmfAction("9", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.DtmfStar.JoinNumber, () => SendDtmfAction("*", trilist, joinMap)); - trilist.SetSigFalseAction(joinMap.DtmfPound.JoinNumber, () => SendDtmfAction("#", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf0.JoinNumber, () => SendDtmfAction("0", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf1.JoinNumber, () => SendDtmfAction("1", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf2.JoinNumber, () => SendDtmfAction("2", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf3.JoinNumber, () => SendDtmfAction("3", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf4.JoinNumber, () => SendDtmfAction("4", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf5.JoinNumber, () => SendDtmfAction("5", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf6.JoinNumber, () => SendDtmfAction("6", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf7.JoinNumber, () => SendDtmfAction("7", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf8.JoinNumber, () => SendDtmfAction("8", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.Dtmf9.JoinNumber, () => SendDtmfAction("9", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.DtmfStar.JoinNumber, () => SendDtmfAction("*", trilist, joinMap)); + trilist.SetSigFalseAction(joinMap.DtmfPound.JoinNumber, () => SendDtmfAction("#", trilist, joinMap)); } - /// - /// Sends the specified string as a DTMF command. - /// Reads the value of the SendDtmfToSpecificCallInstance digital join and SelectCall analog join to determine - /// Whther to send to a specific call index or to the last connected call - /// - /// - /// - /// - private void SendDtmfAction(string s, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + /// + /// Sends the specified string as a DTMF command. + /// Reads the value of the SendDtmfToSpecificCallInstance digital join and SelectCall analog join to determine + /// Whther to send to a specific call index or to the last connected call + /// + /// + /// + /// + private void SendDtmfAction(string s, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + if (!trilist.GetBool(joinMap.SendDtmfToSpecificCallIndex.JoinNumber)) { - if (!trilist.GetBool(joinMap.SendDtmfToSpecificCallIndex.JoinNumber)) - { - SendDtmf(s); - } - else + SendDtmf(s); + } + else + { + var callIndex = trilist.GetUshort(joinMap.SelectCall.JoinNumber); + if (callIndex > 0 && callIndex <= 8) { - var callIndex = trilist.GetUshort(joinMap.SelectCall.JoinNumber); - if (callIndex > 0 && callIndex <= 8) + var call = ActiveCalls[callIndex - 1]; + if (call != null && call.IsActiveCall) { - var call = ActiveCalls[callIndex - 1]; - if (call != null && call.IsActiveCall) - { - SendDtmf(s, call); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Warning: No call found at index {0} or call is not active.", callIndex); - } + SendDtmf(s, call); } else { - Debug.LogMessage(LogEventLevel.Information, this, "Warning: Invalid call index specified. Please use a value of 1-8."); + Debug.LogMessage(LogEventLevel.Information, this, "Warning: No call found at index {0} or call is not active.", callIndex); } } + else + { + Debug.LogMessage(LogEventLevel.Information, this, "Warning: Invalid call index specified. Please use a value of 1-8."); + } } + } private void LinkVideoCodecCameraLayoutsToApi(IHasCodecLayouts codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) { @@ -1484,45 +1484,45 @@ private void LinkVideoCodecCameraModeToApi(IHasCameraAutoMode codec, BasicTriLis codec.CameraAutoModeIsOnFeedback.OutputChange += (o, a) => { - if (codec is IHasCameraOff offCodec) + if (codec is IHasCameraOff offCodec) + { + if (offCodec.CameraIsOffFeedback.BoolValue) { - if (offCodec.CameraIsOffFeedback.BoolValue) - { - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); - return; - } - - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue); - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); return; } trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + return; + } + + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, a.BoolValue); trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !a.BoolValue); trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); }; - if (codec is IHasCameraOff offModeCodec) + if (codec is IHasCameraOff offModeCodec) + { + if (offModeCodec.CameraIsOffFeedback.BoolValue) { - if (offModeCodec.CameraIsOffFeedback.BoolValue) - { - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); - return; - } - - trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue); - trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue); - trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, false); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, true); return; } trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue); + trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); + return; + } + + trilist.SetBool(joinMap.CameraModeAuto.JoinNumber, codec.CameraAutoModeIsOnFeedback.BoolValue); trilist.SetBool(joinMap.CameraModeManual.JoinNumber, !codec.CameraAutoModeIsOnFeedback.BoolValue); trilist.SetBool(joinMap.CameraModeOff.JoinNumber, false); } @@ -1542,9 +1542,9 @@ private void LinkVideoCodecCameraToApi(IHasCodecCameras codec, BasicTriList tril { if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; - if (b) camera.TiltUp(); + if (b) camera.TiltUp(); else camera.TiltStop(); }); @@ -1552,27 +1552,27 @@ private void LinkVideoCodecCameraToApi(IHasCodecCameras codec, BasicTriList tril { if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; - if (b) camera.TiltDown(); + if (b) camera.TiltDown(); else camera.TiltStop(); }); trilist.SetBoolSigAction(joinMap.CameraPanLeft.JoinNumber, (b) => { if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; - if (b) camera.PanLeft(); + if (b) camera.PanLeft(); else camera.PanStop(); }); trilist.SetBoolSigAction(joinMap.CameraPanRight.JoinNumber, (b) => { if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; - if (b) camera.PanRight(); + if (b) camera.PanRight(); else camera.PanStop(); }); @@ -1580,9 +1580,9 @@ private void LinkVideoCodecCameraToApi(IHasCodecCameras codec, BasicTriList tril { if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; - if (b) camera.ZoomIn(); + if (b) camera.ZoomIn(); else camera.ZoomStop(); }); @@ -1590,83 +1590,83 @@ private void LinkVideoCodecCameraToApi(IHasCodecCameras codec, BasicTriList tril { if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraPtzControl camera)) return; - if (b) camera.ZoomOut(); + if (b) camera.ZoomOut(); else camera.ZoomStop(); }); - trilist.SetBoolSigAction(joinMap.CameraFocusNear.JoinNumber, (b) => - { - if (codec.SelectedCamera == null) return; + trilist.SetBoolSigAction(joinMap.CameraFocusNear.JoinNumber, (b) => + { + if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return; - if (b) camera.FocusNear(); - else camera.FocusStop(); - }); + if (b) camera.FocusNear(); + else camera.FocusStop(); + }); - trilist.SetBoolSigAction(joinMap.CameraFocusFar.JoinNumber, (b) => - { - if (codec.SelectedCamera == null) return; + trilist.SetBoolSigAction(joinMap.CameraFocusFar.JoinNumber, (b) => + { + if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return; - if (b) camera.FocusFar(); - else camera.FocusStop(); - }); + if (b) camera.FocusFar(); + else camera.FocusStop(); + }); - trilist.SetSigFalseAction(joinMap.CameraFocusAuto.JoinNumber, () => - { - if (codec.SelectedCamera == null) return; + trilist.SetSigFalseAction(joinMap.CameraFocusAuto.JoinNumber, () => + { + if (codec.SelectedCamera == null) return; - if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return; + if (!(codec.SelectedCamera is IHasCameraFocusControl camera)) return; - camera.TriggerAutoFocus(); - }); + camera.TriggerAutoFocus(); + }); - // Camera count - trilist.SetUshort(joinMap.CameraCount.JoinNumber, (ushort)codec.Cameras.Count); + // Camera count + trilist.SetUshort(joinMap.CameraCount.JoinNumber, (ushort)codec.Cameras.Count); - // Camera names - for (uint i = 0; i < joinMap.CameraNamesFb.JoinSpan; i++) + // Camera names + for (uint i = 0; i < joinMap.CameraNamesFb.JoinSpan; i++) + { + //Check the count first + if (i < codec.Cameras.Count && codec.Cameras[(int)i] != null) { - //Check the count first - if (i < codec.Cameras.Count && codec.Cameras[(int)i] != null) - { - trilist.SetString(joinMap.CameraNamesFb.JoinNumber + i, codec.Cameras[(int)i].Name); - } - else - { - trilist.SetString(joinMap.CameraNamesFb.JoinNumber + i, ""); - } + trilist.SetString(joinMap.CameraNamesFb.JoinNumber + i, codec.Cameras[(int)i].Name); } + else + { + trilist.SetString(joinMap.CameraNamesFb.JoinNumber + i, ""); + } + } //Camera Select trilist.SetUShortSigAction(joinMap.CameraNumberSelect.JoinNumber, (i) => { - if (i > 0 && i <= codec.Cameras.Count) - { - codec.SelectCamera(codec.Cameras[i - 1].Key); - } - else - { - Debug.LogMessage(LogEventLevel.Information, this, "Unable to select. No camera found at index {0}", i); - } - }); - - // Set initial selected camera feedback - if (codec.SelectedCamera != null) + if (i > 0 && i <= codec.Cameras.Count) + { + codec.SelectCamera(codec.Cameras[i - 1].Key); + } + else { - trilist.SetUshort(joinMap.CameraNumberSelect.JoinNumber, (ushort)codec.Cameras.FindIndex((c) => c.Key == codec.SelectedCamera.Key)); + Debug.LogMessage(LogEventLevel.Information, this, "Unable to select. No camera found at index {0}", i); } + }); + + // Set initial selected camera feedback + if (codec.SelectedCamera != null) + { + trilist.SetUshort(joinMap.CameraNumberSelect.JoinNumber, (ushort)codec.Cameras.FindIndex((c) => c.Key == codec.SelectedCamera.Key)); + } codec.CameraSelected += (sender, args) => { var i = (ushort)codec.Cameras.FindIndex((c) => c.Key == args.SelectedCamera.Key); - trilist.SetUshort(joinMap.CameraNumberSelect.JoinNumber, (ushort)(i + 1)); + trilist.SetUshort(joinMap.CameraNumberSelect.JoinNumber, (ushort)(i + 1)); if (codec is IHasCodecRoomPresets) { @@ -1713,11 +1713,11 @@ private void LinkVideoCodecCameraToApi(IHasCodecCameras codec, BasicTriList tril }); - // Far End Presets - trilist.SetUShortSigAction(joinMap.FarEndPresetSelect.JoinNumber, (i) => - { - presetCodec.SelectFarEndPreset(i); - }); + // Far End Presets + trilist.SetUShortSigAction(joinMap.FarEndPresetSelect.JoinNumber, (i) => + { + presetCodec.SelectFarEndPreset(i); + }); trilist.SetSigFalseAction(joinMap.CameraPresetSave.JoinNumber, @@ -1728,105 +1728,105 @@ private void LinkVideoCodecCameraToApi(IHasCodecCameras codec, BasicTriList tril trilist.PulseBool(joinMap.CameraPresetSave.JoinNumber, 3000); }); - trilist.OnlineStatusChange += (device, args) => - { - if (!args.DeviceOnLine) return; + trilist.OnlineStatusChange += (device, args) => + { + if (!args.DeviceOnLine) return; - // TODO [ ] Issue #868 - trilist.SetString(joinMap.CameraPresetNames.JoinNumber, "\xFC"); - SetCameraPresetNames(presetCodec.NearEndPresets); - }; + // TODO [ ] Issue #868 + trilist.SetString(joinMap.CameraPresetNames.JoinNumber, "\xFC"); + SetCameraPresetNames(presetCodec.NearEndPresets); + }; } - // Following fields only used for Bridging - private int _selectedRecentCallItemIndex; - private DirectoryItem _selectedDirectoryItem; + // Following fields only used for Bridging + private int _selectedRecentCallItemIndex; + private DirectoryItem _selectedDirectoryItem; - private void LinkVideoCodecCallHistoryToApi(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) - { - codec.CallHistory.RecentCallsListHasChanged += (o, a) => - { - UpdateCallHistory(codec, trilist, joinMap); - }; + private void LinkVideoCodecCallHistoryToApi(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + codec.CallHistory.RecentCallsListHasChanged += (o, a) => + { + UpdateCallHistory(codec, trilist, joinMap); + }; - // Selected item action and feedback - trilist.SetUShortSigAction(joinMap.SelectRecentCallItem.JoinNumber, (u) => + // Selected item action and feedback + trilist.SetUShortSigAction(joinMap.SelectRecentCallItem.JoinNumber, (u) => + { + if (u == 0 || u > codec.CallHistory.RecentCalls.Count) { - if (u == 0 || u > codec.CallHistory.RecentCalls.Count) - { - Debug.LogMessage(LogEventLevel.Verbose, this, "Recent Call History index out of range"); - return; - } + Debug.LogMessage(LogEventLevel.Verbose, this, "Recent Call History index out of range"); + return; + } - _selectedRecentCallItemIndex = (int)(u - 1); - trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, u); + _selectedRecentCallItemIndex = (int)(u - 1); + trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, u); - var _selectedRecentCallItem = codec.CallHistory.RecentCalls[_selectedRecentCallItemIndex]; - - if (_selectedRecentCallItem != null) - { - trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, _selectedRecentCallItem.Name); - trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, _selectedRecentCallItem.Number); - trilist.SetSigFalseAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber, () => codec.RemoveCallHistoryEntry(_selectedRecentCallItem)); - trilist.SetSigFalseAction(joinMap.DialSelectedRecentCallItem.JoinNumber, () => this.Dial(_selectedRecentCallItem.Number)); - } - else - { - trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty); - trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty); - trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber); - trilist.ClearBoolSigAction(joinMap.DialSelectedRecentCallItem.JoinNumber); - } - }); - } + var _selectedRecentCallItem = codec.CallHistory.RecentCalls[_selectedRecentCallItemIndex]; + + if (_selectedRecentCallItem != null) + { + trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, _selectedRecentCallItem.Name); + trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, _selectedRecentCallItem.Number); + trilist.SetSigFalseAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber, () => codec.RemoveCallHistoryEntry(_selectedRecentCallItem)); + trilist.SetSigFalseAction(joinMap.DialSelectedRecentCallItem.JoinNumber, () => this.Dial(_selectedRecentCallItem.Number)); + } + else + { + trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty); + trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty); + trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber); + trilist.ClearBoolSigAction(joinMap.DialSelectedRecentCallItem.JoinNumber); + } + }); + } - private void UpdateCallHistory(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) - { - // Clear out selected item - _selectedRecentCallItemIndex = 0; + private void UpdateCallHistory(IHasCallHistory codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) + { + // Clear out selected item + _selectedRecentCallItemIndex = 0; - trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, 0); - trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty); - trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty); - trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber); - // + trilist.SetUshort(joinMap.SelectRecentCallItem.JoinNumber, 0); + trilist.SetString(joinMap.SelectedRecentCallName.JoinNumber, string.Empty); + trilist.SetString(joinMap.SelectedRecentCallNumber.JoinNumber, string.Empty); + trilist.ClearBoolSigAction(joinMap.RemoveSelectedRecentCallItem.JoinNumber); + // - trilist.SetUshort(joinMap.RecentCallCount.JoinNumber, (ushort)codec.CallHistory.RecentCalls.Count); + trilist.SetUshort(joinMap.RecentCallCount.JoinNumber, (ushort)codec.CallHistory.RecentCalls.Count); - // Update the call history joins - var maxItems = joinMap.RecentCallNamesStart.JoinSpan; + // Update the call history joins + var maxItems = joinMap.RecentCallNamesStart.JoinSpan; - // Create history - uint index = 0; - for (uint i = 0; i < maxItems && i < codec.CallHistory.RecentCalls.Count; i++) - { - trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, codec.CallHistory.RecentCalls[(int)i].Name); - trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, codec.CallHistory.RecentCalls[(int)i].StartTime.ToShortTimeString()); - trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)codec.CallHistory.RecentCalls[(int)i].OccurrenceType); - //i++; - index = i; - } - - //foreach(var item in codec.CallHistory.RecentCalls) - //{ - // trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, item.Name); - // trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, item.StartTime.ToShortTimeString()); - // trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)item.OccurrenceType); - // i++; - //} - - // Clears existing items - for (uint j = index; j < maxItems; j++) - { - trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + j, string.Empty); - trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + j, string.Empty); - trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + j, 0); - } + // Create history + uint index = 0; + for (uint i = 0; i < maxItems && i < codec.CallHistory.RecentCalls.Count; i++) + { + trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, codec.CallHistory.RecentCalls[(int)i].Name); + trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, codec.CallHistory.RecentCalls[(int)i].StartTime.ToShortTimeString()); + trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)codec.CallHistory.RecentCalls[(int)i].OccurrenceType); + //i++; + index = i; } + + //foreach(var item in codec.CallHistory.RecentCalls) + //{ + // trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + i, item.Name); + // trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + i, item.StartTime.ToShortTimeString()); + // trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + i, (ushort)item.OccurrenceType); + // i++; + //} + + // Clears existing items + for (uint j = index; j < maxItems; j++) + { + trilist.SetString(joinMap.RecentCallNamesStart.JoinNumber + j, string.Empty); + trilist.SetString(joinMap.RecentCallTimesStart.JoinNumber + j, string.Empty); + trilist.SetUshort(joinMap.RecentCallOccurrenceType.JoinNumber + j, 0); + } + } - private string SetCameraPresetNames(IEnumerable presets) + private string SetCameraPresetNames(IEnumerable presets) { return SetCameraPresetNames(presets.Select(p => p.Description).ToList()); } @@ -1895,8 +1895,8 @@ private set { if (value == true) { - InitialSyncCompleted?.Invoke(this, new EventArgs()); - } + InitialSyncCompleted?.Invoke(this, new EventArgs()); + } _InitialSyncComplete = value; } } @@ -1971,21 +1971,18 @@ private void CheckSyncStatus() } } } - /// - /// Represents a codec command that might need to have a friendly label applied for UI feedback purposes - /// - public class CodecCommandWithLabel - { - public string Command { get; private set; } - public string Label { get; private set; } +/// +/// Represents a codec command that might need to have a friendly label applied for UI feedback purposes +/// +public class CodecCommandWithLabel +{ + public string Command { get; private set; } + public string Label { get; private set; } - public CodecCommandWithLabel(string command, string label) - { - Command = command; - Label = label; - } + public CodecCommandWithLabel(string command, string label) + { + Command = command; + Label = label; } +} - - -} \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/ContentTypes.cs b/src/PepperDash.Essentials.MobileControl.Messengers/ContentTypes.cs index e555f11f0..4c8506fb8 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/ContentTypes.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/ContentTypes.cs @@ -1,31 +1,30 @@ using Newtonsoft.Json; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.AppServer -{ - public class SourceSelectMessageContent - { +namespace PepperDash.Essentials.AppServer; - [JsonProperty("sourceListItemKey")] - public string SourceListItemKey { get; set; } - [JsonProperty("sourceListKey")] - public string SourceListKey { get; set; } - } +public class SourceSelectMessageContent +{ - public class DirectRoute - { + [JsonProperty("sourceListItemKey")] + public string SourceListItemKey { get; set; } + [JsonProperty("sourceListKey")] + public string SourceListKey { get; set; } +} - [JsonProperty("sourceKey")] - public string SourceKey { get; set; } - [JsonProperty("destinationKey")] - public string DestinationKey { get; set; } - [JsonProperty("signalType")] - public eRoutingSignalType SignalType { get; set; } - } +public class DirectRoute +{ - /// - /// - /// - /// - public delegate void PressAndHoldAction(bool b); + [JsonProperty("sourceKey")] + public string SourceKey { get; set; } + [JsonProperty("destinationKey")] + public string DestinationKey { get; set; } + [JsonProperty("signalType")] + public eRoutingSignalType SignalType { get; set; } } + +/// +/// +/// +/// +public delegate void PressAndHoldAction(bool b); diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/DisplayBaseMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/DisplayBaseMessenger.cs index cc09a6371..8db472dbf 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/DisplayBaseMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/DisplayBaseMessenger.cs @@ -6,55 +6,54 @@ using System.Linq; using DisplayBase = PepperDash.Essentials.Devices.Common.Displays.DisplayBase; -namespace PepperDash.Essentials.Room.MobileControl +namespace PepperDash.Essentials.Room.MobileControl; + +public class DisplayBaseMessenger : MessengerBase { - public class DisplayBaseMessenger : MessengerBase + private readonly DisplayBase display; + + public DisplayBaseMessenger(string key, string messagePath, DisplayBase device) : base(key, messagePath, device) + { + display = device; + } + + protected override void RegisterActions() { - private readonly DisplayBase display; + base.RegisterActions(); - public DisplayBaseMessenger(string key, string messagePath, DisplayBase device) : base(key, messagePath, device) - { - display = device; - } + /*AddAction("/powerOn", (id, content) => display.PowerOn()); + AddAction("/powerOff", (id, content) => display.PowerOff()); + AddAction("/powerToggle", (id, content) => display.PowerToggle());*/ - protected override void RegisterActions() + AddAction("/inputSelect", (id, content) => { - base.RegisterActions(); + var s = content.ToObject>(); - /*AddAction("/powerOn", (id, content) => display.PowerOn()); - AddAction("/powerOff", (id, content) => display.PowerOff()); - AddAction("/powerToggle", (id, content) => display.PowerToggle());*/ + var inputPort = display.InputPorts.FirstOrDefault(i => i.Key == s.Value); - AddAction("/inputSelect", (id, content) => + if (inputPort == null) { - var s = content.ToObject>(); + this.LogWarning("No input named {inputName} found for {deviceKey}", s, display.Key); + return; + } - var inputPort = display.InputPorts.FirstOrDefault(i => i.Key == s.Value); + display.ExecuteSwitch(inputPort.Selector); + }); - if (inputPort == null) - { - this.LogWarning("No input named {inputName} found for {deviceKey}", s, display.Key); - return; - } - - display.ExecuteSwitch(inputPort.Selector); - }); + AddAction("/inputs", (id, content) => + { + var inputsList = display.InputPorts.Select(p => p.Key).ToList(); - AddAction("/inputs", (id, content) => + var messageObject = new MobileControlMessage { - var inputsList = display.InputPorts.Select(p => p.Key).ToList(); - - var messageObject = new MobileControlMessage + Type = MessagePath + "/inputs", + Content = JToken.FromObject(new { - Type = MessagePath + "/inputs", - Content = JToken.FromObject(new - { - inputKeys = inputsList, - }) - }; - - AppServerController.SendMessageObject(messageObject); - }); - } + inputKeys = inputsList, + }) + }; + + AppServerController.SendMessageObject(messageObject); + }); } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IChannelMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IChannelMessenger.cs index 4ba89800d..43c0a640f 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IChannelMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IChannelMessenger.cs @@ -2,28 +2,27 @@ using PepperDash.Essentials.AppServer.Messengers; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Room.MobileControl +namespace PepperDash.Essentials.Room.MobileControl; + +public class IChannelMessenger : MessengerBase { - public class IChannelMessenger : MessengerBase - { - private readonly IChannel channelDevice; + private readonly IChannel channelDevice; - public IChannelMessenger(string key, string messagePath, IChannel device) : base(key, messagePath, device as IKeyName) - { - channelDevice = device; - } + public IChannelMessenger(string key, string messagePath, IChannel device) : base(key, messagePath, device as IKeyName) + { + channelDevice = device; + } - protected override void RegisterActions() - { - base.RegisterActions(); + protected override void RegisterActions() + { + base.RegisterActions(); - AddAction("/chanUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.ChannelUp(b))); + AddAction("/chanUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.ChannelUp(b))); - AddAction("/chanDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.ChannelDown(b))); - AddAction("/lastChan", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.LastChannel(b))); - AddAction("/guide", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.Guide(b))); - AddAction("/info", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.Info(b))); - AddAction("/exit", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.Exit(b))); - } + AddAction("/chanDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.ChannelDown(b))); + AddAction("/lastChan", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.LastChannel(b))); + AddAction("/guide", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.Guide(b))); + AddAction("/info", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.Info(b))); + AddAction("/exit", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => channelDevice?.Exit(b))); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IColorMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IColorMessenger.cs index 86df2590f..b4c831ed8 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IColorMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IColorMessenger.cs @@ -2,24 +2,23 @@ using PepperDash.Essentials.AppServer.Messengers; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Room.MobileControl +namespace PepperDash.Essentials.Room.MobileControl; + +public class IColorMessenger : MessengerBase { - public class IColorMessenger : MessengerBase + private readonly IColor colorDevice; + public IColorMessenger(string key, string messagePath, IColor device) : base(key, messagePath, device as IKeyName) { - private readonly IColor colorDevice; - public IColorMessenger(string key, string messagePath, IColor device) : base(key, messagePath, device as IKeyName) - { - colorDevice = device as IColor; - } + colorDevice = device as IColor; + } - protected override void RegisterActions() - { - base.RegisterActions(); + protected override void RegisterActions() + { + base.RegisterActions(); - AddAction("/red", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => colorDevice?.Red(b))); - AddAction("/green", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => colorDevice?.Green(b))); - AddAction("/yellow", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => colorDevice?.Yellow(b))); - AddAction("/blue", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => colorDevice?.Blue(b))); - } + AddAction("/red", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => colorDevice?.Red(b))); + AddAction("/green", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => colorDevice?.Green(b))); + AddAction("/yellow", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => colorDevice?.Yellow(b))); + AddAction("/blue", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => colorDevice?.Blue(b))); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IDPadMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IDPadMessenger.cs index 4af077030..e2b351a19 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IDPadMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IDPadMessenger.cs @@ -2,28 +2,27 @@ using PepperDash.Essentials.AppServer.Messengers; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Room.MobileControl +namespace PepperDash.Essentials.Room.MobileControl; + +public class IDPadMessenger : MessengerBase { - public class IDPadMessenger : MessengerBase + private readonly IDPad dpadDevice; + public IDPadMessenger(string key, string messagePath, IDPad device) : base(key, messagePath, device as IKeyName) { - private readonly IDPad dpadDevice; - public IDPadMessenger(string key, string messagePath, IDPad device) : base(key, messagePath, device as IKeyName) - { - dpadDevice = device; - } + dpadDevice = device; + } - protected override void RegisterActions() - { - base.RegisterActions(); + protected override void RegisterActions() + { + base.RegisterActions(); - AddAction("/up", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Up(b))); - AddAction("/down", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Down(b))); - AddAction("/left", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Left(b))); - AddAction("/right", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Right(b))); - AddAction("/select", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Select(b))); - AddAction("/menu", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Menu(b))); - AddAction("/exit", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Exit(b))); - } + AddAction("/up", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Up(b))); + AddAction("/down", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Down(b))); + AddAction("/left", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Left(b))); + AddAction("/right", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Right(b))); + AddAction("/select", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Select(b))); + AddAction("/menu", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Menu(b))); + AddAction("/exit", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dpadDevice?.Exit(b))); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IDvrMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IDvrMessenger.cs index 8e286979d..f0e02c8af 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IDvrMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IDvrMessenger.cs @@ -2,23 +2,22 @@ using PepperDash.Essentials.AppServer.Messengers; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Room.MobileControl +namespace PepperDash.Essentials.Room.MobileControl; + +public class IDvrMessenger : MessengerBase { - public class IDvrMessenger : MessengerBase + private readonly IDvr dvrDevice; + public IDvrMessenger(string key, string messagePath, IDvr device) : base(key, messagePath, device as IKeyName) { - private readonly IDvr dvrDevice; - public IDvrMessenger(string key, string messagePath, IDvr device) : base(key, messagePath, device as IKeyName) - { - dvrDevice = device; - } - - protected override void RegisterActions() - { - base.RegisterActions(); + dvrDevice = device; + } - AddAction("/dvrlist", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dvrDevice?.DvrList(b))); - AddAction("/record", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dvrDevice?.Record(b))); - } + protected override void RegisterActions() + { + base.RegisterActions(); + AddAction("/dvrlist", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dvrDevice?.DvrList(b))); + AddAction("/record", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => dvrDevice?.Record(b))); } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IHasPowerMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IHasPowerMessenger.cs index 39ed0e6f0..16f294115 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IHasPowerMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/IHasPowerMessenger.cs @@ -2,23 +2,22 @@ using PepperDash.Essentials.AppServer.Messengers; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Room.MobileControl +namespace PepperDash.Essentials.Room.MobileControl; + +public class IHasPowerMessenger : MessengerBase { - public class IHasPowerMessenger : MessengerBase + private readonly IHasPowerControl powerDevice; + public IHasPowerMessenger(string key, string messagePath, IHasPowerControl device) : base(key, messagePath, device as IKeyName) { - private readonly IHasPowerControl powerDevice; - public IHasPowerMessenger(string key, string messagePath, IHasPowerControl device) : base(key, messagePath, device as IKeyName) - { - powerDevice = device; - } + powerDevice = device; + } - protected override void RegisterActions() - { - base.RegisterActions(); + protected override void RegisterActions() + { + base.RegisterActions(); - AddAction("/powerOn", (id, content) => powerDevice?.PowerOn()); - AddAction("/powerOff", (id, content) => powerDevice?.PowerOff()); - AddAction("/powerToggle", (id, content) => powerDevice?.PowerToggle()); - } + AddAction("/powerOn", (id, content) => powerDevice?.PowerOn()); + AddAction("/powerOff", (id, content) => powerDevice?.PowerOff()); + AddAction("/powerToggle", (id, content) => powerDevice?.PowerToggle()); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/INumericMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/INumericMessenger.cs index 69b5bc9d6..c40459eca 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/INumericMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/INumericMessenger.cs @@ -2,33 +2,32 @@ using PepperDash.Essentials.AppServer.Messengers; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Room.MobileControl +namespace PepperDash.Essentials.Room.MobileControl; + +public class INumericKeypadMessenger : MessengerBase { - public class INumericKeypadMessenger : MessengerBase + private readonly INumericKeypad keypadDevice; + public INumericKeypadMessenger(string key, string messagePath, INumericKeypad device) : base(key, messagePath, device as IKeyName) { - private readonly INumericKeypad keypadDevice; - public INumericKeypadMessenger(string key, string messagePath, INumericKeypad device) : base(key, messagePath, device as IKeyName) - { - keypadDevice = device; - } + keypadDevice = device; + } - protected override void RegisterActions() - { - base.RegisterActions(); + protected override void RegisterActions() + { + base.RegisterActions(); - AddAction("/num0", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit0(b))); - AddAction("/num1", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit1(b))); - AddAction("/num2", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit2(b))); - AddAction("/num3", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit3(b))); - AddAction("/num4", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit4(b))); - AddAction("/num5", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit5(b))); - AddAction("/num6", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit6(b))); - AddAction("/num7", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit7(b))); - AddAction("/num8", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit8(b))); - AddAction("/num9", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit9(b))); - AddAction("/numDash", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.KeypadAccessoryButton1(b))); - AddAction("/numEnter", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.KeypadAccessoryButton2(b))); - // Deal with the Accessory functions on the numpad later - } + AddAction("/num0", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit0(b))); + AddAction("/num1", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit1(b))); + AddAction("/num2", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit2(b))); + AddAction("/num3", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit3(b))); + AddAction("/num4", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit4(b))); + AddAction("/num5", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit5(b))); + AddAction("/num6", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit6(b))); + AddAction("/num7", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit7(b))); + AddAction("/num8", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit8(b))); + AddAction("/num9", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.Digit9(b))); + AddAction("/numDash", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.KeypadAccessoryButton1(b))); + AddAction("/numEnter", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => keypadDevice?.KeypadAccessoryButton2(b))); + // Deal with the Accessory functions on the numpad later } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/ISetTopBoxControlsMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/ISetTopBoxControlsMessenger.cs index 0e7c227b0..775ace5e3 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/ISetTopBoxControlsMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/ISetTopBoxControlsMessenger.cs @@ -2,38 +2,37 @@ using PepperDash.Essentials.AppServer.Messengers; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Room.MobileControl +namespace PepperDash.Essentials.Room.MobileControl; + +public class ISetTopBoxControlsMessenger : MessengerBase { - public class ISetTopBoxControlsMessenger : MessengerBase + private readonly ISetTopBoxControls stbDevice; + public ISetTopBoxControlsMessenger(string key, string messagePath, ISetTopBoxControls device) : base(key, messagePath, device as IKeyName) { - private readonly ISetTopBoxControls stbDevice; - public ISetTopBoxControlsMessenger(string key, string messagePath, ISetTopBoxControls device) : base(key, messagePath, device as IKeyName) - { - stbDevice = device; - } - - protected override void RegisterActions() - { - base.RegisterActions(); - AddAction("/fullStatus", (id, content) => SendISetTopBoxControlsFullMessageObject()); - AddAction("/dvrList", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => stbDevice?.DvrList(b))); - AddAction("/replay", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => stbDevice?.Replay(b))); - } - /// - /// Helper method to build call status for vtc - /// - /// - private void SendISetTopBoxControlsFullMessageObject() - { - - PostStatusMessage(new SetTopBoxControlsState()); - - - } + stbDevice = device; } - public class SetTopBoxControlsState : DeviceStateMessageBase + protected override void RegisterActions() + { + base.RegisterActions(); + AddAction("/fullStatus", (id, content) => SendISetTopBoxControlsFullMessageObject()); + AddAction("/dvrList", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => stbDevice?.DvrList(b))); + AddAction("/replay", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => stbDevice?.Replay(b))); + } + /// + /// Helper method to build call status for vtc + /// + /// + private void SendISetTopBoxControlsFullMessageObject() { + PostStatusMessage(new SetTopBoxControlsState()); + + } +} + +public class SetTopBoxControlsState : DeviceStateMessageBase +{ + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/ITransportMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/ITransportMessenger.cs index 75f744180..0beb4f119 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/ITransportMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/DeviceTypeExtensions/ITransportMessenger.cs @@ -2,29 +2,28 @@ using PepperDash.Essentials.AppServer.Messengers; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Room.MobileControl +namespace PepperDash.Essentials.Room.MobileControl; + +public class ITransportMessenger : MessengerBase { - public class ITransportMessenger : MessengerBase + private readonly ITransport transportDevice; + public ITransportMessenger(string key, string messagePath, ITransport device) : base(key, messagePath, device as IKeyName) { - private readonly ITransport transportDevice; - public ITransportMessenger(string key, string messagePath, ITransport device) : base(key, messagePath, device as IKeyName) - { - transportDevice = device; - } - - protected override void RegisterActions() - { - base.RegisterActions(); + transportDevice = device; + } - AddAction("/play", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Play(b))); - AddAction("/pause", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Pause(b))); - AddAction("/stop", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Stop(b))); - AddAction("/prevTrack", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.ChapPlus(b))); - AddAction("/nextTrack", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.ChapMinus(b))); - AddAction("/rewind", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Rewind(b))); - AddAction("/ffwd", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.FFwd(b))); - AddAction("/record", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Record(b))); - } + protected override void RegisterActions() + { + base.RegisterActions(); + AddAction("/play", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Play(b))); + AddAction("/pause", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Pause(b))); + AddAction("/stop", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Stop(b))); + AddAction("/prevTrack", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.ChapPlus(b))); + AddAction("/nextTrack", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.ChapMinus(b))); + AddAction("/rewind", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Rewind(b))); + AddAction("/ffwd", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.FFwd(b))); + AddAction("/record", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => transportDevice?.Record(b))); } + } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/AudioCodecBaseMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/AudioCodecBaseMessenger.cs index 9a42141ee..c30100ae1 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/AudioCodecBaseMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/AudioCodecBaseMessenger.cs @@ -4,113 +4,112 @@ using System; using System.Linq; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +/// +/// Provides a messaging bridge for an AudioCodecBase device +/// +public class AudioCodecBaseMessenger : MessengerBase { /// - /// Provides a messaging bridge for an AudioCodecBase device + /// Device being bridged + /// + public AudioCodecBase Codec { get; private set; } + + /// + /// Constuctor /// - public class AudioCodecBaseMessenger : MessengerBase + /// + /// + /// + public AudioCodecBaseMessenger(string key, AudioCodecBase codec, string messagePath) + : base(key, messagePath, codec) + { + Codec = codec ?? throw new ArgumentNullException("codec"); + codec.CallStatusChange += Codec_CallStatusChange; + } + + protected override void RegisterActions() + { - /// - /// Device being bridged - /// - public AudioCodecBase Codec { get; private set; } - - /// - /// Constuctor - /// - /// - /// - /// - public AudioCodecBaseMessenger(string key, AudioCodecBase codec, string messagePath) - : base(key, messagePath, codec) + base.RegisterActions(); + + AddAction("/fullStatus", (id, content) => SendAtcFullMessageObject()); + AddAction("/dial", (id, content) => { - Codec = codec ?? throw new ArgumentNullException("codec"); - codec.CallStatusChange += Codec_CallStatusChange; - } + var msg = content.ToObject>(); - protected override void RegisterActions() + Codec.Dial(msg.Value); + }); + AddAction("/endCallById", (id, content) => { - base.RegisterActions(); + var msg = content.ToObject>(); - AddAction("/fullStatus", (id, content) => SendAtcFullMessageObject()); - AddAction("/dial", (id, content) => - { - var msg = content.ToObject>(); + var call = GetCallWithId(msg.Value); + if (call != null) + Codec.EndCall(call); + }); - Codec.Dial(msg.Value); - }); + AddAction("/endAllCalls", (id, content) => Codec.EndAllCalls()); + AddAction("/dtmf", (id, content) => + { + var msg = content.ToObject>(); - AddAction("/endCallById", (id, content) => - { - var msg = content.ToObject>(); + Codec.SendDtmf(msg.Value); + }); - var call = GetCallWithId(msg.Value); - if (call != null) - Codec.EndCall(call); - }); + AddAction("/rejectById", (id, content) => + { + var msg = content.ToObject>(); - AddAction("/endAllCalls", (id, content) => Codec.EndAllCalls()); - AddAction("/dtmf", (id, content) => - { - var msg = content.ToObject>(); + var call = GetCallWithId(msg.Value); - Codec.SendDtmf(msg.Value); - }); + if (call != null) + Codec.RejectCall(call); + }); - AddAction("/rejectById", (id, content) => - { - var msg = content.ToObject>(); + AddAction("/acceptById", (id, content) => + { + var msg = content.ToObject>(); + var call = GetCallWithId(msg.Value); + if (call != null) + Codec.AcceptCall(call); + }); + } - var call = GetCallWithId(msg.Value); + /// + /// Helper to grab a call with string ID + /// + /// + /// + private CodecActiveCallItem GetCallWithId(string id) + { + return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id); + } - if (call != null) - Codec.RejectCall(call); - }); + private void Codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e) + { + SendAtcFullMessageObject(); + } - AddAction("/acceptById", (id, content) => - { - var msg = content.ToObject>(); - var call = GetCallWithId(msg.Value); - if (call != null) - Codec.AcceptCall(call); - }); - } - - /// - /// Helper to grab a call with string ID - /// - /// - /// - private CodecActiveCallItem GetCallWithId(string id) - { - return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id); - } + /// + /// Helper method to build call status for vtc + /// + /// + private void SendAtcFullMessageObject() + { + var info = Codec.CodecInfo; - private void Codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e) - { - SendAtcFullMessageObject(); - } - - /// - /// Helper method to build call status for vtc - /// - /// - private void SendAtcFullMessageObject() + PostStatusMessage(JToken.FromObject(new { - var info = Codec.CodecInfo; - - PostStatusMessage(JToken.FromObject(new + isInCall = Codec.IsInCall, + calls = Codec.ActiveCalls, + info = new { - isInCall = Codec.IsInCall, - calls = Codec.ActiveCalls, - info = new - { - phoneNumber = info.PhoneNumber - } - }) - ); - } + phoneNumber = info.PhoneNumber + } + }) + ); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/CameraBaseMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/CameraBaseMessenger.cs index 36a94781d..69023213d 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/CameraBaseMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/CameraBaseMessenger.cs @@ -4,201 +4,200 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class CameraBaseMessenger : MessengerBase { - public class CameraBaseMessenger : MessengerBase + /// + /// Device being bridged + /// + public CameraBase Camera { get; set; } + + /// + /// Constructor + /// + /// + /// + /// + public CameraBaseMessenger(string key, CameraBase camera, string messagePath) + : base(key, messagePath, camera) { - /// - /// Device being bridged - /// - public CameraBase Camera { get; set; } - - /// - /// Constructor - /// - /// - /// - /// - public CameraBaseMessenger(string key, CameraBase camera, string messagePath) - : base(key, messagePath, camera) - { - Camera = camera ?? throw new ArgumentNullException("camera"); + Camera = camera ?? throw new ArgumentNullException("camera"); - if (Camera is IHasCameraPresets presetsCamera) - { - presetsCamera.PresetsListHasChanged += PresetsCamera_PresetsListHasChanged; - } - } - - private void PresetsCamera_PresetsListHasChanged(object sender, EventArgs e) + if (Camera is IHasCameraPresets presetsCamera) { - var presetList = new List(); + presetsCamera.PresetsListHasChanged += PresetsCamera_PresetsListHasChanged; + } + } - if (Camera is IHasCameraPresets presetsCamera) - presetList = presetsCamera.Presets; + private void PresetsCamera_PresetsListHasChanged(object sender, EventArgs e) + { + var presetList = new List(); - PostStatusMessage(JToken.FromObject(new - { - presets = presetList - }) - ); - } + if (Camera is IHasCameraPresets presetsCamera) + presetList = presetsCamera.Presets; - protected override void RegisterActions() + PostStatusMessage(JToken.FromObject(new { - base.RegisterActions(); + presets = presetList + }) + ); + } - AddAction("/fullStatus", (id, content) => SendCameraFullMessageObject()); + protected override void RegisterActions() + { + base.RegisterActions(); + + AddAction("/fullStatus", (id, content) => SendCameraFullMessageObject()); - if (Camera is IHasCameraPtzControl ptzCamera) + if (Camera is IHasCameraPtzControl ptzCamera) + { + // Need to evaluate how to pass through these P&H actions. Need a method that takes a bool maybe? + AddAction("/cameraUp", (id, content) => HandleCameraPressAndHold(content, (b) => { - // Need to evaluate how to pass through these P&H actions. Need a method that takes a bool maybe? - AddAction("/cameraUp", (id, content) => HandleCameraPressAndHold(content, (b) => - { - if (b) - { - ptzCamera.TiltUp(); - return; - } - - ptzCamera.TiltStop(); - })); - AddAction("/cameraDown", (id, content) => HandleCameraPressAndHold(content, (b) => + if (b) { - if (b) - { - ptzCamera.TiltDown(); - return; - } - - ptzCamera.TiltStop(); - })); - AddAction("/cameraLeft", (id, content) => HandleCameraPressAndHold(content, (b) => - { - if (b) - { - ptzCamera.PanLeft(); - return; - } - - ptzCamera.PanStop(); - })); - AddAction("/cameraRight", (id, content) => HandleCameraPressAndHold(content, (b) => - { - if (b) - { - ptzCamera.PanRight(); - return; - } - - ptzCamera.PanStop(); - })); - AddAction("/cameraZoomIn", (id, content) => HandleCameraPressAndHold(content, (b) => - { - if (b) - { - ptzCamera.ZoomIn(); - return; - } - - ptzCamera.ZoomStop(); - })); - AddAction("/cameraZoomOut", (id, content) => HandleCameraPressAndHold(content, (b) => - { - if (b) - { - ptzCamera.ZoomOut(); - return; - } - - ptzCamera.ZoomStop(); - })); - } + ptzCamera.TiltUp(); + return; + } - if (Camera is IHasCameraAutoMode) + ptzCamera.TiltStop(); + })); + AddAction("/cameraDown", (id, content) => HandleCameraPressAndHold(content, (b) => { - AddAction("/cameraModeAuto", (id, content) => (Camera as IHasCameraAutoMode).CameraAutoModeOn()); - - AddAction("/cameraModeManual", (id, content) => (Camera as IHasCameraAutoMode).CameraAutoModeOff()); - - } + if (b) + { + ptzCamera.TiltDown(); + return; + } - if (Camera is IHasPowerControl) + ptzCamera.TiltStop(); + })); + AddAction("/cameraLeft", (id, content) => HandleCameraPressAndHold(content, (b) => { - AddAction("/cameraModeOff", (id, content) => (Camera as IHasPowerControl).PowerOff()); - AddAction("/cameraModeManual", (id, content) => (Camera as IHasPowerControl).PowerOn()); - } - + if (b) + { + ptzCamera.PanLeft(); + return; + } - if (Camera is IHasCameraPresets presetsCamera) + ptzCamera.PanStop(); + })); + AddAction("/cameraRight", (id, content) => HandleCameraPressAndHold(content, (b) => { - for (int i = 1; i <= 6; i++) + if (b) { - var preset = i; - AddAction("/cameraPreset" + i, (id, content) => - { - var msg = content.ToObject>(); + ptzCamera.PanRight(); + return; + } - presetsCamera.PresetSelect(msg.Value); - }); + ptzCamera.PanStop(); + })); + AddAction("/cameraZoomIn", (id, content) => HandleCameraPressAndHold(content, (b) => + { + if (b) + { + ptzCamera.ZoomIn(); + return; + } + ptzCamera.ZoomStop(); + })); + AddAction("/cameraZoomOut", (id, content) => HandleCameraPressAndHold(content, (b) => + { + if (b) + { + ptzCamera.ZoomOut(); + return; } - } + + ptzCamera.ZoomStop(); + })); } - private void HandleCameraPressAndHold(JToken content, Action cameraAction) + if (Camera is IHasCameraAutoMode) { - var state = content.ToObject>(); + AddAction("/cameraModeAuto", (id, content) => (Camera as IHasCameraAutoMode).CameraAutoModeOn()); - var timerHandler = PressAndHoldHandler.GetPressAndHoldHandler(state.Value); - if (timerHandler == null) - { - return; - } + AddAction("/cameraModeManual", (id, content) => (Camera as IHasCameraAutoMode).CameraAutoModeOff()); - timerHandler(state.Value, cameraAction); - - cameraAction(state.Value.Equals("true", StringComparison.InvariantCultureIgnoreCase)); } - /// - /// Helper method to update the full status of the camera - /// - private void SendCameraFullMessageObject() + if (Camera is IHasPowerControl) { - var presetList = new List(); + AddAction("/cameraModeOff", (id, content) => (Camera as IHasPowerControl).PowerOff()); + AddAction("/cameraModeManual", (id, content) => (Camera as IHasPowerControl).PowerOn()); + } - if (Camera is IHasCameraPresets presetsCamera) - presetList = presetsCamera.Presets; - PostStatusMessage(JToken.FromObject(new + if (Camera is IHasCameraPresets presetsCamera) + { + for (int i = 1; i <= 6; i++) { - cameraManualSupported = Camera is IHasCameraControls, - cameraAutoSupported = Camera is IHasCameraAutoMode, - cameraOffSupported = Camera is IHasCameraOff, - cameraMode = GetCameraMode(), - hasPresets = Camera is IHasCameraPresets, - presets = presetList - }) - ); + var preset = i; + AddAction("/cameraPreset" + i, (id, content) => + { + var msg = content.ToObject>(); + + presetsCamera.PresetSelect(msg.Value); + }); + + } } + } + + private void HandleCameraPressAndHold(JToken content, Action cameraAction) + { + var state = content.ToObject>(); - /// - /// Computes the current camera mode - /// - /// - private string GetCameraMode() + var timerHandler = PressAndHoldHandler.GetPressAndHoldHandler(state.Value); + if (timerHandler == null) { - string m; - if (Camera is IHasCameraAutoMode && (Camera as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.BoolValue) - m = eCameraControlMode.Auto.ToString().ToLower(); - else if (Camera is IHasPowerControlWithFeedback && !(Camera as IHasPowerControlWithFeedback).PowerIsOnFeedback.BoolValue) - m = eCameraControlMode.Off.ToString().ToLower(); - else - m = eCameraControlMode.Manual.ToString().ToLower(); - return m; + return; } + + timerHandler(state.Value, cameraAction); + + cameraAction(state.Value.Equals("true", StringComparison.InvariantCultureIgnoreCase)); + } + + /// + /// Helper method to update the full status of the camera + /// + private void SendCameraFullMessageObject() + { + var presetList = new List(); + + if (Camera is IHasCameraPresets presetsCamera) + presetList = presetsCamera.Presets; + + PostStatusMessage(JToken.FromObject(new + { + cameraManualSupported = Camera is IHasCameraControls, + cameraAutoSupported = Camera is IHasCameraAutoMode, + cameraOffSupported = Camera is IHasCameraOff, + cameraMode = GetCameraMode(), + hasPresets = Camera is IHasCameraPresets, + presets = presetList + }) + ); + } + + /// + /// Computes the current camera mode + /// + /// + private string GetCameraMode() + { + string m; + if (Camera is IHasCameraAutoMode && (Camera as IHasCameraAutoMode).CameraAutoModeIsOnFeedback.BoolValue) + m = eCameraControlMode.Auto.ToString().ToLower(); + else if (Camera is IHasPowerControlWithFeedback && !(Camera as IHasPowerControlWithFeedback).PowerIsOnFeedback.BoolValue) + m = eCameraControlMode.Off.ToString().ToLower(); + else + m = eCameraControlMode.Manual.ToString().ToLower(); + return m; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/DeviceInfoMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/DeviceInfoMessenger.cs index c588195ee..58ea373d4 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/DeviceInfoMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/DeviceInfoMessenger.cs @@ -4,87 +4,86 @@ using PepperDash.Essentials.Core.DeviceInfo; using System.Timers; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +/// +/// Facilitates communication of device information by providing mechanisms for status updates and device +/// information reporting. +/// +/// The class integrates with an to manage device-specific information. It uses a debounce timer to limit the +/// frequency of updates, ensuring efficient communication. The timer is initialized with a 1-second interval and +/// is disabled by default. This class also subscribes to device information change events and provides actions for +/// reporting full device status and triggering updates. +public class DeviceInfoMessenger : MessengerBase { - /// - /// Facilitates communication of device information by providing mechanisms for status updates and device - /// information reporting. - /// - /// The class integrates with an to manage device-specific information. It uses a debounce timer to limit the - /// frequency of updates, ensuring efficient communication. The timer is initialized with a 1-second interval and - /// is disabled by default. This class also subscribes to device information change events and provides actions for - /// reporting full device status and triggering updates. - public class DeviceInfoMessenger : MessengerBase - { - private readonly IDeviceInfoProvider _deviceInfoProvider; + private readonly IDeviceInfoProvider _deviceInfoProvider; - private readonly Timer debounceTimer; + private readonly Timer debounceTimer; - /// - /// Initializes a new instance of the class, which facilitates communication - /// of device information. - /// - /// The messenger uses a debounce timer to limit the frequency of certain operations. The - /// timer is initialized with a 1-second interval and is disabled by default. - /// A unique identifier for the messenger instance. - /// The path used for sending and receiving messages. - /// An implementation of that provides device-specific information. - public DeviceInfoMessenger(string key, string messagePath, IDeviceInfoProvider device) : base(key, messagePath, device as Device) - { - _deviceInfoProvider = device; + /// + /// Initializes a new instance of the class, which facilitates communication + /// of device information. + /// + /// The messenger uses a debounce timer to limit the frequency of certain operations. The + /// timer is initialized with a 1-second interval and is disabled by default. + /// A unique identifier for the messenger instance. + /// The path used for sending and receiving messages. + /// An implementation of that provides device-specific information. + public DeviceInfoMessenger(string key, string messagePath, IDeviceInfoProvider device) : base(key, messagePath, device as Device) + { + _deviceInfoProvider = device; - debounceTimer = new Timer(1000) - { - Enabled = false, - AutoReset = false - }; + debounceTimer = new Timer(1000) + { + Enabled = false, + AutoReset = false + }; - debounceTimer.Elapsed += DebounceTimer_Elapsed; - } + debounceTimer.Elapsed += DebounceTimer_Elapsed; + } - private void DebounceTimer_Elapsed(object sender, ElapsedEventArgs e) + private void DebounceTimer_Elapsed(object sender, ElapsedEventArgs e) + { + PostStatusMessage(JToken.FromObject(new { - PostStatusMessage(JToken.FromObject(new - { - deviceInfo = _deviceInfoProvider.DeviceInfo - })); - } + deviceInfo = _deviceInfoProvider.DeviceInfo + })); + } - /// - /// Registers actions and event handlers for device information updates and status reporting. - /// - /// This method sets up actions for handling device status updates and reporting full - /// device status. It also subscribes to the event to - /// trigger debounced updates when the device information changes. - protected override void RegisterActions() - { - base.RegisterActions(); + /// + /// Registers actions and event handlers for device information updates and status reporting. + /// + /// This method sets up actions for handling device status updates and reporting full + /// device status. It also subscribes to the event to + /// trigger debounced updates when the device information changes. + protected override void RegisterActions() + { + base.RegisterActions(); - _deviceInfoProvider.DeviceInfoChanged += (o, a) => - { - debounceTimer.Stop(); - debounceTimer.Start(); - }; + _deviceInfoProvider.DeviceInfoChanged += (o, a) => + { + debounceTimer.Stop(); + debounceTimer.Start(); + }; - AddAction("/fullStatus", (id, context) => PostStatusMessage(new DeviceInfoStateMessage - { - DeviceInfo = _deviceInfoProvider.DeviceInfo - })); + AddAction("/fullStatus", (id, context) => PostStatusMessage(new DeviceInfoStateMessage + { + DeviceInfo = _deviceInfoProvider.DeviceInfo + })); - AddAction("/update", (id, context) => _deviceInfoProvider.UpdateDeviceInfo()); - } + AddAction("/update", (id, context) => _deviceInfoProvider.UpdateDeviceInfo()); } +} - /// - /// Represents a message containing the state information of a device, including detailed device information. - /// - /// This class is used to encapsulate the state of a device along with its associated - /// information. It extends to provide additional details about the - /// device. - public class DeviceInfoStateMessage : DeviceStateMessageBase - { - [JsonProperty("deviceInfo")] - public DeviceInfo DeviceInfo { get; set; } - } +/// +/// Represents a message containing the state information of a device, including detailed device information. +/// +/// This class is used to encapsulate the state of a device along with its associated +/// information. It extends to provide additional details about the +/// device. +public class DeviceInfoStateMessage : DeviceStateMessageBase +{ + [JsonProperty("deviceInfo")] + public DeviceInfo DeviceInfo { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/DevicePresetsModelMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/DevicePresetsModelMessenger.cs index 91b87a83e..3eff389dc 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/DevicePresetsModelMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/DevicePresetsModelMessenger.cs @@ -7,94 +7,93 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class DevicePresetsModelMessenger : MessengerBase { - public class DevicePresetsModelMessenger : MessengerBase - { - private readonly ITvPresetsProvider _presetsDevice; + private readonly ITvPresetsProvider _presetsDevice; - public DevicePresetsModelMessenger(string key, string messagePath, ITvPresetsProvider presetsDevice) - : base(key, messagePath, presetsDevice as Device) - { - _presetsDevice = presetsDevice; - } + public DevicePresetsModelMessenger(string key, string messagePath, ITvPresetsProvider presetsDevice) + : base(key, messagePath, presetsDevice as Device) + { + _presetsDevice = presetsDevice; + } - private void SendPresets() + private void SendPresets() + { + PostStatusMessage(new PresetStateMessage { - PostStatusMessage(new PresetStateMessage - { - Favorites = _presetsDevice.TvPresets.PresetsList - }); - } + Favorites = _presetsDevice.TvPresets.PresetsList + }); + } - private void RecallPreset(ISetTopBoxNumericKeypad device, string channel) - { - _presetsDevice.TvPresets.Dial(channel, device); - } + private void RecallPreset(ISetTopBoxNumericKeypad device, string channel) + { + _presetsDevice.TvPresets.Dial(channel, device); + } - private void SavePresets(List presets) - { - _presetsDevice.TvPresets.UpdatePresets(presets); - } + private void SavePresets(List presets) + { + _presetsDevice.TvPresets.UpdatePresets(presets); + } - #region Overrides of MessengerBase + #region Overrides of MessengerBase - protected override void RegisterActions() + protected override void RegisterActions() + { + AddAction("/fullStatus", (id, content) => { - AddAction("/fullStatus", (id, content) => + this.LogInformation("getting full status for client {id}", id); + try { - this.LogInformation("getting full status for client {id}", id); - try - { - SendPresets(); - } - catch (Exception ex) - { - Debug.LogMessage(ex, "Exception sending preset full status", this); - } - }); - - AddAction("/recall", (id, content) => + SendPresets(); + } + catch (Exception ex) { - var p = content.ToObject(); + Debug.LogMessage(ex, "Exception sending preset full status", this); + } + }); + AddAction("/recall", (id, content) => + { + var p = content.ToObject(); - if (!(DeviceManager.GetDeviceForKey(p.DeviceKey) is ISetTopBoxNumericKeypad dev)) - { - this.LogDebug("Unable to find device with key {0}", p.DeviceKey); - return; - } - - RecallPreset(dev, p.Preset.Channel); - }); - AddAction("/save", (id, content) => + if (!(DeviceManager.GetDeviceForKey(p.DeviceKey) is ISetTopBoxNumericKeypad dev)) { - var presets = content.ToObject>(); + this.LogDebug("Unable to find device with key {0}", p.DeviceKey); + return; + } - SavePresets(presets); - }); + RecallPreset(dev, p.Preset.Channel); + }); - _presetsDevice.TvPresets.PresetsSaved += (p) => SendPresets(); - } + AddAction("/save", (id, content) => + { + var presets = content.ToObject>(); + + SavePresets(presets); + }); - #endregion + _presetsDevice.TvPresets.PresetsSaved += (p) => SendPresets(); } - public class PresetChannelMessage - { - [JsonProperty("preset")] - public PresetChannel Preset; + #endregion +} - [JsonProperty("deviceKey")] - public string DeviceKey; - } +public class PresetChannelMessage +{ + [JsonProperty("preset")] + public PresetChannel Preset; - public class PresetStateMessage : DeviceStateMessageBase - { - [JsonProperty("favorites", NullValueHandling = NullValueHandling.Ignore)] - public List Favorites { get; set; } = new List(); - } + [JsonProperty("deviceKey")] + public string DeviceKey; +} + +public class PresetStateMessage : DeviceStateMessageBase +{ + [JsonProperty("favorites", NullValueHandling = NullValueHandling.Ignore)] + public List Favorites { get; set; } = new List(); } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/DeviceVolumeMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/DeviceVolumeMessenger.cs index 22f837c3a..8e0015c74 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/DeviceVolumeMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/DeviceVolumeMessenger.cs @@ -5,168 +5,167 @@ using PepperDash.Essentials.Core; using System; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class DeviceVolumeMessenger : MessengerBase { - public class DeviceVolumeMessenger : MessengerBase - { - private readonly IBasicVolumeWithFeedback _localDevice; + private readonly IBasicVolumeWithFeedback _localDevice; - public DeviceVolumeMessenger(string key, string messagePath, IBasicVolumeWithFeedback device) - : base(key, messagePath, device as IKeyName) - { - _localDevice = device; - } + public DeviceVolumeMessenger(string key, string messagePath, IBasicVolumeWithFeedback device) + : base(key, messagePath, device as IKeyName) + { + _localDevice = device; + } - private void SendStatus() + private void SendStatus() + { + try { - try + var messageObj = new VolumeStateMessage { - var messageObj = new VolumeStateMessage + Volume = new Volume { - Volume = new Volume - { - Level = _localDevice?.VolumeLevelFeedback.IntValue ?? -1, - Muted = _localDevice?.MuteFeedback.BoolValue ?? false, - HasMute = true, // assume all devices have mute for now - } - }; - - if (_localDevice is IBasicVolumeWithFeedbackAdvanced volumeAdvanced) - { - messageObj.Volume.RawValue = volumeAdvanced.RawVolumeLevel.ToString(); - messageObj.Volume.Units = volumeAdvanced.Units; + Level = _localDevice?.VolumeLevelFeedback.IntValue ?? -1, + Muted = _localDevice?.MuteFeedback.BoolValue ?? false, + HasMute = true, // assume all devices have mute for now } + }; - PostStatusMessage(messageObj); - } - catch (Exception ex) + if (_localDevice is IBasicVolumeWithFeedbackAdvanced volumeAdvanced) { - Debug.LogMessage(ex, "Exception sending full status", this); + messageObj.Volume.RawValue = volumeAdvanced.RawVolumeLevel.ToString(); + messageObj.Volume.Units = volumeAdvanced.Units; } + + PostStatusMessage(messageObj); + } + catch (Exception ex) + { + Debug.LogMessage(ex, "Exception sending full status", this); } + } + + #region Overrides of MessengerBase - #region Overrides of MessengerBase + protected override void RegisterActions() + { + AddAction("/fullStatus", (id, content) => SendStatus()); - protected override void RegisterActions() + AddAction("/level", (id, content) => { - AddAction("/fullStatus", (id, content) => SendStatus()); + var volume = content.ToObject>(); - AddAction("/level", (id, content) => - { - var volume = content.ToObject>(); + _localDevice.SetVolume(volume.Value); + }); - _localDevice.SetVolume(volume.Value); - }); + AddAction("/muteToggle", (id, content) => + { + _localDevice.MuteToggle(); + }); - AddAction("/muteToggle", (id, content) => - { - _localDevice.MuteToggle(); - }); + AddAction("/muteOn", (id, content) => + { + _localDevice.MuteOn(); + }); - AddAction("/muteOn", (id, content) => - { - _localDevice.MuteOn(); - }); + AddAction("/muteOff", (id, content) => + { + _localDevice.MuteOff(); + }); - AddAction("/muteOff", (id, content) => + AddAction("/volumeUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Calling {localDevice} volume up with {value}", DeviceKey, b); + try { - _localDevice.MuteOff(); - }); - - AddAction("/volumeUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => + _localDevice.VolumeUp(b); + } + catch (Exception ex) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Calling {localDevice} volume up with {value}", DeviceKey, b); - try - { - _localDevice.VolumeUp(b); - } - catch (Exception ex) - { - Debug.LogMessage(ex, "Got exception during volume up: {Exception}", null, ex); - } - })); + Debug.LogMessage(ex, "Got exception during volume up: {Exception}", null, ex); + } + })); - AddAction("/volumeDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => + AddAction("/volumeDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Calling {localDevice} volume down with {value}", DeviceKey, b); + + try + { + _localDevice.VolumeDown(b); + } + catch (Exception ex) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Calling {localDevice} volume down with {value}", DeviceKey, b); + Debug.LogMessage(ex, "Got exception during volume down: {Exception}", null, ex); + } + })); - try - { - _localDevice.VolumeDown(b); - } - catch (Exception ex) - { - Debug.LogMessage(ex, "Got exception during volume down: {Exception}", null, ex); - } - })); + _localDevice.MuteFeedback.OutputChange += (sender, args) => + { + PostStatusMessage(JToken.FromObject( + new + { + volume = new + { + muted = args.BoolValue + } + }) + ); + }; - _localDevice.MuteFeedback.OutputChange += (sender, args) => + _localDevice.VolumeLevelFeedback.OutputChange += (sender, args) => + { + var rawValue = ""; + if (_localDevice is IBasicVolumeWithFeedbackAdvanced volumeAdvanced) { - PostStatusMessage(JToken.FromObject( - new - { - volume = new - { - muted = args.BoolValue - } - }) - ); - }; + rawValue = volumeAdvanced.RawVolumeLevel.ToString(); + } - _localDevice.VolumeLevelFeedback.OutputChange += (sender, args) => + var message = new { - var rawValue = ""; - if (_localDevice is IBasicVolumeWithFeedbackAdvanced volumeAdvanced) + volume = new { - rawValue = volumeAdvanced.RawVolumeLevel.ToString(); + level = args.IntValue, + rawValue } - - var message = new - { - volume = new - { - level = args.IntValue, - rawValue - } - }; - - PostStatusMessage(JToken.FromObject(message)); }; + PostStatusMessage(JToken.FromObject(message)); + }; - } - #endregion } - public class VolumeStateMessage : DeviceStateMessageBase - { - [JsonProperty("volume", NullValueHandling = NullValueHandling.Ignore)] - public Volume Volume { get; set; } - } + #endregion +} - public class Volume - { - [JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)] - public int? Level { get; set; } +public class VolumeStateMessage : DeviceStateMessageBase +{ + [JsonProperty("volume", NullValueHandling = NullValueHandling.Ignore)] + public Volume Volume { get; set; } +} + +public class Volume +{ + [JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)] + public int? Level { get; set; } - [JsonProperty("hasMute", NullValueHandling = NullValueHandling.Ignore)] - public bool? HasMute { get; set; } + [JsonProperty("hasMute", NullValueHandling = NullValueHandling.Ignore)] + public bool? HasMute { get; set; } - [JsonProperty("muted", NullValueHandling = NullValueHandling.Ignore)] - public bool? Muted { get; set; } + [JsonProperty("muted", NullValueHandling = NullValueHandling.Ignore)] + public bool? Muted { get; set; } - [JsonProperty("label", NullValueHandling = NullValueHandling.Ignore)] - public string Label { get; set; } + [JsonProperty("label", NullValueHandling = NullValueHandling.Ignore)] + public string Label { get; set; } - [JsonProperty("rawValue", NullValueHandling = NullValueHandling.Ignore)] - public string RawValue { get; set; } + [JsonProperty("rawValue", NullValueHandling = NullValueHandling.Ignore)] + public string RawValue { get; set; } - [JsonConverter(typeof(StringEnumConverter))] - [JsonProperty("units", NullValueHandling = NullValueHandling.Ignore)] - public eVolumeLevelUnits? Units { get; set; } - } + [JsonConverter(typeof(StringEnumConverter))] + [JsonProperty("units", NullValueHandling = NullValueHandling.Ignore)] + public eVolumeLevelUnits? Units { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/GenericMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/GenericMessenger.cs index 64624bfa7..c76b9adc0 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/GenericMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/GenericMessenger.cs @@ -1,25 +1,24 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class GenericMessenger : MessengerBase { - public class GenericMessenger : MessengerBase + public GenericMessenger(string key, EssentialsDevice device, string messagePath) : base(key, messagePath, device) { - public GenericMessenger(string key, EssentialsDevice device, string messagePath) : base(key, messagePath, device) - { - } + } - protected override void RegisterActions() - { - base.RegisterActions(); + protected override void RegisterActions() + { + base.RegisterActions(); - AddAction("/fullStatus", (id, content) => SendFullStatus()); - } + AddAction("/fullStatus", (id, content) => SendFullStatus()); + } - private void SendFullStatus() - { - var state = new DeviceStateMessageBase(); + private void SendFullStatus() + { + var state = new DeviceStateMessageBase(); - PostStatusMessage(state); - } + PostStatusMessage(state); } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ICommunicationMonitorMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ICommunicationMonitorMessenger.cs index 5ab81832a..013e8047a 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ICommunicationMonitorMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ICommunicationMonitorMessenger.cs @@ -4,71 +4,69 @@ using PepperDash.Core; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class ICommunicationMonitorMessenger : MessengerBase { - public class ICommunicationMonitorMessenger : MessengerBase + private readonly ICommunicationMonitor _communicationMonitor; + + public ICommunicationMonitorMessenger(string key, string messagePath, ICommunicationMonitor device) : base(key, messagePath, device as IKeyName) { - private readonly ICommunicationMonitor _communicationMonitor; + _communicationMonitor = device; + } - public ICommunicationMonitorMessenger(string key, string messagePath, ICommunicationMonitor device) : base(key, messagePath, device as IKeyName) - { - _communicationMonitor = device; - } + protected override void RegisterActions() + { + base.RegisterActions(); - protected override void RegisterActions() + AddAction("/fullStatus", (id, content) => { - base.RegisterActions(); - - AddAction("/fullStatus", (id, content) => + PostStatusMessage(new CommunicationMonitorState { - PostStatusMessage(new CommunicationMonitorState + CommunicationMonitor = new CommunicationMonitorProps { - CommunicationMonitor = new CommunicationMonitorProps - { - IsOnline = _communicationMonitor.CommunicationMonitor.IsOnline, - Status = _communicationMonitor.CommunicationMonitor.Status - } - }); + IsOnline = _communicationMonitor.CommunicationMonitor.IsOnline, + Status = _communicationMonitor.CommunicationMonitor.Status + } }); + }); - _communicationMonitor.CommunicationMonitor.StatusChange += (sender, args) => + _communicationMonitor.CommunicationMonitor.StatusChange += (sender, args) => + { + PostStatusMessage(JToken.FromObject(new { - PostStatusMessage(JToken.FromObject(new + commMonitor = new CommunicationMonitorProps { - commMonitor = new CommunicationMonitorProps - { - IsOnline = _communicationMonitor.CommunicationMonitor.IsOnline, - Status = _communicationMonitor.CommunicationMonitor.Status - } - })); - }; - } + IsOnline = _communicationMonitor.CommunicationMonitor.IsOnline, + Status = _communicationMonitor.CommunicationMonitor.Status + } + })); + }; } +} - /// - /// Represents the state of the communication monitor - /// - public class CommunicationMonitorState : DeviceStateMessageBase - { - [JsonProperty("commMonitor", NullValueHandling = NullValueHandling.Ignore)] - public CommunicationMonitorProps CommunicationMonitor { get; set; } - - } +/// +/// Represents the state of the communication monitor +/// +public class CommunicationMonitorState : DeviceStateMessageBase +{ + [JsonProperty("commMonitor", NullValueHandling = NullValueHandling.Ignore)] + public CommunicationMonitorProps CommunicationMonitor { get; set; } - public class CommunicationMonitorProps - { /// - /// For devices that implement ICommunicationMonitor, reports the online status of the device - /// - [JsonProperty("isOnline", NullValueHandling = NullValueHandling.Ignore)] - public bool? IsOnline { get; set; } +} - /// - /// For devices that implement ICommunicationMonitor, reports the online status of the device - /// - [JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)] - [JsonConverter(typeof(StringEnumConverter))] - public MonitorStatus Status { get; set; } +public class CommunicationMonitorProps +{ /// + /// For devices that implement ICommunicationMonitor, reports the online status of the device + /// + [JsonProperty("isOnline", NullValueHandling = NullValueHandling.Ignore)] + public bool? IsOnline { get; set; } - } + /// + /// For devices that implement ICommunicationMonitor, reports the online status of the device + /// + [JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)] + [JsonConverter(typeof(StringEnumConverter))] + public MonitorStatus Status { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IDspPresetsMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IDspPresetsMessenger.cs index e40cd8eb5..f4c8513e2 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IDspPresetsMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IDspPresetsMessenger.cs @@ -3,48 +3,47 @@ using PepperDash.Essentials.Core; using System.Collections.Generic; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class IDspPresetsMessenger : MessengerBase { - public class IDspPresetsMessenger : MessengerBase + private readonly IDspPresets device; + + public IDspPresetsMessenger(string key, string messagePath, IDspPresets device) + : base(key, messagePath, device as IKeyName) { - private readonly IDspPresets device; + this.device = device; + } - public IDspPresetsMessenger(string key, string messagePath, IDspPresets device) - : base(key, messagePath, device as IKeyName) - { - this.device = device; - } + protected override void RegisterActions() + { + base.RegisterActions(); - protected override void RegisterActions() + AddAction("/fullStatus", (id, content) => { - base.RegisterActions(); - - AddAction("/fullStatus", (id, content) => + var message = new IHasDspPresetsStateMessage { - var message = new IHasDspPresetsStateMessage - { - Presets = device.Presets - }; + Presets = device.Presets + }; - PostStatusMessage(message); - }); + PostStatusMessage(message); + }); - AddAction("/recallPreset", (id, content) => - { - var presetKey = content.ToObject(); + AddAction("/recallPreset", (id, content) => + { + var presetKey = content.ToObject(); - if (!string.IsNullOrEmpty(presetKey)) - { - device.RecallPreset(presetKey); - } - }); - } + if (!string.IsNullOrEmpty(presetKey)) + { + device.RecallPreset(presetKey); + } + }); } +} - public class IHasDspPresetsStateMessage : DeviceStateMessageBase - { - [JsonProperty("presets")] - public Dictionary Presets { get; set; } - } +public class IHasDspPresetsStateMessage : DeviceStateMessageBase +{ + [JsonProperty("presets")] + public Dictionary Presets { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IEssentialsRoomCombinerMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IEssentialsRoomCombinerMessenger.cs index 1752b5672..20a6ec927 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IEssentialsRoomCombinerMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IEssentialsRoomCombinerMessenger.cs @@ -6,204 +6,201 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +/// +/// Provides messaging functionality for managing room combination scenarios and partition states in an instance. Enables external systems to interact with the room combiner via +/// predefined actions and status updates. +/// +/// This class facilitates communication with an by +/// exposing actions for toggling modes, managing partitions, and setting room combination scenarios. It also +/// listens for feedback changes and broadcasts status updates to connected systems. Typical usage involves +/// registering actions for external commands and handling feedback events to synchronize state changes. +public class IEssentialsRoomCombinerMessenger : MessengerBase { + private readonly IEssentialsRoomCombiner _roomCombiner; + + /// + /// Initializes a new instance of the class, which facilitates + /// messaging for an instance. + /// + /// This class is designed to enable communication and interaction with an through the specified messaging path. Ensure that the parameter is not null when creating an instance. + /// The unique key identifying this messenger instance. + /// The path used for messaging operations. + /// The instance associated with this messenger. + public IEssentialsRoomCombinerMessenger(string key, string messagePath, IEssentialsRoomCombiner roomCombiner) + : base(key, messagePath, roomCombiner as IKeyName) + { + _roomCombiner = roomCombiner; + } + /// - /// Provides messaging functionality for managing room combination scenarios and partition states in an instance. Enables external systems to interact with the room combiner via - /// predefined actions and status updates. + /// Registers actions and event handlers for managing room combination scenarios and partition states. /// - /// This class facilitates communication with an by - /// exposing actions for toggling modes, managing partitions, and setting room combination scenarios. It also - /// listens for feedback changes and broadcasts status updates to connected systems. Typical usage involves - /// registering actions for external commands and handling feedback events to synchronize state changes. - public class IEssentialsRoomCombinerMessenger : MessengerBase + /// This method sets up various actions that can be triggered via specific endpoints, + /// such as toggling modes, setting room combination scenarios, and managing partition states. It also + /// subscribes to feedback events to update the status when changes occur in room combination scenarios or + /// partition states. + protected override void RegisterActions() { - private readonly IEssentialsRoomCombiner _roomCombiner; - - /// - /// Initializes a new instance of the class, which facilitates - /// messaging for an instance. - /// - /// This class is designed to enable communication and interaction with an through the specified messaging path. Ensure that the parameter is not null when creating an instance. - /// The unique key identifying this messenger instance. - /// The path used for messaging operations. - /// The instance associated with this messenger. - public IEssentialsRoomCombinerMessenger(string key, string messagePath, IEssentialsRoomCombiner roomCombiner) - : base(key, messagePath, roomCombiner as IKeyName) + AddAction("/fullStatus", (id, content) => SendFullStatus()); + + AddAction("/setAutoMode", (id, content) => { - _roomCombiner = roomCombiner; - } + _roomCombiner.SetAutoMode(); + }); - /// - /// Registers actions and event handlers for managing room combination scenarios and partition states. - /// - /// This method sets up various actions that can be triggered via specific endpoints, - /// such as toggling modes, setting room combination scenarios, and managing partition states. It also - /// subscribes to feedback events to update the status when changes occur in room combination scenarios or - /// partition states. - protected override void RegisterActions() + AddAction("/setManualMode", (id, content) => { - AddAction("/fullStatus", (id, content) => SendFullStatus()); + _roomCombiner.SetManualMode(); + }); - AddAction("/setAutoMode", (id, content) => - { - _roomCombiner.SetAutoMode(); - }); + AddAction("/toggleMode", (id, content) => + { + _roomCombiner.ToggleMode(); + }); - AddAction("/setManualMode", (id, content) => + AddAction("/togglePartitionState", (id, content) => + { + try { - _roomCombiner.SetManualMode(); - }); + var partitionKey = content.ToObject(); - AddAction("/toggleMode", (id, content) => + _roomCombiner.TogglePartitionState(partitionKey); + } + catch (Exception e) { - _roomCombiner.ToggleMode(); - }); + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Error toggling partition state: {e}", this); + } + }); - AddAction("/togglePartitionState", (id, content) => + AddAction("/setRoomCombinationScenario", (id, content) => + { + try { - try - { - var partitionKey = content.ToObject(); - - _roomCombiner.TogglePartitionState(partitionKey); - } - catch (Exception e) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Error toggling partition state: {e}", this); - } - }); + var scenarioKey = content.ToObject(); - AddAction("/setRoomCombinationScenario", (id, content) => + _roomCombiner.SetRoomCombinationScenario(scenarioKey); + } + catch (Exception e) { - try - { - var scenarioKey = content.ToObject(); + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Error toggling partition state: {e}", this); + } + }); - _roomCombiner.SetRoomCombinationScenario(scenarioKey); - } - catch (Exception e) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Error toggling partition state: {e}", this); - } - }); + _roomCombiner.RoomCombinationScenarioChanged += (sender, args) => + { + SendFullStatus(); + }; - _roomCombiner.RoomCombinationScenarioChanged += (sender, args) => + _roomCombiner.IsInAutoModeFeedback.OutputChange += (sender, args) => + { + var message = new { - SendFullStatus(); + isInAutoMode = _roomCombiner.IsInAutoModeFeedback.BoolValue }; - _roomCombiner.IsInAutoModeFeedback.OutputChange += (sender, args) => + PostStatusMessage(JToken.FromObject(message)); + }; + + foreach (var partition in _roomCombiner.Partitions) + { + partition.PartitionPresentFeedback.OutputChange += (sender, args) => { var message = new { - isInAutoMode = _roomCombiner.IsInAutoModeFeedback.BoolValue + partitions = _roomCombiner.Partitions }; PostStatusMessage(JToken.FromObject(message)); }; - - foreach (var partition in _roomCombiner.Partitions) - { - partition.PartitionPresentFeedback.OutputChange += (sender, args) => - { - var message = new - { - partitions = _roomCombiner.Partitions - }; - - PostStatusMessage(JToken.FromObject(message)); - }; - } } + } - private void SendFullStatus() + private void SendFullStatus() + { + try { - try - { - var rooms = new List(); + var rooms = new List(); - foreach (var room in _roomCombiner.Rooms) - { - rooms.Add(new RoomCombinerRoom { Key = room.Key, Name = room.Name }); - } - - var message = new IEssentialsRoomCombinerStateMessage - { - DisableAutoMode = _roomCombiner.DisableAutoMode, - IsInAutoMode = _roomCombiner.IsInAutoMode, - CurrentScenario = _roomCombiner.CurrentScenario, - Rooms = rooms, - RoomCombinationScenarios = _roomCombiner.RoomCombinationScenarios, - Partitions = _roomCombiner.Partitions - }; - - PostStatusMessage(message); - } - catch (Exception e) + foreach (var room in _roomCombiner.Rooms) { - this.LogException(e, "Error sending full status"); + rooms.Add(new RoomCombinerRoom { Key = room.Key, Name = room.Name }); } - } - private class RoomCombinerRoom : IKeyName - { - [JsonProperty("key")] - public string Key { get; set; } + var message = new IEssentialsRoomCombinerStateMessage + { + DisableAutoMode = _roomCombiner.DisableAutoMode, + IsInAutoMode = _roomCombiner.IsInAutoMode, + CurrentScenario = _roomCombiner.CurrentScenario, + Rooms = rooms, + RoomCombinationScenarios = _roomCombiner.RoomCombinationScenarios, + Partitions = _roomCombiner.Partitions + }; - [JsonProperty("name")] - public string Name { get; set; } + PostStatusMessage(message); + } + catch (Exception e) + { + this.LogException(e, "Error sending full status"); } } - /// - /// Represents the state message for a room combiner system, providing information about the current configuration, - /// operational mode, and associated rooms, partitions, and scenarios. - /// - /// This class is used to encapsulate the state of a room combiner system, including its current - /// mode of operation, active room combination scenario, and the list of rooms and partitions involved. It is - /// typically serialized and transmitted to communicate the state of the system. - public class IEssentialsRoomCombinerStateMessage : DeviceStateMessageBase + private class RoomCombinerRoom : IKeyName { - /// - /// Gets or sets a value indicating whether automatic mode is disabled. - /// - [JsonProperty("disableAutoMode", NullValueHandling = NullValueHandling.Ignore)] - public bool DisableAutoMode { get; set; } - - /// - /// Gets or sets a value indicating whether the system is operating in automatic mode. - /// - [JsonProperty("isInAutoMode", NullValueHandling = NullValueHandling.Ignore)] - public bool IsInAutoMode { get; set; } - - /// - /// Gets or sets the current room combination scenario. - /// - [JsonProperty("currentScenario", NullValueHandling = NullValueHandling.Ignore)] - public IRoomCombinationScenario CurrentScenario { get; set; } - - /// - /// Gets or sets the collection of rooms associated with the entity. - /// - [JsonProperty("rooms", NullValueHandling = NullValueHandling.Ignore)] - public List Rooms { get; set; } - - /// - /// Gets or sets the collection of room combination scenarios. - /// - [JsonProperty("roomCombinationScenarios", NullValueHandling = NullValueHandling.Ignore)] - public List RoomCombinationScenarios { get; set; } - - /// - /// Gets or sets the collection of partition controllers. - /// - [JsonProperty("partitions", NullValueHandling = NullValueHandling.Ignore)] - public List Partitions { get; set; } + [JsonProperty("key")] + public string Key { get; set; } + + [JsonProperty("name")] + public string Name { get; set; } } +} + +/// +/// Represents the state message for a room combiner system, providing information about the current configuration, +/// operational mode, and associated rooms, partitions, and scenarios. +/// +/// This class is used to encapsulate the state of a room combiner system, including its current +/// mode of operation, active room combination scenario, and the list of rooms and partitions involved. It is +/// typically serialized and transmitted to communicate the state of the system. +public class IEssentialsRoomCombinerStateMessage : DeviceStateMessageBase +{ + /// + /// Gets or sets a value indicating whether automatic mode is disabled. + /// + [JsonProperty("disableAutoMode", NullValueHandling = NullValueHandling.Ignore)] + public bool DisableAutoMode { get; set; } + + /// + /// Gets or sets a value indicating whether the system is operating in automatic mode. + /// + [JsonProperty("isInAutoMode", NullValueHandling = NullValueHandling.Ignore)] + public bool IsInAutoMode { get; set; } + + /// + /// Gets or sets the current room combination scenario. + /// + [JsonProperty("currentScenario", NullValueHandling = NullValueHandling.Ignore)] + public IRoomCombinationScenario CurrentScenario { get; set; } + /// + /// Gets or sets the collection of rooms associated with the entity. + /// + [JsonProperty("rooms", NullValueHandling = NullValueHandling.Ignore)] + public List Rooms { get; set; } + /// + /// Gets or sets the collection of room combination scenarios. + /// + [JsonProperty("roomCombinationScenarios", NullValueHandling = NullValueHandling.Ignore)] + public List RoomCombinationScenarios { get; set; } + + /// + /// Gets or sets the collection of partition controllers. + /// + [JsonProperty("partitions", NullValueHandling = NullValueHandling.Ignore)] + public List Partitions { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCurrentSourceInfoMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCurrentSourceInfoMessenger.cs index 24f1f461e..ebf9a2d2b 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCurrentSourceInfoMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCurrentSourceInfoMessenger.cs @@ -3,55 +3,54 @@ using PepperDash.Core; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class IHasCurrentSourceInfoMessenger : MessengerBase { - public class IHasCurrentSourceInfoMessenger : MessengerBase + private readonly IHasCurrentSourceInfoChange sourceDevice; + public IHasCurrentSourceInfoMessenger(string key, string messagePath, IHasCurrentSourceInfoChange device) : base(key, messagePath, device as IKeyName) { - private readonly IHasCurrentSourceInfoChange sourceDevice; - public IHasCurrentSourceInfoMessenger(string key, string messagePath, IHasCurrentSourceInfoChange device) : base(key, messagePath, device as IKeyName) - { - sourceDevice = device; - } + sourceDevice = device; + } - protected override void RegisterActions() - { - base.RegisterActions(); + protected override void RegisterActions() + { + base.RegisterActions(); - AddAction("/fullStatus", (id, content) => + AddAction("/fullStatus", (id, content) => + { + var message = new CurrentSourceStateMessage { - var message = new CurrentSourceStateMessage - { - CurrentSourceKey = sourceDevice.CurrentSourceInfoKey, - CurrentSource = sourceDevice.CurrentSourceInfo - }; + CurrentSourceKey = sourceDevice.CurrentSourceInfoKey, + CurrentSource = sourceDevice.CurrentSourceInfo + }; - PostStatusMessage(message); - }); + PostStatusMessage(message); + }); - sourceDevice.CurrentSourceChange += (sender, e) => + sourceDevice.CurrentSourceChange += (sender, e) => + { + switch (e) { - switch (e) - { - case ChangeType.DidChange: + case ChangeType.DidChange: + { + PostStatusMessage(JToken.FromObject(new { - PostStatusMessage(JToken.FromObject(new - { - currentSourceKey = string.IsNullOrEmpty(sourceDevice.CurrentSourceInfoKey) ? string.Empty : sourceDevice.CurrentSourceInfoKey, - currentSource = sourceDevice.CurrentSourceInfo - })); - break; - } - } - }; - } + currentSourceKey = string.IsNullOrEmpty(sourceDevice.CurrentSourceInfoKey) ? string.Empty : sourceDevice.CurrentSourceInfoKey, + currentSource = sourceDevice.CurrentSourceInfo + })); + break; + } + } + }; } +} - public class CurrentSourceStateMessage : DeviceStateMessageBase - { - [JsonProperty("currentSourceKey", NullValueHandling = NullValueHandling.Ignore)] - public string CurrentSourceKey { get; set; } +public class CurrentSourceStateMessage : DeviceStateMessageBase +{ + [JsonProperty("currentSourceKey", NullValueHandling = NullValueHandling.Ignore)] + public string CurrentSourceKey { get; set; } - [JsonProperty("currentSource")] - public SourceListItem CurrentSource { get; set; } - } + [JsonProperty("currentSource")] + public SourceListItem CurrentSource { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasInputsMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasInputsMessenger.cs index 8eb693d51..35d3489ce 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasInputsMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasInputsMessenger.cs @@ -5,97 +5,95 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.AppServer.Messengers -{ - public class IHasInputsMessenger : MessengerBase - { - private readonly IHasInputs itemDevice; - - - /// - /// Constructs a messenger for a device that implements IHasInputs - /// - /// - /// - /// - public IHasInputsMessenger(string key, string messagePath, IHasInputs device) : base(key, messagePath, device) +namespace PepperDash.Essentials.AppServer.Messengers; + +public class IHasInputsMessenger : MessengerBase +{ + private readonly IHasInputs itemDevice; + + + /// + /// Constructs a messenger for a device that implements IHasInputs + /// + /// + /// + /// + public IHasInputsMessenger(string key, string messagePath, IHasInputs device) : base(key, messagePath, device) + { + itemDevice = device; + } + + protected override void RegisterActions() + { + base.RegisterActions(); + + AddAction("/fullStatus", (id, context) => { - itemDevice = device; - } + SendFullStatus(); + }); - protected override void RegisterActions() + itemDevice.Inputs.ItemsUpdated += (sender, args) => { - base.RegisterActions(); + SendFullStatus(); + }; - AddAction("/fullStatus", (id, context) => + itemDevice.Inputs.CurrentItemChanged += (sender, args) => + { + SendFullStatus(); + }; + + foreach (var input in itemDevice.Inputs.Items) + { + var key = input.Key; + var localItem = input.Value; + + AddAction($"/{key}", (id, content) => { - SendFullStatus(); + localItem.Select(); }); - itemDevice.Inputs.ItemsUpdated += (sender, args) => + localItem.ItemUpdated += (sender, args) => { SendFullStatus(); }; + } + } - itemDevice.Inputs.CurrentItemChanged += (sender, args) => - { - SendFullStatus(); - }; + private void SendFullStatus() + { + try + { + this.LogInformation("Sending full status"); - foreach (var input in itemDevice.Inputs.Items) + var stateObject = new IHasInputsStateMessage { - var key = input.Key; - var localItem = input.Value; - - AddAction($"/{key}", (id, content) => + Inputs = new Inputs { - localItem.Select(); - }); + Items = itemDevice.Inputs.Items, + CurrentItem = itemDevice.Inputs.CurrentItem + } + }; - localItem.ItemUpdated += (sender, args) => - { - SendFullStatus(); - }; - } + PostStatusMessage(stateObject); } - - private void SendFullStatus() + catch (Exception e) { - try - { - this.LogInformation("Sending full status"); - - var stateObject = new IHasInputsStateMessage - { - Inputs = new Inputs - { - Items = itemDevice.Inputs.Items, - CurrentItem = itemDevice.Inputs.CurrentItem - } - }; - - PostStatusMessage(stateObject); - } - catch (Exception e) - { - this.LogError("Error sending full status: {0}", e.Message); - } + this.LogError("Error sending full status: {0}", e.Message); } } +} - public class IHasInputsStateMessage : DeviceStateMessageBase - { - [JsonProperty("inputs")] - public Inputs Inputs { get; set; } - } - - public class Inputs - { - [JsonProperty("items")] - public Dictionary Items { get; set; } +public class IHasInputsStateMessage : DeviceStateMessageBase +{ + [JsonProperty("inputs")] + public Inputs Inputs { get; set; } +} - [JsonProperty("currentItem")] - public TKey CurrentItem { get; set; } - } +public class Inputs +{ + [JsonProperty("items")] + public Dictionary Items { get; set; } + [JsonProperty("currentItem")] + public TKey CurrentItem { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasPowerControlWithFeedbackMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasPowerControlWithFeedbackMessenger.cs index 7fb39c8c7..ae7ecd5f6 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasPowerControlWithFeedbackMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasPowerControlWithFeedbackMessenger.cs @@ -3,50 +3,49 @@ using PepperDash.Core; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class IHasPowerControlWithFeedbackMessenger : MessengerBase { - public class IHasPowerControlWithFeedbackMessenger : MessengerBase - { - private readonly IHasPowerControlWithFeedback _powerControl; + private readonly IHasPowerControlWithFeedback _powerControl; - public IHasPowerControlWithFeedbackMessenger(string key, string messagePath, IHasPowerControlWithFeedback powerControl) - : base(key, messagePath, powerControl as IKeyName) - { - _powerControl = powerControl; - } + public IHasPowerControlWithFeedbackMessenger(string key, string messagePath, IHasPowerControlWithFeedback powerControl) + : base(key, messagePath, powerControl as IKeyName) + { + _powerControl = powerControl; + } - public void SendFullStatus() + public void SendFullStatus() + { + var messageObj = new PowerControlWithFeedbackStateMessage { - var messageObj = new PowerControlWithFeedbackStateMessage - { - PowerState = _powerControl.PowerIsOnFeedback.BoolValue - }; + PowerState = _powerControl.PowerIsOnFeedback.BoolValue + }; - PostStatusMessage(messageObj); - } - - protected override void RegisterActions() - { - base.RegisterActions(); + PostStatusMessage(messageObj); + } - AddAction("/fullStatus", (id, content) => SendFullStatus()); + protected override void RegisterActions() + { + base.RegisterActions(); - _powerControl.PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange; ; - } + AddAction("/fullStatus", (id, content) => SendFullStatus()); - private void PowerIsOnFeedback_OutputChange(object sender, FeedbackEventArgs args) - { - PostStatusMessage(JToken.FromObject(new - { - powerState = args.BoolValue - }) - ); - } + _powerControl.PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange; ; } - public class PowerControlWithFeedbackStateMessage : DeviceStateMessageBase + private void PowerIsOnFeedback_OutputChange(object sender, FeedbackEventArgs args) { - [JsonProperty("powerState", NullValueHandling = NullValueHandling.Ignore)] - public bool? PowerState { get; set; } + PostStatusMessage(JToken.FromObject(new + { + powerState = args.BoolValue + }) + ); } } + +public class PowerControlWithFeedbackStateMessage : DeviceStateMessageBase +{ + [JsonProperty("powerState", NullValueHandling = NullValueHandling.Ignore)] + public bool? PowerState { get; set; } +} diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasScheduleAwarenessMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasScheduleAwarenessMessenger.cs index 804814705..b658bcf27 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasScheduleAwarenessMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasScheduleAwarenessMessenger.cs @@ -5,77 +5,76 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.AppServer.Messengers -{ - public class IHasScheduleAwarenessMessenger : MessengerBase - { - public IHasScheduleAwareness ScheduleSource { get; private set; } - - public IHasScheduleAwarenessMessenger(string key, IHasScheduleAwareness scheduleSource, string messagePath) - : base(key, messagePath, scheduleSource as IKeyName) - { - ScheduleSource = scheduleSource ?? throw new ArgumentNullException("scheduleSource"); - ScheduleSource.CodecSchedule.MeetingsListHasChanged += new EventHandler(CodecSchedule_MeetingsListHasChanged); - ScheduleSource.CodecSchedule.MeetingEventChange += new EventHandler(CodecSchedule_MeetingEventChange); - } +namespace PepperDash.Essentials.AppServer.Messengers; - protected override void RegisterActions() - { - AddAction("/schedule/fullStatus", (id, content) => SendFullScheduleObject()); - } +public class IHasScheduleAwarenessMessenger : MessengerBase +{ + public IHasScheduleAwareness ScheduleSource { get; private set; } - private void CodecSchedule_MeetingEventChange(object sender, MeetingEventArgs e) - { - PostStatusMessage(JToken.FromObject(new MeetingChangeMessage - { - MeetingChange = new MeetingChange - { - ChangeType = e.ChangeType.ToString(), - Meeting = e.Meeting - } - }) - ); - } + public IHasScheduleAwarenessMessenger(string key, IHasScheduleAwareness scheduleSource, string messagePath) + : base(key, messagePath, scheduleSource as IKeyName) + { + ScheduleSource = scheduleSource ?? throw new ArgumentNullException("scheduleSource"); + ScheduleSource.CodecSchedule.MeetingsListHasChanged += new EventHandler(CodecSchedule_MeetingsListHasChanged); + ScheduleSource.CodecSchedule.MeetingEventChange += new EventHandler(CodecSchedule_MeetingEventChange); + } - private void CodecSchedule_MeetingsListHasChanged(object sender, EventArgs e) - { - SendFullScheduleObject(); - } + protected override void RegisterActions() + { + AddAction("/schedule/fullStatus", (id, content) => SendFullScheduleObject()); + } - /// - /// Helper method to send the full schedule data - /// - private void SendFullScheduleObject() + private void CodecSchedule_MeetingEventChange(object sender, MeetingEventArgs e) + { + PostStatusMessage(JToken.FromObject(new MeetingChangeMessage { - PostStatusMessage(new FullScheduleMessage + MeetingChange = new MeetingChange { - Meetings = ScheduleSource.CodecSchedule.Meetings, - MeetingWarningMinutes = ScheduleSource.CodecSchedule.MeetingWarningMinutes - }); - } + ChangeType = e.ChangeType.ToString(), + Meeting = e.Meeting + } + }) + ); } - public class FullScheduleMessage : DeviceStateMessageBase + private void CodecSchedule_MeetingsListHasChanged(object sender, EventArgs e) { - [JsonProperty("meetings", NullValueHandling = NullValueHandling.Ignore)] - public List Meetings { get; set; } - - [JsonProperty("meetingWarningMinutes", NullValueHandling = NullValueHandling.Ignore)] - public int MeetingWarningMinutes { get; set; } + SendFullScheduleObject(); } - public class MeetingChangeMessage + /// + /// Helper method to send the full schedule data + /// + private void SendFullScheduleObject() { - [JsonProperty("meetingChange", NullValueHandling = NullValueHandling.Ignore)] - public MeetingChange MeetingChange { get; set; } + PostStatusMessage(new FullScheduleMessage + { + Meetings = ScheduleSource.CodecSchedule.Meetings, + MeetingWarningMinutes = ScheduleSource.CodecSchedule.MeetingWarningMinutes + }); } +} - public class MeetingChange - { - [JsonProperty("changeType", NullValueHandling = NullValueHandling.Ignore)] - public string ChangeType { get; set; } +public class FullScheduleMessage : DeviceStateMessageBase +{ + [JsonProperty("meetings", NullValueHandling = NullValueHandling.Ignore)] + public List Meetings { get; set; } - [JsonProperty("meeting", NullValueHandling = NullValueHandling.Ignore)] - public Meeting Meeting { get; set; } - } + [JsonProperty("meetingWarningMinutes", NullValueHandling = NullValueHandling.Ignore)] + public int MeetingWarningMinutes { get; set; } +} + +public class MeetingChangeMessage +{ + [JsonProperty("meetingChange", NullValueHandling = NullValueHandling.Ignore)] + public MeetingChange MeetingChange { get; set; } +} + +public class MeetingChange +{ + [JsonProperty("changeType", NullValueHandling = NullValueHandling.Ignore)] + public string ChangeType { get; set; } + + [JsonProperty("meeting", NullValueHandling = NullValueHandling.Ignore)] + public Meeting Meeting { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHumiditySensor.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHumiditySensor.cs index c44ec9ae6..092655304 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHumiditySensor.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHumiditySensor.cs @@ -3,41 +3,40 @@ using PepperDash.Essentials.Core.DeviceTypeInterfaces; using System; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class IHumiditySensorMessenger : MessengerBase { - public class IHumiditySensorMessenger : MessengerBase - { - private readonly IHumiditySensor device; + private readonly IHumiditySensor device; - public IHumiditySensorMessenger(string key, IHumiditySensor device, string messagePath) - : base(key, messagePath, device as IKeyName) - { - this.device = device; - } + public IHumiditySensorMessenger(string key, IHumiditySensor device, string messagePath) + : base(key, messagePath, device as IKeyName) + { + this.device = device; + } - protected override void RegisterActions() - { - base.RegisterActions(); + protected override void RegisterActions() + { + base.RegisterActions(); - AddAction("/fullStatus", (id, content) => SendFullStatus()); + AddAction("/fullStatus", (id, content) => SendFullStatus()); - device.HumidityFeedback.OutputChange += new EventHandler((o, a) => SendFullStatus()); - } + device.HumidityFeedback.OutputChange += new EventHandler((o, a) => SendFullStatus()); + } - private void SendFullStatus() + private void SendFullStatus() + { + var state = new IHumiditySensorStateMessage { - var state = new IHumiditySensorStateMessage - { - Humidity = string.Format("{0}%", device.HumidityFeedback.UShortValue) - }; + Humidity = string.Format("{0}%", device.HumidityFeedback.UShortValue) + }; - PostStatusMessage(state); - } + PostStatusMessage(state); } +} - public class IHumiditySensorStateMessage : DeviceStateMessageBase - { - [JsonProperty("humidity")] - public string Humidity { get; set; } - } +public class IHumiditySensorStateMessage : DeviceStateMessageBase +{ + [JsonProperty("humidity")] + public string Humidity { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ILevelControlsMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ILevelControlsMessenger.cs index 4fd3515a9..b06a5c4a4 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ILevelControlsMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ILevelControlsMessenger.cs @@ -5,87 +5,86 @@ using System.Collections.Generic; using System.Linq; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class ILevelControlsMessenger : MessengerBase { - public class ILevelControlsMessenger : MessengerBase + private ILevelControls levelControlsDevice; + public ILevelControlsMessenger(string key, string messagePath, ILevelControls device) : base(key, messagePath, device as IKeyName) + { + levelControlsDevice = device; + } + + protected override void RegisterActions() { - private ILevelControls levelControlsDevice; - public ILevelControlsMessenger(string key, string messagePath, ILevelControls device) : base(key, messagePath, device as IKeyName) + base.RegisterActions(); + + AddAction("/fullStatus", (id, context) => { - levelControlsDevice = device; - } + var message = new LevelControlStateMessage + { + Levels = levelControlsDevice.LevelControlPoints.ToDictionary(kv => kv.Key, kv => new Volume { Level = kv.Value.VolumeLevelFeedback.IntValue, Muted = kv.Value.MuteFeedback.BoolValue }) + }; - protected override void RegisterActions() + PostStatusMessage(message); + }); + + foreach (var levelControl in levelControlsDevice.LevelControlPoints) { - base.RegisterActions(); + // reassigning here just in case of lambda closure issues + var key = levelControl.Key; + var control = levelControl.Value; - AddAction("/fullStatus", (id, context) => + AddAction($"/{key}/level", (id, content) => { - var message = new LevelControlStateMessage - { - Levels = levelControlsDevice.LevelControlPoints.ToDictionary(kv => kv.Key, kv => new Volume { Level = kv.Value.VolumeLevelFeedback.IntValue, Muted = kv.Value.MuteFeedback.BoolValue }) - }; + var request = content.ToObject>(); - PostStatusMessage(message); + control.SetVolume(request.Value); }); - foreach (var levelControl in levelControlsDevice.LevelControlPoints) + AddAction($"/{key}/muteToggle", (id, content) => { - // reassigning here just in case of lambda closure issues - var key = levelControl.Key; - var control = levelControl.Value; - - AddAction($"/{key}/level", (id, content) => - { - var request = content.ToObject>(); - - control.SetVolume(request.Value); - }); - - AddAction($"/{key}/muteToggle", (id, content) => - { - control.MuteToggle(); - }); + control.MuteToggle(); + }); - AddAction($"/{key}/muteOn", (id, content) => control.MuteOn()); + AddAction($"/{key}/muteOn", (id, content) => control.MuteOn()); - AddAction($"/{key}/muteOff", (id, content) => control.MuteOff()); + AddAction($"/{key}/muteOff", (id, content) => control.MuteOff()); - AddAction($"/{key}/volumeUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => control.VolumeUp(b))); + AddAction($"/{key}/volumeUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => control.VolumeUp(b))); - AddAction($"/{key}/volumeDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => control.VolumeDown(b))); + AddAction($"/{key}/volumeDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => control.VolumeDown(b))); - control.VolumeLevelFeedback.OutputChange += (o, a) => PostStatusMessage(JToken.FromObject(new + control.VolumeLevelFeedback.OutputChange += (o, a) => PostStatusMessage(JToken.FromObject(new + { + levelControls = new Dictionary { - levelControls = new Dictionary - { - {key, new Volume{Level = a.IntValue} } - } - })); + {key, new Volume{Level = a.IntValue} } + } + })); - control.MuteFeedback.OutputChange += (o, a) => PostStatusMessage(JToken.FromObject(new + control.MuteFeedback.OutputChange += (o, a) => PostStatusMessage(JToken.FromObject(new + { + levelControls = new Dictionary { - levelControls = new Dictionary - { - {key, new Volume{Muted = a.BoolValue} } - } - })); - } + {key, new Volume{Muted = a.BoolValue} } + } + })); } } +} - public class LevelControlStateMessage : DeviceStateMessageBase - { - [JsonProperty("levelControls")] - public Dictionary Levels { get; set; } - } +public class LevelControlStateMessage : DeviceStateMessageBase +{ + [JsonProperty("levelControls")] + public Dictionary Levels { get; set; } +} - public class LevelControlRequestMessage - { - [JsonProperty("key")] - public string Key { get; set; } +public class LevelControlRequestMessage +{ + [JsonProperty("key")] + public string Key { get; set; } - [JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)] - public ushort? Level { get; set; } - } + [JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)] + public ushort? Level { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IMatrixRoutingMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IMatrixRoutingMessenger.cs index 2a9669f16..cdad69890 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IMatrixRoutingMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IMatrixRoutingMessenger.cs @@ -8,161 +8,160 @@ using System.Collections.Generic; using System.Linq; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +/// +/// Messenger for devices that implment IMatrixRouting +/// +public class IMatrixRoutingMessenger : MessengerBase { - /// - /// Messenger for devices that implment IMatrixRouting - /// - public class IMatrixRoutingMessenger : MessengerBase + private readonly IMatrixRouting matrixDevice; + public IMatrixRoutingMessenger(string key, string messagePath, IMatrixRouting device) : base(key, messagePath, device as IKeyName) { - private readonly IMatrixRouting matrixDevice; - public IMatrixRoutingMessenger(string key, string messagePath, IMatrixRouting device) : base(key, messagePath, device as IKeyName) - { - matrixDevice = device; - } + matrixDevice = device; + } - protected override void RegisterActions() - { - base.RegisterActions(); + protected override void RegisterActions() + { + base.RegisterActions(); - AddAction("/fullStatus", (id, content) => + AddAction("/fullStatus", (id, content) => + { + try { - try + Debug.LogMessage(LogEventLevel.Verbose, "InputCount: {inputCount}, OutputCount: {outputCount}", this, matrixDevice.InputSlots.Count, matrixDevice.OutputSlots.Count); + var message = new MatrixStateMessage { - Debug.LogMessage(LogEventLevel.Verbose, "InputCount: {inputCount}, OutputCount: {outputCount}", this, matrixDevice.InputSlots.Count, matrixDevice.OutputSlots.Count); - var message = new MatrixStateMessage - { - Outputs = matrixDevice.OutputSlots.ToDictionary(kvp => kvp.Key, kvp => new RoutingOutput(kvp.Value)), - Inputs = matrixDevice.InputSlots.ToDictionary(kvp => kvp.Key, kvp => new RoutingInput(kvp.Value)), - }; - + Outputs = matrixDevice.OutputSlots.ToDictionary(kvp => kvp.Key, kvp => new RoutingOutput(kvp.Value)), + Inputs = matrixDevice.InputSlots.ToDictionary(kvp => kvp.Key, kvp => new RoutingInput(kvp.Value)), + }; - PostStatusMessage(message); - } - catch (Exception e) - { - Debug.LogMessage(e, "Exception Getting full status: {@exception}", this, e); - } - }); - AddAction("/route", (id, content) => + PostStatusMessage(message); + } + catch (Exception e) { - var request = content.ToObject(); + Debug.LogMessage(e, "Exception Getting full status: {@exception}", this, e); + } + }); - matrixDevice.Route(request.InputKey, request.OutputKey, request.RouteType); - }); + AddAction("/route", (id, content) => + { + var request = content.ToObject(); - foreach (var output in matrixDevice.OutputSlots) - { - var key = output.Key; - var outputSlot = output.Value; + matrixDevice.Route(request.InputKey, request.OutputKey, request.RouteType); + }); - outputSlot.OutputSlotChanged += (sender, args) => - { - PostStatusMessage(JToken.FromObject(new - { - outputs = matrixDevice.OutputSlots.ToDictionary(kvp => kvp.Key, kvp => new RoutingOutput(kvp.Value)) - })); - }; - } + foreach (var output in matrixDevice.OutputSlots) + { + var key = output.Key; + var outputSlot = output.Value; - foreach (var input in matrixDevice.InputSlots) + outputSlot.OutputSlotChanged += (sender, args) => { - var key = input.Key; - var inputSlot = input.Value; + PostStatusMessage(JToken.FromObject(new + { + outputs = matrixDevice.OutputSlots.ToDictionary(kvp => kvp.Key, kvp => new RoutingOutput(kvp.Value)) + })); + }; + } + + foreach (var input in matrixDevice.InputSlots) + { + var key = input.Key; + var inputSlot = input.Value; - inputSlot.VideoSyncChanged += (sender, args) => + inputSlot.VideoSyncChanged += (sender, args) => + { + PostStatusMessage(JToken.FromObject(new { - PostStatusMessage(JToken.FromObject(new - { - inputs = matrixDevice.InputSlots.ToDictionary(kvp => kvp.Key, kvp => new RoutingInput(kvp.Value)) - })); - }; - } + inputs = matrixDevice.InputSlots.ToDictionary(kvp => kvp.Key, kvp => new RoutingInput(kvp.Value)) + })); + }; } } +} - public class MatrixStateMessage : DeviceStateMessageBase - { - [JsonProperty("outputs")] - public Dictionary Outputs; +public class MatrixStateMessage : DeviceStateMessageBase +{ + [JsonProperty("outputs")] + public Dictionary Outputs; - [JsonProperty("inputs")] - public Dictionary Inputs; - } + [JsonProperty("inputs")] + public Dictionary Inputs; +} - public class RoutingInput - { - private IRoutingInputSlot _input; +public class RoutingInput +{ + private IRoutingInputSlot _input; - [JsonProperty("txDeviceKey", NullValueHandling = NullValueHandling.Ignore)] - public string TxDeviceKey => _input?.TxDeviceKey; + [JsonProperty("txDeviceKey", NullValueHandling = NullValueHandling.Ignore)] + public string TxDeviceKey => _input?.TxDeviceKey; - [JsonProperty("slotNumber", NullValueHandling = NullValueHandling.Ignore)] - public int? SlotNumber => _input?.SlotNumber; + [JsonProperty("slotNumber", NullValueHandling = NullValueHandling.Ignore)] + public int? SlotNumber => _input?.SlotNumber; - [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] - [JsonProperty("supportedSignalTypes", NullValueHandling = NullValueHandling.Ignore)] - public eRoutingSignalType? SupportedSignalTypes => _input?.SupportedSignalTypes; + [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + [JsonProperty("supportedSignalTypes", NullValueHandling = NullValueHandling.Ignore)] + public eRoutingSignalType? SupportedSignalTypes => _input?.SupportedSignalTypes; - [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] - public string Name => _input?.Name; + [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] + public string Name => _input?.Name; - [JsonProperty("isOnline", NullValueHandling = NullValueHandling.Ignore)] - public bool? IsOnline => _input?.IsOnline.BoolValue; + [JsonProperty("isOnline", NullValueHandling = NullValueHandling.Ignore)] + public bool? IsOnline => _input?.IsOnline.BoolValue; - [JsonProperty("videoSyncDetected", NullValueHandling = NullValueHandling.Ignore)] + [JsonProperty("videoSyncDetected", NullValueHandling = NullValueHandling.Ignore)] - public bool? VideoSyncDetected => _input?.VideoSyncDetected; + public bool? VideoSyncDetected => _input?.VideoSyncDetected; - [JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)] - public string Key => _input?.Key; + [JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)] + public string Key => _input?.Key; - public RoutingInput(IRoutingInputSlot input) - { - _input = input; - } + public RoutingInput(IRoutingInputSlot input) + { + _input = input; } +} - public class RoutingOutput - { - private IRoutingOutputSlot _output; +public class RoutingOutput +{ + private IRoutingOutputSlot _output; - public RoutingOutput(IRoutingOutputSlot output) - { - _output = output; - } + public RoutingOutput(IRoutingOutputSlot output) + { + _output = output; + } - [JsonProperty("rxDeviceKey")] - public string RxDeviceKey => _output.RxDeviceKey; + [JsonProperty("rxDeviceKey")] + public string RxDeviceKey => _output.RxDeviceKey; - [JsonProperty("currentRoutes")] - public Dictionary CurrentRoutes => _output.CurrentRoutes.ToDictionary(kvp => kvp.Key.ToString(), kvp => new RoutingInput(kvp.Value)); + [JsonProperty("currentRoutes")] + public Dictionary CurrentRoutes => _output.CurrentRoutes.ToDictionary(kvp => kvp.Key.ToString(), kvp => new RoutingInput(kvp.Value)); - [JsonProperty("slotNumber")] - public int SlotNumber => _output.SlotNumber; + [JsonProperty("slotNumber")] + public int SlotNumber => _output.SlotNumber; - [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] - [JsonProperty("supportedSignalTypes")] - public eRoutingSignalType SupportedSignalTypes => _output.SupportedSignalTypes; + [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + [JsonProperty("supportedSignalTypes")] + public eRoutingSignalType SupportedSignalTypes => _output.SupportedSignalTypes; - [JsonProperty("name")] - public string Name => _output.Name; + [JsonProperty("name")] + public string Name => _output.Name; - [JsonProperty("key")] - public string Key => _output.Key; - } + [JsonProperty("key")] + public string Key => _output.Key; +} - public class MatrixRouteRequest - { - [JsonProperty("outputKey")] - public string OutputKey { get; set; } +public class MatrixRouteRequest +{ + [JsonProperty("outputKey")] + public string OutputKey { get; set; } - [JsonProperty("inputKey")] - public string InputKey { get; set; } + [JsonProperty("inputKey")] + public string InputKey { get; set; } - [JsonProperty("routeType")] - public eRoutingSignalType RouteType { get; set; } - } + [JsonProperty("routeType")] + public eRoutingSignalType RouteType { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IProjectorScreenLiftControlMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IProjectorScreenLiftControlMessenger.cs index a66a85863..cc114794c 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IProjectorScreenLiftControlMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IProjectorScreenLiftControlMessenger.cs @@ -5,74 +5,73 @@ using PepperDash.Essentials.Core.DeviceTypeInterfaces; using System; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class IProjectorScreenLiftControlMessenger : MessengerBase { - public class IProjectorScreenLiftControlMessenger : MessengerBase - { - private readonly IProjectorScreenLiftControl device; + private readonly IProjectorScreenLiftControl device; - public IProjectorScreenLiftControlMessenger(string key, string messagePath, IProjectorScreenLiftControl screenLiftDevice) - : base(key, messagePath, screenLiftDevice as IKeyName) - { - device = screenLiftDevice; - } + public IProjectorScreenLiftControlMessenger(string key, string messagePath, IProjectorScreenLiftControl screenLiftDevice) + : base(key, messagePath, screenLiftDevice as IKeyName) + { + device = screenLiftDevice; + } - protected override void RegisterActions() - { - base.RegisterActions(); + protected override void RegisterActions() + { + base.RegisterActions(); - AddAction("/fullStatus", (id, content) => SendFullStatus()); + AddAction("/fullStatus", (id, content) => SendFullStatus()); - AddAction("/raise", (id, content) => - { + AddAction("/raise", (id, content) => + { - device.Raise(); + device.Raise(); - }); + }); - AddAction("/lower", (id, content) => - { + AddAction("/lower", (id, content) => + { - device.Lower(); + device.Lower(); - }); + }); - device.PositionChanged += Device_PositionChanged; + device.PositionChanged += Device_PositionChanged; - } + } - private void Device_PositionChanged(object sender, EventArgs e) - { - var state = new - { - inUpPosition = device.InUpPosition - }; - PostStatusMessage(JToken.FromObject(state)); - } - - private void SendFullStatus() + private void Device_PositionChanged(object sender, EventArgs e) + { + var state = new { - var state = new ScreenLiftStateMessage - { - InUpPosition = device.InUpPosition, - Type = device.Type, - DisplayDeviceKey = device.DisplayDeviceKey - }; - - PostStatusMessage(state); - } + inUpPosition = device.InUpPosition + }; + PostStatusMessage(JToken.FromObject(state)); } - public class ScreenLiftStateMessage : DeviceStateMessageBase + private void SendFullStatus() { - [JsonProperty("inUpPosition", NullValueHandling = NullValueHandling.Ignore)] - public bool? InUpPosition { get; set; } - - [JsonProperty("displayDeviceKey", NullValueHandling = NullValueHandling.Ignore)] - public string DisplayDeviceKey { get; set; } + var state = new ScreenLiftStateMessage + { + InUpPosition = device.InUpPosition, + Type = device.Type, + DisplayDeviceKey = device.DisplayDeviceKey + }; - [JsonConverter(typeof(StringEnumConverter))] - [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] - public eScreenLiftControlType Type { get; set; } + PostStatusMessage(state); } } + +public class ScreenLiftStateMessage : DeviceStateMessageBase +{ + [JsonProperty("inUpPosition", NullValueHandling = NullValueHandling.Ignore)] + public bool? InUpPosition { get; set; } + + [JsonProperty("displayDeviceKey", NullValueHandling = NullValueHandling.Ignore)] + public string DisplayDeviceKey { get; set; } + + [JsonConverter(typeof(StringEnumConverter))] + [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)] + public eScreenLiftControlType Type { get; set; } +} diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IRunRouteActionMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IRunRouteActionMessenger.cs index 8ca6668b1..e4ac3e5c6 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IRunRouteActionMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IRunRouteActionMessenger.cs @@ -5,80 +5,79 @@ using System; -namespace PepperDash.Essentials.AppServer.Messengers -{ - public class RunRouteActionMessenger : MessengerBase - { - /// - /// Device being bridged - /// - public IRunRouteAction RoutingDevice { get; private set; } +namespace PepperDash.Essentials.AppServer.Messengers; - public RunRouteActionMessenger(string key, IRunRouteAction routingDevice, string messagePath) - : base(key, messagePath, routingDevice as IKeyName) - { - RoutingDevice = routingDevice ?? throw new ArgumentNullException("routingDevice"); +public class RunRouteActionMessenger : MessengerBase +{ + /// + /// Device being bridged + /// + public IRunRouteAction RoutingDevice { get; private set; } + public RunRouteActionMessenger(string key, IRunRouteAction routingDevice, string messagePath) + : base(key, messagePath, routingDevice as IKeyName) + { + RoutingDevice = routingDevice ?? throw new ArgumentNullException("routingDevice"); - if (RoutingDevice is IRoutingSink routingSink) - { - routingSink.CurrentSourceChange += RoutingSink_CurrentSourceChange; - } - } - private void RoutingSink_CurrentSourceChange(SourceListItem info, ChangeType type) + if (RoutingDevice is IRoutingSink routingSink) { - SendRoutingFullMessageObject(); + routingSink.CurrentSourceChange += RoutingSink_CurrentSourceChange; } + } - protected override void RegisterActions() - { - AddAction("/fullStatus", (id, content) => SendRoutingFullMessageObject()); + private void RoutingSink_CurrentSourceChange(SourceListItem info, ChangeType type) + { + SendRoutingFullMessageObject(); + } - AddAction("/source", (id, content) => - { - var c = content.ToObject(); - // assume no sourceListKey - var sourceListKey = string.Empty; + protected override void RegisterActions() + { + AddAction("/fullStatus", (id, content) => SendRoutingFullMessageObject()); - if (!string.IsNullOrEmpty(c.SourceListKey)) - { - // Check for source list in content of message - sourceListKey = c.SourceListKey; - } + AddAction("/source", (id, content) => + { + var c = content.ToObject(); + // assume no sourceListKey + var sourceListKey = string.Empty; + + if (!string.IsNullOrEmpty(c.SourceListKey)) + { + // Check for source list in content of message + sourceListKey = c.SourceListKey; + } - RoutingDevice.RunRouteAction(c.SourceListItemKey, sourceListKey); - }); + RoutingDevice.RunRouteAction(c.SourceListItemKey, sourceListKey); + }); - if (RoutingDevice is IRoutingSink sinkDevice) - { - sinkDevice.CurrentSourceChange += (o, a) => SendRoutingFullMessageObject(); - } + if (RoutingDevice is IRoutingSink sinkDevice) + { + sinkDevice.CurrentSourceChange += (o, a) => SendRoutingFullMessageObject(); } + } - /// - /// Helper method to update full status of the routing device - /// - private void SendRoutingFullMessageObject() + /// + /// Helper method to update full status of the routing device + /// + private void SendRoutingFullMessageObject() + { + if (RoutingDevice is IRoutingSink sinkDevice) { - if (RoutingDevice is IRoutingSink sinkDevice) - { - var sourceKey = sinkDevice.CurrentSourceInfoKey; + var sourceKey = sinkDevice.CurrentSourceInfoKey; - if (string.IsNullOrEmpty(sourceKey)) - sourceKey = "none"; + if (string.IsNullOrEmpty(sourceKey)) + sourceKey = "none"; - PostStatusMessage(new RoutingStateMessage - { - SelectedSourceKey = sourceKey - }); - } + PostStatusMessage(new RoutingStateMessage + { + SelectedSourceKey = sourceKey + }); } } +} - public class RoutingStateMessage : DeviceStateMessageBase - { - [JsonProperty("selectedSourceKey")] - public string SelectedSourceKey { get; set; } - } +public class RoutingStateMessage : DeviceStateMessageBase +{ + [JsonProperty("selectedSourceKey")] + public string SelectedSourceKey { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ISelectableItemsMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ISelectableItemsMessenger.cs index d7c4a59f4..04747dbc6 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ISelectableItemsMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ISelectableItemsMessenger.cs @@ -5,91 +5,89 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.AppServer.Messengers -{ - public class ISelectableItemsMessenger : MessengerBase - { - private readonly ISelectableItems itemDevice; - - private readonly string _propName; - - /// - /// Constructs a messenger for a device that implements ISelectableItems - /// - /// - /// - /// - /// - public ISelectableItemsMessenger(string key, string messagePath, ISelectableItems device, string propName) : base(key, messagePath, device as IKeyName) +namespace PepperDash.Essentials.AppServer.Messengers; + +public class ISelectableItemsMessenger : MessengerBase +{ + private readonly ISelectableItems itemDevice; + + private readonly string _propName; + + /// + /// Constructs a messenger for a device that implements ISelectableItems + /// + /// + /// + /// + /// + public ISelectableItemsMessenger(string key, string messagePath, ISelectableItems device, string propName) : base(key, messagePath, device as IKeyName) + { + itemDevice = device; + _propName = propName; + } + + protected override void RegisterActions() + { + base.RegisterActions(); + + AddAction("/fullStatus", (id, context) => { - itemDevice = device; - _propName = propName; - } + SendFullStatus(); + }); - protected override void RegisterActions() + itemDevice.ItemsUpdated += (sender, args) => { - base.RegisterActions(); + SendFullStatus(); + }; - AddAction("/fullStatus", (id, context) => + itemDevice.CurrentItemChanged += (sender, args) => + { + SendFullStatus(); + }; + + foreach (var input in itemDevice.Items) + { + var key = input.Key; + var localItem = input.Value; + + AddAction($"/{key}", (id, content) => { - SendFullStatus(); + localItem.Select(); }); - itemDevice.ItemsUpdated += (sender, args) => + localItem.ItemUpdated += (sender, args) => { SendFullStatus(); }; + } + } - itemDevice.CurrentItemChanged += (sender, args) => + private void SendFullStatus() + { + try + { + this.LogInformation("Sending full status"); + + var stateObject = new ISelectableItemsStateMessage { - SendFullStatus(); + Items = itemDevice.Items, + CurrentItem = itemDevice.CurrentItem }; - foreach (var input in itemDevice.Items) - { - var key = input.Key; - var localItem = input.Value; - - AddAction($"/{key}", (id, content) => - { - localItem.Select(); - }); - - localItem.ItemUpdated += (sender, args) => - { - SendFullStatus(); - }; - } + PostStatusMessage(stateObject); } - - private void SendFullStatus() + catch (Exception e) { - try - { - this.LogInformation("Sending full status"); - - var stateObject = new ISelectableItemsStateMessage - { - Items = itemDevice.Items, - CurrentItem = itemDevice.CurrentItem - }; - - PostStatusMessage(stateObject); - } - catch (Exception e) - { - this.LogError("Error sending full status: {0}", e.Message); - } + this.LogError("Error sending full status: {0}", e.Message); } } +} - public class ISelectableItemsStateMessage : DeviceStateMessageBase - { - [JsonProperty("items")] - public Dictionary Items { get; set; } - - [JsonProperty("currentItem")] - public TKey CurrentItem { get; set; } - } +public class ISelectableItemsStateMessage : DeviceStateMessageBase +{ + [JsonProperty("items")] + public Dictionary Items { get; set; } + [JsonProperty("currentItem")] + public TKey CurrentItem { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IShutdownPromptTimerMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IShutdownPromptTimerMessenger.cs index ca5fc3d38..23adcef8b 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IShutdownPromptTimerMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IShutdownPromptTimerMessenger.cs @@ -3,91 +3,90 @@ using PepperDash.Core; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class IShutdownPromptTimerMessenger : MessengerBase { - public class IShutdownPromptTimerMessenger : MessengerBase + private readonly IShutdownPromptTimer _room; + + public IShutdownPromptTimerMessenger(string key, string messagePath, IShutdownPromptTimer room) + : base(key, messagePath, room as IKeyName) { - private readonly IShutdownPromptTimer _room; + _room = room; + } - public IShutdownPromptTimerMessenger(string key, string messagePath, IShutdownPromptTimer room) - : base(key, messagePath, room as IKeyName) + protected override void RegisterActions() + { + AddAction("/status", (id, content) => { - _room = room; - } + SendFullStatus(); + }); - protected override void RegisterActions() + AddAction("/setShutdownPromptSeconds", (id, content) => { - AddAction("/status", (id, content) => - { - SendFullStatus(); - }); + var response = content.ToObject(); - AddAction("/setShutdownPromptSeconds", (id, content) => - { - var response = content.ToObject(); + _room.SetShutdownPromptSeconds(response); - _room.SetShutdownPromptSeconds(response); + SendFullStatus(); + }); - SendFullStatus(); - }); + AddAction("/shutdownStart", (id, content) => _room.StartShutdown(eShutdownType.Manual)); - AddAction("/shutdownStart", (id, content) => _room.StartShutdown(eShutdownType.Manual)); + AddAction("/shutdownEnd", (id, content) => _room.ShutdownPromptTimer.Finish()); - AddAction("/shutdownEnd", (id, content) => _room.ShutdownPromptTimer.Finish()); + AddAction("/shutdownCancel", (id, content) => _room.ShutdownPromptTimer.Cancel()); - AddAction("/shutdownCancel", (id, content) => _room.ShutdownPromptTimer.Cancel()); + _room.ShutdownPromptTimer.HasStarted += (sender, args) => + { + PostEventMessage("timerStarted"); + }; - _room.ShutdownPromptTimer.HasStarted += (sender, args) => - { - PostEventMessage("timerStarted"); - }; + _room.ShutdownPromptTimer.HasFinished += (sender, args) => + { + PostEventMessage("timerFinished"); + }; - _room.ShutdownPromptTimer.HasFinished += (sender, args) => - { - PostEventMessage("timerFinished"); - }; + _room.ShutdownPromptTimer.WasCancelled += (sender, args) => + { + PostEventMessage("timerCancelled"); + }; - _room.ShutdownPromptTimer.WasCancelled += (sender, args) => + _room.ShutdownPromptTimer.SecondsRemainingFeedback.OutputChange += (sender, args) => + { + var status = new { - PostEventMessage("timerCancelled"); + secondsRemaining = _room.ShutdownPromptTimer.SecondsRemainingFeedback.IntValue, + percentageRemaining = _room.ShutdownPromptTimer.PercentFeedback.UShortValue }; - _room.ShutdownPromptTimer.SecondsRemainingFeedback.OutputChange += (sender, args) => - { - var status = new - { - secondsRemaining = _room.ShutdownPromptTimer.SecondsRemainingFeedback.IntValue, - percentageRemaining = _room.ShutdownPromptTimer.PercentFeedback.UShortValue - }; - - PostStatusMessage(JToken.FromObject(status)); - }; - } + PostStatusMessage(JToken.FromObject(status)); + }; + } - private void SendFullStatus() + private void SendFullStatus() + { + var status = new IShutdownPromptTimerStateMessage { - var status = new IShutdownPromptTimerStateMessage - { - ShutdownPromptSeconds = _room.ShutdownPromptTimer.SecondsToCount, - SecondsRemaining = _room.ShutdownPromptTimer.SecondsRemainingFeedback.IntValue, - PercentageRemaining = _room.ShutdownPromptTimer.PercentFeedback.UShortValue - }; + ShutdownPromptSeconds = _room.ShutdownPromptTimer.SecondsToCount, + SecondsRemaining = _room.ShutdownPromptTimer.SecondsRemainingFeedback.IntValue, + PercentageRemaining = _room.ShutdownPromptTimer.PercentFeedback.UShortValue + }; - PostStatusMessage(status); - } + PostStatusMessage(status); } +} - public class IShutdownPromptTimerStateMessage : DeviceStateMessageBase - { - [JsonProperty("secondsRemaining")] - public int SecondsRemaining { get; set; } +public class IShutdownPromptTimerStateMessage : DeviceStateMessageBase +{ + [JsonProperty("secondsRemaining")] + public int SecondsRemaining { get; set; } - [JsonProperty("percentageRemaining")] - public int PercentageRemaining { get; set; } + [JsonProperty("percentageRemaining")] + public int PercentageRemaining { get; set; } - [JsonProperty("shutdownPromptSeconds")] - public int ShutdownPromptSeconds { get; set; } - } + [JsonProperty("shutdownPromptSeconds")] + public int ShutdownPromptSeconds { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ISwitchedOutputMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ISwitchedOutputMessenger.cs index f49d189de..a5d5f7e26 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ISwitchedOutputMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ISwitchedOutputMessenger.cs @@ -3,56 +3,55 @@ using PepperDash.Essentials.Core.CrestronIO; using System; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class ISwitchedOutputMessenger : MessengerBase { - public class ISwitchedOutputMessenger : MessengerBase - { - private readonly ISwitchedOutput device; + private readonly ISwitchedOutput device; - public ISwitchedOutputMessenger(string key, ISwitchedOutput device, string messagePath) - : base(key, messagePath, device as IKeyName) - { - this.device = device; - } + public ISwitchedOutputMessenger(string key, ISwitchedOutput device, string messagePath) + : base(key, messagePath, device as IKeyName) + { + this.device = device; + } - protected override void RegisterActions() - { - base.RegisterActions(); + protected override void RegisterActions() + { + base.RegisterActions(); - AddAction("/fullStatus", (id, content) => SendFullStatus()); + AddAction("/fullStatus", (id, content) => SendFullStatus()); - AddAction("/on", (id, content) => - { + AddAction("/on", (id, content) => + { - device.On(); + device.On(); - }); + }); - AddAction("/off", (id, content) => - { + AddAction("/off", (id, content) => + { - device.Off(); + device.Off(); - }); + }); - device.OutputIsOnFeedback.OutputChange += new EventHandler((o, a) => SendFullStatus()); - } + device.OutputIsOnFeedback.OutputChange += new EventHandler((o, a) => SendFullStatus()); + } - private void SendFullStatus() + private void SendFullStatus() + { + var state = new ISwitchedOutputStateMessage { - var state = new ISwitchedOutputStateMessage - { - IsOn = device.OutputIsOnFeedback.BoolValue - }; + IsOn = device.OutputIsOnFeedback.BoolValue + }; - PostStatusMessage(state); - } + PostStatusMessage(state); } +} - public class ISwitchedOutputStateMessage : DeviceStateMessageBase - { - [JsonProperty("isOn")] - public bool IsOn { get; set; } - } +public class ISwitchedOutputStateMessage : DeviceStateMessageBase +{ + [JsonProperty("isOn")] + public bool IsOn { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ITechPasswordMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ITechPasswordMessenger.cs index 5b15d7abd..8f64c9d58 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ITechPasswordMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ITechPasswordMessenger.cs @@ -2,87 +2,85 @@ using PepperDash.Core; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class ITechPasswordMessenger : MessengerBase { - public class ITechPasswordMessenger : MessengerBase + private readonly ITechPassword _room; + + public ITechPasswordMessenger(string key, string messagePath, ITechPassword room) + : base(key, messagePath, room as IKeyName) { - private readonly ITechPassword _room; + _room = room; + } - public ITechPasswordMessenger(string key, string messagePath, ITechPassword room) - : base(key, messagePath, room as IKeyName) - { - _room = room; - } + protected override void RegisterActions() + { - protected override void RegisterActions() + AddAction("/status", (id, content) => { + SendFullStatus(); + }); - AddAction("/status", (id, content) => - { - SendFullStatus(); - }); - - AddAction("/validateTechPassword", (id, content) => - { - var password = content.Value("password"); - - _room.ValidateTechPassword(password); - }); - - AddAction("/setTechPassword", (id, content) => - { - var response = content.ToObject(); + AddAction("/validateTechPassword", (id, content) => + { + var password = content.Value("password"); - _room.SetTechPassword(response.OldPassword, response.NewPassword); - }); + _room.ValidateTechPassword(password); + }); - _room.TechPasswordChanged += (sender, args) => - { - PostEventMessage("passwordChangedSuccessfully"); - }; + AddAction("/setTechPassword", (id, content) => + { + var response = content.ToObject(); - _room.TechPasswordValidateResult += (sender, args) => - { - var evt = new ITechPasswordEventMessage - { - IsValid = args.IsValid - }; + _room.SetTechPassword(response.OldPassword, response.NewPassword); + }); - PostEventMessage(evt, "passwordValidationResult"); - }; - } + _room.TechPasswordChanged += (sender, args) => + { + PostEventMessage("passwordChangedSuccessfully"); + }; - private void SendFullStatus() + _room.TechPasswordValidateResult += (sender, args) => { - var status = new ITechPasswordStateMessage + var evt = new ITechPasswordEventMessage { - TechPasswordLength = _room.TechPasswordLength + IsValid = args.IsValid }; - PostStatusMessage(status); - } - + PostEventMessage(evt, "passwordValidationResult"); + }; } - public class ITechPasswordStateMessage : DeviceStateMessageBase + private void SendFullStatus() { - [JsonProperty("techPasswordLength", NullValueHandling = NullValueHandling.Ignore)] - public int? TechPasswordLength { get; set; } - } + var status = new ITechPasswordStateMessage + { + TechPasswordLength = _room.TechPasswordLength + }; - public class ITechPasswordEventMessage : DeviceEventMessageBase - { - [JsonProperty("isValid", NullValueHandling = NullValueHandling.Ignore)] - public bool? IsValid { get; set; } + PostStatusMessage(status); } - internal class SetTechPasswordContent - { - [JsonProperty("oldPassword")] - public string OldPassword { get; set; } +} - [JsonProperty("newPassword")] - public string NewPassword { get; set; } - } +public class ITechPasswordStateMessage : DeviceStateMessageBase +{ + [JsonProperty("techPasswordLength", NullValueHandling = NullValueHandling.Ignore)] + public int? TechPasswordLength { get; set; } +} + +public class ITechPasswordEventMessage : DeviceEventMessageBase +{ + [JsonProperty("isValid", NullValueHandling = NullValueHandling.Ignore)] + public bool? IsValid { get; set; } +} + +internal class SetTechPasswordContent +{ + [JsonProperty("oldPassword")] + public string OldPassword { get; set; } + [JsonProperty("newPassword")] + public string NewPassword { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ITemperatureSensorMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ITemperatureSensorMessenger.cs index 6f7371c12..84c349692 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ITemperatureSensorMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ITemperatureSensorMessenger.cs @@ -3,59 +3,58 @@ using PepperDash.Essentials.Core.DeviceTypeInterfaces; using System; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class ITemperatureSensorMessenger : MessengerBase { - public class ITemperatureSensorMessenger : MessengerBase + private readonly ITemperatureSensor device; + + public ITemperatureSensorMessenger(string key, ITemperatureSensor device, string messagePath) + : base(key, messagePath, device as IKeyName) { - private readonly ITemperatureSensor device; + this.device = device; + } - public ITemperatureSensorMessenger(string key, ITemperatureSensor device, string messagePath) - : base(key, messagePath, device as IKeyName) - { - this.device = device; - } + protected override void RegisterActions() + { + base.RegisterActions(); - protected override void RegisterActions() - { - base.RegisterActions(); + AddAction("/fullStatus", (id, content) => SendFullStatus()); - AddAction("/fullStatus", (id, content) => SendFullStatus()); + AddAction("/setTemperatureUnitsToCelcius", (id, content) => + { + device.SetTemperatureFormat(true); + }); - AddAction("/setTemperatureUnitsToCelcius", (id, content) => - { - device.SetTemperatureFormat(true); - }); + AddAction("/setTemperatureUnitsToFahrenheit", (id, content) => + { + device.SetTemperatureFormat(false); + }); - AddAction("/setTemperatureUnitsToFahrenheit", (id, content) => - { - device.SetTemperatureFormat(false); - }); + device.TemperatureFeedback.OutputChange += new EventHandler((o, a) => SendFullStatus()); + device.TemperatureInCFeedback.OutputChange += new EventHandler((o, a) => SendFullStatus()); + } - device.TemperatureFeedback.OutputChange += new EventHandler((o, a) => SendFullStatus()); - device.TemperatureInCFeedback.OutputChange += new EventHandler((o, a) => SendFullStatus()); - } + private void SendFullStatus() + { + // format the temperature to a string with one decimal place + var tempString = string.Format("{0}.{1}", device.TemperatureFeedback.UShortValue / 10, device.TemperatureFeedback.UShortValue % 10); - private void SendFullStatus() + var state = new ITemperatureSensorStateMessage { - // format the temperature to a string with one decimal place - var tempString = string.Format("{0}.{1}", device.TemperatureFeedback.UShortValue / 10, device.TemperatureFeedback.UShortValue % 10); + Temperature = tempString, + TemperatureInCelsius = device.TemperatureInCFeedback.BoolValue + }; - var state = new ITemperatureSensorStateMessage - { - Temperature = tempString, - TemperatureInCelsius = device.TemperatureInCFeedback.BoolValue - }; - - PostStatusMessage(state); - } + PostStatusMessage(state); } +} - public class ITemperatureSensorStateMessage : DeviceStateMessageBase - { - [JsonProperty("temperature")] - public string Temperature { get; set; } +public class ITemperatureSensorStateMessage : DeviceStateMessageBase +{ + [JsonProperty("temperature")] + public string Temperature { get; set; } - [JsonProperty("temperatureInCelsius")] - public bool TemperatureInCelsius { get; set; } - } + [JsonProperty("temperatureInCelsius")] + public bool TemperatureInCelsius { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/LightingBaseMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/LightingBaseMessenger.cs index 8ae91d36e..ccb1a70b3 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/LightingBaseMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/LightingBaseMessenger.cs @@ -4,67 +4,66 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class ILightingScenesMessenger : MessengerBase { - public class ILightingScenesMessenger : MessengerBase - { - private ILightingScenes lightingScenesDevice; + private ILightingScenes lightingScenesDevice; - public ILightingScenesMessenger(string key, ILightingScenes device, string messagePath) - : base(key, messagePath, device as IKeyName) - { - lightingScenesDevice = device ?? throw new ArgumentNullException("device"); + public ILightingScenesMessenger(string key, ILightingScenes device, string messagePath) + : base(key, messagePath, device as IKeyName) + { + lightingScenesDevice = device ?? throw new ArgumentNullException("device"); - lightingScenesDevice.LightingSceneChange += new EventHandler(LightingDevice_LightingSceneChange); - } + lightingScenesDevice.LightingSceneChange += new EventHandler(LightingDevice_LightingSceneChange); + } - private void LightingDevice_LightingSceneChange(object sender, LightingSceneChangeEventArgs e) + private void LightingDevice_LightingSceneChange(object sender, LightingSceneChangeEventArgs e) + { + var state = new LightingBaseStateMessage { - var state = new LightingBaseStateMessage - { - CurrentLightingScene = e.CurrentLightingScene - }; + CurrentLightingScene = e.CurrentLightingScene + }; - PostStatusMessage(state); - } + PostStatusMessage(state); + } - protected override void RegisterActions() - { - base.RegisterActions(); + protected override void RegisterActions() + { + base.RegisterActions(); - AddAction("/fullStatus", (id, content) => SendFullStatus()); + AddAction("/fullStatus", (id, content) => SendFullStatus()); - AddAction("/selectScene", (id, content) => - { - var s = content.ToObject(); - lightingScenesDevice.SelectScene(s); - }); + AddAction("/selectScene", (id, content) => + { + var s = content.ToObject(); + lightingScenesDevice.SelectScene(s); + }); - if(!(lightingScenesDevice is ILightingScenesDynamic lightingScenesDynamic)) - return; + if(!(lightingScenesDevice is ILightingScenesDynamic lightingScenesDynamic)) + return; - lightingScenesDynamic.LightingScenesUpdated += (s, e) => SendFullStatus(); - } + lightingScenesDynamic.LightingScenesUpdated += (s, e) => SendFullStatus(); + } - private void SendFullStatus() + private void SendFullStatus() + { + var state = new LightingBaseStateMessage { - var state = new LightingBaseStateMessage - { - Scenes = lightingScenesDevice.LightingScenes, - CurrentLightingScene = lightingScenesDevice.CurrentLightingScene - }; - - PostStatusMessage(state); - } + Scenes = lightingScenesDevice.LightingScenes, + CurrentLightingScene = lightingScenesDevice.CurrentLightingScene + }; + + PostStatusMessage(state); } +} - public class LightingBaseStateMessage : DeviceStateMessageBase - { - [JsonProperty("scenes", NullValueHandling = NullValueHandling.Ignore)] - public List Scenes { get; set; } +public class LightingBaseStateMessage : DeviceStateMessageBase +{ + [JsonProperty("scenes", NullValueHandling = NullValueHandling.Ignore)] + public List Scenes { get; set; } - [JsonProperty("currentLightingScene", NullValueHandling = NullValueHandling.Ignore)] - public LightingScene CurrentLightingScene { get; set; } - } + [JsonProperty("currentLightingScene", NullValueHandling = NullValueHandling.Ignore)] + public LightingScene CurrentLightingScene { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/MessengerBase.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/MessengerBase.cs index c3a612bc5..03a69c04f 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/MessengerBase.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/MessengerBase.cs @@ -8,286 +8,284 @@ using System.Collections.Generic; using System.Linq; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +/// +/// Provides a messaging bridge +/// +public abstract class MessengerBase : EssentialsDevice, IMobileControlMessenger { - /// - /// Provides a messaging bridge - /// - public abstract class MessengerBase : EssentialsDevice, IMobileControlMessenger - { - protected IKeyName _device; + protected IKeyName _device; - private readonly List _deviceInterfaces; + private readonly List _deviceInterfaces; - private readonly Dictionary> _actions = new Dictionary>(); + private readonly Dictionary> _actions = new Dictionary>(); - public string DeviceKey => _device?.Key ?? ""; + public string DeviceKey => _device?.Key ?? ""; - /// - /// - /// + /// + /// + /// - public IMobileControl AppServerController { get; private set; } + public IMobileControl AppServerController { get; private set; } - public string MessagePath { get; private set; } + public string MessagePath { get; private set; } - /// - /// - /// - /// - /// - protected MessengerBase(string key, string messagePath) - : base(key) - { - Key = key; + /// + /// + /// + /// + /// + protected MessengerBase(string key, string messagePath) + : base(key) + { + Key = key; - if (string.IsNullOrEmpty(messagePath)) - throw new ArgumentException("messagePath must not be empty or null"); + if (string.IsNullOrEmpty(messagePath)) + throw new ArgumentException("messagePath must not be empty or null"); - MessagePath = messagePath; - } + MessagePath = messagePath; + } - protected MessengerBase(string key, string messagePath, IKeyName device) - : this(key, messagePath) - { - _device = device; + protected MessengerBase(string key, string messagePath, IKeyName device) + : this(key, messagePath) + { + _device = device; - _deviceInterfaces = GetInterfaces(_device as Device); - } + _deviceInterfaces = GetInterfaces(_device as Device); + } - /// - /// Gets the interfaces implmented on the device - /// - /// - /// - private List GetInterfaces(Device device) - { - return device?.GetType().GetInterfaces().Select((i) => i.Name).ToList() ?? new List(); - } + /// + /// Gets the interfaces implmented on the device + /// + /// + /// + private List GetInterfaces(Device device) + { + return device?.GetType().GetInterfaces().Select((i) => i.Name).ToList() ?? new List(); + } - /// - /// Registers this messenger with appserver controller - /// - /// - public void RegisterWithAppServer(IMobileControl appServerController) - { - AppServerController = appServerController ?? throw new ArgumentNullException("appServerController"); + /// + /// Registers this messenger with appserver controller + /// + /// + public void RegisterWithAppServer(IMobileControl appServerController) + { + AppServerController = appServerController ?? throw new ArgumentNullException("appServerController"); - AppServerController.AddAction(this, HandleMessage); + AppServerController.AddAction(this, HandleMessage); - RegisterActions(); - } + RegisterActions(); + } + + private void HandleMessage(string path, string id, JToken content) + { + // replace base path with empty string. Should leave something like /fullStatus + var route = path.Replace(MessagePath, string.Empty); - private void HandleMessage(string path, string id, JToken content) + if (!_actions.TryGetValue(route, out var action)) { - // replace base path with empty string. Should leave something like /fullStatus - var route = path.Replace(MessagePath, string.Empty); + return; + } - if (!_actions.TryGetValue(route, out var action)) - { - return; - } + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Executing action for path {path}", this, path); - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Executing action for path {path}", this, path); + action(id, content); + } - action(id, content); + protected void AddAction(string path, Action action) + { + if (_actions.ContainsKey(path)) + { + //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Messenger {Key} already has action registered at {path}", this); + return; } - protected void AddAction(string path, Action action) - { - if (_actions.ContainsKey(path)) - { - //Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Messenger {Key} already has action registered at {path}", this); - return; - } + _actions.Add(path, action); + } - _actions.Add(path, action); - } + public List GetActionPaths() + { + return _actions.Keys.ToList(); + } - public List GetActionPaths() + protected void RemoveAction(string path) + { + if (!_actions.ContainsKey(path)) { - return _actions.Keys.ToList(); + return; } - protected void RemoveAction(string path) - { - if (!_actions.ContainsKey(path)) - { - return; - } - - _actions.Remove(path); - } + _actions.Remove(path); + } - /// - /// Implemented in extending classes. Wire up API calls and feedback here - /// - /// - protected virtual void RegisterActions() - { + /// + /// Implemented in extending classes. Wire up API calls and feedback here + /// + /// + protected virtual void RegisterActions() + { - } + } - /// - /// Helper for posting status message - /// - /// - /// - protected void PostStatusMessage(DeviceStateMessageBase message, string clientId = null) + /// + /// Helper for posting status message + /// + /// + /// + protected void PostStatusMessage(DeviceStateMessageBase message, string clientId = null) + { + try { - try + if (message == null) { - if (message == null) - { - throw new ArgumentNullException("message"); - } + throw new ArgumentNullException("message"); + } - if (_device == null) - { - throw new ArgumentNullException("device"); - } + if (_device == null) + { + throw new ArgumentNullException("device"); + } - message.SetInterfaces(_deviceInterfaces); + message.SetInterfaces(_deviceInterfaces); - message.Key = _device.Key; + message.Key = _device.Key; - message.Name = _device.Name; + message.Name = _device.Name; - var token = JToken.FromObject(message); - - PostStatusMessage(token, MessagePath, clientId); - } - catch (Exception ex) - { - this.LogError(ex, "Exception posting status message for {messagePath} to {clientId}", MessagePath, clientId ?? "all clients"); - } + var token = JToken.FromObject(message); + + PostStatusMessage(token, MessagePath, clientId); } + catch (Exception ex) + { + this.LogError(ex, "Exception posting status message for {messagePath} to {clientId}", MessagePath, clientId ?? "all clients"); + } + } - protected void PostStatusMessage(string type, DeviceStateMessageBase deviceState, string clientId = null) + protected void PostStatusMessage(string type, DeviceStateMessageBase deviceState, string clientId = null) + { + try { - try - { - //Debug.Console(2, this, "*********************Setting DeviceStateMessageProperties on MobileControlResponseMessage"); - deviceState.SetInterfaces(_deviceInterfaces); + //Debug.Console(2, this, "*********************Setting DeviceStateMessageProperties on MobileControlResponseMessage"); + deviceState.SetInterfaces(_deviceInterfaces); - deviceState.Key = _device.Key; + deviceState.Key = _device.Key; - deviceState.Name = _device.Name; + deviceState.Name = _device.Name; - deviceState.MessageBasePath = MessagePath; + deviceState.MessageBasePath = MessagePath; - var token = JToken.FromObject(deviceState); + var token = JToken.FromObject(deviceState); - PostStatusMessage(token, type, clientId); - } - catch (Exception ex) - { - this.LogError(ex, "Exception posting status message for {type} to {clientId}", type, clientId ?? "all clients"); - } + PostStatusMessage(token, type, clientId); } - - protected void PostStatusMessage(JToken content, string type = "", string clientId = null) + catch (Exception ex) { - try - { - AppServerController?.SendMessageObject(new MobileControlMessage { Type = !string.IsNullOrEmpty(type) ? type : MessagePath, ClientId = clientId, Content = content }); - } - catch (Exception ex) - { - Debug.LogMessage(ex, "Exception posting status message", this); - } + this.LogError(ex, "Exception posting status message for {type} to {clientId}", type, clientId ?? "all clients"); } + } - protected void PostEventMessage(DeviceEventMessageBase message) + protected void PostStatusMessage(JToken content, string type = "", string clientId = null) + { + try { - message.Key = _device.Key; + AppServerController?.SendMessageObject(new MobileControlMessage { Type = !string.IsNullOrEmpty(type) ? type : MessagePath, ClientId = clientId, Content = content }); + } + catch (Exception ex) + { + Debug.LogMessage(ex, "Exception posting status message", this); + } + } - message.Name = _device.Name; + protected void PostEventMessage(DeviceEventMessageBase message) + { + message.Key = _device.Key; - AppServerController?.SendMessageObject(new MobileControlMessage - { - Type = $"/event{MessagePath}/{message.EventType}", - Content = JToken.FromObject(message), - }); - } + message.Name = _device.Name; - protected void PostEventMessage(DeviceEventMessageBase message, string eventType) + AppServerController?.SendMessageObject(new MobileControlMessage { - message.Key = _device.Key; + Type = $"/event{MessagePath}/{message.EventType}", + Content = JToken.FromObject(message), + }); + } - message.Name = _device.Name; + protected void PostEventMessage(DeviceEventMessageBase message, string eventType) + { + message.Key = _device.Key; - message.EventType = eventType; + message.Name = _device.Name; - AppServerController?.SendMessageObject(new MobileControlMessage - { - Type = $"/event{MessagePath}/{eventType}", - Content = JToken.FromObject(message), - }); - } + message.EventType = eventType; - protected void PostEventMessage(string eventType) + AppServerController?.SendMessageObject(new MobileControlMessage { - AppServerController?.SendMessageObject(new MobileControlMessage - { - Type = $"/event{MessagePath}/{eventType}", - Content = JToken.FromObject(new { }), - }); - } - + Type = $"/event{MessagePath}/{eventType}", + Content = JToken.FromObject(message), + }); } - public abstract class DeviceMessageBase + protected void PostEventMessage(string eventType) { - /// - /// The device key - /// - [JsonProperty("key")] - public string Key { get; set; } - - /// - /// The device name - /// - [JsonProperty("name")] - public string Name { get; set; } - - /// - /// The type of the message class - /// - [JsonProperty("messageType")] - public string MessageType => GetType().Name; - - [JsonProperty("messageBasePath")] - public string MessageBasePath { get; set; } + AppServerController?.SendMessageObject(new MobileControlMessage + { + Type = $"/event{MessagePath}/{eventType}", + Content = JToken.FromObject(new { }), + }); } +} + +public abstract class DeviceMessageBase +{ /// - /// Base class for state messages that includes the type of message and the implmented interfaces + /// The device key /// - public class DeviceStateMessageBase : DeviceMessageBase - { - /// - /// The interfaces implmented by the device sending the messsage - /// - [JsonProperty("interfaces")] - public List Interfaces { get; private set; } + [JsonProperty("key")] + public string Key { get; set; } - public void SetInterfaces(List interfaces) - { - Interfaces = interfaces; - } - } + /// + /// The device name + /// + [JsonProperty("name")] + public string Name { get; set; } + + /// + /// The type of the message class + /// + [JsonProperty("messageType")] + public string MessageType => GetType().Name; + + [JsonProperty("messageBasePath")] + public string MessageBasePath { get; set; } +} +/// +/// Base class for state messages that includes the type of message and the implmented interfaces +/// +public class DeviceStateMessageBase : DeviceMessageBase +{ /// - /// Base class for event messages that include the type of message and an event type + /// The interfaces implmented by the device sending the messsage /// - public abstract class DeviceEventMessageBase : DeviceMessageBase + [JsonProperty("interfaces")] + public List Interfaces { get; private set; } + + public void SetInterfaces(List interfaces) { - /// - /// The event type - /// - [JsonProperty("eventType")] - public string EventType { get; set; } + Interfaces = interfaces; } +} +/// +/// Base class for event messages that include the type of message and an event type +/// +public abstract class DeviceEventMessageBase : DeviceMessageBase +{ + /// + /// The event type + /// + [JsonProperty("eventType")] + public string EventType { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/PressAndHoldHandler.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/PressAndHoldHandler.cs index 9ec2a4e4b..f6b518e54 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/PressAndHoldHandler.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/PressAndHoldHandler.cs @@ -4,113 +4,112 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public static class PressAndHoldHandler { - public static class PressAndHoldHandler - { - private const long ButtonHeartbeatInterval = 1000; + private const long ButtonHeartbeatInterval = 1000; - private static readonly Dictionary _pushedActions = new Dictionary(); + private static readonly Dictionary _pushedActions = new Dictionary(); - private static readonly Dictionary>> _pushedActionHandlers; + private static readonly Dictionary>> _pushedActionHandlers; - static PressAndHoldHandler() + static PressAndHoldHandler() + { + _pushedActionHandlers = new Dictionary>> { - _pushedActionHandlers = new Dictionary>> - { - {"pressed", AddTimer }, - {"held", ResetTimer }, - {"released", StopTimer } - }; - } + {"pressed", AddTimer }, + {"held", ResetTimer }, + {"released", StopTimer } + }; + } - private static void AddTimer(string deviceKey, Action action) + private static void AddTimer(string deviceKey, Action action) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to add timer for {deviceKey}", deviceKey); + + if (_pushedActions.TryGetValue(deviceKey, out CTimer cancelTimer)) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to add timer for {deviceKey}", deviceKey); + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Timer for {deviceKey} already exists", deviceKey); + return; + } - if (_pushedActions.TryGetValue(deviceKey, out CTimer cancelTimer)) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Timer for {deviceKey} already exists", deviceKey); - return; - } + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Adding timer for {deviceKey} with due time {dueTime}", deviceKey, ButtonHeartbeatInterval); - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Adding timer for {deviceKey} with due time {dueTime}", deviceKey, ButtonHeartbeatInterval); + action(true); - action(true); + cancelTimer = new CTimer(o => + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Timer expired for {deviceKey}", deviceKey); - cancelTimer = new CTimer(o => - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Timer expired for {deviceKey}", deviceKey); + action(false); - action(false); + _pushedActions.Remove(deviceKey); + }, ButtonHeartbeatInterval); - _pushedActions.Remove(deviceKey); - }, ButtonHeartbeatInterval); + _pushedActions.Add(deviceKey, cancelTimer); + } - _pushedActions.Add(deviceKey, cancelTimer); - } + private static void ResetTimer(string deviceKey, Action action) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to reset timer for {deviceKey}", deviceKey); - private static void ResetTimer(string deviceKey, Action action) + if (!_pushedActions.TryGetValue(deviceKey, out CTimer cancelTimer)) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to reset timer for {deviceKey}", deviceKey); - - if (!_pushedActions.TryGetValue(deviceKey, out CTimer cancelTimer)) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Timer for {deviceKey} not found", deviceKey); - return; - } - - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Resetting timer for {deviceKey} with due time {dueTime}", deviceKey, ButtonHeartbeatInterval); - - cancelTimer.Reset(ButtonHeartbeatInterval); + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Timer for {deviceKey} not found", deviceKey); + return; } - private static void StopTimer(string deviceKey, Action action) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to stop timer for {deviceKey}", deviceKey); + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Resetting timer for {deviceKey} with due time {dueTime}", deviceKey, ButtonHeartbeatInterval); - if (!_pushedActions.TryGetValue(deviceKey, out CTimer cancelTimer)) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Timer for {deviceKey} not found", deviceKey); - return; - } + cancelTimer.Reset(ButtonHeartbeatInterval); + } - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Stopping timer for {deviceKey} with due time {dueTime}", deviceKey, ButtonHeartbeatInterval); + private static void StopTimer(string deviceKey, Action action) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Attempting to stop timer for {deviceKey}", deviceKey); - action(false); - cancelTimer.Stop(); - _pushedActions.Remove(deviceKey); + if (!_pushedActions.TryGetValue(deviceKey, out CTimer cancelTimer)) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Timer for {deviceKey} not found", deviceKey); + return; } - public static Action> GetPressAndHoldHandler(string value) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Getting press and hold handler for {value}", value); + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Stopping timer for {deviceKey} with due time {dueTime}", deviceKey, ButtonHeartbeatInterval); - if (!_pushedActionHandlers.TryGetValue(value, out Action> handler)) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Press and hold handler for {value} not found", value); - return null; - } + action(false); + cancelTimer.Stop(); + _pushedActions.Remove(deviceKey); + } - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Got handler for {value}", value); + public static Action> GetPressAndHoldHandler(string value) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Getting press and hold handler for {value}", value); - return handler; + if (!_pushedActionHandlers.TryGetValue(value, out Action> handler)) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Press and hold handler for {value} not found", value); + return null; } - public static void HandlePressAndHold(string deviceKey, JToken content, Action action) - { - var msg = content.ToObject>(); + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Got handler for {value}", value); + + return handler; + } - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Handling press and hold message of {type} for {deviceKey}", msg.Value, deviceKey); + public static void HandlePressAndHold(string deviceKey, JToken content, Action action) + { + var msg = content.ToObject>(); - var timerHandler = GetPressAndHoldHandler(msg.Value); + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Handling press and hold message of {type} for {deviceKey}", msg.Value, deviceKey); - if (timerHandler == null) - { - return; - } + var timerHandler = GetPressAndHoldHandler(msg.Value); - timerHandler(deviceKey, action); + if (timerHandler == null) + { + return; } + + timerHandler(deviceKey, action); } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/RoomEventScheduleMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/RoomEventScheduleMessenger.cs index b8f5fefff..845934dc1 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/RoomEventScheduleMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/RoomEventScheduleMessenger.cs @@ -6,71 +6,70 @@ using System; using System.Collections.Generic; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class RoomEventScheduleMessenger : MessengerBase { - public class RoomEventScheduleMessenger : MessengerBase - { - private readonly IRoomEventSchedule _room; + private readonly IRoomEventSchedule _room; - public RoomEventScheduleMessenger(string key, string messagePath, IRoomEventSchedule room) - : base(key, messagePath, room as IKeyName) - { - _room = room; - } + public RoomEventScheduleMessenger(string key, string messagePath, IRoomEventSchedule room) + : base(key, messagePath, room as IKeyName) + { + _room = room; + } - #region Overrides of MessengerBase + #region Overrides of MessengerBase - protected override void RegisterActions() + protected override void RegisterActions() + { + AddAction("/saveScheduledEvents", (id, content) => SaveScheduledEvents(content.ToObject>())); + AddAction("/status", (id, content) => { - AddAction("/saveScheduledEvents", (id, content) => SaveScheduledEvents(content.ToObject>())); - AddAction("/status", (id, content) => - { - var events = _room.GetScheduledEvents(); + var events = _room.GetScheduledEvents(); - SendFullStatus(events); - }); + SendFullStatus(events); + }); - _room.ScheduledEventsChanged += (sender, args) => SendFullStatus(args.ScheduledEvents); - } + _room.ScheduledEventsChanged += (sender, args) => SendFullStatus(args.ScheduledEvents); + } - #endregion + #endregion - private void SaveScheduledEvents(List events) + private void SaveScheduledEvents(List events) + { + foreach (var evt in events) { - foreach (var evt in events) - { - SaveScheduledEvent(evt); - } + SaveScheduledEvent(evt); } + } - private void SaveScheduledEvent(ScheduledEventConfig eventConfig) + private void SaveScheduledEvent(ScheduledEventConfig eventConfig) + { + try { - try - { - _room.AddOrUpdateScheduledEvent(eventConfig); - } - catch (Exception ex) - { - this.LogException(ex,"Exception saving event"); - } + _room.AddOrUpdateScheduledEvent(eventConfig); } - - private void SendFullStatus(List events) + catch (Exception ex) { - - var message = new RoomEventScheduleStateMessage - { - ScheduleEvents = events, - }; - - PostStatusMessage(message); + this.LogException(ex,"Exception saving event"); } } - public class RoomEventScheduleStateMessage : DeviceStateMessageBase + private void SendFullStatus(List events) { - [JsonProperty("scheduleEvents")] - public List ScheduleEvents { get; set; } + + var message = new RoomEventScheduleStateMessage + { + ScheduleEvents = events, + }; + + PostStatusMessage(message); } +} + +public class RoomEventScheduleStateMessage : DeviceStateMessageBase +{ + [JsonProperty("scheduleEvents")] + public List ScheduleEvents { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ShadeBaseMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ShadeBaseMessenger.cs index ff41670a5..13d1bcfbc 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ShadeBaseMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ShadeBaseMessenger.cs @@ -3,98 +3,97 @@ using PepperDash.Essentials.Core.Shades; using System; -namespace PepperDash.Essentials.AppServer.Messengers -{ - public class IShadesOpenCloseStopMessenger : MessengerBase - { - private readonly IShadesOpenCloseStop device; +namespace PepperDash.Essentials.AppServer.Messengers; - public IShadesOpenCloseStopMessenger(string key, IShadesOpenCloseStop shades, string messagePath) - : base(key, messagePath, shades as IKeyName) - { - device = shades; - } +public class IShadesOpenCloseStopMessenger : MessengerBase +{ + private readonly IShadesOpenCloseStop device; - protected override void RegisterActions() - { - base.RegisterActions(); + public IShadesOpenCloseStopMessenger(string key, IShadesOpenCloseStop shades, string messagePath) + : base(key, messagePath, shades as IKeyName) + { + device = shades; + } - AddAction("/fullStatus", (id, content) => SendFullStatus()); + protected override void RegisterActions() + { + base.RegisterActions(); - AddAction("/shadeUp", (id, content) => - { + AddAction("/fullStatus", (id, content) => SendFullStatus()); - device.Open(); + AddAction("/shadeUp", (id, content) => + { - }); + device.Open(); - AddAction("/shadeDown", (id, content) => - { + }); - device.Close(); + AddAction("/shadeDown", (id, content) => + { - }); + device.Close(); - var stopDevice = device; - if (stopDevice != null) - { - AddAction("/stopOrPreset", (id, content) => - { - stopDevice.Stop(); - }); - } + }); - if (device is IShadesOpenClosedFeedback feedbackDevice) + var stopDevice = device; + if (stopDevice != null) + { + AddAction("/stopOrPreset", (id, content) => { - feedbackDevice.ShadeIsOpenFeedback.OutputChange += new EventHandler(ShadeIsOpenFeedback_OutputChange); - feedbackDevice.ShadeIsClosedFeedback.OutputChange += new EventHandler(ShadeIsClosedFeedback_OutputChange); - } + stopDevice.Stop(); + }); } - private void ShadeIsOpenFeedback_OutputChange(object sender, Core.FeedbackEventArgs e) + if (device is IShadesOpenClosedFeedback feedbackDevice) { - var state = new ShadeBaseStateMessage - { - IsOpen = e.BoolValue - }; - - PostStatusMessage(state); + feedbackDevice.ShadeIsOpenFeedback.OutputChange += new EventHandler(ShadeIsOpenFeedback_OutputChange); + feedbackDevice.ShadeIsClosedFeedback.OutputChange += new EventHandler(ShadeIsClosedFeedback_OutputChange); } + } - private void ShadeIsClosedFeedback_OutputChange(object sender, Core.FeedbackEventArgs e) + private void ShadeIsOpenFeedback_OutputChange(object sender, Core.FeedbackEventArgs e) + { + var state = new ShadeBaseStateMessage { - var state = new ShadeBaseStateMessage - { - IsClosed = e.BoolValue - }; - - PostStatusMessage(state); - } + IsOpen = e.BoolValue + }; + PostStatusMessage(state); + } - private void SendFullStatus() + private void ShadeIsClosedFeedback_OutputChange(object sender, Core.FeedbackEventArgs e) + { + var state = new ShadeBaseStateMessage { - var state = new ShadeBaseStateMessage(); - - if (device is IShadesOpenClosedFeedback feedbackDevice) - { - state.IsOpen = feedbackDevice.ShadeIsOpenFeedback.BoolValue; - state.IsClosed = feedbackDevice.ShadeIsClosedFeedback.BoolValue; - } + IsClosed = e.BoolValue + }; - PostStatusMessage(state); - } + PostStatusMessage(state); } - public class ShadeBaseStateMessage : DeviceStateMessageBase + + private void SendFullStatus() { - [JsonProperty("middleButtonLabel", NullValueHandling = NullValueHandling.Ignore)] - public string MiddleButtonLabel { get; set; } + var state = new ShadeBaseStateMessage(); - [JsonProperty("isOpen", NullValueHandling = NullValueHandling.Ignore)] - public bool? IsOpen { get; set; } + if (device is IShadesOpenClosedFeedback feedbackDevice) + { + state.IsOpen = feedbackDevice.ShadeIsOpenFeedback.BoolValue; + state.IsClosed = feedbackDevice.ShadeIsClosedFeedback.BoolValue; + } - [JsonProperty("isClosed", NullValueHandling = NullValueHandling.Ignore)] - public bool? IsClosed { get; set; } + PostStatusMessage(state); } +} + +public class ShadeBaseStateMessage : DeviceStateMessageBase +{ + [JsonProperty("middleButtonLabel", NullValueHandling = NullValueHandling.Ignore)] + public string MiddleButtonLabel { get; set; } + + [JsonProperty("isOpen", NullValueHandling = NullValueHandling.Ignore)] + public bool? IsOpen { get; set; } + + [JsonProperty("isClosed", NullValueHandling = NullValueHandling.Ignore)] + public bool? IsClosed { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/SystemMonitorMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/SystemMonitorMessenger.cs index 2cb2ced09..4d6f040c6 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/SystemMonitorMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/SystemMonitorMessenger.cs @@ -6,104 +6,103 @@ using System; using System.Threading.Tasks; -namespace PepperDash.Essentials.AppServer.Messengers -{ - public class SystemMonitorMessenger : MessengerBase - { - private readonly SystemMonitorController systemMonitor; - - public SystemMonitorMessenger(string key, SystemMonitorController sysMon, string messagePath) - : base(key, messagePath, sysMon) - { - systemMonitor = sysMon ?? throw new ArgumentNullException("sysMon"); +namespace PepperDash.Essentials.AppServer.Messengers; - systemMonitor.SystemMonitorPropertiesChanged += SysMon_SystemMonitorPropertiesChanged; +public class SystemMonitorMessenger : MessengerBase +{ + private readonly SystemMonitorController systemMonitor; - foreach (var p in systemMonitor.ProgramStatusFeedbackCollection) - { - p.Value.ProgramInfoChanged += ProgramInfoChanged; - } + public SystemMonitorMessenger(string key, SystemMonitorController sysMon, string messagePath) + : base(key, messagePath, sysMon) + { + systemMonitor = sysMon ?? throw new ArgumentNullException("sysMon"); - CrestronConsole.AddNewConsoleCommand(s => SendFullStatusMessage(), "SendFullSysMonStatus", - "Sends the full System Monitor Status", ConsoleAccessLevelEnum.AccessOperator); - } + systemMonitor.SystemMonitorPropertiesChanged += SysMon_SystemMonitorPropertiesChanged; - /// - /// Posts the program information message - /// - /// - /// - private void ProgramInfoChanged(object sender, ProgramInfoEventArgs e) + foreach (var p in systemMonitor.ProgramStatusFeedbackCollection) { - if (e.ProgramInfo != null) - { - //Debug.Console(1, "Posting Status Message: {0}", e.ProgramInfo.ToString()); - PostStatusMessage(JToken.FromObject(e.ProgramInfo) - ); - } + p.Value.ProgramInfoChanged += ProgramInfoChanged; } - /// - /// Posts the system monitor properties - /// - /// - /// - private void SysMon_SystemMonitorPropertiesChanged(object sender, EventArgs e) + CrestronConsole.AddNewConsoleCommand(s => SendFullStatusMessage(), "SendFullSysMonStatus", + "Sends the full System Monitor Status", ConsoleAccessLevelEnum.AccessOperator); + } + + /// + /// Posts the program information message + /// + /// + /// + private void ProgramInfoChanged(object sender, ProgramInfoEventArgs e) + { + if (e.ProgramInfo != null) { - SendSystemMonitorStatusMessage(); + //Debug.Console(1, "Posting Status Message: {0}", e.ProgramInfo.ToString()); + PostStatusMessage(JToken.FromObject(e.ProgramInfo) + ); } + } - private void SendFullStatusMessage() - { - SendSystemMonitorStatusMessage(); + /// + /// Posts the system monitor properties + /// + /// + /// + private void SysMon_SystemMonitorPropertiesChanged(object sender, EventArgs e) + { + SendSystemMonitorStatusMessage(); + } - foreach (var p in systemMonitor.ProgramStatusFeedbackCollection) - { - PostStatusMessage(JToken.FromObject(p.Value.ProgramInfo)); - } - } + private void SendFullStatusMessage() + { + SendSystemMonitorStatusMessage(); - private void SendSystemMonitorStatusMessage() + foreach (var p in systemMonitor.ProgramStatusFeedbackCollection) { - // This takes a while, launch a new thread - - Task.Run(() => PostStatusMessage(JToken.FromObject(new SystemMonitorStateMessage - { - - TimeZone = systemMonitor.TimeZoneFeedback.IntValue, - TimeZoneName = systemMonitor.TimeZoneTextFeedback.StringValue, - IoControllerVersion = systemMonitor.IoControllerVersionFeedback.StringValue, - SnmpVersion = systemMonitor.SnmpVersionFeedback.StringValue, - BacnetVersion = systemMonitor.BaCnetAppVersionFeedback.StringValue, - ControllerVersion = systemMonitor.ControllerVersionFeedback.StringValue - }) - )); + PostStatusMessage(JToken.FromObject(p.Value.ProgramInfo)); } + } - protected override void RegisterActions() + private void SendSystemMonitorStatusMessage() + { + // This takes a while, launch a new thread + + Task.Run(() => PostStatusMessage(JToken.FromObject(new SystemMonitorStateMessage { - AddAction("/fullStatus", (id, content) => SendFullStatusMessage()); - } + + TimeZone = systemMonitor.TimeZoneFeedback.IntValue, + TimeZoneName = systemMonitor.TimeZoneTextFeedback.StringValue, + IoControllerVersion = systemMonitor.IoControllerVersionFeedback.StringValue, + SnmpVersion = systemMonitor.SnmpVersionFeedback.StringValue, + BacnetVersion = systemMonitor.BaCnetAppVersionFeedback.StringValue, + ControllerVersion = systemMonitor.ControllerVersionFeedback.StringValue + }) + )); } - public class SystemMonitorStateMessage + protected override void RegisterActions() { - [JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)] - public int TimeZone { get; set; } + AddAction("/fullStatus", (id, content) => SendFullStatusMessage()); + } +} - [JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)] - public string TimeZoneName { get; set; } +public class SystemMonitorStateMessage +{ + [JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)] + public int TimeZone { get; set; } - [JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)] - public string IoControllerVersion { get; set; } + [JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)] + public string TimeZoneName { get; set; } - [JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)] - public string SnmpVersion { get; set; } + [JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)] + public string IoControllerVersion { get; set; } - [JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)] - public string BacnetVersion { get; set; } + [JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)] + public string SnmpVersion { get; set; } - [JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)] - public string ControllerVersion { get; set; } - } + [JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)] + public string BacnetVersion { get; set; } + + [JsonProperty("timeZone", NullValueHandling = NullValueHandling.Ignore)] + public string ControllerVersion { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/TwoWayDisplayBaseMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/TwoWayDisplayBaseMessenger.cs index f0600dd51..d721a7943 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/TwoWayDisplayBaseMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/TwoWayDisplayBaseMessenger.cs @@ -3,91 +3,90 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Devices.Common.Displays; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class TwoWayDisplayBaseMessenger : MessengerBase { - public class TwoWayDisplayBaseMessenger : MessengerBase - { - private readonly TwoWayDisplayBase _display; + private readonly TwoWayDisplayBase _display; - public TwoWayDisplayBaseMessenger(string key, string messagePath, TwoWayDisplayBase display) - : base(key, messagePath, display) - { - _display = display; - } + public TwoWayDisplayBaseMessenger(string key, string messagePath, TwoWayDisplayBase display) + : base(key, messagePath, display) + { + _display = display; + } - #region Overrides of MessengerBase + #region Overrides of MessengerBase - public void SendFullStatus() + public void SendFullStatus() + { + var messageObj = new TwoWayDisplayBaseStateMessage { - var messageObj = new TwoWayDisplayBaseStateMessage - { - //PowerState = _display.PowerIsOnFeedback.BoolValue, - CurrentInput = _display.CurrentInputFeedback.StringValue - }; + //PowerState = _display.PowerIsOnFeedback.BoolValue, + CurrentInput = _display.CurrentInputFeedback.StringValue + }; - PostStatusMessage(messageObj); - } + PostStatusMessage(messageObj); + } - protected override void RegisterActions() - { - base.RegisterActions(); + protected override void RegisterActions() + { + base.RegisterActions(); - AddAction("/fullStatus", (id, content) => SendFullStatus()); + AddAction("/fullStatus", (id, content) => SendFullStatus()); - //_display.PowerIsOnFeedback.OutputChange += PowerIsOnFeedbackOnOutputChange; - _display.CurrentInputFeedback.OutputChange += CurrentInputFeedbackOnOutputChange; - _display.IsCoolingDownFeedback.OutputChange += IsCoolingFeedbackOnOutputChange; - _display.IsWarmingUpFeedback.OutputChange += IsWarmingFeedbackOnOutputChange; - } + //_display.PowerIsOnFeedback.OutputChange += PowerIsOnFeedbackOnOutputChange; + _display.CurrentInputFeedback.OutputChange += CurrentInputFeedbackOnOutputChange; + _display.IsCoolingDownFeedback.OutputChange += IsCoolingFeedbackOnOutputChange; + _display.IsWarmingUpFeedback.OutputChange += IsWarmingFeedbackOnOutputChange; + } - private void CurrentInputFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs) - { - PostStatusMessage(JToken.FromObject(new - { - currentInput = feedbackEventArgs.StringValue - }) - ); - } - - - //private void PowerIsOnFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs) - //{ - // PostStatusMessage(JToken.FromObject(new - // { - // powerState = feedbackEventArgs.BoolValue - // }) - // ); - //} - - private void IsWarmingFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs) - { - PostStatusMessage(JToken.FromObject(new - { - isWarming = feedbackEventArgs.BoolValue - }) - ); - } - - private void IsCoolingFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs) + private void CurrentInputFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs) + { + PostStatusMessage(JToken.FromObject(new { - PostStatusMessage(JToken.FromObject(new - { - isCooling = feedbackEventArgs.BoolValue - }) - ); + currentInput = feedbackEventArgs.StringValue + }) + ); + } - } + //private void PowerIsOnFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs) + //{ + // PostStatusMessage(JToken.FromObject(new + // { + // powerState = feedbackEventArgs.BoolValue + // }) + // ); + //} - #endregion + private void IsWarmingFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs) + { + PostStatusMessage(JToken.FromObject(new + { + isWarming = feedbackEventArgs.BoolValue + }) + ); } - public class TwoWayDisplayBaseStateMessage : DeviceStateMessageBase + private void IsCoolingFeedbackOnOutputChange(object sender, FeedbackEventArgs feedbackEventArgs) { - //[JsonProperty("powerState", NullValueHandling = NullValueHandling.Ignore)] - //public bool? PowerState { get; set; } + PostStatusMessage(JToken.FromObject(new + { + isCooling = feedbackEventArgs.BoolValue + }) + ); + - [JsonProperty("currentInput", NullValueHandling = NullValueHandling.Ignore)] - public string CurrentInput { get; set; } } + + #endregion +} + +public class TwoWayDisplayBaseStateMessage : DeviceStateMessageBase +{ + //[JsonProperty("powerState", NullValueHandling = NullValueHandling.Ignore)] + //public bool? PowerState { get; set; } + + [JsonProperty("currentInput", NullValueHandling = NullValueHandling.Ignore)] + public string CurrentInput { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/VideoCodecBaseMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/VideoCodecBaseMessenger.cs index 16cf642e1..69ecbf064 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/VideoCodecBaseMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/VideoCodecBaseMessenger.cs @@ -13,1080 +13,1079 @@ using System.Collections.Generic; using System.Linq; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +/// +/// Provides a messaging bridge for a VideoCodecBase device +/// +public class VideoCodecBaseMessenger : MessengerBase { /// - /// Provides a messaging bridge for a VideoCodecBase device + /// /// - public class VideoCodecBaseMessenger : MessengerBase - { - /// - /// - /// - protected VideoCodecBase Codec { get; private set; } - - + protected VideoCodecBase Codec { get; private set; } - /// - /// - /// - /// - /// - /// - public VideoCodecBaseMessenger(string key, VideoCodecBase codec, string messagePath) - : base(key, messagePath, codec) - { - Codec = codec ?? throw new ArgumentNullException("codec"); - codec.CallStatusChange += Codec_CallStatusChange; - codec.IsReadyChange += Codec_IsReadyChange; - if (codec is IHasDirectory dirCodec) - { - dirCodec.DirectoryResultReturned += DirCodec_DirectoryResultReturned; - } - if (codec is IHasCallHistory recCodec) - { - recCodec.CallHistory.RecentCallsListHasChanged += CallHistory_RecentCallsListHasChanged; - } + /// + /// + /// + /// + /// + /// + public VideoCodecBaseMessenger(string key, VideoCodecBase codec, string messagePath) + : base(key, messagePath, codec) + { + Codec = codec ?? throw new ArgumentNullException("codec"); + codec.CallStatusChange += Codec_CallStatusChange; + codec.IsReadyChange += Codec_IsReadyChange; - if (codec is IPasswordPrompt pwPromptCodec) - { - pwPromptCodec.PasswordRequired += OnPasswordRequired; - } + if (codec is IHasDirectory dirCodec) + { + dirCodec.DirectoryResultReturned += DirCodec_DirectoryResultReturned; } - private void OnPasswordRequired(object sender, PasswordPromptEventArgs args) + if (codec is IHasCallHistory recCodec) { - var eventMsg = new PasswordPromptEventMessage - { - Message = args.Message, - LastAttemptWasIncorrect = args.LastAttemptWasIncorrect, - LoginAttemptFailed = args.LoginAttemptFailed, - LoginAttemptCancelled = args.LoginAttemptCancelled, - EventType = "passwordPrompt" - }; + recCodec.CallHistory.RecentCallsListHasChanged += CallHistory_RecentCallsListHasChanged; + } - PostEventMessage(eventMsg); + if (codec is IPasswordPrompt pwPromptCodec) + { + pwPromptCodec.PasswordRequired += OnPasswordRequired; } + } - /// - /// - /// - /// - /// - private void CallHistory_RecentCallsListHasChanged(object sender, EventArgs e) + private void OnPasswordRequired(object sender, PasswordPromptEventArgs args) + { + var eventMsg = new PasswordPromptEventMessage { - try - { - var state = new VideoCodecBaseStateMessage(); + Message = args.Message, + LastAttemptWasIncorrect = args.LastAttemptWasIncorrect, + LoginAttemptFailed = args.LoginAttemptFailed, + LoginAttemptCancelled = args.LoginAttemptCancelled, + EventType = "passwordPrompt" + }; + + PostEventMessage(eventMsg); + } - if (!(sender is CodecCallHistory codecCallHistory)) return; - var recents = codecCallHistory.RecentCalls; + /// + /// + /// + /// + /// + private void CallHistory_RecentCallsListHasChanged(object sender, EventArgs e) + { + try + { + var state = new VideoCodecBaseStateMessage(); - if (recents != null) - { - state.RecentCalls = recents; + if (!(sender is CodecCallHistory codecCallHistory)) return; + var recents = codecCallHistory.RecentCalls; - PostStatusMessage(state); - } - } - catch (Exception ex) + if (recents != null) { - this.LogError(ex, "Error posting call history"); + state.RecentCalls = recents; + + PostStatusMessage(state); } } - - /// - /// - /// - /// - /// - protected virtual void DirCodec_DirectoryResultReturned(object sender, DirectoryEventArgs e) + catch (Exception ex) { - if (Codec is IHasDirectory) - SendDirectory(e.Directory); + this.LogError(ex, "Error posting call history"); } + } - /// - /// Posts the current directory - /// - protected void SendDirectory(CodecDirectory directory) + /// + /// + /// + /// + /// + protected virtual void DirCodec_DirectoryResultReturned(object sender, DirectoryEventArgs e) + { + if (Codec is IHasDirectory) + SendDirectory(e.Directory); + } + + /// + /// Posts the current directory + /// + protected void SendDirectory(CodecDirectory directory) + { + try { - try - { - var state = new VideoCodecBaseStateMessage(); + var state = new VideoCodecBaseStateMessage(); - if (Codec is IHasDirectory dirCodec) - { - this.LogVerbose("Sending Directory. Directory Item Count: {directoryItemCount}", directory.CurrentDirectoryResults.Count); + if (Codec is IHasDirectory dirCodec) + { + this.LogVerbose("Sending Directory. Directory Item Count: {directoryItemCount}", directory.CurrentDirectoryResults.Count); - //state.CurrentDirectory = PrefixDirectoryFolderItems(directory); - state.CurrentDirectory = directory; + //state.CurrentDirectory = PrefixDirectoryFolderItems(directory); + state.CurrentDirectory = directory; - CrestronInvoke.BeginInvoke((o) => PostStatusMessage(state)); - } - } - catch (Exception ex) - { - this.LogError(ex, "Error sending directory"); + CrestronInvoke.BeginInvoke((o) => PostStatusMessage(state)); } } - - /// - /// - /// - /// - /// - private void Codec_IsReadyChange(object sender, EventArgs e) + catch (Exception ex) { - try - { - var state = new VideoCodecBaseStateMessage - { - IsReady = true - }; - - PostStatusMessage(state); - - SendFullStatus(); - } catch (Exception ex) - { - this.LogError(ex, "Error sending codec ready status"); - } + this.LogError(ex, "Error sending directory"); } + } - /// - /// Called from base's RegisterWithAppServer method - /// - /// - protected override void RegisterActions() + /// + /// + /// + /// + /// + private void Codec_IsReadyChange(object sender, EventArgs e) + { + try { - try + var state = new VideoCodecBaseStateMessage { - base.RegisterActions(); - - AddAction("/isReady", (id, content) => SendIsReady()); + IsReady = true + }; - AddAction("/fullStatus", (id, content) => SendFullStatus()); + PostStatusMessage(state); - AddAction("/dial", (id, content) => - { - var value = content.ToObject>(); - - Codec.Dial(value.Value); - }); + SendFullStatus(); + } catch (Exception ex) + { + this.LogError(ex, "Error sending codec ready status"); + } + } - AddAction("/dialMeeting", (id, content) => Codec.Dial(content.ToObject())); + /// + /// Called from base's RegisterWithAppServer method + /// + /// + protected override void RegisterActions() + { + try + { + base.RegisterActions(); - AddAction("/endCallById", (id, content) => - { - var s = content.ToObject>(); - var call = GetCallWithId(s.Value); - if (call != null) - Codec.EndCall(call); - }); + AddAction("/isReady", (id, content) => SendIsReady()); - AddAction("/endAllCalls", (id, content) => Codec.EndAllCalls()); + AddAction("/fullStatus", (id, content) => SendFullStatus()); - AddAction("/dtmf", (id, content) => - { - var s = content.ToObject>(); - Codec.SendDtmf(s.Value); - }); + AddAction("/dial", (id, content) => + { + var value = content.ToObject>(); - AddAction("/rejectById", (id, content) => - { - var s = content.ToObject>(); + Codec.Dial(value.Value); + }); - var call = GetCallWithId(s.Value); - if (call != null) - Codec.RejectCall(call); - }); + AddAction("/dialMeeting", (id, content) => Codec.Dial(content.ToObject())); - AddAction("/acceptById", (id, content) => - { - var s = content.ToObject>(); + AddAction("/endCallById", (id, content) => + { + var s = content.ToObject>(); + var call = GetCallWithId(s.Value); + if (call != null) + Codec.EndCall(call); + }); - var call = GetCallWithId(s.Value); - if (call != null) - Codec.AcceptCall(call); - }); + AddAction("/endAllCalls", (id, content) => Codec.EndAllCalls()); - Codec.SharingContentIsOnFeedback.OutputChange += SharingContentIsOnFeedback_OutputChange; - Codec.SharingSourceFeedback.OutputChange += SharingSourceFeedback_OutputChange; + AddAction("/dtmf", (id, content) => + { + var s = content.ToObject>(); + Codec.SendDtmf(s.Value); + }); - // Directory actions - if (Codec is IHasDirectory dirCodec) - { - AddAction("/getDirectory", (id, content) => GetDirectoryRoot()); + AddAction("/rejectById", (id, content) => + { + var s = content.ToObject>(); - AddAction("/directoryById", (id, content) => - { - var msg = content.ToObject>(); - GetDirectory(msg.Value); - }); + var call = GetCallWithId(s.Value); + if (call != null) + Codec.RejectCall(call); + }); - AddAction("/directorySearch", (id, content) => - { - var msg = content.ToObject>(); + AddAction("/acceptById", (id, content) => + { + var s = content.ToObject>(); - GetDirectory(msg.Value); - }); + var call = GetCallWithId(s.Value); + if (call != null) + Codec.AcceptCall(call); + }); - AddAction("/directoryBack", (id, content) => GetPreviousDirectory()); + Codec.SharingContentIsOnFeedback.OutputChange += SharingContentIsOnFeedback_OutputChange; + Codec.SharingSourceFeedback.OutputChange += SharingSourceFeedback_OutputChange; - dirCodec.PhonebookSyncState.InitialSyncCompleted += PhonebookSyncState_InitialSyncCompleted; - } + // Directory actions + if (Codec is IHasDirectory dirCodec) + { + AddAction("/getDirectory", (id, content) => GetDirectoryRoot()); - // History actions - if (Codec is IHasCallHistory recCodec) + AddAction("/directoryById", (id, content) => { - AddAction("/getCallHistory", (id, content) => PostCallHistory()); - } - if (Codec is IHasCodecCameras cameraCodec) + var msg = content.ToObject>(); + GetDirectory(msg.Value); + }); + + AddAction("/directorySearch", (id, content) => { - this.LogVerbose("Adding IHasCodecCameras Actions"); + var msg = content.ToObject>(); - cameraCodec.CameraSelected += CameraCodec_CameraSelected; + GetDirectory(msg.Value); + }); - AddAction("/cameraSelect", (id, content) => - { - var msg = content.ToObject>(); + AddAction("/directoryBack", (id, content) => GetPreviousDirectory()); - cameraCodec.SelectCamera(msg.Value); - }); + dirCodec.PhonebookSyncState.InitialSyncCompleted += PhonebookSyncState_InitialSyncCompleted; + } + // History actions + if (Codec is IHasCallHistory recCodec) + { + AddAction("/getCallHistory", (id, content) => PostCallHistory()); + } + if (Codec is IHasCodecCameras cameraCodec) + { + this.LogVerbose("Adding IHasCodecCameras Actions"); - MapCameraActions(); + cameraCodec.CameraSelected += CameraCodec_CameraSelected; - if (Codec is IHasCodecRoomPresets presetsCodec) - { - this.LogVerbose("Adding IHasCodecRoomPresets Actions"); + AddAction("/cameraSelect", (id, content) => + { + var msg = content.ToObject>(); - presetsCodec.CodecRoomPresetsListHasChanged += PresetsCodec_CameraPresetsListHasChanged; + cameraCodec.SelectCamera(msg.Value); + }); - AddAction("/cameraPreset", (id, content) => - { - var msg = content.ToObject>(); - presetsCodec.CodecRoomPresetSelect(msg.Value); - }); + MapCameraActions(); - AddAction("/cameraPresetStore", (id, content) => - { - var msg = content.ToObject(); + if (Codec is IHasCodecRoomPresets presetsCodec) + { + this.LogVerbose("Adding IHasCodecRoomPresets Actions"); - presetsCodec.CodecRoomPresetStore(msg.ID, msg.Description); - }); - } + presetsCodec.CodecRoomPresetsListHasChanged += PresetsCodec_CameraPresetsListHasChanged; - if (Codec is IHasCameraAutoMode speakerTrackCodec) + AddAction("/cameraPreset", (id, content) => { - this.LogVerbose("Adding IHasCameraAutoMode Actions"); - - speakerTrackCodec.CameraAutoModeIsOnFeedback.OutputChange += CameraAutoModeIsOnFeedback_OutputChange; + var msg = content.ToObject>(); - AddAction("/cameraModeAuto", (id, content) => speakerTrackCodec.CameraAutoModeOn()); - - AddAction("/cameraModeManual", (id, content) => speakerTrackCodec.CameraAutoModeOff()); - } + presetsCodec.CodecRoomPresetSelect(msg.Value); + }); - if (Codec is IHasCameraOff cameraOffCodec) + AddAction("/cameraPresetStore", (id, content) => { - this.LogVerbose("Adding IHasCameraOff Actions"); - - cameraOffCodec.CameraIsOffFeedback.OutputChange += (CameraIsOffFeedback_OutputChange); + var msg = content.ToObject(); - AddAction("/cameraModeOff", (id, content) => cameraOffCodec.CameraOff()); - } + presetsCodec.CodecRoomPresetStore(msg.ID, msg.Description); + }); } - - - if (Codec is IHasCodecSelfView selfViewCodec) + if (Codec is IHasCameraAutoMode speakerTrackCodec) { - this.LogVerbose("Adding IHasCodecSelfView Actions"); + this.LogVerbose("Adding IHasCameraAutoMode Actions"); - AddAction("/cameraSelfView", (id, content) => selfViewCodec.SelfViewModeToggle()); + speakerTrackCodec.CameraAutoModeIsOnFeedback.OutputChange += CameraAutoModeIsOnFeedback_OutputChange; - selfViewCodec.SelfviewIsOnFeedback.OutputChange += new EventHandler(SelfviewIsOnFeedback_OutputChange); - } + AddAction("/cameraModeAuto", (id, content) => speakerTrackCodec.CameraAutoModeOn()); + AddAction("/cameraModeManual", (id, content) => speakerTrackCodec.CameraAutoModeOff()); + } - if (Codec is IHasCodecLayouts layoutsCodec) + if (Codec is IHasCameraOff cameraOffCodec) { - this.LogVerbose("Adding IHasCodecLayouts Actions"); + this.LogVerbose("Adding IHasCameraOff Actions"); - AddAction("/cameraRemoteView", (id, content) => layoutsCodec.LocalLayoutToggle()); + cameraOffCodec.CameraIsOffFeedback.OutputChange += (CameraIsOffFeedback_OutputChange); - AddAction("/cameraLayout", (id, content) => layoutsCodec.LocalLayoutToggle()); + AddAction("/cameraModeOff", (id, content) => cameraOffCodec.CameraOff()); } + } - if (Codec is IPasswordPrompt pwCodec) - { - this.LogVerbose("Adding IPasswordPrompt Actions"); - AddAction("/password", (id, content) => - { - var msg = content.ToObject>(); - pwCodec.SubmitPassword(msg.Value); - }); - } + if (Codec is IHasCodecSelfView selfViewCodec) + { + this.LogVerbose("Adding IHasCodecSelfView Actions"); + AddAction("/cameraSelfView", (id, content) => selfViewCodec.SelfViewModeToggle()); - if (Codec is IHasFarEndContentStatus farEndContentStatus) - { - farEndContentStatus.ReceivingContent.OutputChange += - (sender, args) => PostReceivingContent(args.BoolValue); - } + selfViewCodec.SelfviewIsOnFeedback.OutputChange += new EventHandler(SelfviewIsOnFeedback_OutputChange); + } - this.LogVerbose("Adding Privacy & Standby Actions"); - AddAction("/privacyModeOn", (id, content) => Codec.PrivacyModeOn()); - AddAction("/privacyModeOff", (id, content) => Codec.PrivacyModeOff()); - AddAction("/privacyModeToggle", (id, content) => Codec.PrivacyModeToggle()); - AddAction("/sharingStart", (id, content) => Codec.StartSharing()); - AddAction("/sharingStop", (id, content) => Codec.StopSharing()); - AddAction("/standbyOn", (id, content) => Codec.StandbyActivate()); - AddAction("/standbyOff", (id, content) => Codec.StandbyDeactivate()); - } - catch (Exception e) + if (Codec is IHasCodecLayouts layoutsCodec) { - this.LogException(e, "Exception adding paths"); + this.LogVerbose("Adding IHasCodecLayouts Actions"); + + AddAction("/cameraRemoteView", (id, content) => layoutsCodec.LocalLayoutToggle()); + + AddAction("/cameraLayout", (id, content) => layoutsCodec.LocalLayoutToggle()); } - } - private void SharingSourceFeedback_OutputChange(object sender, FeedbackEventArgs e) - { - try + if (Codec is IPasswordPrompt pwCodec) { - var state = new VideoCodecBaseStateMessage + this.LogVerbose("Adding IPasswordPrompt Actions"); + + AddAction("/password", (id, content) => { - SharingSource = e.StringValue - }; + var msg = content.ToObject>(); - PostStatusMessage(state); - } catch (Exception ex) - { - this.LogError(ex, "Error posting sharing source"); + pwCodec.SubmitPassword(msg.Value); + }); } - } - private void SharingContentIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) - { - try - { - var state = new VideoCodecBaseStateMessage - { - SharingContentIsOn = e.BoolValue - }; - PostStatusMessage(state); - } catch (Exception ex) + if (Codec is IHasFarEndContentStatus farEndContentStatus) { - this.LogError(ex, "Error posting sharing content"); + farEndContentStatus.ReceivingContent.OutputChange += + (sender, args) => PostReceivingContent(args.BoolValue); } + + this.LogVerbose("Adding Privacy & Standby Actions"); + + AddAction("/privacyModeOn", (id, content) => Codec.PrivacyModeOn()); + AddAction("/privacyModeOff", (id, content) => Codec.PrivacyModeOff()); + AddAction("/privacyModeToggle", (id, content) => Codec.PrivacyModeToggle()); + AddAction("/sharingStart", (id, content) => Codec.StartSharing()); + AddAction("/sharingStop", (id, content) => Codec.StopSharing()); + AddAction("/standbyOn", (id, content) => Codec.StandbyActivate()); + AddAction("/standbyOff", (id, content) => Codec.StandbyDeactivate()); } + catch (Exception e) + { + this.LogException(e, "Exception adding paths"); + } + } - private void PhonebookSyncState_InitialSyncCompleted(object sender, EventArgs e) + private void SharingSourceFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + try { - try + var state = new VideoCodecBaseStateMessage { - var state = new VideoCodecBaseStateMessage - { - InitialPhonebookSyncComplete = true - }; + SharingSource = e.StringValue + }; - PostStatusMessage(state); - } - catch (Exception ex) - { - this.LogError(ex, "Error posting phonebook sync state"); - } + PostStatusMessage(state); + } catch (Exception ex) + { + this.LogError(ex, "Error posting sharing source"); } + } - private void CameraIsOffFeedback_OutputChange(object sender, FeedbackEventArgs e) + private void SharingContentIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + try { - PostCameraMode(); - } + var state = new VideoCodecBaseStateMessage + { + SharingContentIsOn = e.BoolValue + }; - private void SelfviewIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + PostStatusMessage(state); + } catch (Exception ex) { - PostCameraSelfView(); + this.LogError(ex, "Error posting sharing content"); } + } - private void PresetsCodec_CameraPresetsListHasChanged(object sender, EventArgs e) + private void PhonebookSyncState_InitialSyncCompleted(object sender, EventArgs e) + { + try { - PostCameraPresets(); - } + var state = new VideoCodecBaseStateMessage + { + InitialPhonebookSyncComplete = true + }; - private void CameraAutoModeIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + PostStatusMessage(state); + } + catch (Exception ex) { - PostCameraMode(); + this.LogError(ex, "Error posting phonebook sync state"); } + } + private void CameraIsOffFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + PostCameraMode(); + } + + private void SelfviewIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + PostCameraSelfView(); + } + + private void PresetsCodec_CameraPresetsListHasChanged(object sender, EventArgs e) + { + PostCameraPresets(); + } - private void CameraCodec_CameraSelected(object sender, CameraSelectedEventArgs e) + private void CameraAutoModeIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + PostCameraMode(); + } + + + private void CameraCodec_CameraSelected(object sender, CameraSelectedEventArgs e) + { + try { - try - { - MapCameraActions(); - PostSelectedCamera(); - } catch(Exception ex) - { - this.LogError(ex, "Exception handling camera selected event"); - } + MapCameraActions(); + PostSelectedCamera(); + } catch(Exception ex) + { + this.LogError(ex, "Exception handling camera selected event"); } + } - /// - /// Maps the camera control actions to the current selected camera on the codec - /// - private void MapCameraActions() + /// + /// Maps the camera control actions to the current selected camera on the codec + /// + private void MapCameraActions() + { + if (Codec is IHasCameras cameraCodec && cameraCodec.SelectedCamera != null) { - if (Codec is IHasCameras cameraCodec && cameraCodec.SelectedCamera != null) + RemoveAction("/cameraUp"); + RemoveAction("/cameraDown"); + RemoveAction("/cameraLeft"); + RemoveAction("/cameraRight"); + RemoveAction("/cameraZoomIn"); + RemoveAction("/cameraZoomOut"); + RemoveAction("/cameraHome"); + + if (cameraCodec.SelectedCamera is IHasCameraPtzControl camera) { - RemoveAction("/cameraUp"); - RemoveAction("/cameraDown"); - RemoveAction("/cameraLeft"); - RemoveAction("/cameraRight"); - RemoveAction("/cameraZoomIn"); - RemoveAction("/cameraZoomOut"); - RemoveAction("/cameraHome"); - - if (cameraCodec.SelectedCamera is IHasCameraPtzControl camera) + AddAction("/cameraUp", (id, content) => HandleCameraPressAndHold(content, (b) => { - AddAction("/cameraUp", (id, content) => HandleCameraPressAndHold(content, (b) => + if (b) { - if (b) - { - camera.TiltUp(); - return; - } + camera.TiltUp(); + return; + } - camera.TiltStop(); - })); + camera.TiltStop(); + })); - AddAction("/cameraDown", (id, content) => HandleCameraPressAndHold(content, (b) => + AddAction("/cameraDown", (id, content) => HandleCameraPressAndHold(content, (b) => + { + if (b) { - if (b) - { - camera.TiltDown(); - return; - } + camera.TiltDown(); + return; + } - camera.TiltStop(); - })); + camera.TiltStop(); + })); - AddAction("/cameraLeft", (id, content) => HandleCameraPressAndHold(content, (b) => + AddAction("/cameraLeft", (id, content) => HandleCameraPressAndHold(content, (b) => + { + if (b) { - if (b) - { - camera.PanLeft(); - return; - } + camera.PanLeft(); + return; + } - camera.PanStop(); - })); + camera.PanStop(); + })); - AddAction("/cameraRight", (id, content) => HandleCameraPressAndHold(content, (b) => + AddAction("/cameraRight", (id, content) => HandleCameraPressAndHold(content, (b) => + { + if (b) { - if (b) - { - camera.PanRight(); - return; - } + camera.PanRight(); + return; + } - camera.PanStop(); - })); + camera.PanStop(); + })); + + AddAction("/cameraZoomIn", (id, content) => HandleCameraPressAndHold(content, (b) => + { + if (b) + { + camera.ZoomIn(); + return; + } + + camera.ZoomStop(); + })); - AddAction("/cameraZoomIn", (id, content) => HandleCameraPressAndHold(content, (b) => + AddAction("/cameraZoomOut", (id, content) => HandleCameraPressAndHold(content, (b) => + { + if (b) + { + camera.ZoomOut(); + return; + } + + camera.ZoomStop(); + })); + AddAction("/cameraHome", (id, content) => camera.PositionHome()); + + + RemoveAction("/cameraAutoFocus"); + RemoveAction("/cameraFocusNear"); + RemoveAction("/cameraFocusFar"); + + if (cameraCodec is IHasCameraFocusControl focusCamera) + { + AddAction("/cameraAutoFocus", (id, content) => focusCamera.TriggerAutoFocus()); + + AddAction("/cameraFocusNear", (id, content) => HandleCameraPressAndHold(content, (b) => { if (b) { - camera.ZoomIn(); + focusCamera.FocusNear(); return; } - camera.ZoomStop(); + focusCamera.FocusStop(); })); - AddAction("/cameraZoomOut", (id, content) => HandleCameraPressAndHold(content, (b) => + AddAction("/cameraFocusFar", (id, content) => HandleCameraPressAndHold(content, (b) => { if (b) { - camera.ZoomOut(); + focusCamera.FocusFar(); return; } - camera.ZoomStop(); + focusCamera.FocusStop(); })); - AddAction("/cameraHome", (id, content) => camera.PositionHome()); - - - RemoveAction("/cameraAutoFocus"); - RemoveAction("/cameraFocusNear"); - RemoveAction("/cameraFocusFar"); - - if (cameraCodec is IHasCameraFocusControl focusCamera) - { - AddAction("/cameraAutoFocus", (id, content) => focusCamera.TriggerAutoFocus()); - - AddAction("/cameraFocusNear", (id, content) => HandleCameraPressAndHold(content, (b) => - { - if (b) - { - focusCamera.FocusNear(); - return; - } - - focusCamera.FocusStop(); - })); - - AddAction("/cameraFocusFar", (id, content) => HandleCameraPressAndHold(content, (b) => - { - if (b) - { - focusCamera.FocusFar(); - return; - } - - focusCamera.FocusStop(); - })); - } } } } + } + + private void HandleCameraPressAndHold(JToken content, Action cameraAction) + { + var state = content.ToObject>(); - private void HandleCameraPressAndHold(JToken content, Action cameraAction) + var timerHandler = PressAndHoldHandler.GetPressAndHoldHandler(state.Value); + if (timerHandler == null) { - var state = content.ToObject>(); + return; + } - var timerHandler = PressAndHoldHandler.GetPressAndHoldHandler(state.Value); - if (timerHandler == null) - { - return; - } + timerHandler(state.Value, cameraAction); - timerHandler(state.Value, cameraAction); + cameraAction(state.Value.Equals("true", StringComparison.InvariantCultureIgnoreCase)); + } - cameraAction(state.Value.Equals("true", StringComparison.InvariantCultureIgnoreCase)); - } + private string GetCameraMode() + { + string m = ""; - private string GetCameraMode() + if (Codec is IHasCameraAutoMode speakerTrackCodec) { - string m = ""; - - if (Codec is IHasCameraAutoMode speakerTrackCodec) - { - m = speakerTrackCodec.CameraAutoModeIsOnFeedback.BoolValue - ? eCameraControlMode.Auto.ToString().ToLower() - : eCameraControlMode.Manual.ToString().ToLower(); - } - - if (Codec is IHasCameraOff cameraOffCodec) - { - if (cameraOffCodec.CameraIsOffFeedback.BoolValue) - m = eCameraControlMode.Off.ToString().ToLower(); - } + m = speakerTrackCodec.CameraAutoModeIsOnFeedback.BoolValue + ? eCameraControlMode.Auto.ToString().ToLower() + : eCameraControlMode.Manual.ToString().ToLower(); + } - return m; + if (Codec is IHasCameraOff cameraOffCodec) + { + if (cameraOffCodec.CameraIsOffFeedback.BoolValue) + m = eCameraControlMode.Off.ToString().ToLower(); } - private void PostCallHistory() + return m; + } + + private void PostCallHistory() + { + try { - try - { - var codec = (Codec as IHasCallHistory); + var codec = (Codec as IHasCallHistory); - if (codec != null) - { - var status = new VideoCodecBaseStateMessage(); + if (codec != null) + { + var status = new VideoCodecBaseStateMessage(); - var recents = codec.CallHistory.RecentCalls; + var recents = codec.CallHistory.RecentCalls; - if (recents != null) - { - status.RecentCalls = codec.CallHistory.RecentCalls; + if (recents != null) + { + status.RecentCalls = codec.CallHistory.RecentCalls; - PostStatusMessage(status); - } + PostStatusMessage(status); } } - catch (Exception ex) - { - this.LogError(ex, "Error posting call history"); - } } + catch (Exception ex) + { + this.LogError(ex, "Error posting call history"); + } + } - /// - /// Helper to grab a call with string ID - /// - /// - /// - private CodecActiveCallItem GetCallWithId(string id) + /// + /// Helper to grab a call with string ID + /// + /// + /// + private CodecActiveCallItem GetCallWithId(string id) + { + return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id); + } + + /// + /// + /// + /// + private void GetDirectory(string id) + { + if (!(Codec is IHasDirectory dirCodec)) { - return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id); + return; } + dirCodec.GetDirectoryFolderContents(id); + } - /// - /// - /// - /// - private void GetDirectory(string id) + /// + /// + /// + private void GetDirectoryRoot() + { + try { if (!(Codec is IHasDirectory dirCodec)) { + // do something else? return; } - dirCodec.GetDirectoryFolderContents(id); - } - - /// - /// - /// - private void GetDirectoryRoot() - { - try + if (!dirCodec.PhonebookSyncState.InitialSyncComplete) { - if (!(Codec is IHasDirectory dirCodec)) - { - // do something else? - return; - } - if (!dirCodec.PhonebookSyncState.InitialSyncComplete) + var state = new VideoCodecBaseStateMessage { - var state = new VideoCodecBaseStateMessage - { - InitialPhonebookSyncComplete = false - }; - - PostStatusMessage(state); - return; - } - - dirCodec.SetCurrentDirectoryToRoot(); - } - catch (Exception ex) - { - this.LogError(ex, "Error getting directory root"); - } - } + InitialPhonebookSyncComplete = false + }; - /// - /// Requests the parent folder contents - /// - private void GetPreviousDirectory() - { - if (!(Codec is IHasDirectory dirCodec)) - { + PostStatusMessage(state); return; } - dirCodec.GetDirectoryParentFolderContents(); + dirCodec.SetCurrentDirectoryToRoot(); + } + catch (Exception ex) + { + this.LogError(ex, "Error getting directory root"); } + } - /// - /// Handler for codec changes - /// - private void Codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e) + /// + /// Requests the parent folder contents + /// + private void GetPreviousDirectory() + { + if (!(Codec is IHasDirectory dirCodec)) { - SendFullStatus(); + return; } - /// - /// - /// - private void SendIsReady() + dirCodec.GetDirectoryParentFolderContents(); + } + + /// + /// Handler for codec changes + /// + private void Codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e) + { + SendFullStatus(); + } + + /// + /// + /// + private void SendIsReady() + { + try { - try - { - var status = new VideoCodecBaseStateMessage(); + var status = new VideoCodecBaseStateMessage(); - var codecType = Codec.GetType(); + var codecType = Codec.GetType(); - status.IsReady = Codec.IsReady; - status.IsZoomRoom = codecType.GetInterface("IHasZoomRoomLayouts") != null; + status.IsReady = Codec.IsReady; + status.IsZoomRoom = codecType.GetInterface("IHasZoomRoomLayouts") != null; - PostStatusMessage(status); - } - catch (Exception ex) - { - this.LogError(ex, "Error sending codec ready status"); - } + PostStatusMessage(status); } - - /// - /// Helper method to build call status for vtc - /// - /// - protected VideoCodecBaseStateMessage GetStatus() + catch (Exception ex) { - try - { - var status = new VideoCodecBaseStateMessage(); - - if (Codec is IHasCodecCameras camerasCodec) - { - status.Cameras = new CameraStatus - { - CameraManualIsSupported = true, - CameraAutoIsSupported = Codec.SupportsCameraAutoMode, - CameraOffIsSupported = Codec.SupportsCameraOff, - CameraMode = GetCameraMode(), - Cameras = camerasCodec.Cameras, - SelectedCamera = GetSelectedCamera(camerasCodec) - }; - } + this.LogError(ex, "Error sending codec ready status"); + } + } - if (Codec is IHasDirectory directoryCodec) - { - status.HasDirectory = true; - status.HasDirectorySearch = true; - status.CurrentDirectory = directoryCodec.CurrentDirectoryResult; - } + /// + /// Helper method to build call status for vtc + /// + /// + protected VideoCodecBaseStateMessage GetStatus() + { + try + { + var status = new VideoCodecBaseStateMessage(); - var codecType = Codec.GetType(); - - status.CameraSelfViewIsOn = Codec is IHasCodecSelfView && (Codec as IHasCodecSelfView).SelfviewIsOnFeedback.BoolValue; - status.IsInCall = Codec.IsInCall; - status.PrivacyModeIsOn = Codec.PrivacyModeIsOnFeedback.BoolValue; - status.SharingContentIsOn = Codec.SharingContentIsOnFeedback.BoolValue; - status.SharingSource = Codec.SharingSourceFeedback.StringValue; - status.StandbyIsOn = Codec.StandbyIsOnFeedback.BoolValue; - status.Calls = Codec.ActiveCalls; - status.Info = Codec.CodecInfo; - status.ShowSelfViewByDefault = Codec.ShowSelfViewByDefault; - status.SupportsAdHocMeeting = Codec is IHasStartMeeting; - status.HasRecents = Codec is IHasCallHistory; - status.HasCameras = Codec is IHasCameras; - status.Presets = GetCurrentPresets(); - status.IsZoomRoom = codecType.GetInterface("IHasZoomRoomLayouts") != null; - status.ReceivingContent = Codec is IHasFarEndContentStatus && (Codec as IHasFarEndContentStatus).ReceivingContent.BoolValue; - - if (Codec is IHasMeetingInfo meetingInfoCodec) + if (Codec is IHasCodecCameras camerasCodec) + { + status.Cameras = new CameraStatus { - status.MeetingInfo = meetingInfoCodec.MeetingInfo; - } - - return status; + CameraManualIsSupported = true, + CameraAutoIsSupported = Codec.SupportsCameraAutoMode, + CameraOffIsSupported = Codec.SupportsCameraOff, + CameraMode = GetCameraMode(), + Cameras = camerasCodec.Cameras, + SelectedCamera = GetSelectedCamera(camerasCodec) + }; } - catch (Exception ex) + + if (Codec is IHasDirectory directoryCodec) { - this.LogError(ex, "Error getting codec status"); - return null; + status.HasDirectory = true; + status.HasDirectorySearch = true; + status.CurrentDirectory = directoryCodec.CurrentDirectoryResult; } - } - protected virtual void SendFullStatus() - { - if (!Codec.IsReady) + var codecType = Codec.GetType(); + + status.CameraSelfViewIsOn = Codec is IHasCodecSelfView && (Codec as IHasCodecSelfView).SelfviewIsOnFeedback.BoolValue; + status.IsInCall = Codec.IsInCall; + status.PrivacyModeIsOn = Codec.PrivacyModeIsOnFeedback.BoolValue; + status.SharingContentIsOn = Codec.SharingContentIsOnFeedback.BoolValue; + status.SharingSource = Codec.SharingSourceFeedback.StringValue; + status.StandbyIsOn = Codec.StandbyIsOnFeedback.BoolValue; + status.Calls = Codec.ActiveCalls; + status.Info = Codec.CodecInfo; + status.ShowSelfViewByDefault = Codec.ShowSelfViewByDefault; + status.SupportsAdHocMeeting = Codec is IHasStartMeeting; + status.HasRecents = Codec is IHasCallHistory; + status.HasCameras = Codec is IHasCameras; + status.Presets = GetCurrentPresets(); + status.IsZoomRoom = codecType.GetInterface("IHasZoomRoomLayouts") != null; + status.ReceivingContent = Codec is IHasFarEndContentStatus && (Codec as IHasFarEndContentStatus).ReceivingContent.BoolValue; + + if (Codec is IHasMeetingInfo meetingInfoCodec) { - return; + status.MeetingInfo = meetingInfoCodec.MeetingInfo; } - CrestronInvoke.BeginInvoke((o) => PostStatusMessage(GetStatus())); + return status; } - - private void PostReceivingContent(bool receivingContent) + catch (Exception ex) { - try - { - var state = new VideoCodecBaseStateMessage - { - ReceivingContent = receivingContent - }; + this.LogError(ex, "Error getting codec status"); + return null; + } + } - PostStatusMessage(state); - } catch(Exception ex) - { - this.LogError(ex, "Error posting receiving content"); - } + protected virtual void SendFullStatus() + { + if (!Codec.IsReady) + { + return; } - private void PostCameraSelfView() + CrestronInvoke.BeginInvoke((o) => PostStatusMessage(GetStatus())); + } + + private void PostReceivingContent(bool receivingContent) + { + try { - try + var state = new VideoCodecBaseStateMessage { - var status = new VideoCodecBaseStateMessage - { - CameraSelfViewIsOn = Codec is IHasCodecSelfView - && (Codec as IHasCodecSelfView).SelfviewIsOnFeedback.BoolValue - }; + ReceivingContent = receivingContent + }; - PostStatusMessage(status); - } - catch (Exception ex) - { - this.LogError(ex, "Error posting camera self view"); - } + PostStatusMessage(state); + } catch(Exception ex) + { + this.LogError(ex, "Error posting receiving content"); } + } - /// - /// - /// - private void PostCameraMode() + private void PostCameraSelfView() + { + try { - try + var status = new VideoCodecBaseStateMessage { - var status = new VideoCodecBaseStateMessage - { - CameraMode = GetCameraMode() - }; + CameraSelfViewIsOn = Codec is IHasCodecSelfView + && (Codec as IHasCodecSelfView).SelfviewIsOnFeedback.BoolValue + }; - PostStatusMessage(status); - } - catch (Exception ex) - { - this.LogError(ex, "Error posting camera mode"); - } + PostStatusMessage(status); + } + catch (Exception ex) + { + this.LogError(ex, "Error posting camera self view"); } + } - private void PostSelectedCamera() + /// + /// + /// + private void PostCameraMode() + { + try { - try + var status = new VideoCodecBaseStateMessage { - var camerasCodec = Codec as IHasCodecCameras; + CameraMode = GetCameraMode() + }; - var status = new VideoCodecBaseStateMessage - { - Cameras = new CameraStatus() { SelectedCamera = GetSelectedCamera(camerasCodec) }, - Presets = GetCurrentPresets() - }; + PostStatusMessage(status); + } + catch (Exception ex) + { + this.LogError(ex, "Error posting camera mode"); + } + } - PostStatusMessage(status); - } - catch (Exception e) + private void PostSelectedCamera() + { + try + { + var camerasCodec = Codec as IHasCodecCameras; + + var status = new VideoCodecBaseStateMessage { - this.LogError(e, "Error posting selected camera"); - } + Cameras = new CameraStatus() { SelectedCamera = GetSelectedCamera(camerasCodec) }, + Presets = GetCurrentPresets() + }; + + PostStatusMessage(status); } + catch (Exception e) + { + this.LogError(e, "Error posting selected camera"); + } + } - private void PostCameraPresets() + private void PostCameraPresets() + { + try { - try + var status = new VideoCodecBaseStateMessage { - var status = new VideoCodecBaseStateMessage - { - Presets = GetCurrentPresets() - }; + Presets = GetCurrentPresets() + }; - PostStatusMessage(status); - } - catch (Exception e) - { - this.LogError(e, "Error posting camera presets"); - } + PostStatusMessage(status); + } + catch (Exception e) + { + this.LogError(e, "Error posting camera presets"); } + } + + private Camera GetSelectedCamera(IHasCodecCameras camerasCodec) + { + var camera = new Camera(); - private Camera GetSelectedCamera(IHasCodecCameras camerasCodec) + if (camerasCodec.SelectedCameraFeedback != null) + camera.Key = camerasCodec.SelectedCameraFeedback.StringValue; + if (camerasCodec.SelectedCamera != null) { - var camera = new Camera(); + camera.Name = camerasCodec.SelectedCamera.Name; - if (camerasCodec.SelectedCameraFeedback != null) - camera.Key = camerasCodec.SelectedCameraFeedback.StringValue; - if (camerasCodec.SelectedCamera != null) + camera.Capabilities = new CameraCapabilities() { - camera.Name = camerasCodec.SelectedCamera.Name; - - camera.Capabilities = new CameraCapabilities() - { - CanPan = camerasCodec.SelectedCamera.CanPan, - CanTilt = camerasCodec.SelectedCamera.CanTilt, - CanZoom = camerasCodec.SelectedCamera.CanZoom, - CanFocus = camerasCodec.SelectedCamera.CanFocus, - }; - } + CanPan = camerasCodec.SelectedCamera.CanPan, + CanTilt = camerasCodec.SelectedCamera.CanTilt, + CanZoom = camerasCodec.SelectedCamera.CanZoom, + CanFocus = camerasCodec.SelectedCamera.CanFocus, + }; + } - if (camerasCodec.ControllingFarEndCameraFeedback != null) - camera.IsFarEnd = camerasCodec.ControllingFarEndCameraFeedback.BoolValue; + if (camerasCodec.ControllingFarEndCameraFeedback != null) + camera.IsFarEnd = camerasCodec.ControllingFarEndCameraFeedback.BoolValue; - return camera; - } + return camera; + } - private List GetCurrentPresets() - { - var presetsCodec = Codec as IHasCodecRoomPresets; + private List GetCurrentPresets() + { + var presetsCodec = Codec as IHasCodecRoomPresets; - List currentPresets = null; + List currentPresets = null; - if (presetsCodec != null && Codec is IHasFarEndCameraControl && - (Codec as IHasFarEndCameraControl).ControllingFarEndCameraFeedback.BoolValue) - currentPresets = presetsCodec.FarEndRoomPresets; - else if (presetsCodec != null) currentPresets = presetsCodec.NearEndPresets; + if (presetsCodec != null && Codec is IHasFarEndCameraControl && + (Codec as IHasFarEndCameraControl).ControllingFarEndCameraFeedback.BoolValue) + currentPresets = presetsCodec.FarEndRoomPresets; + else if (presetsCodec != null) currentPresets = presetsCodec.NearEndPresets; - return currentPresets; - } + return currentPresets; } +} - /// - /// A class that represents the state data to be sent to the user app - /// - public class VideoCodecBaseStateMessage : DeviceStateMessageBase - { +/// +/// A class that represents the state data to be sent to the user app +/// +public class VideoCodecBaseStateMessage : DeviceStateMessageBase +{ - [JsonProperty("calls", NullValueHandling = NullValueHandling.Ignore)] - public List Calls { get; set; } + [JsonProperty("calls", NullValueHandling = NullValueHandling.Ignore)] + public List Calls { get; set; } - [JsonProperty("cameraMode", NullValueHandling = NullValueHandling.Ignore)] - public string CameraMode { get; set; } + [JsonProperty("cameraMode", NullValueHandling = NullValueHandling.Ignore)] + public string CameraMode { get; set; } - [JsonProperty("cameraSelfView", NullValueHandling = NullValueHandling.Ignore)] - public bool? CameraSelfViewIsOn { get; set; } + [JsonProperty("cameraSelfView", NullValueHandling = NullValueHandling.Ignore)] + public bool? CameraSelfViewIsOn { get; set; } - [JsonProperty("cameras", NullValueHandling = NullValueHandling.Ignore)] - public CameraStatus Cameras { get; set; } + [JsonProperty("cameras", NullValueHandling = NullValueHandling.Ignore)] + public CameraStatus Cameras { get; set; } - [JsonProperty("cameraSupportsAutoMode", NullValueHandling = NullValueHandling.Ignore)] - public bool? CameraSupportsAutoMode { get; set; } + [JsonProperty("cameraSupportsAutoMode", NullValueHandling = NullValueHandling.Ignore)] + public bool? CameraSupportsAutoMode { get; set; } - [JsonProperty("cameraSupportsOffMode", NullValueHandling = NullValueHandling.Ignore)] - public bool? CameraSupportsOffMode { get; set; } + [JsonProperty("cameraSupportsOffMode", NullValueHandling = NullValueHandling.Ignore)] + public bool? CameraSupportsOffMode { get; set; } - [JsonProperty("currentDialString", NullValueHandling = NullValueHandling.Ignore)] - public string CurrentDialString { get; set; } + [JsonProperty("currentDialString", NullValueHandling = NullValueHandling.Ignore)] + public string CurrentDialString { get; set; } - [JsonProperty("currentDirectory", NullValueHandling = NullValueHandling.Ignore)] - public CodecDirectory CurrentDirectory { get; set; } + [JsonProperty("currentDirectory", NullValueHandling = NullValueHandling.Ignore)] + public CodecDirectory CurrentDirectory { get; set; } - [JsonProperty("directorySelectedFolderName", NullValueHandling = NullValueHandling.Ignore)] - public string DirectorySelectedFolderName { get; set; } + [JsonProperty("directorySelectedFolderName", NullValueHandling = NullValueHandling.Ignore)] + public string DirectorySelectedFolderName { get; set; } - [JsonProperty("hasCameras", NullValueHandling = NullValueHandling.Ignore)] - public bool? HasCameras { get; set; } + [JsonProperty("hasCameras", NullValueHandling = NullValueHandling.Ignore)] + public bool? HasCameras { get; set; } - [JsonProperty("hasDirectory", NullValueHandling = NullValueHandling.Ignore)] - public bool? HasDirectory { get; set; } + [JsonProperty("hasDirectory", NullValueHandling = NullValueHandling.Ignore)] + public bool? HasDirectory { get; set; } - [JsonProperty("hasDirectorySearch", NullValueHandling = NullValueHandling.Ignore)] - public bool? HasDirectorySearch { get; set; } + [JsonProperty("hasDirectorySearch", NullValueHandling = NullValueHandling.Ignore)] + public bool? HasDirectorySearch { get; set; } - [JsonProperty("hasPresets", NullValueHandling = NullValueHandling.Ignore)] - public bool? HasPresets { get; set; } + [JsonProperty("hasPresets", NullValueHandling = NullValueHandling.Ignore)] + public bool? HasPresets { get; set; } - [JsonProperty("hasRecents", NullValueHandling = NullValueHandling.Ignore)] - public bool? HasRecents { get; set; } + [JsonProperty("hasRecents", NullValueHandling = NullValueHandling.Ignore)] + public bool? HasRecents { get; set; } - [JsonProperty("initialPhonebookSyncComplete", NullValueHandling = NullValueHandling.Ignore)] - public bool? InitialPhonebookSyncComplete { get; set; } + [JsonProperty("initialPhonebookSyncComplete", NullValueHandling = NullValueHandling.Ignore)] + public bool? InitialPhonebookSyncComplete { get; set; } - [JsonProperty("info", NullValueHandling = NullValueHandling.Ignore)] - public VideoCodecInfo Info { get; set; } + [JsonProperty("info", NullValueHandling = NullValueHandling.Ignore)] + public VideoCodecInfo Info { get; set; } - [JsonProperty("isInCall", NullValueHandling = NullValueHandling.Ignore)] - public bool? IsInCall { get; set; } + [JsonProperty("isInCall", NullValueHandling = NullValueHandling.Ignore)] + public bool? IsInCall { get; set; } - [JsonProperty("isReady", NullValueHandling = NullValueHandling.Ignore)] - public bool? IsReady { get; set; } + [JsonProperty("isReady", NullValueHandling = NullValueHandling.Ignore)] + public bool? IsReady { get; set; } - [JsonProperty("isZoomRoom", NullValueHandling = NullValueHandling.Ignore)] - public bool? IsZoomRoom { get; set; } + [JsonProperty("isZoomRoom", NullValueHandling = NullValueHandling.Ignore)] + public bool? IsZoomRoom { get; set; } - [JsonProperty("meetingInfo", NullValueHandling = NullValueHandling.Ignore)] - public MeetingInfo MeetingInfo { get; set; } + [JsonProperty("meetingInfo", NullValueHandling = NullValueHandling.Ignore)] + public MeetingInfo MeetingInfo { get; set; } - [JsonProperty("presets", NullValueHandling = NullValueHandling.Ignore)] - public List Presets { get; set; } + [JsonProperty("presets", NullValueHandling = NullValueHandling.Ignore)] + public List Presets { get; set; } - [JsonProperty("privacyModeIsOn", NullValueHandling = NullValueHandling.Ignore)] - public bool? PrivacyModeIsOn { get; set; } + [JsonProperty("privacyModeIsOn", NullValueHandling = NullValueHandling.Ignore)] + public bool? PrivacyModeIsOn { get; set; } - [JsonProperty("receivingContent", NullValueHandling = NullValueHandling.Ignore)] - public bool? ReceivingContent { get; set; } + [JsonProperty("receivingContent", NullValueHandling = NullValueHandling.Ignore)] + public bool? ReceivingContent { get; set; } - [JsonProperty("recentCalls", NullValueHandling = NullValueHandling.Ignore)] - public List RecentCalls { get; set; } + [JsonProperty("recentCalls", NullValueHandling = NullValueHandling.Ignore)] + public List RecentCalls { get; set; } - [JsonProperty("sharingContentIsOn", NullValueHandling = NullValueHandling.Ignore)] - public bool? SharingContentIsOn { get; set; } + [JsonProperty("sharingContentIsOn", NullValueHandling = NullValueHandling.Ignore)] + public bool? SharingContentIsOn { get; set; } - [JsonProperty("sharingSource", NullValueHandling = NullValueHandling.Ignore)] - public string SharingSource { get; set; } + [JsonProperty("sharingSource", NullValueHandling = NullValueHandling.Ignore)] + public string SharingSource { get; set; } - [JsonProperty("showCamerasWhenNotInCall", NullValueHandling = NullValueHandling.Ignore)] - public bool? ShowCamerasWhenNotInCall { get; set; } + [JsonProperty("showCamerasWhenNotInCall", NullValueHandling = NullValueHandling.Ignore)] + public bool? ShowCamerasWhenNotInCall { get; set; } - [JsonProperty("showSelfViewByDefault", NullValueHandling = NullValueHandling.Ignore)] - public bool? ShowSelfViewByDefault { get; set; } + [JsonProperty("showSelfViewByDefault", NullValueHandling = NullValueHandling.Ignore)] + public bool? ShowSelfViewByDefault { get; set; } - [JsonProperty("standbyIsOn", NullValueHandling = NullValueHandling.Ignore)] - public bool? StandbyIsOn { get; set; } + [JsonProperty("standbyIsOn", NullValueHandling = NullValueHandling.Ignore)] + public bool? StandbyIsOn { get; set; } - [JsonProperty("supportsAdHocMeeting", NullValueHandling = NullValueHandling.Ignore)] - public bool? SupportsAdHocMeeting { get; set; } - } + [JsonProperty("supportsAdHocMeeting", NullValueHandling = NullValueHandling.Ignore)] + public bool? SupportsAdHocMeeting { get; set; } +} - public class CameraStatus - { - [JsonProperty("cameraManualSupported", NullValueHandling = NullValueHandling.Ignore)] - public bool? CameraManualIsSupported { get; set; } +public class CameraStatus +{ + [JsonProperty("cameraManualSupported", NullValueHandling = NullValueHandling.Ignore)] + public bool? CameraManualIsSupported { get; set; } - [JsonProperty("cameraAutoSupported", NullValueHandling = NullValueHandling.Ignore)] - public bool? CameraAutoIsSupported { get; set; } + [JsonProperty("cameraAutoSupported", NullValueHandling = NullValueHandling.Ignore)] + public bool? CameraAutoIsSupported { get; set; } - [JsonProperty("cameraOffSupported", NullValueHandling = NullValueHandling.Ignore)] - public bool? CameraOffIsSupported { get; set; } + [JsonProperty("cameraOffSupported", NullValueHandling = NullValueHandling.Ignore)] + public bool? CameraOffIsSupported { get; set; } - [JsonProperty("cameraMode", NullValueHandling = NullValueHandling.Ignore)] - public string CameraMode { get; set; } + [JsonProperty("cameraMode", NullValueHandling = NullValueHandling.Ignore)] + public string CameraMode { get; set; } - [JsonProperty("cameraList", NullValueHandling = NullValueHandling.Ignore)] - public List Cameras { get; set; } + [JsonProperty("cameraList", NullValueHandling = NullValueHandling.Ignore)] + public List Cameras { get; set; } - [JsonProperty("selectedCamera", NullValueHandling = NullValueHandling.Ignore)] - public Camera SelectedCamera { get; set; } - } + [JsonProperty("selectedCamera", NullValueHandling = NullValueHandling.Ignore)] + public Camera SelectedCamera { get; set; } +} - public class Camera - { - [JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)] - public string Key { get; set; } +public class Camera +{ + [JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)] + public string Key { get; set; } - [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] - public string Name { get; set; } + [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] + public string Name { get; set; } - [JsonProperty("isFarEnd", NullValueHandling = NullValueHandling.Ignore)] - public bool? IsFarEnd { get; set; } + [JsonProperty("isFarEnd", NullValueHandling = NullValueHandling.Ignore)] + public bool? IsFarEnd { get; set; } - [JsonProperty("capabilities", NullValueHandling = NullValueHandling.Ignore)] - public CameraCapabilities Capabilities { get; set; } - } + [JsonProperty("capabilities", NullValueHandling = NullValueHandling.Ignore)] + public CameraCapabilities Capabilities { get; set; } +} - public class CameraCapabilities - { - [JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)] - public bool? CanPan { get; set; } +public class CameraCapabilities +{ + [JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)] + public bool? CanPan { get; set; } - [JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)] - public bool? CanTilt { get; set; } + [JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)] + public bool? CanTilt { get; set; } - [JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)] - public bool? CanZoom { get; set; } + [JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)] + public bool? CanZoom { get; set; } - [JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)] - public bool? CanFocus { get; set; } + [JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)] + public bool? CanFocus { get; set; } - } +} - public class VideoCodecBaseEventMessage : DeviceEventMessageBase - { +public class VideoCodecBaseEventMessage : DeviceEventMessageBase +{ - } +} - public class PasswordPromptEventMessage : VideoCodecBaseEventMessage - { - [JsonProperty("message", NullValueHandling = NullValueHandling.Ignore)] - public string Message { get; set; } - [JsonProperty("lastAttemptWasIncorrect", NullValueHandling = NullValueHandling.Ignore)] - public bool LastAttemptWasIncorrect { get; set; } +public class PasswordPromptEventMessage : VideoCodecBaseEventMessage +{ + [JsonProperty("message", NullValueHandling = NullValueHandling.Ignore)] + public string Message { get; set; } + [JsonProperty("lastAttemptWasIncorrect", NullValueHandling = NullValueHandling.Ignore)] + public bool LastAttemptWasIncorrect { get; set; } - [JsonProperty("loginAttemptFailed", NullValueHandling = NullValueHandling.Ignore)] - public bool LoginAttemptFailed { get; set; } + [JsonProperty("loginAttemptFailed", NullValueHandling = NullValueHandling.Ignore)] + public bool LoginAttemptFailed { get; set; } - [JsonProperty("loginAttemptCancelled", NullValueHandling = NullValueHandling.Ignore)] - public bool LoginAttemptCancelled { get; set; } - } + [JsonProperty("loginAttemptCancelled", NullValueHandling = NullValueHandling.Ignore)] + public bool LoginAttemptCancelled { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/MobileControlMessage.cs b/src/PepperDash.Essentials.MobileControl.Messengers/MobileControlMessage.cs index 6e92d9da0..8f109bec6 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/MobileControlMessage.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/MobileControlMessage.cs @@ -2,17 +2,16 @@ using Newtonsoft.Json.Linq; using PepperDash.Essentials.Core.DeviceTypeInterfaces; -namespace PepperDash.Essentials.AppServer.Messengers +namespace PepperDash.Essentials.AppServer.Messengers; + +public class MobileControlMessage : IMobileControlMessage { - public class MobileControlMessage : IMobileControlMessage - { - [JsonProperty("type")] - public string Type { get; set; } + [JsonProperty("type")] + public string Type { get; set; } - [JsonProperty("clientId")] - public string ClientId { get; set; } + [JsonProperty("clientId")] + public string ClientId { get; set; } - [JsonProperty("content")] - public JToken Content { get; set; } - } + [JsonProperty("content")] + public JToken Content { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/MobileControlSimpleContent.cs b/src/PepperDash.Essentials.MobileControl.Messengers/MobileControlSimpleContent.cs index 1d8047586..195714942 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/MobileControlSimpleContent.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/MobileControlSimpleContent.cs @@ -1,10 +1,9 @@ using Newtonsoft.Json; -namespace PepperDash.Essentials.AppServer +namespace PepperDash.Essentials.AppServer; + +public class MobileControlSimpleContent { - public class MobileControlSimpleContent - { - [JsonProperty("value", NullValueHandling = NullValueHandling.Ignore)] - public T Value { get; set; } - } + [JsonProperty("value", NullValueHandling = NullValueHandling.Ignore)] + public T Value { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/PepperDash.Essentials.MobileControl.Messengers.csproj b/src/PepperDash.Essentials.MobileControl.Messengers/PepperDash.Essentials.MobileControl.Messengers.csproj index 8739c95b0..be5c8fc4a 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/PepperDash.Essentials.MobileControl.Messengers.csproj +++ b/src/PepperDash.Essentials.MobileControl.Messengers/PepperDash.Essentials.MobileControl.Messengers.csproj @@ -1,7 +1,7 @@  PepperDash.Essentials.AppServer - net472 + net8 mobile-control-messengers mobile-control-messengers mobile-control-messengers @@ -32,7 +32,8 @@ - + + diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/SIMPLJoinMaps/MobileControlSIMPLRoomJoinMap.cs b/src/PepperDash.Essentials.MobileControl.Messengers/SIMPLJoinMaps/MobileControlSIMPLRoomJoinMap.cs index fd6e8713f..2770e67dc 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/SIMPLJoinMaps/MobileControlSIMPLRoomJoinMap.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/SIMPLJoinMaps/MobileControlSIMPLRoomJoinMap.cs @@ -1,570 +1,569 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.AppServer +namespace PepperDash.Essentials.AppServer; + +// ReSharper disable once InconsistentNaming +public class MobileControlSIMPLRoomJoinMap : JoinMapBaseAdvanced { - // ReSharper disable once InconsistentNaming - public class MobileControlSIMPLRoomJoinMap : JoinMapBaseAdvanced - { - [JoinName("QrCodeUrl")] - public JoinDataComplete QrCodeUrl = - new JoinDataComplete(new JoinData { JoinNumber = 403, JoinSpan = 1 }, - new JoinMetadata - { - Description = "QR Code URL", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("PortalSystemUrl")] - public JoinDataComplete PortalSystemUrl = - new JoinDataComplete(new JoinData { JoinNumber = 404, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Portal System URL", - JoinCapabilities = eJoinCapabilities.FromSIMPL, + [JoinName("QrCodeUrl")] + public JoinDataComplete QrCodeUrl = + new JoinDataComplete(new JoinData { JoinNumber = 403, JoinSpan = 1 }, + new JoinMetadata + { + Description = "QR Code URL", + JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); - [JoinName("MasterVolume")] - public JoinDataComplete MasterVolume = - new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Master Volume Mute Toggle/FB/Level/Label", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.DigitalAnalogSerial - }); - - [JoinName("VolumeJoinStart")] - public JoinDataComplete VolumeJoinStart = - new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 8 }, - new JoinMetadata - { - Description = "Volume Mute Toggle/FB/Level/Label", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.DigitalAnalogSerial - }); - - [JoinName("PrivacyMute")] - public JoinDataComplete PrivacyMute = - new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Privacy Mute Toggle/FB", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("PromptForCode")] - public JoinDataComplete PromptForCode = - new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Prompt User for Code", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ClientJoined")] - public JoinDataComplete ClientJoined = - new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Client Joined", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ActivityPhoneCallEnable")] - public JoinDataComplete ActivityPhoneCallEnable = - new JoinDataComplete(new JoinData { JoinNumber = 48, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Enable Activity Phone Call", - JoinCapabilities = eJoinCapabilities.FromSIMPL, + [JoinName("PortalSystemUrl")] + public JoinDataComplete PortalSystemUrl = + new JoinDataComplete(new JoinData { JoinNumber = 404, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Portal System URL", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("MasterVolume")] + public JoinDataComplete MasterVolume = + new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Master Volume Mute Toggle/FB/Level/Label", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.DigitalAnalogSerial + }); + + [JoinName("VolumeJoinStart")] + public JoinDataComplete VolumeJoinStart = + new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 8 }, + new JoinMetadata + { + Description = "Volume Mute Toggle/FB/Level/Label", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.DigitalAnalogSerial + }); + + [JoinName("PrivacyMute")] + public JoinDataComplete PrivacyMute = + new JoinDataComplete(new JoinData { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Privacy Mute Toggle/FB", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ActivityVideoCallEnable")] - public JoinDataComplete ActivityVideoCallEnable = - new JoinDataComplete(new JoinData { JoinNumber = 49, JoinSpan = 1 }, + [JoinName("PromptForCode")] + public JoinDataComplete PromptForCode = + new JoinDataComplete(new JoinData { JoinNumber = 41, JoinSpan = 1 }, new JoinMetadata { - Description = "Enable Activity Video Call", - JoinCapabilities = eJoinCapabilities.FromSIMPL, + Description = "Prompt User for Code", + JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ActivityShare")] - public JoinDataComplete ActivityShare = - new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Activity Share", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ActivityPhoneCall")] - public JoinDataComplete ActivityPhoneCall = - new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Activity Phone Call", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ActivityVideoCall")] - public JoinDataComplete ActivityVideoCall = - new JoinDataComplete(new JoinData { JoinNumber = 53, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Activity Video Call", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ShutdownPromptDuration")] - public JoinDataComplete ShutdownPromptDuration = - new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Shutdown Cancel", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("ShutdownCancel")] - public JoinDataComplete ShutdownCancel = - new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Shutdown Cancel", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ShutdownEnd")] - public JoinDataComplete ShutdownEnd = - new JoinDataComplete(new JoinData { JoinNumber = 62, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Shutdown End", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ShutdownStart")] - public JoinDataComplete ShutdownStart = - new JoinDataComplete(new JoinData { JoinNumber = 63, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Shutdown Start", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SourceHasChanged")] - public JoinDataComplete SourceHasChanged = - new JoinDataComplete(new JoinData { JoinNumber = 71, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Source Changed", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CurrentSourceKey")] - public JoinDataComplete CurrentSourceKey = - new JoinDataComplete(new JoinData { JoinNumber = 71, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Key of selected source", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Serial - }); - - - [JoinName("ConfigIsLocal")] - public JoinDataComplete ConfigIsLocal = - new JoinDataComplete(new JoinData { JoinNumber = 100, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Config is local to Essentials", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("NumberOfAuxFaders")] - public JoinDataComplete NumberOfAuxFaders = - new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Number of Auxilliary Faders", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("SpeedDialNameStartJoin")] - public JoinDataComplete SpeedDialNameStartJoin = - new JoinDataComplete(new JoinData { JoinNumber = 241, JoinSpan = 10 }, - new JoinMetadata - { - Description = "Speed Dial names", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SpeedDialNumberStartJoin")] - public JoinDataComplete SpeedDialNumberStartJoin = - new JoinDataComplete(new JoinData { JoinNumber = 251, JoinSpan = 10 }, - new JoinMetadata - { - Description = "Speed Dial numbers", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SpeedDialVisibleStartJoin")] - public JoinDataComplete SpeedDialVisibleStartJoin = - new JoinDataComplete(new JoinData { JoinNumber = 261, JoinSpan = 10 }, - new JoinMetadata - { - Description = "Speed Dial Visible", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("RoomIsOn")] - public JoinDataComplete RoomIsOn = - new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Room Is On", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("UserCodeToSystem")] - public JoinDataComplete UserCodeToSystem = - new JoinDataComplete(new JoinData { JoinNumber = 401, JoinSpan = 1 }, - new JoinMetadata - { - Description = "User Code", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("ServerUrl")] - public JoinDataComplete ServerUrl = - new JoinDataComplete(new JoinData { JoinNumber = 402, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Server URL", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("ConfigRoomName")] - public JoinDataComplete ConfigRoomName = - new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Room Name", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("ConfigHelpMessage")] - public JoinDataComplete ConfigHelpMessage = - new JoinDataComplete(new JoinData { JoinNumber = 502, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Room help message", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("ConfigHelpNumber")] - public JoinDataComplete ConfigHelpNumber = - new JoinDataComplete(new JoinData { JoinNumber = 503, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Room help number", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("ConfigRoomPhoneNumber")] - public JoinDataComplete ConfigRoomPhoneNumber = - new JoinDataComplete(new JoinData { JoinNumber = 504, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Room phone number", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("ConfigRoomURI")] - public JoinDataComplete ConfigRoomUri = - new JoinDataComplete(new JoinData { JoinNumber = 505, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Room URI", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("ApiOnlineAndAuthorized")] - public JoinDataComplete ApiOnlineAndAuthorized = - new JoinDataComplete(new JoinData { JoinNumber = 500, JoinSpan = 1 }, + [JoinName("ClientJoined")] + public JoinDataComplete ClientJoined = + new JoinDataComplete(new JoinData { JoinNumber = 42, JoinSpan = 1 }, new JoinMetadata { - Description = "Config info from SIMPL is ready", + Description = "Client Joined", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); - [JoinName("ConfigIsReady")] - public JoinDataComplete ConfigIsReady = - new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Config info from SIMPL is ready", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); + [JoinName("ActivityPhoneCallEnable")] + public JoinDataComplete ActivityPhoneCallEnable = + new JoinDataComplete(new JoinData { JoinNumber = 48, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Enable Activity Phone Call", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ActivityVideoCallEnable")] + public JoinDataComplete ActivityVideoCallEnable = + new JoinDataComplete(new JoinData { JoinNumber = 49, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Enable Activity Video Call", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ActivityShare")] + public JoinDataComplete ActivityShare = + new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Activity Share", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); - [JoinName("ReadyForConfig")] - public JoinDataComplete ReadyForConfig = - new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 1 }, + [JoinName("ActivityPhoneCall")] + public JoinDataComplete ActivityPhoneCall = + new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1 }, new JoinMetadata { - Description = "Config info from SIMPL is ready", - JoinCapabilities = eJoinCapabilities.ToSIMPL, + Description = "Activity Phone Call", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ActivityVideoCall")] + public JoinDataComplete ActivityVideoCall = + new JoinDataComplete(new JoinData { JoinNumber = 53, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Activity Video Call", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ShutdownPromptDuration")] + public JoinDataComplete ShutdownPromptDuration = + new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Shutdown Cancel", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("ShutdownCancel")] + public JoinDataComplete ShutdownCancel = + new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Shutdown Cancel", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ShutdownEnd")] + public JoinDataComplete ShutdownEnd = + new JoinDataComplete(new JoinData { JoinNumber = 62, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Shutdown End", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ShutdownStart")] + public JoinDataComplete ShutdownStart = + new JoinDataComplete(new JoinData { JoinNumber = 63, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Shutdown Start", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("HideVideoConfRecents")] - public JoinDataComplete HideVideoConfRecents = - new JoinDataComplete(new JoinData { JoinNumber = 502, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Hide Video Conference Recents", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("ShowCameraWhenNotInCall")] - public JoinDataComplete ShowCameraWhenNotInCall = - new JoinDataComplete(new JoinData { JoinNumber = 503, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Show camera when not in call", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("UseSourceEnabled")] - public JoinDataComplete UseSourceEnabled = - new JoinDataComplete(new JoinData { JoinNumber = 504, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Use Source Enabled Joins", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - - [JoinName("SourceShareDisableJoinStart")] - public JoinDataComplete SourceShareDisableJoinStart = - new JoinDataComplete(new JoinData { JoinNumber = 601, JoinSpan = 20 }, - new JoinMetadata - { - Description = "Source is not sharable", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SourceIsEnabledJoinStart")] - public JoinDataComplete SourceIsEnabledJoinStart = - new JoinDataComplete(new JoinData { JoinNumber = 621, JoinSpan = 20 }, - new JoinMetadata - { - Description = "Source is enabled/visible", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SourceIsControllableJoinStart")] - public JoinDataComplete SourceIsControllableJoinStart = - new JoinDataComplete(new JoinData { JoinNumber = 641, JoinSpan = 20 }, - new JoinMetadata - { - Description = "Source is controllable", + [JoinName("SourceHasChanged")] + public JoinDataComplete SourceHasChanged = + new JoinDataComplete(new JoinData { JoinNumber = 71, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Source Changed", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("SourceIsAudioSourceJoinStart")] - public JoinDataComplete SourceIsAudioSourceJoinStart = - new JoinDataComplete(new JoinData { JoinNumber = 661, JoinSpan = 20 }, + [JoinName("CurrentSourceKey")] + public JoinDataComplete CurrentSourceKey = + new JoinDataComplete(new JoinData { JoinNumber = 71, JoinSpan = 1 }, new JoinMetadata { - Description = "Source is Audio Source", + Description = "Key of selected source", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Serial + }); + + + [JoinName("ConfigIsLocal")] + public JoinDataComplete ConfigIsLocal = + new JoinDataComplete(new JoinData { JoinNumber = 100, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Config is local to Essentials", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("NumberOfAuxFaders")] + public JoinDataComplete NumberOfAuxFaders = + new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Number of Auxilliary Faders", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); - [JoinName("SourceNameJoinStart")] - public JoinDataComplete SourceNameJoinStart = - new JoinDataComplete(new JoinData { JoinNumber = 601, JoinSpan = 20 }, - new JoinMetadata - { - Description = "Source Names", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SourceIconJoinStart")] - public JoinDataComplete SourceIconJoinStart = - new JoinDataComplete(new JoinData { JoinNumber = 621, JoinSpan = 20 }, - new JoinMetadata - { - Description = "Source Icons", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SourceKeyJoinStart")] - public JoinDataComplete SourceKeyJoinStart = - new JoinDataComplete(new JoinData { JoinNumber = 641, JoinSpan = 20 }, - new JoinMetadata - { - Description = "Source Keys", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("SourceControlDeviceKeyJoinStart")] - public JoinDataComplete SourceControlDeviceKeyJoinStart = - new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 20 }, - new JoinMetadata - { - Description = "Source Control Device Keys", + [JoinName("SpeedDialNameStartJoin")] + public JoinDataComplete SpeedDialNameStartJoin = + new JoinDataComplete(new JoinData { JoinNumber = 241, JoinSpan = 10 }, + new JoinMetadata + { + Description = "Speed Dial names", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Serial }); - [JoinName("SourceTypeJoinStart")] - public JoinDataComplete SourceTypeJoinStart = - new JoinDataComplete(new JoinData { JoinNumber = 661, JoinSpan = 20 }, - new JoinMetadata - { - Description = "Source Types", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CameraNearNameStart")] - public JoinDataComplete CameraNearNameStart = - new JoinDataComplete(new JoinData { JoinNumber = 761, JoinSpan = 10 }, - new JoinMetadata - { - Description = "Near End Camera Names", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CameraFarName")] - public JoinDataComplete CameraFarName = - new JoinDataComplete(new JoinData { JoinNumber = 771, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Far End Camera Name", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - #region Advanced Sharing - [JoinName("SupportsAdvancedSharing")] - public JoinDataComplete SupportsAdvancedSharing = - new JoinDataComplete(new JoinData { JoinNumber = 505, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Supports Advanced Sharing", + [JoinName("SpeedDialNumberStartJoin")] + public JoinDataComplete SpeedDialNumberStartJoin = + new JoinDataComplete(new JoinData { JoinNumber = 251, JoinSpan = 10 }, + new JoinMetadata + { + Description = "Speed Dial numbers", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SpeedDialVisibleStartJoin")] + public JoinDataComplete SpeedDialVisibleStartJoin = + new JoinDataComplete(new JoinData { JoinNumber = 261, JoinSpan = 10 }, + new JoinMetadata + { + Description = "Speed Dial Visible", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - [JoinName("UseDestinationEnable")] - public JoinDataComplete UseDestinationEnable = - new JoinDataComplete(new JoinData { JoinNumber = 506, JoinSpan = 1 }, + [JoinName("RoomIsOn")] + public JoinDataComplete RoomIsOn = + new JoinDataComplete(new JoinData { JoinNumber = 301, JoinSpan = 1 }, new JoinMetadata { - Description = "Use Destination Enable", + Description = "Room Is On", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("UserCodeToSystem")] + public JoinDataComplete UserCodeToSystem = + new JoinDataComplete(new JoinData { JoinNumber = 401, JoinSpan = 1 }, + new JoinMetadata + { + Description = "User Code", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); - [JoinName("UserCanChangeShareMode")] - public JoinDataComplete UserCanChangeShareMode = - new JoinDataComplete(new JoinData { JoinNumber = 507, JoinSpan = 1 }, + [JoinName("ServerUrl")] + public JoinDataComplete ServerUrl = + new JoinDataComplete(new JoinData { JoinNumber = 402, JoinSpan = 1 }, new JoinMetadata { - Description = "Share Mode Toggle Visible to User", + Description = "Server URL", JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital + JoinType = eJoinType.Serial }); - [JoinName("DestinationNameJoinStart")] - public JoinDataComplete DestinationNameJoinStart = - new JoinDataComplete(new JoinData { JoinNumber = 801, JoinSpan = 10 }, + [JoinName("ConfigRoomName")] + public JoinDataComplete ConfigRoomName = + new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 1 }, new JoinMetadata { - Description = "Destination Name", + Description = "Room Name", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Serial }); - [JoinName("DestinationDeviceKeyJoinStart")] - public JoinDataComplete DestinationDeviceKeyJoinStart = - new JoinDataComplete(new JoinData { JoinNumber = 811, JoinSpan = 10 }, + [JoinName("ConfigHelpMessage")] + public JoinDataComplete ConfigHelpMessage = + new JoinDataComplete(new JoinData { JoinNumber = 502, JoinSpan = 1 }, new JoinMetadata { - Description = "Destination Device Key", + Description = "Room help message", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Serial }); - [JoinName("DestinationTypeJoinStart")] - public JoinDataComplete DestinationTypeJoinStart = - new JoinDataComplete(new JoinData { JoinNumber = 821, JoinSpan = 10 }, + [JoinName("ConfigHelpNumber")] + public JoinDataComplete ConfigHelpNumber = + new JoinDataComplete(new JoinData { JoinNumber = 503, JoinSpan = 1 }, new JoinMetadata { - Description = "Destination type. Should be Audio, Video, AudioVideo", + Description = "Room help number", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Serial }); - [JoinName("DestinationIsEnabledJoinStart")] - public JoinDataComplete DestinationIsEnabledJoinStart = - new JoinDataComplete(new JoinData { JoinNumber = 801, JoinSpan = 10 }, + [JoinName("ConfigRoomPhoneNumber")] + public JoinDataComplete ConfigRoomPhoneNumber = + new JoinDataComplete(new JoinData { JoinNumber = 504, JoinSpan = 1 }, new JoinMetadata { - Description = "Show Destination on UI", + Description = "Room phone number", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("ConfigRoomURI")] + public JoinDataComplete ConfigRoomUri = + new JoinDataComplete(new JoinData { JoinNumber = 505, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Room URI", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("ApiOnlineAndAuthorized")] + public JoinDataComplete ApiOnlineAndAuthorized = + new JoinDataComplete(new JoinData { JoinNumber = 500, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Config info from SIMPL is ready", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ConfigIsReady")] + public JoinDataComplete ConfigIsReady = + new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Config info from SIMPL is ready", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); - #endregion - public MobileControlSIMPLRoomJoinMap(uint joinStart) - : base(joinStart, typeof(MobileControlSIMPLRoomJoinMap)) + [JoinName("ReadyForConfig")] + public JoinDataComplete ReadyForConfig = + new JoinDataComplete(new JoinData { JoinNumber = 501, JoinSpan = 1 }, + new JoinMetadata { - } + Description = "Config info from SIMPL is ready", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("HideVideoConfRecents")] + public JoinDataComplete HideVideoConfRecents = + new JoinDataComplete(new JoinData { JoinNumber = 502, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Hide Video Conference Recents", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("ShowCameraWhenNotInCall")] + public JoinDataComplete ShowCameraWhenNotInCall = + new JoinDataComplete(new JoinData { JoinNumber = 503, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Show camera when not in call", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("UseSourceEnabled")] + public JoinDataComplete UseSourceEnabled = + new JoinDataComplete(new JoinData { JoinNumber = 504, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Use Source Enabled Joins", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("SourceShareDisableJoinStart")] + public JoinDataComplete SourceShareDisableJoinStart = + new JoinDataComplete(new JoinData { JoinNumber = 601, JoinSpan = 20 }, + new JoinMetadata + { + Description = "Source is not sharable", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SourceIsEnabledJoinStart")] + public JoinDataComplete SourceIsEnabledJoinStart = + new JoinDataComplete(new JoinData { JoinNumber = 621, JoinSpan = 20 }, + new JoinMetadata + { + Description = "Source is enabled/visible", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SourceIsControllableJoinStart")] + public JoinDataComplete SourceIsControllableJoinStart = + new JoinDataComplete(new JoinData { JoinNumber = 641, JoinSpan = 20 }, + new JoinMetadata + { + Description = "Source is controllable", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SourceIsAudioSourceJoinStart")] + public JoinDataComplete SourceIsAudioSourceJoinStart = + new JoinDataComplete(new JoinData { JoinNumber = 661, JoinSpan = 20 }, + new JoinMetadata + { + Description = "Source is Audio Source", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("SourceNameJoinStart")] + public JoinDataComplete SourceNameJoinStart = + new JoinDataComplete(new JoinData { JoinNumber = 601, JoinSpan = 20 }, + new JoinMetadata + { + Description = "Source Names", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SourceIconJoinStart")] + public JoinDataComplete SourceIconJoinStart = + new JoinDataComplete(new JoinData { JoinNumber = 621, JoinSpan = 20 }, + new JoinMetadata + { + Description = "Source Icons", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SourceKeyJoinStart")] + public JoinDataComplete SourceKeyJoinStart = + new JoinDataComplete(new JoinData { JoinNumber = 641, JoinSpan = 20 }, + new JoinMetadata + { + Description = "Source Keys", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SourceControlDeviceKeyJoinStart")] + public JoinDataComplete SourceControlDeviceKeyJoinStart = + new JoinDataComplete(new JoinData { JoinNumber = 701, JoinSpan = 20 }, + new JoinMetadata + { + Description = "Source Control Device Keys", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SourceTypeJoinStart")] + public JoinDataComplete SourceTypeJoinStart = + new JoinDataComplete(new JoinData { JoinNumber = 661, JoinSpan = 20 }, + new JoinMetadata + { + Description = "Source Types", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CameraNearNameStart")] + public JoinDataComplete CameraNearNameStart = + new JoinDataComplete(new JoinData { JoinNumber = 761, JoinSpan = 10 }, + new JoinMetadata + { + Description = "Near End Camera Names", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CameraFarName")] + public JoinDataComplete CameraFarName = + new JoinDataComplete(new JoinData { JoinNumber = 771, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Far End Camera Name", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + #region Advanced Sharing + [JoinName("SupportsAdvancedSharing")] + public JoinDataComplete SupportsAdvancedSharing = + new JoinDataComplete(new JoinData { JoinNumber = 505, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Supports Advanced Sharing", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("UseDestinationEnable")] + public JoinDataComplete UseDestinationEnable = + new JoinDataComplete(new JoinData { JoinNumber = 506, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Use Destination Enable", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("UserCanChangeShareMode")] + public JoinDataComplete UserCanChangeShareMode = + new JoinDataComplete(new JoinData { JoinNumber = 507, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Share Mode Toggle Visible to User", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DestinationNameJoinStart")] + public JoinDataComplete DestinationNameJoinStart = + new JoinDataComplete(new JoinData { JoinNumber = 801, JoinSpan = 10 }, + new JoinMetadata + { + Description = "Destination Name", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DestinationDeviceKeyJoinStart")] + public JoinDataComplete DestinationDeviceKeyJoinStart = + new JoinDataComplete(new JoinData { JoinNumber = 811, JoinSpan = 10 }, + new JoinMetadata + { + Description = "Destination Device Key", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DestinationTypeJoinStart")] + public JoinDataComplete DestinationTypeJoinStart = + new JoinDataComplete(new JoinData { JoinNumber = 821, JoinSpan = 10 }, + new JoinMetadata + { + Description = "Destination type. Should be Audio, Video, AudioVideo", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DestinationIsEnabledJoinStart")] + public JoinDataComplete DestinationIsEnabledJoinStart = + new JoinDataComplete(new JoinData { JoinNumber = 801, JoinSpan = 10 }, + new JoinMetadata + { + Description = "Show Destination on UI", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + #endregion + + public MobileControlSIMPLRoomJoinMap(uint joinStart) + : base(joinStart, typeof(MobileControlSIMPLRoomJoinMap)) + { } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/SIMPLJoinMaps/MobileControlSIMPLRunDirectRouteActionJoinMap.cs b/src/PepperDash.Essentials.MobileControl.Messengers/SIMPLJoinMaps/MobileControlSIMPLRunDirectRouteActionJoinMap.cs index 10c516eeb..d61a68ecd 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/SIMPLJoinMaps/MobileControlSIMPLRunDirectRouteActionJoinMap.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/SIMPLJoinMaps/MobileControlSIMPLRunDirectRouteActionJoinMap.cs @@ -1,52 +1,62 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.AppServer +namespace PepperDash.Essentials.AppServer; + +public class MobileControlSIMPLRunDirectRouteActionJoinMap : JoinMapBaseAdvanced { - public class MobileControlSIMPLRunDirectRouteActionJoinMap : JoinMapBaseAdvanced - { - [JoinName("AdvancedSharingModeFb")] - public JoinDataComplete AdvancedSharingModeFb = - new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Use Advanced Sharing Mode", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); + [JoinName("AdvancedSharingModeFb")] + public JoinDataComplete AdvancedSharingModeFb = + new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Use Advanced Sharing Mode", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); - [JoinName("AdvancedSharingModeOn")] - public JoinDataComplete AdvancedSharingModeOn = - new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Use Advanced Sharing Mode", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); + [JoinName("AdvancedSharingModeOn")] + public JoinDataComplete AdvancedSharingModeOn = + new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Use Advanced Sharing Mode", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); - [JoinName("AdvancedSharingModeOff")] - public JoinDataComplete AdvancedSharingModeOff = - new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Use Advanced Sharing Mode", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); + [JoinName("AdvancedSharingModeOff")] + public JoinDataComplete AdvancedSharingModeOff = + new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Use Advanced Sharing Mode", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); - [JoinName("AdvancedSharingModeToggle")] - public JoinDataComplete AdvancedSharingModeToggle = - new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Use Advanced Sharing Mode", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); + [JoinName("AdvancedSharingModeToggle")] + public JoinDataComplete AdvancedSharingModeToggle = + new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata + { + Description = "Use Advanced Sharing Mode", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); - [JoinName("SourceForDestinationJoinStart")] - public JoinDataComplete SourceForDestinationJoinStart = - new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 10 }, + [JoinName("SourceForDestinationJoinStart")] + public JoinDataComplete SourceForDestinationJoinStart = + new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 10 }, + new JoinMetadata + { + Description = "Source to Route to Destination & FB", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("SourceForDestinationAudio")] + public JoinDataComplete SourceForDestinationAudio = + new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1 }, new JoinMetadata { Description = "Source to Route to Destination & FB", @@ -54,19 +64,8 @@ public class MobileControlSIMPLRunDirectRouteActionJoinMap : JoinMapBaseAdvanced JoinType = eJoinType.Serial }); - [JoinName("SourceForDestinationAudio")] - public JoinDataComplete SourceForDestinationAudio = - new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1 }, - new JoinMetadata - { - Description = "Source to Route to Destination & FB", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Serial - }); - - public MobileControlSIMPLRunDirectRouteActionJoinMap(uint joinStart) - : base(joinStart, typeof(MobileControlSIMPLRunDirectRouteActionJoinMap)) - { - } + public MobileControlSIMPLRunDirectRouteActionJoinMap(uint joinStart) + : base(joinStart, typeof(MobileControlSIMPLRunDirectRouteActionJoinMap)) + { } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/SIMPLJoinMaps/SIMPLAtcJoinMap.cs b/src/PepperDash.Essentials.MobileControl.Messengers/SIMPLJoinMaps/SIMPLAtcJoinMap.cs index 0ec4de5a0..8d7c78b5c 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/SIMPLJoinMaps/SIMPLAtcJoinMap.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/SIMPLJoinMaps/SIMPLAtcJoinMap.cs @@ -1,247 +1,246 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.AppServer +namespace PepperDash.Essentials.AppServer; + +public class SIMPLAtcJoinMap : JoinMapBaseAdvanced { - public class SIMPLAtcJoinMap : JoinMapBaseAdvanced + [JoinName("EndCall")] + public JoinDataComplete EndCall = + new JoinDataComplete(new JoinData() { JoinNumber = 21, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Hang Up", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingAnswer")] + public JoinDataComplete IncomingAnswer = + new JoinDataComplete(new JoinData() { JoinNumber = 51, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Answer Incoming Call", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingReject")] + public JoinDataComplete IncomingReject = + new JoinDataComplete(new JoinData() { JoinNumber = 52, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Reject Incoming Call", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SpeedDialStart")] + public JoinDataComplete SpeedDialStart = + new JoinDataComplete(new JoinData() { JoinNumber = 41, JoinSpan = 4 }, + new JoinMetadata() + { + Description = "Speed Dial", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CurrentDialString")] + public JoinDataComplete CurrentDialString = + new JoinDataComplete(new JoinData() { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Current Dial String", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentCallNumber")] + public JoinDataComplete CurrentCallNumber = + new JoinDataComplete(new JoinData() { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Current Call Number", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentCallName")] + public JoinDataComplete CurrentCallName = + new JoinDataComplete(new JoinData() { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Current Call Name", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("HookState")] + public JoinDataComplete HookState = + new JoinDataComplete(new JoinData() { JoinNumber = 21, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Current Hook State", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CallDirection")] + public JoinDataComplete CallDirection = + new JoinDataComplete(new JoinData() { JoinNumber = 22, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Current Call Direction", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallName")] + public JoinDataComplete IncomingCallName = + new JoinDataComplete(new JoinData() { JoinNumber = 51, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Incoming Call Name", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallNumber")] + public JoinDataComplete IncomingCallNumber = + new JoinDataComplete(new JoinData() { JoinNumber = 52, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Incoming Call Number", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("0")] + public JoinDataComplete Dtmf0 = + new JoinDataComplete(new JoinData() { JoinNumber = 10, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 0", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("1")] + public JoinDataComplete Dtmf1 = + new JoinDataComplete(new JoinData() { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 1", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("2")] + public JoinDataComplete Dtmf2 = + new JoinDataComplete(new JoinData() { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 2", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("3")] + public JoinDataComplete Dtmf3 = + new JoinDataComplete(new JoinData() { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 3", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("4")] + public JoinDataComplete Dtmf4 = + new JoinDataComplete(new JoinData() { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 4", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("5")] + public JoinDataComplete Dtmf5 = + new JoinDataComplete(new JoinData() { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 5", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("6")] + public JoinDataComplete Dtmf6 = + new JoinDataComplete(new JoinData() { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 6", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("7")] + public JoinDataComplete Dtmf7 = + new JoinDataComplete(new JoinData() { JoinNumber = 7, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 7", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("8")] + public JoinDataComplete Dtmf8 = + new JoinDataComplete(new JoinData() { JoinNumber = 8, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 8", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("9")] + public JoinDataComplete Dtmf9 = + new JoinDataComplete(new JoinData() { JoinNumber = 9, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 9", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("*")] + public JoinDataComplete DtmfStar = + new JoinDataComplete(new JoinData() { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF *", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("#")] + public JoinDataComplete DtmfPound = + new JoinDataComplete(new JoinData() { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF #", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + /// + /// Constructor that passes the joinStart to the base class + /// + /// + public SIMPLAtcJoinMap(uint joinStart) + : base(joinStart, typeof(SIMPLAtcJoinMap)) { - [JoinName("EndCall")] - public JoinDataComplete EndCall = - new JoinDataComplete(new JoinData() { JoinNumber = 21, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Hang Up", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingAnswer")] - public JoinDataComplete IncomingAnswer = - new JoinDataComplete(new JoinData() { JoinNumber = 51, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Answer Incoming Call", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingReject")] - public JoinDataComplete IncomingReject = - new JoinDataComplete(new JoinData() { JoinNumber = 52, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Reject Incoming Call", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SpeedDialStart")] - public JoinDataComplete SpeedDialStart = - new JoinDataComplete(new JoinData() { JoinNumber = 41, JoinSpan = 4 }, - new JoinMetadata() - { - Description = "Speed Dial", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CurrentDialString")] - public JoinDataComplete CurrentDialString = - new JoinDataComplete(new JoinData() { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Current Dial String", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentCallNumber")] - public JoinDataComplete CurrentCallNumber = - new JoinDataComplete(new JoinData() { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Current Call Number", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentCallName")] - public JoinDataComplete CurrentCallName = - new JoinDataComplete(new JoinData() { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Current Call Name", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("HookState")] - public JoinDataComplete HookState = - new JoinDataComplete(new JoinData() { JoinNumber = 21, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Current Hook State", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CallDirection")] - public JoinDataComplete CallDirection = - new JoinDataComplete(new JoinData() { JoinNumber = 22, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Current Call Direction", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingCallName")] - public JoinDataComplete IncomingCallName = - new JoinDataComplete(new JoinData() { JoinNumber = 51, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Incoming Call Name", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingCallNumber")] - public JoinDataComplete IncomingCallNumber = - new JoinDataComplete(new JoinData() { JoinNumber = 52, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Incoming Call Number", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("0")] - public JoinDataComplete Dtmf0 = - new JoinDataComplete(new JoinData() { JoinNumber = 10, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 0", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("1")] - public JoinDataComplete Dtmf1 = - new JoinDataComplete(new JoinData() { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 1", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("2")] - public JoinDataComplete Dtmf2 = - new JoinDataComplete(new JoinData() { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 2", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("3")] - public JoinDataComplete Dtmf3 = - new JoinDataComplete(new JoinData() { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 3", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("4")] - public JoinDataComplete Dtmf4 = - new JoinDataComplete(new JoinData() { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 4", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("5")] - public JoinDataComplete Dtmf5 = - new JoinDataComplete(new JoinData() { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 5", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("6")] - public JoinDataComplete Dtmf6 = - new JoinDataComplete(new JoinData() { JoinNumber = 6, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 6", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("7")] - public JoinDataComplete Dtmf7 = - new JoinDataComplete(new JoinData() { JoinNumber = 7, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 7", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("8")] - public JoinDataComplete Dtmf8 = - new JoinDataComplete(new JoinData() { JoinNumber = 8, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 8", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("9")] - public JoinDataComplete Dtmf9 = - new JoinDataComplete(new JoinData() { JoinNumber = 9, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 9", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("*")] - public JoinDataComplete DtmfStar = - new JoinDataComplete(new JoinData() { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF *", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("#")] - public JoinDataComplete DtmfPound = - new JoinDataComplete(new JoinData() { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF #", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - /// - /// Constructor that passes the joinStart to the base class - /// - /// - public SIMPLAtcJoinMap(uint joinStart) - : base(joinStart, typeof(SIMPLAtcJoinMap)) - { - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/SIMPLJoinMaps/SIMPLVtcJoinMap.cs b/src/PepperDash.Essentials.MobileControl.Messengers/SIMPLJoinMaps/SIMPLVtcJoinMap.cs index 69b32495b..59b9fbf2f 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/SIMPLJoinMaps/SIMPLVtcJoinMap.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/SIMPLJoinMaps/SIMPLVtcJoinMap.cs @@ -1,553 +1,552 @@ using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.AppServer +namespace PepperDash.Essentials.AppServer; + +public class SIMPLVtcJoinMap : JoinMapBaseAdvanced { - public class SIMPLVtcJoinMap : JoinMapBaseAdvanced + [JoinName("EndCall")] + public JoinDataComplete EndCall = + new JoinDataComplete(new JoinData() { JoinNumber = 24, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Hang Up", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingCall")] + public JoinDataComplete IncomingCall = + new JoinDataComplete(new JoinData() { JoinNumber = 50, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Incoming Call", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingAnswer")] + public JoinDataComplete IncomingAnswer = + new JoinDataComplete(new JoinData() { JoinNumber = 51, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Answer Incoming Call", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("IncomingReject")] + public JoinDataComplete IncomingReject = + new JoinDataComplete(new JoinData() { JoinNumber = 52, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Reject Incoming Call", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("SpeedDialStart")] + public JoinDataComplete SpeedDialStart = + new JoinDataComplete(new JoinData() { JoinNumber = 41, JoinSpan = 4 }, + new JoinMetadata() + { + Description = "Speed Dial", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectorySearchBusy")] + public JoinDataComplete DirectorySearchBusy = + new JoinDataComplete(new JoinData() { JoinNumber = 100, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Directory Search Busy FB", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryLineSelected")] + public JoinDataComplete DirectoryLineSelected = + new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Directory Line Selected FB", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryEntryIsContact")] + public JoinDataComplete DirectoryEntryIsContact = + new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Directory Selected Entry Is Contact FB", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryIsRoot")] + public JoinDataComplete DirectoryIsRoot = + new JoinDataComplete(new JoinData() { JoinNumber = 102, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Directory is on Root FB", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DDirectoryHasChanged")] + public JoinDataComplete DDirectoryHasChanged = + new JoinDataComplete(new JoinData() { JoinNumber = 103, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Directory has changed FB", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryRoot")] + public JoinDataComplete DirectoryRoot = + new JoinDataComplete(new JoinData() { JoinNumber = 104, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Go to Directory Root", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryFolderBack")] + public JoinDataComplete DirectoryFolderBack = + new JoinDataComplete(new JoinData() { JoinNumber = 105, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Go back one directory level", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectoryDialSelectedLine")] + public JoinDataComplete DirectoryDialSelectedLine = + new JoinDataComplete(new JoinData() { JoinNumber = 106, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Dial selected directory line", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraTiltUp")] + public JoinDataComplete CameraTiltUp = + new JoinDataComplete(new JoinData() { JoinNumber = 111, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Camera Tilt Up", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraTiltDown")] + public JoinDataComplete CameraTiltDown = + new JoinDataComplete(new JoinData() { JoinNumber = 112, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Camera Tilt Down", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPanLeft")] + public JoinDataComplete CameraPanLeft = + new JoinDataComplete(new JoinData() { JoinNumber = 113, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Camera Pan Left", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPanRight")] + public JoinDataComplete CameraPanRight = + new JoinDataComplete(new JoinData() { JoinNumber = 114, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Camera Pan Right", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraZoomIn")] + public JoinDataComplete CameraZoomIn = + new JoinDataComplete(new JoinData() { JoinNumber = 115, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Camera Zoom In", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraZoomOut")] + public JoinDataComplete CameraZoomOut = + new JoinDataComplete(new JoinData() { JoinNumber = 116, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Camera Zoom Out", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraPresetStart")] + public JoinDataComplete CameraPresetStart = + new JoinDataComplete(new JoinData() { JoinNumber = 121, JoinSpan = 5 }, + new JoinMetadata() + { + Description = "Camera Presets", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeAuto")] + public JoinDataComplete CameraModeAuto = + new JoinDataComplete(new JoinData() { JoinNumber = 131, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Camera Mode Auto", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeManual")] + public JoinDataComplete CameraModeManual = + new JoinDataComplete(new JoinData() { JoinNumber = 132, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Camera Mode Manual", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraModeOff")] + public JoinDataComplete CameraModeOff = + new JoinDataComplete(new JoinData() { JoinNumber = 133, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Camera Mode Off", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSelfView")] + public JoinDataComplete CameraSelfView = + new JoinDataComplete(new JoinData() { JoinNumber = 141, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Camera Self View Toggle/FB", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraLayout")] + public JoinDataComplete CameraLayout = + new JoinDataComplete(new JoinData() { JoinNumber = 142, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Camera Layout Toggle", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSupportsAutoMode")] + public JoinDataComplete CameraSupportsAutoMode = + new JoinDataComplete(new JoinData() { JoinNumber = 143, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Camera Supports Auto Mode FB", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraSupportsOffMode")] + public JoinDataComplete CameraSupportsOffMode = + new JoinDataComplete(new JoinData() { JoinNumber = 144, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Camera Supports Off Mode FB", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("CameraNumberSelect")] + public JoinDataComplete CameraNumberSelect = + new JoinDataComplete(new JoinData() { JoinNumber = 60, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Camera Number Select/FB", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("DirectorySelectRow")] + public JoinDataComplete DirectorySelectRow = + new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Directory Select Row", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("DirectoryRowCount")] + public JoinDataComplete DirectoryRowCount = + new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Directory Row Count FB", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Analog + }); + + [JoinName("CurrentDialString")] + public JoinDataComplete CurrentDialString = + new JoinDataComplete(new JoinData() { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Current Dial String", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentCallName")] + public JoinDataComplete CurrentCallName = + new JoinDataComplete(new JoinData() { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Current Call Name", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CurrentCallNumber")] + public JoinDataComplete CurrentCallNumber = + new JoinDataComplete(new JoinData() { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Current Call Number", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("HookState")] + public JoinDataComplete HookState = + new JoinDataComplete(new JoinData() { JoinNumber = 31, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Current Hook State", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("CallDirection")] + public JoinDataComplete CallDirection = + new JoinDataComplete(new JoinData() { JoinNumber = 22, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Current Call Direction", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallName")] + public JoinDataComplete IncomingCallName = + new JoinDataComplete(new JoinData() { JoinNumber = 51, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Incoming Call Name", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("IncomingCallNumber")] + public JoinDataComplete IncomingCallNumber = + new JoinDataComplete(new JoinData() { JoinNumber = 52, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Incoming Call Number", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectorySearchString")] + public JoinDataComplete DirectorySearchString = + new JoinDataComplete(new JoinData() { JoinNumber = 100, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Directory Search String", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntriesStart")] + public JoinDataComplete DirectoryEntriesStart = + new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 255 }, + new JoinMetadata() + { + Description = "Directory Entries", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntrySelectedName")] + public JoinDataComplete DirectoryEntrySelectedName = + new JoinDataComplete(new JoinData() { JoinNumber = 356, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Selected Directory Entry Name", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectoryEntrySelectedNumber")] + public JoinDataComplete DirectoryEntrySelectedNumber = + new JoinDataComplete(new JoinData() { JoinNumber = 357, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Selected Directory Entry Number", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("DirectorySelectedFolderName")] + public JoinDataComplete DirectorySelectedFolderName = + new JoinDataComplete(new JoinData() { JoinNumber = 358, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "Selected Directory Folder Name", + JoinCapabilities = eJoinCapabilities.FromSIMPL, + JoinType = eJoinType.Serial + }); + + [JoinName("1")] + public JoinDataComplete Dtmf1 = + new JoinDataComplete(new JoinData() { JoinNumber = 1, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 1", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("2")] + public JoinDataComplete Dtmf2 = + new JoinDataComplete(new JoinData() { JoinNumber = 2, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 2", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("3")] + public JoinDataComplete Dtmf3 = + new JoinDataComplete(new JoinData() { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 3", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("4")] + public JoinDataComplete Dtmf4 = + new JoinDataComplete(new JoinData() { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 4", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("5")] + public JoinDataComplete Dtmf5 = + new JoinDataComplete(new JoinData() { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 5", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("6")] + public JoinDataComplete Dtmf6 = + new JoinDataComplete(new JoinData() { JoinNumber = 6, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 6", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("7")] + public JoinDataComplete Dtmf7 = + new JoinDataComplete(new JoinData() { JoinNumber = 7, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 7", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("8")] + public JoinDataComplete Dtmf8 = + new JoinDataComplete(new JoinData() { JoinNumber = 8, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 8", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("9")] + public JoinDataComplete Dtmf9 = + new JoinDataComplete(new JoinData() { JoinNumber = 9, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 9", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("0")] + public JoinDataComplete Dtmf0 = + new JoinDataComplete(new JoinData() { JoinNumber = 10, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF 0", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("*")] + public JoinDataComplete DtmfStar = + new JoinDataComplete(new JoinData() { JoinNumber = 11, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF *", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + [JoinName("#")] + public JoinDataComplete DtmfPound = + new JoinDataComplete(new JoinData() { JoinNumber = 12, JoinSpan = 1 }, + new JoinMetadata() + { + Description = "DTMF #", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + public SIMPLVtcJoinMap(uint joinStart) + : base(joinStart, typeof(SIMPLVtcJoinMap)) { - [JoinName("EndCall")] - public JoinDataComplete EndCall = - new JoinDataComplete(new JoinData() { JoinNumber = 24, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Hang Up", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingCall")] - public JoinDataComplete IncomingCall = - new JoinDataComplete(new JoinData() { JoinNumber = 50, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Incoming Call", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingAnswer")] - public JoinDataComplete IncomingAnswer = - new JoinDataComplete(new JoinData() { JoinNumber = 51, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Answer Incoming Call", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("IncomingReject")] - public JoinDataComplete IncomingReject = - new JoinDataComplete(new JoinData() { JoinNumber = 52, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Reject Incoming Call", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("SpeedDialStart")] - public JoinDataComplete SpeedDialStart = - new JoinDataComplete(new JoinData() { JoinNumber = 41, JoinSpan = 4 }, - new JoinMetadata() - { - Description = "Speed Dial", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectorySearchBusy")] - public JoinDataComplete DirectorySearchBusy = - new JoinDataComplete(new JoinData() { JoinNumber = 100, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Directory Search Busy FB", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryLineSelected")] - public JoinDataComplete DirectoryLineSelected = - new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Directory Line Selected FB", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryEntryIsContact")] - public JoinDataComplete DirectoryEntryIsContact = - new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Directory Selected Entry Is Contact FB", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryIsRoot")] - public JoinDataComplete DirectoryIsRoot = - new JoinDataComplete(new JoinData() { JoinNumber = 102, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Directory is on Root FB", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DDirectoryHasChanged")] - public JoinDataComplete DDirectoryHasChanged = - new JoinDataComplete(new JoinData() { JoinNumber = 103, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Directory has changed FB", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryRoot")] - public JoinDataComplete DirectoryRoot = - new JoinDataComplete(new JoinData() { JoinNumber = 104, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Go to Directory Root", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryFolderBack")] - public JoinDataComplete DirectoryFolderBack = - new JoinDataComplete(new JoinData() { JoinNumber = 105, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Go back one directory level", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectoryDialSelectedLine")] - public JoinDataComplete DirectoryDialSelectedLine = - new JoinDataComplete(new JoinData() { JoinNumber = 106, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Dial selected directory line", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraTiltUp")] - public JoinDataComplete CameraTiltUp = - new JoinDataComplete(new JoinData() { JoinNumber = 111, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Camera Tilt Up", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraTiltDown")] - public JoinDataComplete CameraTiltDown = - new JoinDataComplete(new JoinData() { JoinNumber = 112, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Camera Tilt Down", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraPanLeft")] - public JoinDataComplete CameraPanLeft = - new JoinDataComplete(new JoinData() { JoinNumber = 113, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Camera Pan Left", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraPanRight")] - public JoinDataComplete CameraPanRight = - new JoinDataComplete(new JoinData() { JoinNumber = 114, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Camera Pan Right", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraZoomIn")] - public JoinDataComplete CameraZoomIn = - new JoinDataComplete(new JoinData() { JoinNumber = 115, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Camera Zoom In", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraZoomOut")] - public JoinDataComplete CameraZoomOut = - new JoinDataComplete(new JoinData() { JoinNumber = 116, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Camera Zoom Out", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraPresetStart")] - public JoinDataComplete CameraPresetStart = - new JoinDataComplete(new JoinData() { JoinNumber = 121, JoinSpan = 5 }, - new JoinMetadata() - { - Description = "Camera Presets", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraModeAuto")] - public JoinDataComplete CameraModeAuto = - new JoinDataComplete(new JoinData() { JoinNumber = 131, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Camera Mode Auto", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraModeManual")] - public JoinDataComplete CameraModeManual = - new JoinDataComplete(new JoinData() { JoinNumber = 132, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Camera Mode Manual", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraModeOff")] - public JoinDataComplete CameraModeOff = - new JoinDataComplete(new JoinData() { JoinNumber = 133, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Camera Mode Off", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSelfView")] - public JoinDataComplete CameraSelfView = - new JoinDataComplete(new JoinData() { JoinNumber = 141, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Camera Self View Toggle/FB", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraLayout")] - public JoinDataComplete CameraLayout = - new JoinDataComplete(new JoinData() { JoinNumber = 142, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Camera Layout Toggle", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSupportsAutoMode")] - public JoinDataComplete CameraSupportsAutoMode = - new JoinDataComplete(new JoinData() { JoinNumber = 143, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Camera Supports Auto Mode FB", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraSupportsOffMode")] - public JoinDataComplete CameraSupportsOffMode = - new JoinDataComplete(new JoinData() { JoinNumber = 144, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Camera Supports Off Mode FB", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("CameraNumberSelect")] - public JoinDataComplete CameraNumberSelect = - new JoinDataComplete(new JoinData() { JoinNumber = 60, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Camera Number Select/FB", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("DirectorySelectRow")] - public JoinDataComplete DirectorySelectRow = - new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Directory Select Row", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("DirectoryRowCount")] - public JoinDataComplete DirectoryRowCount = - new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Directory Row Count FB", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Analog - }); - - [JoinName("CurrentDialString")] - public JoinDataComplete CurrentDialString = - new JoinDataComplete(new JoinData() { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Current Dial String", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentCallName")] - public JoinDataComplete CurrentCallName = - new JoinDataComplete(new JoinData() { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Current Call Name", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CurrentCallNumber")] - public JoinDataComplete CurrentCallNumber = - new JoinDataComplete(new JoinData() { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Current Call Number", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("HookState")] - public JoinDataComplete HookState = - new JoinDataComplete(new JoinData() { JoinNumber = 31, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Current Hook State", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("CallDirection")] - public JoinDataComplete CallDirection = - new JoinDataComplete(new JoinData() { JoinNumber = 22, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Current Call Direction", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingCallName")] - public JoinDataComplete IncomingCallName = - new JoinDataComplete(new JoinData() { JoinNumber = 51, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Incoming Call Name", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("IncomingCallNumber")] - public JoinDataComplete IncomingCallNumber = - new JoinDataComplete(new JoinData() { JoinNumber = 52, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Incoming Call Number", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectorySearchString")] - public JoinDataComplete DirectorySearchString = - new JoinDataComplete(new JoinData() { JoinNumber = 100, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Directory Search String", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryEntriesStart")] - public JoinDataComplete DirectoryEntriesStart = - new JoinDataComplete(new JoinData() { JoinNumber = 101, JoinSpan = 255 }, - new JoinMetadata() - { - Description = "Directory Entries", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryEntrySelectedName")] - public JoinDataComplete DirectoryEntrySelectedName = - new JoinDataComplete(new JoinData() { JoinNumber = 356, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Selected Directory Entry Name", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectoryEntrySelectedNumber")] - public JoinDataComplete DirectoryEntrySelectedNumber = - new JoinDataComplete(new JoinData() { JoinNumber = 357, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Selected Directory Entry Number", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("DirectorySelectedFolderName")] - public JoinDataComplete DirectorySelectedFolderName = - new JoinDataComplete(new JoinData() { JoinNumber = 358, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "Selected Directory Folder Name", - JoinCapabilities = eJoinCapabilities.FromSIMPL, - JoinType = eJoinType.Serial - }); - - [JoinName("1")] - public JoinDataComplete Dtmf1 = - new JoinDataComplete(new JoinData() { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 1", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("2")] - public JoinDataComplete Dtmf2 = - new JoinDataComplete(new JoinData() { JoinNumber = 2, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 2", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("3")] - public JoinDataComplete Dtmf3 = - new JoinDataComplete(new JoinData() { JoinNumber = 3, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 3", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("4")] - public JoinDataComplete Dtmf4 = - new JoinDataComplete(new JoinData() { JoinNumber = 4, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 4", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("5")] - public JoinDataComplete Dtmf5 = - new JoinDataComplete(new JoinData() { JoinNumber = 5, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 5", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("6")] - public JoinDataComplete Dtmf6 = - new JoinDataComplete(new JoinData() { JoinNumber = 6, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 6", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("7")] - public JoinDataComplete Dtmf7 = - new JoinDataComplete(new JoinData() { JoinNumber = 7, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 7", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("8")] - public JoinDataComplete Dtmf8 = - new JoinDataComplete(new JoinData() { JoinNumber = 8, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 8", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("9")] - public JoinDataComplete Dtmf9 = - new JoinDataComplete(new JoinData() { JoinNumber = 9, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 9", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("0")] - public JoinDataComplete Dtmf0 = - new JoinDataComplete(new JoinData() { JoinNumber = 10, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF 0", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("*")] - public JoinDataComplete DtmfStar = - new JoinDataComplete(new JoinData() { JoinNumber = 11, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF *", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - [JoinName("#")] - public JoinDataComplete DtmfPound = - new JoinDataComplete(new JoinData() { JoinNumber = 12, JoinSpan = 1 }, - new JoinMetadata() - { - Description = "DTMF #", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - public SIMPLVtcJoinMap(uint joinStart) - : base(joinStart, typeof(SIMPLVtcJoinMap)) - { - } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl/AuthorizationResponse.cs b/src/PepperDash.Essentials.MobileControl/AuthorizationResponse.cs index 4e4a44395..59faab0e5 100644 --- a/src/PepperDash.Essentials.MobileControl/AuthorizationResponse.cs +++ b/src/PepperDash.Essentials.MobileControl/AuthorizationResponse.cs @@ -1,19 +1,18 @@ using Newtonsoft.Json; -namespace PepperDash.Essentials +namespace PepperDash.Essentials; + +public class AuthorizationResponse { - public class AuthorizationResponse - { - [JsonProperty("authorized")] - public bool Authorized { get; set; } + [JsonProperty("authorized")] + public bool Authorized { get; set; } - [JsonProperty("reason", NullValueHandling = NullValueHandling.Ignore)] - public string Reason { get; set; } = null; - } + [JsonProperty("reason", NullValueHandling = NullValueHandling.Ignore)] + public string Reason { get; set; } = null; +} - public class AuthorizationRequest - { - [JsonProperty("grantCode")] - public string GrantCode { get; set; } - } +public class AuthorizationRequest +{ + [JsonProperty("grantCode")] + public string GrantCode { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl/Interfaces.cs b/src/PepperDash.Essentials.MobileControl/Interfaces.cs index dc5552c61..418e7cc1e 100644 --- a/src/PepperDash.Essentials.MobileControl/Interfaces.cs +++ b/src/PepperDash.Essentials.MobileControl/Interfaces.cs @@ -1,16 +1,15 @@ using System; -namespace PepperDash.Essentials +namespace PepperDash.Essentials; + +/// +/// Represents a room whose configuration is derived from runtime data, +/// perhaps from another program, and that the data may not be fully +/// available at startup. +/// +public interface IDelayedConfiguration { - /// - /// Represents a room whose configuration is derived from runtime data, - /// perhaps from another program, and that the data may not be fully - /// available at startup. - /// - public interface IDelayedConfiguration - { - event EventHandler ConfigurationIsReady; - } + event EventHandler ConfigurationIsReady; } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl/MobileControlAction.cs b/src/PepperDash.Essentials.MobileControl/MobileControlAction.cs index 2f12f5bd9..905bff7bb 100644 --- a/src/PepperDash.Essentials.MobileControl/MobileControlAction.cs +++ b/src/PepperDash.Essentials.MobileControl/MobileControlAction.cs @@ -2,18 +2,17 @@ using PepperDash.Essentials.Core.DeviceTypeInterfaces; using System; -namespace PepperDash.Essentials +namespace PepperDash.Essentials; + +public class MobileControlAction : IMobileControlAction { - public class MobileControlAction : IMobileControlAction - { - public IMobileControlMessenger Messenger { get; private set; } + public IMobileControlMessenger Messenger { get; private set; } - public Action Action { get; private set; } + public Action Action { get; private set; } - public MobileControlAction(IMobileControlMessenger messenger, Action handler) - { - Messenger = messenger; - Action = handler; - } + public MobileControlAction(IMobileControlMessenger messenger, Action handler) + { + Messenger = messenger; + Action = handler; } } diff --git a/src/PepperDash.Essentials.MobileControl/MobileControlConfig.cs b/src/PepperDash.Essentials.MobileControl/MobileControlConfig.cs index af25f27a6..8bc7de9ee 100644 --- a/src/PepperDash.Essentials.MobileControl/MobileControlConfig.cs +++ b/src/PepperDash.Essentials.MobileControl/MobileControlConfig.cs @@ -2,143 +2,142 @@ using Newtonsoft.Json.Converters; using System.Collections.Generic; -namespace PepperDash.Essentials +namespace PepperDash.Essentials; + +/// +/// +/// +public class MobileControlConfig { - /// - /// - /// - public class MobileControlConfig - { - [JsonProperty("serverUrl")] - public string ServerUrl { get; set; } + [JsonProperty("serverUrl")] + public string ServerUrl { get; set; } - [JsonProperty("clientAppUrl")] - public string ClientAppUrl { get; set; } + [JsonProperty("clientAppUrl")] + public string ClientAppUrl { get; set; } - [JsonProperty("directServer")] - public MobileControlDirectServerPropertiesConfig DirectServer { get; set; } + [JsonProperty("directServer")] + public MobileControlDirectServerPropertiesConfig DirectServer { get; set; } - [JsonProperty("applicationConfig")] - public MobileControlApplicationConfig ApplicationConfig { get; set; } = null; + [JsonProperty("applicationConfig")] + public MobileControlApplicationConfig ApplicationConfig { get; set; } = null; - [JsonProperty("enableApiServer")] - public bool EnableApiServer { get; set; } = true; - } + [JsonProperty("enableApiServer")] + public bool EnableApiServer { get; set; } = true; +} - public class MobileControlDirectServerPropertiesConfig - { - [JsonProperty("enableDirectServer")] - public bool EnableDirectServer { get; set; } +public class MobileControlDirectServerPropertiesConfig +{ + [JsonProperty("enableDirectServer")] + public bool EnableDirectServer { get; set; } - [JsonProperty("port")] - public int Port { get; set; } + [JsonProperty("port")] + public int Port { get; set; } - [JsonProperty("logging")] - public MobileControlLoggingConfig Logging { get; set; } + [JsonProperty("logging")] + public MobileControlLoggingConfig Logging { get; set; } - [JsonProperty("automaticallyForwardPortToCSLAN")] - public bool? AutomaticallyForwardPortToCSLAN { get; set; } + [JsonProperty("automaticallyForwardPortToCSLAN")] + public bool? AutomaticallyForwardPortToCSLAN { get; set; } - public MobileControlDirectServerPropertiesConfig() - { - Logging = new MobileControlLoggingConfig(); - } + public MobileControlDirectServerPropertiesConfig() + { + Logging = new MobileControlLoggingConfig(); } +} - public class MobileControlLoggingConfig - { - [JsonProperty("enableRemoteLogging")] - public bool EnableRemoteLogging { get; set; } +public class MobileControlLoggingConfig +{ + [JsonProperty("enableRemoteLogging")] + public bool EnableRemoteLogging { get; set; } - [JsonProperty("host")] - public string Host { get; set; } + [JsonProperty("host")] + public string Host { get; set; } - [JsonProperty("port")] - public int Port { get; set; } + [JsonProperty("port")] + public int Port { get; set; } - } +} - public class MobileControlRoomBridgePropertiesConfig - { - [JsonProperty("key")] - public string Key { get; set; } +public class MobileControlRoomBridgePropertiesConfig +{ + [JsonProperty("key")] + public string Key { get; set; } - [JsonProperty("roomKey")] - public string RoomKey { get; set; } - } + [JsonProperty("roomKey")] + public string RoomKey { get; set; } +} - /// - /// - /// - public class MobileControlSimplRoomBridgePropertiesConfig - { - [JsonProperty("eiscId")] - public string EiscId { get; set; } - } +/// +/// +/// +public class MobileControlSimplRoomBridgePropertiesConfig +{ + [JsonProperty("eiscId")] + public string EiscId { get; set; } +} - public class MobileControlApplicationConfig - { - [JsonProperty("apiPath")] - public string ApiPath { get; set; } +public class MobileControlApplicationConfig +{ + [JsonProperty("apiPath")] + public string ApiPath { get; set; } - [JsonProperty("gatewayAppPath")] - public string GatewayAppPath { get; set; } + [JsonProperty("gatewayAppPath")] + public string GatewayAppPath { get; set; } - [JsonProperty("enableDev")] - public bool? EnableDev { get; set; } + [JsonProperty("enableDev")] + public bool? EnableDev { get; set; } - [JsonProperty("logoPath")] - /// - /// Client logo to be used in header and/or splash screen - /// - public string LogoPath { get; set; } + [JsonProperty("logoPath")] + /// + /// Client logo to be used in header and/or splash screen + /// + public string LogoPath { get; set; } - [JsonProperty("iconSet")] - [JsonConverter(typeof(StringEnumConverter))] - public MCIconSet? IconSet { get; set; } + [JsonProperty("iconSet")] + [JsonConverter(typeof(StringEnumConverter))] + public MCIconSet? IconSet { get; set; } - [JsonProperty("loginMode")] - public string LoginMode { get; set; } + [JsonProperty("loginMode")] + public string LoginMode { get; set; } - [JsonProperty("modes")] - public Dictionary Modes { get; set; } + [JsonProperty("modes")] + public Dictionary Modes { get; set; } - [JsonProperty("enableRemoteLogging")] - public bool Logging { get; set; } + [JsonProperty("enableRemoteLogging")] + public bool Logging { get; set; } - [JsonProperty("partnerMetadata", NullValueHandling = NullValueHandling.Ignore)] - public List PartnerMetadata { get; set; } - } + [JsonProperty("partnerMetadata", NullValueHandling = NullValueHandling.Ignore)] + public List PartnerMetadata { get; set; } +} - public class MobileControlPartnerMetadata - { - [JsonProperty("role")] - public string Role { get; set; } +public class MobileControlPartnerMetadata +{ + [JsonProperty("role")] + public string Role { get; set; } - [JsonProperty("description")] - public string Description { get; set; } + [JsonProperty("description")] + public string Description { get; set; } - [JsonProperty("logoPath")] - public string LogoPath { get; set; } - } + [JsonProperty("logoPath")] + public string LogoPath { get; set; } +} - public class McMode - { - [JsonProperty("listPageText")] - public string ListPageText { get; set; } - [JsonProperty("loginHelpText")] - public string LoginHelpText { get; set; } +public class McMode +{ + [JsonProperty("listPageText")] + public string ListPageText { get; set; } + [JsonProperty("loginHelpText")] + public string LoginHelpText { get; set; } - [JsonProperty("passcodePageText")] - public string PasscodePageText { get; set; } - } + [JsonProperty("passcodePageText")] + public string PasscodePageText { get; set; } +} - public enum MCIconSet - { - GOOGLE, - HABANERO, - NEO - } +public enum MCIconSet +{ + GOOGLE, + HABANERO, + NEO } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl/MobileControlDeviceFactory.cs b/src/PepperDash.Essentials.MobileControl/MobileControlDeviceFactory.cs index 9fc8cc413..1e04e4842 100644 --- a/src/PepperDash.Essentials.MobileControl/MobileControlDeviceFactory.cs +++ b/src/PepperDash.Essentials.MobileControl/MobileControlDeviceFactory.cs @@ -8,27 +8,26 @@ using System.Linq; -namespace PepperDash.Essentials +namespace PepperDash.Essentials; + +public class MobileControlDeviceFactory : EssentialsDeviceFactory { - public class MobileControlDeviceFactory : EssentialsDeviceFactory + public MobileControlDeviceFactory() { - public MobileControlDeviceFactory() + TypeNames = new List { "appserver", "mobilecontrol", "webserver" }; + } + + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + try { - TypeNames = new List { "appserver", "mobilecontrol", "webserver" }; + var props = dc.Properties.ToObject(); + return new MobileControlSystemController(dc.Key, dc.Name, props); } - - public override EssentialsDevice BuildDevice(DeviceConfig dc) + catch (Exception e) { - try - { - var props = dc.Properties.ToObject(); - return new MobileControlSystemController(dc.Key, dc.Name, props); - } - catch (Exception e) - { - Debug.LogMessage(e, "Error building Mobile Control System Controller"); - return null; - } + Debug.LogMessage(e, "Error building Mobile Control System Controller"); + return null; } } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl/MobileControlEssentialsConfig.cs b/src/PepperDash.Essentials.MobileControl/MobileControlEssentialsConfig.cs index 0ba33b6ee..4621586cc 100644 --- a/src/PepperDash.Essentials.MobileControl/MobileControlEssentialsConfig.cs +++ b/src/PepperDash.Essentials.MobileControl/MobileControlEssentialsConfig.cs @@ -3,52 +3,51 @@ using System.Collections.Generic; -namespace PepperDash.Essentials +namespace PepperDash.Essentials; + +/// +/// Used to overlay additional config data from mobile control on +/// +public class MobileControlEssentialsConfig : EssentialsConfig { - /// - /// Used to overlay additional config data from mobile control on - /// - public class MobileControlEssentialsConfig : EssentialsConfig + [JsonProperty("runtimeInfo")] + public MobileControlRuntimeInfo RuntimeInfo { get; set; } + + public MobileControlEssentialsConfig(EssentialsConfig config) + : base() { - [JsonProperty("runtimeInfo")] - public MobileControlRuntimeInfo RuntimeInfo { get; set; } - - public MobileControlEssentialsConfig(EssentialsConfig config) - : base() - { - // TODO: Consider using Reflection to iterate properties - this.Devices = config.Devices; - this.Info = config.Info; - this.JoinMaps = config.JoinMaps; - this.Rooms = config.Rooms; - this.SourceLists = config.SourceLists; - this.DestinationLists = config.DestinationLists; - this.SystemUrl = config.SystemUrl; - this.TemplateUrl = config.TemplateUrl; - this.TieLines = config.TieLines; - - if (this.Info == null) - this.Info = new InfoConfig(); - - RuntimeInfo = new MobileControlRuntimeInfo(); - } + // TODO: Consider using Reflection to iterate properties + this.Devices = config.Devices; + this.Info = config.Info; + this.JoinMaps = config.JoinMaps; + this.Rooms = config.Rooms; + this.SourceLists = config.SourceLists; + this.DestinationLists = config.DestinationLists; + this.SystemUrl = config.SystemUrl; + this.TemplateUrl = config.TemplateUrl; + this.TieLines = config.TieLines; + + if (this.Info == null) + this.Info = new InfoConfig(); + + RuntimeInfo = new MobileControlRuntimeInfo(); } +} - /// - /// Used to add any additional runtime information from mobile control to be send to the API - /// - public class MobileControlRuntimeInfo - { - [JsonProperty("pluginVersion")] - public string PluginVersion { get; set; } +/// +/// Used to add any additional runtime information from mobile control to be send to the API +/// +public class MobileControlRuntimeInfo +{ + [JsonProperty("pluginVersion")] + public string PluginVersion { get; set; } - [JsonProperty("essentialsVersion")] - public string EssentialsVersion { get; set; } + [JsonProperty("essentialsVersion")] + public string EssentialsVersion { get; set; } - [JsonProperty("pepperDashCoreVersion")] - public string PepperDashCoreVersion { get; set; } + [JsonProperty("pepperDashCoreVersion")] + public string PepperDashCoreVersion { get; set; } - [JsonProperty("essentialsPlugins")] - public List EssentialsPlugins { get; set; } - } + [JsonProperty("essentialsPlugins")] + public List EssentialsPlugins { get; set; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl/MobileControlFactory.cs b/src/PepperDash.Essentials.MobileControl/MobileControlFactory.cs index 58e4ed8a2..bbd1d6def 100644 --- a/src/PepperDash.Essentials.MobileControl/MobileControlFactory.cs +++ b/src/PepperDash.Essentials.MobileControl/MobileControlFactory.cs @@ -4,36 +4,54 @@ using System.Linq; using System.Reflection; -namespace PepperDash.Essentials +namespace PepperDash.Essentials; + +public class MobileControlFactory { - public class MobileControlFactory + public MobileControlFactory() { - public MobileControlFactory() - { - var assembly = Assembly.GetExecutingAssembly(); + var assembly = Assembly.GetExecutingAssembly(); - PluginLoader.SetEssentialsAssembly(assembly.GetName().Name, assembly); + PluginLoader.AddLoadedAssembly(assembly.GetName().Name, assembly); - var types = assembly.GetTypes().Where(t => typeof(IDeviceFactory).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract); + var types = assembly.GetTypes().Where(t => typeof(IDeviceFactory).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract); - if (types == null) + if (types == null) + { + return; + } + + foreach (var type in types) + { + try { - return; - } + var factory = (IDeviceFactory)Activator.CreateInstance(type); - foreach (var type in types) + LoadDeviceFactories(factory); + } + catch (Exception ex) { - try - { - var factory = (IDeviceFactory)Activator.CreateInstance(type); - - factory.LoadTypeFactories(); - } - catch (Exception ex) - { - Debug.LogMessage(ex, "Unable to load type '{type}' DeviceFactory: {factory}", null, type.Name); - } + Debug.LogMessage(ex, "Unable to load type '{type}' DeviceFactory: {factory}", null, type.Name); } } } + + /// + /// Loads device factories from the specified plugin device factory and registers them for use. + /// + /// This method retrieves metadata from the provided , including + /// type names, descriptions, and configuration snippets, and registers the factory for each device type. The type + /// names are converted to lowercase for registration. + /// The plugin device factory that provides the device types, descriptions, and factory methods to be registered. + private static void LoadDeviceFactories(IDeviceFactory deviceFactory) + { + foreach (var typeName in deviceFactory.TypeNames) + { + //Debug.LogMessage(LogEventLevel.Verbose, "Getting Description Attribute from class: '{0}'", typeof(T).FullName); + var descriptionAttribute = deviceFactory.FactoryType.GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[]; + string description = descriptionAttribute[0].Description; + var snippetAttribute = deviceFactory.FactoryType.GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[]; + Core.DeviceFactory.AddFactoryForType(typeName.ToLower(), description, deviceFactory.FactoryType, deviceFactory.BuildDevice); + } + } } diff --git a/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs b/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs index b17e0490f..cb026a53c 100644 --- a/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs +++ b/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs @@ -1,4 +1,10 @@ -using Crestron.SimplSharp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Crestron.SimplSharp; using Crestron.SimplSharp.CrestronIO; using Crestron.SimplSharp.Net.Http; using Crestron.SimplSharp.WebScripting; @@ -30,2323 +36,2306 @@ using PepperDash.Essentials.Services; using PepperDash.Essentials.WebApiHandlers; using PepperDash.Essentials.WebSocketServer; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text.RegularExpressions; -using System.Threading.Tasks; using WebSocketSharp; -namespace PepperDash.Essentials +namespace PepperDash.Essentials; + +public class MobileControlSystemController : EssentialsDevice, IMobileControl { - public class MobileControlSystemController : EssentialsDevice, IMobileControl - { - private bool _initialized = false; - private const long ServerReconnectInterval = 5000; - private const long PingInterval = 25000; + private bool _initialized = false; + private const long ServerReconnectInterval = 5000; + private const long PingInterval = 25000; - private readonly Dictionary> _actionDictionary = - new Dictionary>( - StringComparer.InvariantCultureIgnoreCase - ); + private readonly Dictionary> _actionDictionary = + new Dictionary>( + StringComparer.InvariantCultureIgnoreCase + ); - public Dictionary> ActionDictionary => _actionDictionary; + public Dictionary> ActionDictionary => _actionDictionary; - private readonly GenericQueue _receiveQueue; - private readonly List _roomBridges = - new List(); + private readonly GenericQueue _receiveQueue; + private readonly List _roomBridges = + new List(); - private readonly Dictionary _messengers = - new Dictionary(); + private readonly Dictionary _messengers = + new Dictionary(); - private readonly Dictionary _defaultMessengers = - new Dictionary(); + private readonly Dictionary _defaultMessengers = + new Dictionary(); - private readonly GenericQueue _transmitToServerQueue; + private readonly GenericQueue _transmitToServerQueue; - private readonly GenericQueue _transmitToClientsQueue; + private readonly GenericQueue _transmitToClientsQueue; - private bool _disableReconnect; - private WebSocket _wsClient2; + private bool _disableReconnect; + private WebSocket _wsClient2; - public MobileControlApiService ApiService { get; private set; } + public MobileControlApiService ApiService { get; private set; } - public List RoomBridges => _roomBridges; + public List RoomBridges => _roomBridges; - private readonly MobileControlWebsocketServer _directServer; + private readonly MobileControlWebsocketServer _directServer; - public MobileControlWebsocketServer DirectServer => _directServer; + public MobileControlWebsocketServer DirectServer => _directServer; - private readonly CCriticalSection _wsCriticalSection = new CCriticalSection(); + private readonly CCriticalSection _wsCriticalSection = new CCriticalSection(); - public string SystemUrl; //set only from SIMPL Bridge! + public string SystemUrl; //set only from SIMPL Bridge! - public bool Connected => _wsClient2 != null && _wsClient2.IsAlive; + public bool Connected => _wsClient2 != null && _wsClient2.IsAlive; - private IEssentialsRoomCombiner _roomCombiner; + private IEssentialsRoomCombiner _roomCombiner; - public string SystemUuid + public string SystemUuid + { + get { - get + // Check to see if the SystemUuid value is populated. If not populated from configuration, check for value from SIMPL bridge. + if ( + !string.IsNullOrEmpty(ConfigReader.ConfigObject.SystemUuid) + && ConfigReader.ConfigObject.SystemUuid != "missing url" + ) { - // Check to see if the SystemUuid value is populated. If not populated from configuration, check for value from SIMPL bridge. - if ( - !string.IsNullOrEmpty(ConfigReader.ConfigObject.SystemUuid) - && ConfigReader.ConfigObject.SystemUuid != "missing url" - ) - { - return ConfigReader.ConfigObject.SystemUuid; - } - - this.LogWarning( - "No system_url value defined in config. Checking for value from SIMPL Bridge." - ); + return ConfigReader.ConfigObject.SystemUuid; + } - if (!string.IsNullOrEmpty(SystemUrl)) - { - this.LogError( - "No system_url value defined in config or SIMPL Bridge. Unable to connect to Mobile Control." - ); - return string.Empty; - } + this.LogWarning( + "No system_url value defined in config. Checking for value from SIMPL Bridge." + ); - var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/#.*"); - string uuid = result.Groups[1].Value; - return uuid; + if (!string.IsNullOrEmpty(SystemUrl)) + { + this.LogError( + "No system_url value defined in config or SIMPL Bridge. Unable to connect to Mobile Control." + ); + return string.Empty; } + + var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/#.*"); + string uuid = result.Groups[1].Value; + return uuid; } + } - public BoolFeedback ApiOnlineAndAuthorized { get; private set; } + public BoolFeedback ApiOnlineAndAuthorized { get; private set; } - /// - /// Used for tracking HTTP debugging - /// - private bool _httpDebugEnabled; + /// + /// Used for tracking HTTP debugging + /// + private bool _httpDebugEnabled; - private bool _isAuthorized; + private bool _isAuthorized; - /// - /// Tracks if the system is authorized to the API server - /// - public bool IsAuthorized + /// + /// Tracks if the system is authorized to the API server + /// + public bool IsAuthorized + { + get { return _isAuthorized; } + private set { - get { return _isAuthorized; } - private set - { - if (value == _isAuthorized) - return; + if (value == _isAuthorized) + return; - _isAuthorized = value; - ApiOnlineAndAuthorized.FireUpdate(); - } + _isAuthorized = value; + ApiOnlineAndAuthorized.FireUpdate(); } + } - private DateTime _lastAckMessage; + private DateTime _lastAckMessage; - public DateTime LastAckMessage => _lastAckMessage; + public DateTime LastAckMessage => _lastAckMessage; - private CTimer _pingTimer; + private CTimer _pingTimer; - private CTimer _serverReconnectTimer; - private LogLevel _wsLogLevel = LogLevel.Error; + private CTimer _serverReconnectTimer; + private LogLevel _wsLogLevel = LogLevel.Error; - /// - /// - /// - /// - /// - /// - public MobileControlSystemController(string key, string name, MobileControlConfig config) - : base(key, name) + /// + /// + /// + /// + /// + /// + public MobileControlSystemController(string key, string name, MobileControlConfig config) + : base(key, name) + { + Config = config; + + // The queue that will collect the incoming messages in the order they are received + //_receiveQueue = new ReceiveQueue(key, ParseStreamRx); + _receiveQueue = new GenericQueue( + key + "-rxqueue", + Crestron.SimplSharpPro.CrestronThread.Thread.eThreadPriority.HighPriority, + 25 + ); + + // The queue that will collect the outgoing messages in the order they are received + _transmitToServerQueue = new GenericQueue( + key + "-txqueue", + Crestron.SimplSharpPro.CrestronThread.Thread.eThreadPriority.HighPriority, + 25 + ); + + if (Config.DirectServer != null && Config.DirectServer.EnableDirectServer) { - Config = config; - - // The queue that will collect the incoming messages in the order they are received - //_receiveQueue = new ReceiveQueue(key, ParseStreamRx); - _receiveQueue = new GenericQueue( - key + "-rxqueue", - Crestron.SimplSharpPro.CrestronThread.Thread.eThreadPriority.HighPriority, - 25 + _directServer = new MobileControlWebsocketServer( + Key + "-directServer", + Config.DirectServer.Port, + this ); + DeviceManager.AddDevice(_directServer); - // The queue that will collect the outgoing messages in the order they are received - _transmitToServerQueue = new GenericQueue( - key + "-txqueue", + _transmitToClientsQueue = new GenericQueue( + key + "-clienttxqueue", Crestron.SimplSharpPro.CrestronThread.Thread.eThreadPriority.HighPriority, 25 ); + } - if (Config.DirectServer != null && Config.DirectServer.EnableDirectServer) - { - _directServer = new MobileControlWebsocketServer( - Key + "-directServer", - Config.DirectServer.Port, - this - ); - DeviceManager.AddDevice(_directServer); - - _transmitToClientsQueue = new GenericQueue( - key + "-clienttxqueue", - Crestron.SimplSharpPro.CrestronThread.Thread.eThreadPriority.HighPriority, - 25 - ); - } + Host = config.ServerUrl; + if (!Host.StartsWith("http")) + { + Host = "https://" + Host; + } - Host = config.ServerUrl; - if (!Host.StartsWith("http")) - { - Host = "https://" + Host; - } + ApiService = new MobileControlApiService(Host); - ApiService = new MobileControlApiService(Host); + this.LogInformation( + "Mobile UI controller initializing for server:{0}", + config.ServerUrl + ); - this.LogInformation( - "Mobile UI controller initializing for server:{0}", - config.ServerUrl - ); + if (Global.Platform == eDevicePlatform.Appliance) + { + AddConsoleCommands(); + } - if (Global.Platform == eDevicePlatform.Appliance) - { - AddConsoleCommands(); - } + AddPreActivationAction(() => LinkSystemMonitorToAppServer()); - AddPreActivationAction(() => LinkSystemMonitorToAppServer()); + AddPreActivationAction(() => SetupDefaultDeviceMessengers()); - AddPreActivationAction(() => SetupDefaultDeviceMessengers()); + AddPreActivationAction(() => SetupDefaultRoomMessengers()); - AddPreActivationAction(() => SetupDefaultRoomMessengers()); + AddPreActivationAction(() => AddWebApiPaths()); - AddPreActivationAction(() => AddWebApiPaths()); + AddPreActivationAction(() => + { + _roomCombiner = DeviceManager.AllDevices.OfType().FirstOrDefault(); - AddPreActivationAction(() => - { - _roomCombiner = DeviceManager.AllDevices.OfType().FirstOrDefault(); + if (_roomCombiner == null) + return; - if (_roomCombiner == null) - return; + _roomCombiner.RoomCombinationScenarioChanged += OnRoomCombinationScenarioChanged; + }); - _roomCombiner.RoomCombinationScenarioChanged += OnRoomCombinationScenarioChanged; - }); + CrestronEnvironment.ProgramStatusEventHandler += + CrestronEnvironment_ProgramStatusEventHandler; - CrestronEnvironment.ProgramStatusEventHandler += - CrestronEnvironment_ProgramStatusEventHandler; + ApiOnlineAndAuthorized = new BoolFeedback(() => + { + if (_wsClient2 == null) + return false; - ApiOnlineAndAuthorized = new BoolFeedback(() => - { - if (_wsClient2 == null) - return false; + return _wsClient2.IsAlive && IsAuthorized; + }); + } - return _wsClient2.IsAlive && IsAuthorized; - }); - } + private void SetupDefaultRoomMessengers() + { + this.LogVerbose("Setting up room messengers"); - private void SetupDefaultRoomMessengers() + foreach (var room in DeviceManager.AllDevices.OfType()) { - this.LogVerbose("Setting up room messengers"); - - foreach (var room in DeviceManager.AllDevices.OfType()) - { - this.LogVerbose( - "Setting up room messengers for room: {key}", - room.Key - ); + this.LogVerbose( + "Setting up room messengers for room: {key}", + room.Key + ); - var messenger = new MobileControlEssentialsRoomBridge(room); + var messenger = new MobileControlEssentialsRoomBridge(room); - messenger.AddParent(this); + messenger.AddParent(this); - _roomBridges.Add(messenger); + _roomBridges.Add(messenger); - AddDefaultDeviceMessenger(messenger); + AddDefaultDeviceMessenger(messenger); - this.LogVerbose( - "Attempting to set up default room messengers for room: {0}", - room.Key - ); + this.LogVerbose( + "Attempting to set up default room messengers for room: {0}", + room.Key + ); - if (room is IRoomEventSchedule) - { - this.LogInformation("Setting up event schedule messenger for room: {key}", room.Key); + if (room is IRoomEventSchedule) + { + this.LogInformation("Setting up event schedule messenger for room: {key}", room.Key); - var scheduleMessenger = new RoomEventScheduleMessenger( - $"{room.Key}-schedule-{Key}", - string.Format("/room/{0}", room.Key), - room as IRoomEventSchedule - ); + var scheduleMessenger = new RoomEventScheduleMessenger( + $"{room.Key}-schedule-{Key}", + string.Format("/room/{0}", room.Key), + room as IRoomEventSchedule + ); - AddDefaultDeviceMessenger(scheduleMessenger); - } + AddDefaultDeviceMessenger(scheduleMessenger); + } - if (room is ITechPassword) - { - this.LogInformation("Setting up tech password messenger for room: {key}", room.Key); + if (room is ITechPassword) + { + this.LogInformation("Setting up tech password messenger for room: {key}", room.Key); - var techPasswordMessenger = new ITechPasswordMessenger( - $"{room.Key}-techPassword-{Key}", - string.Format("/room/{0}", room.Key), - room as ITechPassword - ); + var techPasswordMessenger = new ITechPasswordMessenger( + $"{room.Key}-techPassword-{Key}", + string.Format("/room/{0}", room.Key), + room as ITechPassword + ); - AddDefaultDeviceMessenger(techPasswordMessenger); - } + AddDefaultDeviceMessenger(techPasswordMessenger); + } - if (room is IShutdownPromptTimer) - { - this.LogInformation("Setting up shutdown prompt timer messenger for room: {key}", this, room.Key); + if (room is IShutdownPromptTimer) + { + this.LogInformation("Setting up shutdown prompt timer messenger for room: {key}", this, room.Key); - var shutdownPromptTimerMessenger = new IShutdownPromptTimerMessenger( - $"{room.Key}-shutdownPromptTimer-{Key}", - string.Format("/room/{0}", room.Key), - room as IShutdownPromptTimer - ); + var shutdownPromptTimerMessenger = new IShutdownPromptTimerMessenger( + $"{room.Key}-shutdownPromptTimer-{Key}", + string.Format("/room/{0}", room.Key), + room as IShutdownPromptTimer + ); - AddDefaultDeviceMessenger(shutdownPromptTimerMessenger); - } + AddDefaultDeviceMessenger(shutdownPromptTimerMessenger); + } - if (room is ILevelControls levelControls) - { - this.LogInformation("Setting up level controls messenger for room: {key}", this, room.Key); + if (room is ILevelControls levelControls) + { + this.LogInformation("Setting up level controls messenger for room: {key}", this, room.Key); - var levelControlsMessenger = new ILevelControlsMessenger( - $"{room.Key}-levelControls-{Key}", - $"/room/{room.Key}", - levelControls - ); + var levelControlsMessenger = new ILevelControlsMessenger( + $"{room.Key}-levelControls-{Key}", + $"/room/{room.Key}", + levelControls + ); - AddDefaultDeviceMessenger(levelControlsMessenger); - } + AddDefaultDeviceMessenger(levelControlsMessenger); } } + } - /// - /// Set up the messengers for each device type - /// - private void SetupDefaultDeviceMessengers() - { - bool messengerAdded = false; + /// + /// Set up the messengers for each device type + /// + private void SetupDefaultDeviceMessengers() + { + bool messengerAdded = false; - var allDevices = DeviceManager.AllDevices.Where((d) => !(d is IEssentialsRoom)); + var allDevices = DeviceManager.AllDevices.Where((d) => !(d is IEssentialsRoom)); - this.LogInformation( - "All Devices that aren't rooms count: {0}", - allDevices?.Count() - ); + this.LogInformation( + "All Devices that aren't rooms count: {0}", + allDevices?.Count() + ); - var count = allDevices.Count(); + var count = allDevices.Count(); - foreach (var device in allDevices) + foreach (var device in allDevices) + { + try { - try + this.LogVerbose( + "Attempting to set up device messengers for {deviceKey}", + device.Key + ); + + // StatusMonitorBase which is prop of ICommunicationMonitor is not a PepperDash.Core.Device, but is in the device array + if (device is ICommunicationMonitor) { this.LogVerbose( - "Attempting to set up device messengers for {deviceKey}", + "Checking if {deviceKey} implements ICommunicationMonitor", device.Key ); - // StatusMonitorBase which is prop of ICommunicationMonitor is not a PepperDash.Core.Device, but is in the device array - if (device is ICommunicationMonitor) + if (!(device is ICommunicationMonitor commMonitor)) { - this.LogVerbose( - "Checking if {deviceKey} implements ICommunicationMonitor", + this.LogDebug( + "{deviceKey} does not implement ICommunicationMonitor. Skipping CommunicationMonitorMessenger", device.Key ); - if (!(device is ICommunicationMonitor commMonitor)) - { - this.LogDebug( - "{deviceKey} does not implement ICommunicationMonitor. Skipping CommunicationMonitorMessenger", - device.Key - ); + this.LogDebug("Created all messengers for {deviceKey}. Devices Left: {deviceCount}", device.Key, --count); - this.LogDebug("Created all messengers for {deviceKey}. Devices Left: {deviceCount}", device.Key, --count); + continue; + } - continue; - } + this.LogDebug( + "Adding CommunicationMonitorMessenger for {deviceKey}", + device.Key + ); - this.LogDebug( - "Adding CommunicationMonitorMessenger for {deviceKey}", - device.Key - ); + var commMessenger = new ICommunicationMonitorMessenger( + $"{device.Key}-commMonitor-{Key}", + string.Format("/device/{0}", device.Key), + commMonitor + ); - var commMessenger = new ICommunicationMonitorMessenger( - $"{device.Key}-commMonitor-{Key}", - string.Format("/device/{0}", device.Key), - commMonitor - ); + AddDefaultDeviceMessenger(commMessenger); - AddDefaultDeviceMessenger(commMessenger); + messengerAdded = true; + } - messengerAdded = true; - } + if (device is CameraBase cameraDevice) + { + this.LogVerbose( + "Adding CameraBaseMessenger for {deviceKey}", + device.Key + ); - if (device is CameraBase cameraDevice) - { - this.LogVerbose( - "Adding CameraBaseMessenger for {deviceKey}", - device.Key - ); + var cameraMessenger = new CameraBaseMessenger( + $"{device.Key}-cameraBase-{Key}", + cameraDevice, + $"/device/{device.Key}" + ); - var cameraMessenger = new CameraBaseMessenger( - $"{device.Key}-cameraBase-{Key}", - cameraDevice, - $"/device/{device.Key}" - ); + AddDefaultDeviceMessenger(cameraMessenger); - AddDefaultDeviceMessenger(cameraMessenger); + messengerAdded = true; + } - messengerAdded = true; - } + if (device is BlueJeansPc) + { + this.LogVerbose( + "Adding IRunRouteActionMessnger for {deviceKey}", + device.Key + ); - if (device is BlueJeansPc) - { - this.LogVerbose( - "Adding IRunRouteActionMessnger for {deviceKey}", - device.Key - ); + var routeMessenger = new RunRouteActionMessenger( + $"{device.Key}-runRouteAction-{Key}", + device as BlueJeansPc, + $"/device/{device.Key}" + ); - var routeMessenger = new RunRouteActionMessenger( - $"{device.Key}-runRouteAction-{Key}", - device as BlueJeansPc, - $"/device/{device.Key}" - ); + AddDefaultDeviceMessenger(routeMessenger); - AddDefaultDeviceMessenger(routeMessenger); + messengerAdded = true; + } - messengerAdded = true; - } + if (device is ITvPresetsProvider) + { + this.LogVerbose( + "Trying to cast to ITvPresetsProvider for {deviceKey}", + device.Key + ); - if (device is ITvPresetsProvider) - { - this.LogVerbose( - "Trying to cast to ITvPresetsProvider for {deviceKey}", - device.Key - ); + var presetsDevice = device as ITvPresetsProvider; - var presetsDevice = device as ITvPresetsProvider; + this.LogVerbose( + "Adding ITvPresetsProvider for {deviceKey}", + device.Key + ); - this.LogVerbose( - "Adding ITvPresetsProvider for {deviceKey}", - device.Key - ); + var presetsMessenger = new DevicePresetsModelMessenger( + $"{device.Key}-presets-{Key}", + $"/device/{device.Key}", + presetsDevice + ); - var presetsMessenger = new DevicePresetsModelMessenger( - $"{device.Key}-presets-{Key}", - $"/device/{device.Key}", - presetsDevice - ); + AddDefaultDeviceMessenger(presetsMessenger); - AddDefaultDeviceMessenger(presetsMessenger); + messengerAdded = true; + } - messengerAdded = true; - } + if (device is DisplayBase) + { + this.LogVerbose("Adding actions for device: {0}", device.Key); - if (device is DisplayBase) - { - this.LogVerbose("Adding actions for device: {0}", device.Key); + var dbMessenger = new DisplayBaseMessenger( + $"{device.Key}-displayBase-{Key}", + $"/device/{device.Key}", + device as DisplayBase + ); - var dbMessenger = new DisplayBaseMessenger( - $"{device.Key}-displayBase-{Key}", - $"/device/{device.Key}", - device as DisplayBase - ); + AddDefaultDeviceMessenger(dbMessenger); - AddDefaultDeviceMessenger(dbMessenger); + messengerAdded = true; + } - messengerAdded = true; - } + if (device is TwoWayDisplayBase twoWayDisplay) + { + this.LogVerbose( + "Adding TwoWayDisplayBase for {deviceKey}", + device.Key + ); + var twoWayDisplayMessenger = new TwoWayDisplayBaseMessenger( + $"{device.Key}-twoWayDisplay-{Key}", + string.Format("/device/{0}", device.Key), + twoWayDisplay + ); + AddDefaultDeviceMessenger(twoWayDisplayMessenger); - if (device is TwoWayDisplayBase twoWayDisplay) - { - this.LogVerbose( - "Adding TwoWayDisplayBase for {deviceKey}", - device.Key - ); - var twoWayDisplayMessenger = new TwoWayDisplayBaseMessenger( - $"{device.Key}-twoWayDisplay-{Key}", - string.Format("/device/{0}", device.Key), - twoWayDisplay - ); - AddDefaultDeviceMessenger(twoWayDisplayMessenger); + messengerAdded = true; + } - messengerAdded = true; - } + if (device is IBasicVolumeWithFeedback) + { + var deviceKey = device.Key; + this.LogVerbose( + "Adding IBasicVolumeControlWithFeedback for {deviceKey}", + deviceKey + ); - if (device is IBasicVolumeWithFeedback) - { - var deviceKey = device.Key; - this.LogVerbose( - "Adding IBasicVolumeControlWithFeedback for {deviceKey}", - deviceKey - ); + var volControlDevice = device as IBasicVolumeWithFeedback; + var messenger = new DeviceVolumeMessenger( + $"{device.Key}-volume-{Key}", + string.Format("/device/{0}", deviceKey), + volControlDevice + ); + AddDefaultDeviceMessenger(messenger); - var volControlDevice = device as IBasicVolumeWithFeedback; - var messenger = new DeviceVolumeMessenger( - $"{device.Key}-volume-{Key}", - string.Format("/device/{0}", deviceKey), - volControlDevice - ); - AddDefaultDeviceMessenger(messenger); + messengerAdded = true; + } - messengerAdded = true; - } + if (device is ILightingScenes || device is LightingBase) + { + var deviceKey = device.Key; - if (device is ILightingScenes || device is LightingBase) - { - var deviceKey = device.Key; + this.LogVerbose( + "Adding LightingBaseMessenger for {deviceKey}", + deviceKey + ); - this.LogVerbose( - "Adding LightingBaseMessenger for {deviceKey}", - deviceKey - ); + var lightingDevice = device as ILightingScenes; + var messenger = new ILightingScenesMessenger( + $"{device.Key}-lighting-{Key}", + lightingDevice, + string.Format("/device/{0}", deviceKey) + ); + AddDefaultDeviceMessenger(messenger); - var lightingDevice = device as ILightingScenes; - var messenger = new ILightingScenesMessenger( - $"{device.Key}-lighting-{Key}", - lightingDevice, - string.Format("/device/{0}", deviceKey) - ); - AddDefaultDeviceMessenger(messenger); + messengerAdded = true; + } - messengerAdded = true; - } + if (device is IShadesOpenCloseStop) + { + var deviceKey = device.Key; + var shadeDevice = device as IShadesOpenCloseStop; - if (device is IShadesOpenCloseStop) - { - var deviceKey = device.Key; - var shadeDevice = device as IShadesOpenCloseStop; + this.LogVerbose( + "Adding ShadeBaseMessenger for {deviceKey}", + deviceKey + ); - this.LogVerbose( - "Adding ShadeBaseMessenger for {deviceKey}", - deviceKey - ); + var messenger = new IShadesOpenCloseStopMessenger( + $"{device.Key}-shades-{Key}", + shadeDevice, + string.Format("/device/{0}", deviceKey) + ); + AddDefaultDeviceMessenger(messenger); - var messenger = new IShadesOpenCloseStopMessenger( - $"{device.Key}-shades-{Key}", - shadeDevice, - string.Format("/device/{0}", deviceKey) - ); - AddDefaultDeviceMessenger(messenger); + messengerAdded = true; + } - messengerAdded = true; - } + if (device is VideoCodecBase codec) + { + this.LogVerbose( + "Adding VideoCodecBaseMessenger for {deviceKey}", codec.Key); - if (device is VideoCodecBase codec) - { - this.LogVerbose( - "Adding VideoCodecBaseMessenger for {deviceKey}", codec.Key); + var messenger = new VideoCodecBaseMessenger( + $"{codec.Key}-videoCodec-{Key}", + codec, + $"/device/{codec.Key}" + ); - var messenger = new VideoCodecBaseMessenger( - $"{codec.Key}-videoCodec-{Key}", - codec, - $"/device/{codec.Key}" - ); + AddDefaultDeviceMessenger(messenger); - AddDefaultDeviceMessenger(messenger); + messengerAdded = true; + } - messengerAdded = true; - } + if (device is AudioCodecBase audioCodec) + { + this.LogVerbose( + "Adding AudioCodecBaseMessenger for {deviceKey}", audioCodec.Key + ); - if (device is AudioCodecBase audioCodec) - { - this.LogVerbose( - "Adding AudioCodecBaseMessenger for {deviceKey}", audioCodec.Key - ); + var messenger = new AudioCodecBaseMessenger( + $"{audioCodec.Key}-audioCodec-{Key}", + audioCodec, + $"/device/{audioCodec.Key}" + ); - var messenger = new AudioCodecBaseMessenger( - $"{audioCodec.Key}-audioCodec-{Key}", - audioCodec, - $"/device/{audioCodec.Key}" - ); + AddDefaultDeviceMessenger(messenger); - AddDefaultDeviceMessenger(messenger); + messengerAdded = true; + } - messengerAdded = true; - } + if (device is ISetTopBoxControls stbDevice) + { + this.LogVerbose( + "Adding ISetTopBoxControlMessenger for {deviceKey}" + ); - if (device is ISetTopBoxControls stbDevice) - { - this.LogVerbose( - "Adding ISetTopBoxControlMessenger for {deviceKey}" - ); + var messenger = new ISetTopBoxControlsMessenger( + $"{device.Key}-stb-{Key}", + $"/device/{device.Key}", + stbDevice + ); - var messenger = new ISetTopBoxControlsMessenger( - $"{device.Key}-stb-{Key}", - $"/device/{device.Key}", - stbDevice - ); + AddDefaultDeviceMessenger(messenger); - AddDefaultDeviceMessenger(messenger); + messengerAdded = true; + } - messengerAdded = true; - } + if (device is IChannel channelDevice) + { + this.LogVerbose( + "Adding IChannelMessenger for {deviceKey}", device.Key + ); - if (device is IChannel channelDevice) - { - this.LogVerbose( - "Adding IChannelMessenger for {deviceKey}", device.Key - ); + var messenger = new IChannelMessenger( + $"{device.Key}-channel-{Key}", + $"/device/{device.Key}", + channelDevice + ); - var messenger = new IChannelMessenger( - $"{device.Key}-channel-{Key}", - $"/device/{device.Key}", - channelDevice - ); + AddDefaultDeviceMessenger(messenger); - AddDefaultDeviceMessenger(messenger); + messengerAdded = true; + } - messengerAdded = true; - } + if (device is IColor colorDevice) + { + this.LogVerbose("Adding IColorMessenger for {deviceKey}", device.Key); - if (device is IColor colorDevice) - { - this.LogVerbose("Adding IColorMessenger for {deviceKey}", device.Key); + var messenger = new IColorMessenger( + $"{device.Key}-color-{Key}", + $"/device/{device.Key}", + colorDevice + ); - var messenger = new IColorMessenger( - $"{device.Key}-color-{Key}", - $"/device/{device.Key}", - colorDevice - ); + AddDefaultDeviceMessenger(messenger); - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IDPad dPadDevice) - { - this.LogVerbose("Adding IDPadMessenger for {deviceKey}", device.Key); - - var messenger = new IDPadMessenger( - $"{device.Key}-dPad-{Key}", - $"/device/{device.Key}", - dPadDevice - ); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is IDPad dPadDevice) + { + this.LogVerbose("Adding IDPadMessenger for {deviceKey}", device.Key); - messengerAdded = true; - } + var messenger = new IDPadMessenger( + $"{device.Key}-dPad-{Key}", + $"/device/{device.Key}", + dPadDevice + ); - if (device is INumericKeypad nkDevice) - { - this.LogVerbose("Adding INumericKeyapdMessenger for {deviceKey}", device.Key); + AddDefaultDeviceMessenger(messenger); - var messenger = new INumericKeypadMessenger( - $"{device.Key}-numericKeypad-{Key}", - $"/device/{device.Key}", - nkDevice - ); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is INumericKeypad nkDevice) + { + this.LogVerbose("Adding INumericKeyapdMessenger for {deviceKey}", device.Key); - messengerAdded = true; - } + var messenger = new INumericKeypadMessenger( + $"{device.Key}-numericKeypad-{Key}", + $"/device/{device.Key}", + nkDevice + ); - if (device is IHasPowerControl pcDevice) - { - this.LogVerbose("Adding IHasPowerControlMessenger for {deviceKey}", device.Key); + AddDefaultDeviceMessenger(messenger); - var messenger = new IHasPowerMessenger( - $"{device.Key}-powerControl-{Key}", - $"/device/{device.Key}", - pcDevice - ); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is IHasPowerControl pcDevice) + { + this.LogVerbose("Adding IHasPowerControlMessenger for {deviceKey}", device.Key); - messengerAdded = true; - } + var messenger = new IHasPowerMessenger( + $"{device.Key}-powerControl-{Key}", + $"/device/{device.Key}", + pcDevice + ); - if (device is IHasPowerControlWithFeedback powerControl) - { - var deviceKey = device.Key; - this.LogVerbose( - "Adding IHasPowerControlWithFeedbackMessenger for {deviceKey}", - deviceKey - ); + AddDefaultDeviceMessenger(messenger); - var messenger = new IHasPowerControlWithFeedbackMessenger( - $"{device.Key}-powerFeedback-{Key}", - string.Format("/device/{0}", deviceKey), - powerControl - ); - AddDefaultDeviceMessenger(messenger); - messengerAdded = true; - } + messengerAdded = true; + } - if (device is ITransport transportDevice) - { - this.LogVerbose( - "Adding ITransportMessenger for {deviceKey}", device.Key - ); + if (device is IHasPowerControlWithFeedback powerControl) + { + var deviceKey = device.Key; + this.LogVerbose( + "Adding IHasPowerControlWithFeedbackMessenger for {deviceKey}", + deviceKey + ); - var messenger = new ITransportMessenger( - $"{device.Key}-transport-{Key}", - $"/device/{device.Key}", - transportDevice - ); + var messenger = new IHasPowerControlWithFeedbackMessenger( + $"{device.Key}-powerFeedback-{Key}", + string.Format("/device/{0}", deviceKey), + powerControl + ); + AddDefaultDeviceMessenger(messenger); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is ITransport transportDevice) + { + this.LogVerbose( + "Adding ITransportMessenger for {deviceKey}", device.Key + ); - messengerAdded = true; - } + var messenger = new ITransportMessenger( + $"{device.Key}-transport-{Key}", + $"/device/{device.Key}", + transportDevice + ); - if (device is IHasCurrentSourceInfoChange csiChange) - { - this.LogVerbose("Adding IHasCurrentSourceInfoMessenger for {deviceKey}", device.Key); + AddDefaultDeviceMessenger(messenger); - var messenger = new IHasCurrentSourceInfoMessenger( - $"{device.Key}-currentSource-{Key}", - $"/device/{device.Key}", - csiChange - ); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is IHasCurrentSourceInfoChange csiChange) + { + this.LogVerbose("Adding IHasCurrentSourceInfoMessenger for {deviceKey}", device.Key); - messengerAdded = true; - } + var messenger = new IHasCurrentSourceInfoMessenger( + $"{device.Key}-currentSource-{Key}", + $"/device/{device.Key}", + csiChange + ); - if (device is ISwitchedOutput switchedDevice) - { - this.LogVerbose( - "Adding ISwitchedOutputMessenger for {deviceKey}", device.Key - ); + AddDefaultDeviceMessenger(messenger); - var messenger = new ISwitchedOutputMessenger( - $"{device.Key}-switchedOutput-{Key}", - switchedDevice, - $"/device/{device.Key}" - ); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is ISwitchedOutput switchedDevice) + { + this.LogVerbose( + "Adding ISwitchedOutputMessenger for {deviceKey}", device.Key + ); - messengerAdded = true; - } + var messenger = new ISwitchedOutputMessenger( + $"{device.Key}-switchedOutput-{Key}", + switchedDevice, + $"/device/{device.Key}" + ); - if (device is IDeviceInfoProvider provider) - { - this.LogVerbose("Adding IHasDeviceInfoMessenger for {deviceKey}", device.Key - ); + AddDefaultDeviceMessenger(messenger); - var messenger = new DeviceInfoMessenger( - $"{device.Key}-deviceInfo-{Key}", - $"/device/{device.Key}", - provider - ); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is IDeviceInfoProvider provider) + { + this.LogVerbose("Adding IHasDeviceInfoMessenger for {deviceKey}", device.Key + ); - messengerAdded = true; - } + var messenger = new DeviceInfoMessenger( + $"{device.Key}-deviceInfo-{Key}", + $"/device/{device.Key}", + provider + ); - if (device is ILevelControls levelControls) - { - this.LogVerbose( - "Adding LevelControlsMessenger for {deviceKey}", device.Key - ); + AddDefaultDeviceMessenger(messenger); - var messenger = new ILevelControlsMessenger( - $"{device.Key}-levelControls-{Key}", - $"/device/{device.Key}", - levelControls - ); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is ILevelControls levelControls) + { + this.LogVerbose( + "Adding LevelControlsMessenger for {deviceKey}", device.Key + ); - messengerAdded = true; - } + var messenger = new ILevelControlsMessenger( + $"{device.Key}-levelControls-{Key}", + $"/device/{device.Key}", + levelControls + ); - if (device is IHasInputs stringInputs) - { - this.LogVerbose("Adding InputsMessenger for {deviceKey}", device.Key); + AddDefaultDeviceMessenger(messenger); - var messenger = new IHasInputsMessenger( - $"{device.Key}-inputs-{Key}", - $"/device/{device.Key}", - stringInputs - ); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is IHasInputs stringInputs) + { + this.LogVerbose("Adding InputsMessenger for {deviceKey}", device.Key); - messengerAdded = true; - } + var messenger = new IHasInputsMessenger( + $"{device.Key}-inputs-{Key}", + $"/device/{device.Key}", + stringInputs + ); - if (device is IHasInputs byteInputs) - { - this.LogVerbose("Adding InputsMessenger for {deviceKey}", device.Key); + AddDefaultDeviceMessenger(messenger); - var messenger = new IHasInputsMessenger( - $"{device.Key}-inputs-{Key}", - $"/device/{device.Key}", - byteInputs - ); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is IHasInputs byteInputs) + { + this.LogVerbose("Adding InputsMessenger for {deviceKey}", device.Key); - messengerAdded = true; - } + var messenger = new IHasInputsMessenger( + $"{device.Key}-inputs-{Key}", + $"/device/{device.Key}", + byteInputs + ); - if (device is IHasInputs intInputs) - { - this.LogVerbose("Adding InputsMessenger for {deviceKey}", device.Key); + AddDefaultDeviceMessenger(messenger); - var messenger = new IHasInputsMessenger( - $"{device.Key}-inputs-{Key}", - $"/device/{device.Key}", - intInputs - ); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is IHasInputs intInputs) + { + this.LogVerbose("Adding InputsMessenger for {deviceKey}", device.Key); - messengerAdded = true; - } + var messenger = new IHasInputsMessenger( + $"{device.Key}-inputs-{Key}", + $"/device/{device.Key}", + intInputs + ); - if (device is IMatrixRouting matrix) - { - this.LogVerbose( - "Adding IMatrixRoutingMessenger for {deviceKey}", - device.Key - ); + AddDefaultDeviceMessenger(messenger); - var messenger = new IMatrixRoutingMessenger( - $"{device.Key}-matrixRouting", - $"/device/{device.Key}", - matrix - ); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is IMatrixRouting matrix) + { + this.LogVerbose( + "Adding IMatrixRoutingMessenger for {deviceKey}", + device.Key + ); - messengerAdded = true; - } + var messenger = new IMatrixRoutingMessenger( + $"{device.Key}-matrixRouting", + $"/device/{device.Key}", + matrix + ); - if (device is ITemperatureSensor tempSensor) - { - this.LogVerbose( - "Adding ITemperatureSensor for {deviceKey}", - device.Key - ); + AddDefaultDeviceMessenger(messenger); - var messenger = new ITemperatureSensorMessenger( - $"{device.Key}-tempSensor", - tempSensor, - $"/device/{device.Key}" - ); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is ITemperatureSensor tempSensor) + { + this.LogVerbose( + "Adding ITemperatureSensor for {deviceKey}", + device.Key + ); - messengerAdded = true; - } + var messenger = new ITemperatureSensorMessenger( + $"{device.Key}-tempSensor", + tempSensor, + $"/device/{device.Key}" + ); - if (device is IHumiditySensor humSensor) - { - this.LogVerbose( - "Adding IHumiditySensor for {deviceKey}", - device.Key - ); + AddDefaultDeviceMessenger(messenger); - var messenger = new IHumiditySensorMessenger( - $"{device.Key}-humiditySensor", - humSensor, - $"/device/{device.Key}" - ); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is IHumiditySensor humSensor) + { + this.LogVerbose( + "Adding IHumiditySensor for {deviceKey}", + device.Key + ); - messengerAdded = true; - } + var messenger = new IHumiditySensorMessenger( + $"{device.Key}-humiditySensor", + humSensor, + $"/device/{device.Key}" + ); - if (device is IEssentialsRoomCombiner roomCombiner) - { - this.LogVerbose( - "Adding IEssentialsRoomCombinerMessenger for {deviceKey}", device.Key - ); + AddDefaultDeviceMessenger(messenger); - var messenger = new IEssentialsRoomCombinerMessenger( - $"{device.Key}-roomCombiner-{Key}", - $"/device/{device.Key}", - roomCombiner - ); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is IEssentialsRoomCombiner roomCombiner) + { + this.LogVerbose( + "Adding IEssentialsRoomCombinerMessenger for {deviceKey}", device.Key + ); - messengerAdded = true; - } + var messenger = new IEssentialsRoomCombinerMessenger( + $"{device.Key}-roomCombiner-{Key}", + $"/device/{device.Key}", + roomCombiner + ); - if (device is IProjectorScreenLiftControl screenLiftControl) - { - this.LogVerbose("Adding IProjectorScreenLiftControlMessenger for {deviceKey}", device.Key - ); + AddDefaultDeviceMessenger(messenger); - var messenger = new IProjectorScreenLiftControlMessenger( - $"{device.Key}-screenLiftControl-{Key}", - $"/device/{device.Key}", - screenLiftControl - ); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is IProjectorScreenLiftControl screenLiftControl) + { + this.LogVerbose("Adding IProjectorScreenLiftControlMessenger for {deviceKey}", device.Key + ); - messengerAdded = true; - } + var messenger = new IProjectorScreenLiftControlMessenger( + $"{device.Key}-screenLiftControl-{Key}", + $"/device/{device.Key}", + screenLiftControl + ); - if (device is IDspPresets dspPresets) - { - this.LogVerbose("Adding IDspPresetsMessenger for {deviceKey}", device.Key - ); + AddDefaultDeviceMessenger(messenger); - var messenger = new IDspPresetsMessenger( - $"{device.Key}-dspPresets-{Key}", - $"/device/{device.Key}", - dspPresets - ); + messengerAdded = true; + } - AddDefaultDeviceMessenger(messenger); + if (device is IDspPresets dspPresets) + { + this.LogVerbose("Adding IDspPresetsMessenger for {deviceKey}", device.Key + ); - messengerAdded = true; - } + var messenger = new IDspPresetsMessenger( + $"{device.Key}-dspPresets-{Key}", + $"/device/{device.Key}", + dspPresets + ); - this.LogVerbose("Trying to cast to generic device for device: {key}", device.Key); + AddDefaultDeviceMessenger(messenger); - if (device is EssentialsDevice) - { - if (!(device is EssentialsDevice genericDevice) || messengerAdded) - { - this.LogVerbose( - "Skipping GenericMessenger for {deviceKey}. Messenger(s) Added: {messengersAdded}.", - device.Key, - messengerAdded - ); - this.LogDebug( - "AllDevices Completed a device. Devices Left: {count}", - --count - ); - continue; - } + messengerAdded = true; + } - this.LogDebug( - "Adding GenericMessenger for {deviceKey}", - this, - genericDevice?.Key - ); + this.LogVerbose("Trying to cast to generic device for device: {key}", device.Key); - AddDefaultDeviceMessenger( - new GenericMessenger( - genericDevice.Key + "-" + Key + "-generic", - genericDevice, - string.Format("/device/{0}", genericDevice.Key) - ) - ); - } - else + if (device is EssentialsDevice) + { + if (!(device is EssentialsDevice genericDevice) || messengerAdded) { this.LogVerbose( - "Not Essentials Device. Skipping GenericMessenger for {deviceKey}", - device.Key + "Skipping GenericMessenger for {deviceKey}. Messenger(s) Added: {messengersAdded}.", + device.Key, + messengerAdded + ); + this.LogDebug( + "AllDevices Completed a device. Devices Left: {count}", + --count ); + continue; } + this.LogDebug( - "AllDevices Completed a device. Devices Left: {count}", - --count + "Adding GenericMessenger for {deviceKey}", + this, + genericDevice?.Key ); - } - catch (Exception ex) + AddDefaultDeviceMessenger( + new GenericMessenger( + genericDevice.Key + "-" + Key + "-generic", + genericDevice, + string.Format("/device/{0}", genericDevice.Key) + ) + ); + } + else { - this.LogException(ex, "Exception setting up default device messengers"); + this.LogVerbose( + "Not Essentials Device. Skipping GenericMessenger for {deviceKey}", + device.Key + ); } + this.LogDebug( + "AllDevices Completed a device. Devices Left: {count}", + --count + ); + } + + catch (Exception ex) + { + this.LogException(ex, "Exception setting up default device messengers"); } } + } + + private void AddWebApiPaths() + { + var apiServer = DeviceManager + .AllDevices.OfType() + .FirstOrDefault(d => d.Key == "essentialsWebApi"); - private void AddWebApiPaths() + if (apiServer == null) { - var apiServer = DeviceManager - .AllDevices.OfType() - .FirstOrDefault(d => d.Key == "essentialsWebApi"); + this.LogWarning("No API Server available"); + return; + } - if (apiServer == null) + // TODO: Add routes for the rest of the MC console commands + var routes = new List + { + new HttpCwsRoute($"device/{Key}/authorize") { - this.LogWarning("No API Server available"); - return; + Name = "MobileControlAuthorize", + RouteHandler = new MobileAuthRequestHandler(this) + }, + new HttpCwsRoute($"device/{Key}/info") + { + Name = "MobileControlInformation", + RouteHandler = new MobileInfoHandler(this) + }, + new HttpCwsRoute($"device/{Key}/actionPaths") + { + Name = "MobileControlActionPaths", + RouteHandler = new ActionPathsHandler(this) } + }; + + apiServer.AddRoute(routes); + } - // TODO: Add routes for the rest of the MC console commands - var routes = new List + private void AddConsoleCommands() + { + CrestronConsole.AddNewConsoleCommand( + AuthorizeSystem, + "mobileauth", + "Authorizes system to talk to Mobile Control server", + ConsoleAccessLevelEnum.AccessOperator + ); + CrestronConsole.AddNewConsoleCommand( + s => ShowInfo(), + "mobileinfo", + "Shows information for current mobile control session", + ConsoleAccessLevelEnum.AccessOperator + ); + CrestronConsole.AddNewConsoleCommand( + s => { - new HttpCwsRoute($"device/{Key}/authorize") - { - Name = "MobileControlAuthorize", - RouteHandler = new MobileAuthRequestHandler(this) - }, - new HttpCwsRoute($"device/{Key}/info") - { - Name = "MobileControlInformation", - RouteHandler = new MobileInfoHandler(this) - }, - new HttpCwsRoute($"device/{Key}/actionPaths") + s = s.Trim(); + if (!string.IsNullOrEmpty(s)) { - Name = "MobileControlActionPaths", - RouteHandler = new ActionPathsHandler(this) + _httpDebugEnabled = (s.Trim() != "0"); } - }; + CrestronConsole.ConsoleCommandResponse( + "HTTP Debug {0}", + _httpDebugEnabled ? "Enabled" : "Disabled" + ); + }, + "mobilehttpdebug", + "1 enables more verbose HTTP response debugging", + ConsoleAccessLevelEnum.AccessOperator + ); + CrestronConsole.AddNewConsoleCommand( + TestHttpRequest, + "mobilehttprequest", + "Tests an HTTP get to URL given", + ConsoleAccessLevelEnum.AccessOperator + ); + + CrestronConsole.AddNewConsoleCommand( + PrintActionDictionaryPaths, + "mobileshowactionpaths", + "Prints the paths in the Action Dictionary", + ConsoleAccessLevelEnum.AccessOperator + ); + CrestronConsole.AddNewConsoleCommand( + s => + { + _disableReconnect = false; - apiServer.AddRoute(routes); - } + CrestronConsole.ConsoleCommandResponse( + $"Connecting to MC API server" + ); - private void AddConsoleCommands() - { - CrestronConsole.AddNewConsoleCommand( - AuthorizeSystem, - "mobileauth", - "Authorizes system to talk to Mobile Control server", - ConsoleAccessLevelEnum.AccessOperator - ); - CrestronConsole.AddNewConsoleCommand( - s => ShowInfo(), - "mobileinfo", - "Shows information for current mobile control session", - ConsoleAccessLevelEnum.AccessOperator - ); - CrestronConsole.AddNewConsoleCommand( - s => - { - s = s.Trim(); - if (!string.IsNullOrEmpty(s)) - { - _httpDebugEnabled = (s.Trim() != "0"); - } - CrestronConsole.ConsoleCommandResponse( - "HTTP Debug {0}", - _httpDebugEnabled ? "Enabled" : "Disabled" - ); - }, - "mobilehttpdebug", - "1 enables more verbose HTTP response debugging", - ConsoleAccessLevelEnum.AccessOperator - ); - CrestronConsole.AddNewConsoleCommand( - TestHttpRequest, - "mobilehttprequest", - "Tests an HTTP get to URL given", - ConsoleAccessLevelEnum.AccessOperator - ); + ConnectWebsocketClient(); + }, + "mobileconnect", + "Forces connect of websocket", + ConsoleAccessLevelEnum.AccessOperator + ); - CrestronConsole.AddNewConsoleCommand( - PrintActionDictionaryPaths, - "mobileshowactionpaths", - "Prints the paths in the Action Dictionary", - ConsoleAccessLevelEnum.AccessOperator - ); - CrestronConsole.AddNewConsoleCommand( - s => - { - _disableReconnect = false; + CrestronConsole.AddNewConsoleCommand( + s => + { + _disableReconnect = true; - CrestronConsole.ConsoleCommandResponse( - $"Connecting to MC API server" - ); + CleanUpWebsocketClient(); - ConnectWebsocketClient(); - }, - "mobileconnect", - "Forces connect of websocket", - ConsoleAccessLevelEnum.AccessOperator - ); + CrestronConsole.ConsoleCommandResponse( + $"Disonnected from MC API server" + ); + }, + "mobiledisco", + "Disconnects websocket", + ConsoleAccessLevelEnum.AccessOperator + ); + + CrestronConsole.AddNewConsoleCommand( + ParseStreamRx, + "mobilesimulateaction", + "Simulates a message from the server", + ConsoleAccessLevelEnum.AccessOperator + ); + + CrestronConsole.AddNewConsoleCommand( + SetWebsocketDebugLevel, + "mobilewsdebug", + "Set Websocket debug level", + ConsoleAccessLevelEnum.AccessProgrammer + ); + } - CrestronConsole.AddNewConsoleCommand( - s => - { - _disableReconnect = true; + public MobileControlConfig Config { get; private set; } - CleanUpWebsocketClient(); + public string Host { get; private set; } - CrestronConsole.ConsoleCommandResponse( - $"Disonnected from MC API server" - ); - }, - "mobiledisco", - "Disconnects websocket", - ConsoleAccessLevelEnum.AccessOperator - ); + public string ClientAppUrl => Config.ClientAppUrl; - CrestronConsole.AddNewConsoleCommand( - ParseStreamRx, - "mobilesimulateaction", - "Simulates a message from the server", - ConsoleAccessLevelEnum.AccessOperator - ); + private void OnRoomCombinationScenarioChanged( + object sender, + EventArgs eventArgs + ) + { + SendMessageObject(new MobileControlMessage { Type = "/system/roomCombinationChanged" }); + } - CrestronConsole.AddNewConsoleCommand( - SetWebsocketDebugLevel, - "mobilewsdebug", - "Set Websocket debug level", - ConsoleAccessLevelEnum.AccessProgrammer - ); + public bool CheckForDeviceMessenger(string key) + { + return _messengers.ContainsKey(key); + } + + public void AddDeviceMessenger(IMobileControlMessenger messenger) + { + if (_messengers.ContainsKey(messenger.Key)) + { + this.LogWarning("Messenger with key {messengerKey) already added", messenger.Key); + return; } - public MobileControlConfig Config { get; private set; } + if (messenger is IDelayedConfiguration simplMessenger) + { + simplMessenger.ConfigurationIsReady += Bridge_ConfigurationIsReady; + } + + if (messenger is MobileControlBridgeBase roomBridge) + { + _roomBridges.Add(roomBridge); + } - public string Host { get; private set; } + this.LogVerbose( + "Adding messenger with key {messengerKey} for path {messengerPath}", + messenger.Key, + messenger.MessagePath + ); - public string ClientAppUrl => Config.ClientAppUrl; + _messengers.Add(messenger.Key, messenger); - private void OnRoomCombinationScenarioChanged( - object sender, - EventArgs eventArgs - ) + if (_initialized) { - SendMessageObject(new MobileControlMessage { Type = "/system/roomCombinationChanged" }); + this.LogDebug("Registering messenger {messengerKey} AFTER initialization", messenger.Key); + messenger.RegisterWithAppServer(this); } + } - public bool CheckForDeviceMessenger(string key) + private void AddDefaultDeviceMessenger(IMobileControlMessenger messenger) + { + if (_defaultMessengers.ContainsKey(messenger.Key)) { - return _messengers.ContainsKey(key); + this.LogWarning( + "Default messenger with key {messengerKey} already added", + messenger.Key + ); + return; } - public void AddDeviceMessenger(IMobileControlMessenger messenger) + if (messenger is IDelayedConfiguration simplMessenger) { - if (_messengers.ContainsKey(messenger.Key)) - { - this.LogWarning("Messenger with key {messengerKey) already added", messenger.Key); - return; - } + simplMessenger.ConfigurationIsReady += Bridge_ConfigurationIsReady; + } + this.LogVerbose( + "Adding default messenger with key {messengerKey} for path {messengerPath}", + messenger.Key, + messenger.MessagePath + ); - if (messenger is IDelayedConfiguration simplMessenger) - { - simplMessenger.ConfigurationIsReady += Bridge_ConfigurationIsReady; - } + _defaultMessengers.Add(messenger.Key, messenger); - if (messenger is MobileControlBridgeBase roomBridge) - { - _roomBridges.Add(roomBridge); - } + if (_initialized) + { + RegisterMessengerWithServer(messenger); + } + } - this.LogVerbose( - "Adding messenger with key {messengerKey} for path {messengerPath}", - messenger.Key, - messenger.MessagePath - ); + private void RegisterMessengerWithServer(IMobileControlMessenger messenger) + { + this.LogVerbose( + "Registering messenger with key {messengerKey} for path {messengerPath}", + messenger.Key, + messenger.MessagePath + ); - _messengers.Add(messenger.Key, messenger); + messenger.RegisterWithAppServer(this); + } - if (_initialized) + public override void Initialize() + { + foreach (var messenger in _messengers) + { + try { - this.LogDebug("Registering messenger {messengerKey} AFTER initialization", messenger.Key); - messenger.RegisterWithAppServer(this); + RegisterMessengerWithServer(messenger.Value); + } + catch (Exception ex) + { + this.LogException(ex, "Exception registering custom messenger {messengerKey}", messenger.Key); + continue; } } - private void AddDefaultDeviceMessenger(IMobileControlMessenger messenger) + foreach (var messenger in _defaultMessengers) { - if (_defaultMessengers.ContainsKey(messenger.Key)) + try { - this.LogWarning( - "Default messenger with key {messengerKey} already added", - messenger.Key - ); - return; + RegisterMessengerWithServer(messenger.Value); } - - if (messenger is IDelayedConfiguration simplMessenger) + catch (Exception ex) { - simplMessenger.ConfigurationIsReady += Bridge_ConfigurationIsReady; + this.LogException(ex, "Exception registering default messenger {messengerKey}", messenger.Key); + continue; } - this.LogVerbose( - "Adding default messenger with key {messengerKey} for path {messengerPath}", - messenger.Key, - messenger.MessagePath - ); + } - _defaultMessengers.Add(messenger.Key, messenger); + var simplMessengers = _messengers.OfType().ToList(); - if (_initialized) - { - RegisterMessengerWithServer(messenger); - } + if (simplMessengers.Count > 0) + { + return; } - private void RegisterMessengerWithServer(IMobileControlMessenger messenger) - { - this.LogVerbose( - "Registering messenger with key {messengerKey} for path {messengerPath}", - messenger.Key, - messenger.MessagePath - ); + _initialized = true; - messenger.RegisterWithAppServer(this); + RegisterSystemToServer(); + } + + #region IMobileControl Members + + public static IMobileControl GetAppServer() + { + try + { + var appServer = + DeviceManager.GetDevices().SingleOrDefault(s => s is IMobileControl) + as MobileControlSystemController; + return appServer; } + catch (Exception e) + { + Debug.LogMessage(e, "Unable to find MobileControlSystemController in Devices"); + return null; + } + } - public override void Initialize() + /// + /// Generates the url and creates the websocket client + /// + private bool CreateWebsocket() + { + if (_wsClient2 != null) { - foreach (var messenger in _messengers) - { - try - { - RegisterMessengerWithServer(messenger.Value); - } - catch (Exception ex) - { - this.LogException(ex, "Exception registering custom messenger {messengerKey}", messenger.Key); - continue; - } - } + _wsClient2.Close(); + _wsClient2 = null; + } - foreach (var messenger in _defaultMessengers) - { - try - { - RegisterMessengerWithServer(messenger.Value); - } - catch (Exception ex) - { - this.LogException(ex, "Exception registering default messenger {messengerKey}", messenger.Key); - continue; - } - } + if (string.IsNullOrEmpty(SystemUuid)) + { + this.LogError( + "System UUID not defined. Unable to connect to Mobile Control" + ); + return false; + } - var simplMessengers = _messengers.OfType().ToList(); + var wsHost = Host.Replace("http", "ws"); + var url = string.Format("{0}/system/join/{1}", wsHost, SystemUuid); - if (simplMessengers.Count > 0) + _wsClient2 = new WebSocket(url) + { + Log = { - return; + Output = (data, s) => + this.LogDebug( + "Message from websocket: {message}", + data + ) } + }; - _initialized = true; + _wsClient2.SslConfiguration.EnabledSslProtocols = + System.Security.Authentication.SslProtocols.Tls11 + | System.Security.Authentication.SslProtocols.Tls12; - RegisterSystemToServer(); - } + _wsClient2.OnMessage += HandleMessage; + _wsClient2.OnOpen += HandleOpen; + _wsClient2.OnError += HandleError; + _wsClient2.OnClose += HandleClose; - #region IMobileControl Members + return true; + } - public static IMobileControl GetAppServer() + public void LinkSystemMonitorToAppServer() + { + if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Appliance) { - try - { - var appServer = - DeviceManager.GetDevices().SingleOrDefault(s => s is IMobileControl) - as MobileControlSystemController; - return appServer; - } - catch (Exception e) - { - Debug.LogMessage(e, "Unable to find MobileControlSystemController in Devices"); - return null; - } + this.LogWarning( + "System Monitor does not exist for this platform. Skipping..." + ); + return; } - /// - /// Generates the url and creates the websocket client - /// - private bool CreateWebsocket() + if (!(DeviceManager.GetDeviceForKey("systemMonitor") is SystemMonitorController sysMon)) { - if (_wsClient2 != null) - { - _wsClient2.Close(); - _wsClient2 = null; - } + return; + } - if (string.IsNullOrEmpty(SystemUuid)) - { - this.LogError( - "System UUID not defined. Unable to connect to Mobile Control" - ); - return false; - } + var key = sysMon.Key + "-" + Key; + var messenger = new SystemMonitorMessenger(key, sysMon, "/device/systemMonitor"); - var wsHost = Host.Replace("http", "ws"); - var url = string.Format("{0}/system/join/{1}", wsHost, SystemUuid); + AddDeviceMessenger(messenger); + } - _wsClient2 = new WebSocket(url) - { - Log = - { - Output = (data, s) => - this.LogDebug( - "Message from websocket: {message}", - data - ) - } - }; + #endregion - _wsClient2.SslConfiguration.EnabledSslProtocols = - System.Security.Authentication.SslProtocols.Tls11 - | System.Security.Authentication.SslProtocols.Tls12; + private void SetWebsocketDebugLevel(string cmdparameters) + { + if (CrestronEnvironment.ProgramCompatibility == eCrestronSeries.Series4) + { + this.LogInformation( + "Setting websocket log level not currently allowed on 4 series." + ); + return; // Web socket log level not currently allowed in series4 + } - _wsClient2.OnMessage += HandleMessage; - _wsClient2.OnOpen += HandleOpen; - _wsClient2.OnError += HandleError; - _wsClient2.OnClose += HandleClose; + if (string.IsNullOrEmpty(cmdparameters)) + { + this.LogInformation("Current Websocket debug level: {webSocketDebugLevel}", _wsLogLevel); + return; + } - return true; + if (cmdparameters.ToLower().Contains("help") || cmdparameters.ToLower().Contains("?")) + { + CrestronConsole.ConsoleCommandResponse( + $"valid options are:\r\n{LogLevel.Trace}\r\n{LogLevel.Debug}\r\n{LogLevel.Info}\r\n{LogLevel.Warn}\r\n{LogLevel.Error}\r\n{LogLevel.Fatal}\r\n" + ); } - public void LinkSystemMonitorToAppServer() + try { - if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Appliance) - { - this.LogWarning( - "System Monitor does not exist for this platform. Skipping..." - ); - return; - } + var debugLevel = (LogLevel)Enum.Parse(typeof(LogLevel), cmdparameters, true); + + _wsLogLevel = debugLevel; - if (!(DeviceManager.GetDeviceForKey("systemMonitor") is SystemMonitorController sysMon)) + if (_wsClient2 != null) { - return; + _wsClient2.Log.Level = _wsLogLevel; } - var key = sysMon.Key + "-" + Key; - var messenger = new SystemMonitorMessenger(key, sysMon, "/device/systemMonitor"); - - AddDeviceMessenger(messenger); + CrestronConsole.ConsoleCommandResponse($"Websocket log level set to {debugLevel}"); } + catch + { + CrestronConsole.ConsoleCommandResponse( + $"{cmdparameters} is not a valid debug level. Valid options are:\r\n{LogLevel.Trace}\r\n{LogLevel.Debug}\r\n{LogLevel.Info}\r\n{LogLevel.Warn}\r\n{LogLevel.Error}\r\n{LogLevel.Fatal}\r\n" + ); - #endregion + } + } - private void SetWebsocketDebugLevel(string cmdparameters) + /// + /// Sends message to server to indicate the system is shutting down + /// + /// + private void CrestronEnvironment_ProgramStatusEventHandler( + eProgramStatusEventType programEventType + ) + { + if ( + programEventType != eProgramStatusEventType.Stopping + || _wsClient2 == null + || !_wsClient2.IsAlive + ) { - if (CrestronEnvironment.ProgramCompatibility == eCrestronSeries.Series4) - { - this.LogInformation( - "Setting websocket log level not currently allowed on 4 series." - ); - return; // Web socket log level not currently allowed in series4 - } + return; + } - if (string.IsNullOrEmpty(cmdparameters)) - { - this.LogInformation("Current Websocket debug level: {webSocketDebugLevel}", _wsLogLevel); - return; - } + _disableReconnect = true; - if (cmdparameters.ToLower().Contains("help") || cmdparameters.ToLower().Contains("?")) - { - CrestronConsole.ConsoleCommandResponse( - $"valid options are:\r\n{LogLevel.Trace}\r\n{LogLevel.Debug}\r\n{LogLevel.Info}\r\n{LogLevel.Warn}\r\n{LogLevel.Error}\r\n{LogLevel.Fatal}\r\n" - ); - } + StopServerReconnectTimer(); + CleanUpWebsocketClient(); + } - try - { - var debugLevel = (LogLevel)Enum.Parse(typeof(LogLevel), cmdparameters, true); + public void PrintActionDictionaryPaths(object o) + { + CrestronConsole.ConsoleCommandResponse("ActionDictionary Contents:\r\n"); - _wsLogLevel = debugLevel; + foreach (var (messengerKey, actionPath) in GetActionDictionaryPaths()) + { + CrestronConsole.ConsoleCommandResponse($"<{messengerKey}> {actionPath}\r\n"); + } + } - if (_wsClient2 != null) - { - _wsClient2.Log.Level = _wsLogLevel; - } + public List<(string, string)> GetActionDictionaryPaths() + { + var paths = new List<(string, string)>(); - CrestronConsole.ConsoleCommandResponse($"Websocket log level set to {debugLevel}"); - } - catch + foreach (var item in _actionDictionary) + { + var messengers = item.Value.Select(a => a.Messenger).Cast(); + foreach (var messenger in messengers) { - CrestronConsole.ConsoleCommandResponse( - $"{cmdparameters} is not a valid debug level. Valid options are:\r\n{LogLevel.Trace}\r\n{LogLevel.Debug}\r\n{LogLevel.Info}\r\n{LogLevel.Warn}\r\n{LogLevel.Error}\r\n{LogLevel.Fatal}\r\n" - ); - + foreach (var actionPath in messenger.GetActionPaths()) + { + paths.Add((messenger.Key, $"{item.Key}{actionPath}")); + } } } - /// - /// Sends message to server to indicate the system is shutting down - /// - /// - private void CrestronEnvironment_ProgramStatusEventHandler( - eProgramStatusEventType programEventType + return paths; + } + + /// + /// Adds an action to the dictionary + /// + /// The path of the API command + /// The action to be triggered by the commmand + public void AddAction(T messenger, Action action) + where T : IMobileControlMessenger + { + if ( + _actionDictionary.TryGetValue( + messenger.MessagePath, + out List actionList + ) ) { if ( - programEventType != eProgramStatusEventType.Stopping - || _wsClient2 == null - || !_wsClient2.IsAlive + actionList.Any(a => + a.Messenger.GetType() == messenger.GetType() + && a.Messenger.DeviceKey == messenger.DeviceKey + ) ) { + this.LogWarning("Messenger of type {messengerType} already exists. Skipping actions for {messengerKey}", messenger.GetType().Name, messenger.Key); return; } - _disableReconnect = true; - - StopServerReconnectTimer(); - CleanUpWebsocketClient(); + actionList.Add(new MobileControlAction(messenger, action)); + return; } - public void PrintActionDictionaryPaths(object o) + actionList = new List { - CrestronConsole.ConsoleCommandResponse("ActionDictionary Contents:\r\n"); + new MobileControlAction(messenger, action) + }; - foreach (var (messengerKey, actionPath) in GetActionDictionaryPaths()) - { - CrestronConsole.ConsoleCommandResponse($"<{messengerKey}> {actionPath}\r\n"); - } - } + _actionDictionary.Add(messenger.MessagePath, actionList); + } - public List<(string, string)> GetActionDictionaryPaths() + /// + /// Removes an action from the dictionary + /// + /// + public void RemoveAction(string key) + { + if (_actionDictionary.ContainsKey(key)) { - var paths = new List<(string, string)>(); - - foreach (var item in _actionDictionary) - { - var messengers = item.Value.Select(a => a.Messenger).Cast(); - foreach (var messenger in messengers) - { - foreach (var actionPath in messenger.GetActionPaths()) - { - paths.Add((messenger.Key, $"{item.Key}{actionPath}")); - } - } - } - - return paths; + _actionDictionary.Remove(key); } + } - /// - /// Adds an action to the dictionary - /// - /// The path of the API command - /// The action to be triggered by the commmand - public void AddAction(T messenger, Action action) - where T : IMobileControlMessenger - { - if ( - _actionDictionary.TryGetValue( - messenger.MessagePath, - out List actionList - ) - ) - { - if ( - actionList.Any(a => - a.Messenger.GetType() == messenger.GetType() - && a.Messenger.DeviceKey == messenger.DeviceKey - ) - ) - { - this.LogWarning("Messenger of type {messengerType} already exists. Skipping actions for {messengerKey}", messenger.GetType().Name, messenger.Key); - return; - } + public MobileControlBridgeBase GetRoomBridge(string key) + { + return _roomBridges.FirstOrDefault((r) => r.RoomKey.Equals(key)); + } - actionList.Add(new MobileControlAction(messenger, action)); - return; - } + public IMobileControlRoomMessenger GetRoomMessenger(string key) + { + return _roomBridges.FirstOrDefault((r) => r.RoomKey.Equals(key)); + } - actionList = new List - { - new MobileControlAction(messenger, action) - }; + /// + /// + /// + /// + /// + private void Bridge_ConfigurationIsReady(object sender, EventArgs e) + { + this.LogDebug("Bridge ready. Registering"); - _actionDictionary.Add(messenger.MessagePath, actionList); - } + // send the configuration object to the server - /// - /// Removes an action from the dictionary - /// - /// - public void RemoveAction(string key) + if (_wsClient2 == null) { - if (_actionDictionary.ContainsKey(key)) - { - _actionDictionary.Remove(key); - } + RegisterSystemToServer(); } - - public MobileControlBridgeBase GetRoomBridge(string key) + else if (!_wsClient2.IsAlive) { - return _roomBridges.FirstOrDefault((r) => r.RoomKey.Equals(key)); + ConnectWebsocketClient(); } - - public IMobileControlRoomMessenger GetRoomMessenger(string key) + else { - return _roomBridges.FirstOrDefault((r) => r.RoomKey.Equals(key)); + SendInitialMessage(); } + } - /// - /// - /// - /// - /// - private void Bridge_ConfigurationIsReady(object sender, EventArgs e) - { - this.LogDebug("Bridge ready. Registering"); + /// + /// + /// + /// + private void ReconnectToServerTimerCallback(object o) + { + this.LogDebug("Attempting to reconnect to server..."); - // send the configuration object to the server + ConnectWebsocketClient(); + } - if (_wsClient2 == null) - { - RegisterSystemToServer(); - } - else if (!_wsClient2.IsAlive) - { - ConnectWebsocketClient(); - } - else - { - SendInitialMessage(); - } + /// + /// Verifies system connection with servers + /// + private void AuthorizeSystem(string code) + { + if ( + string.IsNullOrEmpty(SystemUuid) + || SystemUuid.Equals("missing url", StringComparison.OrdinalIgnoreCase) + ) + { + CrestronConsole.ConsoleCommandResponse( + "System does not have a UUID. Please ensure proper configuration is loaded and restart." + ); + return; } - - /// - /// - /// - /// - private void ReconnectToServerTimerCallback(object o) + if (string.IsNullOrEmpty(code)) { - this.LogDebug("Attempting to reconnect to server..."); - - ConnectWebsocketClient(); + CrestronConsole.ConsoleCommandResponse( + "Please enter a grant code to authorize a system" + ); + return; + } + if (string.IsNullOrEmpty(Config.ServerUrl)) + { + CrestronConsole.ConsoleCommandResponse( + "Mobile control API address is not set. Check portal configuration" + ); + return; } - /// - /// Verifies system connection with servers - /// - private void AuthorizeSystem(string code) + var authTask = ApiService.SendAuthorizationRequest(Host, code, SystemUuid); + + authTask.ContinueWith(t => { - if ( - string.IsNullOrEmpty(SystemUuid) - || SystemUuid.Equals("missing url", StringComparison.OrdinalIgnoreCase) - ) - { - CrestronConsole.ConsoleCommandResponse( - "System does not have a UUID. Please ensure proper configuration is loaded and restart." - ); - return; - } - if (string.IsNullOrEmpty(code)) - { - CrestronConsole.ConsoleCommandResponse( - "Please enter a grant code to authorize a system" - ); - return; - } - if (string.IsNullOrEmpty(Config.ServerUrl)) + var response = t.Result; + + if (response.Authorized) { - CrestronConsole.ConsoleCommandResponse( - "Mobile control API address is not set. Check portal configuration" - ); + this.LogDebug("System authorized, sending config."); + RegisterSystemToServer(); return; } - var authTask = ApiService.SendAuthorizationRequest(Host, code, SystemUuid); + this.LogInformation(response.Reason); + }); + } - authTask.ContinueWith(t => - { - var response = t.Result; + /// + /// Dumps info in response to console command. + /// + private void ShowInfo() + { + var url = Config != null ? Host : "No config"; + string name; + string code; + if (_roomBridges != null && _roomBridges.Count > 0) + { + name = _roomBridges[0].RoomName; + code = _roomBridges[0].UserCode; + } + else + { + name = "No config"; + code = "Not available"; + } + var conn = _wsClient2 == null ? "No client" : (_wsClient2.IsAlive ? "Yes" : "No"); - if (response.Authorized) - { - this.LogDebug("System authorized, sending config."); - RegisterSystemToServer(); - return; - } + var secSinceLastAck = DateTime.Now - _lastAckMessage; - this.LogInformation(response.Reason); - }); + if (Config.EnableApiServer) + { + CrestronConsole.ConsoleCommandResponse( + "Mobile Control Edge Server API Information:\r\n\r\n" + + "\tServer address: {0}\r\n" + + "\tSystem Name: {1}\r\n" + + "\tSystem URL: {2}\r\n" + + "\tSystem UUID: {3}\r\n" + + "\tSystem User code: {4}\r\n" + + "\tConnected?: {5}\r\n" + + "\tSeconds Since Last Ack: {6}\r\n", + url, + name, + ConfigReader.ConfigObject.SystemUrl, + SystemUuid, + code, + conn, + secSinceLastAck.Seconds + ); } - - /// - /// Dumps info in response to console command. - /// - private void ShowInfo() + else { - var url = Config != null ? Host : "No config"; - string name; - string code; - if (_roomBridges != null && _roomBridges.Count > 0) - { - name = _roomBridges[0].RoomName; - code = _roomBridges[0].UserCode; - } - else - { - name = "No config"; - code = "Not available"; - } - var conn = _wsClient2 == null ? "No client" : (_wsClient2.IsAlive ? "Yes" : "No"); + CrestronConsole.ConsoleCommandResponse( + "\r\nMobile Control Edge Server API Information:\r\n" + + " Not Enabled in Config.\r\n" + ); + } - var secSinceLastAck = DateTime.Now - _lastAckMessage; + if ( + Config.DirectServer != null + && Config.DirectServer.EnableDirectServer + && _directServer != null + ) + { + CrestronConsole.ConsoleCommandResponse( + "\r\nMobile Control Direct Server Information:\r\n" + + " User App URL: {0}\r\n" + + " Server port: {1}\r\n", + string.Format("{0}[insert_client_token]", _directServer.UserAppUrlPrefix), + _directServer.Port + ); - if (Config.EnableApiServer) - { - CrestronConsole.ConsoleCommandResponse( - @"Mobile Control Edge Server API Information: - - Server address: {0} - System Name: {1} - System URL: {2} - System UUID: {3} - System User code: {4} - Connected?: {5} - Seconds Since Last Ack: {6}", - url, - name, - ConfigReader.ConfigObject.SystemUrl, - SystemUuid, - code, - conn, - secSinceLastAck.Seconds - ); - } - else - { - CrestronConsole.ConsoleCommandResponse( - @" -Mobile Control Edge Server API Information: - Not Enabled in Config. -" - ); - } + CrestronConsole.ConsoleCommandResponse( + "\r\n UI Client Info:\r\n" + + " Tokens Defined: {0}\r\n" + + " Clients Connected: {1}\r\n", + _directServer.UiClients.Count, + _directServer.ConnectedUiClientsCount + ); - if ( - Config.DirectServer != null - && Config.DirectServer.EnableDirectServer - && _directServer != null - ) + var clientNo = 1; + foreach (var clientContext in _directServer.UiClients) { - CrestronConsole.ConsoleCommandResponse( - @" -Mobile Control Direct Server Information: - User App URL: {0} - Server port: {1} -", - string.Format("{0}[insert_client_token]", _directServer.UserAppUrlPrefix), - _directServer.Port - ); - - CrestronConsole.ConsoleCommandResponse( - @" - UI Client Info: - Tokens Defined: {0} - Clients Connected: {1} -", - _directServer.UiClients.Count, - _directServer.ConnectedUiClientsCount - ); + var isAlive = false; + var duration = "Not Connected"; - var clientNo = 1; - foreach (var clientContext in _directServer.UiClients) + if (clientContext.Value.Client != null) { - var isAlive = false; - var duration = "Not Connected"; - - if (clientContext.Value.Client != null) - { - isAlive = clientContext.Value.Client.Context.WebSocket.IsAlive; - duration = clientContext.Value.Client.ConnectedDuration.ToString(); - } - - CrestronConsole.ConsoleCommandResponse( - @" -Client {0}: -Room Key: {1} -Touchpanel Key: {6} -Token: {2} -Client URL: {3} -Connected: {4} -Duration: {5} -", - clientNo, - clientContext.Value.Token.RoomKey, - clientContext.Key, - string.Format("{0}{1}", _directServer.UserAppUrlPrefix, clientContext.Key), - isAlive, - duration, - clientContext.Value.Token.TouchpanelKey - ); - clientNo++; + isAlive = clientContext.Value.Client.Context.WebSocket.IsAlive; + duration = clientContext.Value.Client.ConnectedDuration.ToString(); } - } - else - { + CrestronConsole.ConsoleCommandResponse( - @" -Mobile Control Direct Server Infromation: - Not Enabled in Config." + "\r\nClient {0}:\r\n" + + "Room Key: {1}\r\n" + + "Touchpanel Key: {6}\r\n" + + "Token: {2}\r\n" + + "Client URL: {3}\r\n" + + "Connected: {4}\r\n" + + "Duration: {5}\r\n", + clientNo, + clientContext.Value.Token.RoomKey, + clientContext.Key, + string.Format("{0}{1}", _directServer.UserAppUrlPrefix, clientContext.Key), + isAlive, + duration, + clientContext.Value.Token.TouchpanelKey ); + clientNo++; } } - - /// - /// Registers the room with the server - /// - public void RegisterSystemToServer() + else { - - if (!Config.EnableApiServer) - { - this.LogInformation( - "ApiServer disabled via config. Cancelling attempt to register to server." - ); - return; - } - - var result = CreateWebsocket(); - - if (!result) - { - this.LogFatal("Unable to create websocket."); - return; - } - - ConnectWebsocketClient(); + CrestronConsole.ConsoleCommandResponse( + "\r\nMobile Control Direct Server Information:\r\n" + + " Not Enabled in Config.\r\n" + ); } + } - /// - /// Connects the Websocket Client - /// - private void ConnectWebsocketClient() - { - try - { - _wsCriticalSection.Enter(); - - // set to 99999 to let things work on 4-Series - if ( - (CrestronEnvironment.ProgramCompatibility & eCrestronSeries.Series4) - == eCrestronSeries.Series4 - ) - { - _wsClient2.Log.Level = (LogLevel)99999; - } - else if ( - (CrestronEnvironment.ProgramCompatibility & eCrestronSeries.Series3) - == eCrestronSeries.Series3 - ) - { - _wsClient2.Log.Level = _wsLogLevel; - } - - //This version of the websocket client is TLS1.2 ONLY + /// + /// Registers the room with the server + /// + public void RegisterSystemToServer() + { - //Fires OnMessage event when PING is received. - _wsClient2.EmitOnPing = true; + if (!Config.EnableApiServer) + { + this.LogInformation( + "ApiServer disabled via config. Cancelling attempt to register to server." + ); + return; + } - this.LogDebug( - "Connecting mobile control client to {mobileControlUrl}", - _wsClient2.Url - ); + var result = CreateWebsocket(); - TryConnect(); - } - finally - { - _wsCriticalSection.Leave(); - } + if (!result) + { + this.LogFatal("Unable to create websocket."); + return; } - /// - /// Attempts to connect the websocket - /// - private void TryConnect() + ConnectWebsocketClient(); + } + + /// + /// Connects the Websocket Client + /// + private void ConnectWebsocketClient() + { + try { - try - { - IsAuthorized = false; - _wsClient2.Connect(); - } - catch (InvalidOperationException) - { - this.LogError( - "Maximum retries exceeded. Restarting websocket" - ); - HandleConnectFailure(); - } - catch (IOException ex) + _wsCriticalSection.Enter(); + + // set to 99999 to let things work on 4-Series + if ( + (CrestronEnvironment.ProgramCompatibility & eCrestronSeries.Series4) + == eCrestronSeries.Series4 + ) { - this.LogException(ex, "IO Exception on connect"); - HandleConnectFailure(); + _wsClient2.Log.Level = (LogLevel)99999; } - catch (Exception ex) + else if ( + (CrestronEnvironment.ProgramCompatibility & eCrestronSeries.Series3) + == eCrestronSeries.Series3 + ) { - this.LogException( - ex, - "Error on Websocket Connect" - ); - HandleConnectFailure(); + _wsClient2.Log.Level = _wsLogLevel; } - } - /// - /// Gracefully handles conect failures by reconstructing the ws client and starting the reconnect timer - /// - private void HandleConnectFailure() - { - _wsClient2 = null; - - var wsHost = Host.Replace("http", "ws"); - var url = string.Format("{0}/system/join/{1}", wsHost, SystemUuid); - _wsClient2 = new WebSocket(url) - { - Log = - { - Output = (data, s) => - this.LogDebug( - "Message from websocket: {message}", - data - ) - } - }; + //This version of the websocket client is TLS1.2 ONLY - _wsClient2.OnMessage -= HandleMessage; - _wsClient2.OnOpen -= HandleOpen; - _wsClient2.OnError -= HandleError; - _wsClient2.OnClose -= HandleClose; + //Fires OnMessage event when PING is received. + _wsClient2.EmitOnPing = true; - _wsClient2.OnMessage += HandleMessage; - _wsClient2.OnOpen += HandleOpen; - _wsClient2.OnError += HandleError; - _wsClient2.OnClose += HandleClose; + this.LogDebug( + "Connecting mobile control client to {mobileControlUrl}", + _wsClient2.Url + ); - StartServerReconnectTimer(); + TryConnect(); + } + finally + { + _wsCriticalSection.Leave(); } + } - /// - /// - /// - /// - /// - private void HandleOpen(object sender, EventArgs e) + /// + /// Attempts to connect the websocket + /// + private void TryConnect() + { + try { - StopServerReconnectTimer(); - StartPingTimer(); - this.LogInformation("Mobile Control API connected"); - SendMessageObject(new MobileControlMessage { Type = "hello" }); + IsAuthorized = false; + _wsClient2.Connect(); + } + catch (InvalidOperationException) + { + this.LogError( + "Maximum retries exceeded. Restarting websocket" + ); + HandleConnectFailure(); + } + catch (IOException ex) + { + this.LogException(ex, "IO Exception on connect"); + HandleConnectFailure(); } + catch (Exception ex) + { + this.LogException( + ex, + "Error on Websocket Connect" + ); + HandleConnectFailure(); + } + } + + /// + /// Gracefully handles conect failures by reconstructing the ws client and starting the reconnect timer + /// + private void HandleConnectFailure() + { + _wsClient2 = null; - /// - /// - /// - /// - /// - private void HandleMessage(object sender, MessageEventArgs e) + var wsHost = Host.Replace("http", "ws"); + var url = string.Format("{0}/system/join/{1}", wsHost, SystemUuid); + _wsClient2 = new WebSocket(url) { - if (e.IsPing) + Log = { - _lastAckMessage = DateTime.Now; - IsAuthorized = true; - ResetPingTimer(); - return; + Output = (data, s) => + this.LogDebug( + "Message from websocket: {message}", + data + ) } + }; - if (e.IsText && e.Data.Length > 0) - { - _receiveQueue.Enqueue(new ProcessStringMessage(e.Data, ParseStreamRx)); - } - } + _wsClient2.OnMessage -= HandleMessage; + _wsClient2.OnOpen -= HandleOpen; + _wsClient2.OnError -= HandleError; + _wsClient2.OnClose -= HandleClose; + + _wsClient2.OnMessage += HandleMessage; + _wsClient2.OnOpen += HandleOpen; + _wsClient2.OnError += HandleError; + _wsClient2.OnClose += HandleClose; + + StartServerReconnectTimer(); + } + + /// + /// + /// + /// + /// + private void HandleOpen(object sender, EventArgs e) + { + StopServerReconnectTimer(); + StartPingTimer(); + this.LogInformation("Mobile Control API connected"); + SendMessageObject(new MobileControlMessage { Type = "hello" }); + } - /// - /// - /// - /// - /// - private void HandleError(object sender, ErrorEventArgs e) + /// + /// + /// + /// + /// + private void HandleMessage(object sender, MessageEventArgs e) + { + if (e.IsPing) { - this.LogError("Websocket error {0}", e.Message); - - IsAuthorized = false; - StartServerReconnectTimer(); + _lastAckMessage = DateTime.Now; + IsAuthorized = true; + ResetPingTimer(); + return; } - /// - /// - /// - /// - /// - private void HandleClose(object sender, CloseEventArgs e) + if (e.IsText && e.Data.Length > 0) { - this.LogDebug( - "Websocket close {code} {reason}, clean={wasClean}", - e.Code, - e.Reason, - e.WasClean - ); - IsAuthorized = false; - StopPingTimer(); + _receiveQueue.Enqueue(new ProcessStringMessage(e.Data, ParseStreamRx)); + } + } - // Start the reconnect timer only if disableReconnect is false and the code isn't 4200. 4200 indicates system is not authorized; - if (_disableReconnect || e.Code == 4200) - { - return; - } + /// + /// + /// + /// + /// + private void HandleError(object sender, ErrorEventArgs e) + { + this.LogError("Websocket error {0}", e.Message); - StartServerReconnectTimer(); - } + IsAuthorized = false; + StartServerReconnectTimer(); + } - /// - /// After a "hello" from the server, sends config and stuff - /// - private void SendInitialMessage() + /// + /// + /// + /// + /// + private void HandleClose(object sender, CloseEventArgs e) + { + this.LogDebug( + "Websocket close {code} {reason}, clean={wasClean}", + e.Code, + e.Reason, + e.WasClean + ); + IsAuthorized = false; + StopPingTimer(); + + // Start the reconnect timer only if disableReconnect is false and the code isn't 4200. 4200 indicates system is not authorized; + if (_disableReconnect || e.Code == 4200) { - this.LogInformation("Sending initial join message"); + return; + } - var touchPanels = DeviceManager - .AllDevices.OfType() - .Where(tp => !tp.UseDirectServer) - .Select( - (tp) => - { - return new { touchPanelKey = tp.Key, roomKey = tp.DefaultRoomKey }; - } - ); + StartServerReconnectTimer(); + } - var msg = new MobileControlMessage - { - Type = "join", - Content = JToken.FromObject( - new { config = GetConfigWithPluginVersion(), touchPanels } - ) - }; + /// + /// After a "hello" from the server, sends config and stuff + /// + private void SendInitialMessage() + { + this.LogInformation("Sending initial join message"); - SendMessageObject(msg); - } + var touchPanels = DeviceManager + .AllDevices.OfType() + .Where(tp => !tp.UseDirectServer) + .Select( + (tp) => + { + return new { touchPanelKey = tp.Key, roomKey = tp.DefaultRoomKey }; + } + ); - public MobileControlEssentialsConfig GetConfigWithPluginVersion() + var msg = new MobileControlMessage { - // Populate the application name and version number - var confObject = new MobileControlEssentialsConfig(ConfigReader.ConfigObject); + Type = "join", + Content = JToken.FromObject( + new { config = GetConfigWithPluginVersion(), touchPanels } + ) + }; - confObject.Info.RuntimeInfo.AppName = Assembly.GetExecutingAssembly().GetName().Name; + SendMessageObject(msg); + } - var essentialsVersion = Global.AssemblyVersion; - confObject.Info.RuntimeInfo.AssemblyVersion = essentialsVersion; + public MobileControlEssentialsConfig GetConfigWithPluginVersion() + { + // Populate the application name and version number + var confObject = new MobileControlEssentialsConfig(ConfigReader.ConfigObject); + confObject.Info.RuntimeInfo.AppName = Assembly.GetExecutingAssembly().GetName().Name; - // // Set for local testing - // confObject.RuntimeInfo.PluginVersion = "4.0.0-localBuild"; + var essentialsVersion = Global.AssemblyVersion; + confObject.Info.RuntimeInfo.AssemblyVersion = essentialsVersion; - // Populate the plugin version - var pluginVersion = Assembly - .GetExecutingAssembly() - .GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false); + // // Set for local testing + // confObject.RuntimeInfo.PluginVersion = "4.0.0-localBuild"; - if (pluginVersion[0] is AssemblyInformationalVersionAttribute fullVersionAtt) - { - var pluginInformationalVersion = fullVersionAtt.InformationalVersion; + // Populate the plugin version + var pluginVersion = Assembly + .GetExecutingAssembly() + .GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false); - confObject.RuntimeInfo.PluginVersion = pluginInformationalVersion; - confObject.RuntimeInfo.EssentialsVersion = Global.AssemblyVersion; - confObject.RuntimeInfo.PepperDashCoreVersion = PluginLoader.PepperDashCoreAssembly.Version; - confObject.RuntimeInfo.EssentialsPlugins = PluginLoader.EssentialsPluginAssemblies; - } - return confObject; - } - public void SetClientUrl(string path, string roomKey = null) + if (pluginVersion[0] is AssemblyInformationalVersionAttribute fullVersionAtt) { - var message = new MobileControlMessage - { - Type = string.IsNullOrEmpty(roomKey) ? $"/event/system/setUrl" : $"/event/room/{roomKey}/setUrl", - Content = JToken.FromObject(new MobileControlSimpleContent { Value = path }) - }; + var pluginInformationalVersion = fullVersionAtt.InformationalVersion; - SendMessageObject(message); + confObject.RuntimeInfo.PluginVersion = pluginInformationalVersion; + confObject.RuntimeInfo.EssentialsVersion = Global.AssemblyVersion; + confObject.RuntimeInfo.PepperDashCoreVersion = PluginLoader.PepperDashCoreAssembly.Version; + confObject.RuntimeInfo.EssentialsPlugins = PluginLoader.EssentialsPluginAssemblies; } + return confObject; + } - /// - /// Sends any object type to server - /// - /// - public void SendMessageObject(IMobileControlMessage o) + public void SetClientUrl(string path, string roomKey = null) + { + var message = new MobileControlMessage { + Type = string.IsNullOrEmpty(roomKey) ? $"/event/system/setUrl" : $"/event/room/{roomKey}/setUrl", + Content = JToken.FromObject(new MobileControlSimpleContent { Value = path }) + }; - if (Config.EnableApiServer) - { + SendMessageObject(message); + } - _transmitToServerQueue.Enqueue(new TransmitMessage(o, _wsClient2)); + /// + /// Sends any object type to server + /// + /// + public void SendMessageObject(IMobileControlMessage o) + { - } + if (Config.EnableApiServer) + { - if ( - Config.DirectServer != null - && Config.DirectServer.EnableDirectServer - && _directServer != null - ) - { - _transmitToClientsQueue.Enqueue(new MessageToClients(o, _directServer)); - } + _transmitToServerQueue.Enqueue(new TransmitMessage(o, _wsClient2)); } - - public void SendMessageObjectToDirectClient(object o) + if ( + Config.DirectServer != null + && Config.DirectServer.EnableDirectServer + && _directServer != null + ) { - if ( - Config.DirectServer != null - && Config.DirectServer.EnableDirectServer - && _directServer != null - ) - { - _transmitToClientsQueue.Enqueue(new MessageToClients(o, _directServer)); - } + _transmitToClientsQueue.Enqueue(new MessageToClients(o, _directServer)); } + } - /// - /// Disconnects the Websocket Client and stops the heartbeat timer - /// - private void CleanUpWebsocketClient() - { - if (_wsClient2 == null) - { - return; - } - - this.LogDebug("Disconnecting websocket"); - _wsClient2.Close(); + public void SendMessageObjectToDirectClient(object o) + { + if ( + Config.DirectServer != null + && Config.DirectServer.EnableDirectServer + && _directServer != null + ) + { + _transmitToClientsQueue.Enqueue(new MessageToClients(o, _directServer)); } + } + - private void ResetPingTimer() + /// + /// Disconnects the Websocket Client and stops the heartbeat timer + /// + private void CleanUpWebsocketClient() + { + if (_wsClient2 == null) { - // This tells us we're online with the API and getting pings - _pingTimer.Reset(PingInterval); + return; } - private void StartPingTimer() + this.LogDebug("Disconnecting websocket"); + + _wsClient2.Close(); + } + + private void ResetPingTimer() + { + // This tells us we're online with the API and getting pings + _pingTimer.Reset(PingInterval); + } + + private void StartPingTimer() + { + StopPingTimer(); + _pingTimer = new CTimer(PingTimerCallback, null, PingInterval); + } + + private void StopPingTimer() + { + if (_pingTimer == null) { - StopPingTimer(); - _pingTimer = new CTimer(PingTimerCallback, null, PingInterval); + return; } - private void StopPingTimer() - { - if (_pingTimer == null) - { - return; - } + _pingTimer.Stop(); + _pingTimer.Dispose(); + _pingTimer = null; + } - _pingTimer.Stop(); - _pingTimer.Dispose(); - _pingTimer = null; - } + private void PingTimerCallback(object o) + { + this.LogDebug( - private void PingTimerCallback(object o) - { - this.LogDebug( + "Ping timer expired. Closing websocket" + ); - "Ping timer expired. Closing websocket" + try + { + _wsClient2.Close(); + } + catch (Exception ex) + { + this.LogException(ex, + "Exception closing websocket" ); - try - { - _wsClient2.Close(); - } - catch (Exception ex) - { - this.LogException(ex, - "Exception closing websocket" - ); - - HandleConnectFailure(); - } + HandleConnectFailure(); } + } + + /// + /// + /// + private void StartServerReconnectTimer() + { + StopServerReconnectTimer(); + _serverReconnectTimer = new CTimer( + ReconnectToServerTimerCallback, + ServerReconnectInterval + ); + this.LogDebug("Reconnect Timer Started."); + } - /// - /// - /// - private void StartServerReconnectTimer() + /// + /// Does what it says + /// + private void StopServerReconnectTimer() + { + if (_serverReconnectTimer == null) { - StopServerReconnectTimer(); - _serverReconnectTimer = new CTimer( - ReconnectToServerTimerCallback, - ServerReconnectInterval - ); - this.LogDebug("Reconnect Timer Started."); + return; } + _serverReconnectTimer.Stop(); + _serverReconnectTimer = null; + } + + /// + /// Resets reconnect timer and updates usercode + /// + /// + private void HandleHeartBeat(JToken content) + { + SendMessageObject(new MobileControlMessage { Type = "/system/heartbeatAck" }); - /// - /// Does what it says - /// - private void StopServerReconnectTimer() + var code = content["userCode"]; + if (code == null) { - if (_serverReconnectTimer == null) - { - return; - } - _serverReconnectTimer.Stop(); - _serverReconnectTimer = null; + return; } - /// - /// Resets reconnect timer and updates usercode - /// - /// - private void HandleHeartBeat(JToken content) + foreach (var b in _roomBridges) { - SendMessageObject(new MobileControlMessage { Type = "/system/heartbeatAck" }); + b.SetUserCode(code.Value()); + } + } - var code = content["userCode"]; - if (code == null) - { - return; - } + private void HandleClientJoined(JToken content) + { + var clientId = content["clientId"].Value(); + var roomKey = content["roomKey"].Value(); - foreach (var b in _roomBridges) + if (_roomCombiner == null) + { + var message = new MobileControlMessage { - b.SetUserCode(code.Value()); - } + Type = "/system/roomKey", + ClientId = clientId, + Content = roomKey + }; + + SendMessageObject(message); + return; } - private void HandleClientJoined(JToken content) + if (!_roomCombiner.CurrentScenario.UiMap.ContainsKey(roomKey)) { - var clientId = content["clientId"].Value(); - var roomKey = content["roomKey"].Value(); + this.LogWarning( + "Unable to find correct roomKey for {roomKey} in current scenario. Returning {roomKey} as roomKey", roomKey); - if (_roomCombiner == null) + var message = new MobileControlMessage { - var message = new MobileControlMessage - { - Type = "/system/roomKey", - ClientId = clientId, - Content = roomKey - }; + Type = "/system/roomKey", + ClientId = clientId, + Content = roomKey + }; - SendMessageObject(message); - return; - } + SendMessageObject(message); + return; + } - if (!_roomCombiner.CurrentScenario.UiMap.ContainsKey(roomKey)) - { - this.LogWarning( - "Unable to find correct roomKey for {roomKey} in current scenario. Returning {roomKey} as roomKey", roomKey); + var newRoomKey = _roomCombiner.CurrentScenario.UiMap[roomKey]; - var message = new MobileControlMessage - { - Type = "/system/roomKey", - ClientId = clientId, - Content = roomKey - }; + var newMessage = new MobileControlMessage + { + Type = "/system/roomKey", + ClientId = clientId, + Content = newRoomKey + }; - SendMessageObject(message); - return; - } + SendMessageObject(newMessage); + } - var newRoomKey = _roomCombiner.CurrentScenario.UiMap[roomKey]; + private void HandleUserCode(JToken content, Action action = null) + { + var code = content["userCode"]; - var newMessage = new MobileControlMessage - { - Type = "/system/roomKey", - ClientId = clientId, - Content = newRoomKey - }; + JToken qrChecksum; - SendMessageObject(newMessage); + try + { + qrChecksum = content.SelectToken("qrChecksum", false); } - - private void HandleUserCode(JToken content, Action action = null) + catch { - var code = content["userCode"]; + qrChecksum = new JValue(string.Empty); + } - JToken qrChecksum; + if (code == null) + { + return; + } - try - { - qrChecksum = content.SelectToken("qrChecksum", false); - } - catch + if (action == null) + { + foreach (var bridge in _roomBridges) { - qrChecksum = new JValue(string.Empty); + bridge.SetUserCode(code.Value(), qrChecksum.Value()); } - if (code == null) - { - return; - } + return; + } - if (action == null) - { - foreach (var bridge in _roomBridges) - { - bridge.SetUserCode(code.Value(), qrChecksum.Value()); - } + action(code.Value(), qrChecksum.Value()); + } - return; - } + public void HandleClientMessage(string message) + { + _receiveQueue.Enqueue(new ProcessStringMessage(message, ParseStreamRx)); + } + + /// + /// + /// + private void ParseStreamRx(string messageText) + { + if (string.IsNullOrEmpty(messageText)) + { + return; + } - action(code.Value(), qrChecksum.Value()); + if (!messageText.Contains("/system/heartbeat")) + { + this.LogDebug( + "Message RX: {messageText}", + messageText + ); } - public void HandleClientMessage(string message) + try + { + var message = JsonConvert.DeserializeObject(messageText); + + switch (message.Type) + { + case "hello": + SendInitialMessage(); + break; + case "/system/heartbeat": + HandleHeartBeat(message.Content); + break; + case "/system/userCode": + HandleUserCode(message.Content); + break; + case "/system/clientJoined": + HandleClientJoined(message.Content); + break; + case "/system/reboot": + SystemMonitorController.ProcessorReboot(); + break; + case "/system/programReset": + SystemMonitorController.ProgramReset(InitialParametersClass.ApplicationNumber); + break; + case "raw": + var wrapper = message.Content.ToObject(); + DeviceJsonApi.DoDeviceAction(wrapper); + break; + case "close": + this.LogDebug("Received close message from server"); + break; + default: + // Incoming message example + // /room/roomA/status + // /room/roomAB/status + + // ActionDictionary Keys example + // /room/roomA + // /room/roomAB + + // Can't do direct comparison because it will match /room/roomA with /room/roomA/xxx instead of /room/roomAB/xxx + var handlers = _actionDictionary.Where(kv => message.Type.StartsWith(kv.Key + "/")).SelectMany(kv => kv.Value).ToList(); // adds trailing slash to ensure above case is handled + + + if (handlers.Count == 0) + { + this.LogInformation("-- Warning: Incoming message has no registered handler {type}", message.Type); + break; + } + + foreach (var handler in handlers) + { + Task.Run( + () => + handler.Action(message.Type, message.ClientId, message.Content) + ); + } + + break; + } + } + catch (Exception err) { - _receiveQueue.Enqueue(new ProcessStringMessage(message, ParseStreamRx)); + this.LogException( + err, + "Unable to parse {message}", + messageText + ); } + } - /// - /// - /// - private void ParseStreamRx(string messageText) + /// + /// + /// + /// + private void TestHttpRequest(string s) + { { - if (string.IsNullOrEmpty(messageText)) + s = s.Trim(); + if (string.IsNullOrEmpty(s)) { + PrintTestHttpRequestUsage(); return; } - - if (!messageText.Contains("/system/heartbeat")) + var tokens = s.Split(' '); + if (tokens.Length < 2) { - this.LogDebug( - "Message RX: {messageText}", - messageText - ); + CrestronConsole.ConsoleCommandResponse("Too few paramaters\r"); + PrintTestHttpRequestUsage(); + return; } try { - var message = JsonConvert.DeserializeObject(messageText); - - switch (message.Type) + var url = tokens[1]; + switch (tokens[0].ToLower()) { - case "hello": - SendInitialMessage(); - break; - case "/system/heartbeat": - HandleHeartBeat(message.Content); - break; - case "/system/userCode": - HandleUserCode(message.Content); - break; - case "/system/clientJoined": - HandleClientJoined(message.Content); - break; - case "/system/reboot": - SystemMonitorController.ProcessorReboot(); - break; - case "/system/programReset": - SystemMonitorController.ProgramReset(InitialParametersClass.ApplicationNumber); - break; - case "raw": - var wrapper = message.Content.ToObject(); - DeviceJsonApi.DoDeviceAction(wrapper); - break; - case "close": - this.LogDebug("Received close message from server"); - break; - default: - // Incoming message example - // /room/roomA/status - // /room/roomAB/status - - // ActionDictionary Keys example - // /room/roomA - // /room/roomAB - - // Can't do direct comparison because it will match /room/roomA with /room/roomA/xxx instead of /room/roomAB/xxx - var handlers = _actionDictionary.Where(kv => message.Type.StartsWith(kv.Key + "/")).SelectMany(kv => kv.Value).ToList(); // adds trailing slash to ensure above case is handled - - - if (handlers.Count == 0) + case "get": { - this.LogInformation("-- Warning: Incoming message has no registered handler {type}", message.Type); - break; - } - - foreach (var handler in handlers) + var resp = new HttpClient().Get(url); + CrestronConsole.ConsoleCommandResponse("RESPONSE:\r{0}\r\r", resp); + } + break; + case "post": { - Task.Run( - () => - handler.Action(message.Type, message.ClientId, message.Content) - ); + var resp = new HttpClient().Post(url, new byte[] { }); + CrestronConsole.ConsoleCommandResponse("RESPONSE:\r{0}\r\r", resp); } - + break; + default: + CrestronConsole.ConsoleCommandResponse("Only get or post supported\r"); + PrintTestHttpRequestUsage(); break; } } - catch (Exception err) + catch (HttpException e) { - this.LogException( - err, - "Unable to parse {message}", - messageText + CrestronConsole.ConsoleCommandResponse("Exception in request:\r"); + CrestronConsole.ConsoleCommandResponse( + "Response URL: {0}\r", + e.Response.ResponseUrl + ); + CrestronConsole.ConsoleCommandResponse( + "Response Error Code: {0}\r", + e.Response.Code + ); + CrestronConsole.ConsoleCommandResponse( + "Response body: {0}\r", + e.Response.ContentString ); } } - - /// - /// - /// - /// - private void TestHttpRequest(string s) - { - { - s = s.Trim(); - if (string.IsNullOrEmpty(s)) - { - PrintTestHttpRequestUsage(); - return; - } - var tokens = s.Split(' '); - if (tokens.Length < 2) - { - CrestronConsole.ConsoleCommandResponse("Too few paramaters\r"); - PrintTestHttpRequestUsage(); - return; - } - - try - { - var url = tokens[1]; - switch (tokens[0].ToLower()) - { - case "get": - { - var resp = new HttpClient().Get(url); - CrestronConsole.ConsoleCommandResponse("RESPONSE:\r{0}\r\r", resp); - } - break; - case "post": - { - var resp = new HttpClient().Post(url, new byte[] { }); - CrestronConsole.ConsoleCommandResponse("RESPONSE:\r{0}\r\r", resp); - } - break; - default: - CrestronConsole.ConsoleCommandResponse("Only get or post supported\r"); - PrintTestHttpRequestUsage(); - break; - } - } - catch (HttpException e) - { - CrestronConsole.ConsoleCommandResponse("Exception in request:\r"); - CrestronConsole.ConsoleCommandResponse( - "Response URL: {0}\r", - e.Response.ResponseUrl - ); - CrestronConsole.ConsoleCommandResponse( - "Response Error Code: {0}\r", - e.Response.Code - ); - CrestronConsole.ConsoleCommandResponse( - "Response body: {0}\r", - e.Response.ContentString - ); - } - } - } - - private void PrintTestHttpRequestUsage() - { - CrestronConsole.ConsoleCommandResponse("Usage: mobilehttprequest:N get/post url\r"); - } } - public class ClientSpecificUpdateRequest + private void PrintTestHttpRequestUsage() { - public ClientSpecificUpdateRequest(Action action) - { - ResponseMethod = action; - } - - public Action ResponseMethod { get; private set; } + CrestronConsole.ConsoleCommandResponse("Usage: mobilehttprequest:N get/post url\r"); } +} - public class UserCodeChanged +public class ClientSpecificUpdateRequest +{ + public ClientSpecificUpdateRequest(Action action) { - public Action UpdateUserCode { get; private set; } + ResponseMethod = action; + } - public UserCodeChanged(Action updateMethod) - { - UpdateUserCode = updateMethod; - } + public Action ResponseMethod { get; private set; } +} + +public class UserCodeChanged +{ + public Action UpdateUserCode { get; private set; } + + public UserCodeChanged(Action updateMethod) + { + UpdateUserCode = updateMethod; } } diff --git a/src/PepperDash.Essentials.MobileControl/PepperDash.Essentials.MobileControl.csproj b/src/PepperDash.Essentials.MobileControl/PepperDash.Essentials.MobileControl.csproj index 1e8877289..a043af9a2 100644 --- a/src/PepperDash.Essentials.MobileControl/PepperDash.Essentials.MobileControl.csproj +++ b/src/PepperDash.Essentials.MobileControl/PepperDash.Essentials.MobileControl.csproj @@ -1,7 +1,7 @@  PepperDash.Essentials - net472 + net8 true false epi-essentials-mobile-control @@ -37,7 +37,8 @@ - + + diff --git a/src/PepperDash.Essentials.MobileControl/RoomBridges/MobileControlBridgeBase.cs b/src/PepperDash.Essentials.MobileControl/RoomBridges/MobileControlBridgeBase.cs index c005ca177..f3cb8d682 100644 --- a/src/PepperDash.Essentials.MobileControl/RoomBridges/MobileControlBridgeBase.cs +++ b/src/PepperDash.Essentials.MobileControl/RoomBridges/MobileControlBridgeBase.cs @@ -5,127 +5,126 @@ using System; -namespace PepperDash.Essentials.RoomBridges +namespace PepperDash.Essentials.RoomBridges; + +/// +/// +/// +public abstract class MobileControlBridgeBase : MessengerBase, IMobileControlRoomMessenger { - /// - /// - /// - public abstract class MobileControlBridgeBase : MessengerBase, IMobileControlRoomMessenger - { - public event EventHandler UserCodeChanged; + public event EventHandler UserCodeChanged; - public event EventHandler UserPromptedForCode; + public event EventHandler UserPromptedForCode; - public event EventHandler ClientJoined; + public event EventHandler ClientJoined; - public event EventHandler AppUrlChanged; + public event EventHandler AppUrlChanged; - public IMobileControl Parent { get; private set; } + public IMobileControl Parent { get; private set; } - public string AppUrl { get; private set; } - public string UserCode { get; private set; } + public string AppUrl { get; private set; } + public string UserCode { get; private set; } - public string QrCodeUrl { get; protected set; } + public string QrCodeUrl { get; protected set; } - public string QrCodeChecksum { get; protected set; } + public string QrCodeChecksum { get; protected set; } - public string McServerUrl { get; private set; } + public string McServerUrl { get; private set; } - public abstract string RoomName { get; } + public abstract string RoomName { get; } - public abstract string RoomKey { get; } + public abstract string RoomKey { get; } - protected MobileControlBridgeBase(string key, string messagePath) - : base(key, messagePath) - { - } + protected MobileControlBridgeBase(string key, string messagePath) + : base(key, messagePath) + { + } - protected MobileControlBridgeBase(string key, string messagePath, IKeyName device) - : base(key, messagePath, device) - { - } + protected MobileControlBridgeBase(string key, string messagePath, IKeyName device) + : base(key, messagePath, device) + { + } - /// - /// Set the parent. Does nothing else. Override to add functionality such - /// as adding actions to parent - /// - /// - public virtual void AddParent(IMobileControl parent) - { - Parent = parent; + /// + /// Set the parent. Does nothing else. Override to add functionality such + /// as adding actions to parent + /// + /// + public virtual void AddParent(IMobileControl parent) + { + Parent = parent; - McServerUrl = Parent.ClientAppUrl; - } + McServerUrl = Parent.ClientAppUrl; + } - /// - /// Sets the UserCode on the bridge object. Called from controller. A changed code will - /// fire method UserCodeChange. Override that to handle changes - /// - /// - public void SetUserCode(string code) + /// + /// Sets the UserCode on the bridge object. Called from controller. A changed code will + /// fire method UserCodeChange. Override that to handle changes + /// + /// + public void SetUserCode(string code) + { + var changed = UserCode != code; + UserCode = code; + if (changed) { - var changed = UserCode != code; - UserCode = code; - if (changed) - { - UserCodeChange(); - } + UserCodeChange(); } + } - /// - /// Sets the UserCode on the bridge object. Called from controller. A changed code will - /// fire method UserCodeChange. Override that to handle changes - /// - /// - /// Checksum of the QR code. Used for Cisco codec branding command - public void SetUserCode(string code, string qrChecksum) - { - QrCodeChecksum = qrChecksum; + /// + /// Sets the UserCode on the bridge object. Called from controller. A changed code will + /// fire method UserCodeChange. Override that to handle changes + /// + /// + /// Checksum of the QR code. Used for Cisco codec branding command + public void SetUserCode(string code, string qrChecksum) + { + QrCodeChecksum = qrChecksum; - SetUserCode(code); - } + SetUserCode(code); + } - public virtual void UpdateAppUrl(string url) - { - AppUrl = url; + public virtual void UpdateAppUrl(string url) + { + AppUrl = url; - var handler = AppUrlChanged; + var handler = AppUrlChanged; - if (handler == null) return; + if (handler == null) return; - handler(this, new EventArgs()); - } + handler(this, new EventArgs()); + } - /// - /// Empty method in base class. Override this to add functionality - /// when code changes - /// - protected virtual void UserCodeChange() - { - this.LogDebug("Server user code changed: {userCode}", UserCode); + /// + /// Empty method in base class. Override this to add functionality + /// when code changes + /// + protected virtual void UserCodeChange() + { + this.LogDebug("Server user code changed: {userCode}", UserCode); - var qrUrl = string.Format($"{Parent.Host}/api/rooms/{Parent.SystemUuid}/{RoomKey}/qr?x={new Random().Next()}"); - QrCodeUrl = qrUrl; + var qrUrl = string.Format($"{Parent.Host}/api/rooms/{Parent.SystemUuid}/{RoomKey}/qr?x={new Random().Next()}"); + QrCodeUrl = qrUrl; - this.LogDebug("Server user code changed: {userCode} - {qrCodeUrl}", UserCode, qrUrl); + this.LogDebug("Server user code changed: {userCode} - {qrCodeUrl}", UserCode, qrUrl); - OnUserCodeChanged(); - } + OnUserCodeChanged(); + } - protected void OnUserCodeChanged() - { - UserCodeChanged?.Invoke(this, new EventArgs()); - } + protected void OnUserCodeChanged() + { + UserCodeChanged?.Invoke(this, new EventArgs()); + } - protected void OnUserPromptedForCode() - { - UserPromptedForCode?.Invoke(this, new EventArgs()); - } + protected void OnUserPromptedForCode() + { + UserPromptedForCode?.Invoke(this, new EventArgs()); + } - protected void OnClientJoined() - { - ClientJoined?.Invoke(this, new EventArgs()); - } + protected void OnClientJoined() + { + ClientJoined?.Invoke(this, new EventArgs()); } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl/RoomBridges/MobileControlEssentialsRoomBridge.cs b/src/PepperDash.Essentials.MobileControl/RoomBridges/MobileControlEssentialsRoomBridge.cs index 9009c4cc9..cb5d51ae1 100644 --- a/src/PepperDash.Essentials.MobileControl/RoomBridges/MobileControlEssentialsRoomBridge.cs +++ b/src/PepperDash.Essentials.MobileControl/RoomBridges/MobileControlEssentialsRoomBridge.cs @@ -23,944 +23,943 @@ using IShades = PepperDash.Essentials.Core.Shades.IShades; using ShadeBase = PepperDash.Essentials.Devices.Common.Shades.ShadeBase; -namespace PepperDash.Essentials.RoomBridges +namespace PepperDash.Essentials.RoomBridges; + +public class MobileControlEssentialsRoomBridge : MobileControlBridgeBase { - public class MobileControlEssentialsRoomBridge : MobileControlBridgeBase + private List _touchPanelTokens = new List(); + public IEssentialsRoom Room { get; private set; } + + public string DefaultRoomKey { get; private set; } + /// + /// + /// + public override string RoomName { - private List _touchPanelTokens = new List(); - public IEssentialsRoom Room { get; private set; } - - public string DefaultRoomKey { get; private set; } - /// - /// - /// - public override string RoomName - { - get { return Room.Name; } - } + get { return Room.Name; } + } - public override string RoomKey - { - get { return Room.Key; } - } + public override string RoomKey + { + get { return Room.Key; } + } - public MobileControlEssentialsRoomBridge(IEssentialsRoom room) : - this($"mobileControlBridge-{room.Key}", room.Key, room) - { - Room = room; - } + public MobileControlEssentialsRoomBridge(IEssentialsRoom room) : + this($"mobileControlBridge-{room.Key}", room.Key, room) + { + Room = room; + } - public MobileControlEssentialsRoomBridge(string key, string roomKey, IEssentialsRoom room) : base(key, $"/room/{room.Key}", room as Device) - { - DefaultRoomKey = roomKey; + public MobileControlEssentialsRoomBridge(string key, string roomKey, IEssentialsRoom room) : base(key, $"/room/{room.Key}", room as Device) + { + DefaultRoomKey = roomKey; - AddPreActivationAction(GetRoom); - } + AddPreActivationAction(GetRoom); + } - protected override void RegisterActions() - { - // we add actions to the messaging system with a path, and a related action. Custom action - // content objects can be handled in the controller's LineReceived method - and perhaps other - // sub-controller parsing could be attached to these classes, so that the systemController - // doesn't need to know about everything. + protected override void RegisterActions() + { + // we add actions to the messaging system with a path, and a related action. Custom action + // content objects can be handled in the controller's LineReceived method - and perhaps other + // sub-controller parsing could be attached to these classes, so that the systemController + // doesn't need to know about everything. - this.LogInformation("Registering Actions with AppServer"); + this.LogInformation("Registering Actions with AppServer"); - AddAction("/promptForCode", (id, content) => OnUserPromptedForCode()); - AddAction("/clientJoined", (id, content) => OnClientJoined()); + AddAction("/promptForCode", (id, content) => OnUserPromptedForCode()); + AddAction("/clientJoined", (id, content) => OnClientJoined()); - AddAction("/touchPanels", (id, content) => OnTouchPanelsUpdated(content)); + AddAction("/touchPanels", (id, content) => OnTouchPanelsUpdated(content)); - AddAction($"/userApp", (id, content) => OnUserAppUpdated(content)); + AddAction($"/userApp", (id, content) => OnUserAppUpdated(content)); - AddAction("/userCode", (id, content) => - { - var msg = content.ToObject(); + AddAction("/userCode", (id, content) => + { + var msg = content.ToObject(); - SetUserCode(msg.UserCode, msg.QrChecksum ?? string.Empty); - }); + SetUserCode(msg.UserCode, msg.QrChecksum ?? string.Empty); + }); - // Source Changes and room off - AddAction("/status", (id, content) => - { - SendFullStatusForClientId(id, Room); - }); + // Source Changes and room off + AddAction("/status", (id, content) => + { + SendFullStatusForClientId(id, Room); + }); - if (Room is IRunRouteAction routeRoom) - AddAction("/source", (id, content) => - { + if (Room is IRunRouteAction routeRoom) + AddAction("/source", (id, content) => + { - var msg = content.ToObject(); + var msg = content.ToObject(); - this.LogVerbose("Received request to route to source: {sourceListKey} on list: {sourceList}", msg.SourceListItemKey, msg.SourceListKey); + this.LogVerbose("Received request to route to source: {sourceListKey} on list: {sourceList}", msg.SourceListItemKey, msg.SourceListKey); - routeRoom.RunRouteAction(msg.SourceListItemKey, msg.SourceListKey); - }); + routeRoom.RunRouteAction(msg.SourceListItemKey, msg.SourceListKey); + }); - if (Room is IRunDirectRouteAction directRouteRoom) + if (Room is IRunDirectRouteAction directRouteRoom) + { + AddAction("/directRoute", (id, content) => { - AddAction("/directRoute", (id, content) => - { - var msg = content.ToObject(); + var msg = content.ToObject(); - this.LogVerbose("Running direct route from {sourceKey} to {destinationKey} with signal type {signalType}", msg.SourceKey, msg.DestinationKey, msg.SignalType); + this.LogVerbose("Running direct route from {sourceKey} to {destinationKey} with signal type {signalType}", msg.SourceKey, msg.DestinationKey, msg.SignalType); - directRouteRoom.RunDirectRoute(msg.SourceKey, msg.DestinationKey, msg.SignalType); - }); - } + directRouteRoom.RunDirectRoute(msg.SourceKey, msg.DestinationKey, msg.SignalType); + }); + } - if (Room is IRunDefaultPresentRoute defaultRoom) - AddAction("/defaultsource", (id, content) => defaultRoom.RunDefaultPresentRoute()); + if (Room is IRunDefaultPresentRoute defaultRoom) + AddAction("/defaultsource", (id, content) => defaultRoom.RunDefaultPresentRoute()); - if (Room is IHasCurrentSourceInfoChange sscRoom) - sscRoom.CurrentSourceChange += Room_CurrentSingleSourceChange; + if (Room is IHasCurrentSourceInfoChange sscRoom) + sscRoom.CurrentSourceChange += Room_CurrentSingleSourceChange; - if (Room is IEssentialsHuddleVtc1Room vtcRoom) + if (Room is IEssentialsHuddleVtc1Room vtcRoom) + { + if (vtcRoom.ScheduleSource != null) { - if (vtcRoom.ScheduleSource != null) - { - var key = vtcRoom.Key + "-" + Key; + var key = vtcRoom.Key + "-" + Key; - if (!AppServerController.CheckForDeviceMessenger(key)) - { - var scheduleMessenger = new IHasScheduleAwarenessMessenger(key, vtcRoom.ScheduleSource, - $"/room/{vtcRoom.Key}"); - AppServerController.AddDeviceMessenger(scheduleMessenger); - } + if (!AppServerController.CheckForDeviceMessenger(key)) + { + var scheduleMessenger = new IHasScheduleAwarenessMessenger(key, vtcRoom.ScheduleSource, + $"/room/{vtcRoom.Key}"); + AppServerController.AddDeviceMessenger(scheduleMessenger); } - - vtcRoom.InCallFeedback.OutputChange += InCallFeedback_OutputChange; } - if (Room is IPrivacy privacyRoom) - { - AddAction("/volumes/master/privacyMuteToggle", (id, content) => privacyRoom.PrivacyModeToggle()); + vtcRoom.InCallFeedback.OutputChange += InCallFeedback_OutputChange; + } - privacyRoom.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange; - } + if (Room is IPrivacy privacyRoom) + { + AddAction("/volumes/master/privacyMuteToggle", (id, content) => privacyRoom.PrivacyModeToggle()); + privacyRoom.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange; + } - if (Room is IRunDefaultCallRoute defCallRm) - { - AddAction("/activityVideo", (id, content) => defCallRm.RunDefaultCallRoute()); - } - Room.OnFeedback.OutputChange += OnFeedback_OutputChange; - Room.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange; - Room.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange; + if (Room is IRunDefaultCallRoute defCallRm) + { + AddAction("/activityVideo", (id, content) => defCallRm.RunDefaultCallRoute()); + } - AddTechRoomActions(); + Room.OnFeedback.OutputChange += OnFeedback_OutputChange; + Room.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange; + Room.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange; - if (Room is IHasCurrentVolumeControls volumeRoom) - { - volumeRoom.CurrentVolumeDeviceChange += Room_CurrentVolumeDeviceChange; + AddTechRoomActions(); - if (volumeRoom.CurrentVolumeControls == null) return; + if (Room is IHasCurrentVolumeControls volumeRoom) + { + volumeRoom.CurrentVolumeDeviceChange += Room_CurrentVolumeDeviceChange; - AddAction("/volumes/master/level", (id, content) => - { - var msg = content.ToObject>(); + if (volumeRoom.CurrentVolumeControls == null) return; + AddAction("/volumes/master/level", (id, content) => + { + var msg = content.ToObject>(); - if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback) - basicVolumeWithFeedback.SetVolume(msg.Value); - }); - AddAction("/volumes/master/muteToggle", (id, content) => volumeRoom.CurrentVolumeControls.MuteToggle()); + if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback) + basicVolumeWithFeedback.SetVolume(msg.Value); + }); - AddAction("/volumes/master/muteOn", (id, content) => - { - if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback) - basicVolumeWithFeedback.MuteOn(); - }); + AddAction("/volumes/master/muteToggle", (id, content) => volumeRoom.CurrentVolumeControls.MuteToggle()); - AddAction("/volumes/master/muteOff", (id, content) => - { - if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback) - basicVolumeWithFeedback.MuteOff(); - }); + AddAction("/volumes/master/muteOn", (id, content) => + { + if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback) + basicVolumeWithFeedback.MuteOn(); + }); + + AddAction("/volumes/master/muteOff", (id, content) => + { + if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback) + basicVolumeWithFeedback.MuteOff(); + }); - AddAction("/volumes/master/volumeUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => + AddAction("/volumes/master/volumeUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => + { + if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback) { - if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback) - { - basicVolumeWithFeedback.VolumeUp(b); - } + basicVolumeWithFeedback.VolumeUp(b); } - )); + } + )); - AddAction("/volumes/master/volumeDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => + AddAction("/volumes/master/volumeDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) => + { + if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback) { - if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback) - { - basicVolumeWithFeedback.VolumeDown(b); - } + basicVolumeWithFeedback.VolumeDown(b); } - )); + } + )); - // Registers for initial volume events, if possible - if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback currentVolumeDevice) - { - this.LogVerbose("Registering for volume feedback events"); + // Registers for initial volume events, if possible + if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback currentVolumeDevice) + { + this.LogVerbose("Registering for volume feedback events"); - currentVolumeDevice.MuteFeedback.OutputChange += MuteFeedback_OutputChange; - currentVolumeDevice.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange; - } + currentVolumeDevice.MuteFeedback.OutputChange += MuteFeedback_OutputChange; + currentVolumeDevice.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange; } } + } - private void OnTouchPanelsUpdated(JToken content) - { - var message = content.ToObject(); + private void OnTouchPanelsUpdated(JToken content) + { + var message = content.ToObject(); - _touchPanelTokens = message.TouchPanels; + _touchPanelTokens = message.TouchPanels; - UpdateTouchPanelAppUrls(message.UserAppUrl); - } + UpdateTouchPanelAppUrls(message.UserAppUrl); + } - private void UpdateTouchPanelAppUrls(string userAppUrl) + private void UpdateTouchPanelAppUrls(string userAppUrl) + { + foreach (var tp in _touchPanelTokens) { - foreach (var tp in _touchPanelTokens) - { - var dev = DeviceManager.AllDevices.OfType().FirstOrDefault((tpc) => tpc.Key.Equals(tp.TouchpanelKey, StringComparison.InvariantCultureIgnoreCase)); + var dev = DeviceManager.AllDevices.OfType().FirstOrDefault((tpc) => tpc.Key.Equals(tp.TouchpanelKey, StringComparison.InvariantCultureIgnoreCase)); - if (dev == null) - { - continue; - } + if (dev == null) + { + continue; + } - //UpdateAppUrl($"{userAppUrl}?token={tp.Token}"); + //UpdateAppUrl($"{userAppUrl}?token={tp.Token}"); - dev.SetAppUrl($"{userAppUrl}?token={tp.Token}"); - } + dev.SetAppUrl($"{userAppUrl}?token={tp.Token}"); } + } - private void OnUserAppUpdated(JToken content) - { - var message = content.ToObject(); + private void OnUserAppUpdated(JToken content) + { + var message = content.ToObject(); - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Updating User App URL to {userAppUrl}. Full Message: {@message}", this, message.UserAppUrl, content); + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Updating User App URL to {userAppUrl}. Full Message: {@message}", this, message.UserAppUrl, content); - UpdateTouchPanelAppUrls(message.UserAppUrl); - } + UpdateTouchPanelAppUrls(message.UserAppUrl); + } + + private void InCallFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + var state = new RoomStateMessage + { + IsInCall = e.BoolValue + }; + PostStatusMessage(state); + } - private void InCallFeedback_OutputChange(object sender, FeedbackEventArgs e) + private void GetRoom() + { + if (Room != null) { - var state = new RoomStateMessage - { - IsInCall = e.BoolValue - }; - PostStatusMessage(state); + this.LogInformation("Room with key {key} already linked.", DefaultRoomKey); + return; } - private void GetRoom() + + if (!(DeviceManager.GetDeviceForKey(DefaultRoomKey) is IEssentialsRoom tempRoom)) { - if (Room != null) - { - this.LogInformation("Room with key {key} already linked.", DefaultRoomKey); - return; - } + this.LogInformation("Room with key {key} not found or is not an Essentials Room", DefaultRoomKey); + return; + } + Room = tempRoom; + } - if (!(DeviceManager.GetDeviceForKey(DefaultRoomKey) is IEssentialsRoom tempRoom)) - { - this.LogInformation("Room with key {key} not found or is not an Essentials Room", DefaultRoomKey); - return; - } + protected override void UserCodeChange() + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Server user code changed: {userCode}", this, UserCode); - Room = tempRoom; - } + var qrUrl = string.Format("{0}/rooms/{1}/{3}/qr?x={2}", Parent?.Host, Parent?.SystemUuid, new Random().Next(), DefaultRoomKey); - protected override void UserCodeChange() - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Server user code changed: {userCode}", this, UserCode); + QrCodeUrl = qrUrl; - var qrUrl = string.Format("{0}/rooms/{1}/{3}/qr?x={2}", Parent?.Host, Parent?.SystemUuid, new Random().Next(), DefaultRoomKey); + this.LogDebug("Server user code changed: {userCode} - {qrUrl}", UserCode, qrUrl); - QrCodeUrl = qrUrl; + OnUserCodeChanged(); + } - this.LogDebug("Server user code changed: {userCode} - {qrUrl}", UserCode, qrUrl); + /* /// + /// Override of base: calls base to add parent and then registers actions and events. + /// + /// + public override void AddParent(MobileControlSystemController parent) + { + base.AddParent(parent); + + }*/ - OnUserCodeChanged(); + private void AddTechRoomActions() + { + if (!(Room is IEssentialsTechRoom techRoom)) + { + return; } - /* /// - /// Override of base: calls base to add parent and then registers actions and events. - /// - /// - public override void AddParent(MobileControlSystemController parent) - { - base.AddParent(parent); + AddAction("/roomPowerOn", (id, content) => techRoom.RoomPowerOn()); + AddAction("/roomPowerOff", (id, content) => techRoom.RoomPowerOff()); + } - }*/ + private void PrivacyModeIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + var state = new RoomStateMessage(); - private void AddTechRoomActions() + var volumes = new Dictionary { - if (!(Room is IEssentialsTechRoom techRoom)) - { - return; + { "master", new Volume("master") + { + PrivacyMuted = e.BoolValue + } } + }; - AddAction("/roomPowerOn", (id, content) => techRoom.RoomPowerOn()); - AddAction("/roomPowerOff", (id, content) => techRoom.RoomPowerOff()); - } - - private void PrivacyModeIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) - { - var state = new RoomStateMessage(); + state.Volumes = volumes; - var volumes = new Dictionary - { - { "master", new Volume("master") - { - PrivacyMuted = e.BoolValue - } - } - }; + PostStatusMessage(state); + } - state.Volumes = volumes; + /// + /// + /// + /// + /// + private void IsSharingFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + // sharing source + string shareText; + bool isSharing; - PostStatusMessage(state); + if (Room is IHasCurrentSourceInfoChange srcInfoRoom && Room is IHasVideoCodec vcRoom && vcRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue && srcInfoRoom.CurrentSourceInfo != null) + { + shareText = srcInfoRoom.CurrentSourceInfo.PreferredName; + isSharing = true; } - - /// - /// - /// - /// - /// - private void IsSharingFeedback_OutputChange(object sender, FeedbackEventArgs e) + else { - // sharing source - string shareText; - bool isSharing; + shareText = "None"; + isSharing = false; + } - if (Room is IHasCurrentSourceInfoChange srcInfoRoom && Room is IHasVideoCodec vcRoom && vcRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue && srcInfoRoom.CurrentSourceInfo != null) - { - shareText = srcInfoRoom.CurrentSourceInfo.PreferredName; - isSharing = true; - } - else + var state = new RoomStateMessage + { + Share = new ShareState { - shareText = "None"; - isSharing = false; + CurrentShareText = shareText, + IsSharing = isSharing } + }; - var state = new RoomStateMessage - { - Share = new ShareState - { - CurrentShareText = shareText, - IsSharing = isSharing - } - }; - - PostStatusMessage(state); - } + PostStatusMessage(state); + } - /// - /// - /// - /// - /// - private void IsWarmingUpFeedback_OutputChange(object sender, FeedbackEventArgs e) + /// + /// + /// + /// + /// + private void IsWarmingUpFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + var state = new { - var state = new - { - isWarmingUp = e.BoolValue - }; + isWarmingUp = e.BoolValue + }; - PostStatusMessage(JToken.FromObject(state)); - } + PostStatusMessage(JToken.FromObject(state)); + } - /// - /// - /// - /// - /// - private void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e) + /// + /// + /// + /// + /// + private void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + var state = new { - var state = new - { - isCoolingDown = e.BoolValue - }; - PostStatusMessage(JToken.FromObject(state)); - } + isCoolingDown = e.BoolValue + }; + PostStatusMessage(JToken.FromObject(state)); + } - /// - /// - /// - /// - /// - private void OnFeedback_OutputChange(object sender, FeedbackEventArgs e) + /// + /// + /// + /// + /// + private void OnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + var state = new { - var state = new - { - isOn = e.BoolValue - }; - PostStatusMessage(JToken.FromObject(state)); - } + isOn = e.BoolValue + }; + PostStatusMessage(JToken.FromObject(state)); + } - private void Room_CurrentVolumeDeviceChange(object sender, VolumeDeviceChangeEventArgs e) + private void Room_CurrentVolumeDeviceChange(object sender, VolumeDeviceChangeEventArgs e) + { + if (e.OldDev is IBasicVolumeWithFeedback) { - if (e.OldDev is IBasicVolumeWithFeedback) - { - var oldDev = e.OldDev as IBasicVolumeWithFeedback; - oldDev.MuteFeedback.OutputChange -= MuteFeedback_OutputChange; - oldDev.VolumeLevelFeedback.OutputChange -= VolumeLevelFeedback_OutputChange; - } + var oldDev = e.OldDev as IBasicVolumeWithFeedback; + oldDev.MuteFeedback.OutputChange -= MuteFeedback_OutputChange; + oldDev.VolumeLevelFeedback.OutputChange -= VolumeLevelFeedback_OutputChange; + } - if (e.NewDev is IBasicVolumeWithFeedback) - { - var newDev = e.NewDev as IBasicVolumeWithFeedback; - newDev.MuteFeedback.OutputChange += MuteFeedback_OutputChange; - newDev.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange; - } + if (e.NewDev is IBasicVolumeWithFeedback) + { + var newDev = e.NewDev as IBasicVolumeWithFeedback; + newDev.MuteFeedback.OutputChange += MuteFeedback_OutputChange; + newDev.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange; } + } - /// - /// Event handler for mute changes - /// - private void MuteFeedback_OutputChange(object sender, FeedbackEventArgs e) + /// + /// Event handler for mute changes + /// + private void MuteFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + var state = new RoomStateMessage(); + + var volumes = new Dictionary { - var state = new RoomStateMessage(); + { "master", new Volume("master", e.BoolValue) } + }; - var volumes = new Dictionary - { - { "master", new Volume("master", e.BoolValue) } - }; + state.Volumes = volumes; - state.Volumes = volumes; + PostStatusMessage(state); + } - PostStatusMessage(state); - } + /// + /// Handles Volume changes on room + /// + private void VolumeLevelFeedback_OutputChange(object sender, FeedbackEventArgs e) + { - /// - /// Handles Volume changes on room - /// - private void VolumeLevelFeedback_OutputChange(object sender, FeedbackEventArgs e) + var state = new { - - var state = new + volumes = new Dictionary { - volumes = new Dictionary - { - { "master", new Volume("master", e.IntValue) } - } - }; - PostStatusMessage(JToken.FromObject(state)); - } + { "master", new Volume("master", e.IntValue) } + } + }; + PostStatusMessage(JToken.FromObject(state)); + } - private void Room_CurrentSingleSourceChange(SourceListItem info, ChangeType type) - { - /* Example message - * { + private void Room_CurrentSingleSourceChange(SourceListItem info, ChangeType type) + { + /* Example message + * {    "type":"/room/status",    "content": {      "selectedSourceKey": "off",    } - } - */ + } + */ - } + } - /// - /// Sends the full status of the room to the server - /// - /// - private void SendFullStatusForClientId(string id, IEssentialsRoom room) - { - //Parent.SendMessageObject(GetFullStatus(room)); - var message = GetFullStatusForClientId(room); + /// + /// Sends the full status of the room to the server + /// + /// + private void SendFullStatusForClientId(string id, IEssentialsRoom room) + { + //Parent.SendMessageObject(GetFullStatus(room)); + var message = GetFullStatusForClientId(room); - if (message == null) - { - return; - } - PostStatusMessage(message, id); + if (message == null) + { + return; } + PostStatusMessage(message, id); + } - /// - /// Gets full room status - /// - /// The room to get status of - /// The status response message - private RoomStateMessage GetFullStatusForClientId(IEssentialsRoom room) + /// + /// Gets full room status + /// + /// The room to get status of + /// The status response message + private RoomStateMessage GetFullStatusForClientId(IEssentialsRoom room) + { + try { - try - { - this.LogVerbose("GetFullStatus"); + this.LogVerbose("GetFullStatus"); - var sourceKey = room is IHasCurrentSourceInfoChange ? (room as IHasCurrentSourceInfoChange).CurrentSourceInfoKey : null; + var sourceKey = room is IHasCurrentSourceInfoChange ? (room as IHasCurrentSourceInfoChange).CurrentSourceInfoKey : null; - var volumes = new Dictionary(); - if (room is IHasCurrentVolumeControls rmVc) + var volumes = new Dictionary(); + if (room is IHasCurrentVolumeControls rmVc) + { + if (rmVc.CurrentVolumeControls is IBasicVolumeWithFeedback vc) { - if (rmVc.CurrentVolumeControls is IBasicVolumeWithFeedback vc) + var volume = new Volume("master", vc.VolumeLevelFeedback.UShortValue, vc.MuteFeedback.BoolValue, "Volume", true, ""); + if (room is IPrivacy privacyRoom) { - var volume = new Volume("master", vc.VolumeLevelFeedback.UShortValue, vc.MuteFeedback.BoolValue, "Volume", true, ""); - if (room is IPrivacy privacyRoom) - { - volume.HasPrivacyMute = true; - volume.PrivacyMuted = privacyRoom.PrivacyModeIsOnFeedback.BoolValue; - } - - volumes.Add("master", volume); + volume.HasPrivacyMute = true; + volume.PrivacyMuted = privacyRoom.PrivacyModeIsOnFeedback.BoolValue; } - } - var state = new RoomStateMessage - { - Configuration = GetRoomConfiguration(room), - ActivityMode = 1, - IsOn = room.OnFeedback.BoolValue, - SelectedSourceKey = sourceKey, - Volumes = volumes, - IsWarmingUp = room.IsWarmingUpFeedback.BoolValue, - IsCoolingDown = room.IsCoolingDownFeedback.BoolValue - }; - - if (room is IEssentialsHuddleVtc1Room vtcRoom) - { - state.IsInCall = vtcRoom.InCallFeedback.BoolValue; + volumes.Add("master", volume); } - - return state; } - catch (Exception ex) + + var state = new RoomStateMessage { - Debug.LogMessage(ex, "Error getting full status", this); - return null; + Configuration = GetRoomConfiguration(room), + ActivityMode = 1, + IsOn = room.OnFeedback.BoolValue, + SelectedSourceKey = sourceKey, + Volumes = volumes, + IsWarmingUp = room.IsWarmingUpFeedback.BoolValue, + IsCoolingDown = room.IsCoolingDownFeedback.BoolValue + }; + + if (room is IEssentialsHuddleVtc1Room vtcRoom) + { + state.IsInCall = vtcRoom.InCallFeedback.BoolValue; } + + return state; } + catch (Exception ex) + { + Debug.LogMessage(ex, "Error getting full status", this); + return null; + } + } - /// - /// Determines the configuration of the room and the details about the devices associated with the room - /// - /// - private RoomConfiguration GetRoomConfiguration(IEssentialsRoom room) + /// + /// Determines the configuration of the room and the details about the devices associated with the room + /// + /// + private RoomConfiguration GetRoomConfiguration(IEssentialsRoom room) + { + try { + var configuration = new RoomConfiguration + { + //ShutdownPromptSeconds = room.ShutdownPromptSeconds, + TouchpanelKeys = DeviceManager.AllDevices. + OfType() + .Where((tp) => tp.DefaultRoomKey.Equals(room.Key, StringComparison.InvariantCultureIgnoreCase)) + .Select(tp => tp.Key).ToList() + }; + try { - var configuration = new RoomConfiguration - { - //ShutdownPromptSeconds = room.ShutdownPromptSeconds, - TouchpanelKeys = DeviceManager.AllDevices. - OfType() - .Where((tp) => tp.DefaultRoomKey.Equals(room.Key, StringComparison.InvariantCultureIgnoreCase)) - .Select(tp => tp.Key).ToList() - }; - - try - { - var zrcTp = DeviceManager.AllDevices.OfType().SingleOrDefault((tp) => tp.ZoomRoomController); + var zrcTp = DeviceManager.AllDevices.OfType().SingleOrDefault((tp) => tp.ZoomRoomController); - configuration.ZoomRoomControllerKey = zrcTp?.Key; - } - catch - { - configuration.ZoomRoomControllerKey = room.Key; - } + configuration.ZoomRoomControllerKey = zrcTp?.Key; + } + catch + { + configuration.ZoomRoomControllerKey = room.Key; + } - if (room is IHasCiscoNavigatorTouchpanel ciscoNavRoom) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Setting CiscoNavigatorKey to: {ciscoNavRoom.CiscoNavigatorTouchpanelKey}", this); - configuration.CiscoNavigatorKey = ciscoNavRoom.CiscoNavigatorTouchpanelKey; - } + if (room is IHasCiscoNavigatorTouchpanel ciscoNavRoom) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Setting CiscoNavigatorKey to: {ciscoNavRoom.CiscoNavigatorTouchpanelKey}", this); + configuration.CiscoNavigatorKey = ciscoNavRoom.CiscoNavigatorTouchpanelKey; + } - // find the room combiner for this room by checking if the room is in the list of rooms for the room combiner - var roomCombiner = DeviceManager.AllDevices.OfType().FirstOrDefault(); + // find the room combiner for this room by checking if the room is in the list of rooms for the room combiner + var roomCombiner = DeviceManager.AllDevices.OfType().FirstOrDefault(); - configuration.RoomCombinerKey = roomCombiner?.Key; + configuration.RoomCombinerKey = roomCombiner?.Key; - if (room is IEssentialsRoomPropertiesConfig propertiesConfig) - { - configuration.HelpMessage = propertiesConfig.PropertiesConfig.HelpMessageForDisplay; - } + if (room is IEssentialsRoomPropertiesConfig propertiesConfig) + { + configuration.HelpMessage = propertiesConfig.PropertiesConfig.HelpMessageForDisplay; + } - if (room is IEssentialsHuddleSpaceRoom huddleRoom && !string.IsNullOrEmpty(huddleRoom.PropertiesConfig.HelpMessageForDisplay)) - { - this.LogVerbose("Getting huddle room config"); - configuration.HelpMessage = huddleRoom.PropertiesConfig.HelpMessageForDisplay; - configuration.UiBehavior = huddleRoom.PropertiesConfig.UiBehavior; - configuration.DefaultPresentationSourceKey = huddleRoom.PropertiesConfig.DefaultSourceItem; + if (room is IEssentialsHuddleSpaceRoom huddleRoom && !string.IsNullOrEmpty(huddleRoom.PropertiesConfig.HelpMessageForDisplay)) + { + this.LogVerbose("Getting huddle room config"); + configuration.HelpMessage = huddleRoom.PropertiesConfig.HelpMessageForDisplay; + configuration.UiBehavior = huddleRoom.PropertiesConfig.UiBehavior; + configuration.DefaultPresentationSourceKey = huddleRoom.PropertiesConfig.DefaultSourceItem; - } + } - if (room is IEssentialsHuddleVtc1Room vtc1Room && !string.IsNullOrEmpty(vtc1Room.PropertiesConfig.HelpMessageForDisplay)) - { - this.LogVerbose("Getting vtc room config"); - configuration.HelpMessage = vtc1Room.PropertiesConfig.HelpMessageForDisplay; - configuration.UiBehavior = vtc1Room.PropertiesConfig.UiBehavior; - configuration.DefaultPresentationSourceKey = vtc1Room.PropertiesConfig.DefaultSourceItem; - } + if (room is IEssentialsHuddleVtc1Room vtc1Room && !string.IsNullOrEmpty(vtc1Room.PropertiesConfig.HelpMessageForDisplay)) + { + this.LogVerbose("Getting vtc room config"); + configuration.HelpMessage = vtc1Room.PropertiesConfig.HelpMessageForDisplay; + configuration.UiBehavior = vtc1Room.PropertiesConfig.UiBehavior; + configuration.DefaultPresentationSourceKey = vtc1Room.PropertiesConfig.DefaultSourceItem; + } - if (room is IEssentialsTechRoom techRoom && !string.IsNullOrEmpty(techRoom.PropertiesConfig.HelpMessage)) - { - this.LogVerbose("Getting tech room config"); - configuration.HelpMessage = techRoom.PropertiesConfig.HelpMessage; - } + if (room is IEssentialsTechRoom techRoom && !string.IsNullOrEmpty(techRoom.PropertiesConfig.HelpMessage)) + { + this.LogVerbose("Getting tech room config"); + configuration.HelpMessage = techRoom.PropertiesConfig.HelpMessage; + } - if (room is IHasVideoCodec vcRoom) + if (room is IHasVideoCodec vcRoom) + { + if (vcRoom.VideoCodec != null) { - if (vcRoom.VideoCodec != null) - { - this.LogVerbose("Getting codec config"); - var type = vcRoom.VideoCodec.GetType(); + this.LogVerbose("Getting codec config"); + var type = vcRoom.VideoCodec.GetType(); - configuration.HasVideoConferencing = true; - configuration.VideoCodecKey = vcRoom.VideoCodec.Key; - configuration.VideoCodecIsZoomRoom = type.Name.Equals("ZoomRoom", StringComparison.InvariantCultureIgnoreCase); - } + configuration.HasVideoConferencing = true; + configuration.VideoCodecKey = vcRoom.VideoCodec.Key; + configuration.VideoCodecIsZoomRoom = type.Name.Equals("ZoomRoom", StringComparison.InvariantCultureIgnoreCase); } - ; + } + ; - if (room is IHasAudioCodec acRoom) + if (room is IHasAudioCodec acRoom) + { + if (acRoom.AudioCodec != null) { - if (acRoom.AudioCodec != null) - { - this.LogVerbose("Getting audio codec config"); - configuration.HasAudioConferencing = true; - configuration.AudioCodecKey = acRoom.AudioCodec.Key; - } + this.LogVerbose("Getting audio codec config"); + configuration.HasAudioConferencing = true; + configuration.AudioCodecKey = acRoom.AudioCodec.Key; } + } - if (room is IHasMatrixRouting matrixRoutingRoom) - { - this.LogVerbose("Getting matrix routing config"); - configuration.MatrixRoutingKey = matrixRoutingRoom.MatrixRoutingDeviceKey; - configuration.EndpointKeys = matrixRoutingRoom.EndpointKeys; - } + if (room is IHasMatrixRouting matrixRoutingRoom) + { + this.LogVerbose("Getting matrix routing config"); + configuration.MatrixRoutingKey = matrixRoutingRoom.MatrixRoutingDeviceKey; + configuration.EndpointKeys = matrixRoutingRoom.EndpointKeys; + } + + if (room is IEnvironmentalControls envRoom) + { + this.LogVerbose("Getting environmental controls config. RoomHasEnvironmentalControls: {hasEnvironmentalControls}", envRoom.HasEnvironmentalControlDevices); + configuration.HasEnvironmentalControls = envRoom.HasEnvironmentalControlDevices; - if (room is IEnvironmentalControls envRoom) + if (envRoom.HasEnvironmentalControlDevices) { - this.LogVerbose("Getting environmental controls config. RoomHasEnvironmentalControls: {hasEnvironmentalControls}", envRoom.HasEnvironmentalControlDevices); - configuration.HasEnvironmentalControls = envRoom.HasEnvironmentalControlDevices; + this.LogVerbose("Room Has {count} Environmental Control Devices.", envRoom.EnvironmentalControlDevices.Count); - if (envRoom.HasEnvironmentalControlDevices) + foreach (var dev in envRoom.EnvironmentalControlDevices) { - this.LogVerbose("Room Has {count} Environmental Control Devices.", envRoom.EnvironmentalControlDevices.Count); + this.LogVerbose("Adding environmental device: {key}", dev.Key); + + eEnvironmentalDeviceTypes type = eEnvironmentalDeviceTypes.None; - foreach (var dev in envRoom.EnvironmentalControlDevices) + if (dev is ILightingScenes) { - this.LogVerbose("Adding environmental device: {key}", dev.Key); - - eEnvironmentalDeviceTypes type = eEnvironmentalDeviceTypes.None; - - if (dev is ILightingScenes) - { - type = eEnvironmentalDeviceTypes.Lighting; - } - else if (dev is ShadeBase || dev is IShadesOpenCloseStop || dev is IShadesOpenClosePreset) - { - type = eEnvironmentalDeviceTypes.Shade; - } - else if (dev is IShades) - { - type = eEnvironmentalDeviceTypes.ShadeController; - } - else if (dev is ISwitchedOutput) - { - type = eEnvironmentalDeviceTypes.Relay; - } - - this.LogVerbose("Environmental Device Type: {type}", type); - - var envDevice = new EnvironmentalDeviceConfiguration(dev.Key, type); - - configuration.EnvironmentalDevices.Add(envDevice); + type = eEnvironmentalDeviceTypes.Lighting; + } + else if (dev is ShadeBase || dev is IShadesOpenCloseStop || dev is IShadesOpenClosePreset) + { + type = eEnvironmentalDeviceTypes.Shade; + } + else if (dev is IShades) + { + type = eEnvironmentalDeviceTypes.ShadeController; + } + else if (dev is ISwitchedOutput) + { + type = eEnvironmentalDeviceTypes.Relay; } - } - else - { - this.LogVerbose("Room Has No Environmental Control Devices"); - } - } - - if (room is IHasDefaultDisplay defDisplayRoom) - { - this.LogVerbose("Getting default display config"); - configuration.DefaultDisplayKey = defDisplayRoom.DefaultDisplay.Key; - configuration.Destinations.Add(eSourceListItemDestinationTypes.defaultDisplay, defDisplayRoom.DefaultDisplay.Key); - } - if (room is IHasMultipleDisplays multiDisplayRoom) - { - this.LogVerbose("Getting multiple display config"); + this.LogVerbose("Environmental Device Type: {type}", type); - if (multiDisplayRoom.Displays == null) - { - this.LogVerbose("Displays collection is null"); - } - else - { - this.LogVerbose("Displays collection exists"); + var envDevice = new EnvironmentalDeviceConfiguration(dev.Key, type); - configuration.Destinations = multiDisplayRoom.Displays.ToDictionary(kv => kv.Key, kv => kv.Value.Key); + configuration.EnvironmentalDevices.Add(envDevice); } } - - if (room is IHasAccessoryDevices accRoom) + else { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Getting accessory devices config", this); + this.LogVerbose("Room Has No Environmental Control Devices"); + } + } - if (accRoom.AccessoryDeviceKeys == null) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Accessory devices collection is null", this); - } - else - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Accessory devices collection exists", this); + if (room is IHasDefaultDisplay defDisplayRoom) + { + this.LogVerbose("Getting default display config"); + configuration.DefaultDisplayKey = defDisplayRoom.DefaultDisplay.Key; + configuration.Destinations.Add(eSourceListItemDestinationTypes.defaultDisplay, defDisplayRoom.DefaultDisplay.Key); + } - configuration.AccessoryDeviceKeys = accRoom.AccessoryDeviceKeys; - } - } + if (room is IHasMultipleDisplays multiDisplayRoom) + { + this.LogVerbose("Getting multiple display config"); - var sourceList = ConfigReader.ConfigObject.GetSourceListForKey(room.SourceListKey); - if (sourceList != null) + if (multiDisplayRoom.Displays == null) + { + this.LogVerbose("Displays collection is null"); + } + else { - this.LogVerbose("Getting source list config"); - configuration.SourceList = sourceList; - configuration.HasRoutingControls = true; + this.LogVerbose("Displays collection exists"); - foreach (var source in sourceList) - { - if (source.Value.SourceDevice is Devices.Common.IRSetTopBoxBase) - { - configuration.HasSetTopBoxControls = true; - continue; - } - else if (source.Value.SourceDevice is CameraBase) - { - configuration.HasCameraControls = true; - continue; - } - } + configuration.Destinations = multiDisplayRoom.Displays.ToDictionary(kv => kv.Key, kv => kv.Value.Key); } + } - var destinationList = ConfigReader.ConfigObject.GetDestinationListForKey(room.DestinationListKey); + if (room is IHasAccessoryDevices accRoom) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Getting accessory devices config", this); - if (destinationList != null) + if (accRoom.AccessoryDeviceKeys == null) { - configuration.DestinationList = destinationList; + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Accessory devices collection is null", this); } - - var audioControlPointList = ConfigReader.ConfigObject.GetAudioControlPointListForKey(room.AudioControlPointListKey); - - if (audioControlPointList != null) + else { - configuration.AudioControlPointList = audioControlPointList; + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Accessory devices collection exists", this); + + configuration.AccessoryDeviceKeys = accRoom.AccessoryDeviceKeys; } + } - var cameraList = ConfigReader.ConfigObject.GetCameraListForKey(room.CameraListKey); + var sourceList = ConfigReader.ConfigObject.GetSourceListForKey(room.SourceListKey); + if (sourceList != null) + { + this.LogVerbose("Getting source list config"); + configuration.SourceList = sourceList; + configuration.HasRoutingControls = true; - if (cameraList != null) + foreach (var source in sourceList) { - configuration.CameraList = cameraList; + if (source.Value.SourceDevice is Devices.Common.IRSetTopBoxBase) + { + configuration.HasSetTopBoxControls = true; + continue; + } + else if (source.Value.SourceDevice is CameraBase) + { + configuration.HasCameraControls = true; + continue; + } } + } - return configuration; + var destinationList = ConfigReader.ConfigObject.GetDestinationListForKey(room.DestinationListKey); + if (destinationList != null) + { + configuration.DestinationList = destinationList; } - catch (Exception ex) + + var audioControlPointList = ConfigReader.ConfigObject.GetAudioControlPointListForKey(room.AudioControlPointListKey); + + if (audioControlPointList != null) { - Debug.LogMessage(ex, "Exception getting room configuration"); - return new RoomConfiguration(); + configuration.AudioControlPointList = audioControlPointList; } - } - } + var cameraList = ConfigReader.ConfigObject.GetCameraListForKey(room.CameraListKey); - public class RoomStateMessage : DeviceStateMessageBase - { - [JsonProperty("configuration", NullValueHandling = NullValueHandling.Ignore)] - public RoomConfiguration Configuration { get; set; } - - [JsonProperty("activityMode", NullValueHandling = NullValueHandling.Ignore)] - public int? ActivityMode { get; set; } - [JsonProperty("advancedSharingActive", NullValueHandling = NullValueHandling.Ignore)] - public bool? AdvancedSharingActive { get; set; } - [JsonProperty("isOn", NullValueHandling = NullValueHandling.Ignore)] - public bool? IsOn { get; set; } - [JsonProperty("isWarmingUp", NullValueHandling = NullValueHandling.Ignore)] - public bool? IsWarmingUp { get; set; } - [JsonProperty("isCoolingDown", NullValueHandling = NullValueHandling.Ignore)] - public bool? IsCoolingDown { get; set; } - [JsonProperty("selectedSourceKey", NullValueHandling = NullValueHandling.Ignore)] - public string SelectedSourceKey { get; set; } - [JsonProperty("share", NullValueHandling = NullValueHandling.Ignore)] - public ShareState Share { get; set; } - - [JsonProperty("volumes", NullValueHandling = NullValueHandling.Ignore)] - public Dictionary Volumes { get; set; } - - [JsonProperty("isInCall", NullValueHandling = NullValueHandling.Ignore)] - public bool? IsInCall { get; set; } - } + if (cameraList != null) + { + configuration.CameraList = cameraList; + } - public class ShareState - { - [JsonProperty("currentShareText", NullValueHandling = NullValueHandling.Ignore)] - public string CurrentShareText { get; set; } - [JsonProperty("enabled", NullValueHandling = NullValueHandling.Ignore)] - public bool? Enabled { get; set; } - [JsonProperty("isSharing", NullValueHandling = NullValueHandling.Ignore)] - public bool? IsSharing { get; set; } - } + return configuration; - /// - /// Represents the capabilities of the room and the associated device info - /// - public class RoomConfiguration - { - //[JsonProperty("shutdownPromptSeconds", NullValueHandling = NullValueHandling.Ignore)] - //public int? ShutdownPromptSeconds { get; set; } - - [JsonProperty("hasVideoConferencing", NullValueHandling = NullValueHandling.Ignore)] - public bool? HasVideoConferencing { get; set; } - [JsonProperty("videoCodecIsZoomRoom", NullValueHandling = NullValueHandling.Ignore)] - public bool? VideoCodecIsZoomRoom { get; set; } - [JsonProperty("hasAudioConferencing", NullValueHandling = NullValueHandling.Ignore)] - public bool? HasAudioConferencing { get; set; } - [JsonProperty("hasEnvironmentalControls", NullValueHandling = NullValueHandling.Ignore)] - public bool? HasEnvironmentalControls { get; set; } - [JsonProperty("hasCameraControls", NullValueHandling = NullValueHandling.Ignore)] - public bool? HasCameraControls { get; set; } - [JsonProperty("hasSetTopBoxControls", NullValueHandling = NullValueHandling.Ignore)] - public bool? HasSetTopBoxControls { get; set; } - [JsonProperty("hasRoutingControls", NullValueHandling = NullValueHandling.Ignore)] - public bool? HasRoutingControls { get; set; } - - [JsonProperty("touchpanelKeys", NullValueHandling = NullValueHandling.Ignore)] - public List TouchpanelKeys { get; set; } - - [JsonProperty("zoomRoomControllerKey", NullValueHandling = NullValueHandling.Ignore)] - public string ZoomRoomControllerKey { get; set; } - - [JsonProperty("ciscoNavigatorKey", NullValueHandling = NullValueHandling.Ignore)] - public string CiscoNavigatorKey { get; set; } - - - [JsonProperty("videoCodecKey", NullValueHandling = NullValueHandling.Ignore)] - public string VideoCodecKey { get; set; } - [JsonProperty("audioCodecKey", NullValueHandling = NullValueHandling.Ignore)] - public string AudioCodecKey { get; set; } - [JsonProperty("matrixRoutingKey", NullValueHandling = NullValueHandling.Ignore)] - public string MatrixRoutingKey { get; set; } - [JsonProperty("endpointKeys", NullValueHandling = NullValueHandling.Ignore)] - public List EndpointKeys { get; set; } - - [JsonProperty("accessoryDeviceKeys", NullValueHandling = NullValueHandling.Ignore)] - public List AccessoryDeviceKeys { get; set; } - - [JsonProperty("defaultDisplayKey", NullValueHandling = NullValueHandling.Ignore)] - public string DefaultDisplayKey { get; set; } - [JsonProperty("destinations", NullValueHandling = NullValueHandling.Ignore)] - public Dictionary Destinations { get; set; } - [JsonProperty("environmentalDevices", NullValueHandling = NullValueHandling.Ignore)] - public List EnvironmentalDevices { get; set; } - [JsonProperty("sourceList", NullValueHandling = NullValueHandling.Ignore)] - public Dictionary SourceList { get; set; } - - [JsonProperty("destinationList", NullValueHandling = NullValueHandling.Ignore)] - public Dictionary DestinationList { get; set; } - - [JsonProperty("audioControlPointList", NullValueHandling = NullValueHandling.Ignore)] - public AudioControlPointListItem AudioControlPointList { get; set; } - - [JsonProperty("cameraList", NullValueHandling = NullValueHandling.Ignore)] - public Dictionary CameraList { get; set; } - - [JsonProperty("defaultPresentationSourceKey", NullValueHandling = NullValueHandling.Ignore)] - public string DefaultPresentationSourceKey { get; set; } - - - [JsonProperty("helpMessage", NullValueHandling = NullValueHandling.Ignore)] - public string HelpMessage { get; set; } - - [JsonProperty("techPassword", NullValueHandling = NullValueHandling.Ignore)] - public string TechPassword { get; set; } - - [JsonProperty("uiBehavior", NullValueHandling = NullValueHandling.Ignore)] - public EssentialsRoomUiBehaviorConfig UiBehavior { get; set; } - - [JsonProperty("supportsAdvancedSharing", NullValueHandling = NullValueHandling.Ignore)] - public bool? SupportsAdvancedSharing { get; set; } - [JsonProperty("userCanChangeShareMode", NullValueHandling = NullValueHandling.Ignore)] - public bool? UserCanChangeShareMode { get; set; } - - [JsonProperty("roomCombinerKey", NullValueHandling = NullValueHandling.Ignore)] - public string RoomCombinerKey { get; set; } - - public RoomConfiguration() + } + catch (Exception ex) { - Destinations = new Dictionary(); - EnvironmentalDevices = new List(); - SourceList = new Dictionary(); - TouchpanelKeys = new List(); + Debug.LogMessage(ex, "Exception getting room configuration"); + return new RoomConfiguration(); } } - public class EnvironmentalDeviceConfiguration +} + +public class RoomStateMessage : DeviceStateMessageBase +{ + [JsonProperty("configuration", NullValueHandling = NullValueHandling.Ignore)] + public RoomConfiguration Configuration { get; set; } + + [JsonProperty("activityMode", NullValueHandling = NullValueHandling.Ignore)] + public int? ActivityMode { get; set; } + [JsonProperty("advancedSharingActive", NullValueHandling = NullValueHandling.Ignore)] + public bool? AdvancedSharingActive { get; set; } + [JsonProperty("isOn", NullValueHandling = NullValueHandling.Ignore)] + public bool? IsOn { get; set; } + [JsonProperty("isWarmingUp", NullValueHandling = NullValueHandling.Ignore)] + public bool? IsWarmingUp { get; set; } + [JsonProperty("isCoolingDown", NullValueHandling = NullValueHandling.Ignore)] + public bool? IsCoolingDown { get; set; } + [JsonProperty("selectedSourceKey", NullValueHandling = NullValueHandling.Ignore)] + public string SelectedSourceKey { get; set; } + [JsonProperty("share", NullValueHandling = NullValueHandling.Ignore)] + public ShareState Share { get; set; } + + [JsonProperty("volumes", NullValueHandling = NullValueHandling.Ignore)] + public Dictionary Volumes { get; set; } + + [JsonProperty("isInCall", NullValueHandling = NullValueHandling.Ignore)] + public bool? IsInCall { get; set; } +} + +public class ShareState +{ + [JsonProperty("currentShareText", NullValueHandling = NullValueHandling.Ignore)] + public string CurrentShareText { get; set; } + [JsonProperty("enabled", NullValueHandling = NullValueHandling.Ignore)] + public bool? Enabled { get; set; } + [JsonProperty("isSharing", NullValueHandling = NullValueHandling.Ignore)] + public bool? IsSharing { get; set; } +} + +/// +/// Represents the capabilities of the room and the associated device info +/// +public class RoomConfiguration +{ + //[JsonProperty("shutdownPromptSeconds", NullValueHandling = NullValueHandling.Ignore)] + //public int? ShutdownPromptSeconds { get; set; } + + [JsonProperty("hasVideoConferencing", NullValueHandling = NullValueHandling.Ignore)] + public bool? HasVideoConferencing { get; set; } + [JsonProperty("videoCodecIsZoomRoom", NullValueHandling = NullValueHandling.Ignore)] + public bool? VideoCodecIsZoomRoom { get; set; } + [JsonProperty("hasAudioConferencing", NullValueHandling = NullValueHandling.Ignore)] + public bool? HasAudioConferencing { get; set; } + [JsonProperty("hasEnvironmentalControls", NullValueHandling = NullValueHandling.Ignore)] + public bool? HasEnvironmentalControls { get; set; } + [JsonProperty("hasCameraControls", NullValueHandling = NullValueHandling.Ignore)] + public bool? HasCameraControls { get; set; } + [JsonProperty("hasSetTopBoxControls", NullValueHandling = NullValueHandling.Ignore)] + public bool? HasSetTopBoxControls { get; set; } + [JsonProperty("hasRoutingControls", NullValueHandling = NullValueHandling.Ignore)] + public bool? HasRoutingControls { get; set; } + + [JsonProperty("touchpanelKeys", NullValueHandling = NullValueHandling.Ignore)] + public List TouchpanelKeys { get; set; } + + [JsonProperty("zoomRoomControllerKey", NullValueHandling = NullValueHandling.Ignore)] + public string ZoomRoomControllerKey { get; set; } + + [JsonProperty("ciscoNavigatorKey", NullValueHandling = NullValueHandling.Ignore)] + public string CiscoNavigatorKey { get; set; } + + + [JsonProperty("videoCodecKey", NullValueHandling = NullValueHandling.Ignore)] + public string VideoCodecKey { get; set; } + [JsonProperty("audioCodecKey", NullValueHandling = NullValueHandling.Ignore)] + public string AudioCodecKey { get; set; } + [JsonProperty("matrixRoutingKey", NullValueHandling = NullValueHandling.Ignore)] + public string MatrixRoutingKey { get; set; } + [JsonProperty("endpointKeys", NullValueHandling = NullValueHandling.Ignore)] + public List EndpointKeys { get; set; } + + [JsonProperty("accessoryDeviceKeys", NullValueHandling = NullValueHandling.Ignore)] + public List AccessoryDeviceKeys { get; set; } + + [JsonProperty("defaultDisplayKey", NullValueHandling = NullValueHandling.Ignore)] + public string DefaultDisplayKey { get; set; } + [JsonProperty("destinations", NullValueHandling = NullValueHandling.Ignore)] + public Dictionary Destinations { get; set; } + [JsonProperty("environmentalDevices", NullValueHandling = NullValueHandling.Ignore)] + public List EnvironmentalDevices { get; set; } + [JsonProperty("sourceList", NullValueHandling = NullValueHandling.Ignore)] + public Dictionary SourceList { get; set; } + + [JsonProperty("destinationList", NullValueHandling = NullValueHandling.Ignore)] + public Dictionary DestinationList { get; set; } + + [JsonProperty("audioControlPointList", NullValueHandling = NullValueHandling.Ignore)] + public AudioControlPointListItem AudioControlPointList { get; set; } + + [JsonProperty("cameraList", NullValueHandling = NullValueHandling.Ignore)] + public Dictionary CameraList { get; set; } + + [JsonProperty("defaultPresentationSourceKey", NullValueHandling = NullValueHandling.Ignore)] + public string DefaultPresentationSourceKey { get; set; } + + + [JsonProperty("helpMessage", NullValueHandling = NullValueHandling.Ignore)] + public string HelpMessage { get; set; } + + [JsonProperty("techPassword", NullValueHandling = NullValueHandling.Ignore)] + public string TechPassword { get; set; } + + [JsonProperty("uiBehavior", NullValueHandling = NullValueHandling.Ignore)] + public EssentialsRoomUiBehaviorConfig UiBehavior { get; set; } + + [JsonProperty("supportsAdvancedSharing", NullValueHandling = NullValueHandling.Ignore)] + public bool? SupportsAdvancedSharing { get; set; } + [JsonProperty("userCanChangeShareMode", NullValueHandling = NullValueHandling.Ignore)] + public bool? UserCanChangeShareMode { get; set; } + + [JsonProperty("roomCombinerKey", NullValueHandling = NullValueHandling.Ignore)] + public string RoomCombinerKey { get; set; } + + public RoomConfiguration() { - [JsonProperty("deviceKey", NullValueHandling = NullValueHandling.Ignore)] - public string DeviceKey { get; private set; } + Destinations = new Dictionary(); + EnvironmentalDevices = new List(); + SourceList = new Dictionary(); + TouchpanelKeys = new List(); + } +} - [JsonConverter(typeof(StringEnumConverter))] - [JsonProperty("deviceType", NullValueHandling = NullValueHandling.Ignore)] - public eEnvironmentalDeviceTypes DeviceType { get; private set; } +public class EnvironmentalDeviceConfiguration +{ + [JsonProperty("deviceKey", NullValueHandling = NullValueHandling.Ignore)] + public string DeviceKey { get; private set; } - public EnvironmentalDeviceConfiguration(string key, eEnvironmentalDeviceTypes type) - { - DeviceKey = key; - DeviceType = type; - } - } + [JsonConverter(typeof(StringEnumConverter))] + [JsonProperty("deviceType", NullValueHandling = NullValueHandling.Ignore)] + public eEnvironmentalDeviceTypes DeviceType { get; private set; } - public enum eEnvironmentalDeviceTypes + public EnvironmentalDeviceConfiguration(string key, eEnvironmentalDeviceTypes type) { - None, - Lighting, - Shade, - ShadeController, - Relay, + DeviceKey = key; + DeviceType = type; } +} - public class ApiTouchPanelToken - { - [JsonProperty("touchPanels", NullValueHandling = NullValueHandling.Ignore)] - public List TouchPanels { get; set; } = new List(); +public enum eEnvironmentalDeviceTypes +{ + None, + Lighting, + Shade, + ShadeController, + Relay, +} + +public class ApiTouchPanelToken +{ + [JsonProperty("touchPanels", NullValueHandling = NullValueHandling.Ignore)] + public List TouchPanels { get; set; } = new List(); - [JsonProperty("userAppUrl", NullValueHandling = NullValueHandling.Ignore)] - public string UserAppUrl { get; set; } = ""; - } + [JsonProperty("userAppUrl", NullValueHandling = NullValueHandling.Ignore)] + public string UserAppUrl { get; set; } = ""; +} #if SERIES3 - public class SourceSelectMessageContent - { - public string SourceListItem { get; set; } - public string SourceListKey { get; set; } - } - - public class DirectRoute - { - public string SourceKey { get; set; } - public string DestinationKey { get; set; } - } +public class SourceSelectMessageContent +{ + public string SourceListItem { get; set; } + public string SourceListKey { get; set; } +} - /// - /// - /// - /// - public delegate void PressAndHoldAction(bool b); +public class DirectRoute +{ + public string SourceKey { get; set; } + public string DestinationKey { get; set; } +} + +/// +/// +/// +/// +public delegate void PressAndHoldAction(bool b); #endif -} \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl/Services/MobileControlApiService.cs b/src/PepperDash.Essentials.MobileControl/Services/MobileControlApiService.cs index 262c7e07f..2872dd667 100644 --- a/src/PepperDash.Essentials.MobileControl/Services/MobileControlApiService.cs +++ b/src/PepperDash.Essentials.MobileControl/Services/MobileControlApiService.cs @@ -3,75 +3,74 @@ using System.Net.Http; using System.Threading.Tasks; -namespace PepperDash.Essentials.Services +namespace PepperDash.Essentials.Services; + + +public class MobileControlApiService { + private readonly HttpClient _client; - public class MobileControlApiService + public MobileControlApiService(string apiUrl) { - private readonly HttpClient _client; - - public MobileControlApiService(string apiUrl) + var handler = new HttpClientHandler { - var handler = new HttpClientHandler - { - AllowAutoRedirect = false, - ServerCertificateCustomValidationCallback = (req, cert, certChain, errors) => true - }; + AllowAutoRedirect = false, + ServerCertificateCustomValidationCallback = (req, cert, certChain, errors) => true + }; - _client = new HttpClient(handler); - } + _client = new HttpClient(handler); + } - public async Task SendAuthorizationRequest(string apiUrl, string grantCode, string systemUuid) + public async Task SendAuthorizationRequest(string apiUrl, string grantCode, string systemUuid) + { + try { - try - { - var request = new HttpRequestMessage(HttpMethod.Get, $"{apiUrl}/system/{systemUuid}/authorize?grantCode={grantCode}"); - - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Sending authorization request to {host}", null, request.RequestUri); - - var response = await _client.SendAsync(request); - - var authResponse = new AuthorizationResponse - { - Authorized = response.StatusCode == System.Net.HttpStatusCode.OK - }; + var request = new HttpRequestMessage(HttpMethod.Get, $"{apiUrl}/system/{systemUuid}/authorize?grantCode={grantCode}"); - if (authResponse.Authorized) - { - return authResponse; - } + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Sending authorization request to {host}", null, request.RequestUri); - if (response.StatusCode == System.Net.HttpStatusCode.Moved) - { - var location = response.Headers.Location; + var response = await _client.SendAsync(request); - authResponse.Reason = $"ERROR: Mobile Control API has moved. Please adjust configuration to \"{location}\""; + var authResponse = new AuthorizationResponse + { + Authorized = response.StatusCode == System.Net.HttpStatusCode.OK + }; - return authResponse; - } + if (authResponse.Authorized) + { + return authResponse; + } - var responseString = await response.Content.ReadAsStringAsync(); + if (response.StatusCode == System.Net.HttpStatusCode.Moved) + { + var location = response.Headers.Location; - switch (responseString) - { - case "codeNotFound": - authResponse.Reason = $"Authorization failed. Code not found for system UUID {systemUuid}"; - break; - case "uuidNotFound": - authResponse.Reason = $"Authorization failed. System UUID {systemUuid} not found. Check Essentials configuration."; - break; - default: - authResponse.Reason = $"Authorization failed. Response {response.StatusCode}: {responseString}"; - break; - } + authResponse.Reason = $"ERROR: Mobile Control API has moved. Please adjust configuration to \"{location}\""; return authResponse; } - catch (Exception ex) + + var responseString = await response.Content.ReadAsStringAsync(); + + switch (responseString) { - Debug.LogMessage(ex, "Error authorizing with Mobile Control"); - return new AuthorizationResponse { Authorized = false, Reason = ex.Message }; + case "codeNotFound": + authResponse.Reason = $"Authorization failed. Code not found for system UUID {systemUuid}"; + break; + case "uuidNotFound": + authResponse.Reason = $"Authorization failed. System UUID {systemUuid} not found. Check Essentials configuration."; + break; + default: + authResponse.Reason = $"Authorization failed. Response {response.StatusCode}: {responseString}"; + break; } + + return authResponse; + } + catch (Exception ex) + { + Debug.LogMessage(ex, "Error authorizing with Mobile Control"); + return new AuthorizationResponse { Authorized = false, Reason = ex.Message }; } } } diff --git a/src/PepperDash.Essentials.MobileControl/Touchpanel/ITheme.cs b/src/PepperDash.Essentials.MobileControl/Touchpanel/ITheme.cs index 7dc4ae16d..918ae2f25 100644 --- a/src/PepperDash.Essentials.MobileControl/Touchpanel/ITheme.cs +++ b/src/PepperDash.Essentials.MobileControl/Touchpanel/ITheme.cs @@ -1,11 +1,10 @@ using PepperDash.Core; -namespace PepperDash.Essentials.Touchpanel +namespace PepperDash.Essentials.Touchpanel; + +public interface ITheme : IKeyed { - public interface ITheme : IKeyed - { - string Theme { get; } + string Theme { get; } - void UpdateTheme(string theme); - } + void UpdateTheme(string theme); } diff --git a/src/PepperDash.Essentials.MobileControl/Touchpanel/ITswAppControl.cs b/src/PepperDash.Essentials.MobileControl/Touchpanel/ITswAppControl.cs index 814b51c6e..886ac6bb2 100644 --- a/src/PepperDash.Essentials.MobileControl/Touchpanel/ITswAppControl.cs +++ b/src/PepperDash.Essentials.MobileControl/Touchpanel/ITswAppControl.cs @@ -1,25 +1,24 @@ using PepperDash.Core; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Touchpanel +namespace PepperDash.Essentials.Touchpanel; + +public interface ITswAppControl : IKeyed { - public interface ITswAppControl : IKeyed - { - BoolFeedback AppOpenFeedback { get; } + BoolFeedback AppOpenFeedback { get; } - void HideOpenApp(); + void HideOpenApp(); - void CloseOpenApp(); + void CloseOpenApp(); - void OpenApp(); - } + void OpenApp(); +} - public interface ITswZoomControl : IKeyed - { - BoolFeedback ZoomIncomingCallFeedback { get; } +public interface ITswZoomControl : IKeyed +{ + BoolFeedback ZoomIncomingCallFeedback { get; } - BoolFeedback ZoomInCallFeedback { get; } + BoolFeedback ZoomInCallFeedback { get; } - void EndZoomCall(); - } + void EndZoomCall(); } diff --git a/src/PepperDash.Essentials.MobileControl/Touchpanel/ITswAppControlMessenger.cs b/src/PepperDash.Essentials.MobileControl/Touchpanel/ITswAppControlMessenger.cs index 19e04775b..c2f397676 100644 --- a/src/PepperDash.Essentials.MobileControl/Touchpanel/ITswAppControlMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl/Touchpanel/ITswAppControlMessenger.cs @@ -4,56 +4,55 @@ using PepperDash.Core.Logging; using PepperDash.Essentials.AppServer.Messengers; -namespace PepperDash.Essentials.Touchpanel +namespace PepperDash.Essentials.Touchpanel; + +public class ITswAppControlMessenger : MessengerBase { - public class ITswAppControlMessenger : MessengerBase + private readonly ITswAppControl _appControl; + + public ITswAppControlMessenger(string key, string messagePath, Device device) : base(key, messagePath, device) { - private readonly ITswAppControl _appControl; + _appControl = device as ITswAppControl; + } - public ITswAppControlMessenger(string key, string messagePath, Device device) : base(key, messagePath, device) + protected override void RegisterActions() + { + if (_appControl == null) { - _appControl = device as ITswAppControl; + this.LogInformation("{deviceKey} does not implement ITswAppControl", _device.Key); + return; } - protected override void RegisterActions() - { - if (_appControl == null) - { - this.LogInformation("{deviceKey} does not implement ITswAppControl", _device.Key); - return; - } - - AddAction($"/fullStatus", (id, context) => SendFullStatus()); + AddAction($"/fullStatus", (id, context) => SendFullStatus()); - AddAction($"/openApp", (id, context) => _appControl.OpenApp()); + AddAction($"/openApp", (id, context) => _appControl.OpenApp()); - AddAction($"/closeApp", (id, context) => _appControl.CloseOpenApp()); + AddAction($"/closeApp", (id, context) => _appControl.CloseOpenApp()); - AddAction($"/hideApp", (id, context) => _appControl.HideOpenApp()); + AddAction($"/hideApp", (id, context) => _appControl.HideOpenApp()); - _appControl.AppOpenFeedback.OutputChange += (s, a) => - { - PostStatusMessage(JToken.FromObject(new - { - appOpen = a.BoolValue - })); - }; - } - - private void SendFullStatus() + _appControl.AppOpenFeedback.OutputChange += (s, a) => { - var message = new TswAppStateMessage + PostStatusMessage(JToken.FromObject(new { - AppOpen = _appControl.AppOpenFeedback.BoolValue, - }; - - PostStatusMessage(message); - } + appOpen = a.BoolValue + })); + }; } - public class TswAppStateMessage : DeviceStateMessageBase + private void SendFullStatus() { - [JsonProperty("appOpen", NullValueHandling = NullValueHandling.Ignore)] - public bool? AppOpen { get; set; } + var message = new TswAppStateMessage + { + AppOpen = _appControl.AppOpenFeedback.BoolValue, + }; + + PostStatusMessage(message); } } + +public class TswAppStateMessage : DeviceStateMessageBase +{ + [JsonProperty("appOpen", NullValueHandling = NullValueHandling.Ignore)] + public bool? AppOpen { get; set; } +} diff --git a/src/PepperDash.Essentials.MobileControl/Touchpanel/ITswZoomControlMessenger.cs b/src/PepperDash.Essentials.MobileControl/Touchpanel/ITswZoomControlMessenger.cs index cbd4f6a21..da62a198c 100644 --- a/src/PepperDash.Essentials.MobileControl/Touchpanel/ITswZoomControlMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl/Touchpanel/ITswZoomControlMessenger.cs @@ -5,69 +5,68 @@ using PepperDash.Essentials.AppServer.Messengers; -namespace PepperDash.Essentials.Touchpanel +namespace PepperDash.Essentials.Touchpanel; + +public class ITswZoomControlMessenger : MessengerBase { - public class ITswZoomControlMessenger : MessengerBase + private readonly ITswZoomControl _zoomControl; + + public ITswZoomControlMessenger(string key, string messagePath, Device device) : base(key, messagePath, device) { - private readonly ITswZoomControl _zoomControl; + _zoomControl = device as ITswZoomControl; + } - public ITswZoomControlMessenger(string key, string messagePath, Device device) : base(key, messagePath, device) + protected override void RegisterActions() + { + if (_zoomControl == null) { - _zoomControl = device as ITswZoomControl; + this.LogInformation("{deviceKey} does not implement ITswZoomControl", _device.Key); + return; } - protected override void RegisterActions() - { - if (_zoomControl == null) - { - this.LogInformation("{deviceKey} does not implement ITswZoomControl", _device.Key); - return; - } - - AddAction($"/fullStatus", (id, context) => SendFullStatus()); + AddAction($"/fullStatus", (id, context) => SendFullStatus()); - AddAction($"/endCall", (id, context) => _zoomControl.EndZoomCall()); + AddAction($"/endCall", (id, context) => _zoomControl.EndZoomCall()); - _zoomControl.ZoomIncomingCallFeedback.OutputChange += (s, a) => + _zoomControl.ZoomIncomingCallFeedback.OutputChange += (s, a) => + { + PostStatusMessage(JToken.FromObject(new { - PostStatusMessage(JToken.FromObject(new - { - incomingCall = a.BoolValue, - inCall = _zoomControl.ZoomInCallFeedback.BoolValue - })); - }; - + incomingCall = a.BoolValue, + inCall = _zoomControl.ZoomInCallFeedback.BoolValue + })); + }; - _zoomControl.ZoomInCallFeedback.OutputChange += (s, a) => - { - PostStatusMessage(JToken.FromObject( - new - { - inCall = a.BoolValue, - incomingCall = _zoomControl.ZoomIncomingCallFeedback.BoolValue - })); - }; - } - private void SendFullStatus() + _zoomControl.ZoomInCallFeedback.OutputChange += (s, a) => { - var message = new TswZoomStateMessage + PostStatusMessage(JToken.FromObject( + new { - InCall = _zoomControl?.ZoomInCallFeedback.BoolValue, - IncomingCall = _zoomControl?.ZoomIncomingCallFeedback.BoolValue - }; - - PostStatusMessage(message); - } + inCall = a.BoolValue, + incomingCall = _zoomControl.ZoomIncomingCallFeedback.BoolValue + })); + }; } - public class TswZoomStateMessage : DeviceStateMessageBase + private void SendFullStatus() { - [JsonProperty("inCall", NullValueHandling = NullValueHandling.Ignore)] - public bool? InCall { get; set; } + var message = new TswZoomStateMessage + { + InCall = _zoomControl?.ZoomInCallFeedback.BoolValue, + IncomingCall = _zoomControl?.ZoomIncomingCallFeedback.BoolValue + }; - [JsonProperty("incomingCall", NullValueHandling = NullValueHandling.Ignore)] - public bool? IncomingCall { get; set; } + PostStatusMessage(message); } } + +public class TswZoomStateMessage : DeviceStateMessageBase +{ + [JsonProperty("inCall", NullValueHandling = NullValueHandling.Ignore)] + public bool? InCall { get; set; } + + [JsonProperty("incomingCall", NullValueHandling = NullValueHandling.Ignore)] + public bool? IncomingCall { get; set; } +} diff --git a/src/PepperDash.Essentials.MobileControl/Touchpanel/MobileControlTouchpanelController.cs b/src/PepperDash.Essentials.MobileControl/Touchpanel/MobileControlTouchpanelController.cs index 9acd04f40..1f36b1edf 100644 --- a/src/PepperDash.Essentials.MobileControl/Touchpanel/MobileControlTouchpanelController.cs +++ b/src/PepperDash.Essentials.MobileControl/Touchpanel/MobileControlTouchpanelController.cs @@ -15,560 +15,559 @@ using System.Linq; using Feedback = PepperDash.Essentials.Core.Feedback; -namespace PepperDash.Essentials.Touchpanel -{ - //public interface IMobileControlTouchpanelController - //{ - // StringFeedback AppUrlFeedback { get; } - // string DefaultRoomKey { get; } - // string DeviceKey { get; } - //} +namespace PepperDash.Essentials.Touchpanel; +//public interface IMobileControlTouchpanelController +//{ +// StringFeedback AppUrlFeedback { get; } +// string DefaultRoomKey { get; } +// string DeviceKey { get; } +//} - public class MobileControlTouchpanelController : TouchpanelBase, IHasFeedback, ITswAppControl, ITswZoomControl, IDeviceInfoProvider, IMobileControlTouchpanelController, ITheme - { - private readonly MobileControlTouchpanelProperties localConfig; - private IMobileControlRoomMessenger _bridge; - private string _appUrl; +public class MobileControlTouchpanelController : TouchpanelBase, IHasFeedback, ITswAppControl, ITswZoomControl, IDeviceInfoProvider, IMobileControlTouchpanelController, ITheme +{ + private readonly MobileControlTouchpanelProperties localConfig; + private IMobileControlRoomMessenger _bridge; - public StringFeedback AppUrlFeedback { get; private set; } - private readonly StringFeedback QrCodeUrlFeedback; - private readonly StringFeedback McServerUrlFeedback; - private readonly StringFeedback UserCodeFeedback; + private string _appUrl; - private readonly BoolFeedback _appOpenFeedback; + public StringFeedback AppUrlFeedback { get; private set; } + private readonly StringFeedback QrCodeUrlFeedback; + private readonly StringFeedback McServerUrlFeedback; + private readonly StringFeedback UserCodeFeedback; - public BoolFeedback AppOpenFeedback => _appOpenFeedback; + private readonly BoolFeedback _appOpenFeedback; - private readonly BoolFeedback _zoomIncomingCallFeedback; + public BoolFeedback AppOpenFeedback => _appOpenFeedback; - public BoolFeedback ZoomIncomingCallFeedback => _zoomIncomingCallFeedback; + private readonly BoolFeedback _zoomIncomingCallFeedback; - private readonly BoolFeedback _zoomInCallFeedback; + public BoolFeedback ZoomIncomingCallFeedback => _zoomIncomingCallFeedback; - public event DeviceInfoChangeHandler DeviceInfoChanged; + private readonly BoolFeedback _zoomInCallFeedback; - public BoolFeedback ZoomInCallFeedback => _zoomInCallFeedback; + public event DeviceInfoChangeHandler DeviceInfoChanged; + public BoolFeedback ZoomInCallFeedback => _zoomInCallFeedback; - public FeedbackCollection Feedbacks { get; private set; } - public FeedbackCollection ZoomFeedbacks { get; private set; } + public FeedbackCollection Feedbacks { get; private set; } - public string DefaultRoomKey => _config.DefaultRoomKey; + public FeedbackCollection ZoomFeedbacks { get; private set; } - public bool UseDirectServer => localConfig.UseDirectServer; + public string DefaultRoomKey => _config.DefaultRoomKey; - public bool ZoomRoomController => localConfig.ZoomRoomController; + public bool UseDirectServer => localConfig.UseDirectServer; - public string Theme => localConfig.Theme; + public bool ZoomRoomController => localConfig.ZoomRoomController; - public StringFeedback ThemeFeedback { get; private set; } + public string Theme => localConfig.Theme; - public DeviceInfo DeviceInfo => new DeviceInfo(); + public StringFeedback ThemeFeedback { get; private set; } - public MobileControlTouchpanelController(string key, string name, BasicTriListWithSmartObject panel, MobileControlTouchpanelProperties config) : base(key, name, panel, config) - { - localConfig = config; + public DeviceInfo DeviceInfo => new DeviceInfo(); - AddPostActivationAction(SubscribeForMobileControlUpdates); + public MobileControlTouchpanelController(string key, string name, BasicTriListWithSmartObject panel, MobileControlTouchpanelProperties config) : base(key, name, panel, config) + { + localConfig = config; + + AddPostActivationAction(SubscribeForMobileControlUpdates); - ThemeFeedback = new StringFeedback($"{Key}-theme", () => Theme); - AppUrlFeedback = new StringFeedback($"{Key}-appUrl", () => _appUrl); - QrCodeUrlFeedback = new StringFeedback($"{Key}-qrCodeUrl", () => _bridge?.QrCodeUrl); - McServerUrlFeedback = new StringFeedback($"{Key}-mcServerUrl", () => _bridge?.McServerUrl); - UserCodeFeedback = new StringFeedback($"{Key}-userCode", () => _bridge?.UserCode); + ThemeFeedback = new StringFeedback($"{Key}-theme", () => Theme); + AppUrlFeedback = new StringFeedback($"{Key}-appUrl", () => _appUrl); + QrCodeUrlFeedback = new StringFeedback($"{Key}-qrCodeUrl", () => _bridge?.QrCodeUrl); + McServerUrlFeedback = new StringFeedback($"{Key}-mcServerUrl", () => _bridge?.McServerUrl); + UserCodeFeedback = new StringFeedback($"{Key}-userCode", () => _bridge?.UserCode); - _appOpenFeedback = new BoolFeedback($"{Key}-appOpen", () => + _appOpenFeedback = new BoolFeedback($"{Key}-appOpen", () => + { + if (Panel is TswX60BaseClass tsX60) { - if (Panel is TswX60BaseClass tsX60) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"x60 sending {tsX60.ExtenderApplicationControlReservedSigs.HideOpenApplicationFeedback.BoolValue}"); - return !tsX60.ExtenderApplicationControlReservedSigs.HideOpenApplicationFeedback.BoolValue; - } + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"x60 sending {tsX60.ExtenderApplicationControlReservedSigs.HideOpenApplicationFeedback.BoolValue}"); + return !tsX60.ExtenderApplicationControlReservedSigs.HideOpenApplicationFeedback.BoolValue; + } - if (Panel is TswX70Base tsX70) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"x70 sending {tsX70.ExtenderApplicationControlReservedSigs.HideOpenedApplicationFeedback.BoolValue}"); - return !tsX70.ExtenderApplicationControlReservedSigs.HideOpenedApplicationFeedback.BoolValue; - } + if (Panel is TswX70Base tsX70) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"x70 sending {tsX70.ExtenderApplicationControlReservedSigs.HideOpenedApplicationFeedback.BoolValue}"); + return !tsX70.ExtenderApplicationControlReservedSigs.HideOpenedApplicationFeedback.BoolValue; + } - return false; - }); + return false; + }); - _zoomIncomingCallFeedback = new BoolFeedback($"{Key}-zoomIncomingCall", () => + _zoomIncomingCallFeedback = new BoolFeedback($"{Key}-zoomIncomingCall", () => + { + if (Panel is TswX60WithZoomRoomAppReservedSigs tsX60) { - if (Panel is TswX60WithZoomRoomAppReservedSigs tsX60) - { - return tsX60.ExtenderZoomRoomAppReservedSigs.ZoomRoomIncomingCallFeedback.BoolValue; - } + return tsX60.ExtenderZoomRoomAppReservedSigs.ZoomRoomIncomingCallFeedback.BoolValue; + } - if (Panel is TswX70Base tsX70) - { - return tsX70.ExtenderZoomRoomAppReservedSigs.ZoomRoomIncomingCallFeedback.BoolValue; - } + if (Panel is TswX70Base tsX70) + { + return tsX70.ExtenderZoomRoomAppReservedSigs.ZoomRoomIncomingCallFeedback.BoolValue; + } - return false; - }); + return false; + }); - _zoomInCallFeedback = new BoolFeedback($"{Key}-zoomInCall", () => + _zoomInCallFeedback = new BoolFeedback($"{Key}-zoomInCall", () => + { + if (Panel is TswX60WithZoomRoomAppReservedSigs tsX60) { - if (Panel is TswX60WithZoomRoomAppReservedSigs tsX60) - { - return tsX60.ExtenderZoomRoomAppReservedSigs.ZoomRoomActiveFeedback.BoolValue; - } + return tsX60.ExtenderZoomRoomAppReservedSigs.ZoomRoomActiveFeedback.BoolValue; + } - if (Panel is TswX70Base tsX70) - { - return tsX70.ExtenderZoomRoomAppReservedSigs.ZoomRoomActiveFeedback.BoolValue; - } + if (Panel is TswX70Base tsX70) + { + return tsX70.ExtenderZoomRoomAppReservedSigs.ZoomRoomActiveFeedback.BoolValue; + } - return false; - }); + return false; + }); - Feedbacks = new FeedbackCollection - { - AppUrlFeedback, QrCodeUrlFeedback, McServerUrlFeedback, UserCodeFeedback - }; + Feedbacks = new FeedbackCollection + { + AppUrlFeedback, QrCodeUrlFeedback, McServerUrlFeedback, UserCodeFeedback + }; - ZoomFeedbacks = new FeedbackCollection { - AppOpenFeedback, _zoomInCallFeedback, _zoomIncomingCallFeedback - }; + ZoomFeedbacks = new FeedbackCollection { + AppOpenFeedback, _zoomInCallFeedback, _zoomIncomingCallFeedback + }; - RegisterForExtenders(); - } + RegisterForExtenders(); + } - public void UpdateTheme(string theme) - { - localConfig.Theme = theme; + public void UpdateTheme(string theme) + { + localConfig.Theme = theme; - var props = JToken.FromObject(localConfig); + var props = JToken.FromObject(localConfig); - var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault((d) => d.Key == Key); + var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault((d) => d.Key == Key); - if (deviceConfig == null) { return; } + if (deviceConfig == null) { return; } - deviceConfig.Properties = props; + deviceConfig.Properties = props; - ConfigWriter.UpdateDeviceConfig(deviceConfig); - } + ConfigWriter.UpdateDeviceConfig(deviceConfig); + } - private void RegisterForExtenders() + private void RegisterForExtenders() + { + if (Panel is TswXX70Base x70Panel) { - if (Panel is TswXX70Base x70Panel) + x70Panel.ExtenderApplicationControlReservedSigs.DeviceExtenderSigChange += (e, a) => { - x70Panel.ExtenderApplicationControlReservedSigs.DeviceExtenderSigChange += (e, a) => - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X70 App Control Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}"); - - UpdateZoomFeedbacks(); + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X70 App Control Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}"); - if (!x70Panel.ExtenderApplicationControlReservedSigs.HideOpenedApplicationFeedback.BoolValue) - { - x70Panel.ExtenderButtonToolbarReservedSigs.ShowButtonToolbar(); - x70Panel.ExtenderButtonToolbarReservedSigs.Button2On(); - } - else - { - x70Panel.ExtenderButtonToolbarReservedSigs.HideButtonToolbar(); - x70Panel.ExtenderButtonToolbarReservedSigs.Button2Off(); - } - }; + UpdateZoomFeedbacks(); - - x70Panel.ExtenderZoomRoomAppReservedSigs.DeviceExtenderSigChange += (e, a) => + if (!x70Panel.ExtenderApplicationControlReservedSigs.HideOpenedApplicationFeedback.BoolValue) + { + x70Panel.ExtenderButtonToolbarReservedSigs.ShowButtonToolbar(); + x70Panel.ExtenderButtonToolbarReservedSigs.Button2On(); + } + else { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X70 Zoom Room Ap Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}"); + x70Panel.ExtenderButtonToolbarReservedSigs.HideButtonToolbar(); + x70Panel.ExtenderButtonToolbarReservedSigs.Button2Off(); + } + }; - if (a.Sig.Number == x70Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomIncomingCallFeedback.Number) - { - ZoomIncomingCallFeedback.FireUpdate(); - } - else if (a.Sig.Number == x70Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomActiveFeedback.Number) - { - ZoomInCallFeedback.FireUpdate(); - } - }; + x70Panel.ExtenderZoomRoomAppReservedSigs.DeviceExtenderSigChange += (e, a) => + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X70 Zoom Room Ap Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}"); - x70Panel.ExtenderEthernetReservedSigs.DeviceExtenderSigChange += (e, a) => + if (a.Sig.Number == x70Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomIncomingCallFeedback.Number) + { + ZoomIncomingCallFeedback.FireUpdate(); + } + else if (a.Sig.Number == x70Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomActiveFeedback.Number) { - DeviceInfo.MacAddress = x70Panel.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue; - DeviceInfo.IpAddress = x70Panel.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue; + ZoomInCallFeedback.FireUpdate(); + } + }; + + + x70Panel.ExtenderEthernetReservedSigs.DeviceExtenderSigChange += (e, a) => + { + DeviceInfo.MacAddress = x70Panel.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue; + DeviceInfo.IpAddress = x70Panel.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue; - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"MAC: {DeviceInfo.MacAddress} IP: {DeviceInfo.IpAddress}"); + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"MAC: {DeviceInfo.MacAddress} IP: {DeviceInfo.IpAddress}"); - var handler = DeviceInfoChanged; + var handler = DeviceInfoChanged; - if (handler == null) - { - return; - } + if (handler == null) + { + return; + } - handler(this, new DeviceInfoEventArgs(DeviceInfo)); - }; + handler(this, new DeviceInfoEventArgs(DeviceInfo)); + }; - x70Panel.ExtenderApplicationControlReservedSigs.Use(); - x70Panel.ExtenderZoomRoomAppReservedSigs.Use(); - x70Panel.ExtenderEthernetReservedSigs.Use(); - x70Panel.ExtenderButtonToolbarReservedSigs.Use(); + x70Panel.ExtenderApplicationControlReservedSigs.Use(); + x70Panel.ExtenderZoomRoomAppReservedSigs.Use(); + x70Panel.ExtenderEthernetReservedSigs.Use(); + x70Panel.ExtenderButtonToolbarReservedSigs.Use(); - x70Panel.ExtenderButtonToolbarReservedSigs.Button1Off(); - x70Panel.ExtenderButtonToolbarReservedSigs.Button3Off(); - x70Panel.ExtenderButtonToolbarReservedSigs.Button4Off(); - x70Panel.ExtenderButtonToolbarReservedSigs.Button5Off(); - x70Panel.ExtenderButtonToolbarReservedSigs.Button6Off(); + x70Panel.ExtenderButtonToolbarReservedSigs.Button1Off(); + x70Panel.ExtenderButtonToolbarReservedSigs.Button3Off(); + x70Panel.ExtenderButtonToolbarReservedSigs.Button4Off(); + x70Panel.ExtenderButtonToolbarReservedSigs.Button5Off(); + x70Panel.ExtenderButtonToolbarReservedSigs.Button6Off(); - return; - } + return; + } - if (Panel is TswX60WithZoomRoomAppReservedSigs x60withZoomApp) + if (Panel is TswX60WithZoomRoomAppReservedSigs x60withZoomApp) + { + x60withZoomApp.ExtenderApplicationControlReservedSigs.DeviceExtenderSigChange += (e, a) => { - x60withZoomApp.ExtenderApplicationControlReservedSigs.DeviceExtenderSigChange += (e, a) => + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X60 App Control Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}"); + + if (a.Sig.Number == x60withZoomApp.ExtenderApplicationControlReservedSigs.HideOpenApplicationFeedback.Number) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X60 App Control Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}"); - - if (a.Sig.Number == x60withZoomApp.ExtenderApplicationControlReservedSigs.HideOpenApplicationFeedback.Number) - { - AppOpenFeedback.FireUpdate(); - } - }; - x60withZoomApp.ExtenderZoomRoomAppReservedSigs.DeviceExtenderSigChange += (e, a) => + AppOpenFeedback.FireUpdate(); + } + }; + x60withZoomApp.ExtenderZoomRoomAppReservedSigs.DeviceExtenderSigChange += (e, a) => + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X60 Zoom Room App Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}"); + + if (a.Sig.Number == x60withZoomApp.ExtenderZoomRoomAppReservedSigs.ZoomRoomIncomingCallFeedback.Number) { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"X60 Zoom Room App Device Extender args: {a.Event}:{a.Sig}:{a.Sig.Type}:{a.Sig.BoolValue}:{a.Sig.UShortValue}:{a.Sig.StringValue}"); - - if (a.Sig.Number == x60withZoomApp.ExtenderZoomRoomAppReservedSigs.ZoomRoomIncomingCallFeedback.Number) - { - ZoomIncomingCallFeedback.FireUpdate(); - } - else if (a.Sig.Number == x60withZoomApp.ExtenderZoomRoomAppReservedSigs.ZoomRoomActiveFeedback.Number) - { - ZoomInCallFeedback.FireUpdate(); - } - }; - - x60withZoomApp.ExtenderEthernetReservedSigs.DeviceExtenderSigChange += (e, a) => + ZoomIncomingCallFeedback.FireUpdate(); + } + else if (a.Sig.Number == x60withZoomApp.ExtenderZoomRoomAppReservedSigs.ZoomRoomActiveFeedback.Number) { - DeviceInfo.MacAddress = x60withZoomApp.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue; - DeviceInfo.IpAddress = x60withZoomApp.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue; - - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"MAC: {DeviceInfo.MacAddress} IP: {DeviceInfo.IpAddress}"); + ZoomInCallFeedback.FireUpdate(); + } + }; - var handler = DeviceInfoChanged; + x60withZoomApp.ExtenderEthernetReservedSigs.DeviceExtenderSigChange += (e, a) => + { + DeviceInfo.MacAddress = x60withZoomApp.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue; + DeviceInfo.IpAddress = x60withZoomApp.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue; - if (handler == null) - { - return; - } + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"MAC: {DeviceInfo.MacAddress} IP: {DeviceInfo.IpAddress}"); - handler(this, new DeviceInfoEventArgs(DeviceInfo)); - }; + var handler = DeviceInfoChanged; - x60withZoomApp.ExtenderZoomRoomAppReservedSigs.Use(); - x60withZoomApp.ExtenderApplicationControlReservedSigs.Use(); - x60withZoomApp.ExtenderEthernetReservedSigs.Use(); - } - } + if (handler == null) + { + return; + } - public override bool CustomActivate() - { - var appMessenger = new ITswAppControlMessenger($"appControlMessenger-{Key}", $"/device/{Key}", this); + handler(this, new DeviceInfoEventArgs(DeviceInfo)); + }; - var zoomMessenger = new ITswZoomControlMessenger($"zoomControlMessenger-{Key}", $"/device/{Key}", this); + x60withZoomApp.ExtenderZoomRoomAppReservedSigs.Use(); + x60withZoomApp.ExtenderApplicationControlReservedSigs.Use(); + x60withZoomApp.ExtenderEthernetReservedSigs.Use(); + } + } - var themeMessenger = new ThemeMessenger($"themeMessenger-{Key}", $"/device/{Key}", this); + public override bool CustomActivate() + { + var appMessenger = new ITswAppControlMessenger($"appControlMessenger-{Key}", $"/device/{Key}", this); - var mc = DeviceManager.AllDevices.OfType().FirstOrDefault(); + var zoomMessenger = new ITswZoomControlMessenger($"zoomControlMessenger-{Key}", $"/device/{Key}", this); - if (mc == null) - { - return base.CustomActivate(); - } + var themeMessenger = new ThemeMessenger($"themeMessenger-{Key}", $"/device/{Key}", this); - if (!(Panel is TswXX70Base) && !(Panel is TswX60WithZoomRoomAppReservedSigs)) - { - mc.AddDeviceMessenger(themeMessenger); + var mc = DeviceManager.AllDevices.OfType().FirstOrDefault(); - return base.CustomActivate(); - } + if (mc == null) + { + return base.CustomActivate(); + } - mc.AddDeviceMessenger(appMessenger); - mc.AddDeviceMessenger(zoomMessenger); + if (!(Panel is TswXX70Base) && !(Panel is TswX60WithZoomRoomAppReservedSigs)) + { mc.AddDeviceMessenger(themeMessenger); return base.CustomActivate(); } + mc.AddDeviceMessenger(appMessenger); + mc.AddDeviceMessenger(zoomMessenger); + mc.AddDeviceMessenger(themeMessenger); - protected override void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"System Device Extender args: ${args.Event}:${args.Sig}"); - } + return base.CustomActivate(); + } + + + protected override void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, this, $"System Device Extender args: ${args.Event}:${args.Sig}"); + } - protected override void SetupPanelDrivers(string roomKey) + protected override void SetupPanelDrivers(string roomKey) + { + AppUrlFeedback.LinkInputSig(Panel.StringInput[1]); + QrCodeUrlFeedback.LinkInputSig(Panel.StringInput[2]); + McServerUrlFeedback.LinkInputSig(Panel.StringInput[3]); + UserCodeFeedback.LinkInputSig(Panel.StringInput[4]); + + Panel.OnlineStatusChange += (sender, args) => { - AppUrlFeedback.LinkInputSig(Panel.StringInput[1]); - QrCodeUrlFeedback.LinkInputSig(Panel.StringInput[2]); - McServerUrlFeedback.LinkInputSig(Panel.StringInput[3]); - UserCodeFeedback.LinkInputSig(Panel.StringInput[4]); + UpdateFeedbacks(); - Panel.OnlineStatusChange += (sender, args) => - { - UpdateFeedbacks(); + this.LogInformation("Sending {appUrl} on join 1", AppUrlFeedback.StringValue); - this.LogInformation("Sending {appUrl} on join 1", AppUrlFeedback.StringValue); + Panel.StringInput[1].StringValue = AppUrlFeedback.StringValue; + Panel.StringInput[2].StringValue = QrCodeUrlFeedback.StringValue; + Panel.StringInput[3].StringValue = McServerUrlFeedback.StringValue; + Panel.StringInput[4].StringValue = UserCodeFeedback.StringValue; + }; + } - Panel.StringInput[1].StringValue = AppUrlFeedback.StringValue; - Panel.StringInput[2].StringValue = QrCodeUrlFeedback.StringValue; - Panel.StringInput[3].StringValue = McServerUrlFeedback.StringValue; - Panel.StringInput[4].StringValue = UserCodeFeedback.StringValue; - }; + private void SubscribeForMobileControlUpdates() + { + foreach (var dev in DeviceManager.AllDevices) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"{dev.Key}:{dev.GetType().Name}"); } - private void SubscribeForMobileControlUpdates() + var mcList = DeviceManager.AllDevices.OfType().ToList(); + + if (mcList.Count == 0) { - foreach (var dev in DeviceManager.AllDevices) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"{dev.Key}:{dev.GetType().Name}"); - } + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"No Mobile Control controller found"); - var mcList = DeviceManager.AllDevices.OfType().ToList(); + return; + } - if (mcList.Count == 0) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"No Mobile Control controller found"); + // use first in list, since there should only be one. + var mc = mcList[0]; - return; - } + var bridge = mc.GetRoomBridge(_config.DefaultRoomKey); - // use first in list, since there should only be one. - var mc = mcList[0]; + if (bridge == null) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"No Mobile Control bridge for {_config.DefaultRoomKey} found "); + return; + } - var bridge = mc.GetRoomBridge(_config.DefaultRoomKey); + _bridge = bridge; - if (bridge == null) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"No Mobile Control bridge for {_config.DefaultRoomKey} found "); - return; - } + _bridge.UserCodeChanged += UpdateFeedbacks; + _bridge.AppUrlChanged += (s, a) => + { + this.LogInformation("AppURL changed"); + SetAppUrl(_bridge.AppUrl); + UpdateFeedbacks(s, a); + }; - _bridge = bridge; + SetAppUrl(_bridge.AppUrl); + } - _bridge.UserCodeChanged += UpdateFeedbacks; - _bridge.AppUrlChanged += (s, a) => - { - this.LogInformation("AppURL changed"); - SetAppUrl(_bridge.AppUrl); - UpdateFeedbacks(s, a); - }; + public void SetAppUrl(string url) + { + _appUrl = url; + AppUrlFeedback.FireUpdate(); + } - SetAppUrl(_bridge.AppUrl); - } + private void UpdateFeedbacks(object sender, EventArgs args) + { + UpdateFeedbacks(); + } - public void SetAppUrl(string url) + private void UpdateFeedbacks() + { + foreach (var feedback in Feedbacks) { this.LogDebug("Updating {feedbackKey}", feedback.Key); feedback.FireUpdate(); } + } + + private void UpdateZoomFeedbacks() + { + foreach (var feedback in ZoomFeedbacks) { - _appUrl = url; - AppUrlFeedback.FireUpdate(); + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"Updating {feedback.Key}"); + feedback.FireUpdate(); } + } - private void UpdateFeedbacks(object sender, EventArgs args) + public void HideOpenApp() + { + if (Panel is TswX70Base x70Panel) { - UpdateFeedbacks(); + x70Panel.ExtenderApplicationControlReservedSigs.HideOpenedApplication(); + return; } - private void UpdateFeedbacks() + if (Panel is TswX60BaseClass x60Panel) { - foreach (var feedback in Feedbacks) { this.LogDebug("Updating {feedbackKey}", feedback.Key); feedback.FireUpdate(); } + x60Panel.ExtenderApplicationControlReservedSigs.HideOpenApplication(); + return; } + } - private void UpdateZoomFeedbacks() + public void OpenApp() + { + if (Panel is TswX70Base x70Panel) { - foreach (var feedback in ZoomFeedbacks) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"Updating {feedback.Key}"); - feedback.FireUpdate(); - } + x70Panel.ExtenderApplicationControlReservedSigs.OpenApplication(); + return; } - public void HideOpenApp() + if (Panel is TswX60WithZoomRoomAppReservedSigs) { - if (Panel is TswX70Base x70Panel) - { - x70Panel.ExtenderApplicationControlReservedSigs.HideOpenedApplication(); - return; - } - - if (Panel is TswX60BaseClass x60Panel) - { - x60Panel.ExtenderApplicationControlReservedSigs.HideOpenApplication(); - return; - } + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"X60 panel does not support zoom app"); + return; } + } - public void OpenApp() + public void CloseOpenApp() + { + if (Panel is TswX70Base x70Panel) { - if (Panel is TswX70Base x70Panel) - { - x70Panel.ExtenderApplicationControlReservedSigs.OpenApplication(); - return; - } + x70Panel.ExtenderApplicationControlReservedSigs.CloseOpenedApplication(); + return; + } - if (Panel is TswX60WithZoomRoomAppReservedSigs) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, this, $"X60 panel does not support zoom app"); - return; - } + if (Panel is TswX60WithZoomRoomAppReservedSigs x60Panel) + { + x60Panel.ExtenderApplicationControlReservedSigs.CloseOpenedApplication(); + return; } + } - public void CloseOpenApp() + public void EndZoomCall() + { + if (Panel is TswX70Base x70Panel) { - if (Panel is TswX70Base x70Panel) - { - x70Panel.ExtenderApplicationControlReservedSigs.CloseOpenedApplication(); - return; - } + x70Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomEndCall(); + return; + } - if (Panel is TswX60WithZoomRoomAppReservedSigs x60Panel) - { - x60Panel.ExtenderApplicationControlReservedSigs.CloseOpenedApplication(); - return; - } + if (Panel is TswX60WithZoomRoomAppReservedSigs x60Panel) + { + x60Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomEndCall(); + return; } + } - public void EndZoomCall() + public void UpdateDeviceInfo() + { + if (Panel is TswXX70Base x70Panel) { - if (Panel is TswX70Base x70Panel) - { - x70Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomEndCall(); - return; - } + DeviceInfo.MacAddress = x70Panel.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue; + DeviceInfo.IpAddress = x70Panel.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue; - if (Panel is TswX60WithZoomRoomAppReservedSigs x60Panel) + var handler = DeviceInfoChanged; + + if (handler == null) { - x60Panel.ExtenderZoomRoomAppReservedSigs.ZoomRoomEndCall(); return; } + + handler(this, new DeviceInfoEventArgs(DeviceInfo)); } - public void UpdateDeviceInfo() + if (Panel is TswX60WithZoomRoomAppReservedSigs x60Panel) { - if (Panel is TswXX70Base x70Panel) - { - DeviceInfo.MacAddress = x70Panel.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue; - DeviceInfo.IpAddress = x70Panel.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue; + DeviceInfo.MacAddress = x60Panel.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue; + DeviceInfo.IpAddress = x60Panel.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue; - var handler = DeviceInfoChanged; - - if (handler == null) - { - return; - } - - handler(this, new DeviceInfoEventArgs(DeviceInfo)); - } + var handler = DeviceInfoChanged; - if (Panel is TswX60WithZoomRoomAppReservedSigs x60Panel) + if (handler == null) { - DeviceInfo.MacAddress = x60Panel.ExtenderEthernetReservedSigs.MacAddressFeedback.StringValue; - DeviceInfo.IpAddress = x60Panel.ExtenderEthernetReservedSigs.IpAddressFeedback.StringValue; - - var handler = DeviceInfoChanged; - - if (handler == null) - { - return; - } - - handler(this, new DeviceInfoEventArgs(DeviceInfo)); + return; } - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"MAC: {DeviceInfo.MacAddress} IP: {DeviceInfo.IpAddress}"); + handler(this, new DeviceInfoEventArgs(DeviceInfo)); } + + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, this, $"MAC: {DeviceInfo.MacAddress} IP: {DeviceInfo.IpAddress}"); } +} - public class MobileControlTouchpanelControllerFactory : EssentialsPluginDeviceFactory +public class MobileControlTouchpanelControllerFactory : EssentialsPluginDeviceFactory +{ + public MobileControlTouchpanelControllerFactory() { - public MobileControlTouchpanelControllerFactory() - { - TypeNames = new List() { "mccrestronapp", "mctsw550", "mctsw750", "mctsw1050", "mctsw560", "mctsw760", "mctsw1060", "mctsw570", "mctsw770", "mcts770", "mctsw1070", "mcts1070", "mcxpanel", "mcdge1000" }; - MinimumEssentialsFrameworkVersion = "2.0.0"; - } + TypeNames = new List() { "mccrestronapp", "mctsw550", "mctsw750", "mctsw1050", "mctsw560", "mctsw760", "mctsw1060", "mctsw570", "mctsw770", "mcts770", "mctsw1070", "mcts1070", "mcxpanel", "mcdge1000" }; + MinimumEssentialsFrameworkVersion = "2.0.0"; + } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - var comm = CommFactory.GetControlPropertiesConfig(dc); - var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + var comm = CommFactory.GetControlPropertiesConfig(dc); + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); - var panel = GetPanelForType(dc.Type, comm.IpIdInt, props.ProjectName); + var panel = GetPanelForType(dc.Type, comm.IpIdInt, props.ProjectName); - if (panel == null) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Unable to create Touchpanel for type {0}. Touchpanel Controller WILL NOT function correctly", dc.Type); - } + if (panel == null) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Unable to create Touchpanel for type {0}. Touchpanel Controller WILL NOT function correctly", dc.Type); + } - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Factory Attempting to create new MobileControlTouchpanelController"); + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, "Factory Attempting to create new MobileControlTouchpanelController"); - var panelController = new MobileControlTouchpanelController(dc.Key, dc.Name, panel, props); + var panelController = new MobileControlTouchpanelController(dc.Key, dc.Name, panel, props); - return panelController; - } + return panelController; + } - private BasicTriListWithSmartObject GetPanelForType(string type, uint id, string projectName) + private BasicTriListWithSmartObject GetPanelForType(string type, uint id, string projectName) + { + type = type.ToLower().Replace("mc", ""); + try { - type = type.ToLower().Replace("mc", ""); - try + if (type == "crestronapp") { - if (type == "crestronapp") - { - var app = new CrestronApp(id, Global.ControlSystem); - app.ParameterProjectName.Value = projectName; - return app; - } - else if (type == "xpanel") - return new XpanelForHtml5(id, Global.ControlSystem); - else if (type == "tsw550") - return new Tsw550(id, Global.ControlSystem); - else if (type == "tsw552") - return new Tsw552(id, Global.ControlSystem); - else if (type == "tsw560") - return new Tsw560(id, Global.ControlSystem); - else if (type == "tsw750") - return new Tsw750(id, Global.ControlSystem); - else if (type == "tsw752") - return new Tsw752(id, Global.ControlSystem); - else if (type == "tsw760") - return new Tsw760(id, Global.ControlSystem); - else if (type == "tsw1050") - return new Tsw1050(id, Global.ControlSystem); - else if (type == "tsw1052") - return new Tsw1052(id, Global.ControlSystem); - else if (type == "tsw1060") - return new Tsw1060(id, Global.ControlSystem); - else if (type == "tsw570") - return new Tsw570(id, Global.ControlSystem); - else if (type == "tsw770") - return new Tsw770(id, Global.ControlSystem); - else if (type == "ts770") - return new Ts770(id, Global.ControlSystem); - else if (type == "tsw1070") - return new Tsw1070(id, Global.ControlSystem); - else if (type == "ts1070") - return new Ts1070(id, Global.ControlSystem); - else if (type == "dge1000") - return new Dge1000(id, Global.ControlSystem); - else - - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "WARNING: Cannot create TSW controller with type '{0}'", type); - return null; - } + var app = new CrestronApp(id, Global.ControlSystem); + app.ParameterProjectName.Value = projectName; + return app; } - catch (Exception e) + else if (type == "xpanel") + return new XpanelForHtml5(id, Global.ControlSystem); + else if (type == "tsw550") + return new Tsw550(id, Global.ControlSystem); + else if (type == "tsw552") + return new Tsw552(id, Global.ControlSystem); + else if (type == "tsw560") + return new Tsw560(id, Global.ControlSystem); + else if (type == "tsw750") + return new Tsw750(id, Global.ControlSystem); + else if (type == "tsw752") + return new Tsw752(id, Global.ControlSystem); + else if (type == "tsw760") + return new Tsw760(id, Global.ControlSystem); + else if (type == "tsw1050") + return new Tsw1050(id, Global.ControlSystem); + else if (type == "tsw1052") + return new Tsw1052(id, Global.ControlSystem); + else if (type == "tsw1060") + return new Tsw1060(id, Global.ControlSystem); + else if (type == "tsw570") + return new Tsw570(id, Global.ControlSystem); + else if (type == "tsw770") + return new Tsw770(id, Global.ControlSystem); + else if (type == "ts770") + return new Ts770(id, Global.ControlSystem); + else if (type == "tsw1070") + return new Tsw1070(id, Global.ControlSystem); + else if (type == "ts1070") + return new Ts1070(id, Global.ControlSystem); + else if (type == "dge1000") + return new Dge1000(id, Global.ControlSystem); + else + { - Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message); + Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "WARNING: Cannot create TSW controller with type '{0}'", type); return null; } } + catch (Exception e) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message); + return null; + } } } diff --git a/src/PepperDash.Essentials.MobileControl/Touchpanel/MobileControlTouchpanelProperties.cs b/src/PepperDash.Essentials.MobileControl/Touchpanel/MobileControlTouchpanelProperties.cs index 87f6d9a9d..4c12ebf27 100644 --- a/src/PepperDash.Essentials.MobileControl/Touchpanel/MobileControlTouchpanelProperties.cs +++ b/src/PepperDash.Essentials.MobileControl/Touchpanel/MobileControlTouchpanelProperties.cs @@ -1,20 +1,19 @@ using Newtonsoft.Json; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.Touchpanel +namespace PepperDash.Essentials.Touchpanel; + +public class MobileControlTouchpanelProperties : CrestronTouchpanelPropertiesConfig { - public class MobileControlTouchpanelProperties : CrestronTouchpanelPropertiesConfig - { - [JsonProperty("useDirectServer")] - public bool UseDirectServer { get; set; } = false; + [JsonProperty("useDirectServer")] + public bool UseDirectServer { get; set; } = false; - [JsonProperty("zoomRoomController")] - public bool ZoomRoomController { get; set; } = false; + [JsonProperty("zoomRoomController")] + public bool ZoomRoomController { get; set; } = false; - [JsonProperty("buttonToolbarTimeoutInS")] - public ushort ButtonToolbarTimoutInS { get; set; } = 0; + [JsonProperty("buttonToolbarTimeoutInS")] + public ushort ButtonToolbarTimoutInS { get; set; } = 0; - [JsonProperty("theme")] - public string Theme { get; set; } = "light"; - } + [JsonProperty("theme")] + public string Theme { get; set; } = "light"; } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl/Touchpanel/ThemeMessenger.cs b/src/PepperDash.Essentials.MobileControl/Touchpanel/ThemeMessenger.cs index ab48b60a6..57f23cb9d 100644 --- a/src/PepperDash.Essentials.MobileControl/Touchpanel/ThemeMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl/Touchpanel/ThemeMessenger.cs @@ -4,39 +4,38 @@ using PepperDash.Essentials.AppServer; using PepperDash.Essentials.AppServer.Messengers; -namespace PepperDash.Essentials.Touchpanel +namespace PepperDash.Essentials.Touchpanel; + +public class ThemeMessenger : MessengerBase { - public class ThemeMessenger : MessengerBase + private readonly ITheme _tpDevice; + + public ThemeMessenger(string key, string path, ITheme device) : base(key, path, device as Device) { - private readonly ITheme _tpDevice; + _tpDevice = device; + } - public ThemeMessenger(string key, string path, ITheme device) : base(key, path, device as Device) + protected override void RegisterActions() + { + AddAction("/fullStatus", (id, content) => { - _tpDevice = device; - } + PostStatusMessage(new ThemeUpdateMessage { Theme = _tpDevice.Theme }); + }); - protected override void RegisterActions() + AddAction("/saveTheme", (id, content) => { - AddAction("/fullStatus", (id, content) => - { - PostStatusMessage(new ThemeUpdateMessage { Theme = _tpDevice.Theme }); - }); - - AddAction("/saveTheme", (id, content) => - { - var theme = content.ToObject>(); + var theme = content.ToObject>(); - Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Setting theme to {theme}", this, theme.Value); - _tpDevice.UpdateTheme(theme.Value); + Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Setting theme to {theme}", this, theme.Value); + _tpDevice.UpdateTheme(theme.Value); - PostStatusMessage(JToken.FromObject(new { theme = theme.Value })); - }); - } + PostStatusMessage(JToken.FromObject(new { theme = theme.Value })); + }); } +} - public class ThemeUpdateMessage : DeviceStateMessageBase - { - [JsonProperty("theme")] - public string Theme { get; set; } - } +public class ThemeUpdateMessage : DeviceStateMessageBase +{ + [JsonProperty("theme")] + public string Theme { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl/TransmitMessage.cs b/src/PepperDash.Essentials.MobileControl/TransmitMessage.cs index b9ca686b7..27d52c155 100644 --- a/src/PepperDash.Essentials.MobileControl/TransmitMessage.cs +++ b/src/PepperDash.Essentials.MobileControl/TransmitMessage.cs @@ -10,121 +10,119 @@ using System.Threading; using WebSocketSharp; -namespace PepperDash.Essentials +namespace PepperDash.Essentials; + +public class TransmitMessage : IQueueMessage { - public class TransmitMessage : IQueueMessage - { - private readonly WebSocket _ws; - private readonly object msgToSend; + private readonly WebSocket _ws; + private readonly object msgToSend; - public TransmitMessage(object msg, WebSocket ws) - { - _ws = ws; - msgToSend = msg; - } + public TransmitMessage(object msg, WebSocket ws) + { + _ws = ws; + msgToSend = msg; + } - public TransmitMessage(DeviceStateMessageBase msg, WebSocket ws) - { - _ws = ws; - msgToSend = msg; - } + public TransmitMessage(DeviceStateMessageBase msg, WebSocket ws) + { + _ws = ws; + msgToSend = msg; + } - #region Implementation of IQueueMessage + #region Implementation of IQueueMessage - public void Dispatch() + public void Dispatch() + { + try { - try + if (_ws == null) { - if (_ws == null) - { - Debug.LogMessage(LogEventLevel.Warning, "Cannot send message. Websocket client is null"); - return; - } + Debug.LogMessage(LogEventLevel.Warning, "Cannot send message. Websocket client is null"); + return; + } - if (!_ws.IsAlive) - { - Debug.LogMessage(LogEventLevel.Warning, "Cannot send message. Websocket client is not connected"); - return; - } + if (!_ws.IsAlive) + { + Debug.LogMessage(LogEventLevel.Warning, "Cannot send message. Websocket client is not connected"); + return; + } - var message = JsonConvert.SerializeObject(msgToSend, Formatting.None, - new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Converters = { new IsoDateTimeConverter() } }); + var message = JsonConvert.SerializeObject(msgToSend, Formatting.None, + new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Converters = { new IsoDateTimeConverter() } }); - Debug.LogMessage(LogEventLevel.Verbose, "Message TX: {0}", null, message); + Debug.LogMessage(LogEventLevel.Verbose, "Message TX: {0}", null, message); - _ws.Send(message); + _ws.Send(message); - } - catch (Exception ex) - { - Debug.LogMessage(ex, "Caught an exception in the Transmit Processor"); - } } - #endregion + catch (Exception ex) + { + Debug.LogMessage(ex, "Caught an exception in the Transmit Processor"); + } } + #endregion +} - public class MessageToClients : IQueueMessage - { - private readonly MobileControlWebsocketServer _server; - private readonly object msgToSend; +public class MessageToClients : IQueueMessage +{ + private readonly MobileControlWebsocketServer _server; + private readonly object msgToSend; - public MessageToClients(object msg, MobileControlWebsocketServer server) - { - _server = server; - msgToSend = msg; - } + public MessageToClients(object msg, MobileControlWebsocketServer server) + { + _server = server; + msgToSend = msg; + } - public MessageToClients(DeviceStateMessageBase msg, MobileControlWebsocketServer server) - { - _server = server; - msgToSend = msg; - } + public MessageToClients(DeviceStateMessageBase msg, MobileControlWebsocketServer server) + { + _server = server; + msgToSend = msg; + } - #region Implementation of IQueueMessage + #region Implementation of IQueueMessage - public void Dispatch() + public void Dispatch() + { + try { - try + if (_server == null) { - if (_server == null) - { - Debug.LogMessage(LogEventLevel.Warning, "Cannot send message. Server is null"); - return; - } + Debug.LogMessage(LogEventLevel.Warning, "Cannot send message. Server is null"); + return; + } - var message = JsonConvert.SerializeObject(msgToSend, Formatting.None, - new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Converters = { new IsoDateTimeConverter() } }); + var message = JsonConvert.SerializeObject(msgToSend, Formatting.None, + new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Converters = { new IsoDateTimeConverter() } }); - var clientSpecificMessage = msgToSend as MobileControlMessage; - if (clientSpecificMessage.ClientId != null) - { - var clientId = clientSpecificMessage.ClientId; + var clientSpecificMessage = msgToSend as MobileControlMessage; + if (clientSpecificMessage.ClientId != null) + { + var clientId = clientSpecificMessage.ClientId; - _server.LogVerbose("Message TX To client {clientId} Message: {message}", clientId, message); + _server.LogVerbose("Message TX To client {clientId} Message: {message}", clientId, message); - _server.SendMessageToClient(clientId, message); + _server.SendMessageToClient(clientId, message); - return; - } + return; + } - _server.SendMessageToAllClients(message); + _server.SendMessageToAllClients(message); - _server.LogVerbose("Message TX To all clients: {message}", message); - } - catch (ThreadAbortException) - { - //Swallowing this exception, as it occurs on shutdown and there's no need to print out a scary stack trace - } - catch (Exception ex) - { - Debug.LogMessage(ex, "Caught an exception in the Transmit Processor"); - } + _server.LogVerbose("Message TX To all clients: {message}", message); + } + catch (ThreadAbortException) + { + //Swallowing this exception, as it occurs on shutdown and there's no need to print out a scary stack trace + } + catch (Exception ex) + { + Debug.LogMessage(ex, "Caught an exception in the Transmit Processor"); } - #endregion } - + #endregion } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl/UserCodeChangedContent.cs b/src/PepperDash.Essentials.MobileControl/UserCodeChangedContent.cs index 851f1b80d..923137a06 100644 --- a/src/PepperDash.Essentials.MobileControl/UserCodeChangedContent.cs +++ b/src/PepperDash.Essentials.MobileControl/UserCodeChangedContent.cs @@ -1,13 +1,12 @@ using Newtonsoft.Json; -namespace PepperDash.Essentials +namespace PepperDash.Essentials; + +public class UserCodeChangedContent { - public class UserCodeChangedContent - { - [JsonProperty("userCode")] - public string UserCode { get; set; } + [JsonProperty("userCode")] + public string UserCode { get; set; } - [JsonProperty("qrChecksum", NullValueHandling = NullValueHandling.Include)] - public string QrChecksum { get; set; } - } + [JsonProperty("qrChecksum", NullValueHandling = NullValueHandling.Include)] + public string QrChecksum { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl/Volumes.cs b/src/PepperDash.Essentials.MobileControl/Volumes.cs index 6cd83cf40..7abbba0a3 100644 --- a/src/PepperDash.Essentials.MobileControl/Volumes.cs +++ b/src/PepperDash.Essentials.MobileControl/Volumes.cs @@ -1,76 +1,75 @@ using Newtonsoft.Json; using System.Collections.Generic; -namespace PepperDash.Essentials +namespace PepperDash.Essentials; + +public class Volumes { - public class Volumes - { - [JsonProperty("master", NullValueHandling = NullValueHandling.Ignore)] - public Volume Master { get; set; } + [JsonProperty("master", NullValueHandling = NullValueHandling.Ignore)] + public Volume Master { get; set; } - [JsonProperty("auxFaders", NullValueHandling = NullValueHandling.Ignore)] - public Dictionary AuxFaders { get; set; } + [JsonProperty("auxFaders", NullValueHandling = NullValueHandling.Ignore)] + public Dictionary AuxFaders { get; set; } - [JsonProperty("numberOfAuxFaders", NullValueHandling = NullValueHandling.Ignore)] - public int? NumberOfAuxFaders { get; set; } + [JsonProperty("numberOfAuxFaders", NullValueHandling = NullValueHandling.Ignore)] + public int? NumberOfAuxFaders { get; set; } - public Volumes() - { - } + public Volumes() + { } +} - public class Volume - { - [JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)] - public string Key { get; set; } +public class Volume +{ + [JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)] + public string Key { get; set; } - [JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)] - public int? Level { get; set; } + [JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)] + public int? Level { get; set; } - [JsonProperty("muted", NullValueHandling = NullValueHandling.Ignore)] - public bool? Muted { get; set; } + [JsonProperty("muted", NullValueHandling = NullValueHandling.Ignore)] + public bool? Muted { get; set; } - [JsonProperty("label", NullValueHandling = NullValueHandling.Ignore)] - public string Label { get; set; } + [JsonProperty("label", NullValueHandling = NullValueHandling.Ignore)] + public string Label { get; set; } - [JsonProperty("hasMute", NullValueHandling = NullValueHandling.Ignore)] - public bool? HasMute { get; set; } + [JsonProperty("hasMute", NullValueHandling = NullValueHandling.Ignore)] + public bool? HasMute { get; set; } - [JsonProperty("hasPrivacyMute", NullValueHandling = NullValueHandling.Ignore)] - public bool? HasPrivacyMute { get; set; } + [JsonProperty("hasPrivacyMute", NullValueHandling = NullValueHandling.Ignore)] + public bool? HasPrivacyMute { get; set; } - [JsonProperty("privacyMuted", NullValueHandling = NullValueHandling.Ignore)] - public bool? PrivacyMuted { get; set; } + [JsonProperty("privacyMuted", NullValueHandling = NullValueHandling.Ignore)] + public bool? PrivacyMuted { get; set; } - [JsonProperty("muteIcon", NullValueHandling = NullValueHandling.Ignore)] - public string MuteIcon { get; set; } + [JsonProperty("muteIcon", NullValueHandling = NullValueHandling.Ignore)] + public string MuteIcon { get; set; } - public Volume(string key, int level, bool muted, string label, bool hasMute, string muteIcon) - : this(key) - { - Level = level; - Muted = muted; - Label = label; - HasMute = hasMute; - MuteIcon = muteIcon; - } + public Volume(string key, int level, bool muted, string label, bool hasMute, string muteIcon) + : this(key) + { + Level = level; + Muted = muted; + Label = label; + HasMute = hasMute; + MuteIcon = muteIcon; + } - public Volume(string key, int level) - : this(key) - { - Level = level; - } + public Volume(string key, int level) + : this(key) + { + Level = level; + } - public Volume(string key, bool muted) - : this(key) - { - Muted = muted; - } + public Volume(string key, bool muted) + : this(key) + { + Muted = muted; + } - public Volume(string key) - { - Key = key; - } + public Volume(string key) + { + Key = key; } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl/WebApiHandlers/ActionPathsHandler.cs b/src/PepperDash.Essentials.MobileControl/WebApiHandlers/ActionPathsHandler.cs index 2988241b1..f4324d62c 100644 --- a/src/PepperDash.Essentials.MobileControl/WebApiHandlers/ActionPathsHandler.cs +++ b/src/PepperDash.Essentials.MobileControl/WebApiHandlers/ActionPathsHandler.cs @@ -4,48 +4,47 @@ using System.Collections.Generic; using System.Linq; -namespace PepperDash.Essentials.WebApiHandlers +namespace PepperDash.Essentials.WebApiHandlers; + +public class ActionPathsHandler : WebApiBaseRequestHandler { - public class ActionPathsHandler : WebApiBaseRequestHandler + private readonly MobileControlSystemController mcController; + public ActionPathsHandler(MobileControlSystemController controller) : base(true) { - private readonly MobileControlSystemController mcController; - public ActionPathsHandler(MobileControlSystemController controller) : base(true) - { - mcController = controller; - } - - protected override void HandleGet(HttpCwsContext context) - { - var response = JsonConvert.SerializeObject(new ActionPathsResponse(mcController)); - - context.Response.StatusCode = 200; - context.Response.ContentType = "application/json"; - context.Response.Headers.Add("Content-Type", "application/json"); - context.Response.Write(response, false); - context.Response.End(); - } + mcController = controller; } - public class ActionPathsResponse + protected override void HandleGet(HttpCwsContext context) { - [JsonIgnore] - private readonly MobileControlSystemController mcController; - - [JsonProperty("actionPaths")] - public List ActionPaths => mcController.GetActionDictionaryPaths().Select((path) => new ActionPath { MessengerKey = path.Item1, Path = path.Item2 }).ToList(); + var response = JsonConvert.SerializeObject(new ActionPathsResponse(mcController)); - public ActionPathsResponse(MobileControlSystemController mcController) - { - this.mcController = mcController; - } + context.Response.StatusCode = 200; + context.Response.ContentType = "application/json"; + context.Response.Headers.Add("Content-Type", "application/json"); + context.Response.Write(response, false); + context.Response.End(); } +} - public class ActionPath - { - [JsonProperty("messengerKey")] - public string MessengerKey { get; set; } +public class ActionPathsResponse +{ + [JsonIgnore] + private readonly MobileControlSystemController mcController; + + [JsonProperty("actionPaths")] + public List ActionPaths => mcController.GetActionDictionaryPaths().Select((path) => new ActionPath { MessengerKey = path.Item1, Path = path.Item2 }).ToList(); - [JsonProperty("path")] - public string Path { get; set; } + public ActionPathsResponse(MobileControlSystemController mcController) + { + this.mcController = mcController; } } + +public class ActionPath +{ + [JsonProperty("messengerKey")] + public string MessengerKey { get; set; } + + [JsonProperty("path")] + public string Path { get; set; } +} diff --git a/src/PepperDash.Essentials.MobileControl/WebApiHandlers/MobileAuthRequestHandler.cs b/src/PepperDash.Essentials.MobileControl/WebApiHandlers/MobileAuthRequestHandler.cs index 4f2774f4e..342767641 100644 --- a/src/PepperDash.Essentials.MobileControl/WebApiHandlers/MobileAuthRequestHandler.cs +++ b/src/PepperDash.Essentials.MobileControl/WebApiHandlers/MobileAuthRequestHandler.cs @@ -6,54 +6,53 @@ using System; using System.Threading.Tasks; -namespace PepperDash.Essentials.WebApiHandlers +namespace PepperDash.Essentials.WebApiHandlers; + +public class MobileAuthRequestHandler : WebApiBaseRequestAsyncHandler { - public class MobileAuthRequestHandler : WebApiBaseRequestAsyncHandler - { - private readonly MobileControlSystemController mcController; + private readonly MobileControlSystemController mcController; - public MobileAuthRequestHandler(MobileControlSystemController controller) : base(true) - { - mcController = controller; - } + public MobileAuthRequestHandler(MobileControlSystemController controller) : base(true) + { + mcController = controller; + } - protected override async Task HandlePost(HttpCwsContext context) + protected override async Task HandlePost(HttpCwsContext context) + { + try { - try - { - var requestBody = EssentialsWebApiHelpers.GetRequestBody(context.Request); - - var grantCode = JsonConvert.DeserializeObject(requestBody); - - if (string.IsNullOrEmpty(grantCode?.GrantCode)) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Error, "Missing grant code"); - context.Response.StatusCode = 400; - context.Response.StatusDescription = "Missing grant code"; - context.Response.End(); - return; - } + var requestBody = EssentialsWebApiHelpers.GetRequestBody(context.Request); - var response = await mcController.ApiService.SendAuthorizationRequest(mcController.Host, grantCode.GrantCode, mcController.SystemUuid); + var grantCode = JsonConvert.DeserializeObject(requestBody); - Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, $"response received"); - if (response.Authorized) - { - mcController.RegisterSystemToServer(); - } - - - context.Response.StatusCode = 200; - var responseBody = JsonConvert.SerializeObject(response, Formatting.None); - context.Response.ContentType = "application/json"; - context.Response.Headers.Add("Content-Type", "application/json"); - context.Response.Write(responseBody, false); + if (string.IsNullOrEmpty(grantCode?.GrantCode)) + { + Debug.LogMessage(Serilog.Events.LogEventLevel.Error, "Missing grant code"); + context.Response.StatusCode = 400; + context.Response.StatusDescription = "Missing grant code"; context.Response.End(); + return; } - catch (Exception ex) + + var response = await mcController.ApiService.SendAuthorizationRequest(mcController.Host, grantCode.GrantCode, mcController.SystemUuid); + + Debug.LogMessage(Serilog.Events.LogEventLevel.Debug, $"response received"); + if (response.Authorized) { - Debug.LogMessage(ex, "Exception recieved authorizing system"); + mcController.RegisterSystemToServer(); } + + + context.Response.StatusCode = 200; + var responseBody = JsonConvert.SerializeObject(response, Formatting.None); + context.Response.ContentType = "application/json"; + context.Response.Headers.Add("Content-Type", "application/json"); + context.Response.Write(responseBody, false); + context.Response.End(); + } + catch (Exception ex) + { + Debug.LogMessage(ex, "Exception recieved authorizing system"); } } } diff --git a/src/PepperDash.Essentials.MobileControl/WebApiHandlers/MobileInfoHandler.cs b/src/PepperDash.Essentials.MobileControl/WebApiHandlers/MobileInfoHandler.cs index c8b97d0be..c9ca236c4 100644 --- a/src/PepperDash.Essentials.MobileControl/WebApiHandlers/MobileInfoHandler.cs +++ b/src/PepperDash.Essentials.MobileControl/WebApiHandlers/MobileInfoHandler.cs @@ -8,152 +8,151 @@ using System.Collections.Generic; using System.Linq; -namespace PepperDash.Essentials.WebApiHandlers +namespace PepperDash.Essentials.WebApiHandlers; + +public class MobileInfoHandler : WebApiBaseRequestHandler { - public class MobileInfoHandler : WebApiBaseRequestHandler + private readonly MobileControlSystemController mcController; + public MobileInfoHandler(MobileControlSystemController controller) : base(true) + { + mcController = controller; + } + + protected override void HandleGet(HttpCwsContext context) { - private readonly MobileControlSystemController mcController; - public MobileInfoHandler(MobileControlSystemController controller) : base(true) + try { - mcController = controller; - } + var response = new InformationResponse(mcController); - protected override void HandleGet(HttpCwsContext context) + context.Response.StatusCode = 200; + context.Response.ContentType = "application/json"; + context.Response.Write(JsonConvert.SerializeObject(response), false); + context.Response.End(); + } + catch (Exception ex) { - try - { - var response = new InformationResponse(mcController); - - context.Response.StatusCode = 200; - context.Response.ContentType = "application/json"; - context.Response.Write(JsonConvert.SerializeObject(response), false); - context.Response.End(); - } - catch (Exception ex) - { - Debug.LogMessage(ex, "exception showing mobile info"); - - context.Response.StatusCode = 500; - context.Response.End(); - } + Debug.LogMessage(ex, "exception showing mobile info"); + + context.Response.StatusCode = 500; + context.Response.End(); } } +} - public class InformationResponse - { - [JsonIgnore] - private readonly MobileControlSystemController mcController; +public class InformationResponse +{ + [JsonIgnore] + private readonly MobileControlSystemController mcController; - [JsonProperty("edgeServer", NullValueHandling = NullValueHandling.Ignore)] - public MobileControlEdgeServer EdgeServer => mcController.Config.EnableApiServer ? new MobileControlEdgeServer(mcController) : null; + [JsonProperty("edgeServer", NullValueHandling = NullValueHandling.Ignore)] + public MobileControlEdgeServer EdgeServer => mcController.Config.EnableApiServer ? new MobileControlEdgeServer(mcController) : null; - [JsonProperty("directServer", NullValueHandling = NullValueHandling.Ignore)] - public MobileControlDirectServer DirectServer => mcController.Config.DirectServer.EnableDirectServer ? new MobileControlDirectServer(mcController.DirectServer) : null; + [JsonProperty("directServer", NullValueHandling = NullValueHandling.Ignore)] + public MobileControlDirectServer DirectServer => mcController.Config.DirectServer.EnableDirectServer ? new MobileControlDirectServer(mcController.DirectServer) : null; - public InformationResponse(MobileControlSystemController controller) - { - mcController = controller; - } + public InformationResponse(MobileControlSystemController controller) + { + mcController = controller; } +} - public class MobileControlEdgeServer - { - [JsonIgnore] - private readonly MobileControlSystemController mcController; +public class MobileControlEdgeServer +{ + [JsonIgnore] + private readonly MobileControlSystemController mcController; - [JsonProperty("serverAddress")] - public string ServerAddress => mcController.Config == null ? "No Config" : mcController.Host; + [JsonProperty("serverAddress")] + public string ServerAddress => mcController.Config == null ? "No Config" : mcController.Host; - [JsonProperty("systemName")] - public string SystemName => mcController.RoomBridges.Count > 0 ? mcController.RoomBridges[0].RoomName : "No Config"; + [JsonProperty("systemName")] + public string SystemName => mcController.RoomBridges.Count > 0 ? mcController.RoomBridges[0].RoomName : "No Config"; - [JsonProperty("systemUrl")] - public string SystemUrl => ConfigReader.ConfigObject.SystemUrl; + [JsonProperty("systemUrl")] + public string SystemUrl => ConfigReader.ConfigObject.SystemUrl; - [JsonProperty("userCode")] - public string UserCode => mcController.RoomBridges.Count > 0 ? mcController.RoomBridges[0].UserCode : "Not available"; + [JsonProperty("userCode")] + public string UserCode => mcController.RoomBridges.Count > 0 ? mcController.RoomBridges[0].UserCode : "Not available"; - [JsonProperty("connected")] - public bool Connected => mcController.Connected; + [JsonProperty("connected")] + public bool Connected => mcController.Connected; - [JsonProperty("secondsSinceLastAck")] - public int SecondsSinceLastAck => (DateTime.Now - mcController.LastAckMessage).Seconds; + [JsonProperty("secondsSinceLastAck")] + public int SecondsSinceLastAck => (DateTime.Now - mcController.LastAckMessage).Seconds; - public MobileControlEdgeServer(MobileControlSystemController controller) - { - mcController = controller; - } + public MobileControlEdgeServer(MobileControlSystemController controller) + { + mcController = controller; } +} - public class MobileControlDirectServer - { - [JsonIgnore] - private readonly MobileControlWebsocketServer directServer; +public class MobileControlDirectServer +{ + [JsonIgnore] + private readonly MobileControlWebsocketServer directServer; - [JsonProperty("userAppUrl")] - public string UserAppUrl => $"{directServer.UserAppUrlPrefix}/[insert_client_token]"; + [JsonProperty("userAppUrl")] + public string UserAppUrl => $"{directServer.UserAppUrlPrefix}/[insert_client_token]"; - [JsonProperty("serverPort")] - public int ServerPort => directServer.Port; + [JsonProperty("serverPort")] + public int ServerPort => directServer.Port; - [JsonProperty("tokensDefined")] - public int TokensDefined => directServer.UiClients.Count; + [JsonProperty("tokensDefined")] + public int TokensDefined => directServer.UiClients.Count; - [JsonProperty("clientsConnected")] - public int ClientsConnected => directServer.ConnectedUiClientsCount; + [JsonProperty("clientsConnected")] + public int ClientsConnected => directServer.ConnectedUiClientsCount; - [JsonProperty("clients")] - public List Clients => directServer.UiClients.Select((c, i) => { return new MobileControlDirectClient(c, i, directServer.UserAppUrlPrefix); }).ToList(); + [JsonProperty("clients")] + public List Clients => directServer.UiClients.Select((c, i) => { return new MobileControlDirectClient(c, i, directServer.UserAppUrlPrefix); }).ToList(); - public MobileControlDirectServer(MobileControlWebsocketServer server) - { - directServer = server; - } + public MobileControlDirectServer(MobileControlWebsocketServer server) + { + directServer = server; } +} - public class MobileControlDirectClient - { - [JsonIgnore] - private readonly UiClientContext context; +public class MobileControlDirectClient +{ + [JsonIgnore] + private readonly UiClientContext context; - [JsonIgnore] - private readonly string Key; + [JsonIgnore] + private readonly string Key; - [JsonIgnore] - private readonly int clientNumber; + [JsonIgnore] + private readonly int clientNumber; - [JsonIgnore] - private readonly string urlPrefix; + [JsonIgnore] + private readonly string urlPrefix; - [JsonProperty("clientNumber")] - public string ClientNumber => $"{clientNumber}"; + [JsonProperty("clientNumber")] + public string ClientNumber => $"{clientNumber}"; - [JsonProperty("roomKey")] - public string RoomKey => context.Token.RoomKey; + [JsonProperty("roomKey")] + public string RoomKey => context.Token.RoomKey; - [JsonProperty("touchpanelKey")] - public string TouchpanelKey => context.Token.TouchpanelKey; + [JsonProperty("touchpanelKey")] + public string TouchpanelKey => context.Token.TouchpanelKey; - [JsonProperty("url")] - public string Url => $"{urlPrefix}{Key}"; + [JsonProperty("url")] + public string Url => $"{urlPrefix}{Key}"; - [JsonProperty("token")] - public string Token => Key; + [JsonProperty("token")] + public string Token => Key; - [JsonProperty("connected")] - public bool Connected => context.Client != null && context.Client.Context.WebSocket.IsAlive; + [JsonProperty("connected")] + public bool Connected => context.Client != null && context.Client.Context.WebSocket.IsAlive; - [JsonProperty("duration")] - public double Duration => context.Client == null ? 0 : context.Client.ConnectedDuration.TotalSeconds; + [JsonProperty("duration")] + public double Duration => context.Client == null ? 0 : context.Client.ConnectedDuration.TotalSeconds; - public MobileControlDirectClient(KeyValuePair clientContext, int index, string urlPrefix) - { - context = clientContext.Value; - Key = clientContext.Key; - clientNumber = index; - this.urlPrefix = urlPrefix; - } + public MobileControlDirectClient(KeyValuePair clientContext, int index, string urlPrefix) + { + context = clientContext.Value; + Key = clientContext.Key; + clientNumber = index; + this.urlPrefix = urlPrefix; } } diff --git a/src/PepperDash.Essentials.MobileControl/WebApiHandlers/UiClientHandler.cs b/src/PepperDash.Essentials.MobileControl/WebApiHandlers/UiClientHandler.cs index 73fdb1044..4732fc4e8 100644 --- a/src/PepperDash.Essentials.MobileControl/WebApiHandlers/UiClientHandler.cs +++ b/src/PepperDash.Essentials.MobileControl/WebApiHandlers/UiClientHandler.cs @@ -6,161 +6,160 @@ using PepperDash.Essentials.WebSocketServer; using Serilog.Events; -namespace PepperDash.Essentials.WebApiHandlers +namespace PepperDash.Essentials.WebApiHandlers; + +public class UiClientHandler : WebApiBaseRequestHandler { - public class UiClientHandler : WebApiBaseRequestHandler + private readonly MobileControlWebsocketServer server; + public UiClientHandler(MobileControlWebsocketServer directServer) : base(true) { - private readonly MobileControlWebsocketServer server; - public UiClientHandler(MobileControlWebsocketServer directServer) : base(true) - { - server = directServer; - } - - protected override void HandlePost(HttpCwsContext context) - { - var req = context.Request; - var res = context.Response; - var body = EssentialsWebApiHelpers.GetRequestBody(req); - - var request = JsonConvert.DeserializeObject(body); - - var response = new ClientResponse(); - - if (string.IsNullOrEmpty(request?.RoomKey)) - { - response.Error = "roomKey is required"; - - res.StatusCode = 400; - res.ContentType = "application/json"; - res.Headers.Add("Content-Type", "application/json"); - res.Write(JsonConvert.SerializeObject(response), false); - res.End(); - return; - } + server = directServer; + } - if (string.IsNullOrEmpty(request.GrantCode)) - { - response.Error = "grantCode is required"; + protected override void HandlePost(HttpCwsContext context) + { + var req = context.Request; + var res = context.Response; + var body = EssentialsWebApiHelpers.GetRequestBody(req); - res.StatusCode = 400; - res.ContentType = "application/json"; - res.Headers.Add("Content-Type", "application/json"); - res.Write(JsonConvert.SerializeObject(response), false); - res.End(); - return; - } + var request = JsonConvert.DeserializeObject(body); - var (token, path) = server.ValidateGrantCode(request.GrantCode, request.RoomKey); + var response = new ClientResponse(); - response.Token = token; - response.Path = path; + if (string.IsNullOrEmpty(request?.RoomKey)) + { + response.Error = "roomKey is required"; - res.StatusCode = 200; + res.StatusCode = 400; res.ContentType = "application/json"; res.Headers.Add("Content-Type", "application/json"); res.Write(JsonConvert.SerializeObject(response), false); res.End(); + return; } - protected override void HandleDelete(HttpCwsContext context) + if (string.IsNullOrEmpty(request.GrantCode)) { - var req = context.Request; - var res = context.Response; - var body = EssentialsWebApiHelpers.GetRequestBody(req); + response.Error = "grantCode is required"; - var request = JsonConvert.DeserializeObject(body); + res.StatusCode = 400; + res.ContentType = "application/json"; + res.Headers.Add("Content-Type", "application/json"); + res.Write(JsonConvert.SerializeObject(response), false); + res.End(); + return; + } + var (token, path) = server.ValidateGrantCode(request.GrantCode, request.RoomKey); + response.Token = token; + response.Path = path; - if (string.IsNullOrEmpty(request?.Token)) - { - var response = new ClientResponse - { - Error = "token is required" - }; + res.StatusCode = 200; + res.ContentType = "application/json"; + res.Headers.Add("Content-Type", "application/json"); + res.Write(JsonConvert.SerializeObject(response), false); + res.End(); + } - res.StatusCode = 400; - res.ContentType = "application/json"; - res.Headers.Add("Content-Type", "application/json"); - res.Write(JsonConvert.SerializeObject(response), false); - res.End(); + protected override void HandleDelete(HttpCwsContext context) + { + var req = context.Request; + var res = context.Response; + var body = EssentialsWebApiHelpers.GetRequestBody(req); - return; - } + var request = JsonConvert.DeserializeObject(body); - if (!server.UiClients.TryGetValue(request.Token, out UiClientContext clientContext)) + if (string.IsNullOrEmpty(request?.Token)) + { + var response = new ClientResponse { - var response = new ClientResponse - { - Error = $"Unable to find client with token: {request.Token}" - }; + Error = "token is required" + }; - res.StatusCode = 200; - res.ContentType = "application/json"; - res.Headers.Add("Content-Type", "application/json"); - res.Write(JsonConvert.SerializeObject(response), false); - res.End(); + res.StatusCode = 400; + res.ContentType = "application/json"; + res.Headers.Add("Content-Type", "application/json"); + res.Write(JsonConvert.SerializeObject(response), false); + res.End(); - return; - } + return; + } - if (clientContext.Client != null && clientContext.Client.Context.WebSocket.IsAlive) - { - clientContext.Client.Context.WebSocket.Close(WebSocketSharp.CloseStatusCode.Normal, "Token removed from server"); - } - var path = server.WsPath + request.Token; - if (!server.Server.RemoveWebSocketService(path)) + if (!server.UiClients.TryGetValue(request.Token, out UiClientContext clientContext)) + { + var response = new ClientResponse { - Debug.LogMessage(LogEventLevel.Warning, "Unable to remove client with token {token}", request.Token); + Error = $"Unable to find client with token: {request.Token}" + }; - var response = new ClientResponse - { - Error = $"Unable to remove client with token {request.Token}" - }; + res.StatusCode = 200; + res.ContentType = "application/json"; + res.Headers.Add("Content-Type", "application/json"); + res.Write(JsonConvert.SerializeObject(response), false); + res.End(); - res.StatusCode = 500; - res.ContentType = "application/json"; - res.Headers.Add("Content-Type", "application/json"); - res.Write(JsonConvert.SerializeObject(response), false); - res.End(); + return; + } - return; - } + if (clientContext.Client != null && clientContext.Client.Context.WebSocket.IsAlive) + { + clientContext.Client.Context.WebSocket.Close(WebSocketSharp.CloseStatusCode.Normal, "Token removed from server"); + } - server.UiClients.Remove(request.Token); + var path = server.WsPath + request.Token; - server.UpdateSecret(); + if (!server.Server.RemoveWebSocketService(path)) + { + Debug.LogMessage(LogEventLevel.Warning, "Unable to remove client with token {token}", request.Token); - res.StatusCode = 200; + var response = new ClientResponse + { + Error = $"Unable to remove client with token {request.Token}" + }; + + res.StatusCode = 500; + res.ContentType = "application/json"; + res.Headers.Add("Content-Type", "application/json"); + res.Write(JsonConvert.SerializeObject(response), false); res.End(); + + return; } - } - public class ClientRequest - { - [JsonProperty("roomKey", NullValueHandling = NullValueHandling.Ignore)] - public string RoomKey { get; set; } + server.UiClients.Remove(request.Token); - [JsonProperty("grantCode", NullValueHandling = NullValueHandling.Ignore)] - public string GrantCode { get; set; } + server.UpdateSecret(); - [JsonProperty("token", NullValueHandling = NullValueHandling.Ignore)] - public string Token { get; set; } + res.StatusCode = 200; + res.End(); } +} - public class ClientResponse - { - [JsonProperty("error", NullValueHandling = NullValueHandling.Ignore)] - public string Error { get; set; } +public class ClientRequest +{ + [JsonProperty("roomKey", NullValueHandling = NullValueHandling.Ignore)] + public string RoomKey { get; set; } - [JsonProperty("token", NullValueHandling = NullValueHandling.Ignore)] - public string Token { get; set; } + [JsonProperty("grantCode", NullValueHandling = NullValueHandling.Ignore)] + public string GrantCode { get; set; } - [JsonProperty("path", NullValueHandling = NullValueHandling.Ignore)] - public string Path { get; set; } - } + [JsonProperty("token", NullValueHandling = NullValueHandling.Ignore)] + public string Token { get; set; } +} + +public class ClientResponse +{ + [JsonProperty("error", NullValueHandling = NullValueHandling.Ignore)] + public string Error { get; set; } + + [JsonProperty("token", NullValueHandling = NullValueHandling.Ignore)] + public string Token { get; set; } + + [JsonProperty("path", NullValueHandling = NullValueHandling.Ignore)] + public string Path { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl/WebSocketServer/MobileControlWebsocketServer.cs b/src/PepperDash.Essentials.MobileControl/WebSocketServer/MobileControlWebsocketServer.cs index 859a7c7b0..e74ba0162 100644 --- a/src/PepperDash.Essentials.MobileControl/WebSocketServer/MobileControlWebsocketServer.cs +++ b/src/PepperDash.Essentials.MobileControl/WebSocketServer/MobileControlWebsocketServer.cs @@ -20,1262 +20,1261 @@ using WebSocketSharp.Server; -namespace PepperDash.Essentials.WebSocketServer +namespace PepperDash.Essentials.WebSocketServer; + +public class MobileControlWebsocketServer : EssentialsDevice { - public class MobileControlWebsocketServer : EssentialsDevice - { - private readonly string userAppPath = Global.FilePathPrefix + "mcUserApp" + Global.DirectorySeparator; + private readonly string userAppPath = Global.FilePathPrefix + "mcUserApp" + Global.DirectorySeparator; - private readonly string localConfigFolderName = "_local-config"; + private readonly string localConfigFolderName = "_local-config"; - private readonly string appConfigFileName = "_config.local.json"; - private readonly string appConfigCsFileName = "_config.cs.json"; + private readonly string appConfigFileName = "_config.local.json"; + private readonly string appConfigCsFileName = "_config.cs.json"; - /// - /// Where the key is the join token and the value is the room key - /// - //private Dictionary _joinTokens; + /// + /// Where the key is the join token and the value is the room key + /// + //private Dictionary _joinTokens; - private HttpServer _server; + private HttpServer _server; - public HttpServer Server => _server; + public HttpServer Server => _server; - public Dictionary UiClients { get; private set; } + public Dictionary UiClients { get; private set; } - private readonly MobileControlSystemController _parent; + private readonly MobileControlSystemController _parent; - private WebSocketServerSecretProvider _secretProvider; + private WebSocketServerSecretProvider _secretProvider; - private ServerTokenSecrets _secret; + private ServerTokenSecrets _secret; - private static readonly HttpClient LogClient = new HttpClient(); + private static readonly HttpClient LogClient = new HttpClient(); - private string SecretProviderKey + private string SecretProviderKey + { + get { - get - { - return string.Format("{0}:{1}-tokens", Global.ControlSystem.ProgramNumber, Key); - } + return string.Format("{0}:{1}-tokens", Global.ControlSystem.ProgramNumber, Key); } + } - private string lanIpAddress => CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetLANAdapter)); + private string lanIpAddress => CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetLANAdapter)); - private System.Net.IPAddress csIpAddress; + private System.Net.IPAddress csIpAddress; - private System.Net.IPAddress csSubnetMask; + private System.Net.IPAddress csSubnetMask; - /// - /// The path for the WebSocket messaging - /// - private readonly string _wsPath = "/mc/api/ui/join/"; + /// + /// The path for the WebSocket messaging + /// + private readonly string _wsPath = "/mc/api/ui/join/"; - public string WsPath => _wsPath; + public string WsPath => _wsPath; - /// - /// The path to the location of the files for the user app (single page Angular app) - /// - private readonly string _appPath = string.Format("{0}mcUserApp", Global.FilePathPrefix); + /// + /// The path to the location of the files for the user app (single page Angular app) + /// + private readonly string _appPath = string.Format("{0}mcUserApp", Global.FilePathPrefix); - /// - /// The base HREF that the user app uses - /// - private string _userAppBaseHref = "/mc/app"; + /// + /// The base HREF that the user app uses + /// + private string _userAppBaseHref = "/mc/app"; - /// - /// The port the server will run on - /// - public int Port { get; private set; } + /// + /// The port the server will run on + /// + public int Port { get; private set; } - public string UserAppUrlPrefix + public string UserAppUrlPrefix + { + get { - get - { - return string.Format("http://{0}:{1}{2}?token=", - CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0), - Port, - _userAppBaseHref); + return string.Format("http://{0}:{1}{2}?token=", + CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0), + Port, + _userAppBaseHref); - } } + } - public int ConnectedUiClientsCount + public int ConnectedUiClientsCount + { + get { - get - { - var count = 0; + var count = 0; - foreach (var client in UiClients) + foreach (var client in UiClients) + { + if (client.Value.Client != null && client.Value.Client.Context.WebSocket.IsAlive) { - if (client.Value.Client != null && client.Value.Client.Context.WebSocket.IsAlive) - { - count++; - } + count++; } - - return count; } + + return count; } + } - public MobileControlWebsocketServer(string key, int customPort, MobileControlSystemController parent) - : base(key) - { - _parent = parent; + public MobileControlWebsocketServer(string key, int customPort, MobileControlSystemController parent) + : base(key) + { + _parent = parent; - // Set the default port to be 50000 plus the slot number of the program - Port = 50000 + (int)Global.ControlSystem.ProgramNumber; + // Set the default port to be 50000 plus the slot number of the program + Port = 50000 + (int)Global.ControlSystem.ProgramNumber; - if (customPort != 0) - { - Port = customPort; - } + if (customPort != 0) + { + Port = customPort; + } - if (parent.Config.DirectServer.AutomaticallyForwardPortToCSLAN == true) + if (parent.Config.DirectServer.AutomaticallyForwardPortToCSLAN == true) + { + try { - try - { - Debug.LogMessage(LogEventLevel.Information, "Automatically forwarding port {0} to CS LAN", Port); + Debug.LogMessage(LogEventLevel.Information, "Automatically forwarding port {0} to CS LAN", Port); - var csAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetCSAdapter); - var csIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, csAdapterId); + var csAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetCSAdapter); + var csIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, csAdapterId); - var result = CrestronEthernetHelper.AddPortForwarding((ushort)Port, (ushort)Port, csIp, CrestronEthernetHelper.ePortMapTransport.TCP); + var result = CrestronEthernetHelper.AddPortForwarding((ushort)Port, (ushort)Port, csIp, CrestronEthernetHelper.ePortMapTransport.TCP); - if (result != CrestronEthernetHelper.PortForwardingUserPatRetCodes.NoErr) - { - Debug.LogMessage(LogEventLevel.Error, "Error adding port forwarding: {0}", result); - } - } - catch (ArgumentException) + if (result != CrestronEthernetHelper.PortForwardingUserPatRetCodes.NoErr) { - Debug.LogMessage(LogEventLevel.Information, "This processor does not have a CS LAN", this); + Debug.LogMessage(LogEventLevel.Error, "Error adding port forwarding: {0}", result); } - catch (Exception ex) - { - Debug.LogMessage(ex, "Error automatically forwarding port to CS LAN"); - } - } - - try - { - var csAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetCSAdapter); - var csSubnetMask = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, csAdapterId); - var csIpAddress = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, csAdapterId); - - this.csSubnetMask = System.Net.IPAddress.Parse(csSubnetMask); - this.csIpAddress = System.Net.IPAddress.Parse(csIpAddress); } catch (ArgumentException) { - if (parent.Config.DirectServer.AutomaticallyForwardPortToCSLAN == false) - { - Debug.LogMessage(LogEventLevel.Information, "This processor does not have a CS LAN", this); - } + Debug.LogMessage(LogEventLevel.Information, "This processor does not have a CS LAN", this); } - - - UiClients = new Dictionary(); - - //_joinTokens = new Dictionary(); - - if (Global.Platform == eDevicePlatform.Appliance) + catch (Exception ex) { - AddConsoleCommands(); + Debug.LogMessage(ex, "Error automatically forwarding port to CS LAN"); } - - AddPreActivationAction(() => AddWebApiPaths()); } - private void AddWebApiPaths() - { - var apiServer = DeviceManager.AllDevices.OfType().FirstOrDefault(); + try + { + var csAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetCSAdapter); + var csSubnetMask = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, csAdapterId); + var csIpAddress = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, csAdapterId); - if (apiServer == null) + this.csSubnetMask = System.Net.IPAddress.Parse(csSubnetMask); + this.csIpAddress = System.Net.IPAddress.Parse(csIpAddress); + } + catch (ArgumentException) + { + if (parent.Config.DirectServer.AutomaticallyForwardPortToCSLAN == false) { - this.LogInformation("No API Server available"); - return; + Debug.LogMessage(LogEventLevel.Information, "This processor does not have a CS LAN", this); } + } - var routes = new List - { - new HttpCwsRoute($"devices/{Key}/client") - { - Name = "ClientHandler", - RouteHandler = new UiClientHandler(this) - }, - }; - apiServer.AddRoute(routes); - } + UiClients = new Dictionary(); + + //_joinTokens = new Dictionary(); - private void AddConsoleCommands() + if (Global.Platform == eDevicePlatform.Appliance) { - CrestronConsole.AddNewConsoleCommand(GenerateClientTokenFromConsole, "MobileAddUiClient", "Adds a client and generates a token. ? for more help", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(RemoveToken, "MobileRemoveUiClient", "Removes a client. ? for more help", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand((s) => PrintClientInfo(), "MobileGetClientInfo", "Displays the current client info", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(RemoveAllTokens, "MobileRemoveAllClients", "Removes all clients", ConsoleAccessLevelEnum.AccessOperator); + AddConsoleCommands(); } + AddPreActivationAction(() => AddWebApiPaths()); + } + + private void AddWebApiPaths() + { + var apiServer = DeviceManager.AllDevices.OfType().FirstOrDefault(); - public override void Initialize() + if (apiServer == null) { - try + this.LogInformation("No API Server available"); + return; + } + + var routes = new List + { + new HttpCwsRoute($"devices/{Key}/client") { - base.Initialize(); + Name = "ClientHandler", + RouteHandler = new UiClientHandler(this) + }, + }; - _server = new HttpServer(Port, false); + apiServer.AddRoute(routes); + } - _server.OnGet += Server_OnGet; + private void AddConsoleCommands() + { + CrestronConsole.AddNewConsoleCommand(GenerateClientTokenFromConsole, "MobileAddUiClient", "Adds a client and generates a token. ? for more help", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(RemoveToken, "MobileRemoveUiClient", "Removes a client. ? for more help", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand((s) => PrintClientInfo(), "MobileGetClientInfo", "Displays the current client info", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(RemoveAllTokens, "MobileRemoveAllClients", "Removes all clients", ConsoleAccessLevelEnum.AccessOperator); + } - _server.OnOptions += Server_OnOptions; - if (_parent.Config.DirectServer.Logging.EnableRemoteLogging) - { - _server.OnPost += Server_OnPost; - } + public override void Initialize() + { + try + { + base.Initialize(); - CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler; + _server = new HttpServer(Port, false); - _server.Start(); + _server.OnGet += Server_OnGet; - if (_server.IsListening) - { - Debug.LogMessage(LogEventLevel.Information, "Mobile Control WebSocket Server listening on port {port}", this, _server.Port); - } + _server.OnOptions += Server_OnOptions; - CrestronEnvironment.ProgramStatusEventHandler += OnProgramStop; + if (_parent.Config.DirectServer.Logging.EnableRemoteLogging) + { + _server.OnPost += Server_OnPost; + } - RetrieveSecret(); + CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler; - CreateFolderStructure(); + _server.Start(); - AddClientsForTouchpanels(); - } - catch (Exception ex) + if (_server.IsListening) { - Debug.LogMessage(ex, "Exception intializing websocket server", this); + Debug.LogMessage(LogEventLevel.Information, "Mobile Control WebSocket Server listening on port {port}", this, _server.Port); } - } - private void AddClientsForTouchpanels() + CrestronEnvironment.ProgramStatusEventHandler += OnProgramStop; + + RetrieveSecret(); + + CreateFolderStructure(); + + AddClientsForTouchpanels(); + } + catch (Exception ex) { - var touchpanels = DeviceManager.AllDevices - .OfType().Where(tp => tp.UseDirectServer); + Debug.LogMessage(ex, "Exception intializing websocket server", this); + } + } + private void AddClientsForTouchpanels() + { + var touchpanels = DeviceManager.AllDevices + .OfType().Where(tp => tp.UseDirectServer); - var touchpanelsToAdd = new List(); - if (_secret != null) - { - var newTouchpanels = touchpanels.Where(tp => !_secret.Tokens.Any(t => t.Value.TouchpanelKey != null && t.Value.TouchpanelKey.Equals(tp.Key, StringComparison.InvariantCultureIgnoreCase))); + var touchpanelsToAdd = new List(); - touchpanelsToAdd.AddRange(newTouchpanels); - } - else - { - touchpanelsToAdd.AddRange(touchpanels); - } + if (_secret != null) + { + var newTouchpanels = touchpanels.Where(tp => !_secret.Tokens.Any(t => t.Value.TouchpanelKey != null && t.Value.TouchpanelKey.Equals(tp.Key, StringComparison.InvariantCultureIgnoreCase))); - foreach (var client in touchpanelsToAdd) - { - var bridge = _parent.GetRoomBridge(client.DefaultRoomKey); + touchpanelsToAdd.AddRange(newTouchpanels); + } + else + { + touchpanelsToAdd.AddRange(touchpanels); + } - if (bridge == null) - { - this.LogWarning("Unable to find room with key: {defaultRoomKey}", client.DefaultRoomKey); - return; - } + foreach (var client in touchpanelsToAdd) + { + var bridge = _parent.GetRoomBridge(client.DefaultRoomKey); + + if (bridge == null) + { + this.LogWarning("Unable to find room with key: {defaultRoomKey}", client.DefaultRoomKey); + return; + } - var (key, path) = GenerateClientToken(bridge, client.Key); + var (key, path) = GenerateClientToken(bridge, client.Key); - if (key == null) - { - this.LogWarning("Unable to generate a client for {clientKey}", client.Key); - continue; - } + if (key == null) + { + this.LogWarning("Unable to generate a client for {clientKey}", client.Key); + continue; } + } - var lanAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetLANAdapter); + var lanAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetLANAdapter); - var processorIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, lanAdapterId); + var processorIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, lanAdapterId); - this.LogVerbose("Processor IP: {processorIp}", processorIp); + this.LogVerbose("Processor IP: {processorIp}", processorIp); - foreach (var touchpanel in touchpanels.Select(tp => - { - var token = _secret.Tokens.FirstOrDefault((t) => t.Value.TouchpanelKey.Equals(tp.Key, StringComparison.InvariantCultureIgnoreCase)); + foreach (var touchpanel in touchpanels.Select(tp => + { + var token = _secret.Tokens.FirstOrDefault((t) => t.Value.TouchpanelKey.Equals(tp.Key, StringComparison.InvariantCultureIgnoreCase)); - var messenger = _parent.GetRoomBridge(tp.DefaultRoomKey); + var messenger = _parent.GetRoomBridge(tp.DefaultRoomKey); - return new { token.Key, Touchpanel = tp, Messenger = messenger }; - })) + return new { token.Key, Touchpanel = tp, Messenger = messenger }; + })) + { + if (touchpanel.Key == null) { - if (touchpanel.Key == null) - { - this.LogWarning("Token for touchpanel {touchpanelKey} not found", touchpanel.Touchpanel.Key); - continue; - } + this.LogWarning("Token for touchpanel {touchpanelKey} not found", touchpanel.Touchpanel.Key); + continue; + } - if (touchpanel.Messenger == null) - { - this.LogWarning("Unable to find room messenger for {defaultRoomKey}", touchpanel.Touchpanel.DefaultRoomKey); - continue; - } + if (touchpanel.Messenger == null) + { + this.LogWarning("Unable to find room messenger for {defaultRoomKey}", touchpanel.Touchpanel.DefaultRoomKey); + continue; + } - var appUrl = $"http://{processorIp}:{_parent.Config.DirectServer.Port}/mc/app?token={touchpanel.Key}"; + var appUrl = $"http://{processorIp}:{_parent.Config.DirectServer.Port}/mc/app?token={touchpanel.Key}"; - this.LogVerbose("Sending URL {appUrl}", appUrl); + this.LogVerbose("Sending URL {appUrl}", appUrl); - touchpanel.Messenger.UpdateAppUrl($"http://{processorIp}:{_parent.Config.DirectServer.Port}/mc/app?token={touchpanel.Key}"); - } + touchpanel.Messenger.UpdateAppUrl($"http://{processorIp}:{_parent.Config.DirectServer.Port}/mc/app?token={touchpanel.Key}"); } + } - private void OnProgramStop(eProgramStatusEventType programEventType) + private void OnProgramStop(eProgramStatusEventType programEventType) + { + switch (programEventType) { - switch (programEventType) - { - case eProgramStatusEventType.Stopping: - _server.Stop(); - break; - } + case eProgramStatusEventType.Stopping: + _server.Stop(); + break; } + } - private void CreateFolderStructure() + private void CreateFolderStructure() + { + if (!Directory.Exists(userAppPath)) { - if (!Directory.Exists(userAppPath)) - { - Directory.CreateDirectory(userAppPath); - } + Directory.CreateDirectory(userAppPath); + } - if (!Directory.Exists($"{userAppPath}{localConfigFolderName}")) - { - Directory.CreateDirectory($"{userAppPath}{localConfigFolderName}"); - } + if (!Directory.Exists($"{userAppPath}{localConfigFolderName}")) + { + Directory.CreateDirectory($"{userAppPath}{localConfigFolderName}"); + } - using (var sw = new StreamWriter(File.Open($"{userAppPath}{localConfigFolderName}{Global.DirectorySeparator}{appConfigFileName}", FileMode.Create, FileAccess.ReadWrite))) - { - // Write the LAN application configuration file. Used when a request comes in for the application config from the LAN - var lanAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetLANAdapter); + using (var sw = new StreamWriter(File.Open($"{userAppPath}{localConfigFolderName}{Global.DirectorySeparator}{appConfigFileName}", FileMode.Create, FileAccess.ReadWrite))) + { + // Write the LAN application configuration file. Used when a request comes in for the application config from the LAN + var lanAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetLANAdapter); - this.LogDebug("LAN Adapter ID: {lanAdapterId}", lanAdapterId); + this.LogDebug("LAN Adapter ID: {lanAdapterId}", lanAdapterId); - var processorIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, lanAdapterId); + var processorIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, lanAdapterId); - var config = GetApplicationConfig(processorIp); + var config = GetApplicationConfig(processorIp); - var contents = JsonConvert.SerializeObject(config, Formatting.Indented); + var contents = JsonConvert.SerializeObject(config, Formatting.Indented); - sw.Write(contents); - } + sw.Write(contents); + } - short csAdapterId; - try - { - csAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetCSAdapter); - } - catch (ArgumentException) - { - this.LogDebug("This processor does not have a CS LAN"); - return; - } + short csAdapterId; + try + { + csAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetCSAdapter); + } + catch (ArgumentException) + { + this.LogDebug("This processor does not have a CS LAN"); + return; + } - if(csAdapterId == -1) - { - this.LogDebug("CS LAN Adapter not found"); - return; - } + if(csAdapterId == -1) + { + this.LogDebug("CS LAN Adapter not found"); + return; + } - this.LogDebug("CS LAN Adapter ID: {csAdapterId}. Adding CS Config", csAdapterId); + this.LogDebug("CS LAN Adapter ID: {csAdapterId}. Adding CS Config", csAdapterId); - using (var sw = new StreamWriter(File.Open($"{userAppPath}{localConfigFolderName}{Global.DirectorySeparator}{appConfigCsFileName}", FileMode.Create, FileAccess.ReadWrite))) - { - // Write the CS application configuration file. Used when a request comes in for the application config from the CS - var processorIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, csAdapterId); - - var config = GetApplicationConfig(processorIp); + using (var sw = new StreamWriter(File.Open($"{userAppPath}{localConfigFolderName}{Global.DirectorySeparator}{appConfigCsFileName}", FileMode.Create, FileAccess.ReadWrite))) + { + // Write the CS application configuration file. Used when a request comes in for the application config from the CS + var processorIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, csAdapterId); + + var config = GetApplicationConfig(processorIp); - var contents = JsonConvert.SerializeObject(config, Formatting.Indented); + var contents = JsonConvert.SerializeObject(config, Formatting.Indented); - sw.Write(contents); - } + sw.Write(contents); } + } - private MobileControlApplicationConfig GetApplicationConfig(string processorIp) - { - try - { - var config = new MobileControlApplicationConfig + private MobileControlApplicationConfig GetApplicationConfig(string processorIp) + { + try + { + var config = new MobileControlApplicationConfig + { + ApiPath = string.Format("http://{0}:{1}/mc/api", processorIp, _parent.Config.DirectServer.Port), + GatewayAppPath = "", + LogoPath = _parent.Config.ApplicationConfig?.LogoPath ?? "logo/logo.png", + EnableDev = _parent.Config.ApplicationConfig?.EnableDev ?? false, + IconSet = _parent.Config.ApplicationConfig?.IconSet ?? MCIconSet.GOOGLE, + LoginMode = _parent.Config.ApplicationConfig?.LoginMode ?? "room-list", + Modes = _parent.Config.ApplicationConfig?.Modes ?? new Dictionary { - ApiPath = string.Format("http://{0}:{1}/mc/api", processorIp, _parent.Config.DirectServer.Port), - GatewayAppPath = "", - LogoPath = _parent.Config.ApplicationConfig?.LogoPath ?? "logo/logo.png", - EnableDev = _parent.Config.ApplicationConfig?.EnableDev ?? false, - IconSet = _parent.Config.ApplicationConfig?.IconSet ?? MCIconSet.GOOGLE, - LoginMode = _parent.Config.ApplicationConfig?.LoginMode ?? "room-list", - Modes = _parent.Config.ApplicationConfig?.Modes ?? new Dictionary { - { - "room-list", - new McMode { - ListPageText = "Please select your room", - LoginHelpText = "Please select your room from the list, then enter the code shown on the display.", - PasscodePageText = "Please enter the code shown on this room's display" - } + "room-list", + new McMode { + ListPageText = "Please select your room", + LoginHelpText = "Please select your room from the list, then enter the code shown on the display.", + PasscodePageText = "Please enter the code shown on this room's display" } - }, - Logging = _parent.Config.ApplicationConfig?.Logging ?? false, - PartnerMetadata = _parent.Config.ApplicationConfig?.PartnerMetadata ?? new List() - }; - - return config; - } - catch (Exception ex) - { - this.LogError(ex, "Error getting application configuration"); + } + }, + Logging = _parent.Config.ApplicationConfig?.Logging ?? false, + PartnerMetadata = _parent.Config.ApplicationConfig?.PartnerMetadata ?? new List() + }; - return null; - } + return config; } + catch (Exception ex) + { + this.LogError(ex, "Error getting application configuration"); + + return null; + } + } - /// - /// Attempts to retrieve secrets previously stored in memory - /// - private void RetrieveSecret() + /// + /// Attempts to retrieve secrets previously stored in memory + /// + private void RetrieveSecret() + { + try { - try - { - // Add secret provider - _secretProvider = new WebSocketServerSecretProvider(SecretProviderKey); + // Add secret provider + _secretProvider = new WebSocketServerSecretProvider(SecretProviderKey); - // Check for existing secrets - var secret = _secretProvider.GetSecret(SecretProviderKey); + // Check for existing secrets + var secret = _secretProvider.GetSecret(SecretProviderKey); - if (secret != null) - { - Debug.LogMessage(LogEventLevel.Information, "Secret successfully retrieved", this); + if (secret != null) + { + Debug.LogMessage(LogEventLevel.Information, "Secret successfully retrieved", this); - Debug.LogMessage(LogEventLevel.Debug, "Secret: {0}", this, secret.Value.ToString()); + Debug.LogMessage(LogEventLevel.Debug, "Secret: {0}", this, secret.Value.ToString()); - // populate the local secrets object - _secret = JsonConvert.DeserializeObject(secret.Value.ToString()); + // populate the local secrets object + _secret = JsonConvert.DeserializeObject(secret.Value.ToString()); - if (_secret != null && _secret.Tokens != null) + if (_secret != null && _secret.Tokens != null) + { + // populate the _uiClient collection + foreach (var token in _secret.Tokens) { - // populate the _uiClient collection - foreach (var token in _secret.Tokens) + if (token.Value == null) { - if (token.Value == null) - { - Debug.LogMessage(LogEventLevel.Warning, "Token value is null", this); - continue; - } - - Debug.LogMessage(LogEventLevel.Information, "Adding token: {0} for room: {1}", this, token.Key, token.Value.RoomKey); + Debug.LogMessage(LogEventLevel.Warning, "Token value is null", this); + continue; + } - if (UiClients == null) - { - Debug.LogMessage(LogEventLevel.Warning, "UiClients is null", this); - UiClients = new Dictionary(); - } + Debug.LogMessage(LogEventLevel.Information, "Adding token: {0} for room: {1}", this, token.Key, token.Value.RoomKey); - UiClients.Add(token.Key, new UiClientContext(token.Value)); + if (UiClients == null) + { + Debug.LogMessage(LogEventLevel.Warning, "UiClients is null", this); + UiClients = new Dictionary(); } + + UiClients.Add(token.Key, new UiClientContext(token.Value)); } + } - if (UiClients.Count > 0) + if (UiClients.Count > 0) + { + Debug.LogMessage(LogEventLevel.Information, "Restored {uiClientCount} UiClients from secrets data", this, UiClients.Count); + + foreach (var client in UiClients) { - Debug.LogMessage(LogEventLevel.Information, "Restored {uiClientCount} UiClients from secrets data", this, UiClients.Count); + var key = client.Key; + var path = _wsPath + key; + var roomKey = client.Value.Token.RoomKey; - foreach (var client in UiClients) + _server.AddWebSocketService(path, () => { - var key = client.Key; - var path = _wsPath + key; - var roomKey = client.Value.Token.RoomKey; - - _server.AddWebSocketService(path, () => - { - var c = new UiClient(); - Debug.LogMessage(LogEventLevel.Debug, "Constructing UiClient with id: {key}", this, key); - - c.Controller = _parent; - c.RoomKey = roomKey; - UiClients[key].SetClient(c); - return c; - }); - - - //_server.WebSocketServices.AddService(path, (c) => - //{ - // Debug.Console(2, this, "Constructing UiClient with id: {0}", key); - // c.Controller = _parent; - // c.RoomKey = roomKey; - // UiClients[key].SetClient(c); - //}); - } + var c = new UiClient(); + Debug.LogMessage(LogEventLevel.Debug, "Constructing UiClient with id: {key}", this, key); + + c.Controller = _parent; + c.RoomKey = roomKey; + UiClients[key].SetClient(c); + return c; + }); + + + //_server.WebSocketServices.AddService(path, (c) => + //{ + // Debug.Console(2, this, "Constructing UiClient with id: {0}", key); + // c.Controller = _parent; + // c.RoomKey = roomKey; + // UiClients[key].SetClient(c); + //}); } } - else - { - Debug.LogMessage(LogEventLevel.Warning, "No secret found"); - } - - Debug.LogMessage(LogEventLevel.Debug, "{uiClientCount} UiClients restored from secrets data", this, UiClients.Count); } - catch (Exception ex) + else { - Debug.LogMessage(ex, "Exception retrieving secret", this); + Debug.LogMessage(LogEventLevel.Warning, "No secret found"); } + + Debug.LogMessage(LogEventLevel.Debug, "{uiClientCount} UiClients restored from secrets data", this, UiClients.Count); + } + catch (Exception ex) + { + Debug.LogMessage(ex, "Exception retrieving secret", this); } + } - /// - /// Stores secrets to memory to persist through reboot - /// - public void UpdateSecret() + /// + /// Stores secrets to memory to persist through reboot + /// + public void UpdateSecret() + { + try { - try + if (_secret == null) { - if (_secret == null) - { - Debug.LogMessage(LogEventLevel.Error, "Secret is null", this); - - _secret = new ServerTokenSecrets(string.Empty); - } - - _secret.Tokens.Clear(); + Debug.LogMessage(LogEventLevel.Error, "Secret is null", this); - foreach (var uiClientContext in UiClients) - { - _secret.Tokens.Add(uiClientContext.Key, uiClientContext.Value.Token); - } + _secret = new ServerTokenSecrets(string.Empty); + } - var serializedSecret = JsonConvert.SerializeObject(_secret); + _secret.Tokens.Clear(); - _secretProvider.SetSecret(SecretProviderKey, serializedSecret); - } - catch (Exception ex) + foreach (var uiClientContext in UiClients) { - Debug.LogMessage(ex, "Exception updating secret", this); + _secret.Tokens.Add(uiClientContext.Key, uiClientContext.Value.Token); } - } - /// - /// Generates a new token based on validating a room key and grant code passed in. If valid, returns a token and adds a service to the server for that token's path - /// - /// - private void GenerateClientTokenFromConsole(string s) + var serializedSecret = JsonConvert.SerializeObject(_secret); + + _secretProvider.SetSecret(SecretProviderKey, serializedSecret); + } + catch (Exception ex) { - if (s == "?" || string.IsNullOrEmpty(s)) - { - CrestronConsole.ConsoleCommandResponse(@"[RoomKey] [GrantCode] Validates the room key against the grant code and returns a token for use in a UI client"); - return; - } + Debug.LogMessage(ex, "Exception updating secret", this); + } + } - var values = s.Split(' '); + /// + /// Generates a new token based on validating a room key and grant code passed in. If valid, returns a token and adds a service to the server for that token's path + /// + /// + private void GenerateClientTokenFromConsole(string s) + { + if (s == "?" || string.IsNullOrEmpty(s)) + { + CrestronConsole.ConsoleCommandResponse(@"[RoomKey] [GrantCode] Validates the room key against the grant code and returns a token for use in a UI client"); + return; + } - if(values.Length < 2) - { - CrestronConsole.ConsoleCommandResponse("Invalid number of arguments. Please provide a room key and a grant code"); - return; - } + var values = s.Split(' '); + if(values.Length < 2) + { + CrestronConsole.ConsoleCommandResponse("Invalid number of arguments. Please provide a room key and a grant code"); + return; + } - var roomKey = values[0]; - var grantCode = values[1]; - var bridge = _parent.GetRoomBridge(roomKey); + var roomKey = values[0]; + var grantCode = values[1]; - if (bridge == null) - { - CrestronConsole.ConsoleCommandResponse(string.Format("Unable to find room with key: {0}", roomKey)); - return; - } + var bridge = _parent.GetRoomBridge(roomKey); - var (token, path) = ValidateGrantCode(grantCode, bridge); + if (bridge == null) + { + CrestronConsole.ConsoleCommandResponse(string.Format("Unable to find room with key: {0}", roomKey)); + return; + } - if (token == null) - { - CrestronConsole.ConsoleCommandResponse("Grant Code is not valid"); - return; - } + var (token, path) = ValidateGrantCode(grantCode, bridge); - CrestronConsole.ConsoleCommandResponse($"Added new WebSocket UiClient service at path: {path}"); - CrestronConsole.ConsoleCommandResponse($"Token: {token}"); + if (token == null) + { + CrestronConsole.ConsoleCommandResponse("Grant Code is not valid"); + return; } - public (string, string) ValidateGrantCode(string grantCode, string roomKey) - { - var bridge = _parent.GetRoomBridge(roomKey); + CrestronConsole.ConsoleCommandResponse($"Added new WebSocket UiClient service at path: {path}"); + CrestronConsole.ConsoleCommandResponse($"Token: {token}"); + } - if (bridge == null) - { - this.LogWarning("Unable to find room with key: {roomKey}", roomKey); - return (null, null); - } + public (string, string) ValidateGrantCode(string grantCode, string roomKey) + { + var bridge = _parent.GetRoomBridge(roomKey); - return ValidateGrantCode(grantCode, bridge); + if (bridge == null) + { + this.LogWarning("Unable to find room with key: {roomKey}", roomKey); + return (null, null); } - public (string, string) ValidateGrantCode(string grantCode, MobileControlBridgeBase bridge) - { - // TODO: Authenticate grant code passed in - // For now, we just generate a random guid as the token and use it as the ClientId as well - var grantCodeIsValid = true; + return ValidateGrantCode(grantCode, bridge); + } - if (grantCodeIsValid) - { - if (_secret == null) - { - _secret = new ServerTokenSecrets(grantCode); - } + public (string, string) ValidateGrantCode(string grantCode, MobileControlBridgeBase bridge) + { + // TODO: Authenticate grant code passed in + // For now, we just generate a random guid as the token and use it as the ClientId as well + var grantCodeIsValid = true; - return GenerateClientToken(bridge, ""); - } - else + if (grantCodeIsValid) + { + if (_secret == null) { - return (null, null); + _secret = new ServerTokenSecrets(grantCode); } - } - public (string, string) GenerateClientToken(MobileControlBridgeBase bridge, string touchPanelKey = "") + return GenerateClientToken(bridge, ""); + } + else { - var key = Guid.NewGuid().ToString(); + return (null, null); + } + } - var token = new JoinToken { Code = bridge.UserCode, RoomKey = bridge.RoomKey, Uuid = _parent.SystemUuid, TouchpanelKey = touchPanelKey }; + public (string, string) GenerateClientToken(MobileControlBridgeBase bridge, string touchPanelKey = "") + { + var key = Guid.NewGuid().ToString(); - UiClients.Add(key, new UiClientContext(token)); + var token = new JoinToken { Code = bridge.UserCode, RoomKey = bridge.RoomKey, Uuid = _parent.SystemUuid, TouchpanelKey = touchPanelKey }; - var path = _wsPath + key; + UiClients.Add(key, new UiClientContext(token)); - _server.AddWebSocketService(path, () => - { - var c = new UiClient(); - Debug.LogMessage(LogEventLevel.Verbose, "Constructing UiClient with id: {0}", this, key); - c.Controller = _parent; - c.RoomKey = bridge.RoomKey; - UiClients[key].SetClient(c); - return c; - }); + var path = _wsPath + key; + + _server.AddWebSocketService(path, () => + { + var c = new UiClient(); + Debug.LogMessage(LogEventLevel.Verbose, "Constructing UiClient with id: {0}", this, key); + c.Controller = _parent; + c.RoomKey = bridge.RoomKey; + UiClients[key].SetClient(c); + return c; + }); - Debug.LogMessage(LogEventLevel.Information, "Added new WebSocket UiClient service at path: {path}", this, path); - Debug.LogMessage(LogEventLevel.Information, "Token: {@token}", this, token); + Debug.LogMessage(LogEventLevel.Information, "Added new WebSocket UiClient service at path: {path}", this, path); + Debug.LogMessage(LogEventLevel.Information, "Token: {@token}", this, token); - Debug.LogMessage(LogEventLevel.Verbose, "{serviceCount} websocket services present", this, _server.WebSocketServices.Count); + Debug.LogMessage(LogEventLevel.Verbose, "{serviceCount} websocket services present", this, _server.WebSocketServices.Count); - UpdateSecret(); + UpdateSecret(); - return (key, path); + return (key, path); + } + + /// + /// Removes all clients from the server + /// + private void RemoveAllTokens(string s) + { + if (s == "?" || string.IsNullOrEmpty(s)) + { + CrestronConsole.ConsoleCommandResponse(@"Removes all clients from the server. To execute add 'confirm' to command"); + return; } - /// - /// Removes all clients from the server - /// - private void RemoveAllTokens(string s) + if (s != "confirm") { - if (s == "?" || string.IsNullOrEmpty(s)) + CrestronConsole.ConsoleCommandResponse(@"To remove all clients, add 'confirm' to the command"); + return; + } + + foreach (var client in UiClients) + { + if (client.Value.Client != null && client.Value.Client.Context.WebSocket.IsAlive) { - CrestronConsole.ConsoleCommandResponse(@"Removes all clients from the server. To execute add 'confirm' to command"); - return; + client.Value.Client.Context.WebSocket.Close(CloseStatusCode.Normal, "Server Shutting Down"); } - if (s != "confirm") + var path = _wsPath + client.Key; + if (_server.RemoveWebSocketService(path)) { - CrestronConsole.ConsoleCommandResponse(@"To remove all clients, add 'confirm' to the command"); - return; + CrestronConsole.ConsoleCommandResponse(string.Format("Client removed with token: {0}", client.Key)); } - - foreach (var client in UiClients) + else { - if (client.Value.Client != null && client.Value.Client.Context.WebSocket.IsAlive) - { - client.Value.Client.Context.WebSocket.Close(CloseStatusCode.Normal, "Server Shutting Down"); - } - - var path = _wsPath + client.Key; - if (_server.RemoveWebSocketService(path)) - { - CrestronConsole.ConsoleCommandResponse(string.Format("Client removed with token: {0}", client.Key)); - } - else - { - CrestronConsole.ConsoleCommandResponse(string.Format("Unable to remove client with token : {0}", client.Key)); - } + CrestronConsole.ConsoleCommandResponse(string.Format("Unable to remove client with token : {0}", client.Key)); } + } + + UiClients.Clear(); - UiClients.Clear(); + UpdateSecret(); + } - UpdateSecret(); + /// + /// Removes a client with the specified token value + /// + /// + private void RemoveToken(string s) + { + if (s == "?" || string.IsNullOrEmpty(s)) + { + CrestronConsole.ConsoleCommandResponse(@"[token] Removes the client with the specified token value"); + return; } - /// - /// Removes a client with the specified token value - /// - /// - private void RemoveToken(string s) + var key = s; + + if (UiClients.ContainsKey(key)) { - if (s == "?" || string.IsNullOrEmpty(s)) + var uiClientContext = UiClients[key]; + + if (uiClientContext.Client != null && uiClientContext.Client.Context.WebSocket.IsAlive) { - CrestronConsole.ConsoleCommandResponse(@"[token] Removes the client with the specified token value"); - return; + uiClientContext.Client.Context.WebSocket.Close(CloseStatusCode.Normal, "Token removed from server"); } - var key = s; - - if (UiClients.ContainsKey(key)) + var path = _wsPath + key; + if (_server.RemoveWebSocketService(path)) { - var uiClientContext = UiClients[key]; + UiClients.Remove(key); - if (uiClientContext.Client != null && uiClientContext.Client.Context.WebSocket.IsAlive) - { - uiClientContext.Client.Context.WebSocket.Close(CloseStatusCode.Normal, "Token removed from server"); - } - - var path = _wsPath + key; - if (_server.RemoveWebSocketService(path)) - { - UiClients.Remove(key); + UpdateSecret(); - UpdateSecret(); - - CrestronConsole.ConsoleCommandResponse(string.Format("Client removed with token: {0}", key)); - } - else - { - CrestronConsole.ConsoleCommandResponse(string.Format("Unable to remove client with token : {0}", key)); - } + CrestronConsole.ConsoleCommandResponse(string.Format("Client removed with token: {0}", key)); } else { - CrestronConsole.ConsoleCommandResponse(string.Format("Unable to find client with token: {0}", key)); + CrestronConsole.ConsoleCommandResponse(string.Format("Unable to remove client with token : {0}", key)); } } - - /// - /// Prints out info about current client IDs - /// - private void PrintClientInfo() + else { - CrestronConsole.ConsoleCommandResponse("Mobile Control UI Client Info:\r"); + CrestronConsole.ConsoleCommandResponse(string.Format("Unable to find client with token: {0}", key)); + } + } + + /// + /// Prints out info about current client IDs + /// + private void PrintClientInfo() + { + CrestronConsole.ConsoleCommandResponse("Mobile Control UI Client Info:\r"); - CrestronConsole.ConsoleCommandResponse(string.Format("{0} clients found:\r", UiClients.Count)); + CrestronConsole.ConsoleCommandResponse(string.Format("{0} clients found:\r", UiClients.Count)); - foreach (var client in UiClients) - { - CrestronConsole.ConsoleCommandResponse(string.Format("RoomKey: {0} Token: {1}\r", client.Value.Token.RoomKey, client.Key)); - } + foreach (var client in UiClients) + { + CrestronConsole.ConsoleCommandResponse(string.Format("RoomKey: {0} Token: {1}\r", client.Value.Token.RoomKey, client.Key)); } + } - private void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + private void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + { + if (programEventType == eProgramStatusEventType.Stopping) { - if (programEventType == eProgramStatusEventType.Stopping) + foreach (var client in UiClients.Values) { - foreach (var client in UiClients.Values) + if (client.Client != null && client.Client.Context.WebSocket.IsAlive) { - if (client.Client != null && client.Client.Context.WebSocket.IsAlive) - { - client.Client.Context.WebSocket.Close(CloseStatusCode.Normal, "Server Shutting Down"); - } + client.Client.Context.WebSocket.Close(CloseStatusCode.Normal, "Server Shutting Down"); } - - StopServer(); } + + StopServer(); } + } - /// - /// Handler for GET requests to server - /// - /// - /// - private void Server_OnGet(object sender, HttpRequestEventArgs e) + /// + /// Handler for GET requests to server + /// + /// + /// + private void Server_OnGet(object sender, HttpRequestEventArgs e) + { + try { - try - { - var req = e.Request; - var res = e.Response; - res.ContentEncoding = Encoding.UTF8; + var req = e.Request; + var res = e.Response; + res.ContentEncoding = Encoding.UTF8; - res.AddHeader("Access-Control-Allow-Origin", "*"); + res.AddHeader("Access-Control-Allow-Origin", "*"); - var path = req.RawUrl; + var path = req.RawUrl; - this.LogVerbose("GET Request received at path: {path}", path); + this.LogVerbose("GET Request received at path: {path}", path); - // Call for user app to join the room with a token - if (path.StartsWith("/mc/api/ui/joinroom")) - { - HandleJoinRequest(req, res); - } - // Call to get the server version - else if (path.StartsWith("/mc/api/version")) - { - HandleVersionRequest(res); - } - else if (path.StartsWith("/mc/app/logo")) - { - HandleImageRequest(req, res); - } - // Call to serve the user app - else if (path.StartsWith(_userAppBaseHref)) - { - HandleUserAppRequest(req, res, path); - } - else - { - // All other paths - res.StatusCode = 404; - res.Close(); - } + // Call for user app to join the room with a token + if (path.StartsWith("/mc/api/ui/joinroom")) + { + HandleJoinRequest(req, res); } - catch (Exception ex) + // Call to get the server version + else if (path.StartsWith("/mc/api/version")) + { + HandleVersionRequest(res); + } + else if (path.StartsWith("/mc/app/logo")) + { + HandleImageRequest(req, res); + } + // Call to serve the user app + else if (path.StartsWith(_userAppBaseHref)) + { + HandleUserAppRequest(req, res, path); + } + else { - Debug.LogMessage(ex, "Caught an exception in the OnGet handler", this); + // All other paths + res.StatusCode = 404; + res.Close(); } } + catch (Exception ex) + { + Debug.LogMessage(ex, "Caught an exception in the OnGet handler", this); + } + } - private async void Server_OnPost(object sender, HttpRequestEventArgs e) + private async void Server_OnPost(object sender, HttpRequestEventArgs e) + { + try { - try - { - var req = e.Request; - var res = e.Response; + var req = e.Request; + var res = e.Response; - res.AddHeader("Access-Control-Allow-Origin", "*"); + res.AddHeader("Access-Control-Allow-Origin", "*"); - var path = req.RawUrl; - var ip = req.RemoteEndPoint.Address.ToString(); + var path = req.RawUrl; + var ip = req.RemoteEndPoint.Address.ToString(); - this.LogVerbose("POST Request received at path: {path} from host {host}", path, ip); + this.LogVerbose("POST Request received at path: {path} from host {host}", path, ip); - var body = new StreamReader(req.InputStream).ReadToEnd(); + var body = new StreamReader(req.InputStream).ReadToEnd(); - if (path.StartsWith("/mc/api/log")) - { - res.StatusCode = 200; - res.Close(); + if (path.StartsWith("/mc/api/log")) + { + res.StatusCode = 200; + res.Close(); - var logRequest = new HttpRequestMessage(HttpMethod.Post, $"http://{_parent.Config.DirectServer.Logging.Host}:{_parent.Config.DirectServer.Logging.Port}/logs") - { - Content = new StringContent(body, Encoding.UTF8, "application/json"), - }; + var logRequest = new HttpRequestMessage(HttpMethod.Post, $"http://{_parent.Config.DirectServer.Logging.Host}:{_parent.Config.DirectServer.Logging.Port}/logs") + { + Content = new StringContent(body, Encoding.UTF8, "application/json"), + }; - logRequest.Headers.Add("x-pepperdash-host", ip); + logRequest.Headers.Add("x-pepperdash-host", ip); - await LogClient.SendAsync(logRequest); + await LogClient.SendAsync(logRequest); - this.LogVerbose("Log data sent to {host}:{port}", _parent.Config.DirectServer.Logging.Host, _parent.Config.DirectServer.Logging.Port); - } - else - { - res.StatusCode = 404; - res.Close(); - } + this.LogVerbose("Log data sent to {host}:{port}", _parent.Config.DirectServer.Logging.Host, _parent.Config.DirectServer.Logging.Port); } - catch (Exception ex) + else { - this.LogException(ex, "Caught an exception in the OnPost handler"); + res.StatusCode = 404; + res.Close(); } } + catch (Exception ex) + { + this.LogException(ex, "Caught an exception in the OnPost handler"); + } + } - private void Server_OnOptions(object sender, HttpRequestEventArgs e) + private void Server_OnOptions(object sender, HttpRequestEventArgs e) + { + try { - try - { - var res = e.Response; + var res = e.Response; - res.AddHeader("Access-Control-Allow-Origin", "*"); - res.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); - res.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me"); + res.AddHeader("Access-Control-Allow-Origin", "*"); + res.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); + res.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me"); - res.StatusCode = 200; - res.Close(); - } - catch (Exception ex) - { - Debug.LogMessage(ex, "Caught an exception in the OnPost handler", this); - } + res.StatusCode = 200; + res.Close(); } - - /// - /// Handle the request to join the room with a token - /// - /// - /// - private void HandleJoinRequest(HttpListenerRequest req, HttpListenerResponse res) + catch (Exception ex) { - var qp = req.QueryString; - var token = qp["token"]; + Debug.LogMessage(ex, "Caught an exception in the OnPost handler", this); + } + } - this.LogVerbose("Join Room Request with token: {token}", token); + /// + /// Handle the request to join the room with a token + /// + /// + /// + private void HandleJoinRequest(HttpListenerRequest req, HttpListenerResponse res) + { + var qp = req.QueryString; + var token = qp["token"]; + this.LogVerbose("Join Room Request with token: {token}", token); - if (UiClients.TryGetValue(token, out UiClientContext clientContext)) + + if (UiClients.TryGetValue(token, out UiClientContext clientContext)) + { + var bridge = _parent.GetRoomBridge(clientContext.Token.RoomKey); + + if (bridge != null) { - var bridge = _parent.GetRoomBridge(clientContext.Token.RoomKey); + res.StatusCode = 200; + res.ContentType = "application/json"; - if (bridge != null) + // Construct the response object + JoinResponse jRes = new JoinResponse { - res.StatusCode = 200; - res.ContentType = "application/json"; + ClientId = token, + RoomKey = bridge.RoomKey, + SystemUuid = _parent.SystemUuid, + RoomUuid = _parent.SystemUuid, + Config = _parent.GetConfigWithPluginVersion(), + CodeExpires = new DateTime().AddYears(1), + UserCode = bridge.UserCode, + UserAppUrl = string.Format("http://{0}:{1}/mc/app", + CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0), + Port), + EnableDebug = false + }; - // Construct the response object - JoinResponse jRes = new JoinResponse - { - ClientId = token, - RoomKey = bridge.RoomKey, - SystemUuid = _parent.SystemUuid, - RoomUuid = _parent.SystemUuid, - Config = _parent.GetConfigWithPluginVersion(), - CodeExpires = new DateTime().AddYears(1), - UserCode = bridge.UserCode, - UserAppUrl = string.Format("http://{0}:{1}/mc/app", - CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0), - Port), - EnableDebug = false - }; - - // Serialize to JSON and convert to Byte[] - var json = JsonConvert.SerializeObject(jRes); - var body = Encoding.UTF8.GetBytes(json); - res.ContentLength64 = body.LongLength; - - // Send the response - res.Close(body, true); - } - else - { - var message = string.Format("Unable to find bridge with key: {0}", clientContext.Token.RoomKey); - res.StatusCode = 404; - res.ContentType = "application/json"; - this.LogVerbose("{message}", message); - var body = Encoding.UTF8.GetBytes(message); - res.ContentLength64 = body.LongLength; - res.Close(body, true); + // Serialize to JSON and convert to Byte[] + var json = JsonConvert.SerializeObject(jRes); + var body = Encoding.UTF8.GetBytes(json); + res.ContentLength64 = body.LongLength; - } + // Send the response + res.Close(body, true); } else { - var message = "Token invalid or has expired"; - res.StatusCode = 401; + var message = string.Format("Unable to find bridge with key: {0}", clientContext.Token.RoomKey); + res.StatusCode = 404; res.ContentType = "application/json"; this.LogVerbose("{message}", message); var body = Encoding.UTF8.GetBytes(message); res.ContentLength64 = body.LongLength; res.Close(body, true); + } } - - /// - /// Handles a server version request - /// - /// - private void HandleVersionRequest(HttpListenerResponse res) + else { - res.StatusCode = 200; + var message = "Token invalid or has expired"; + res.StatusCode = 401; res.ContentType = "application/json"; - var version = new Version() { ServerVersion = _parent.GetConfigWithPluginVersion().RuntimeInfo.PluginVersion }; - var message = JsonConvert.SerializeObject(version); this.LogVerbose("{message}", message); - var body = Encoding.UTF8.GetBytes(message); res.ContentLength64 = body.LongLength; res.Close(body, true); } + } - /// - /// Handler to return images requested by the user app - /// - /// - /// - private void HandleImageRequest(HttpListenerRequest req, HttpListenerResponse res) - { - var path = req.RawUrl; + /// + /// Handles a server version request + /// + /// + private void HandleVersionRequest(HttpListenerResponse res) + { + res.StatusCode = 200; + res.ContentType = "application/json"; + var version = new Version() { ServerVersion = _parent.GetConfigWithPluginVersion().RuntimeInfo.PluginVersion }; + var message = JsonConvert.SerializeObject(version); + this.LogVerbose("{message}", message); + + var body = Encoding.UTF8.GetBytes(message); + res.ContentLength64 = body.LongLength; + res.Close(body, true); + } + + /// + /// Handler to return images requested by the user app + /// + /// + /// + private void HandleImageRequest(HttpListenerRequest req, HttpListenerResponse res) + { + var path = req.RawUrl; - Debug.LogMessage(LogEventLevel.Verbose, "Requesting Image: {0}", this, path); + Debug.LogMessage(LogEventLevel.Verbose, "Requesting Image: {0}", this, path); - var imageBasePath = Global.DirectorySeparator + "html" + Global.DirectorySeparator + "logo" + Global.DirectorySeparator; + var imageBasePath = Global.DirectorySeparator + "html" + Global.DirectorySeparator + "logo" + Global.DirectorySeparator; - var image = path.Split('/').Last(); + var image = path.Split('/').Last(); - var filePath = imageBasePath + image; + var filePath = imageBasePath + image; - Debug.LogMessage(LogEventLevel.Verbose, "Retrieving Image: {0}", this, filePath); + Debug.LogMessage(LogEventLevel.Verbose, "Retrieving Image: {0}", this, filePath); - if (File.Exists(filePath)) + if (File.Exists(filePath)) + { + if (filePath.EndsWith(".png")) { - if (filePath.EndsWith(".png")) - { - res.ContentType = "image/png"; - } - else if (filePath.EndsWith(".jpg")) - { - res.ContentType = "image/jpeg"; - } - else if (filePath.EndsWith(".gif")) - { - res.ContentType = "image/gif"; - } - else if (filePath.EndsWith(".svg")) - { - res.ContentType = "image/svg+xml"; - } - byte[] contents = File.ReadAllBytes(filePath); - res.ContentLength64 = contents.LongLength; - res.Close(contents, true); + res.ContentType = "image/png"; } - else + else if (filePath.EndsWith(".jpg")) { - res.StatusCode = (int)HttpStatusCode.NotFound; - res.Close(); + res.ContentType = "image/jpeg"; + } + else if (filePath.EndsWith(".gif")) + { + res.ContentType = "image/gif"; } + else if (filePath.EndsWith(".svg")) + { + res.ContentType = "image/svg+xml"; + } + byte[] contents = File.ReadAllBytes(filePath); + res.ContentLength64 = contents.LongLength; + res.Close(contents, true); } - - /// - /// Handles requests to serve files for the Angular single page app - /// - /// - /// - /// - private void HandleUserAppRequest(HttpListenerRequest req, HttpListenerResponse res, string path) + else { - this.LogVerbose("Requesting User app file"); + res.StatusCode = (int)HttpStatusCode.NotFound; + res.Close(); + } + } - string filePath = path.Split('?')[0]; + /// + /// Handles requests to serve files for the Angular single page app + /// + /// + /// + /// + private void HandleUserAppRequest(HttpListenerRequest req, HttpListenerResponse res, string path) + { + this.LogVerbose("Requesting User app file"); - // remove the token from the path if found - //string filePath = path.Replace(string.Format("?token={0}", token), ""); + string filePath = path.Split('?')[0]; - // if there's no file suffix strip any extra path data after the base href - if (filePath != _userAppBaseHref && !filePath.Contains(".") && (!filePath.EndsWith(_userAppBaseHref) || !filePath.EndsWith(_userAppBaseHref += "/"))) + // remove the token from the path if found + //string filePath = path.Replace(string.Format("?token={0}", token), ""); + + // if there's no file suffix strip any extra path data after the base href + if (filePath != _userAppBaseHref && !filePath.Contains(".") && (!filePath.EndsWith(_userAppBaseHref) || !filePath.EndsWith(_userAppBaseHref += "/"))) + { + var suffix = filePath.Substring(_userAppBaseHref.Length, filePath.Length - _userAppBaseHref.Length); + if (suffix != "/") { - var suffix = filePath.Substring(_userAppBaseHref.Length, filePath.Length - _userAppBaseHref.Length); - if (suffix != "/") - { - //Debug.Console(2, this, "Suffix: {0}", suffix); - filePath = filePath.Replace(suffix, ""); - } + //Debug.Console(2, this, "Suffix: {0}", suffix); + filePath = filePath.Replace(suffix, ""); } + } - // swap the base href prefix for the file path prefix - filePath = filePath.Replace(_userAppBaseHref, _appPath); + // swap the base href prefix for the file path prefix + filePath = filePath.Replace(_userAppBaseHref, _appPath); - this.LogVerbose("filepath: {filePath}", filePath); + this.LogVerbose("filepath: {filePath}", filePath); - // append index.html if no specific file is specified - if (!filePath.Contains(".")) - { - if (filePath.EndsWith("/")) - { - filePath += "index.html"; - } - else - { - filePath += "/index.html"; - } - } - - // Set ContentType based on file type - if (filePath.EndsWith(".html")) + // append index.html if no specific file is specified + if (!filePath.Contains(".")) + { + if (filePath.EndsWith("/")) { - this.LogVerbose("Client requesting User App"); - - res.ContentType = "text/html"; + filePath += "index.html"; } else { - if (path.EndsWith(".js")) - { - res.ContentType = "application/javascript"; - } - else if (path.EndsWith(".css")) - { - res.ContentType = "text/css"; - } - else if (path.EndsWith(".json")) - { - res.ContentType = "application/json"; - } + filePath += "/index.html"; } + } - this.LogVerbose("Attempting to serve file: {filePath}", filePath); - - var remoteIp = req.RemoteEndPoint.Address; + // Set ContentType based on file type + if (filePath.EndsWith(".html")) + { + this.LogVerbose("Client requesting User App"); - // Check if the request is coming from the CS LAN and if so, send the CS config instead of the LAN config - if (csSubnetMask != null && csIpAddress != null && remoteIp.IsInSameSubnet(csIpAddress, csSubnetMask) && filePath.Contains(appConfigFileName)) + res.ContentType = "text/html"; + } + else + { + if (path.EndsWith(".js")) { - filePath = filePath.Replace(appConfigFileName, appConfigCsFileName); + res.ContentType = "application/javascript"; } - - byte[] contents; - if (File.Exists(filePath)) + else if (path.EndsWith(".css")) { - this.LogVerbose("File found: {filePath}", filePath); - contents = File.ReadAllBytes(filePath); + res.ContentType = "text/css"; } - else + else if (path.EndsWith(".json")) { - this.LogVerbose("File not found: {filePath}", filePath); - res.StatusCode = (int)HttpStatusCode.NotFound; - res.Close(); - return; + res.ContentType = "application/json"; } - - res.ContentLength64 = contents.LongLength; - res.Close(contents, true); } - public void StopServer() + this.LogVerbose("Attempting to serve file: {filePath}", filePath); + + var remoteIp = req.RemoteEndPoint.Address; + + // Check if the request is coming from the CS LAN and if so, send the CS config instead of the LAN config + if (csSubnetMask != null && csIpAddress != null && remoteIp.IsInSameSubnet(csIpAddress, csSubnetMask) && filePath.Contains(appConfigFileName)) { - this.LogVerbose("Stopping WebSocket Server"); - _server.Stop(CloseStatusCode.Normal, "Server Shutting Down"); + filePath = filePath.Replace(appConfigFileName, appConfigCsFileName); } - /// - /// Sends a message to all connectd clients - /// - /// - public void SendMessageToAllClients(string message) + byte[] contents; + if (File.Exists(filePath)) { - foreach (var clientContext in UiClients.Values) - { - if (clientContext.Client != null && clientContext.Client.Context.WebSocket.IsAlive) - { - clientContext.Client.Context.WebSocket.Send(message); - } - } + this.LogVerbose("File found: {filePath}", filePath); + contents = File.ReadAllBytes(filePath); } - - /// - /// Sends a message to a specific client - /// - /// - /// - public void SendMessageToClient(object clientId, string message) + else { - if (clientId == null) - { - return; - } + this.LogVerbose("File not found: {filePath}", filePath); + res.StatusCode = (int)HttpStatusCode.NotFound; + res.Close(); + return; + } - if (UiClients.TryGetValue((string)clientId, out UiClientContext clientContext)) - { - if (clientContext.Client != null) - { - var socket = clientContext.Client.Context.WebSocket; + res.ContentLength64 = contents.LongLength; + res.Close(contents, true); + } - if (socket.IsAlive) - { - socket.Send(message); - } - } - } - else - { - this.LogWarning("Unable to find client with ID: {clientId}", clientId); - } - } + public void StopServer() + { + this.LogVerbose("Stopping WebSocket Server"); + _server.Stop(CloseStatusCode.Normal, "Server Shutting Down"); } /// - /// Class to describe the server version info + /// Sends a message to all connectd clients /// - public class Version + /// + public void SendMessageToAllClients(string message) { - [JsonProperty("serverVersion")] - public string ServerVersion { get; set; } - - [JsonProperty("serverIsRunningOnProcessorHardware")] - public bool ServerIsRunningOnProcessorHardware { get; private set; } - - public Version() + foreach (var clientContext in UiClients.Values) { - ServerIsRunningOnProcessorHardware = true; + if (clientContext.Client != null && clientContext.Client.Context.WebSocket.IsAlive) + { + clientContext.Client.Context.WebSocket.Send(message); + } } } /// - /// Represents an instance of a UiClient and the associated Token + /// Sends a message to a specific client /// - public class UiClientContext + /// + /// + public void SendMessageToClient(object clientId, string message) { - public UiClient Client { get; private set; } - public JoinToken Token { get; private set; } - - public UiClientContext(JoinToken token) + if (clientId == null) { - Token = token; + return; } - public void SetClient(UiClient client) + if (UiClients.TryGetValue((string)clientId, out UiClientContext clientContext)) { - Client = client; - } + if (clientContext.Client != null) + { + var socket = clientContext.Client.Context.WebSocket; + if (socket.IsAlive) + { + socket.Send(message); + } + } + } + else + { + this.LogWarning("Unable to find client with ID: {clientId}", clientId); + } } +} - /// - /// Represents the data structure for the grant code and UiClient tokens to be stored in the secrets manager - /// - public class ServerTokenSecrets +/// +/// Class to describe the server version info +/// +public class Version +{ + [JsonProperty("serverVersion")] + public string ServerVersion { get; set; } + + [JsonProperty("serverIsRunningOnProcessorHardware")] + public bool ServerIsRunningOnProcessorHardware { get; private set; } + + public Version() { - public string GrantCode { get; set; } + ServerIsRunningOnProcessorHardware = true; + } +} - public Dictionary Tokens { get; set; } +/// +/// Represents an instance of a UiClient and the associated Token +/// +public class UiClientContext +{ + public UiClient Client { get; private set; } + public JoinToken Token { get; private set; } - public ServerTokenSecrets(string grantCode) - { - GrantCode = grantCode; - Tokens = new Dictionary(); - } + public UiClientContext(JoinToken token) + { + Token = token; } - /// - /// Represents a join token with the associated properties - /// - public class JoinToken + public void SetClient(UiClient client) { - public string Code { get; set; } + Client = client; + } - public string RoomKey { get; set; } +} - public string Uuid { get; set; } +/// +/// Represents the data structure for the grant code and UiClient tokens to be stored in the secrets manager +/// +public class ServerTokenSecrets +{ + public string GrantCode { get; set; } - public string TouchpanelKey { get; set; } = ""; + public Dictionary Tokens { get; set; } - public string Token { get; set; } = null; + public ServerTokenSecrets(string grantCode) + { + GrantCode = grantCode; + Tokens = new Dictionary(); } +} - /// - /// Represents the structure of the join response - /// - public class JoinResponse - { - [JsonProperty("clientId")] - public string ClientId { get; set; } +/// +/// Represents a join token with the associated properties +/// +public class JoinToken +{ + public string Code { get; set; } - [JsonProperty("roomKey")] - public string RoomKey { get; set; } + public string RoomKey { get; set; } - [JsonProperty("systemUUid")] - public string SystemUuid { get; set; } + public string Uuid { get; set; } - [JsonProperty("roomUUid")] - public string RoomUuid { get; set; } + public string TouchpanelKey { get; set; } = ""; - [JsonProperty("config")] - public object Config { get; set; } + public string Token { get; set; } = null; +} - [JsonProperty("codeExpires")] - public DateTime CodeExpires { get; set; } +/// +/// Represents the structure of the join response +/// +public class JoinResponse +{ + [JsonProperty("clientId")] + public string ClientId { get; set; } - [JsonProperty("userCode")] - public string UserCode { get; set; } + [JsonProperty("roomKey")] + public string RoomKey { get; set; } - [JsonProperty("userAppUrl")] - public string UserAppUrl { get; set; } + [JsonProperty("systemUUid")] + public string SystemUuid { get; set; } - [JsonProperty("enableDebug")] - public bool EnableDebug { get; set; } - } + [JsonProperty("roomUUid")] + public string RoomUuid { get; set; } + + [JsonProperty("config")] + public object Config { get; set; } + + [JsonProperty("codeExpires")] + public DateTime CodeExpires { get; set; } + + [JsonProperty("userCode")] + public string UserCode { get; set; } + + [JsonProperty("userAppUrl")] + public string UserAppUrl { get; set; } + + [JsonProperty("enableDebug")] + public bool EnableDebug { get; set; } } diff --git a/src/PepperDash.Essentials.MobileControl/WebSocketServer/UiClient.cs b/src/PepperDash.Essentials.MobileControl/WebSocketServer/UiClient.cs index eb1cf7a15..5b30fab13 100644 --- a/src/PepperDash.Essentials.MobileControl/WebSocketServer/UiClient.cs +++ b/src/PepperDash.Essentials.MobileControl/WebSocketServer/UiClient.cs @@ -11,135 +11,134 @@ using ErrorEventArgs = WebSocketSharp.ErrorEventArgs; -namespace PepperDash.Essentials.WebSocketServer -{ - /// - /// Represents the behaviour to associate with a UiClient for WebSocket communication - /// - public class UiClient : WebSocketBehavior - { - public MobileControlSystemController Controller { get; set; } +namespace PepperDash.Essentials.WebSocketServer; + +/// +/// Represents the behaviour to associate with a UiClient for WebSocket communication +/// +public class UiClient : WebSocketBehavior +{ + public MobileControlSystemController Controller { get; set; } - public string RoomKey { get; set; } + public string RoomKey { get; set; } - private string _clientId; + private string _clientId; - private DateTime _connectionTime; + private DateTime _connectionTime; - public TimeSpan ConnectedDuration + public TimeSpan ConnectedDuration + { + get { - get + if (Context.WebSocket.IsAlive) + { + return DateTime.Now - _connectionTime; + } + else { - if (Context.WebSocket.IsAlive) - { - return DateTime.Now - _connectionTime; - } - else - { - return new TimeSpan(0); - } + return new TimeSpan(0); } } + } - public UiClient() - { + public UiClient() + { - } + } - protected override void OnOpen() - { - base.OnOpen(); + protected override void OnOpen() + { + base.OnOpen(); - var url = Context.WebSocket.Url; - Debug.LogMessage(LogEventLevel.Verbose, "New WebSocket Connection from: {0}", null, url); + var url = Context.WebSocket.Url; + Debug.LogMessage(LogEventLevel.Verbose, "New WebSocket Connection from: {0}", null, url); - var match = Regex.Match(url.AbsoluteUri, "(?:ws|wss):\\/\\/.*(?:\\/mc\\/api\\/ui\\/join\\/)(.*)"); + var match = Regex.Match(url.AbsoluteUri, "(?:ws|wss):\\/\\/.*(?:\\/mc\\/api\\/ui\\/join\\/)(.*)"); - if (!match.Success) - { - _connectionTime = DateTime.Now; - return; - } + if (!match.Success) + { + _connectionTime = DateTime.Now; + return; + } - var clientId = match.Groups[1].Value; - _clientId = clientId; + var clientId = match.Groups[1].Value; + _clientId = clientId; - if (Controller == null) - { - Debug.LogMessage(LogEventLevel.Verbose, "WebSocket UiClient Controller is null"); - _connectionTime = DateTime.Now; - } + if (Controller == null) + { + Debug.LogMessage(LogEventLevel.Verbose, "WebSocket UiClient Controller is null"); + _connectionTime = DateTime.Now; + } - var clientJoinedMessage = new MobileControlMessage + var clientJoinedMessage = new MobileControlMessage + { + Type = "/system/clientJoined", + Content = JToken.FromObject(new { - Type = "/system/clientJoined", - Content = JToken.FromObject(new - { - clientId, - roomKey = RoomKey, - }) - }; + clientId, + roomKey = RoomKey, + }) + }; - Controller.HandleClientMessage(JsonConvert.SerializeObject(clientJoinedMessage)); + Controller.HandleClientMessage(JsonConvert.SerializeObject(clientJoinedMessage)); - var bridge = Controller.GetRoomBridge(RoomKey); + var bridge = Controller.GetRoomBridge(RoomKey); - if (bridge == null) return; + if (bridge == null) return; - SendUserCodeToClient(bridge, clientId); + SendUserCodeToClient(bridge, clientId); - bridge.UserCodeChanged -= Bridge_UserCodeChanged; - bridge.UserCodeChanged += Bridge_UserCodeChanged; + bridge.UserCodeChanged -= Bridge_UserCodeChanged; + bridge.UserCodeChanged += Bridge_UserCodeChanged; - // TODO: Future: Check token to see if there's already an open session using that token and reject/close the session - } + // TODO: Future: Check token to see if there's already an open session using that token and reject/close the session + } - private void Bridge_UserCodeChanged(object sender, EventArgs e) + private void Bridge_UserCodeChanged(object sender, EventArgs e) + { + SendUserCodeToClient((MobileControlEssentialsRoomBridge)sender, _clientId); + } + + private void SendUserCodeToClient(MobileControlBridgeBase bridge, string clientId) + { + var content = new { - SendUserCodeToClient((MobileControlEssentialsRoomBridge)sender, _clientId); - } + userCode = bridge.UserCode, + qrUrl = bridge.QrCodeUrl, + }; - private void SendUserCodeToClient(MobileControlBridgeBase bridge, string clientId) + var message = new MobileControlMessage { - var content = new - { - userCode = bridge.UserCode, - qrUrl = bridge.QrCodeUrl, - }; + Type = "/system/userCodeChanged", + ClientId = clientId, + Content = JToken.FromObject(content) + }; - var message = new MobileControlMessage - { - Type = "/system/userCodeChanged", - ClientId = clientId, - Content = JToken.FromObject(content) - }; + Controller.SendMessageObjectToDirectClient(message); + } - Controller.SendMessageObjectToDirectClient(message); - } + protected override void OnMessage(MessageEventArgs e) + { + base.OnMessage(e); - protected override void OnMessage(MessageEventArgs e) + if (e.IsText && e.Data.Length > 0 && Controller != null) { - base.OnMessage(e); - - if (e.IsText && e.Data.Length > 0 && Controller != null) - { - // Forward the message to the controller to be put on the receive queue - Controller.HandleClientMessage(e.Data); - } + // Forward the message to the controller to be put on the receive queue + Controller.HandleClientMessage(e.Data); } + } - protected override void OnClose(CloseEventArgs e) - { - base.OnClose(e); + protected override void OnClose(CloseEventArgs e) + { + base.OnClose(e); - Debug.LogMessage(LogEventLevel.Verbose, "WebSocket UiClient Closing: {0} reason: {1}", null, e.Code, e.Reason); - } + Debug.LogMessage(LogEventLevel.Verbose, "WebSocket UiClient Closing: {0} reason: {1}", null, e.Code, e.Reason); + } - protected override void OnError(ErrorEventArgs e) - { - base.OnError(e); + protected override void OnError(ErrorEventArgs e) + { + base.OnError(e); - Debug.LogMessage(LogEventLevel.Verbose, "WebSocket UiClient Error: {exception} message: {message}", e.Exception, e.Message); - } + Debug.LogMessage(LogEventLevel.Verbose, "WebSocket UiClient Error: {exception} message: {message}", e.Exception, e.Message); } } diff --git a/src/PepperDash.Essentials.MobileControl/WebSocketServer/WebSocketServerSecretProvider.cs b/src/PepperDash.Essentials.MobileControl/WebSocketServer/WebSocketServerSecretProvider.cs index 1b797767c..a238dc274 100644 --- a/src/PepperDash.Essentials.MobileControl/WebSocketServer/WebSocketServerSecretProvider.cs +++ b/src/PepperDash.Essentials.MobileControl/WebSocketServer/WebSocketServerSecretProvider.cs @@ -1,37 +1,34 @@ using Newtonsoft.Json; using PepperDash.Essentials.Core; -namespace PepperDash.Essentials.WebSocketServer +namespace PepperDash.Essentials.WebSocketServer; + +internal class WebSocketServerSecretProvider : CrestronLocalSecretsProvider { - internal class WebSocketServerSecretProvider : CrestronLocalSecretsProvider + public WebSocketServerSecretProvider(string key) + : base(key) { - public WebSocketServerSecretProvider(string key) - : base(key) - { - Key = key; - } + Key = key; } +} - public class WebSocketServerSecret : ISecret - { - public ISecretProvider Provider { get; private set; } - - public string Key { get; private set; } +public class WebSocketServerSecret : ISecret +{ + public ISecretProvider Provider { get; private set; } - public object Value { get; private set; } + public string Key { get; private set; } - public WebSocketServerSecret(string key, object value, ISecretProvider provider) - { - Key = key; - Value = JsonConvert.SerializeObject(value); - Provider = provider; - } + public object Value { get; private set; } - public ServerTokenSecrets DeserializeSecret() - { - return JsonConvert.DeserializeObject(Value.ToString()); - } + public WebSocketServerSecret(string key, object value, ISecretProvider provider) + { + Key = key; + Value = JsonConvert.SerializeObject(value); + Provider = provider; } - + public ServerTokenSecrets DeserializeSecret() + { + return JsonConvert.DeserializeObject(Value.ToString()); + } } diff --git a/src/PepperDash.Essentials/ControlSystem.cs b/src/PepperDash.Essentials/ControlSystem.cs index 936255a35..b42b7aada 100644 --- a/src/PepperDash.Essentials/ControlSystem.cs +++ b/src/PepperDash.Essentials/ControlSystem.cs @@ -1,5 +1,4 @@ - -using Crestron.SimplSharp; +using Crestron.SimplSharp; using Crestron.SimplSharp.CrestronIO; using System.Reflection; using Crestron.SimplSharpPro; @@ -15,276 +14,268 @@ using System.Linq; using Serilog.Events; using PepperDash.Essentials.Core.Routing; - -namespace PepperDash.Essentials +using System.Threading; +using Timeout = Crestron.SimplSharp.Timeout; + +namespace PepperDash.Essentials; + +/// +/// Represents the main control system for the application, providing initialization, configuration loading, and device +/// management functionality. +/// +/// This class extends and serves as the entry point for the control +/// system. It manages the initialization of devices, rooms, tie lines, and other system components. Additionally, it +/// provides methods for platform determination, configuration loading, and system teardown. +public class ControlSystem : CrestronControlSystem, ILoadConfig { - public class ControlSystem : CrestronControlSystem, ILoadConfig - { - HttpLogoServer LogoServer; - - private CTimer _startTimer; - private CEvent _initializeEvent; - private const long StartupTime = 500; - - public ControlSystem() - : base() + private HttpLogoServer LogoServer; + + private Timer _startTimer; + private ManualResetEventSlim _initializeEvent; + private const long StartupTime = 500; + + /// + /// Initializes a new instance of the class, setting up the system's global state and + /// dependencies. + /// + /// This constructor configures the control system by initializing key components such as the + /// device manager and secrets manager, and sets global properties like the maximum number of user threads and the + /// program initialization state. It also adjusts the error log's minimum debug level based on the device + /// platform. + public ControlSystem() + : base() + + { + try + { + Crestron.SimplSharpPro.CrestronThread.Thread.MaxNumberOfUserThreads = 400; + + Global.ControlSystem = this; + DeviceManager.Initialize(this); + SecretsManager.Initialize(); + SystemMonitor.ProgramInitialization.ProgramInitializationUnderUserControl = true; + + Debug.SetErrorLogMinimumDebugLevel(CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? LogEventLevel.Warning : LogEventLevel.Verbose); + } + catch (Exception e) { - Thread.MaxNumberOfUserThreads = 400; - Global.ControlSystem = this; - DeviceManager.Initialize(this); - SecretsManager.Initialize(); - SystemMonitor.ProgramInitialization.ProgramInitializationUnderUserControl = true; - - Debug.SetErrorLogMinimumDebugLevel(CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? LogEventLevel.Warning : LogEventLevel.Verbose); - - // AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainOnAssemblyResolve; + Debug.LogError(e, "FATAL INITIALIZE ERROR. System is in an inconsistent state"); } + } - private System.Reflection.Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args) + /// + /// Initializes the control system and prepares it for operation. + /// + /// This method ensures that all devices in the system are properly registered and initialized + /// before the system is fully operational. If the control system is of a DMPS type, the method waits for all + /// devices to activate, allowing HD-BaseT DM endpoints to register before completing initialization. For non-DMPS + /// systems, initialization proceeds without waiting. + public override void InitializeSystem() + { + // If the control system is a DMPS type, we need to wait to exit this method until all devices have had time to activate + // to allow any HD-BaseT DM endpoints to register first. + bool preventInitializationComplete = Global.ControlSystemIsDmpsType; + if (preventInitializationComplete) { - var assemblyName = new System.Reflection.AssemblyName(args.Name).Name; - if (assemblyName == "PepperDash_Core") - { - return System.Reflection.Assembly.LoadFrom("PepperDashCore.dll"); - } + Debug.LogMessage(LogEventLevel.Debug, "******************* Initializing System **********************"); + + _startTimer = new Timer(StartSystem, preventInitializationComplete, StartupTime, Timeout.Infinite); - if (assemblyName == "PepperDash_Essentials_Core") - { - return System.Reflection.Assembly.LoadFrom("PepperDash.Essentials.Core.dll"); - } + _initializeEvent = new ManualResetEventSlim(false); - if (assemblyName == "Essentials Devices Common") + DeviceManager.AllDevicesRegistered += (o, a) => { - return System.Reflection.Assembly.LoadFrom("PepperDash.Essentials.Devices.Common.dll"); - } + _initializeEvent.Set(); + }; - return null; - } + _initializeEvent.Wait(30000); - /// - /// Entry point for the program - /// - public override void InitializeSystem() - { - // If the control system is a DMPS type, we need to wait to exit this method until all devices have had time to activate - // to allow any HD-BaseT DM endpoints to register first. - bool preventInitializationComplete = Global.ControlSystemIsDmpsType; - if (preventInitializationComplete) - { - Debug.LogMessage(LogEventLevel.Debug, "******************* InitializeSystem() Entering **********************"); - - _startTimer = new CTimer(StartSystem, preventInitializationComplete, StartupTime); - _initializeEvent = new CEvent(true, false); - DeviceManager.AllDevicesRegistered += (o, a) => - { - _initializeEvent.Set(); - }; - _initializeEvent.Wait(30000); - Debug.LogMessage(LogEventLevel.Debug, "******************* InitializeSystem() Exiting **********************"); - - SystemMonitor.ProgramInitialization.ProgramInitializationComplete = true; - } - else - { - _startTimer = new CTimer(StartSystem, preventInitializationComplete, StartupTime); - } + Debug.LogMessage(LogEventLevel.Debug, "******************* System Initialization Complete **********************"); + + SystemMonitor.ProgramInitialization.ProgramInitializationComplete = true; } - - private void StartSystem(object preventInitialization) + else { - Debug.SetErrorLogMinimumDebugLevel(Serilog.Events.LogEventLevel.Verbose); + _startTimer = new Timer(StartSystem, preventInitializationComplete, StartupTime, Timeout.Infinite); + } + } - DeterminePlatform(); + private void StartSystem(object preventInitialization) + { + DeterminePlatform(); - if (Debug.DoNotLoadConfigOnNextBoot) - { - CrestronConsole.AddNewConsoleCommand(s => CrestronInvoke.BeginInvoke((o) => GoWithLoad()), "go", "Loads configuration file", - ConsoleAccessLevelEnum.AccessOperator); - } + // Print .NET runtime version + Debug.LogMessage(LogEventLevel.Information, "Running on .NET runtime version: {0}", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription); - CrestronConsole.AddNewConsoleCommand(PluginLoader.ReportAssemblyVersions, "reportversions", "Reports the versions of the loaded assemblies", ConsoleAccessLevelEnum.AccessOperator); + if (Debug.DoNotLoadConfigOnNextBoot) + { + CrestronConsole.AddNewConsoleCommand(s => CrestronInvoke.BeginInvoke((o) => GoWithLoad()), "go", "Loads configuration file", + ConsoleAccessLevelEnum.AccessOperator); + } - CrestronConsole.AddNewConsoleCommand(Core.DeviceFactory.GetDeviceFactoryTypes, "gettypes", "Gets the device types that can be built. Accepts a filter string.", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(PluginLoader.ReportAssemblyVersions, "reportversions", "Reports the versions of the loaded assemblies", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(BridgeHelper.PrintJoinMap, "getjoinmap", "map(s) for bridge or device on bridge [brKey [devKey]]", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(Core.DeviceFactory.GetDeviceFactoryTypes, "gettypes", "Gets the device types that can be built. Accepts a filter string.", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(BridgeHelper.JoinmapMarkdown, "getjoinmapmarkdown" - , "generate markdown of map(s) for bridge or device on bridge [brKey [devKey]]", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(BridgeHelper.PrintJoinMap, "getjoinmap", "map(s) for bridge or device on bridge [brKey [devKey]]", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => Debug.LogMessage(LogEventLevel.Information, "CONSOLE MESSAGE: {0}", s), "appdebugmessage", "Writes message to log", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(BridgeHelper.JoinmapMarkdown, "getjoinmapmarkdown" + , "generate markdown of map(s) for bridge or device on bridge [brKey [devKey]]", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => - { - foreach (var tl in TieLineCollection.Default) - CrestronConsole.ConsoleCommandResponse(" {0}{1}", tl, CrestronEnvironment.NewLine); - }, - "listtielines", "Prints out all tie lines", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => Debug.LogMessage(LogEventLevel.Information, "CONSOLE MESSAGE: {0}", s), "appdebugmessage", "Writes message to log", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => - { - CrestronConsole.ConsoleCommandResponse - ("Current running configuration. This is the merged system and template configuration" + CrestronEnvironment.NewLine); - CrestronConsole.ConsoleCommandResponse(Newtonsoft.Json.JsonConvert.SerializeObject - (ConfigReader.ConfigObject, Newtonsoft.Json.Formatting.Indented)); - }, "showconfig", "Shows the current running merged config", ConsoleAccessLevelEnum.AccessOperator); - - CrestronConsole.AddNewConsoleCommand(s => - CrestronConsole.ConsoleCommandResponse( - "This system can be found at the following URLs:{2}" + - "System URL: {0}{2}" + - "Template URL: {1}{2}", - ConfigReader.ConfigObject.SystemUrl, - ConfigReader.ConfigObject.TemplateUrl, - CrestronEnvironment.NewLine), - "portalinfo", - "Shows portal URLS from configuration", - ConsoleAccessLevelEnum.AccessOperator); - - - CrestronConsole.AddNewConsoleCommand(DeviceManager.GetRoutingPorts, - "getroutingports", "Reports all routing ports, if any. Requires a device key", ConsoleAccessLevelEnum.AccessOperator); - - DeviceManager.AddDevice(new EssentialsWebApi("essentialsWebApi", "Essentials Web API")); + CrestronConsole.AddNewConsoleCommand(s => + { + foreach (var tl in TieLineCollection.Default) + CrestronConsole.ConsoleCommandResponse(" {0}{1}", tl, CrestronEnvironment.NewLine); + }, + "listtielines", "Prints out all tie lines", ConsoleAccessLevelEnum.AccessOperator); - if (!Debug.DoNotLoadConfigOnNextBoot) - { - GoWithLoad(); - return; - } + CrestronConsole.AddNewConsoleCommand(s => + { + CrestronConsole.ConsoleCommandResponse + ("Current running configuration. This is the merged system and template configuration" + CrestronEnvironment.NewLine); + CrestronConsole.ConsoleCommandResponse(Newtonsoft.Json.JsonConvert.SerializeObject + (ConfigReader.ConfigObject, Newtonsoft.Json.Formatting.Indented)); + }, "showconfig", "Shows the current running merged config", ConsoleAccessLevelEnum.AccessOperator); + + CrestronConsole.AddNewConsoleCommand(s => + CrestronConsole.ConsoleCommandResponse( + "This system can be found at the following URLs:{2}" + + "System URL: {0}{2}" + + "Template URL: {1}{2}", + ConfigReader.ConfigObject.SystemUrl, + ConfigReader.ConfigObject.TemplateUrl, + CrestronEnvironment.NewLine), + "portalinfo", + "Shows portal URLS from configuration", + ConsoleAccessLevelEnum.AccessOperator); + + + CrestronConsole.AddNewConsoleCommand(DeviceManager.GetRoutingPorts, + "getroutingports", "Reports all routing ports, if any. Requires a device key", ConsoleAccessLevelEnum.AccessOperator); + + + if (!Debug.DoNotLoadConfigOnNextBoot) + { + GoWithLoad(); + return; + } - if (!(bool)preventInitialization) - { - SystemMonitor.ProgramInitialization.ProgramInitializationComplete = true; - } + if (!(bool)preventInitialization) + { + SystemMonitor.ProgramInitialization.ProgramInitializationComplete = true; } + } - /// - /// Determines if the program is running on a processor (appliance) or server (VC-4). - /// - /// Sets Global.FilePathPrefix and Global.ApplicationDirectoryPathPrefix based on platform - /// - public void DeterminePlatform() + /// + /// Determines if the program is running on a processor (appliance) or server (VC-4). + /// + /// Sets Global.FilePathPrefix and Global.ApplicationDirectoryPathPrefix based on platform + /// + public void DeterminePlatform() + { + try { - try - { - Debug.LogMessage(LogEventLevel.Information, "Determining Platform..."); + Debug.LogMessage(LogEventLevel.Information, "Determining Platform..."); - string filePathPrefix; + string filePathPrefix; - var dirSeparator = Global.DirectorySeparator; + var dirSeparator = Global.DirectorySeparator; - string directoryPrefix; + string directoryPrefix; - directoryPrefix = Directory.GetApplicationRootDirectory(); + directoryPrefix = Directory.GetApplicationRootDirectory(); - Global.SetAssemblyVersion(PluginLoader.GetAssemblyVersion(Assembly.GetExecutingAssembly())); + Global.SetAssemblyVersion(PluginLoader.GetAssemblyVersion(Assembly.GetExecutingAssembly())); - if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server) // Handles 3-series running Windows CE OS + if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server) // Handles 3-series running Windows CE OS + { + string userFolder = "user"; + string nvramFolder = "nvram"; + + Debug.LogMessage(LogEventLevel.Information, "Starting Essentials v{version:l} on {processorSeries:l} Appliance", Global.AssemblyVersion, "4-series"); + //Debug.LogMessage(LogEventLevel.Information, "Starting Essentials v{0} on {1} Appliance", Global.AssemblyVersion, is4series ? "4-series" : "3-series"); + + // Check if User/ProgramX exists + if (Directory.Exists(Global.ApplicationDirectoryPathPrefix + dirSeparator + userFolder + + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber))) + { + + Debug.LogMessage(LogEventLevel.Information, "{userFolder:l}/program{applicationNumber} directory found", userFolder, InitialParametersClass.ApplicationNumber); + filePathPrefix = directoryPrefix + dirSeparator + userFolder + + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator; + } + // Check if Nvram/Programx exists + else if (Directory.Exists(directoryPrefix + dirSeparator + nvramFolder + + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber))) { - string userFolder; - string nvramFolder; - bool is4series = false; - - if (eCrestronSeries.Series4 == (Global.ProcessorSeries & eCrestronSeries.Series4)) // Handle 4-series - { - is4series = true; - // Set path to user/ - userFolder = "user"; - nvramFolder = "nvram"; - } - else - { - userFolder = "User"; - nvramFolder = "Nvram"; - } + Debug.LogMessage(LogEventLevel.Information, "{nvramFolder:l}/program{applicationNumber} directory found", nvramFolder, InitialParametersClass.ApplicationNumber); - Debug.LogMessage(LogEventLevel.Information, "Starting Essentials v{version:l} on {processorSeries:l} Appliance", Global.AssemblyVersion, is4series ? "4-series" : "3-series"); - //Debug.LogMessage(LogEventLevel.Information, "Starting Essentials v{0} on {1} Appliance", Global.AssemblyVersion, is4series ? "4-series" : "3-series"); - - // Check if User/ProgramX exists - if (Directory.Exists(Global.ApplicationDirectoryPathPrefix + dirSeparator + userFolder - + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber))) - { - - Debug.LogMessage(LogEventLevel.Information, "{userFolder:l}/program{applicationNumber} directory found", userFolder, InitialParametersClass.ApplicationNumber); - filePathPrefix = directoryPrefix + dirSeparator + userFolder - + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator; - } - // Check if Nvram/Programx exists - else if (Directory.Exists(directoryPrefix + dirSeparator + nvramFolder - + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber))) - { - Debug.LogMessage(LogEventLevel.Information, "{nvramFolder:l}/program{applicationNumber} directory found", nvramFolder, InitialParametersClass.ApplicationNumber); - - filePathPrefix = directoryPrefix + dirSeparator + nvramFolder - + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator; - } - // If neither exists, set path to User/ProgramX - else - { - Debug.LogMessage(LogEventLevel.Information, "{userFolder:l}/program{applicationNumber} directory found", userFolder, InitialParametersClass.ApplicationNumber); - - filePathPrefix = directoryPrefix + dirSeparator + userFolder - + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator; - } + filePathPrefix = directoryPrefix + dirSeparator + nvramFolder + + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator; } - else // Handles Linux OS (Virtual Control) + // If neither exists, set path to User/ProgramX + else { - //Debug.SetDebugLevel(2); - Debug.LogMessage(LogEventLevel.Information, "Starting Essentials v{version:l} on Virtual Control Server", Global.AssemblyVersion); - - // Set path to User/ - filePathPrefix = directoryPrefix + dirSeparator + "User" + dirSeparator; + Debug.LogMessage(LogEventLevel.Information, "{userFolder:l}/program{applicationNumber} directory found", userFolder, InitialParametersClass.ApplicationNumber); + + filePathPrefix = directoryPrefix + dirSeparator + userFolder + + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator; } - - Global.SetFilePathPrefix(filePathPrefix); } - catch (Exception e) + else // Handles Linux OS (Virtual Control) { - Debug.LogMessage(e, "Unable to determine platform due to exception"); + //Debug.SetDebugLevel(2); + Debug.LogMessage(LogEventLevel.Information, "Starting Essentials v{version:l} on Virtual Control Server", Global.AssemblyVersion); + + // Set path to User/ + filePathPrefix = directoryPrefix + dirSeparator + "User" + dirSeparator; } + + Global.SetFilePathPrefix(filePathPrefix); } + catch (Exception e) + { + Debug.LogMessage(e, "Unable to determine platform due to exception"); + } + } - /// - /// Begins the process of loading resources including plugins and configuration data - /// - public void GoWithLoad() + /// + /// Begins the process of loading resources including plugins and configuration data + /// + public void GoWithLoad() + { + try { - try - { - Debug.SetDoNotLoadConfigOnNextBoot(false); + Debug.SetDoNotLoadConfigOnNextBoot(false); - PluginLoader.AddProgramAssemblies(); + PluginLoader.AddProgramAssemblies(); - _ = new Core.DeviceFactory(); - _ = new Devices.Common.DeviceFactory(); - _ = new DeviceFactory(); + _ = new Core.DeviceFactory(); - _ = new ProcessorExtensionDeviceFactory(); - _ = new MobileControlFactory(); + Debug.LogMessage(LogEventLevel.Information, "Starting Essentials load from configuration"); - Debug.LogMessage(LogEventLevel.Information, "Starting Essentials load from configuration"); + var filesReady = SetupFilesystem(); + if (filesReady) + { + Debug.LogMessage(LogEventLevel.Information, "Checking for plugins"); + PluginLoader.LoadPlugins(); - var filesReady = SetupFilesystem(); - if (filesReady) + Debug.LogMessage(LogEventLevel.Information, "Folder structure verified. Loading config..."); + if (!ConfigReader.LoadConfig2()) { - Debug.LogMessage(LogEventLevel.Information, "Checking for plugins"); - PluginLoader.LoadPlugins(); - - Debug.LogMessage(LogEventLevel.Information, "Folder structure verified. Loading config..."); - if (!ConfigReader.LoadConfig2()) - { - Debug.LogMessage(LogEventLevel.Information, "Essentials Load complete with errors"); - return; - } - - Load(); - Debug.LogMessage(LogEventLevel.Information, "Essentials load complete"); + Debug.LogMessage(LogEventLevel.Information, "Essentials Load complete with errors"); + return; } - else - { - Debug.LogMessage(LogEventLevel.Information, - @"---------------------------------------------- + + Load(); + Debug.LogMessage(LogEventLevel.Information, "Essentials load complete"); + } + else + { + Debug.LogMessage(LogEventLevel.Information, + @"---------------------------------------------- ------------------------------------------------ ------------------------------------------------ Essentials file structure setup completed. @@ -293,51 +284,51 @@ restart program. ------------------------------------------------ ------------------------------------------------ ------------------------------------------------"); - } - - } - catch (Exception e) - { - Debug.LogMessage(e, "FATAL INITIALIZE ERROR. System is in an inconsistent state"); - } - finally - { - // Notify the OS that the program intitialization has completed - SystemMonitor.ProgramInitialization.ProgramInitializationComplete = true; } } + catch (Exception e) + { + Debug.LogMessage(e, "FATAL INITIALIZE ERROR. System is in an inconsistent state"); + } + finally + { + // Notify the OS that the program intitialization has completed + SystemMonitor.ProgramInitialization.ProgramInitializationComplete = true; + } - + } - /// - /// Verifies filesystem is set up. IR, SGD, and programX folders - /// - bool SetupFilesystem() - { - Debug.LogMessage(LogEventLevel.Information, "Verifying and/or creating folder structure"); - var configDir = Global.FilePathPrefix; + + + /// + /// Verifies filesystem is set up. IR, SGD, and programX folders + /// + bool SetupFilesystem() + { + Debug.LogMessage(LogEventLevel.Information, "Verifying and/or creating folder structure"); + var configDir = Global.FilePathPrefix; - Debug.LogMessage(LogEventLevel.Information, "FilePathPrefix: {filePathPrefix:l}", configDir); - var configExists = Directory.Exists(configDir); - if (!configExists) - Directory.Create(configDir); + Debug.LogMessage(LogEventLevel.Information, "FilePathPrefix: {filePathPrefix:l}", configDir); + var configExists = Directory.Exists(configDir); + if (!configExists) + Directory.Create(configDir); - var irDir = Global.FilePathPrefix + "ir"; - if (!Directory.Exists(irDir)) - Directory.Create(irDir); + var irDir = Global.FilePathPrefix + "ir"; + if (!Directory.Exists(irDir)) + Directory.Create(irDir); - var sgdDir = Global.FilePathPrefix + "sgd"; + var sgdDir = Global.FilePathPrefix + "sgd"; if (!Directory.Exists(sgdDir)) Directory.Create(sgdDir); - var pluginDir = Global.FilePathPrefix + "plugins"; - if (!Directory.Exists(pluginDir)) - Directory.Create(pluginDir); + var pluginDir = Global.FilePathPrefix + "plugins"; + if (!Directory.Exists(pluginDir)) + Directory.Create(pluginDir); - var joinmapDir = Global.FilePathPrefix + "joinmaps"; - if(!Directory.Exists(joinmapDir)) - Directory.Create(joinmapDir); + var joinmapDir = Global.FilePathPrefix + "joinmaps"; + if(!Directory.Exists(joinmapDir)) + Directory.Create(joinmapDir); return configExists; } @@ -361,6 +352,7 @@ public void TearDown() /// /// /// + void Load() { LoadDevices(); @@ -369,199 +361,198 @@ void Load() DeviceManager.ActivateAll(); - LoadTieLines(); + LoadTieLines(); - /*var mobileControl = GetMobileControlDevice(); + /*var mobileControl = GetMobileControlDevice(); if (mobileControl == null) return; - mobileControl.LinkSystemMonitorToAppServer();*/ + mobileControl.LinkSystemMonitorToAppServer();*/ } - /// - /// Reads all devices from config and adds them to DeviceManager - /// - public void LoadDevices() - { + /// + /// Reads all devices from config and adds them to DeviceManager + /// + public void LoadDevices() + { - // Build the processor wrapper class - DeviceManager.AddDevice(new Core.Devices.CrestronProcessor("processor")); + // Build the processor wrapper class + DeviceManager.AddDevice(new Core.Devices.CrestronProcessor("processor")); - DeviceManager.AddDevice(new RoutingFeedbackManager($"routingFeedbackManager", "Routing Feedback Manager")); + DeviceManager.AddDevice(new RoutingFeedbackManager($"routingFeedbackManager", "Routing Feedback Manager")); - // Add global System Monitor device - if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance) - { - DeviceManager.AddDevice( - new Core.Monitoring.SystemMonitorController("systemMonitor")); - } + // Add global System Monitor device + if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance) + { + DeviceManager.AddDevice( + new Core.Monitoring.SystemMonitorController("systemMonitor")); + } - foreach (var devConf in ConfigReader.ConfigObject.Devices) - { - IKeyed newDev = null; + foreach (var devConf in ConfigReader.ConfigObject.Devices) + { + IKeyed newDev = null; - try + try + { + Debug.LogMessage(LogEventLevel.Information, "Creating device '{deviceKey:l}', type '{deviceType:l}'", devConf.Key, devConf.Type); + // Skip this to prevent unnecessary warnings + if (devConf.Key == "processor") { - Debug.LogMessage(LogEventLevel.Information, "Creating device '{deviceKey:l}', type '{deviceType:l}'", devConf.Key, devConf.Type); - // Skip this to prevent unnecessary warnings - if (devConf.Key == "processor") - { - var prompt = Global.ControlSystem.ControllerPrompt; + var prompt = Global.ControlSystem.ControllerPrompt; - var typeMatch = String.Equals(devConf.Type, prompt, StringComparison.OrdinalIgnoreCase) || - String.Equals(devConf.Type, prompt.Replace("-", ""), StringComparison.OrdinalIgnoreCase); + var typeMatch = string.Equals(devConf.Type, prompt, StringComparison.OrdinalIgnoreCase) || + string.Equals(devConf.Type, prompt.Replace("-", ""), StringComparison.OrdinalIgnoreCase); - if (!typeMatch) - Debug.LogMessage(LogEventLevel.Information, - "WARNING: Config file defines processor type as '{deviceType:l}' but actual processor is '{processorType:l}'! Some ports may not be available", - devConf.Type.ToUpper(), Global.ControlSystem.ControllerPrompt.ToUpper()); + if (!typeMatch) + Debug.LogMessage(LogEventLevel.Information, + "WARNING: Config file defines processor type as '{deviceType:l}' but actual processor is '{processorType:l}'! Some ports may not be available", + devConf.Type.ToUpper(), Global.ControlSystem.ControllerPrompt.ToUpper()); - continue; - } + continue; + } - if (newDev == null) - newDev = Core.DeviceFactory.GetDevice(devConf); + if (newDev == null) + newDev = Core.DeviceFactory.GetDevice(devConf); if (newDev != null) DeviceManager.AddDevice(newDev); else - Debug.LogMessage(LogEventLevel.Information, "ERROR: Cannot load unknown device type '{deviceType:l}', key '{deviceKey:l}'.", devConf.Type, devConf.Key); - } - catch (Exception e) - { - Debug.LogMessage(e, "ERROR: Creating device {deviceKey:l}. Skipping device.",args: new[] { devConf.Key }); - } + Debug.LogMessage(LogEventLevel.Information, "ERROR: Cannot load unknown device type '{deviceType:l}', key '{deviceKey:l}'.", devConf.Type, devConf.Key); + } + catch (Exception e) + { + Debug.LogMessage(e, "ERROR: Creating device {deviceKey:l}. Skipping device.",args: new[] { devConf.Key }); } - Debug.LogMessage(LogEventLevel.Information, "All Devices Loaded."); - } + Debug.LogMessage(LogEventLevel.Information, "All Devices Loaded."); + } - /// - /// Helper method to load tie lines. This should run after devices have loaded - /// - public void LoadTieLines() - { - // In the future, we can't necessarily just clear here because devices - // might be making their own internal sources/tie lines - - var tlc = TieLineCollection.Default; - if (ConfigReader.ConfigObject.TieLines == null) - { - return; - } + /// + /// Helper method to load tie lines. This should run after devices have loaded + /// + public void LoadTieLines() + { + // In the future, we can't necessarily just clear here because devices + // might be making their own internal sources/tie lines - foreach (var tieLineConfig in ConfigReader.ConfigObject.TieLines) - { - var newTL = tieLineConfig.GetTieLine(); - if (newTL != null) - tlc.Add(newTL); - } + var tlc = TieLineCollection.Default; - Debug.LogMessage(LogEventLevel.Information, "All Tie Lines Loaded."); + if (ConfigReader.ConfigObject.TieLines == null) + { + return; + } + foreach (var tieLineConfig in ConfigReader.ConfigObject.TieLines) + { + var newTL = tieLineConfig.GetTieLine(); + if (newTL != null) + tlc.Add(newTL); } - /// - /// Reads all rooms from config and adds them to DeviceManager - /// - public void LoadRooms() - { - if (ConfigReader.ConfigObject.Rooms == null) - { - Debug.LogMessage(LogEventLevel.Information, "Notice: Configuration contains no rooms - Is this intentional? This may be a valid configuration."); - return; - } + Debug.LogMessage(LogEventLevel.Information, "All Tie Lines Loaded."); - foreach (var roomConfig in ConfigReader.ConfigObject.Rooms) - { - try - { - var room = Core.DeviceFactory.GetDevice(roomConfig); + } + + /// + /// Reads all rooms from config and adds them to DeviceManager + /// + public void LoadRooms() + { + if (ConfigReader.ConfigObject.Rooms == null) + { + Debug.LogMessage(LogEventLevel.Information, "Notice: Configuration contains no rooms - Is this intentional? This may be a valid configuration."); + return; + } - if(room == null) - { - Debug.LogWarning("ERROR: Cannot load unknown room type '{roomType:l}', key '{roomKey:l}'.", roomConfig.Type, roomConfig.Key); - continue; - } + foreach (var roomConfig in ConfigReader.ConfigObject.Rooms) + { + try + { + var room = Core.DeviceFactory.GetDevice(roomConfig); - DeviceManager.AddDevice(room); - } catch (Exception ex) + if(room == null) { - Debug.LogMessage(ex, "Exception loading room {roomKey}:{roomType}", null, roomConfig.Key, roomConfig.Type); + Debug.LogWarning("ERROR: Cannot load unknown room type '{roomType:l}', key '{roomKey:l}'.", roomConfig.Type, roomConfig.Key); continue; } + + DeviceManager.AddDevice(room); + } catch (Exception ex) + { + Debug.LogMessage(ex, "Exception loading room {roomKey}:{roomType}", null, roomConfig.Key, roomConfig.Type); + continue; } + } + + Debug.LogMessage(LogEventLevel.Information, "All Rooms Loaded."); - Debug.LogMessage(LogEventLevel.Information, "All Rooms Loaded."); + } + /// + /// Fires up a logo server if not already running + /// + void LoadLogoServer() + { + if (ConfigReader.ConfigObject.Rooms == null) + { + Debug.LogMessage(LogEventLevel.Information, "No rooms configured. Bypassing Logo server startup."); + return; } - /// - /// Fires up a logo server if not already running - /// - void LoadLogoServer() + if ( + !ConfigReader.ConfigObject.Rooms.Any( + CheckRoomConfig)) { - if (ConfigReader.ConfigObject.Rooms == null) - { - Debug.LogMessage(LogEventLevel.Information, "No rooms configured. Bypassing Logo server startup."); - return; - } + Debug.LogMessage(LogEventLevel.Information, "No rooms configured to use system Logo server. Bypassing Logo server startup"); + return; + } + + try + { + LogoServer = new HttpLogoServer(8080, Global.DirectorySeparator + "html" + Global.DirectorySeparator + "logo"); + } + catch (Exception) + { + Debug.LogMessage(LogEventLevel.Information, "NOTICE: Logo server cannot be started. Likely already running in another program"); + } + } + + private bool CheckRoomConfig(DeviceConfig c) + { + string logoDark = null; + string logoLight = null; + string logo = null; - if ( - !ConfigReader.ConfigObject.Rooms.Any( - CheckRoomConfig)) + try + { + if (c.Properties["logoDark"] != null) { - Debug.LogMessage(LogEventLevel.Information, "No rooms configured to use system Logo server. Bypassing Logo server startup"); - return; + logoDark = c.Properties["logoDark"].Value("type"); } - try + if (c.Properties["logoLight"] != null) { - LogoServer = new HttpLogoServer(8080, Global.DirectorySeparator + "html" + Global.DirectorySeparator + "logo"); + logoLight = c.Properties["logoLight"].Value("type"); } - catch (Exception) + + if (c.Properties["logo"] != null) { - Debug.LogMessage(LogEventLevel.Information, "NOTICE: Logo server cannot be started. Likely already running in another program"); + logo = c.Properties["logo"].Value("type"); } - } - private bool CheckRoomConfig(DeviceConfig c) + return ((logoDark != null && logoDark == "system") || + (logoLight != null && logoLight == "system") || (logo != null && logo == "system")); + } + catch { - string logoDark = null; - string logoLight = null; - string logo = null; - - try - { - if (c.Properties["logoDark"] != null) - { - logoDark = c.Properties["logoDark"].Value("type"); - } - - if (c.Properties["logoLight"] != null) - { - logoLight = c.Properties["logoLight"].Value("type"); - } - - if (c.Properties["logo"] != null) - { - logo = c.Properties["logo"].Value("type"); - } - - return ((logoDark != null && logoDark == "system") || - (logoLight != null && logoLight == "system") || (logo != null && logo == "system")); - } - catch - { - Debug.LogMessage(LogEventLevel.Information, "Unable to find logo information in any room config"); - return false; - } + Debug.LogMessage(LogEventLevel.Information, "Unable to find logo information in any room config"); + return false; } } } diff --git a/src/PepperDash.Essentials/Factory/DeviceFactory.cs b/src/PepperDash.Essentials/Factory/DeviceFactory.cs index 262130f1f..425394f8b 100644 --- a/src/PepperDash.Essentials/Factory/DeviceFactory.cs +++ b/src/PepperDash.Essentials/Factory/DeviceFactory.cs @@ -14,36 +14,54 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; -namespace PepperDash.Essentials +namespace PepperDash.Essentials; + +/// +/// Responsible for loading all of the device types for this library +/// +public class DeviceFactory { - /// - /// Responsible for loading all of the device types for this library - /// - public class DeviceFactory - { - public DeviceFactory() - { - var assy = Assembly.GetExecutingAssembly(); - PluginLoader.SetEssentialsAssembly(assy.GetName().Name, assy); + public DeviceFactory() + { + var assy = Assembly.GetExecutingAssembly(); + PluginLoader.AddLoadedAssembly(assy.GetName().Name, assy); - var types = assy.GetTypes().Where(ct => typeof(IDeviceFactory).IsAssignableFrom(ct) && !ct.IsInterface && !ct.IsAbstract); + var types = assy.GetTypes().Where(ct => typeof(IDeviceFactory).IsAssignableFrom(ct) && !ct.IsInterface && !ct.IsAbstract); - if (types != null) + if (types != null) + { + foreach (var type in types) { - foreach (var type in types) + try + { + var factory = (IDeviceFactory)Activator.CreateInstance(type); + LoadDeviceFactories(factory); + } + catch (Exception e) { - try - { - var factory = (IDeviceFactory)Activator.CreateInstance(type); - factory.LoadTypeFactories(); - } - catch (Exception e) - { - Debug.LogMessage(Serilog.Events.LogEventLevel.Error, "Unable to load type: '{exception}' DeviceFactory: {factoryName}", e, type.Name); - } + Debug.LogMessage(Serilog.Events.LogEventLevel.Error, "Unable to load type: '{exception}' DeviceFactory: {factoryName}", e, type.Name); } } } } + + /// + /// Loads device factories from the specified plugin device factory and registers them for use. + /// + /// This method retrieves metadata from the provided , including + /// type names, descriptions, and configuration snippets, and registers the factory for each device type. The type + /// names are converted to lowercase for registration. + /// The plugin device factory that provides the device types, descriptions, and factory methods to be registered. + private static void LoadDeviceFactories(IDeviceFactory deviceFactory) + { + foreach (var typeName in deviceFactory.TypeNames) + { + //Debug.LogMessage(LogEventLevel.Verbose, "Getting Description Attribute from class: '{0}'", typeof(T).FullName); + var descriptionAttribute = deviceFactory.FactoryType.GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[]; + string description = descriptionAttribute[0].Description; + var snippetAttribute = deviceFactory.FactoryType.GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[]; + Core.DeviceFactory.AddFactoryForType(typeName.ToLower(), description, deviceFactory.FactoryType, deviceFactory.BuildDevice); + } + } } diff --git a/src/PepperDash.Essentials/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs b/src/PepperDash.Essentials/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs new file mode 100644 index 000000000..b6533089f --- /dev/null +++ b/src/PepperDash.Essentials/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs @@ -0,0 +1,39 @@ +using System; +using System.Net.WebSockets; +using System.Threading; +using System.Threading.Tasks; + +namespace PepperDash.Essentials.Fusion; + +public class EssentialsHuddleSpaceFusionSystemControllerBase +{ + private ClientWebSocket _webSocket; + + public EssentialsHuddleSpaceFusionSystemControllerBase() + { + _webSocket = new ClientWebSocket(); + } + + public async Task ConnectAsync(Uri uri) + { + await _webSocket.ConnectAsync(uri, CancellationToken.None); + } + + public async Task SendAsync(string message) + { + var buffer = System.Text.Encoding.UTF8.GetBytes(message); + await _webSocket.SendAsync(new ArraySegment(buffer), WebSocketMessageType.Text, true, CancellationToken.None); + } + + public async Task ReceiveAsync() + { + var buffer = new byte[1024]; + var result = await _webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); + return System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count); + } + + public async Task CloseAsync() + { + await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); + } +} diff --git a/src/PepperDash.Essentials/HttpLogoServer.cs b/src/PepperDash.Essentials/HttpLogoServer.cs index 1c7a47838..174ebd7ef 100644 --- a/src/PepperDash.Essentials/HttpLogoServer.cs +++ b/src/PepperDash.Essentials/HttpLogoServer.cs @@ -7,118 +7,117 @@ using PepperDash.Core; using Serilog.Events; -namespace PepperDash.Essentials +namespace PepperDash.Essentials; + +public class HttpLogoServer { - public class HttpLogoServer - { - /// - /// - /// - readonly HttpServer _server; + /// + /// + /// + readonly HttpServer _server; - /// - /// - /// - readonly string _fileDirectory; + /// + /// + /// + readonly string _fileDirectory; - /// - /// - /// - public static Dictionary ExtensionContentTypes; + /// + /// + /// + public static Dictionary ExtensionContentTypes; - /// - /// - /// - /// - /// - public HttpLogoServer(int port, string directory) - { - ExtensionContentTypes = new Dictionary + /// + /// + /// + /// + /// + public HttpLogoServer(int port, string directory) + { + ExtensionContentTypes = new Dictionary { - //{ ".css", "text/css" }, - //{ ".htm", "text/html" }, - //{ ".html", "text/html" }, + //{ ".css", "text/css" }, + //{ ".htm", "text/html" }, + //{ ".html", "text/html" }, { ".jpg", "image/jpeg" }, { ".jpeg", "image/jpeg" }, - //{ ".js", "application/javascript" }, - //{ ".json", "application/json" }, - //{ ".map", "application/x-navimap" }, + //{ ".js", "application/javascript" }, + //{ ".json", "application/json" }, + //{ ".map", "application/x-navimap" }, { ".pdf", "application/pdf" }, { ".png", "image/png" }, - //{ ".txt", "text/plain" }, + //{ ".txt", "text/plain" }, }; - _server = new HttpServer {Port = port}; - _fileDirectory = directory; - _server.OnHttpRequest += Server_OnHttpRequest; - _server.Open(); + _server = new HttpServer {Port = port}; + _fileDirectory = directory; + _server.OnHttpRequest += Server_OnHttpRequest; + _server.Open(); - CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler; - } + CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler; + } - /// - /// - /// - void Server_OnHttpRequest(object sender, OnHttpRequestArgs args) - { - var path = args.Request.Path; - Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "HTTP Request with path: '{requestPath:l}'", args.Request.Path); + /// + /// + /// + void Server_OnHttpRequest(object sender, OnHttpRequestArgs args) + { + var path = args.Request.Path; + Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "HTTP Request with path: '{requestPath:l}'", args.Request.Path); - try + try + { + if (File.Exists(_fileDirectory + path)) { - if (File.Exists(_fileDirectory + path)) - { - var filePath = path.Replace('/', '\\'); - var localPath = string.Format(@"{0}{1}", _fileDirectory, filePath); + var filePath = path.Replace('/', '\\'); + var localPath = string.Format(@"{0}{1}", _fileDirectory, filePath); - Debug.LogMessage(LogEventLevel.Verbose, "HTTP Logo Server attempting to find file: '{localPath:l}'", localPath); - if (File.Exists(localPath)) - { - args.Response.Header.ContentType = GetContentType(new FileInfo(localPath).Extension); - args.Response.ContentStream = new FileStream(localPath, FileMode.Open, FileAccess.Read); - } - else - { - Debug.LogMessage(LogEventLevel.Verbose, "HTTP Logo Server Cannot find file '{localPath:l}'", localPath); - args.Response.ContentString = string.Format("Not found: '{0}'", filePath); - args.Response.Code = 404; - } + Debug.LogMessage(LogEventLevel.Verbose, "HTTP Logo Server attempting to find file: '{localPath:l}'", localPath); + if (File.Exists(localPath)) + { + args.Response.Header.ContentType = GetContentType(new FileInfo(localPath).Extension); + args.Response.ContentStream = new FileStream(localPath, FileMode.Open, FileAccess.Read); } else { - Debug.LogMessage(LogEventLevel.Verbose, "HTTP Logo Server: '{file:l}' does not exist", _fileDirectory + path); - args.Response.ContentString = string.Format("Not found: '{0}'", _fileDirectory + path); + Debug.LogMessage(LogEventLevel.Verbose, "HTTP Logo Server Cannot find file '{localPath:l}'", localPath); + args.Response.ContentString = string.Format("Not found: '{0}'", filePath); args.Response.Code = 404; } } - catch (Exception ex) + else { - Debug.LogMessage(LogEventLevel.Error, "Exception getting file: {exception}", ex.Message, ex.StackTrace); - Debug.LogMessage(LogEventLevel.Verbose, "Stack Trace: {stackTrace}", ex.StackTrace); - - args.Response.Code = 400; - args.Response.ContentString = string.Format("invalid request"); + Debug.LogMessage(LogEventLevel.Verbose, "HTTP Logo Server: '{file:l}' does not exist", _fileDirectory + path); + args.Response.ContentString = string.Format("Not found: '{0}'", _fileDirectory + path); + args.Response.Code = 404; } } - - /// - /// - /// - void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + catch (Exception ex) { - if (programEventType == eProgramStatusEventType.Stopping) - _server.Close(); - } + Debug.LogMessage(LogEventLevel.Error, "Exception getting file: {exception}", ex.Message, ex.StackTrace); + Debug.LogMessage(LogEventLevel.Verbose, "Stack Trace: {stackTrace}", ex.StackTrace); - /// - /// - /// - /// - /// - public static string GetContentType(string extension) - { - var type = ExtensionContentTypes.ContainsKey(extension) ? ExtensionContentTypes[extension] : "text/plain"; - return type; + args.Response.Code = 400; + args.Response.ContentString = string.Format("invalid request"); } } + + /// + /// + /// + void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) + { + if (programEventType == eProgramStatusEventType.Stopping) + _server.Close(); + } + + /// + /// + /// + /// + /// + public static string GetContentType(string extension) + { + var type = ExtensionContentTypes.ContainsKey(extension) ? ExtensionContentTypes[extension] : "text/plain"; + return type; + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials/PepperDash.Essentials.csproj b/src/PepperDash.Essentials/PepperDash.Essentials.csproj index 04ae0d864..5efd98c91 100644 --- a/src/PepperDash.Essentials/PepperDash.Essentials.csproj +++ b/src/PepperDash.Essentials/PepperDash.Essentials.csproj @@ -6,14 +6,17 @@ PepperDash.Essentials PepperDashEssentials - net472 + net8 true - bin\$(Configuration)\ + $(ProjectDir)bin\$(Configuration)\ PepperDash Essentials PepperDashEssentials $(Version) false + + Program + full @@ -24,30 +27,8 @@ pdbonly - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - - + +