mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-16 13:15:03 +00:00
Compare commits
84 Commits
2.0.0-alph
...
feature-2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
afc37f5426 | ||
|
|
4ed5bb7ada | ||
|
|
4360e7f992 | ||
|
|
f926db418d | ||
|
|
0944be2a70 | ||
|
|
bacc0a4f57 | ||
|
|
1d49ea67ad | ||
|
|
35018b3572 | ||
|
|
237fff5398 | ||
|
|
b2eab21fbd | ||
|
|
f2545fb1cf | ||
|
|
27072e3475 | ||
|
|
e4755ed9df | ||
|
|
316867caf8 | ||
|
|
d8fd774324 | ||
|
|
e0058d8cfe | ||
|
|
a055d06bc6 | ||
|
|
66cb592c70 | ||
|
|
d53a5607e2 | ||
|
|
34f59f1410 | ||
|
|
261779d4c4 | ||
|
|
30d5e2b081 | ||
|
|
5516ed16c3 | ||
|
|
8108b9dfdb | ||
|
|
fb4f1482c7 | ||
|
|
54dcb5de08 | ||
|
|
4ef481375c | ||
|
|
d8a88b2a07 | ||
|
|
cc724ddf19 | ||
|
|
e29e800d9d | ||
|
|
134e8ba02e | ||
|
|
a83ba444d3 | ||
|
|
f4c5e6fbeb | ||
|
|
35d7994cc8 | ||
|
|
c3e9d654c9 | ||
|
|
f68b1e9e49 | ||
|
|
cd81b8af73 | ||
|
|
cd52c245a6 | ||
|
|
0b60f53d0e | ||
|
|
ffed2dea8a | ||
|
|
936dce2046 | ||
|
|
b33704eabe | ||
|
|
aca6fe9af5 | ||
|
|
332faaa9cc | ||
|
|
4449077a39 | ||
|
|
86ba9e0f16 | ||
|
|
db2d8a213d | ||
|
|
590e16298c | ||
|
|
1a11e9019c | ||
|
|
0e16dff90c | ||
|
|
d11827bc7b | ||
|
|
631dd2b00d | ||
|
|
639cd2abfb | ||
|
|
f04f70495f | ||
|
|
fa38e8a9a8 | ||
|
|
f351c036ed | ||
|
|
0a7da79356 | ||
|
|
82ebf45921 | ||
|
|
d0dbe986f3 | ||
|
|
aa503f3b29 | ||
|
|
90251d92df | ||
|
|
778af651d0 | ||
|
|
2e31719a84 | ||
|
|
a96fb21898 | ||
|
|
3f45372e1e | ||
|
|
60dbaf547d | ||
|
|
941e537d53 | ||
|
|
f7c5e18af8 | ||
|
|
ab73bbf979 | ||
|
|
1fb1947158 | ||
|
|
e374f7b50f | ||
|
|
7a263a644a | ||
|
|
97bd30e9c9 | ||
|
|
63c653b21f | ||
|
|
c56841d95b | ||
|
|
64d6df70b0 | ||
|
|
d970d806c9 | ||
|
|
5a9b876d80 | ||
|
|
fb60683af6 | ||
|
|
b63996b9e6 | ||
|
|
bc217a2008 | ||
|
|
fec6b0d385 | ||
|
|
f3b4c0aa02 | ||
|
|
b326ccf6c3 |
52
.github/workflows/docker.yml
vendored
52
.github/workflows/docker.yml
vendored
@@ -66,6 +66,55 @@ jobs:
|
|||||||
# Build the solutions in the docker image
|
# Build the solutions in the docker image
|
||||||
- name: Build Solution
|
- name: Build Solution
|
||||||
run: msbuild .\$($Env:SOLUTION_FILE).sln /p:Platform="Any CPU" /p:Configuration="Debug" /p:Version="${{ steps.setVersion.outputs.version }}" -m
|
run: msbuild .\$($Env:SOLUTION_FILE).sln /p:Platform="Any CPU" /p:Configuration="Debug" /p:Version="${{ steps.setVersion.outputs.version }}" -m
|
||||||
|
- name: Debug CPZ Files
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
Write-Host "Checking for CPZ files..."
|
||||||
|
|
||||||
|
# First, let's find out the actual directory structure
|
||||||
|
Write-Host "Current directory: $(Get-Location)"
|
||||||
|
Write-Host "Directory structure:"
|
||||||
|
Get-ChildItem -Path . -Directory -Recurse -Depth 2 | ForEach-Object { Write-Host $_.FullName }
|
||||||
|
|
||||||
|
# Look for all CPZ files in the repository
|
||||||
|
Write-Host "Searching for all CPZ files in the repository:"
|
||||||
|
$cpzFiles = Get-ChildItem -Path . -Recurse -Filter "*.cpz"
|
||||||
|
if ($cpzFiles.Count -eq 0) {
|
||||||
|
Write-Host "No CPZ files found in the repository."
|
||||||
|
} else {
|
||||||
|
Write-Host "Found $($cpzFiles.Count) CPZ files:"
|
||||||
|
foreach ($file in $cpzFiles) {
|
||||||
|
Write-Host " $($file.FullName)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create output directory if it doesn't exist
|
||||||
|
$outputDir = ".\output\build"
|
||||||
|
if (-not (Test-Path $outputDir)) {
|
||||||
|
New-Item -ItemType Directory -Path $outputDir -Force
|
||||||
|
Write-Host "Created output directory: $outputDir"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy all CPZ files to the output directory
|
||||||
|
foreach ($file in $cpzFiles) {
|
||||||
|
$destPath = Join-Path $outputDir $file.Name
|
||||||
|
Write-Host "Copying $($file.FullName) to $destPath"
|
||||||
|
Copy-Item -Path $file.FullName -Destination $destPath -Force
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- name: Pack Solution
|
||||||
|
run: |
|
||||||
|
dotnet pack .\$($Env:SOLUTION_FILE).sln --configuration $env:BUILD_TYPE --output ./output /p:Version="${{ steps.setVersion.outputs.version }}"
|
||||||
|
|
||||||
|
# Ensure CPZ files are included in the package
|
||||||
|
$cpzFiles = Get-ChildItem -Path . -Recurse | Where-Object { $_.Extension -eq ".cpz" }
|
||||||
|
if ($cpzFiles.Count -eq 0) {
|
||||||
|
Write-Host "WARNING: No CPZ files found!"
|
||||||
|
} else {
|
||||||
|
Write-Host "Found $($cpzFiles.Count) CPZ files"
|
||||||
|
foreach ($file in $cpzFiles) {
|
||||||
|
Write-Host "CPZ file: $($file.FullName)"
|
||||||
|
}
|
||||||
|
}
|
||||||
- name: Create tag for non-rc builds
|
- name: Create tag for non-rc builds
|
||||||
if: contains(steps.setVersion.outputs.version, 'alpha')
|
if: contains(steps.setVersion.outputs.version, 'alpha')
|
||||||
run: |
|
run: |
|
||||||
@@ -74,9 +123,6 @@ jobs:
|
|||||||
# Create the release on the source repo
|
# Create the release on the source repo
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
id: create_release
|
id: create_release
|
||||||
# if: contains(steps.setVersion.outputs.version,'-rc-') ||
|
|
||||||
# contains(steps.setVersion.outputs.version,'-hotfix-') ||
|
|
||||||
# contains(steps.setVersion.outputs.version, '-beta-')
|
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
with:
|
with:
|
||||||
artifacts: 'output\**\*.*(cpz|cplz)'
|
artifacts: 'output\**\*.*(cpz|cplz)'
|
||||||
|
|||||||
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@@ -37,6 +37,8 @@ jobs:
|
|||||||
run: nuget restore .\$($Env:SOLUTION_FILE).sln
|
run: nuget restore .\$($Env:SOLUTION_FILE).sln
|
||||||
- name: Build Solution
|
- name: Build Solution
|
||||||
run: msbuild .\$($Env:SOLUTION_FILE).sln /p:Platform="Any CPU" /p:Configuration="Debug" /p:Version="${{ steps.setVersion.outputs.version }}" -m
|
run: msbuild .\$($Env:SOLUTION_FILE).sln /p:Platform="Any CPU" /p:Configuration="Debug" /p:Version="${{ steps.setVersion.outputs.version }}" -m
|
||||||
|
- name: Pack Solution
|
||||||
|
run: dotnet pack .\$($Env:SOLUTION_FILE).sln --configuration $env:BUILD_TYPE --output ./output /p:Version="${{ steps.setVersion.outputs.version }}"
|
||||||
- name: Upload Release
|
- name: Upload Release
|
||||||
id: create_release
|
id: create_release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
Provided under MIT license
|
Provided under MIT license
|
||||||
|
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
PepperDash Essentials is an open source Crestron framework that can be configured as a standalone program capable of running a wide variety of system designs and can also be utilized as a plug-in architecture to augment other Simpl# Pro and Simpl Windows programs.
|
PepperDash Essentials is an open source Crestron framework that can be configured as a standalone program capable of running a wide variety of system designs and can also be utilized as a plug-in architecture to augment other Simpl# Pro and Simpl Windows programs.
|
||||||
|
|||||||
@@ -1,6 +1,19 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="$(PackageOutputPath)\$(AssemblyName)\*.cpz" Condition="$(ProjectType) == 'Program'">
|
<!-- Include CPZ files from multiple possible locations -->
|
||||||
|
<None Include="$(TargetDir)*.cpz" Condition="$(ProjectType) == 'Program'">
|
||||||
|
<Pack>true</Pack>
|
||||||
|
<PackagePath>build;</PackagePath>
|
||||||
|
</None>
|
||||||
|
<None Include="$(OutputPath)*.cpz" Condition="$(ProjectType) == 'Program'">
|
||||||
|
<Pack>true</Pack>
|
||||||
|
<PackagePath>build;</PackagePath>
|
||||||
|
</None>
|
||||||
|
<None Include="$(MSBuildProjectDirectory)\bin\$(Configuration)\**\*.cpz" Condition="$(ProjectType) == 'Program'">
|
||||||
|
<Pack>true</Pack>
|
||||||
|
<PackagePath>build;</PackagePath>
|
||||||
|
</None>
|
||||||
|
<None Include="$(PackageOutputPath)\build\*.cpz" Condition="$(ProjectType) == 'Program'">
|
||||||
<Pack>true</Pack>
|
<Pack>true</Pack>
|
||||||
<PackagePath>build;</PackagePath>
|
<PackagePath>build;</PackagePath>
|
||||||
</None>
|
</None>
|
||||||
@@ -10,17 +23,94 @@
|
|||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Target Name="Create CPLZ" AfterTargets="Build; AfterRebuild" Condition="$(ProjectType) == 'ProgramLibrary' And $(TargetDir) != ''">
|
<Target Name="Create CPLZ" AfterTargets="Build; AfterRebuild" Condition="$(ProjectType) == 'ProgramLibrary' And $(TargetDir) != ''">
|
||||||
<Message Text="Creating CPLZ $(TargetDir)"></Message>
|
<Message Text="Creating CPLZ $(TargetDir)" Importance="high" />
|
||||||
|
<Message Text="PackageOutputPath: $(PackageOutputPath)" Importance="high" />
|
||||||
|
<Message Text="AssemblyName: $(AssemblyName)" Importance="high" />
|
||||||
|
<Message Text="TargetName: $(TargetName)" Importance="high" />
|
||||||
|
<Message Text="Version: $(Version)" Importance="high" />
|
||||||
|
<Message Text="TargetFramework: $(TargetFramework)" Importance="high" />
|
||||||
<MakeDir Directories="$(PackageOutputPath)" Condition="!Exists($(PackageOutputPath))" />
|
<MakeDir Directories="$(PackageOutputPath)" Condition="!Exists($(PackageOutputPath))" />
|
||||||
<MakeDir Directories="$(PackageOutputPath)\$(AssemblyName)" Condition="!Exists('$(PackageOutputPath)\$(AssemblyName)')" />
|
<MakeDir Directories="$(PackageOutputPath)\$(AssemblyName)" Condition="!Exists('$(PackageOutputPath)\$(AssemblyName)')" />
|
||||||
<ZipDirectory SourceDirectory="$(TargetDir)" DestinationFile="$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cplz" Overwrite="true"/>
|
<ZipDirectory SourceDirectory="$(TargetDir)" DestinationFile="$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cplz" Overwrite="true"/>
|
||||||
</Target>
|
</Target>
|
||||||
<Target Name="Copy CPZ NET6" AfterTargets="SimplSharpPostProcess" Condition="($(ProjectType) == 'Program' And ( '$(TargetFramework)' == 'net6.0' ) Or ( '$(TargetFramework)' == 'net8.0' ))">
|
<Target Name="Debug Variables" BeforeTargets="Build">
|
||||||
<Message Text="Copying CPZ"></Message>
|
<Message Text="================ Debug Variables ================" Importance="high" />
|
||||||
<Move SourceFiles="$(TargetDir)$(TargetName).cpz" DestinationFiles="$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cpz" />
|
<Message Text="ProjectType: '$(ProjectType)'" Importance="high" />
|
||||||
|
<Message Text="TargetFramework: '$(TargetFramework)'" Importance="high" />
|
||||||
|
<Message Text="TargetDir: '$(TargetDir)'" Importance="high" />
|
||||||
|
<Message Text="===============================================" Importance="high" />
|
||||||
</Target>
|
</Target>
|
||||||
<Target Name="Copy CPZ NET47" AfterTargets="SimplSharpPostProcess47" Condition="($(ProjectType) == 'Program' And ( '$(TargetFramework)' != 'net6.0' ) And ( '$(TargetFramework)' != 'net8.0' ))">
|
<Target Name="Copy CPZ NET472"
|
||||||
<Message Text="Copying CPZ"></Message>
|
AfterTargets="Build"
|
||||||
<Move SourceFiles="$(TargetDir)$(TargetName).cpz" DestinationFiles="$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cpz" />
|
DependsOnTargets="BuildDependencies"
|
||||||
|
Condition="'$(ProjectType)' == 'Program' And '$(TargetFramework)' == 'net472'">
|
||||||
|
<Message Text="========================================" Importance="high" />
|
||||||
|
<Message Text="Starting CPZ Build Process for NET472" Importance="high" />
|
||||||
|
<Message Text="ProjectType: '$(ProjectType)'" Importance="high" />
|
||||||
|
<Message Text="TargetFramework: '$(TargetFramework)'" Importance="high" />
|
||||||
|
<Message Text="========================================" Importance="high" />
|
||||||
|
|
||||||
|
<!-- Create output directory -->
|
||||||
|
<MakeDir Directories="$(PackageOutputPath)\$(AssemblyName)"
|
||||||
|
Condition="!Exists('$(PackageOutputPath)\$(AssemblyName)')" />
|
||||||
|
|
||||||
|
<!-- Copy the CPZ file -->
|
||||||
|
<Copy SourceFiles="$(TargetDir)$(TargetName).cpz"
|
||||||
|
DestinationFiles="$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cpz"
|
||||||
|
Condition="Exists('$(TargetDir)$(TargetName).cpz')" />
|
||||||
|
|
||||||
|
<Message Text="CPZ Build completed for NET472"
|
||||||
|
Condition="Exists('$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cpz')"
|
||||||
|
Importance="high" />
|
||||||
|
</Target>
|
||||||
|
<Target Name="Copy CPZ NET6"
|
||||||
|
AfterTargets="Build"
|
||||||
|
DependsOnTargets="BuildDependencies"
|
||||||
|
Condition="'$(ProjectType)' == 'Program' And ('$(TargetFramework)' == 'net6.0' Or '$(TargetFramework)' == 'net8.0')">
|
||||||
|
<Message Text="========================================" Importance="high" />
|
||||||
|
<Message Text="Starting CPZ Build Process" Importance="high" />
|
||||||
|
<Message Text="ProjectType: '$(ProjectType)'" Importance="high" />
|
||||||
|
<Message Text="TargetFramework: '$(TargetFramework)'" Importance="high" />
|
||||||
|
<Message Text="MSBuildProjectDirectory: '$(MSBuildProjectDirectory)'" Importance="high" />
|
||||||
|
<Message Text="PATH: '$(PATH)'" Importance="high" />
|
||||||
|
<Message Text="========================================" Importance="high" />
|
||||||
|
|
||||||
|
<!-- Check for SimplSharp compiler -->
|
||||||
|
<PropertyGroup>
|
||||||
|
<SimplSharpCompilerPath>$(HOME)/.crestron/SimplSharpPro/SimplSharpCompiler</SimplSharpCompilerPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Warning Text="SimplSharpCompiler not found at: $(SimplSharpCompilerPath)"
|
||||||
|
Condition="!Exists('$(SimplSharpCompilerPath)')" />
|
||||||
|
|
||||||
|
<!-- Run the SimplSharp compiler to create CPZ -->
|
||||||
|
<Exec Command=""$(SimplSharpCompilerPath)" "$(MSBuildProjectDirectory)" "$(TargetDir)""
|
||||||
|
IgnoreExitCode="false"
|
||||||
|
WorkingDirectory="$(MSBuildProjectDirectory)"
|
||||||
|
ConsoleToMSBuild="true"
|
||||||
|
Condition="Exists('$(SimplSharpCompilerPath)')">
|
||||||
|
<Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" />
|
||||||
|
</Exec>
|
||||||
|
|
||||||
|
<Message Text="SimplSharp Output: $(OutputOfExec)" Importance="high" />
|
||||||
|
|
||||||
|
<!-- Create output directory -->
|
||||||
|
<MakeDir Directories="$(PackageOutputPath)\$(AssemblyName)"
|
||||||
|
Condition="!Exists('$(PackageOutputPath)\$(AssemblyName)')" />
|
||||||
|
|
||||||
|
<!-- Copy the CPZ file -->
|
||||||
|
<Copy SourceFiles="$(TargetDir)$(TargetName).cpz"
|
||||||
|
DestinationFiles="$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cpz"
|
||||||
|
Condition="Exists('$(TargetDir)$(TargetName).cpz')" />
|
||||||
|
|
||||||
|
<Message Text="CPZ Build completed"
|
||||||
|
Condition="Exists('$(PackageOutputPath)\$(AssemblyName)\$(TargetName).$(Version).$(TargetFramework).cpz')"
|
||||||
|
Importance="high" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="BuildDependencies">
|
||||||
|
<MSBuild Projects="@(ProjectReference)"
|
||||||
|
Targets="Build"
|
||||||
|
BuildInParallel="true" />
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -18,81 +18,6 @@ using Serilog.Events;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core.Bridges
|
namespace PepperDash.Essentials.Core.Bridges
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Helper methods for bridges
|
|
||||||
/// </summary>
|
|
||||||
public static class BridgeHelper
|
|
||||||
{
|
|
||||||
public static void PrintJoinMap(string command)
|
|
||||||
{
|
|
||||||
var targets = command.Split(' ');
|
|
||||||
|
|
||||||
var bridgeKey = targets[0].Trim();
|
|
||||||
|
|
||||||
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 (targets.Length > 1)
|
|
||||||
{
|
|
||||||
var deviceKey = targets[1].Trim();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(deviceKey)) return;
|
|
||||||
bridge.PrintJoinMapForDevice(deviceKey);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bridge.PrintJoinMaps();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static void JoinmapMarkdown(string command)
|
|
||||||
{
|
|
||||||
var targets = command.Split(' ');
|
|
||||||
|
|
||||||
var bridgeKey = targets[0].Trim();
|
|
||||||
|
|
||||||
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 (targets.Length > 1)
|
|
||||||
{
|
|
||||||
var deviceKey = targets[1].Trim();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(deviceKey)) return;
|
|
||||||
bridge.MarkdownJoinMapForDevice(deviceKey, bridgeKey);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bridge.MarkdownForBridge(bridgeKey);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Base class for all bridge class variants
|
|
||||||
/// </summary>
|
|
||||||
public class BridgeBase : EssentialsDevice
|
|
||||||
{
|
|
||||||
public BridgeApi Api { get; protected set; }
|
|
||||||
|
|
||||||
public BridgeBase(string key) :
|
|
||||||
base(key)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base class for bridge API variants
|
/// Base class for bridge API variants
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -168,19 +93,15 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Linking Device: '{0}'", device.Key);
|
Debug.LogMessage(LogEventLevel.Debug, this, "Linking Device: '{0}'", device.Key);
|
||||||
|
|
||||||
if (!typeof(IBridgeAdvanced).IsAssignableFrom(device.GetType().GetType()))
|
if (device is IBridgeAdvanced bridge)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, this,
|
bridge.LinkToApi(Eisc, d.JoinStart, d.JoinMapKey, this);
|
||||||
"{0} is not compatible with this bridge type. Please use 'eiscapi' instead, or updae the device.",
|
|
||||||
device.Key);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var bridge = device as IBridgeAdvanced;
|
Debug.LogMessage(LogEventLevel.Information, this,
|
||||||
if (bridge != null)
|
"{0} is not compatible with this bridge type. Please use 'eiscapi' instead, or updae the device.",
|
||||||
{
|
device.Key);
|
||||||
bridge.LinkToApi(Eisc, d.JoinStart, d.JoinMapKey, this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,11 +170,11 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void PrintJoinMaps()
|
public virtual void PrintJoinMaps()
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Join Maps for EISC IPID: {0}", Eisc.ID.ToString("X"));
|
CrestronConsole.ConsoleCommandResponse("Join Maps for EISC IPID: {0}\r\n", Eisc.ID.ToString("X"));
|
||||||
|
|
||||||
foreach (var joinMap in JoinMaps)
|
foreach (var joinMap in JoinMaps)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Join map for device '{0}':", joinMap.Key);
|
CrestronConsole.ConsoleCommandResponse("Join map for device '{0}':", joinMap.Key);
|
||||||
joinMap.Value.PrintJoinMapInfo();
|
joinMap.Value.PrintJoinMapInfo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
66
src/PepperDash.Essentials.Core/Bridges/BridgeHelper.cs
Normal file
66
src/PepperDash.Essentials.Core/Bridges/BridgeHelper.cs
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
using PepperDash.Core;
|
||||||
|
using Serilog.Events;
|
||||||
|
|
||||||
|
//using PepperDash.Essentials.Devices.Common.Cameras;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.Bridges
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Helper methods for bridges
|
||||||
|
/// </summary>
|
||||||
|
public static class BridgeHelper
|
||||||
|
{
|
||||||
|
public static void PrintJoinMap(string command)
|
||||||
|
{
|
||||||
|
var targets = command.Split(' ');
|
||||||
|
|
||||||
|
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 (targets.Length > 1)
|
||||||
|
{
|
||||||
|
var deviceKey = targets[1].Trim();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(deviceKey)) return;
|
||||||
|
bridge.PrintJoinMapForDevice(deviceKey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bridge.PrintJoinMaps();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void JoinmapMarkdown(string command)
|
||||||
|
{
|
||||||
|
var targets = command.Split(' ');
|
||||||
|
|
||||||
|
var bridgeKey = targets[0].Trim();
|
||||||
|
|
||||||
|
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 (targets.Length > 1)
|
||||||
|
{
|
||||||
|
var deviceKey = targets[1].Trim();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(deviceKey)) return;
|
||||||
|
bridge.MarkdownJoinMapForDevice(deviceKey, bridgeKey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bridge.MarkdownForBridge(bridgeKey);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -93,6 +93,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
void OnDataReceived(string s)
|
void OnDataReceived(string s)
|
||||||
{
|
{
|
||||||
|
var eventSubscribed = false;
|
||||||
|
|
||||||
var bytesHandler = BytesReceived;
|
var bytesHandler = BytesReceived;
|
||||||
if (bytesHandler != null)
|
if (bytesHandler != null)
|
||||||
@@ -101,7 +102,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
if (StreamDebugging.RxStreamDebuggingIsEnabled)
|
if (StreamDebugging.RxStreamDebuggingIsEnabled)
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", ComTextHelper.GetEscapedText(bytes));
|
Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", ComTextHelper.GetEscapedText(bytes));
|
||||||
bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes));
|
bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes));
|
||||||
return;
|
eventSubscribed = true;
|
||||||
}
|
}
|
||||||
var textHandler = TextReceived;
|
var textHandler = TextReceived;
|
||||||
if (textHandler != null)
|
if (textHandler != null)
|
||||||
@@ -109,10 +110,10 @@ namespace PepperDash.Essentials.Core
|
|||||||
if (StreamDebugging.RxStreamDebuggingIsEnabled)
|
if (StreamDebugging.RxStreamDebuggingIsEnabled)
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", s);
|
Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", s);
|
||||||
textHandler(this, new GenericCommMethodReceiveTextArgs(s));
|
textHandler(this, new GenericCommMethodReceiveTextArgs(s));
|
||||||
return;
|
eventSubscribed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Warning, this, "Received data but no handler is registered");
|
if(!eventSubscribed) Debug.LogMessage(LogEventLevel.Warning, this, "Received data but no handler is registered");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Deactivate()
|
public override bool Deactivate()
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace PepperDash.Essentials.Core.Config
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Dictionary<string, SourceListItem> GetSourceListForKey(string key)
|
public Dictionary<string, SourceListItem> GetSourceListForKey(string key)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(key) || !SourceLists.ContainsKey(key))
|
if (SourceLists == null || string.IsNullOrEmpty(key) || !SourceLists.ContainsKey(key))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return SourceLists[key];
|
return SourceLists[key];
|
||||||
@@ -68,7 +68,7 @@ namespace PepperDash.Essentials.Core.Config
|
|||||||
/// <returns>DestinationList if the key exists, null otherwise</returns>
|
/// <returns>DestinationList if the key exists, null otherwise</returns>
|
||||||
public Dictionary<string, DestinationListItem> GetDestinationListForKey(string key)
|
public Dictionary<string, DestinationListItem> GetDestinationListForKey(string key)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(key) || !DestinationLists.ContainsKey(key))
|
if (DestinationLists == null || string.IsNullOrEmpty(key) || !DestinationLists.ContainsKey(key))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ namespace PepperDash.Essentials.Core.Config
|
|||||||
/// <returns>AudioControlPointList if the key exists, null otherwise</returns>
|
/// <returns>AudioControlPointList if the key exists, null otherwise</returns>
|
||||||
public AudioControlPointListItem GetAudioControlPointListForKey(string key)
|
public AudioControlPointListItem GetAudioControlPointListForKey(string key)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(key) || !AudioControlPointLists.ContainsKey(key))
|
if (AudioControlPointLists == null || string.IsNullOrEmpty(key) || !AudioControlPointLists.ContainsKey(key))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return AudioControlPointLists[key];
|
return AudioControlPointLists[key];
|
||||||
@@ -94,7 +94,7 @@ namespace PepperDash.Essentials.Core.Config
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Dictionary<string, CameraListItem> GetCameraListForKey(string key)
|
public Dictionary<string, CameraListItem> GetCameraListForKey(string key)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(key) || !CameraLists.ContainsKey(key))
|
if (CameraLists == null || string.IsNullOrEmpty(key) || !CameraLists.ContainsKey(key))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return CameraLists[key];
|
return CameraLists[key];
|
||||||
|
|||||||
@@ -31,9 +31,17 @@ namespace PepperDash.Essentials.Core.Config
|
|||||||
if (string.IsNullOrEmpty(SystemUrl))
|
if (string.IsNullOrEmpty(SystemUrl))
|
||||||
return "missing url";
|
return "missing url";
|
||||||
|
|
||||||
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/#.*");
|
if (SystemUrl.Contains("#"))
|
||||||
string uuid = result.Groups[1].Value;
|
{
|
||||||
return uuid;
|
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/#.*");
|
||||||
|
string uuid = result.Groups[1].Value;
|
||||||
|
return uuid;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/.*");
|
||||||
|
string uuid = result.Groups[1].Value;
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,9 +53,17 @@ namespace PepperDash.Essentials.Core.Config
|
|||||||
if (string.IsNullOrEmpty(TemplateUrl))
|
if (string.IsNullOrEmpty(TemplateUrl))
|
||||||
return "missing template url";
|
return "missing template url";
|
||||||
|
|
||||||
var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/templates\/(.*)\/#.*");
|
if (TemplateUrl.Contains("#"))
|
||||||
string uuid = result.Groups[1].Value;
|
{
|
||||||
return uuid;
|
var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/templates\/(.*)\/#.*");
|
||||||
|
string uuid = result.Groups[1].Value;
|
||||||
|
return uuid;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/system-templates\/(.*)\/system-template-versions\/(.*)\/.*");
|
||||||
|
string uuid = result.Groups[2].Value;
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a generic digital input deviced tied to a versiport
|
/// Represents a generic digital input deviced tied to a versiport
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GenericVersiportDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput
|
public class GenericVersiportDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput, IPartitionStateProvider
|
||||||
{
|
{
|
||||||
public Versiport InputPort { get; private set; }
|
public Versiport InputPort { get; private set; }
|
||||||
|
|
||||||
@@ -35,10 +35,15 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BoolFeedback PartitionPresentFeedback { get; }
|
||||||
|
|
||||||
|
public bool PartitionPresent => !InputStateFeedbackFunc();
|
||||||
|
|
||||||
public GenericVersiportDigitalInputDevice(string key, string name, Func<IOPortConfig, Versiport> postActivationFunc, IOPortConfig config) :
|
public GenericVersiportDigitalInputDevice(string key, string name, Func<IOPortConfig, Versiport> postActivationFunc, IOPortConfig config) :
|
||||||
base(key, name)
|
base(key, name)
|
||||||
{
|
{
|
||||||
InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc);
|
InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc);
|
||||||
|
PartitionPresentFeedback = new BoolFeedback(() => !InputStateFeedbackFunc());
|
||||||
|
|
||||||
AddPostActivationAction(() =>
|
AddPostActivationAction(() =>
|
||||||
{
|
{
|
||||||
@@ -52,7 +57,8 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
|
|
||||||
InputPort.VersiportChange += InputPort_VersiportChange;
|
InputPort.VersiportChange += InputPort_VersiportChange;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
@@ -65,7 +71,10 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Versiport change: {0}", args.Event);
|
Debug.LogMessage(LogEventLevel.Debug, this, "Versiport change: {0}", args.Event);
|
||||||
|
|
||||||
if(args.Event == eVersiportEvent.DigitalInChange)
|
if(args.Event == eVersiportEvent.DigitalInChange)
|
||||||
|
{
|
||||||
InputStateFeedback.FireUpdate();
|
InputStateFeedback.FireUpdate();
|
||||||
|
PartitionPresentFeedback.FireUpdate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||||
|
{
|
||||||
|
public interface IEmergencyOSD
|
||||||
|
{
|
||||||
|
void ShowEmergencyMessage(string url);
|
||||||
|
void HideEmergencyMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||||
|
{
|
||||||
|
public interface IHumiditySensor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Reports the relative humidity level. Level ranging from 0 to 100 (for 0% to 100%
|
||||||
|
/// RH). EventIds: HumidityFeedbackFeedbackEventId will trigger to indicate change.
|
||||||
|
/// </summary>
|
||||||
|
IntFeedback HumidityFeedback { get; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||||
|
{
|
||||||
|
public interface ITemperatureSensor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
IntFeedback TemperatureFeedback { get; }
|
||||||
|
|
||||||
|
|
||||||
|
BoolFeedback TemperatureInCFeedback { get; }
|
||||||
|
|
||||||
|
void SetTemperatureFormat(bool setToC);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,9 +9,15 @@ namespace PepperDash.Essentials.Core
|
|||||||
{
|
{
|
||||||
public abstract class AudioControlListItemBase
|
public abstract class AudioControlListItemBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Key of the parent device in the DeviceManager
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("parentDeviceKey")]
|
[JsonProperty("parentDeviceKey")]
|
||||||
public string ParentDeviceKey { get; set; }
|
public string ParentDeviceKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional key of the item in the parent device
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("itemKey")]
|
[JsonProperty("itemKey")]
|
||||||
public string ItemKey { get; set; }
|
public string ItemKey { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,83 +1,78 @@
|
|||||||
|
using Crestron.SimplSharp;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using PepperDash.Core;
|
||||||
|
using Serilog.Events;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Newtonsoft.Json;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using PepperDash.Core;
|
|
||||||
using Serilog.Events;
|
|
||||||
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
public class DeviceJsonApi
|
public class DeviceJsonApi
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="json"></param>
|
/// <param name="json"></param>
|
||||||
public static void DoDeviceActionWithJson(string json)
|
public static void DoDeviceActionWithJson(string json)
|
||||||
{
|
{
|
||||||
if (String.IsNullOrEmpty(json))
|
if (String.IsNullOrEmpty(json))
|
||||||
{
|
{
|
||||||
CrestronConsole.ConsoleCommandResponse(
|
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.");
|
"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;
|
return;
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var action = JsonConvert.DeserializeObject<DeviceActionWrapper>(json);
|
var action = JsonConvert.DeserializeObject<DeviceActionWrapper>(json);
|
||||||
|
|
||||||
DoDeviceAction(action);
|
DoDeviceAction(action);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
CrestronConsole.ConsoleCommandResponse("Incorrect format for JSON. Please check that the format matches {\"deviceKey\":\"myDevice\", \"methodName\":\"someMethod\", \"params\": [\"param1\", true]}");
|
CrestronConsole.ConsoleCommandResponse("Incorrect format for JSON. Please check that the format matches {\"deviceKey\":\"myDevice\", \"methodName\":\"someMethod\", \"params\": [\"param1\", true]}");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="action"></param>
|
/// <param name="action"></param>
|
||||||
public static void DoDeviceAction(DeviceActionWrapper action)
|
public static void DoDeviceAction(DeviceActionWrapper action)
|
||||||
{
|
{
|
||||||
var key = action.DeviceKey;
|
var key = action.DeviceKey;
|
||||||
var obj = FindObjectOnPath(key);
|
var obj = FindObjectOnPath(key);
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
{
|
{
|
||||||
CrestronConsole.ConsoleCommandResponse("Unable to find object at path {0}", key);
|
CrestronConsole.ConsoleCommandResponse("Unable to find object at path {0}", key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.Params == null)
|
if (action.Params == null)
|
||||||
{
|
{
|
||||||
//no params, so setting action.Params to empty array
|
//no params, so setting action.Params to empty array
|
||||||
action.Params = new object[0];
|
action.Params = new object[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
Type t = obj.GetType();
|
Type t = obj.GetType();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var methods = t.GetMethods().Where(m => m.Name == action.MethodName).ToList();
|
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);
|
var method = methods.Count == 1 ? methods[0] : methods.FirstOrDefault(m => m.GetParameters().Length == action.Params.Length);
|
||||||
|
|
||||||
if (method == null)
|
if (method == null)
|
||||||
{
|
{
|
||||||
CrestronConsole.ConsoleCommandResponse(
|
CrestronConsole.ConsoleCommandResponse(
|
||||||
"Unable to find method with name {0} and that matches parameters {1}", action.MethodName,
|
"Unable to find method with name {0} and that matches parameters {1}", action.MethodName,
|
||||||
action.Params);
|
action.Params);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var mParams = method.GetParameters();
|
var mParams = method.GetParameters();
|
||||||
|
|
||||||
var convertedParams = mParams
|
var convertedParams = mParams
|
||||||
@@ -85,60 +80,124 @@ namespace PepperDash.Essentials.Core
|
|||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "Calling method {methodName} on device {deviceKey}", null, method.Name, action.DeviceKey);
|
Debug.LogMessage(LogEventLevel.Verbose, "Calling method {methodName} on device {deviceKey}", null, method.Name, action.DeviceKey);
|
||||||
method.Invoke(obj, convertedParams);
|
method.Invoke(obj, convertedParams);
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(e, "Error invoking method {methodName} on device {deviceKey}", null, method.Name, action.DeviceKey);
|
Debug.LogMessage(e, "Error invoking method {methodName} on device {deviceKey}", null, method.Name, action.DeviceKey);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
CrestronConsole.ConsoleCommandResponse("Method {0} successfully called on device {1}", method.Name,
|
CrestronConsole.ConsoleCommandResponse("Method {0} successfully called on device {1}", method.Name,
|
||||||
action.DeviceKey);
|
action.DeviceKey);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
CrestronConsole.ConsoleCommandResponse("Unable to call method with name {0}. {1}", action.MethodName,
|
CrestronConsole.ConsoleCommandResponse("Unable to call method with name {0}. {1}", action.MethodName,
|
||||||
ex.Message);}
|
ex.Message);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static object ConvertType(object value, Type conversionType)
|
public static async Task DoDeviceActionAsync(DeviceActionWrapper action)
|
||||||
{
|
{
|
||||||
if (!conversionType.IsEnum)
|
var key = action.DeviceKey;
|
||||||
{
|
var obj = FindObjectOnPath(key);
|
||||||
return Convert.ChangeType(value, conversionType, System.Globalization.CultureInfo.InvariantCulture);
|
if (obj == null)
|
||||||
}
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Warning, "Unable to find object at path {deviceKey}", null, key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var stringValue = Convert.ToString(value);
|
if (action.Params == null)
|
||||||
|
{
|
||||||
|
//no params, so setting action.Params to empty array
|
||||||
|
action.Params = new object[0];
|
||||||
|
}
|
||||||
|
|
||||||
if (String.IsNullOrEmpty(stringValue))
|
Type t = obj.GetType();
|
||||||
{
|
try
|
||||||
throw new InvalidCastException(
|
{
|
||||||
String.Format("{0} cannot be converted to a string prior to conversion to enum"));
|
var methods = t.GetMethods().Where(m => m.Name == action.MethodName).ToList();
|
||||||
}
|
|
||||||
return Enum.Parse(conversionType, stringValue, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
var method = methods.Count == 1 ? methods[0] : methods.FirstOrDefault(m => m.GetParameters().Length == action.Params.Length);
|
||||||
/// Gets the properties on a device
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static string GetProperties(string deviceObjectPath)
|
|
||||||
{
|
|
||||||
var obj = FindObjectOnPath(deviceObjectPath);
|
|
||||||
if (obj == null)
|
|
||||||
return "{ \"error\":\"No Device\"}";
|
|
||||||
|
|
||||||
Type t = obj.GetType();
|
if (method == null)
|
||||||
// get the properties and set them into a new collection of NameType wrappers
|
{
|
||||||
var props = t.GetProperties().Select(p => new PropertyNameType(p, obj));
|
Debug.LogMessage(LogEventLevel.Warning,
|
||||||
return JsonConvert.SerializeObject(props, Formatting.Indented);
|
"Unable to find method with name {methodName} and that matches parameters {@parameters}", null, action.MethodName,
|
||||||
}
|
action.Params);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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<T>, await it
|
||||||
|
else if (result != null && result.GetType().IsGenericType && result.GetType().GetGenericTypeDefinition() == typeof(Task<>))
|
||||||
|
{
|
||||||
|
await (Task)result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(e, "Error invoking method {methodName} on device {deviceKey}", null, method.Name, action.DeviceKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(ex, "Unable to call method with name {methodName} with {@parameters}", null, action.MethodName, action.Params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object ConvertType(object value, Type conversionType)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the properties on a device
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a property from a device path by name
|
/// Gets a property from a device path by name
|
||||||
@@ -149,10 +208,10 @@ namespace PepperDash.Essentials.Core
|
|||||||
public static object GetPropertyByName(string deviceObjectPath, string propertyName)
|
public static object GetPropertyByName(string deviceObjectPath, string propertyName)
|
||||||
{
|
{
|
||||||
var dev = FindObjectOnPath(deviceObjectPath);
|
var dev = FindObjectOnPath(deviceObjectPath);
|
||||||
if(dev == null)
|
if (dev == null)
|
||||||
return "{ \"error\":\"No Device\"}";
|
return "{ \"error\":\"No Device\"}";
|
||||||
|
|
||||||
object prop = dev.GetType().GetType().GetProperty(propertyName).GetValue(dev, null);
|
object prop = dev.GetType().GetProperty(propertyName).GetValue(dev, null);
|
||||||
|
|
||||||
// var prop = t.GetProperty(propertyName);
|
// var prop = t.GetProperty(propertyName);
|
||||||
if (prop != null)
|
if (prop != null)
|
||||||
@@ -166,126 +225,126 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the methods on a device
|
/// Gets the methods on a device
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key"></param>
|
/// <param name="key"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string GetMethods(string deviceObjectPath)
|
public static string GetMethods(string deviceObjectPath)
|
||||||
{
|
{
|
||||||
var obj = FindObjectOnPath(deviceObjectPath);
|
var obj = FindObjectOnPath(deviceObjectPath);
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
return "{ \"error\":\"No Device\"}";
|
return "{ \"error\":\"No Device\"}";
|
||||||
|
|
||||||
// Package up method names using helper objects
|
// Package up method names using helper objects
|
||||||
Type t = obj.GetType();
|
Type t = obj.GetType();
|
||||||
var methods = t.GetMethods()
|
var methods = t.GetMethods()
|
||||||
.Where(m => !m.IsSpecialName)
|
.Where(m => !m.IsSpecialName)
|
||||||
.Select(p => new MethodNameParams(p));
|
.Select(p => new MethodNameParams(p));
|
||||||
return JsonConvert.SerializeObject(methods, Formatting.Indented);
|
return JsonConvert.SerializeObject(methods, Formatting.Indented);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetApiMethods(string deviceObjectPath)
|
public static string GetApiMethods(string deviceObjectPath)
|
||||||
{
|
{
|
||||||
var obj = FindObjectOnPath(deviceObjectPath);
|
var obj = FindObjectOnPath(deviceObjectPath);
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
return "{ \"error\":\"No Device\"}";
|
return "{ \"error\":\"No Device\"}";
|
||||||
|
|
||||||
// Package up method names using helper objects
|
// Package up method names using helper objects
|
||||||
Type t = obj.GetType();
|
Type t = obj.GetType();
|
||||||
var methods = t.GetMethods()
|
var methods = t.GetMethods()
|
||||||
.Where(m => !m.IsSpecialName)
|
.Where(m => !m.IsSpecialName)
|
||||||
.Where(m => m.GetCustomAttributes(typeof(ApiAttribute), true).Any())
|
.Where(m => m.GetCustomAttributes(typeof(ApiAttribute), true).Any())
|
||||||
.Select(p => new MethodNameParams(p));
|
.Select(p => new MethodNameParams(p));
|
||||||
return JsonConvert.SerializeObject(methods, Formatting.Indented);
|
return JsonConvert.SerializeObject(methods, Formatting.Indented);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Walks down a dotted object path, starting with a Device, and returns the object
|
/// Walks down a dotted object path, starting with a Device, and returns the object
|
||||||
/// at the end of the path
|
/// at the end of the path
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static object FindObjectOnPath(string deviceObjectPath)
|
public static object FindObjectOnPath(string deviceObjectPath)
|
||||||
{
|
{
|
||||||
var path = deviceObjectPath.Split('.');
|
var path = deviceObjectPath.Split('.');
|
||||||
|
|
||||||
var dev = DeviceManager.GetDeviceForKey(path[0]);
|
var dev = DeviceManager.GetDeviceForKey(path[0]);
|
||||||
if (dev == null)
|
if (dev == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Device {0} not found", path[0]);
|
Debug.LogMessage(LogEventLevel.Information, "Device {0} not found", path[0]);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop through any dotted properties
|
// loop through any dotted properties
|
||||||
object obj = dev;
|
object obj = dev;
|
||||||
if (path.Length > 1)
|
if (path.Length > 1)
|
||||||
{
|
{
|
||||||
for (int i = 1; i < path.Length; i++)
|
for (int i = 1; i < path.Length; i++)
|
||||||
{
|
{
|
||||||
var objName = path[i];
|
var objName = path[i];
|
||||||
string indexStr = null;
|
string indexStr = null;
|
||||||
var indexOpen = objName.IndexOf('[');
|
var indexOpen = objName.IndexOf('[');
|
||||||
if (indexOpen != -1)
|
if (indexOpen != -1)
|
||||||
{
|
{
|
||||||
var indexClose = objName.IndexOf(']');
|
var indexClose = objName.IndexOf(']');
|
||||||
if (indexClose == -1)
|
if (indexClose == -1)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, dev, "ERROR Unmatched index brackets");
|
Debug.LogMessage(LogEventLevel.Information, dev, "ERROR Unmatched index brackets");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Get the index and strip quotes if any
|
// Get the index and strip quotes if any
|
||||||
indexStr = objName.Substring(indexOpen + 1, indexClose - indexOpen - 1).Replace("\"", "");
|
indexStr = objName.Substring(indexOpen + 1, indexClose - indexOpen - 1).Replace("\"", "");
|
||||||
objName = objName.Substring(0, indexOpen);
|
objName = objName.Substring(0, indexOpen);
|
||||||
Debug.LogMessage(LogEventLevel.Information, dev, " Checking for collection '{0}', index '{1}'", objName, indexStr);
|
Debug.LogMessage(LogEventLevel.Information, dev, " Checking for collection '{0}', index '{1}'", objName, indexStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Type oType = obj.GetType();
|
Type oType = obj.GetType();
|
||||||
var prop = oType.GetProperty(objName);
|
var prop = oType.GetProperty(objName);
|
||||||
if (prop == null)
|
if (prop == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, dev, "Property {0} not found on {1}", objName, path[i - 1]);
|
Debug.LogMessage(LogEventLevel.Information, dev, "Property {0} not found on {1}", objName, path[i - 1]);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// if there's an index, try to get the property
|
// if there's an index, try to get the property
|
||||||
if (indexStr != null)
|
if (indexStr != null)
|
||||||
{
|
{
|
||||||
if (!typeof(ICollection).IsAssignableFrom(prop.PropertyType))
|
if (!typeof(ICollection).IsAssignableFrom(prop.PropertyType))
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, dev, "Property {0} is not collection", objName);
|
Debug.LogMessage(LogEventLevel.Information, dev, "Property {0} is not collection", objName);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var collection = prop.GetValue(obj, null) as ICollection;
|
var collection = prop.GetValue(obj, null) as ICollection;
|
||||||
// Get the indexed items "property"
|
// Get the indexed items "property"
|
||||||
var indexedPropInfo = prop.PropertyType.GetProperty("Item");
|
var indexedPropInfo = prop.PropertyType.GetProperty("Item");
|
||||||
// These are the parameters for the indexing. Only care about one
|
// These are the parameters for the indexing. Only care about one
|
||||||
var indexParams = indexedPropInfo.GetIndexParameters();
|
var indexParams = indexedPropInfo.GetIndexParameters();
|
||||||
if (indexParams.Length > 0)
|
if (indexParams.Length > 0)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, " Indexed, param type: {0}", indexParams[0].ParameterType.Name);
|
Debug.LogMessage(LogEventLevel.Information, " Indexed, param type: {0}", indexParams[0].ParameterType.Name);
|
||||||
var properParam = Convert.ChangeType(indexStr, indexParams[0].ParameterType,
|
var properParam = Convert.ChangeType(indexStr, indexParams[0].ParameterType,
|
||||||
System.Globalization.CultureInfo.InvariantCulture);
|
System.Globalization.CultureInfo.InvariantCulture);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
obj = indexedPropInfo.GetValue(collection, new object[] { properParam });
|
obj = indexedPropInfo.GetValue(collection, new object[] { properParam });
|
||||||
}
|
}
|
||||||
// if the index is bad, catch it here.
|
// if the index is bad, catch it here.
|
||||||
catch (TargetInvocationException e)
|
catch (TargetInvocationException e)
|
||||||
{
|
{
|
||||||
if (e.InnerException is ArgumentOutOfRangeException)
|
if (e.InnerException is ArgumentOutOfRangeException)
|
||||||
Debug.LogMessage(LogEventLevel.Information, " Index Out of range");
|
Debug.LogMessage(LogEventLevel.Information, " Index Out of range");
|
||||||
else if (e.InnerException is KeyNotFoundException)
|
else if (e.InnerException is KeyNotFoundException)
|
||||||
Debug.LogMessage(LogEventLevel.Information, " Key not found");
|
Debug.LogMessage(LogEventLevel.Information, " Key not found");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
obj = prop.GetValue(obj, null);
|
obj = prop.GetValue(obj, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets a property on an object.
|
/// Sets a property on an object.
|
||||||
@@ -309,77 +368,84 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DeviceActionWrapper
|
public class DeviceActionWrapper
|
||||||
{
|
{
|
||||||
public string DeviceKey { get; set; }
|
public string DeviceKey { get; set; }
|
||||||
public string MethodName { get; set; }
|
public string MethodName { get; set; }
|
||||||
public object[] Params { get; set; }
|
public object[] Params { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropertyNameType
|
public class PropertyNameType
|
||||||
{
|
{
|
||||||
object Parent;
|
private object Parent;
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public PropertyInfo PropInfo { get; private set; }
|
public PropertyInfo PropInfo { get; private set; }
|
||||||
public string Name { get { return PropInfo.Name; } }
|
public string Name { get { return PropInfo.Name; } }
|
||||||
public string Type { get { return PropInfo.PropertyType.Name; } }
|
public string Type { get { return PropInfo.PropertyType.Name; } }
|
||||||
public string Value { get
|
public string Value
|
||||||
{
|
{
|
||||||
if (PropInfo.CanRead)
|
get
|
||||||
{
|
{
|
||||||
try
|
if (PropInfo.CanRead)
|
||||||
{
|
{
|
||||||
return PropInfo.GetValue(Parent, null).ToString();
|
try
|
||||||
|
{
|
||||||
|
return PropInfo.GetValue(Parent, null).ToString();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception)
|
else
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
return null;
|
|
||||||
} }
|
|
||||||
|
|
||||||
public bool CanRead { get { return PropInfo.CanRead; } }
|
public bool CanRead { get { return PropInfo.CanRead; } }
|
||||||
public bool CanWrite { get { return PropInfo.CanWrite; } }
|
public bool CanWrite { get { return PropInfo.CanWrite; } }
|
||||||
|
|
||||||
|
|
||||||
public PropertyNameType(PropertyInfo info, object parent)
|
public PropertyNameType(PropertyInfo info, object parent)
|
||||||
{
|
{
|
||||||
PropInfo = info;
|
PropInfo = info;
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MethodNameParams
|
public class MethodNameParams
|
||||||
{
|
{
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public MethodInfo MethodInfo { get; private set; }
|
public MethodInfo MethodInfo { get; private set; }
|
||||||
|
|
||||||
public string Name { get { return MethodInfo.Name; } }
|
public string Name { get { return MethodInfo.Name; } }
|
||||||
public IEnumerable<NameType> Params { get {
|
public IEnumerable<NameType> Params
|
||||||
return MethodInfo.GetParameters().Select(p =>
|
{
|
||||||
new NameType { Name = p.Name, Type = p.ParameterType.Name });
|
get
|
||||||
} }
|
{
|
||||||
|
return MethodInfo.GetParameters().Select(p =>
|
||||||
|
new NameType { Name = p.Name, Type = p.ParameterType.Name });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public MethodNameParams(MethodInfo info)
|
public MethodNameParams(MethodInfo info)
|
||||||
{
|
{
|
||||||
MethodInfo = info;
|
MethodInfo = info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NameType
|
public class NameType
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.All)]
|
[AttributeUsage(AttributeTargets.All)]
|
||||||
public class ApiAttribute : Attribute
|
public class ApiAttribute : Attribute
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,50 +1,50 @@
|
|||||||
using System;
|
using Crestron.SimplSharp;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using Crestron.SimplSharpPro;
|
using Crestron.SimplSharpPro;
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
public static class DeviceManager
|
public static class DeviceManager
|
||||||
{
|
{
|
||||||
public static event EventHandler<EventArgs> AllDevicesActivated;
|
public static event EventHandler<EventArgs> AllDevicesActivated;
|
||||||
public static event EventHandler<EventArgs> AllDevicesRegistered;
|
public static event EventHandler<EventArgs> AllDevicesRegistered;
|
||||||
|
public static event EventHandler<EventArgs> AllDevicesInitialized;
|
||||||
|
|
||||||
private static readonly CCriticalSection DeviceCriticalSection = new CCriticalSection();
|
private static readonly CCriticalSection DeviceCriticalSection = new CCriticalSection();
|
||||||
private static readonly CEvent AllowAddDevicesCEvent = new CEvent(false, true);
|
private static readonly CEvent AllowAddDevicesCEvent = new CEvent(false, true);
|
||||||
//public static List<Device> Devices { get { return _Devices; } }
|
|
||||||
//static List<Device> _Devices = new List<Device>();
|
|
||||||
|
|
||||||
static readonly Dictionary<string, IKeyed> Devices = new Dictionary<string, IKeyed>(StringComparer.OrdinalIgnoreCase);
|
//public static List<Device> Devices { get { return _Devices; } }
|
||||||
|
//static List<Device> _Devices = new List<Device>();
|
||||||
|
|
||||||
/// <summary>
|
private static readonly Dictionary<string, IKeyed> Devices = new Dictionary<string, IKeyed>(StringComparer.OrdinalIgnoreCase);
|
||||||
/// Returns a copy of all the devices in a list
|
|
||||||
/// </summary>
|
|
||||||
public static List<IKeyed> AllDevices { get { return new List<IKeyed>(Devices.Values); } }
|
|
||||||
|
|
||||||
public static bool AddDeviceEnabled;
|
/// <summary>
|
||||||
|
/// Returns a copy of all the devices in a list
|
||||||
|
/// </summary>
|
||||||
|
public static List<IKeyed> AllDevices { get { return new List<IKeyed>(Devices.Values); } }
|
||||||
|
|
||||||
public static void Initialize(CrestronControlSystem cs)
|
public static bool AddDeviceEnabled;
|
||||||
{
|
|
||||||
AddDeviceEnabled = true;
|
public static void Initialize(CrestronControlSystem cs)
|
||||||
CrestronConsole.AddNewConsoleCommand(ListDeviceCommStatuses, "devcommstatus", "Lists the communication status of all devices",
|
{
|
||||||
ConsoleAccessLevelEnum.AccessOperator);
|
AddDeviceEnabled = true;
|
||||||
CrestronConsole.AddNewConsoleCommand(ListDeviceFeedbacks, "devfb", "Lists current feedbacks",
|
CrestronConsole.AddNewConsoleCommand(ListDeviceCommStatuses, "devcommstatus", "Lists the communication status of all devices",
|
||||||
ConsoleAccessLevelEnum.AccessOperator);
|
ConsoleAccessLevelEnum.AccessOperator);
|
||||||
CrestronConsole.AddNewConsoleCommand(ListDevices, "devlist", "Lists current managed devices",
|
CrestronConsole.AddNewConsoleCommand(ListDeviceFeedbacks, "devfb", "Lists current feedbacks",
|
||||||
ConsoleAccessLevelEnum.AccessOperator);
|
ConsoleAccessLevelEnum.AccessOperator);
|
||||||
CrestronConsole.AddNewConsoleCommand(DeviceJsonApi.DoDeviceActionWithJson, "devjson", "",
|
CrestronConsole.AddNewConsoleCommand(ListDevices, "devlist", "Lists current managed devices",
|
||||||
ConsoleAccessLevelEnum.AccessOperator);
|
ConsoleAccessLevelEnum.AccessOperator);
|
||||||
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetProperties(s)), "devprops", "", ConsoleAccessLevelEnum.AccessOperator);
|
CrestronConsole.AddNewConsoleCommand(DeviceJsonApi.DoDeviceActionWithJson, "devjson", "",
|
||||||
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetMethods(s)), "devmethods", "", ConsoleAccessLevelEnum.AccessOperator);
|
ConsoleAccessLevelEnum.AccessOperator);
|
||||||
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s)), "apimethods", "", 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",
|
CrestronConsole.AddNewConsoleCommand(SimulateComReceiveOnDevice, "devsimreceive",
|
||||||
"Simulates incoming data on a com device", ConsoleAccessLevelEnum.AccessOperator);
|
"Simulates incoming data on a com device", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
|
|
||||||
@@ -52,77 +52,89 @@ namespace PepperDash.Essentials.Core
|
|||||||
CrestronConsole.AddNewConsoleCommand(s => DisableAllDeviceStreamDebugging(), "disableallstreamdebug", "disables stream debugging on all devices", ConsoleAccessLevelEnum.AccessOperator);
|
CrestronConsole.AddNewConsoleCommand(s => DisableAllDeviceStreamDebugging(), "disableallstreamdebug", "disables stream debugging on all devices", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calls activate steps on all Device class items
|
/// Calls activate steps on all Device class items
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void ActivateAll()
|
public static void ActivateAll()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
OnAllDevicesRegistered();
|
OnAllDevicesRegistered();
|
||||||
|
|
||||||
DeviceCriticalSection.Enter();
|
DeviceCriticalSection.Enter();
|
||||||
AddDeviceEnabled = false;
|
AddDeviceEnabled = false;
|
||||||
// PreActivate all devices
|
// PreActivate all devices
|
||||||
Debug.LogMessage(LogEventLevel.Information,"****PreActivation starting...****");
|
Debug.LogMessage(LogEventLevel.Information, "****PreActivation starting...****");
|
||||||
foreach (var d in Devices.Values)
|
foreach (var d in Devices.Values)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (d is Device)
|
if (d is Device)
|
||||||
(d as Device).PreActivate();
|
(d as Device).PreActivate();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, d, "ERROR: Device {1} PreActivation failure: {0}", e.Message, d.Key);
|
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.Debug, d, "Stack Trace: {0}", e.StackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Debug.LogMessage(LogEventLevel.Information, "****PreActivation complete****");
|
Debug.LogMessage(LogEventLevel.Information, "****PreActivation complete****");
|
||||||
Debug.LogMessage(LogEventLevel.Information, "****Activation starting...****");
|
Debug.LogMessage(LogEventLevel.Information, "****Activation starting...****");
|
||||||
|
|
||||||
// Activate all devices
|
// Activate all devices
|
||||||
foreach (var d in Devices.Values)
|
foreach (var d in Devices.Values)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (d is Device)
|
if (d is Device)
|
||||||
(d as Device).Activate();
|
(d as Device).Activate();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, d, "ERROR: Device {1} Activation failure: {0}", e.Message, d.Key);
|
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.Debug, d, "Stack Trace: {0}", e.StackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "****Activation complete****");
|
Debug.LogMessage(LogEventLevel.Information, "****Activation complete****");
|
||||||
Debug.LogMessage(LogEventLevel.Information, "****PostActivation starting...****");
|
Debug.LogMessage(LogEventLevel.Information, "****PostActivation starting...****");
|
||||||
|
|
||||||
// PostActivate all devices
|
// PostActivate all devices
|
||||||
foreach (var d in Devices.Values)
|
foreach (var d in Devices.Values)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (d is Device)
|
if (d is Device)
|
||||||
(d as Device).PostActivate();
|
(d as Device).PostActivate();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, d, "ERROR: Device {1} PostActivation failure: {0}", e.Message, d.Key);
|
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.Debug, d, "Stack Trace: {0}", e.StackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "****PostActivation complete****");
|
Debug.LogMessage(LogEventLevel.Information, "****PostActivation complete****");
|
||||||
|
|
||||||
OnAllDevicesActivated();
|
OnAllDevicesActivated();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
DeviceCriticalSection.Leave();
|
DeviceCriticalSection.Leave();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void DeviceManager_Initialized(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var allInitialized = Devices.Values.OfType<EssentialsDevice>().All(d => d.IsInitialized);
|
||||||
|
|
||||||
|
if (allInitialized)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Information, "****All Devices Initalized****");
|
||||||
|
|
||||||
|
OnAllDevicesInitialized();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void OnAllDevicesActivated()
|
private static void OnAllDevicesActivated()
|
||||||
{
|
{
|
||||||
@@ -142,77 +154,85 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
private static void OnAllDevicesInitialized()
|
||||||
/// Calls activate on all Device class items
|
{
|
||||||
/// </summary>
|
var handler = AllDevicesInitialized;
|
||||||
public static void DeactivateAll()
|
if (handler != null)
|
||||||
{
|
{
|
||||||
try
|
handler(null, new EventArgs());
|
||||||
{
|
}
|
||||||
DeviceCriticalSection.Enter();
|
}
|
||||||
foreach (var d in Devices.Values.OfType<Device>())
|
|
||||||
{
|
|
||||||
d.Deactivate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
DeviceCriticalSection.Leave();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//static void ListMethods(string devKey)
|
/// <summary>
|
||||||
//{
|
/// Calls activate on all Device class items
|
||||||
// var dev = GetDeviceForKey(devKey);
|
/// </summary>
|
||||||
// if(dev != null)
|
public static void DeactivateAll()
|
||||||
// {
|
{
|
||||||
// var type = dev.GetType().GetType();
|
try
|
||||||
// var methods = type.GetMethods(BindingFlags.Public|BindingFlags.Instance);
|
{
|
||||||
// var sb = new StringBuilder();
|
DeviceCriticalSection.Enter();
|
||||||
// sb.AppendLine(string.Format("{2} methods on [{0}] ({1}):", dev.Key, type.Name, methods.Length));
|
foreach (var d in Devices.Values.OfType<Device>())
|
||||||
// foreach (var m in methods)
|
{
|
||||||
// {
|
d.Deactivate();
|
||||||
// sb.Append(string.Format("{0}(", m.Name));
|
}
|
||||||
// var pars = m.GetParameters();
|
}
|
||||||
// foreach (var p in pars)
|
finally
|
||||||
// sb.Append(string.Format("({1}){0} ", p.Name, p.ParameterType.Name));
|
{
|
||||||
// sb.AppendLine(")");
|
DeviceCriticalSection.Leave();
|
||||||
// }
|
}
|
||||||
// CrestronConsole.ConsoleCommandResponse(sb.ToString());
|
}
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
private static void ListDevices(string s)
|
//static void ListMethods(string devKey)
|
||||||
{
|
//{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "{0} Devices registered with Device Manager:", Devices.Count);
|
// var dev = GetDeviceForKey(devKey);
|
||||||
var sorted = Devices.Values.ToList();
|
// if(dev != null)
|
||||||
sorted.Sort((a, b) => a.Key.CompareTo(b.Key));
|
// {
|
||||||
|
// 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());
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
foreach (var d in sorted)
|
private static void ListDevices(string s)
|
||||||
{
|
{
|
||||||
var name = d is IKeyName ? (d as IKeyName).Name : "---";
|
Debug.LogMessage(LogEventLevel.Information, "{0} Devices registered with Device Manager:", Devices.Count);
|
||||||
Debug.LogMessage(LogEventLevel.Information, " [{0}] {1}", d.Key, name);
|
var sorted = Devices.Values.ToList();
|
||||||
}
|
sorted.Sort((a, b) => a.Key.CompareTo(b.Key));
|
||||||
}
|
|
||||||
|
|
||||||
private static void ListDeviceFeedbacks(string devKey)
|
foreach (var d in sorted)
|
||||||
{
|
{
|
||||||
var dev = GetDeviceForKey(devKey);
|
var name = d is IKeyName ? (d as IKeyName).Name : "---";
|
||||||
if (dev == null)
|
Debug.LogMessage(LogEventLevel.Information, " [{0}] {1}", d.Key, name);
|
||||||
{
|
}
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Device '{0}' not found", devKey);
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
var statusDev = dev as IHasFeedback;
|
|
||||||
if (statusDev == null)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Device '{0}' does not have visible feedbacks", devKey);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
statusDev.DumpFeedbacksToConsole(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
//static void ListDeviceCommands(string devKey)
|
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, "Device '{0}' does not have visible feedbacks", devKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
statusDev.DumpFeedbacksToConsole(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//static void ListDeviceCommands(string devKey)
|
||||||
//{
|
//{
|
||||||
// var dev = GetDeviceForKey(devKey);
|
// var dev = GetDeviceForKey(devKey);
|
||||||
// if (dev == null)
|
// if (dev == null)
|
||||||
@@ -223,134 +243,135 @@ namespace PepperDash.Essentials.Core
|
|||||||
// Debug.LogMessage(LogEventLevel.Information, "This needs to be reworked. Stay tuned.", devKey);
|
// Debug.LogMessage(LogEventLevel.Information, "This needs to be reworked. Stay tuned.", devKey);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
private static void ListDeviceCommStatuses(string input)
|
private static void ListDeviceCommStatuses(string input)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
|
||||||
foreach (var dev in Devices.Values.OfType<ICommunicationMonitor>())
|
foreach (var dev in Devices.Values.OfType<ICommunicationMonitor>())
|
||||||
{
|
{
|
||||||
sb.Append(string.Format("{0}: {1}\r", dev,
|
CrestronConsole.ConsoleCommandResponse($"{dev}: {dev.CommunicationMonitor.Status}{Environment.NewLine}");
|
||||||
dev.CommunicationMonitor.Status));
|
}
|
||||||
}
|
}
|
||||||
CrestronConsole.ConsoleCommandResponse(sb.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//static void DoDeviceCommand(string command)
|
//static void DoDeviceCommand(string command)
|
||||||
//{
|
//{
|
||||||
// Debug.LogMessage(LogEventLevel.Information, "Not yet implemented. Stay tuned");
|
// Debug.LogMessage(LogEventLevel.Information, "Not yet implemented. Stay tuned");
|
||||||
//}
|
//}
|
||||||
|
|
||||||
public static void AddDevice(IKeyed newDev)
|
public static void AddDevice(IKeyed newDev)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!DeviceCriticalSection.TryEnter())
|
if (!DeviceCriticalSection.TryEnter())
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Currently unable to add devices to Device Manager. Please try again");
|
Debug.LogMessage(LogEventLevel.Information, "Currently unable to add devices to Device Manager. Please try again");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Check for device with same key
|
// Check for device with same key
|
||||||
//var existingDevice = _Devices.FirstOrDefault(d => d.Key.Equals(newDev.Key, StringComparison.OrdinalIgnoreCase));
|
//var existingDevice = _Devices.FirstOrDefault(d => d.Key.Equals(newDev.Key, StringComparison.OrdinalIgnoreCase));
|
||||||
////// If it exists, remove or warn??
|
////// If it exists, remove or warn??
|
||||||
//if (existingDevice != null)
|
//if (existingDevice != null)
|
||||||
|
|
||||||
if (!AddDeviceEnabled)
|
if (!AddDeviceEnabled)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "All devices have been activated. Adding new devices is not allowed.");
|
Debug.LogMessage(LogEventLevel.Information, "All devices have been activated. Adding new devices is not allowed.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Devices.ContainsKey(newDev.Key))
|
if (Devices.ContainsKey(newDev.Key))
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, newDev, "WARNING: A device with this key already exists. Not added to manager");
|
Debug.LogMessage(LogEventLevel.Information, newDev, "WARNING: A device with this key already exists. Not added to manager");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Devices.Add(newDev.Key, newDev);
|
Devices.Add(newDev.Key, newDev);
|
||||||
//if (!(_Devices.Contains(newDev)))
|
//if (!(_Devices.Contains(newDev)))
|
||||||
// _Devices.Add(newDev);
|
// _Devices.Add(newDev);
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
DeviceCriticalSection.Leave();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void AddDevice(IEnumerable<IKeyed> devicesToAdd)
|
if (newDev is EssentialsDevice essentialsDev)
|
||||||
{
|
essentialsDev.Initialized += DeviceManager_Initialized;
|
||||||
try
|
}
|
||||||
{
|
finally
|
||||||
if (!DeviceCriticalSection.TryEnter())
|
{
|
||||||
{
|
DeviceCriticalSection.Leave();
|
||||||
Debug.LogMessage(LogEventLevel.Information,
|
}
|
||||||
"Currently unable to add devices to Device Manager. Please try again");
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!AddDeviceEnabled)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information,
|
|
||||||
"All devices have been activated. Adding new devices is not allowed.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var dev in devicesToAdd)
|
public static void AddDevice(IEnumerable<IKeyed> devicesToAdd)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Devices.Add(dev.Key, dev);
|
if (!DeviceCriticalSection.TryEnter())
|
||||||
}
|
{
|
||||||
catch (ArgumentException ex)
|
Debug.LogMessage(LogEventLevel.Information,
|
||||||
{
|
"Currently unable to add devices to Device Manager. Please try again");
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Error adding device with key {0} to Device Manager: {1}\r\nStack Trace: {2}",
|
return;
|
||||||
dev.Key, ex.Message, ex.StackTrace);
|
}
|
||||||
}
|
if (!AddDeviceEnabled)
|
||||||
}
|
{
|
||||||
}
|
Debug.LogMessage(LogEventLevel.Information,
|
||||||
finally
|
"All devices have been activated. Adding new devices is not allowed.");
|
||||||
{
|
return;
|
||||||
DeviceCriticalSection.Leave();
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void RemoveDevice(IKeyed newDev)
|
foreach (var dev in devicesToAdd)
|
||||||
{
|
{
|
||||||
try
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
DeviceCriticalSection.Leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RemoveDevice(IKeyed newDev)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
DeviceCriticalSection.Enter();
|
DeviceCriticalSection.Enter();
|
||||||
if (newDev == null)
|
if (newDev == null)
|
||||||
return;
|
return;
|
||||||
if (Devices.ContainsKey(newDev.Key))
|
if (Devices.ContainsKey(newDev.Key))
|
||||||
Devices.Remove(newDev.Key);
|
Devices.Remove(newDev.Key);
|
||||||
//if (_Devices.Contains(newDev))
|
//if (_Devices.Contains(newDev))
|
||||||
// _Devices.Remove(newDev);
|
// _Devices.Remove(newDev);
|
||||||
else
|
else
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Device manager: Device '{0}' does not exist in manager. Cannot remove", newDev.Key);
|
Debug.LogMessage(LogEventLevel.Information, "Device manager: Device '{0}' does not exist in manager. Cannot remove", newDev.Key);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
DeviceCriticalSection.Leave();
|
DeviceCriticalSection.Leave();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<string> GetDeviceKeys()
|
public static IEnumerable<string> GetDeviceKeys()
|
||||||
{
|
{
|
||||||
//return _Devices.Select(d => d.Key).ToList();
|
//return _Devices.Select(d => d.Key).ToList();
|
||||||
return Devices.Keys;
|
return Devices.Keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<IKeyed> GetDevices()
|
public static IEnumerable<IKeyed> GetDevices()
|
||||||
{
|
{
|
||||||
//return _Devices.Select(d => d.Key).ToList();
|
//return _Devices.Select(d => d.Key).ToList();
|
||||||
return Devices.Values;
|
return Devices.Values;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IKeyed GetDeviceForKey(string key)
|
public static IKeyed GetDeviceForKey(string key)
|
||||||
{
|
{
|
||||||
//return _Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
|
//return _Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
|
||||||
if (key != null && Devices.ContainsKey(key))
|
if (key != null && Devices.ContainsKey(key))
|
||||||
return Devices[key];
|
return Devices[key];
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Console handler that simulates com port data receive
|
/// Console handler that simulates com port data receive
|
||||||
@@ -367,8 +388,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
//Debug.LogMessage(LogEventLevel.Verbose, "**** {0} - {1} ****", match.Groups[1].Value, match.Groups[2].Value);
|
//Debug.LogMessage(LogEventLevel.Verbose, "**** {0} - {1} ****", match.Groups[1].Value, match.Groups[2].Value);
|
||||||
|
|
||||||
var com = GetDeviceForKey(match.Groups[1].Value) as ComPortController;
|
if (!(GetDeviceForKey(match.Groups[1].Value) is ComPortController com))
|
||||||
if (com == null)
|
|
||||||
{
|
{
|
||||||
CrestronConsole.ConsoleCommandResponse("'{0}' is not a comm port device", match.Groups[1].Value);
|
CrestronConsole.ConsoleCommandResponse("'{0}' is not a comm port device", match.Groups[1].Value);
|
||||||
return;
|
return;
|
||||||
@@ -423,16 +443,15 @@ namespace PepperDash.Essentials.Core
|
|||||||
var deviceKey = args[0];
|
var deviceKey = args[0];
|
||||||
var setting = args[1];
|
var setting = args[1];
|
||||||
|
|
||||||
var timeout= String.Empty;
|
var timeout = String.Empty;
|
||||||
|
|
||||||
if (args.Length >= 3)
|
if (args.Length >= 3)
|
||||||
{
|
{
|
||||||
timeout = args[2];
|
timeout = args[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
var device = GetDeviceForKey(deviceKey) as IStreamDebugging;
|
|
||||||
|
|
||||||
if (device == null)
|
if (!(GetDeviceForKey(deviceKey) is IStreamDebugging device))
|
||||||
{
|
{
|
||||||
CrestronConsole.ConsoleCommandResponse("Unable to get device with key: {0}", deviceKey);
|
CrestronConsole.ConsoleCommandResponse("Unable to get device with key: {0}", deviceKey);
|
||||||
return;
|
return;
|
||||||
@@ -479,13 +498,11 @@ namespace PepperDash.Essentials.Core
|
|||||||
{
|
{
|
||||||
foreach (var device in AllDevices)
|
foreach (var device in AllDevices)
|
||||||
{
|
{
|
||||||
var streamDevice = device as IStreamDebugging;
|
if (device is IStreamDebugging streamDevice)
|
||||||
|
|
||||||
if (streamDevice != null)
|
|
||||||
{
|
{
|
||||||
streamDevice.StreamDebugging.SetDebuggingWithDefaultTimeout(eStreamDebuggingSetting.Off);
|
streamDevice.StreamDebugging.SetDebuggingWithDefaultTimeout(eStreamDebuggingSetting.Off);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,24 @@ namespace PepperDash.Essentials.Core
|
|||||||
[Description("The base Essentials Device Class")]
|
[Description("The base Essentials Device Class")]
|
||||||
public abstract class EssentialsDevice : Device
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected EssentialsDevice(string key)
|
protected EssentialsDevice(string key)
|
||||||
: base(key)
|
: base(key)
|
||||||
{
|
{
|
||||||
@@ -41,6 +59,8 @@ namespace PepperDash.Essentials.Core
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Initialize();
|
Initialize();
|
||||||
|
|
||||||
|
IsInitialized = true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -51,8 +51,18 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// The key of the device in the DeviceManager for control
|
/// The key of the device in the DeviceManager for control
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("deviceKey")]
|
[JsonProperty("deviceKey")]
|
||||||
public string DeviceKey => DeviceManager.AllDevices.
|
public string DeviceKey
|
||||||
Where(d => d.Key.Contains(ParentDeviceKey) && d.Key.Contains(ItemKey)).FirstOrDefault()?.Key ?? $"{ParentDeviceKey}--{ItemKey}";
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if(string.IsNullOrEmpty(ItemKey)) return ParentDeviceKey;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return DeviceManager.AllDevices.
|
||||||
|
Where(d => d.Key.Contains(ParentDeviceKey) && d.Key.Contains(ItemKey)).FirstOrDefault()?.Key ?? $"{ParentDeviceKey}--{ItemKey}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates if the item is a level, mute , or both
|
/// Indicates if the item is a level, mute , or both
|
||||||
|
|||||||
@@ -1,128 +1,121 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using Crestron.SimplSharp.CrestronIO;
|
|
||||||
using Crestron.SimplSharpPro;
|
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum eSourceListItemType
|
public enum eSourceListItemType
|
||||||
{
|
{
|
||||||
Route, Off, Other, SomethingAwesomerThanThese
|
Route, Off, Other, SomethingAwesomerThanThese
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an item in a source list - can be deserialized into.
|
/// Represents an item in a source list - can be deserialized into.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SourceListItem
|
public class SourceListItem
|
||||||
{
|
{
|
||||||
[JsonProperty("sourceKey")]
|
[JsonProperty("sourceKey")]
|
||||||
public string SourceKey { get; set; }
|
public string SourceKey { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the source Device for this, if it exists in DeviceManager
|
/// Returns the source Device for this, if it exists in DeviceManager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Device SourceDevice
|
public Device SourceDevice
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_SourceDevice == null)
|
if (_SourceDevice == null)
|
||||||
_SourceDevice = DeviceManager.GetDeviceForKey(SourceKey) as Device;
|
_SourceDevice = DeviceManager.GetDeviceForKey(SourceKey) as Device;
|
||||||
return _SourceDevice;
|
return _SourceDevice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Device _SourceDevice;
|
|
||||||
|
|
||||||
/// <summary>
|
private Device _SourceDevice;
|
||||||
/// Gets either the source's Name or this AlternateName property, if
|
|
||||||
/// defined. If source doesn't exist, returns "Missing source"
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("preferredName")]
|
|
||||||
public string PreferredName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(Name))
|
|
||||||
{
|
|
||||||
if (SourceDevice == null)
|
|
||||||
return "---";
|
|
||||||
return SourceDevice.Name;
|
|
||||||
}
|
|
||||||
return Name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A name that will override the source's name on the UI
|
/// Gets either the source's Name or this AlternateName property, if
|
||||||
/// </summary>
|
/// defined. If source doesn't exist, returns "Missing source"
|
||||||
[JsonProperty("name")]
|
/// </summary>
|
||||||
public string Name { get; set; }
|
[JsonProperty("preferredName")]
|
||||||
|
public string PreferredName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(Name))
|
||||||
|
{
|
||||||
|
if (SourceDevice == null)
|
||||||
|
return "---";
|
||||||
|
return SourceDevice.Name;
|
||||||
|
}
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A name that will override the source's name on the UI
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies and icon for the source list item
|
/// Specifies and icon for the source list item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("icon")]
|
[JsonProperty("icon")]
|
||||||
public string Icon { get; set; }
|
public string Icon { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Alternate icon
|
/// Alternate icon
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("altIcon")]
|
[JsonProperty("altIcon")]
|
||||||
public string AltIcon { get; set; }
|
public string AltIcon { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates if the item should be included in the source list
|
/// Indicates if the item should be included in the source list
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("includeInSourceList")]
|
[JsonProperty("includeInSourceList")]
|
||||||
public bool IncludeInSourceList { get; set; }
|
public bool IncludeInSourceList { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("order")]
|
[JsonProperty("order")]
|
||||||
public int Order { get; set; }
|
public int Order { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The key of the device for volume control
|
/// The key of the device for volume control
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("volumeControlKey")]
|
[JsonProperty("volumeControlKey")]
|
||||||
public string VolumeControlKey { get; set; }
|
public string VolumeControlKey { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The type of source list item
|
/// The type of source list item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("type")]
|
[JsonProperty("type")]
|
||||||
[JsonConverter(typeof(StringEnumConverter))]
|
[JsonConverter(typeof(StringEnumConverter))]
|
||||||
public eSourceListItemType Type { get; set; }
|
public eSourceListItemType Type { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of routes to execute for this source list item
|
/// The list of routes to execute for this source list item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("routeList")]
|
[JsonProperty("routeList")]
|
||||||
public List<SourceRouteListItem> RouteList { get; set; }
|
public List<SourceRouteListItem> RouteList { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("disableCodecSharing")]
|
[JsonProperty("disableCodecSharing")]
|
||||||
public bool DisableCodecSharing { get; set; }
|
public bool DisableCodecSharing { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("disableRoutedSharing")]
|
[JsonProperty("disableRoutedSharing")]
|
||||||
public bool DisableRoutedSharing { get; set; }
|
public bool DisableRoutedSharing { get; set; }
|
||||||
|
|
||||||
[JsonProperty("destinations")]
|
[JsonProperty("destinations")]
|
||||||
public List<eSourceListItemDestinationTypes> Destinations { get; set; }
|
public List<eSourceListItemDestinationTypes> Destinations { get; set; }
|
||||||
@@ -156,10 +149,10 @@ namespace PepperDash.Essentials.Core
|
|||||||
[JsonProperty("disableSimpleRouting")]
|
[JsonProperty("disableSimpleRouting")]
|
||||||
public bool DisableSimpleRouting { get; set; }
|
public bool DisableSimpleRouting { get; set; }
|
||||||
|
|
||||||
public SourceListItem()
|
public SourceListItem()
|
||||||
{
|
{
|
||||||
Icon = "Blank";
|
Icon = "Blank";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
@@ -167,23 +160,23 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SourceRouteListItem
|
public class SourceRouteListItem
|
||||||
{
|
{
|
||||||
[JsonProperty("sourceKey")]
|
[JsonProperty("sourceKey")]
|
||||||
public string SourceKey { get; set; }
|
public string SourceKey { get; set; }
|
||||||
|
|
||||||
[JsonProperty("sourcePortKey")]
|
[JsonProperty("sourcePortKey")]
|
||||||
public string SourcePortKey { get; set; }
|
public string SourcePortKey { get; set; }
|
||||||
|
|
||||||
[JsonProperty("destinationKey")]
|
[JsonProperty("destinationKey")]
|
||||||
public string DestinationKey { get; set; }
|
public string DestinationKey { get; set; }
|
||||||
|
|
||||||
[JsonProperty("destinationPortKey")]
|
[JsonProperty("destinationPortKey")]
|
||||||
public string DestinationPortKey { get; set; }
|
public string DestinationPortKey { get; set; }
|
||||||
|
|
||||||
[JsonProperty("type")]
|
[JsonProperty("type")]
|
||||||
public eRoutingSignalType Type { get; set; }
|
public eRoutingSignalType Type { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the valid destination types for SourceListItems in a room
|
/// Defines the valid destination types for SourceListItems in a room
|
||||||
@@ -193,8 +186,12 @@ namespace PepperDash.Essentials.Core
|
|||||||
defaultDisplay,
|
defaultDisplay,
|
||||||
leftDisplay,
|
leftDisplay,
|
||||||
rightDisplay,
|
rightDisplay,
|
||||||
centerDisplay,
|
centerDisplay,
|
||||||
programAudio,
|
programAudio,
|
||||||
codecContent
|
codecContent,
|
||||||
|
frontLeftDisplay,
|
||||||
|
frontRightDisplay,
|
||||||
|
rearLeftDisplay,
|
||||||
|
rearRightDisplay,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,17 +109,18 @@ namespace PepperDash.Essentials.Core
|
|||||||
protected void AddJoins(Type type)
|
protected void AddJoins(Type type)
|
||||||
{
|
{
|
||||||
var fields =
|
var fields =
|
||||||
type.GetType()
|
type.GetFields(BindingFlags.Public | BindingFlags.Instance)
|
||||||
.GetFields(BindingFlags.Public | BindingFlags.Instance)
|
.Where(f => f.IsDefined(typeof (JoinNameAttribute), true)).ToList();
|
||||||
.Where(f => f.IsDefined(typeof (JoinNameAttribute), true));
|
|
||||||
|
Debug.LogMessage(LogEventLevel.Debug, "Got {fields} with JoinNameAttribute", fields.Count);
|
||||||
|
|
||||||
foreach (var field in fields)
|
foreach (var field in fields)
|
||||||
{
|
{
|
||||||
var childClass = Convert.ChangeType(this, type, null);
|
var childClass = Convert.ChangeType(this, type, null);
|
||||||
|
|
||||||
var value = field.GetValue(childClass) as JoinDataComplete; //this here is JoinMapBaseAdvanced, not the child class. JoinMapBaseAdvanced has no fields.
|
//this here is JoinMapBaseAdvanced, not the child class. JoinMapBaseAdvanced has no fields.
|
||||||
|
|
||||||
if (value == null)
|
if (!(field.GetValue(childClass) is JoinDataComplete value))
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Unable to cast base class to {0}", type.Name);
|
Debug.LogMessage(LogEventLevel.Information, "Unable to cast base class to {0}", type.Name);
|
||||||
continue;
|
continue;
|
||||||
@@ -129,7 +130,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
var joinName = value.GetNameAttribute(field);
|
var joinName = value.GetNameAttribute(field);
|
||||||
|
|
||||||
if (String.IsNullOrEmpty(joinName)) continue;
|
if (string.IsNullOrEmpty(joinName)) continue;
|
||||||
|
|
||||||
Joins.Add(joinName, value);
|
Joins.Add(joinName, value);
|
||||||
}
|
}
|
||||||
@@ -155,29 +156,37 @@ namespace PepperDash.Essentials.Core
|
|||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
// Get the joins of each type and print them
|
var lineEnding = "\r\n";
|
||||||
sb.AppendLine(String.Format("# {0}", GetType().Name));
|
|
||||||
sb.AppendLine();
|
|
||||||
sb.AppendLine("## Digitals");
|
|
||||||
sb.AppendLine();
|
|
||||||
// Get the joins of each type and print them
|
|
||||||
var digitals =
|
|
||||||
Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Digital) == eJoinType.Digital)
|
|
||||||
.ToDictionary(j => j.Key, j => j.Value);
|
|
||||||
var digitalSb = AppendJoinList(GetSortedJoins(digitals));
|
|
||||||
digitalSb.AppendLine("## Analogs");
|
|
||||||
digitalSb.AppendLine();
|
|
||||||
|
|
||||||
var analogs =
|
var digitals =
|
||||||
Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Analog) == eJoinType.Analog)
|
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);
|
.ToDictionary(j => j.Key, j => j.Value);
|
||||||
var analogSb = AppendJoinList(GetSortedJoins(analogs));
|
|
||||||
analogSb.AppendLine("## Serials");
|
|
||||||
analogSb.AppendLine();
|
|
||||||
|
|
||||||
var serials =
|
var serials =
|
||||||
Joins.Where(j => (j.Value.Metadata.JoinType & eJoinType.Serial) == eJoinType.Serial)
|
Joins.Where(j => j.Value.Metadata.JoinType.HasFlag(eJoinType.Serial))
|
||||||
.ToDictionary(j => j.Key, j => j.Value);
|
.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));
|
var serialSb = AppendJoinList(GetSortedJoins(serials));
|
||||||
|
|
||||||
sb.EnsureCapacity(sb.Length + digitalSb.Length + analogSb.Length + serialSb.Length);
|
sb.EnsureCapacity(sb.Length + digitalSb.Length + analogSb.Length + serialSb.Length);
|
||||||
@@ -202,7 +211,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
private static void WriteJoinmapMarkdown(StringBuilder stringBuilder, string pluginType, string bridgeKey, string 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);
|
var fileName = string.Format("{0}{1}{2}__{3}__{4}.md", Global.FilePathPrefix, "joinMaps/", pluginType, bridgeKey, deviceKey);
|
||||||
|
|
||||||
using (var sw = new StreamWriter(fileName))
|
using (var sw = new StreamWriter(fileName))
|
||||||
{
|
{
|
||||||
@@ -230,7 +239,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
static StringBuilder AppendJoinList(List<KeyValuePair<string, JoinDataComplete>> joins)
|
static StringBuilder AppendJoinList(List<KeyValuePair<string, JoinDataComplete>> joins)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
const string stringFormatter = "| {0} | {1} | {2} | {3} | {4} |";
|
const string stringFormatter = "| {0} | {1} | {2} | {3} | {4} |\r\n";
|
||||||
const int joinNumberLen = 11;
|
const int joinNumberLen = 11;
|
||||||
const int joinSpanLen = 9;
|
const int joinSpanLen = 9;
|
||||||
const int typeLen = 19;
|
const int typeLen = 19;
|
||||||
@@ -238,25 +247,25 @@ namespace PepperDash.Essentials.Core
|
|||||||
var descriptionLen = (from @join in joins select @join.Value into j select j.Metadata.Description.Length).Concat(new[] {11}).Max();
|
var descriptionLen = (from @join in joins select @join.Value into j select j.Metadata.Description.Length).Concat(new[] {11}).Max();
|
||||||
|
|
||||||
//build header
|
//build header
|
||||||
sb.AppendLine(String.Format(stringFormatter,
|
sb.Append(string.Format(stringFormatter,
|
||||||
String.Format("Join Number").PadRight(joinNumberLen, ' '),
|
string.Format("Join Number").PadRight(joinNumberLen, ' '),
|
||||||
String.Format("Join Span").PadRight(joinSpanLen, ' '),
|
string.Format("Join Span").PadRight(joinSpanLen, ' '),
|
||||||
String.Format("Description").PadRight(descriptionLen, ' '),
|
string.Format("Description").PadRight(descriptionLen, ' '),
|
||||||
String.Format("Type").PadRight(typeLen, ' '),
|
string.Format("Type").PadRight(typeLen, ' '),
|
||||||
String.Format("Capabilities").PadRight(capabilitiesLen, ' ')));
|
string.Format("Capabilities").PadRight(capabilitiesLen, ' ')));
|
||||||
//build table seperator
|
//build table seperator
|
||||||
sb.AppendLine(String.Format(stringFormatter,
|
sb.Append(string.Format(stringFormatter,
|
||||||
new String('-', joinNumberLen),
|
new string('-', joinNumberLen),
|
||||||
new String('-', joinSpanLen),
|
new string('-', joinSpanLen),
|
||||||
new String('-', descriptionLen),
|
new string('-', descriptionLen),
|
||||||
new String('-', typeLen),
|
new string('-', typeLen),
|
||||||
new String('-', capabilitiesLen)));
|
new string('-', capabilitiesLen)));
|
||||||
|
|
||||||
foreach (var join in joins)
|
foreach (var join in joins)
|
||||||
{
|
{
|
||||||
sb.AppendLine(join.Value.GetMarkdownFormattedData(stringFormatter, descriptionLen));
|
sb.Append(join.Value.GetMarkdownFormattedData(stringFormatter, descriptionLen));
|
||||||
}
|
}
|
||||||
sb.AppendLine();
|
sb.Append("\r\n");
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,10 +420,10 @@ namespace PepperDash.Essentials.Core
|
|||||||
{
|
{
|
||||||
|
|
||||||
//Fixed Width Headers
|
//Fixed Width Headers
|
||||||
var joinNumberLen = String.Format("Join Number").Length;
|
var joinNumberLen = string.Format("Join Number").Length;
|
||||||
var joinSpanLen = String.Format("Join Span").Length;
|
var joinSpanLen = string.Format("Join Span").Length;
|
||||||
var typeLen = String.Format("AnalogDigitalSerial").Length;
|
var typeLen = string.Format("AnalogDigitalSerial").Length;
|
||||||
var capabilitiesLen = String.Format("ToFromFusion").Length;
|
var capabilitiesLen = string.Format("ToFromFusion").Length;
|
||||||
|
|
||||||
//Track which one failed, if it did
|
//Track which one failed, if it did
|
||||||
const string placeholder = "unknown";
|
const string placeholder = "unknown";
|
||||||
@@ -430,13 +439,13 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
dataArray["joinNumber"] = String.Format("{0}", JoinNumber.ToString(CultureInfo.InvariantCulture).ReplaceIfNullOrEmpty(placeholder)).PadRight(joinNumberLen, ' ');
|
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["joinSpan"] = string.Format("{0}", JoinSpan.ToString(CultureInfo.InvariantCulture).ReplaceIfNullOrEmpty(placeholder)).PadRight(joinSpanLen, ' ');
|
||||||
dataArray["description"] = String.Format("{0}", Metadata.Description.ReplaceIfNullOrEmpty(placeholder)).PadRight(descriptionLen, ' ');
|
dataArray["description"] = string.Format("{0}", Metadata.Description.ReplaceIfNullOrEmpty(placeholder)).PadRight(descriptionLen, ' ');
|
||||||
dataArray["joinType"] = String.Format("{0}", Metadata.JoinType.ToString().ReplaceIfNullOrEmpty(placeholder)).PadRight(typeLen, ' ');
|
dataArray["joinType"] = string.Format("{0}", Metadata.JoinType.ToString().ReplaceIfNullOrEmpty(placeholder)).PadRight(typeLen, ' ');
|
||||||
dataArray["capabilities"] = String.Format("{0}", Metadata.JoinCapabilities.ToString().ReplaceIfNullOrEmpty(placeholder)).PadRight(capabilitiesLen, ' ');
|
dataArray["capabilities"] = string.Format("{0}", Metadata.JoinCapabilities.ToString().ReplaceIfNullOrEmpty(placeholder)).PadRight(capabilitiesLen, ' ');
|
||||||
|
|
||||||
return String.Format(stringFormatter,
|
return string.Format(stringFormatter,
|
||||||
dataArray["joinNumber"],
|
dataArray["joinNumber"],
|
||||||
dataArray["joinSpan"],
|
dataArray["joinSpan"],
|
||||||
dataArray["description"],
|
dataArray["description"],
|
||||||
@@ -454,8 +463,8 @@ namespace PepperDash.Essentials.Core
|
|||||||
errorKey = item.Key;
|
errorKey = item.Key;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Unable to decode join metadata {1}- {0}", e.Message, !String.IsNullOrEmpty(errorKey) ? (' ' + errorKey) : String.Empty);
|
Debug.LogMessage(LogEventLevel.Information, "Unable to decode join metadata {1}- {0}", e.Message, !string.IsNullOrEmpty(errorKey) ? (' ' + errorKey) : string.Empty);
|
||||||
return String.Format(stringFormatter,
|
return string.Format(stringFormatter,
|
||||||
dataArray["joinNumber"],
|
dataArray["joinNumber"],
|
||||||
dataArray["joinSpan"],
|
dataArray["joinSpan"],
|
||||||
dataArray["description"],
|
dataArray["description"],
|
||||||
@@ -520,7 +529,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
public JoinNameAttribute(string name)
|
public JoinNameAttribute(string name)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "Setting Attribute Name: {0}", name);
|
Debug.LogMessage(LogEventLevel.Verbose, "Setting Attribute Name: {0}",null, name);
|
||||||
_Name = name;
|
_Name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
using System;
|
using PepperDash.Core;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using PepperDash.Core;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
@@ -26,6 +22,11 @@ namespace PepperDash.Essentials.Core
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
if (IsInAutoMode)
|
||||||
|
{
|
||||||
|
return _partitionSensor.PartitionPresentFeedback.BoolValue;
|
||||||
|
}
|
||||||
|
|
||||||
return _partitionPresent;
|
return _partitionPresent;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
@@ -73,11 +74,11 @@ namespace PepperDash.Essentials.Core
|
|||||||
PartitionPresentFeedback.FireUpdate();
|
PartitionPresentFeedback.FireUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
private void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
||||||
{
|
{
|
||||||
if (IsInAutoMode)
|
if (IsInAutoMode)
|
||||||
{
|
{
|
||||||
PartitionPresentFeedback.FireUpdate();
|
PartitionPresent = e.BoolValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +104,10 @@ namespace PepperDash.Essentials.Core
|
|||||||
{
|
{
|
||||||
_partitionSensor.PartitionPresentFeedback.OutputChange -= PartitionPresentFeedback_OutputChange;
|
_partitionSensor.PartitionPresentFeedback.OutputChange -= PartitionPresentFeedback_OutputChange;
|
||||||
_partitionSensor.PartitionPresentFeedback.OutputChange += PartitionPresentFeedback_OutputChange;
|
_partitionSensor.PartitionPresentFeedback.OutputChange += PartitionPresentFeedback_OutputChange;
|
||||||
|
PartitionPresent = _partitionSensor.PartitionPresentFeedback.BoolValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PartitionPresentFeedback.FireUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetManualMode()
|
public void SetManualMode()
|
||||||
@@ -123,7 +127,10 @@ namespace PepperDash.Essentials.Core
|
|||||||
if (_partitionSensor != null)
|
if (_partitionSensor != null)
|
||||||
{
|
{
|
||||||
_partitionSensor.PartitionPresentFeedback.OutputChange -= PartitionPresentFeedback_OutputChange;
|
_partitionSensor.PartitionPresentFeedback.OutputChange -= PartitionPresentFeedback_OutputChange;
|
||||||
|
PartitionPresent = _partitionSensor.PartitionPresentFeedback.BoolValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PartitionPresentFeedback.FireUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.20.66" />
|
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.20.66" />
|
||||||
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-424" />
|
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-451" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Crestron\CrestronGenericBaseDevice.cs.orig" />
|
<None Include="Crestron\CrestronGenericBaseDevice.cs.orig" />
|
||||||
|
|||||||
@@ -130,6 +130,8 @@ namespace PepperDash.Essentials.Core.Presets
|
|||||||
var pl = JsonConvert.DeserializeObject<PresetsList>(File.ReadToEnd(_filePath, Encoding.ASCII));
|
var pl = JsonConvert.DeserializeObject<PresetsList>(File.ReadToEnd(_filePath, Encoding.ASCII));
|
||||||
Name = pl.Name;
|
Name = pl.Name;
|
||||||
PresetsList = pl.Channels;
|
PresetsList = pl.Channels;
|
||||||
|
|
||||||
|
Debug.LogMessage(LogEventLevel.Verbose, this, "Loaded {0} presets", PresetsList.Count);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
using System;
|
using Crestron.SimplSharp;
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Core.Logging;
|
||||||
|
using Serilog.Events;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Crestron.SimplSharp;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using PepperDash.Core;
|
|
||||||
using Serilog.Events;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
@@ -35,7 +36,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if(value == _isInAutoMode)
|
if (value == _isInAutoMode)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -49,6 +50,8 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
private int _scenarioChangeDebounceTimeSeconds = 10; // default to 10s
|
private int _scenarioChangeDebounceTimeSeconds = 10; // default to 10s
|
||||||
|
|
||||||
|
private Mutex _scenarioChange = new Mutex();
|
||||||
|
|
||||||
public EssentialsRoomCombiner(string key, EssentialsRoomCombinerPropertiesConfig props)
|
public EssentialsRoomCombiner(string key, EssentialsRoomCombinerPropertiesConfig props)
|
||||||
: base(key)
|
: base(key)
|
||||||
{
|
{
|
||||||
@@ -81,7 +84,15 @@ namespace PepperDash.Essentials.Core
|
|||||||
SetupPartitionStateProviders();
|
SetupPartitionStateProviders();
|
||||||
|
|
||||||
SetRooms();
|
SetRooms();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// 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)
|
if (IsInAutoMode)
|
||||||
{
|
{
|
||||||
DetermineRoomCombinationScenario();
|
DetermineRoomCombinationScenario();
|
||||||
@@ -90,10 +101,10 @@ namespace PepperDash.Essentials.Core
|
|||||||
{
|
{
|
||||||
SetRoomCombinationScenario(_propertiesConfig.defaultScenarioKey);
|
SetRoomCombinationScenario(_propertiesConfig.defaultScenarioKey);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateScenarios()
|
private void CreateScenarios()
|
||||||
{
|
{
|
||||||
foreach (var scenarioConfig in _propertiesConfig.Scenarios)
|
foreach (var scenarioConfig in _propertiesConfig.Scenarios)
|
||||||
{
|
{
|
||||||
@@ -102,21 +113,29 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetRooms()
|
private void SetRooms()
|
||||||
{
|
{
|
||||||
_rooms = new List<IEssentialsRoom>();
|
_rooms = new List<IEssentialsRoom>();
|
||||||
|
|
||||||
foreach (var roomKey in _propertiesConfig.RoomKeys)
|
foreach (var roomKey in _propertiesConfig.RoomKeys)
|
||||||
{
|
{
|
||||||
var room = DeviceManager.GetDeviceForKey(roomKey) as IEssentialsRoom;
|
var room = DeviceManager.GetDeviceForKey(roomKey);
|
||||||
if (room != null)
|
|
||||||
|
if (DeviceManager.GetDeviceForKey(roomKey) is IEssentialsRoom essentialsRoom)
|
||||||
{
|
{
|
||||||
_rooms.Add(room);
|
_rooms.Add(essentialsRoom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var rooms = DeviceManager.AllDevices.OfType<IEssentialsRoom>().Cast<Device>();
|
||||||
|
|
||||||
|
foreach (var room in rooms)
|
||||||
|
{
|
||||||
|
room.Deactivate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupPartitionStateProviders()
|
private void SetupPartitionStateProviders()
|
||||||
{
|
{
|
||||||
foreach (var pConfig in _propertiesConfig.Partitions)
|
foreach (var pConfig in _propertiesConfig.Partitions)
|
||||||
{
|
{
|
||||||
@@ -130,18 +149,18 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
private void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e)
|
||||||
{
|
{
|
||||||
StartDebounceTimer();
|
StartDebounceTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartDebounceTimer()
|
private void StartDebounceTimer()
|
||||||
{
|
{
|
||||||
// default to 500ms for manual mode
|
// default to 500ms for manual mode
|
||||||
var time = 500;
|
var time = 500;
|
||||||
|
|
||||||
// if in auto mode, debounce the scenario change
|
// if in auto mode, debounce the scenario change
|
||||||
if(IsInAutoMode) time = _scenarioChangeDebounceTimeSeconds * 1000;
|
if (IsInAutoMode) time = _scenarioChangeDebounceTimeSeconds * 1000;
|
||||||
|
|
||||||
if (_scenarioChangeDebounceTimer == null)
|
if (_scenarioChangeDebounceTimer == null)
|
||||||
{
|
{
|
||||||
@@ -156,7 +175,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines the current room combination scenario based on the state of the partition sensors
|
/// Determines the current room combination scenario based on the state of the partition sensors
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void DetermineRoomCombinationScenario()
|
private void DetermineRoomCombinationScenario()
|
||||||
{
|
{
|
||||||
if (_scenarioChangeDebounceTimer != null)
|
if (_scenarioChangeDebounceTimer != null)
|
||||||
{
|
{
|
||||||
@@ -164,14 +183,20 @@ namespace PepperDash.Essentials.Core
|
|||||||
_scenarioChangeDebounceTimer = null;
|
_scenarioChangeDebounceTimer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.LogInformation("Determining Combination Scenario");
|
||||||
|
|
||||||
var currentScenario = RoomCombinationScenarios.FirstOrDefault((s) =>
|
var currentScenario = RoomCombinationScenarios.FirstOrDefault((s) =>
|
||||||
{
|
{
|
||||||
|
this.LogDebug("Checking scenario {scenarioKey}", s.Key);
|
||||||
// iterate the partition states
|
// iterate the partition states
|
||||||
foreach (var partitionState in s.PartitionStates)
|
foreach (var partitionState in s.PartitionStates)
|
||||||
{
|
{
|
||||||
|
this.LogDebug("checking PartitionState {partitionStateKey}", partitionState.PartitionKey);
|
||||||
// get the partition by key
|
// get the partition by key
|
||||||
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionState.PartitionKey));
|
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionState.PartitionKey));
|
||||||
|
|
||||||
|
this.LogDebug("Expected State: {partitionPresent} Actual State: {partitionState}", partitionState.PartitionPresent, partition.PartitionPresentFeedback.BoolValue);
|
||||||
|
|
||||||
if (partition != null && partitionState.PartitionPresent != partition.PartitionPresentFeedback.BoolValue)
|
if (partition != null && partitionState.PartitionPresent != partition.PartitionPresentFeedback.BoolValue)
|
||||||
{
|
{
|
||||||
// the partition can't be found or the state doesn't match
|
// the partition can't be found or the state doesn't match
|
||||||
@@ -184,10 +209,41 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
if (currentScenario != null)
|
if (currentScenario != null)
|
||||||
{
|
{
|
||||||
CurrentScenario = currentScenario;
|
this.LogInformation("Found combination Scenario {scenarioKey}", currentScenario.Key);
|
||||||
|
ChangeScenario(currentScenario);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ChangeScenario(IRoomCombinationScenario newScenario)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
if (newScenario == _currentScenario)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deactivate the old scenario first
|
||||||
|
if (_currentScenario != null)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Information, "Deactivating scenario {currentScenario}", this, _currentScenario.Name);
|
||||||
|
await _currentScenario.Deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
_currentScenario = newScenario;
|
||||||
|
|
||||||
|
// Activate the new scenario
|
||||||
|
if (_currentScenario != null)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Debug, $"Current Scenario: {_currentScenario.Name}", this);
|
||||||
|
await _currentScenario.Activate();
|
||||||
|
}
|
||||||
|
|
||||||
|
RoomCombinationScenarioChanged?.Invoke(this, new EventArgs());
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#region IEssentialsRoomCombiner Members
|
#region IEssentialsRoomCombiner Members
|
||||||
|
|
||||||
public event EventHandler<EventArgs> RoomCombinationScenarioChanged;
|
public event EventHandler<EventArgs> RoomCombinationScenarioChanged;
|
||||||
@@ -198,33 +254,6 @@ namespace PepperDash.Essentials.Core
|
|||||||
{
|
{
|
||||||
return _currentScenario;
|
return _currentScenario;
|
||||||
}
|
}
|
||||||
private set
|
|
||||||
{
|
|
||||||
if (value != _currentScenario)
|
|
||||||
{
|
|
||||||
// Deactivate the old scenario first
|
|
||||||
if (_currentScenario != null)
|
|
||||||
{
|
|
||||||
_currentScenario.Deactivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
_currentScenario = value;
|
|
||||||
|
|
||||||
// Activate the new scenario
|
|
||||||
if (_currentScenario != null)
|
|
||||||
{
|
|
||||||
_currentScenario.Activate();
|
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Debug, $"Current Scenario: {_currentScenario.Name}", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
var handler = RoomCombinationScenarioChanged;
|
|
||||||
if (handler != null)
|
|
||||||
{
|
|
||||||
handler(this, new EventArgs());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoolFeedback IsInAutoModeFeedback { get; private set; }
|
public BoolFeedback IsInAutoModeFeedback { get; private set; }
|
||||||
@@ -253,7 +282,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
public void ToggleMode()
|
public void ToggleMode()
|
||||||
{
|
{
|
||||||
if(IsInAutoMode)
|
if (IsInAutoMode)
|
||||||
{
|
{
|
||||||
SetManualMode();
|
SetManualMode();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
|
|
||||||
@@ -87,12 +88,12 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Activates this room combination scenario
|
/// Activates this room combination scenario
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Activate();
|
Task Activate();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deactivates this room combination scenario
|
/// Deactivates this room combination scenario
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Deactivate();
|
Task Deactivate();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The state of the partitions that would activate this scenario
|
/// The state of the partitions that would activate this scenario
|
||||||
|
|||||||
@@ -1,22 +1,16 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Core.Logging;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a room combination scenario
|
/// Represents a room combination scenario
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class RoomCombinationScenario: IRoomCombinationScenario, IKeyName
|
public class RoomCombinationScenario : IRoomCombinationScenario, IKeyName
|
||||||
{
|
{
|
||||||
private RoomCombinationScenarioConfig _config;
|
private RoomCombinationScenarioConfig _config;
|
||||||
|
|
||||||
@@ -40,7 +34,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
get { return _isActive; }
|
get { return _isActive; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if(value == _isActive)
|
if (value == _isActive)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -76,30 +70,36 @@ namespace PepperDash.Essentials.Core
|
|||||||
IsActiveFeedback = new BoolFeedback(() => _isActive);
|
IsActiveFeedback = new BoolFeedback(() => _isActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Activate()
|
public async Task Activate()
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Activating Scenario: '{0}' with {1} action(s) defined", Name, activationActions.Count);
|
this.LogInformation("Activating Scenario {name} with {activationActionCount} action(s) defined", Name, activationActions.Count);
|
||||||
|
|
||||||
|
List<Task> tasks = new List<Task>();
|
||||||
|
|
||||||
if (activationActions != null)
|
if (activationActions != null)
|
||||||
{
|
{
|
||||||
foreach (var action in activationActions)
|
foreach (var action in activationActions)
|
||||||
{
|
{
|
||||||
DeviceJsonApi.DoDeviceAction(action);
|
this.LogInformation("Running Activation action {@action}", action);
|
||||||
|
await DeviceJsonApi.DoDeviceActionAsync(action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IsActive = true;
|
IsActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Deactivate()
|
public async Task Deactivate()
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Deactivating Scenario: '{0}' with {1} action(s) defined", Name, deactivationActions.Count);
|
this.LogInformation("Deactivating Scenario {name} with {deactivationActionCount} action(s) defined", Name, deactivationActions.Count);
|
||||||
|
|
||||||
|
List<Task> tasks = new List<Task>();
|
||||||
|
|
||||||
if (deactivationActions != null)
|
if (deactivationActions != null)
|
||||||
{
|
{
|
||||||
foreach (var action in deactivationActions)
|
foreach (var action in deactivationActions)
|
||||||
{
|
{
|
||||||
DeviceJsonApi.DoDeviceAction(action);
|
this.LogInformation("Running deactivation action {actionDeviceKey}:{actionMethod}", action.DeviceKey, action.MethodName);
|
||||||
|
await DeviceJsonApi.DoDeviceActionAsync(action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ namespace PepperDash.Essentials.Room.Config
|
|||||||
//switch on emergency type here. Right now only contact and shutdown
|
//switch on emergency type here. Right now only contact and shutdown
|
||||||
var e = new EssentialsRoomEmergencyContactClosure(room.Key + "-emergency", props.Emergency, room);
|
var e = new EssentialsRoomEmergencyContactClosure(room.Key + "-emergency", props.Emergency, room);
|
||||||
DeviceManager.AddDevice(e);
|
DeviceManager.AddDevice(e);
|
||||||
|
return e;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
public class EssentialsRoomEmergencyTriggerConfig
|
public class EssentialsRoomEmergencyTriggerConfig
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// contact,
|
/// contact,versiport
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -4,12 +4,16 @@ using PepperDash.Essentials.Room.Config;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
public class EssentialsRoomEmergencyContactClosure : EssentialsRoomEmergencyBase
|
public class EssentialsRoomEmergencyContactClosure : EssentialsRoomEmergencyBase, IEssentialsRoomEmergency
|
||||||
{
|
{
|
||||||
|
public event EventHandler<EventArgs> EmergencyStateChange;
|
||||||
|
|
||||||
IEssentialsRoom Room;
|
IEssentialsRoom Room;
|
||||||
string Behavior;
|
string Behavior;
|
||||||
bool TriggerOnClose;
|
bool TriggerOnClose;
|
||||||
|
|
||||||
|
public bool InEmergency { get; private set; }
|
||||||
|
|
||||||
public EssentialsRoomEmergencyContactClosure(string key, EssentialsRoomEmergencyConfig config, IEssentialsRoom room) :
|
public EssentialsRoomEmergencyContactClosure(string key, EssentialsRoomEmergencyConfig config, IEssentialsRoom room) :
|
||||||
base(key)
|
base(key)
|
||||||
{
|
{
|
||||||
@@ -25,14 +29,49 @@ namespace PepperDash.Essentials.Core
|
|||||||
cs.DigitalInputPorts[portNum].StateChange += EsentialsRoomEmergencyContactClosure_StateChange;
|
cs.DigitalInputPorts[portNum].StateChange += EsentialsRoomEmergencyContactClosure_StateChange;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (config.Trigger.Type.Equals("versiport", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Behavior = config.Behavior;
|
Behavior = config.Behavior;
|
||||||
TriggerOnClose = config.Trigger.TriggerOnClose;
|
TriggerOnClose = config.Trigger.TriggerOnClose;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void EssentialsRoomEmergencyContactClosure_VersiportChange(Versiport port, VersiportEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.Event == eVersiportEvent.DigitalInChange)
|
||||||
|
{
|
||||||
|
ContactClosure_StateChange(port.DigitalIn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EsentialsRoomEmergencyContactClosure_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args)
|
void EsentialsRoomEmergencyContactClosure_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args)
|
||||||
{
|
{
|
||||||
if (args.State && TriggerOnClose || !args.State && !TriggerOnClose)
|
ContactClosure_StateChange(args.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContactClosure_StateChange(bool portState)
|
||||||
|
{
|
||||||
|
if (portState && TriggerOnClose || !portState && !TriggerOnClose)
|
||||||
|
{
|
||||||
|
InEmergency = true;
|
||||||
|
if (EmergencyStateChange != null)
|
||||||
|
EmergencyStateChange(this, new EventArgs());
|
||||||
RunEmergencyBehavior();
|
RunEmergencyBehavior();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InEmergency = false;
|
||||||
|
if (EmergencyStateChange != null)
|
||||||
|
EmergencyStateChange(this, new EventArgs());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -44,4 +83,14 @@ namespace PepperDash.Essentials.Core
|
|||||||
Room.Shutdown();
|
Room.Shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the functionality of a room emergency contact closure
|
||||||
|
/// </summary>
|
||||||
|
public interface IEssentialsRoomEmergency
|
||||||
|
{
|
||||||
|
event EventHandler<EventArgs> EmergencyStateChange;
|
||||||
|
|
||||||
|
bool InEmergency { get; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
using PepperDash.Core;
|
using PepperDash.Essentials.Core.Queues;
|
||||||
|
using PepperDash.Essentials.Core.Routing;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Debug = PepperDash.Core.Debug;
|
||||||
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
@@ -16,6 +19,8 @@ namespace PepperDash.Essentials.Core
|
|||||||
{
|
{
|
||||||
private static readonly Dictionary<string, RouteRequest> RouteRequests = new Dictionary<string, RouteRequest>();
|
private static readonly Dictionary<string, RouteRequest> RouteRequests = new Dictionary<string, RouteRequest>();
|
||||||
|
|
||||||
|
private static readonly GenericQueue routeRequestQueue = new GenericQueue("routingQueue");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets any existing RouteDescriptor for a destination, clears it using ReleaseRoute
|
/// Gets any existing RouteDescriptor for a destination, clears it using ReleaseRoute
|
||||||
/// and then attempts a new Route and if sucessful, stores that RouteDescriptor
|
/// and then attempts a new Route and if sucessful, stores that RouteDescriptor
|
||||||
@@ -23,115 +28,34 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static void ReleaseAndMakeRoute(this IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, string destinationPortKey = "", string sourcePortKey = "")
|
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);
|
||||||
|
|
||||||
var inputPort = string.IsNullOrEmpty(destinationPortKey) ? null : destination.InputPorts.FirstOrDefault(p => p.Key == destinationPortKey);
|
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 outputPort = string.IsNullOrEmpty(sourcePortKey) ? null : source.OutputPorts.FirstOrDefault(p => p.Key == sourcePortKey);
|
||||||
|
|
||||||
ReleaseAndMakeRoute(destination, source, signalType, inputPort, outputPort);
|
ReleaseAndMakeRoute(destination, source, signalType, inputPort, outputPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
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.Verbose, "Destination port is null");
|
|
||||||
if (sourcePort == null) Debug.LogMessage(LogEventLevel.Verbose, "Source port is null");
|
|
||||||
|
|
||||||
var routeRequest = new RouteRequest
|
|
||||||
{
|
|
||||||
Destination = destination,
|
|
||||||
DestinationPort = destinationPort,
|
|
||||||
Source = source,
|
|
||||||
SourcePort = sourcePort,
|
|
||||||
SignalType = signalType
|
|
||||||
};
|
|
||||||
|
|
||||||
var coolingDevice = destination as IWarmingCooling;
|
|
||||||
|
|
||||||
|
|
||||||
//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;
|
|
||||||
|
|
||||||
RouteRequests[destination.Key] = routeRequest;
|
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "Device: {0} is cooling down and already has a routing request stored. Storing new route request to route to source key: {1}", null, destination.Key, routeRequest.Source.Key);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//New Request
|
|
||||||
if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true)
|
|
||||||
{
|
|
||||||
coolingDevice.IsCoolingDownFeedback.OutputChange -= routeRequest.HandleCooldown;
|
|
||||||
|
|
||||||
coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown;
|
|
||||||
|
|
||||||
RouteRequests.Add(destination.Key, routeRequest);
|
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "Device: {0} is cooling down. Storing route request to route to source key: {1}", null, destination.Key, routeRequest.Source.Key);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RouteRequests.ContainsKey(destination.Key) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == false)
|
|
||||||
{
|
|
||||||
RouteRequests.Remove(destination.Key);
|
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "Device: {0} is NOT cooling down. Removing stored route request and routing to source key: {1}", null, destination.Key, routeRequest.Source.Key);
|
|
||||||
}
|
|
||||||
|
|
||||||
destination.ReleaseRoute();
|
|
||||||
|
|
||||||
RunRouteRequest(routeRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void RunRouteRequest(RouteRequest request)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(audioOrSingleRoute);
|
|
||||||
|
|
||||||
if (videoRoute != null)
|
|
||||||
{
|
|
||||||
RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(videoRoute);
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "Executing full route", request.Destination);
|
|
||||||
|
|
||||||
audioOrSingleRoute.ExecuteRoutes();
|
|
||||||
videoRoute?.ExecuteRoutes();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Will release the existing route on the destination, if it is found in
|
|
||||||
/// RouteDescriptorCollection.DefaultCollection
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="destination"></param>
|
|
||||||
public static void ReleaseRoute(this IRoutingInputs destination)
|
public static void ReleaseRoute(this IRoutingInputs destination)
|
||||||
{
|
{
|
||||||
|
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, string.Empty));
|
||||||
|
}
|
||||||
|
|
||||||
if (RouteRequests.TryGetValue(destination.Key, out RouteRequest existingRequest) && destination is IWarmingCooling)
|
public static void ReleaseRoute(this IRoutingInputs destination, string inputPortKey)
|
||||||
{
|
{
|
||||||
var coolingDevice = destination as IWarmingCooling;
|
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, inputPortKey));
|
||||||
|
}
|
||||||
|
|
||||||
coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRequest.HandleCooldown;
|
public static void RemoveRouteRequestForDestination(string destinationKey)
|
||||||
}
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Information, "Removing route request for {destination}", null, destinationKey);
|
||||||
|
|
||||||
RouteRequests.Remove(destination.Key);
|
var result = RouteRequests.Remove(destinationKey);
|
||||||
|
|
||||||
var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination);
|
var messageTemplate = result ? "Route Request for {destination} removed" : "Route Request for {destination} not found";
|
||||||
if (current != null)
|
|
||||||
{
|
Debug.LogMessage(LogEventLevel.Information, messageTemplate, null, destinationKey);
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Releasing current route: {0}", destination, current.Source.Key);
|
|
||||||
current.ReleaseRoutes();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -146,13 +70,14 @@ namespace PepperDash.Essentials.Core
|
|||||||
// if it's a single signal type, find the route
|
// if it's a single signal type, find the route
|
||||||
if (!signalType.HasFlag(eRoutingSignalType.AudioVideo))
|
if (!signalType.HasFlag(eRoutingSignalType.AudioVideo))
|
||||||
{
|
{
|
||||||
var singleTypeRouteDescriptor = new RouteDescriptor(source, destination, signalType);
|
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);
|
Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {sourceKey} of type {type}", destination, source.Key, signalType);
|
||||||
|
|
||||||
if (!destination.GetRouteToSource(source, null, null, signalType, 0, singleTypeRouteDescriptor, destinationPort, sourcePort))
|
if (!destination.GetRouteToSource(source, null, null, signalType, 0, singleTypeRouteDescriptor, destinationPort, sourcePort))
|
||||||
singleTypeRouteDescriptor = null;
|
singleTypeRouteDescriptor = null;
|
||||||
|
|
||||||
foreach (var route in singleTypeRouteDescriptor.Routes)
|
var routes = singleTypeRouteDescriptor?.Routes ?? new List<RouteSwitchDescriptor>();
|
||||||
|
foreach (var route in routes)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "Route for device: {route}", destination, route.ToString());
|
Debug.LogMessage(LogEventLevel.Verbose, "Route for device: {route}", destination, route.ToString());
|
||||||
}
|
}
|
||||||
@@ -163,14 +88,14 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {sourceKey} of type {type}", destination, source.Key);
|
Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {sourceKey} of type {type}", destination, source.Key);
|
||||||
|
|
||||||
var audioRouteDescriptor = new RouteDescriptor(source, destination, eRoutingSignalType.Audio);
|
var audioRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, eRoutingSignalType.Audio);
|
||||||
|
|
||||||
var audioSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Audio, 0, audioRouteDescriptor, destinationPort, sourcePort);
|
var audioSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Audio, 0, audioRouteDescriptor, destinationPort, sourcePort);
|
||||||
|
|
||||||
if (!audioSuccess)
|
if (!audioSuccess)
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Cannot find audio route to {0}", destination, source.Key);
|
Debug.LogMessage(LogEventLevel.Debug, "Cannot find audio route to {0}", destination, source.Key);
|
||||||
|
|
||||||
var videoRouteDescriptor = new RouteDescriptor(source, destination, eRoutingSignalType.Video);
|
var videoRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, eRoutingSignalType.Video);
|
||||||
|
|
||||||
var videoSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Video, 0, videoRouteDescriptor, destinationPort, sourcePort);
|
var videoSuccess = destination.GetRouteToSource(source, null, null, eRoutingSignalType.Video, 0, videoRouteDescriptor, destinationPort, sourcePort);
|
||||||
|
|
||||||
@@ -195,6 +120,126 @@ namespace PepperDash.Essentials.Core
|
|||||||
return (audioRouteDescriptor, videoRouteDescriptor);
|
return (audioRouteDescriptor, videoRouteDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
var routeRequest = new RouteRequest
|
||||||
|
{
|
||||||
|
Destination = destination,
|
||||||
|
DestinationPort = destinationPort,
|
||||||
|
Source = source,
|
||||||
|
SourcePort = sourcePort,
|
||||||
|
SignalType = signalType
|
||||||
|
};
|
||||||
|
|
||||||
|
var coolingDevice = destination as IWarmingCooling;
|
||||||
|
|
||||||
|
//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;
|
||||||
|
|
||||||
|
RouteRequests[destination.Key] = routeRequest;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//New Request
|
||||||
|
if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true)
|
||||||
|
{
|
||||||
|
coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown;
|
||||||
|
|
||||||
|
RouteRequests.Add(destination.Key, routeRequest);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RouteRequests.ContainsKey(destination.Key) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == false)
|
||||||
|
{
|
||||||
|
var handledRequest = RouteRequests[destination.Key];
|
||||||
|
|
||||||
|
coolingDevice.IsCoolingDownFeedback.OutputChange -= handledRequest.HandleCooldown;
|
||||||
|
|
||||||
|
RouteRequests.Remove(destination.Key);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination,destinationPort?.Key ?? string.Empty));
|
||||||
|
|
||||||
|
routeRequestQueue.Enqueue(new RouteRequestQueueItem(RunRouteRequest, routeRequest));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RunRouteRequest(RouteRequest request)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(audioOrSingleRoute);
|
||||||
|
|
||||||
|
if (videoRoute != null)
|
||||||
|
{
|
||||||
|
RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(videoRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.LogMessage(LogEventLevel.Verbose, "Executing full route", request.Destination);
|
||||||
|
|
||||||
|
audioOrSingleRoute.ExecuteRoutes();
|
||||||
|
videoRoute?.ExecuteRoutes();
|
||||||
|
} catch(Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(ex, "Exception Running Route Request {request}", null, request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Will release the existing route on the destination, if it is found in
|
||||||
|
/// RouteDescriptorCollection.DefaultCollection
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="destination"></param>
|
||||||
|
private static void ReleaseRouteInternal(IRoutingInputs destination, string inputPortKey)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Information, "Release route for '{destination}':'{inputPortKey}'", destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
|
||||||
|
|
||||||
|
if (RouteRequests.TryGetValue(destination.Key, out RouteRequest existingRequest) && destination is IWarmingCooling)
|
||||||
|
{
|
||||||
|
var coolingDevice = destination as IWarmingCooling;
|
||||||
|
|
||||||
|
coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRequest.HandleCooldown;
|
||||||
|
}
|
||||||
|
|
||||||
|
RouteRequests.Remove(destination.Key);
|
||||||
|
|
||||||
|
var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination, inputPortKey);
|
||||||
|
if (current != null)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Information, "Releasing current route: {0}", destination, current.Source.Key);
|
||||||
|
current.ReleaseRoutes();
|
||||||
|
}
|
||||||
|
} catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(ex, "Exception releasing route for '{destination}':'{inputPortKey}'",null, destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The recursive part of this. Will stop on each device, search its inputs for the
|
/// 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
|
/// desired source and if not found, invoke this function for the each input port
|
||||||
|
|||||||
@@ -12,30 +12,38 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// Represents an collection of individual route steps between Source and Destination
|
/// Represents an collection of individual route steps between Source and Destination
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class RouteDescriptor
|
public class RouteDescriptor
|
||||||
{
|
{
|
||||||
public IRoutingInputs Destination { get; private set; }
|
public IRoutingInputs Destination { get; private set; }
|
||||||
public IRoutingOutputs Source { get; private set; }
|
|
||||||
public eRoutingSignalType SignalType { get; private set; }
|
public RoutingInputPort InputPort { get; private set; }
|
||||||
public List<RouteSwitchDescriptor> Routes { get; private set; }
|
|
||||||
|
public IRoutingOutputs Source { get; private set; }
|
||||||
|
public eRoutingSignalType SignalType { get; private set; }
|
||||||
|
public List<RouteSwitchDescriptor> Routes { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType)
|
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType) : this(source, destination, null, signalType)
|
||||||
{
|
{
|
||||||
Destination = destination;
|
}
|
||||||
Source = source;
|
|
||||||
SignalType = signalType;
|
|
||||||
Routes = new List<RouteSwitchDescriptor>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, RoutingInputPort inputPort, eRoutingSignalType signalType)
|
||||||
/// Executes all routes described in this collection. Typically called via
|
{
|
||||||
/// extension method IRoutingInputs.ReleaseAndMakeRoute()
|
Destination = destination;
|
||||||
/// </summary>
|
Source = source;
|
||||||
public void ExecuteRoutes()
|
SignalType = signalType;
|
||||||
{
|
InputPort = inputPort;
|
||||||
foreach (var route in Routes)
|
Routes = new List<RouteSwitchDescriptor>();
|
||||||
{
|
}
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "ExecuteRoutes: {0}",null, route.ToString());
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes all routes described in this collection. Typically called via
|
||||||
|
/// extension method IRoutingInputs.ReleaseAndMakeRoute()
|
||||||
|
/// </summary>
|
||||||
|
public void ExecuteRoutes()
|
||||||
|
{
|
||||||
|
foreach (var route in Routes)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Verbose, "ExecuteRoutes: {0}", null, route.ToString());
|
||||||
|
|
||||||
if (route.SwitchingDevice is IRoutingSinkWithSwitching sink)
|
if (route.SwitchingDevice is IRoutingSinkWithSwitching sink)
|
||||||
{
|
{
|
||||||
@@ -51,33 +59,43 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Releases all routes in this collection. Typically called via
|
/// Releases all routes in this collection. Typically called via
|
||||||
/// extension method IRoutingInputs.ReleaseAndMakeRoute()
|
/// extension method IRoutingInputs.ReleaseAndMakeRoute()
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ReleaseRoutes()
|
public void ReleaseRoutes()
|
||||||
{
|
{
|
||||||
foreach (var route in Routes)
|
foreach (var route in Routes.Where(r => r.SwitchingDevice is IRouting))
|
||||||
{
|
{
|
||||||
if (route.SwitchingDevice is IRouting)
|
if (route.SwitchingDevice is IRouting switchingDevice)
|
||||||
{
|
{
|
||||||
// Pull the route from the port. Whatever is watching the output's in use tracker is
|
if (route.OutputPort == null)
|
||||||
// responsible for responding appropriately.
|
{
|
||||||
route.OutputPort.InUseTracker.RemoveUser(Destination, "destination-" + SignalType);
|
continue;
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "Port {0} releasing. Count={1}",null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
if (route.OutputPort.InUseTracker != null)
|
||||||
{
|
{
|
||||||
var routesText = Routes.Select(r => r.ToString()).ToArray();
|
route.OutputPort.InUseTracker.RemoveUser(Destination, "destination-" + SignalType);
|
||||||
return string.Format("Route table from {0} to {1}:\r{2}", Source.Key, Destination.Key, string.Join("\r", routesText));
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*/// <summary>
|
/*/// <summary>
|
||||||
/// Represents an collection of individual route steps between Source and Destination
|
/// Represents an collection of individual route steps between Source and Destination
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using PepperDash.Core;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
using PepperDash.Core;
|
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
@@ -33,10 +32,16 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// <param name="descriptor"></param>
|
/// <param name="descriptor"></param>
|
||||||
public void AddRouteDescriptor(RouteDescriptor descriptor)
|
public void AddRouteDescriptor(RouteDescriptor descriptor)
|
||||||
{
|
{
|
||||||
if (RouteDescriptors.Any(t => t.Destination == descriptor.Destination))
|
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,
|
Debug.LogMessage(LogEventLevel.Debug, descriptor.Destination,
|
||||||
"Route to [{0}] already exists in global routes table", descriptor.Source.Key);
|
"Route to [{0}] already exists in global routes table", descriptor?.Source?.Key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RouteDescriptors.Add(descriptor);
|
RouteDescriptors.Add(descriptor);
|
||||||
@@ -48,18 +53,33 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// <returns>null if no RouteDescriptor for a destination exists</returns>
|
/// <returns>null if no RouteDescriptor for a destination exists</returns>
|
||||||
public RouteDescriptor GetRouteDescriptorForDestination(IRoutingInputs destination)
|
public RouteDescriptor GetRouteDescriptorForDestination(IRoutingInputs destination)
|
||||||
{
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Information, "Getting route descriptor for '{destination}'", destination?.Key ?? null);
|
||||||
|
|
||||||
return RouteDescriptors.FirstOrDefault(rd => rd.Destination == destination);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the RouteDescriptor for a given destination AND removes it from collection.
|
/// Returns the RouteDescriptor for a given destination AND removes it from collection.
|
||||||
/// Returns null if no route with the provided destination exists.
|
/// Returns null if no route with the provided destination exists.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public RouteDescriptor RemoveRouteDescriptor(IRoutingInputs destination)
|
public RouteDescriptor RemoveRouteDescriptor(IRoutingInputs destination, string inputPortKey = "")
|
||||||
{
|
{
|
||||||
var descr = GetRouteDescriptorForDestination(destination);
|
Debug.LogMessage(LogEventLevel.Information, "Removing route descriptor for '{destination}':'{inputPortKey}'", destination.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
|
||||||
|
|
||||||
|
var descr = string.IsNullOrEmpty(inputPortKey)
|
||||||
|
? GetRouteDescriptorForDestination(destination)
|
||||||
|
: GetRouteDescriptorForDestinationAndInputPort(destination, inputPortKey);
|
||||||
if (descr != null)
|
if (descr != null)
|
||||||
RouteDescriptors.Remove(descr);
|
RouteDescriptors.Remove(descr);
|
||||||
|
|
||||||
|
Debug.LogMessage(LogEventLevel.Information, "Found route descriptor {routeDescriptor}", destination, descr);
|
||||||
|
|
||||||
return descr;
|
return descr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
namespace PepperDash.Essentials.Core
|
using PepperDash.Core;
|
||||||
|
using Serilog.Events;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
public class RouteRequest
|
public class RouteRequest
|
||||||
{
|
{
|
||||||
@@ -11,37 +15,33 @@
|
|||||||
|
|
||||||
public void HandleCooldown(object sender, FeedbackEventArgs args)
|
public void HandleCooldown(object sender, FeedbackEventArgs args)
|
||||||
{
|
{
|
||||||
var coolingDevice = sender as IWarmingCooling;
|
try
|
||||||
|
|
||||||
if (args.BoolValue == false)
|
|
||||||
{
|
{
|
||||||
Destination.ReleaseAndMakeRoute(Source, SignalType);
|
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 (sender == null) return;
|
if (args.BoolValue == true)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
coolingDevice.IsCoolingDownFeedback.OutputChange -= HandleCooldown;
|
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);
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(ex, "Exception handling cooldown", Destination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"Route {Source?.Key ?? "No Source Device"}:{SourcePort?.Key ?? "auto"} to {Destination?.Key ?? "No Destination Device"}:{DestinationPort?.Key ?? "auto"}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*public class RouteRequest<TInputSelector, TOutputSelector>
|
|
||||||
{
|
|
||||||
public IRoutingSink<TInputSelector> Destination { get; set; }
|
|
||||||
public IRoutingOutputs<TOutputSelector> Source { get; set; }
|
|
||||||
public eRoutingSignalType SignalType { get; set; }
|
|
||||||
|
|
||||||
public void HandleCooldown(object sender, FeedbackEventArgs args)
|
|
||||||
{
|
|
||||||
var coolingDevice = sender as IWarmingCooling;
|
|
||||||
|
|
||||||
if (args.BoolValue == false)
|
|
||||||
{
|
|
||||||
Destination.ReleaseAndMakeRoute(Source, SignalType);
|
|
||||||
|
|
||||||
if (sender == null) return;
|
|
||||||
|
|
||||||
coolingDevice.IsCoolingDownFeedback.OutputChange -= HandleCooldown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core.Queues;
|
||||||
|
using System;
|
||||||
|
using Serilog.Events;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.Routing
|
||||||
|
{
|
||||||
|
public class RouteRequestQueueItem : IQueueMessage
|
||||||
|
{
|
||||||
|
private readonly Action<RouteRequest> action;
|
||||||
|
private readonly RouteRequest routeRequest;
|
||||||
|
|
||||||
|
public RouteRequestQueueItem(Action<RouteRequest> routeAction, RouteRequest request)
|
||||||
|
{
|
||||||
|
action = routeAction;
|
||||||
|
routeRequest = request;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispatch()
|
||||||
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Information, "Dispatching route request {routeRequest}", null, routeRequest);
|
||||||
|
action(routeRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ReleaseRouteQueueItem : IQueueMessage
|
||||||
|
{
|
||||||
|
private readonly Action<IRoutingInputs, string> action;
|
||||||
|
private readonly IRoutingInputs destination;
|
||||||
|
private readonly string inputPortKey;
|
||||||
|
|
||||||
|
public ReleaseRouteQueueItem(Action<IRoutingInputs, string> action, IRoutingInputs destination, string inputPortKey)
|
||||||
|
{
|
||||||
|
this.action = action;
|
||||||
|
this.destination = destination;
|
||||||
|
this.inputPortKey = inputPortKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class RouteSwitchDescriptor
|
public class RouteSwitchDescriptor
|
||||||
{
|
{
|
||||||
public IRoutingInputs SwitchingDevice { get { return InputPort.ParentDevice; } }
|
public IRoutingInputs SwitchingDevice { get { return InputPort?.ParentDevice; } }
|
||||||
public RoutingOutputPort OutputPort { get; set; }
|
public RoutingOutputPort OutputPort { get; set; }
|
||||||
public RoutingInputPort InputPort { get; set; }
|
public RoutingInputPort InputPort { get; set; }
|
||||||
|
|
||||||
@@ -23,9 +23,9 @@
|
|||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
if (SwitchingDevice is IRouting)
|
if (SwitchingDevice is IRouting)
|
||||||
return $"{SwitchingDevice?.Key} switches output {OutputPort.Key} to input {InputPort.Key}";
|
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
|
else
|
||||||
return $"{SwitchingDevice.Key} switches to input {InputPort.Key}";
|
return $"{(SwitchingDevice != null ? SwitchingDevice.Key : "No Device")} switches to input {(InputPort != null ? InputPort.Key : "No input port")}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
|
|
||||||
private void UpdateDestination(IRoutingSinkWithSwitching destination, RoutingInputPort inputPort)
|
private void UpdateDestination(IRoutingSinkWithSwitching destination, RoutingInputPort inputPort)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Updating destination {destination} with inputPort {inputPort}", this,destination?.Key, inputPort?.Key);
|
// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Updating destination {destination} with inputPort {inputPort}", this,destination?.Key, inputPort?.Key);
|
||||||
|
|
||||||
if(inputPort == null)
|
if(inputPort == null)
|
||||||
{
|
{
|
||||||
@@ -101,7 +101,7 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
return;
|
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;
|
TieLine sourceTieLine;
|
||||||
try
|
try
|
||||||
@@ -128,7 +128,7 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root TieLine {tieLine}", this, sourceTieLine);
|
// 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.
|
// Does not handle combinable scenarios or other scenarios where a display might be part of multiple rooms yet.
|
||||||
var room = DeviceManager.AllDevices.OfType<IEssentialsRoom>().FirstOrDefault((r) => {
|
var room = DeviceManager.AllDevices.OfType<IEssentialsRoom>().FirstOrDefault((r) => {
|
||||||
@@ -151,7 +151,7 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found room {room} for destination {destination}", this, room.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);
|
var sourceList = ConfigReader.ConfigObject.GetSourceListForKey(room.SourceListKey);
|
||||||
|
|
||||||
@@ -161,20 +161,21 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found sourceList for room {room}", this, room.Key);
|
// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found sourceList for room {room}", this, room.Key);
|
||||||
|
|
||||||
var sourceListItem = sourceList.FirstOrDefault(sli => {
|
var sourceListItem = sourceList.FirstOrDefault(sli => {
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose,
|
//// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose,
|
||||||
"SourceListItem {sourceListItem}:{sourceKey} tieLine sourceport device key {sourcePortDeviceKey}",
|
// "SourceListItem {sourceListItem}:{sourceKey} tieLine sourceport device key {sourcePortDeviceKey}",
|
||||||
this,
|
// this,
|
||||||
sli.Key,
|
// sli.Key,
|
||||||
sli.Value.SourceKey,
|
// sli.Value.SourceKey,
|
||||||
sourceTieLine.SourcePort.ParentDevice.Key);
|
// sourceTieLine.SourcePort.ParentDevice.Key);
|
||||||
|
|
||||||
return sli.Value.SourceKey.Equals(sourceTieLine.SourcePort.ParentDevice.Key,StringComparison.InvariantCultureIgnoreCase);
|
return sli.Value.SourceKey.Equals(sourceTieLine.SourcePort.ParentDevice.Key,StringComparison.InvariantCultureIgnoreCase);
|
||||||
});
|
});
|
||||||
|
|
||||||
var source = sourceListItem.Value;
|
var source = sourceListItem.Value;
|
||||||
|
var sourceKey = sourceListItem.Key;
|
||||||
|
|
||||||
if (source == null)
|
if (source == null)
|
||||||
{
|
{
|
||||||
@@ -186,15 +187,16 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
Name = sourceTieLine.SourcePort.Key,
|
Name = sourceTieLine.SourcePort.Key,
|
||||||
};
|
};
|
||||||
|
|
||||||
destination.CurrentSourceInfo = tempSourceListItem; ;
|
|
||||||
destination.CurrentSourceInfoKey = "$transient";
|
destination.CurrentSourceInfoKey = "$transient";
|
||||||
|
destination.CurrentSourceInfo = tempSourceListItem;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Got Source {source}", this, source);
|
//Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Got Source {@source} with key {sourceKey}", this, source, sourceKey);
|
||||||
|
|
||||||
|
destination.CurrentSourceInfoKey = sourceKey;
|
||||||
destination.CurrentSourceInfo = source;
|
destination.CurrentSourceInfo = source;
|
||||||
destination.CurrentSourceInfoKey = source.SourceKey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private TieLine GetRootTieLine(TieLine tieLine)
|
private TieLine GetRootTieLine(TieLine tieLine)
|
||||||
@@ -202,11 +204,11 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
TieLine nextTieLine = null;
|
TieLine nextTieLine = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "**Following tieLine {tieLine}**", this, tieLine);
|
//Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "**Following tieLine {tieLine}**", this, tieLine);
|
||||||
|
|
||||||
if (tieLine.SourcePort.ParentDevice is IRoutingWithFeedback midpoint)
|
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, "TieLine Source device {sourceDevice} is midpoint", this, midpoint);
|
||||||
|
|
||||||
if(midpoint.CurrentRoutes == null || midpoint.CurrentRoutes.Count == 0)
|
if(midpoint.CurrentRoutes == null || midpoint.CurrentRoutes.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -215,9 +217,9 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
}
|
}
|
||||||
|
|
||||||
var currentRoute = midpoint.CurrentRoutes.FirstOrDefault(route => {
|
var currentRoute = midpoint.CurrentRoutes.FirstOrDefault(route => {
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Checking {route} against {tieLine}", this, route, tieLine);
|
//Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Checking {route} against {tieLine}", this, route, tieLine);
|
||||||
|
|
||||||
return route.OutputPort.Key == tieLine.SourcePort.Key && route.OutputPort.ParentDevice.Key == tieLine.SourcePort.ParentDevice.Key;
|
return route.OutputPort != null && route.InputPort != null && route.OutputPort?.Key == tieLine.SourcePort.Key && route.OutputPort?.ParentDevice.Key == tieLine.SourcePort.ParentDevice.Key;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (currentRoute == null)
|
if (currentRoute == null)
|
||||||
@@ -226,28 +228,28 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found currentRoute {currentRoute} through {midpoint}", this, currentRoute, midpoint);
|
//Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found currentRoute {currentRoute} through {midpoint}", this, currentRoute, midpoint);
|
||||||
|
|
||||||
nextTieLine = TieLineCollection.Default.FirstOrDefault(tl => {
|
nextTieLine = TieLineCollection.Default.FirstOrDefault(tl => {
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Checking {route} against {tieLine}", tl.DestinationPort.Key, currentRoute.InputPort.Key);
|
//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; });
|
return tl.DestinationPort.Key == currentRoute.InputPort.Key && tl.DestinationPort.ParentDevice.Key == currentRoute.InputPort.ParentDevice.Key; });
|
||||||
|
|
||||||
if (nextTieLine != null)
|
if (nextTieLine != null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found next tieLine {tieLine}. Walking the chain", this, nextTieLine);
|
//Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found next tieLine {tieLine}. Walking the chain", this, nextTieLine);
|
||||||
return GetRootTieLine(nextTieLine);
|
return GetRootTieLine(nextTieLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root tieLine {tieLine}", this,nextTieLine);
|
//Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root tieLine {tieLine}", this,nextTieLine);
|
||||||
return 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 {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));
|
//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
|
if (tieLine.SourcePort.ParentDevice is IRoutingSource || tieLine.SourcePort.ParentDevice is IRoutingOutputs) //end of the chain
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root: {tieLine}", this, tieLine);
|
// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Found root: {tieLine}", this, tieLine);
|
||||||
return tieLine;
|
return tieLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,6 @@ using PepperDash.Essentials.Core.Config;
|
|||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.Generic
|
namespace PepperDash.Essentials.Devices.Common.Generic
|
||||||
{
|
{
|
||||||
@@ -16,10 +13,9 @@ namespace PepperDash.Essentials.Devices.Common.Generic
|
|||||||
{
|
{
|
||||||
InputPorts = new RoutingPortCollection<RoutingInputPort>();
|
InputPorts = new RoutingPortCollection<RoutingInputPort>();
|
||||||
|
|
||||||
var inputPort = new RoutingInputPort($"{Key}-{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<RoutingInputPort> InputPorts { get; private set; }
|
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
|
||||||
@@ -57,8 +53,8 @@ namespace PepperDash.Essentials.Devices.Common.Generic
|
|||||||
|
|
||||||
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Source Device");
|
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Sink Device");
|
||||||
return new GenericSource(dc.Key, dc.Name);
|
return new GenericSink(dc.Key, dc.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.20.66" />
|
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.20.66" />
|
||||||
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-424" />
|
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-451" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -28,14 +28,14 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
|
|||||||
|
|
||||||
for(var i = 1; i <= props.OutputCount; i++)
|
for(var i = 1; i <= props.OutputCount; i++)
|
||||||
{
|
{
|
||||||
var outputPort = new RoutingOutputPort($"{Key}-output{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, null, this);
|
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++)
|
for(var i = 1; i<= props.ContentInputCount; i++)
|
||||||
{
|
{
|
||||||
var inputPort = new RoutingInputPort($"{Key}-contentInput{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, $"contentInput{i}", this);
|
var inputPort = new RoutingInputPort($"contentInput{i}", eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, $"contentInput{i}", this);
|
||||||
|
|
||||||
InputPorts.Add(inputPort);
|
InputPorts.Add(inputPort);
|
||||||
}
|
}
|
||||||
@@ -47,7 +47,7 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
|
|||||||
|
|
||||||
for(var i = 1; i <=props.CameraInputCount; i++)
|
for(var i = 1; i <=props.CameraInputCount; i++)
|
||||||
{
|
{
|
||||||
var cameraPort = new RoutingInputPort($"{Key}-cameraInput{i}", eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, $"cameraInput{i}", this);
|
var cameraPort = new RoutingInputPort($"cameraInput{i}", eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, $"cameraInput{i}", this);
|
||||||
|
|
||||||
InputPorts.Add(cameraPort);
|
InputPorts.Add(cameraPort);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace PepperDash.Essentials.Devices.Common
|
|||||||
|
|
||||||
public void PrintExpectedIrCommands()
|
public void PrintExpectedIrCommands()
|
||||||
{
|
{
|
||||||
var cmds = typeof (AppleTvIrCommands).GetType().GetFields(BindingFlags.Public | BindingFlags.Static);
|
var cmds = typeof (AppleTvIrCommands).GetFields(BindingFlags.Public | BindingFlags.Static);
|
||||||
|
|
||||||
foreach (var value in cmds.Select(cmd => cmd.GetValue(null)).OfType<string>())
|
foreach (var value in cmds.Select(cmd => cmd.GetValue(null)).OfType<string>())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1214,7 +1214,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
|
|||||||
var entryIndex = counterIndex;
|
var entryIndex = counterIndex;
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "Entry{2:0000} Name: {0}, Folder ID: {1}, Type: {3}, ParentFolderId: {4}",
|
Debug.LogMessage(LogEventLevel.Verbose, this, "Entry{2:0000} Name: {0}, Folder ID: {1}, Type: {3}, ParentFolderId: {4}",
|
||||||
entry.Name, entry.FolderId, entryIndex, entry.GetType().GetType().FullName, entry.ParentFolderId);
|
entry.Name, entry.FolderId, entryIndex, entry.GetType().FullName, entry.ParentFolderId);
|
||||||
|
|
||||||
if (entry is DirectoryFolder)
|
if (entry is DirectoryFolder)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<RootNamespace>PepperDash.Essentials</RootNamespace>
|
<RootNamespace>PepperDash.Essentials</RootNamespace>
|
||||||
<AssemblyName>PepperDashEssentials</AssemblyName>
|
<AssemblyName>PepperDashEssentials</AssemblyName>
|
||||||
<TargetFrameworks>net472;net6</TargetFrameworks>
|
<TargetFrameworks>net472</TargetFrameworks>
|
||||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||||
<Title>PepperDash Essentials</Title>
|
<Title>PepperDash Essentials</Title>
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Crestron.SimplSharp.SDK.Program" Version="2.20.66" />
|
<PackageReference Include="Crestron.SimplSharp.SDK.Program" Version="2.20.66" />
|
||||||
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-424" />
|
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-451" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj" />
|
<ProjectReference Include="..\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj" />
|
||||||
|
|||||||
Reference in New Issue
Block a user