mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-08 17:24:47 +00:00
Compare commits
217 Commits
copilot/fi
...
v2.24.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4fa7a42330 | ||
|
|
9bad3ae21b | ||
|
|
3fb30d5561 | ||
|
|
57cd77f019 | ||
|
|
7f2bb078c8 | ||
|
|
316bb849b4 | ||
|
|
a983e2c87f | ||
|
|
babb9a77df | ||
|
|
7629921113 | ||
|
|
3878c85a7a | ||
|
|
7ad8218af0 | ||
|
|
0c4aec14d1 | ||
|
|
7d3f871460 | ||
|
|
78c9381108 | ||
|
|
a7ff2e8903 | ||
|
|
ae0b2fe086 | ||
|
|
bd11c827da | ||
|
|
7ea1efbabf | ||
|
|
9d6aaa2a0e | ||
|
|
53e7a30224 | ||
|
|
39c1f60a4d | ||
|
|
2cc37a4e40 | ||
|
|
076e5dfa9d | ||
|
|
092896bb25 | ||
|
|
7c8f0586e6 | ||
|
|
c5b0872a4c | ||
|
|
a7b88ec38d | ||
|
|
210b398a13 | ||
|
|
bce1e3610e | ||
|
|
6a33e7c99d | ||
|
|
2048e3f65d | ||
|
|
81df2738de | ||
|
|
08fbec416f | ||
|
|
7594b22096 | ||
|
|
d1babf6b9b | ||
|
|
2187c9fb0d | ||
|
|
a5e6059160 | ||
|
|
9ef4aedcce | ||
|
|
f7c7160bf0 | ||
|
|
dbf5740841 | ||
|
|
c07e099a79 | ||
|
|
06cb508f3a | ||
|
|
e93b5b34cc | ||
|
|
4f5d4ef87a | ||
|
|
636da8cc8c | ||
|
|
5de1e2d7bb | ||
|
|
03bbb84894 | ||
|
|
d17394cdd7 | ||
|
|
8467afde38 | ||
|
|
5c016fb4b8 | ||
|
|
2fbc32947c | ||
|
|
c06b57a5f9 | ||
|
|
6d64fffc50 | ||
|
|
0c4ebdaf1d | ||
|
|
2c49fb9321 | ||
|
|
c55de61da9 | ||
|
|
42444ede0a | ||
|
|
3d50f5f5ac | ||
|
|
11d62aebe1 | ||
|
|
edc10a9c2a | ||
|
|
9be5823956 | ||
|
|
35371dde22 | ||
|
|
d3ceb4d7e7 | ||
|
|
a782b57100 | ||
|
|
1360de599f | ||
|
|
fd95f5fed1 | ||
|
|
9426dff5df | ||
|
|
0d083e63c6 | ||
|
|
6ed7c96ec7 | ||
|
|
314570d6c3 | ||
|
|
ff609dfecd | ||
|
|
666be5ae59 | ||
|
|
bfc9b7e7fa | ||
|
|
b02e952765 | ||
|
|
72861a5097 | ||
|
|
44ed067f4d | ||
|
|
faa2169baf | ||
|
|
fd40b0c6d1 | ||
|
|
afcddad1cc | ||
|
|
c4cf8f13e9 | ||
|
|
c852f87a27 | ||
|
|
071174fa7d | ||
|
|
da0f28a10c | ||
|
|
0538a304ed | ||
|
|
705c5db237 | ||
|
|
2e95f5337e | ||
|
|
ba576180a7 | ||
|
|
92c9db8237 | ||
|
|
c4d064965f | ||
|
|
f27965ac29 | ||
|
|
3ce282e2db | ||
|
|
32a332a6e2 | ||
|
|
151a90c9be | ||
|
|
89e893b3b7 | ||
|
|
d01eb03890 | ||
|
|
16c92afabb | ||
|
|
dff5d2d32e | ||
|
|
317bde3814 | ||
|
|
8bab3dc966 | ||
|
|
514ac850ca | ||
|
|
44432f7a41 | ||
|
|
99253b30c2 | ||
|
|
bf248fe33e | ||
|
|
2f44040e4f | ||
|
|
10399a1be8 | ||
|
|
5409db193c | ||
|
|
f1ce54a524 | ||
|
|
7c72a0d905 | ||
|
|
5d5e78629e | ||
|
|
dab5484d6e | ||
|
|
5c35a3be45 | ||
|
|
6cb98e12fa | ||
|
|
608601990b | ||
|
|
3e0f318f7f | ||
|
|
98d0cc8fdc | ||
|
|
c557c6cdd6 | ||
|
|
8525134ae7 | ||
|
|
1197b15a33 | ||
|
|
ea6a7568fc | ||
|
|
3a2a059ce1 | ||
|
|
f9d9df9d5c | ||
|
|
c284c4275f | ||
|
|
0418f8a7cc | ||
|
|
a5d409e93a | ||
|
|
59944c0e2f | ||
|
|
419177ccd5 | ||
|
|
bd01e2bacc | ||
|
|
2928c5cf94 | ||
|
|
82b5dc96c1 | ||
|
|
37cea8a11c | ||
|
|
a3f0901fa0 | ||
|
|
f91f435768 | ||
|
|
5120b2b574 | ||
|
|
7c90027578 | ||
|
|
bb694b4200 | ||
|
|
087d0a1149 | ||
|
|
4747c16b02 | ||
|
|
aa4d241dde | ||
|
|
9fc5586531 | ||
|
|
d33fd56529 | ||
|
|
8fc4d21f02 | ||
|
|
6d93662b31 | ||
|
|
11b190e76f | ||
|
|
df03a71cbc | ||
|
|
72e67a1c4c | ||
|
|
f8728b6825 | ||
|
|
d9ef8a2289 | ||
|
|
278408a3bc | ||
|
|
fd70377c7f | ||
|
|
06341b14f3 | ||
|
|
d7f9c74b2f | ||
|
|
5921b5dbb0 | ||
|
|
ba0de5128f | ||
|
|
b0a090062f | ||
|
|
9c0cab8218 | ||
|
|
c0af637108 | ||
|
|
9c9eaea928 | ||
|
|
9de94bd65f | ||
|
|
ff46fb8f29 | ||
|
|
d9243def30 | ||
|
|
258699fbcd | ||
|
|
738504e9fc | ||
|
|
cae1bbd6e6 | ||
|
|
dea4407e3e | ||
|
|
ab08a546f7 | ||
|
|
ef98d47792 | ||
|
|
c05976ee60 | ||
|
|
4ca1031bef | ||
|
|
6d61c4525e | ||
|
|
3db274ace5 | ||
|
|
f0f708294c | ||
|
|
a00d186c62 | ||
|
|
51da668dfd | ||
|
|
d2b7400039 | ||
|
|
2424838b7f | ||
|
|
9556edc064 | ||
|
|
f9088691fd | ||
|
|
e40b6a8b4c | ||
|
|
c3b39a87da | ||
|
|
06dc0e947e | ||
|
|
147997f460 | ||
|
|
49abec5eea | ||
|
|
6830efe42a | ||
|
|
d013068a0c | ||
|
|
52916d29f4 | ||
|
|
19e8489166 | ||
|
|
fe33443b25 | ||
|
|
8cf195b262 | ||
|
|
40406b797d | ||
|
|
65bc408ebf | ||
|
|
9d49fb8357 | ||
|
|
fb7797dac7 | ||
|
|
574f5f6dc9 | ||
|
|
e49c69a12f | ||
|
|
7889cba196 | ||
|
|
033aa1f3dd | ||
|
|
4f0d464ba4 | ||
|
|
0107422507 | ||
|
|
1a366790e7 | ||
|
|
bb4b2f88b6 | ||
|
|
a41aba1904 | ||
|
|
b47f1d6b77 | ||
|
|
fda4a5a816 | ||
|
|
9f70e3c721 | ||
|
|
ec6aeb17f6 | ||
|
|
91dc655103 | ||
|
|
bf31fb10eb | ||
|
|
5e21bad596 | ||
|
|
2368f0c8cc | ||
|
|
be58a0bc29 | ||
|
|
8406f69e0d | ||
|
|
116d83394a | ||
|
|
9b8e452eb4 | ||
|
|
c9d86bd5dd | ||
|
|
b2b257020f | ||
|
|
6f58e18d14 | ||
|
|
60fc0298ec |
13
.config/dotnet-tools.json
Normal file
13
.config/dotnet-tools.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {
|
||||||
|
"csharpier": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"commands": [
|
||||||
|
"csharpier"
|
||||||
|
],
|
||||||
|
"rollForward": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -395,3 +395,5 @@ essentials-framework/Essentials Interfaces/PepperDash_Essentials_Interfaces/Pepp
|
|||||||
_site/
|
_site/
|
||||||
api/
|
api/
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
|
/._PepperDash.Essentials.4Series.sln
|
||||||
|
dotnet
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>2.12.1-local</Version>
|
<Version>2.19.4-local</Version>
|
||||||
<InformationalVersion>$(Version)</InformationalVersion>
|
<InformationalVersion>$(Version)</InformationalVersion>
|
||||||
<Authors>PepperDash Technology</Authors>
|
<Authors>PepperDash Technology</Authors>
|
||||||
<Company>PepperDash Technology</Company>
|
<Company>PepperDash Technology</Company>
|
||||||
|
|||||||
@@ -23,23 +23,32 @@
|
|||||||
<FileName>$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cpz</FileName>
|
<FileName>$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cpz</FileName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<Target Name="DeleteCLZ" BeforeTargets="PreBuildEvent" Condition="$(ProjectType) == 'Library' And $(TargetDir) != '' And Exists($(FileName))">
|
<Target Name="DeleteCLZ" BeforeTargets="CoreBuild" Condition="$(ProjectType) == 'Library' And $(TargetDir) != ''">
|
||||||
<Delete Files="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).clz">
|
<ItemGroup>
|
||||||
|
<OldCLZFiles Include="$(TargetDir)$(TargetName).*.$(TargetFramework).clz" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Delete Files="@(OldCLZFiles)" Condition="@(OldCLZFiles) != ''">
|
||||||
<Output TaskParameter="DeletedFiles" ItemName="DeletedList"/>
|
<Output TaskParameter="DeletedFiles" ItemName="DeletedList"/>
|
||||||
</Delete>
|
</Delete>
|
||||||
<Message Text="Deleted files: '@(DeletedList)'" />
|
<Message Text="Deleted old CLZ files: '@(DeletedList)'" Condition="@(DeletedList) != ''" />
|
||||||
</Target>
|
</Target>
|
||||||
<Target Name="DeleteCPZ" BeforeTargets="PreBuildEvent" Condition="$(ProjectType) == 'Program' And $(TargetDir) != '' And Exists($(FileName))">
|
<Target Name="DeleteCPZ" BeforeTargets="CoreBuild" Condition="$(ProjectType) == 'Program' And $(TargetDir) != ''">
|
||||||
<Delete Files="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cpz">
|
<ItemGroup>
|
||||||
|
<OldCPZFiles Include="$(TargetDir)$(TargetName).*.$(TargetFramework).cpz" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Delete Files="@(OldCPZFiles)" Condition="@(OldCPZFiles) != ''">
|
||||||
<Output TaskParameter="DeletedFiles" ItemName="DeletedList"/>
|
<Output TaskParameter="DeletedFiles" ItemName="DeletedList"/>
|
||||||
</Delete>
|
</Delete>
|
||||||
<Message Text="Deleted files: '@(DeletedList)'" />
|
<Message Text="Deleted old CPZ files: '@(DeletedList)'" Condition="@(DeletedList) != ''" />
|
||||||
</Target>
|
</Target>
|
||||||
<Target Name="DeleteCPLZ" BeforeTargets="PreBuildEvent" Condition="$(ProjectType) == 'ProgramLibrary' And $(TargetDir) != '' And Exists($(FileName))">
|
<Target Name="DeleteCPLZ" BeforeTargets="CoreBuild" Condition="$(ProjectType) == 'ProgramLibrary' And $(TargetDir) != ''">
|
||||||
<Delete Files="$(TargetDir)$(TargetName).$(Version).$(TargetFramework).cplz">
|
<ItemGroup>
|
||||||
|
<OldCPLZFiles Include="$(TargetDir)$(TargetName).*.$(TargetFramework).cplz" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Delete Files="@(OldCPLZFiles)" Condition="@(OldCPLZFiles) != ''">
|
||||||
<Output TaskParameter="DeletedFiles" ItemName="DeletedList"/>
|
<Output TaskParameter="DeletedFiles" ItemName="DeletedList"/>
|
||||||
</Delete>
|
</Delete>
|
||||||
<Message Text="Deleted files: '@(DeletedList)'" />
|
<Message Text="Deleted old CPLZ files: '@(DeletedList)'" Condition="@(DeletedList) != ''" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="CreateCPLZ" AfterTargets="Build" Condition="$(ProjectType) == 'ProgramLibrary' And $(TargetDir) != ''" DependsOnTargets="DeleteCPLZ">
|
<Target Name="CreateCPLZ" AfterTargets="Build" Condition="$(ProjectType) == 'ProgramLibrary' And $(TargetDir) != ''" DependsOnTargets="DeleteCPLZ">
|
||||||
|
|||||||
43
src/PepperDash.Core/ComTextHelper.cs
Normal file
43
src/PepperDash.Core/ComTextHelper.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace PepperDash.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Helper class for formatting communication text and byte data for debugging purposes.
|
||||||
|
/// </summary>
|
||||||
|
public class ComTextHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets escaped text for a byte array
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bytes"></param>
|
||||||
|
/// <returns>string with all bytes escaped</returns>
|
||||||
|
public static string GetEscapedText(byte[] bytes)
|
||||||
|
{
|
||||||
|
return string.Concat(bytes.Select(b => string.Format(@"[{0:X2}]", (int)b)).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets escaped text for a string
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text"></param>
|
||||||
|
/// <returns>string with all bytes escaped</returns>
|
||||||
|
public static string GetEscapedText(string text)
|
||||||
|
{
|
||||||
|
var bytes = Encoding.GetEncoding(28591).GetBytes(text);
|
||||||
|
return string.Concat(bytes.Select(b => string.Format(@"[{0:X2}]", (int)b)).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets debug text for a string
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text"></param>
|
||||||
|
/// <returns>string with all non-printable characters escaped</returns>
|
||||||
|
public static string GetDebugText(string text)
|
||||||
|
{
|
||||||
|
return Regex.Replace(text, @"[^\u0020-\u007E]", a => GetEscapedText(a.Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
@@ -37,14 +36,14 @@ namespace PepperDash.Core
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _DebugTimeoutInMs/60000;
|
return _DebugTimeoutInMs / 60000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the RxStreamDebuggingIsEnabled
|
/// Gets or sets the RxStreamDebuggingIsEnabled
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool RxStreamDebuggingIsEnabled{ get; private set; }
|
public bool RxStreamDebuggingIsEnabled { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates that transmit stream debugging is enabled
|
/// Indicates that transmit stream debugging is enabled
|
||||||
@@ -108,7 +107,7 @@ namespace PepperDash.Core
|
|||||||
TxStreamDebuggingIsEnabled = true;
|
TxStreamDebuggingIsEnabled = true;
|
||||||
|
|
||||||
Debug.SetDeviceDebugSettings(ParentDeviceKey, setting);
|
Debug.SetDeviceDebugSettings(ParentDeviceKey, setting);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -136,51 +135,4 @@ namespace PepperDash.Core
|
|||||||
DebugExpiryPeriod = null;
|
DebugExpiryPeriod = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The available settings for stream debugging
|
|
||||||
/// </summary>
|
|
||||||
[Flags]
|
|
||||||
/// <summary>
|
|
||||||
/// Enumeration of eStreamDebuggingSetting values
|
|
||||||
/// </summary>
|
|
||||||
public enum eStreamDebuggingSetting
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Debug off
|
|
||||||
/// </summary>
|
|
||||||
Off = 0,
|
|
||||||
/// <summary>
|
|
||||||
/// Debug received data
|
|
||||||
/// </summary>
|
|
||||||
Rx = 1,
|
|
||||||
/// <summary>
|
|
||||||
/// Debug transmitted data
|
|
||||||
/// </summary>
|
|
||||||
Tx = 2,
|
|
||||||
/// <summary>
|
|
||||||
/// Debug both received and transmitted data
|
|
||||||
/// </summary>
|
|
||||||
Both = Rx | Tx
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The available settings for stream debugging response types
|
|
||||||
/// </summary>
|
|
||||||
[Flags]
|
|
||||||
public enum eStreamDebuggingDataTypeSettings
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Debug data in byte format
|
|
||||||
/// </summary>
|
|
||||||
Bytes = 0,
|
|
||||||
/// <summary>
|
|
||||||
/// Debug data in text format
|
|
||||||
/// </summary>
|
|
||||||
Text = 1,
|
|
||||||
/// <summary>
|
|
||||||
/// Debug data in both byte and text formats
|
|
||||||
/// </summary>
|
|
||||||
Both = Bytes | Text,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
@@ -11,11 +12,12 @@ using Renci.SshNet.Common;
|
|||||||
namespace PepperDash.Core
|
namespace PepperDash.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// SSH Client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GenericSshClient : Device, ISocketStatusWithStreamDebugging, IAutoReconnect
|
public class GenericSshClient : Device, ISocketStatusWithStreamDebugging, IAutoReconnect
|
||||||
{
|
{
|
||||||
private const string SPlusKey = "Uninitialized SshClient";
|
private const string SPlusKey = "Uninitialized SshClient";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Object to enable stream debugging
|
/// Object to enable stream debugging
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -36,11 +38,6 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<GenericSocketStatusChageEventArgs> ConnectionChange;
|
public event EventHandler<GenericSocketStatusChageEventArgs> ConnectionChange;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/////
|
|
||||||
///// </summary>
|
|
||||||
//public event GenericSocketStatusChangeEventDelegate SocketStatusChange;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Hostname
|
/// Gets or sets the Hostname
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -67,7 +64,7 @@ namespace PepperDash.Core
|
|||||||
public bool IsConnected
|
public bool IsConnected
|
||||||
{
|
{
|
||||||
// returns false if no client or not connected
|
// returns false if no client or not connected
|
||||||
get { return Client != null && ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; }
|
get { return client != null && ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -83,16 +80,26 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public SocketStatus ClientStatus
|
public SocketStatus ClientStatus
|
||||||
{
|
{
|
||||||
get { return _ClientStatus; }
|
get { lock (_stateLock) { return _ClientStatus; } }
|
||||||
private set
|
private set
|
||||||
{
|
{
|
||||||
if (_ClientStatus == value)
|
bool shouldFireEvent = false;
|
||||||
return;
|
lock (_stateLock)
|
||||||
_ClientStatus = value;
|
{
|
||||||
OnConnectionChange();
|
if (_ClientStatus != value)
|
||||||
|
{
|
||||||
|
_ClientStatus = value;
|
||||||
|
shouldFireEvent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fire event outside lock to avoid deadlock
|
||||||
|
if (shouldFireEvent)
|
||||||
|
OnConnectionChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SocketStatus _ClientStatus;
|
|
||||||
|
private SocketStatus _ClientStatus;
|
||||||
|
private bool _ConnectEnabled;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains the familiar Simpl analog status values. This drives the ConnectionChange event
|
/// Contains the familiar Simpl analog status values. This drives the ConnectionChange event
|
||||||
@@ -100,7 +107,7 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ushort UStatus
|
public ushort UStatus
|
||||||
{
|
{
|
||||||
get { return (ushort)_ClientStatus; }
|
get { lock (_stateLock) { return (ushort)_ClientStatus; } }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -111,7 +118,11 @@ namespace PepperDash.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Will be set and unset by connect and disconnect only
|
/// Will be set and unset by connect and disconnect only
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ConnectEnabled { get; private set; }
|
public bool ConnectEnabled
|
||||||
|
{
|
||||||
|
get { lock (_stateLock) { return _ConnectEnabled; } }
|
||||||
|
private set { lock (_stateLock) { _ConnectEnabled = value; } }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// S+ helper for AutoReconnect
|
/// S+ helper for AutoReconnect
|
||||||
@@ -127,17 +138,25 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int AutoReconnectIntervalMs { get; set; }
|
public int AutoReconnectIntervalMs { get; set; }
|
||||||
|
|
||||||
SshClient Client;
|
private SshClient client;
|
||||||
|
|
||||||
ShellStream TheStream;
|
private ShellStream shellStream;
|
||||||
|
|
||||||
CTimer ReconnectTimer;
|
private readonly Timer reconnectTimer;
|
||||||
|
|
||||||
//Lock object to prevent simulatneous connect/disconnect operations
|
//Lock object to prevent simulatneous connect/disconnect operations
|
||||||
//private CCriticalSection connectLock = new CCriticalSection();
|
//private CCriticalSection connectLock = new CCriticalSection();
|
||||||
private SemaphoreSlim connectLock = new SemaphoreSlim(1);
|
private readonly SemaphoreSlim connectLock = new SemaphoreSlim(1);
|
||||||
|
|
||||||
private bool DisconnectLogged = false;
|
// Thread-safety lock for state changes
|
||||||
|
private readonly object _stateLock = new object();
|
||||||
|
|
||||||
|
private bool disconnectLogged = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When true, turns off echo for the SSH session
|
||||||
|
/// </summary>
|
||||||
|
public bool DisableEcho { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Typical constructor.
|
/// Typical constructor.
|
||||||
@@ -154,13 +173,13 @@ namespace PepperDash.Core
|
|||||||
Password = password;
|
Password = password;
|
||||||
AutoReconnectIntervalMs = 5000;
|
AutoReconnectIntervalMs = 5000;
|
||||||
|
|
||||||
ReconnectTimer = new CTimer(o =>
|
reconnectTimer = new Timer(o =>
|
||||||
{
|
{
|
||||||
if (ConnectEnabled)
|
if (ConnectEnabled) // Now thread-safe property access
|
||||||
{
|
{
|
||||||
Connect();
|
Connect();
|
||||||
}
|
}
|
||||||
}, System.Threading.Timeout.Infinite);
|
}, null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -172,23 +191,23 @@ namespace PepperDash.Core
|
|||||||
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
|
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
|
||||||
AutoReconnectIntervalMs = 5000;
|
AutoReconnectIntervalMs = 5000;
|
||||||
|
|
||||||
ReconnectTimer = new CTimer(o =>
|
reconnectTimer = new Timer(o =>
|
||||||
{
|
{
|
||||||
if (ConnectEnabled)
|
if (ConnectEnabled) // Now thread-safe property access
|
||||||
{
|
{
|
||||||
Connect();
|
Connect();
|
||||||
}
|
}
|
||||||
}, System.Threading.Timeout.Infinite);
|
}, null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles closing this up when the program shuts down
|
/// Handles closing this up when the program shuts down
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
|
private void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
|
||||||
{
|
{
|
||||||
if (programEventType == eProgramStatusEventType.Stopping)
|
if (programEventType == eProgramStatusEventType.Stopping)
|
||||||
{
|
{
|
||||||
if (Client != null)
|
if (client != null)
|
||||||
{
|
{
|
||||||
this.LogDebug("Program stopping. Closing connection");
|
this.LogDebug("Program stopping. Closing connection");
|
||||||
Disconnect();
|
Disconnect();
|
||||||
@@ -223,10 +242,10 @@ namespace PepperDash.Core
|
|||||||
this.LogDebug("Attempting connect");
|
this.LogDebug("Attempting connect");
|
||||||
|
|
||||||
// Cancel reconnect if running.
|
// Cancel reconnect if running.
|
||||||
ReconnectTimer?.Stop();
|
StopReconnectTimer();
|
||||||
|
|
||||||
// Cleanup the old client if it already exists
|
// Cleanup the old client if it already exists
|
||||||
if (Client != null)
|
if (client != null)
|
||||||
{
|
{
|
||||||
this.LogDebug("Cleaning up disconnected client");
|
this.LogDebug("Cleaning up disconnected client");
|
||||||
KillClient(SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY);
|
KillClient(SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY);
|
||||||
@@ -239,29 +258,36 @@ namespace PepperDash.Core
|
|||||||
|
|
||||||
this.LogDebug("Creating new SshClient");
|
this.LogDebug("Creating new SshClient");
|
||||||
ConnectionInfo connectionInfo = new ConnectionInfo(Hostname, Port, Username, pauth, kauth);
|
ConnectionInfo connectionInfo = new ConnectionInfo(Hostname, Port, Username, pauth, kauth);
|
||||||
Client = new SshClient(connectionInfo);
|
client = new SshClient(connectionInfo);
|
||||||
Client.ErrorOccurred += Client_ErrorOccurred;
|
client.ErrorOccurred += Client_ErrorOccurred;
|
||||||
|
|
||||||
//Attempt to connect
|
//Attempt to connect
|
||||||
ClientStatus = SocketStatus.SOCKET_STATUS_WAITING;
|
ClientStatus = SocketStatus.SOCKET_STATUS_WAITING;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Client.Connect();
|
client.Connect();
|
||||||
TheStream = Client.CreateShellStream("PDTShell", 0, 0, 0, 0, 65534);
|
|
||||||
if (TheStream.DataAvailable)
|
var modes = new Dictionary<TerminalModes, uint>();
|
||||||
|
|
||||||
|
if (DisableEcho)
|
||||||
|
{
|
||||||
|
modes.Add(TerminalModes.ECHO, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
shellStream = client.CreateShellStream("PDTShell", 0, 0, 0, 0, 65534, modes);
|
||||||
|
if (shellStream.DataAvailable)
|
||||||
{
|
{
|
||||||
// empty the buffer if there is data
|
// empty the buffer if there is data
|
||||||
string str = TheStream.Read();
|
shellStream.Read();
|
||||||
}
|
}
|
||||||
TheStream.DataReceived += Stream_DataReceived;
|
shellStream.DataReceived += Stream_DataReceived;
|
||||||
this.LogInformation("Connected");
|
this.LogInformation("Connected");
|
||||||
ClientStatus = SocketStatus.SOCKET_STATUS_CONNECTED;
|
ClientStatus = SocketStatus.SOCKET_STATUS_CONNECTED;
|
||||||
DisconnectLogged = false;
|
disconnectLogged = false;
|
||||||
}
|
}
|
||||||
catch (SshConnectionException e)
|
catch (SshConnectionException e)
|
||||||
{
|
{
|
||||||
var ie = e.InnerException; // The details are inside!!
|
var ie = e.InnerException; // The details are inside!!
|
||||||
var errorLogLevel = DisconnectLogged == true ? Debug.ErrorLogLevel.None : Debug.ErrorLogLevel.Error;
|
|
||||||
|
|
||||||
if (ie is SocketException)
|
if (ie is SocketException)
|
||||||
{
|
{
|
||||||
@@ -286,37 +312,36 @@ namespace PepperDash.Core
|
|||||||
this.LogVerbose(ie, "Exception details: ");
|
this.LogVerbose(ie, "Exception details: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
DisconnectLogged = true;
|
disconnectLogged = true;
|
||||||
KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
|
KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
|
||||||
if (AutoReconnect)
|
if (AutoReconnect)
|
||||||
{
|
{
|
||||||
this.LogDebug("Checking autoreconnect: {autoReconnect}, {autoReconnectInterval}ms", AutoReconnect, AutoReconnectIntervalMs);
|
this.LogDebug("Checking autoreconnect: {autoReconnect}, {autoReconnectInterval}ms", AutoReconnect, AutoReconnectIntervalMs);
|
||||||
ReconnectTimer.Reset(AutoReconnectIntervalMs);
|
StartReconnectTimer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (SshOperationTimeoutException ex)
|
catch (SshOperationTimeoutException ex)
|
||||||
{
|
{
|
||||||
this.LogWarning("Connection attempt timed out: {message}", ex.Message);
|
this.LogWarning("Connection attempt timed out: {message}", ex.Message);
|
||||||
|
|
||||||
DisconnectLogged = true;
|
disconnectLogged = true;
|
||||||
KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
|
KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
|
||||||
if (AutoReconnect)
|
if (AutoReconnect)
|
||||||
{
|
{
|
||||||
this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs);
|
this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs);
|
||||||
ReconnectTimer.Reset(AutoReconnectIntervalMs);
|
StartReconnectTimer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
var errorLogLevel = DisconnectLogged == true ? Debug.ErrorLogLevel.None : Debug.ErrorLogLevel.Error;
|
|
||||||
this.LogError("Unhandled exception on connect: {error}", e.Message);
|
this.LogError("Unhandled exception on connect: {error}", e.Message);
|
||||||
this.LogVerbose(e, "Exception details: ");
|
this.LogVerbose(e, "Exception details: ");
|
||||||
DisconnectLogged = true;
|
disconnectLogged = true;
|
||||||
KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
|
KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
|
||||||
if (AutoReconnect)
|
if (AutoReconnect)
|
||||||
{
|
{
|
||||||
this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs);
|
this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs);
|
||||||
ReconnectTimer.Reset(AutoReconnectIntervalMs);
|
StartReconnectTimer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -334,11 +359,7 @@ namespace PepperDash.Core
|
|||||||
{
|
{
|
||||||
ConnectEnabled = false;
|
ConnectEnabled = false;
|
||||||
// Stop trying reconnects, if we are
|
// Stop trying reconnects, if we are
|
||||||
if (ReconnectTimer != null)
|
StopReconnectTimer();
|
||||||
{
|
|
||||||
ReconnectTimer.Stop();
|
|
||||||
// ReconnectTimer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
KillClient(SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY);
|
KillClient(SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY);
|
||||||
}
|
}
|
||||||
@@ -352,12 +373,12 @@ namespace PepperDash.Core
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Client != null)
|
if (client != null)
|
||||||
{
|
{
|
||||||
Client.ErrorOccurred -= Client_ErrorOccurred;
|
client.ErrorOccurred -= Client_ErrorOccurred;
|
||||||
Client.Disconnect();
|
client.Disconnect();
|
||||||
Client.Dispose();
|
client.Dispose();
|
||||||
Client = null;
|
client = null;
|
||||||
ClientStatus = status;
|
ClientStatus = status;
|
||||||
this.LogDebug("Disconnected");
|
this.LogDebug("Disconnected");
|
||||||
}
|
}
|
||||||
@@ -371,16 +392,16 @@ namespace PepperDash.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Kills the stream
|
/// Kills the stream
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void KillStream()
|
private void KillStream()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (TheStream != null)
|
if (shellStream != null)
|
||||||
{
|
{
|
||||||
TheStream.DataReceived -= Stream_DataReceived;
|
shellStream.DataReceived -= Stream_DataReceived;
|
||||||
TheStream.Close();
|
shellStream.Close();
|
||||||
TheStream.Dispose();
|
shellStream.Dispose();
|
||||||
TheStream = null;
|
shellStream = null;
|
||||||
this.LogDebug("Disconnected stream");
|
this.LogDebug("Disconnected stream");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -393,7 +414,7 @@ namespace PepperDash.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles the keyboard interactive authentication, should it be required.
|
/// Handles the keyboard interactive authentication, should it be required.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void kauth_AuthenticationPrompt(object sender, AuthenticationPromptEventArgs e)
|
private void kauth_AuthenticationPrompt(object sender, AuthenticationPromptEventArgs e)
|
||||||
{
|
{
|
||||||
foreach (AuthenticationPrompt prompt in e.Prompts)
|
foreach (AuthenticationPrompt prompt in e.Prompts)
|
||||||
if (prompt.Request.IndexOf("Password:", StringComparison.InvariantCultureIgnoreCase) != -1)
|
if (prompt.Request.IndexOf("Password:", StringComparison.InvariantCultureIgnoreCase) != -1)
|
||||||
@@ -403,7 +424,7 @@ namespace PepperDash.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handler for data receive on ShellStream. Passes data across to queue for line parsing.
|
/// Handler for data receive on ShellStream. Passes data across to queue for line parsing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Stream_DataReceived(object sender, ShellDataEventArgs e)
|
private void Stream_DataReceived(object sender, ShellDataEventArgs e)
|
||||||
{
|
{
|
||||||
if (((ShellStream)sender).Length <= 0L)
|
if (((ShellStream)sender).Length <= 0L)
|
||||||
{
|
{
|
||||||
@@ -416,18 +437,14 @@ namespace PepperDash.Core
|
|||||||
if (bytesHandler != null)
|
if (bytesHandler != null)
|
||||||
{
|
{
|
||||||
var bytes = Encoding.UTF8.GetBytes(response);
|
var bytes = Encoding.UTF8.GetBytes(response);
|
||||||
if (StreamDebugging.RxStreamDebuggingIsEnabled)
|
this.PrintReceivedBytes(bytes);
|
||||||
{
|
|
||||||
this.LogInformation("Received {1} bytes: '{0}'", ComTextHelper.GetEscapedText(bytes), bytes.Length);
|
|
||||||
}
|
|
||||||
bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes));
|
bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
var textHandler = TextReceived;
|
var textHandler = TextReceived;
|
||||||
if (textHandler != null)
|
if (textHandler != null)
|
||||||
{
|
{
|
||||||
if (StreamDebugging.RxStreamDebuggingIsEnabled)
|
this.PrintReceivedText(response);
|
||||||
this.LogInformation("Received: '{0}'", ComTextHelper.GetDebugText(response));
|
|
||||||
|
|
||||||
textHandler(this, new GenericCommMethodReceiveTextArgs(response));
|
textHandler(this, new GenericCommMethodReceiveTextArgs(response));
|
||||||
}
|
}
|
||||||
@@ -439,7 +456,7 @@ namespace PepperDash.Core
|
|||||||
/// Error event handler for client events - disconnect, etc. Will forward those events via ConnectionChange
|
/// Error event handler for client events - disconnect, etc. Will forward those events via ConnectionChange
|
||||||
/// event
|
/// event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Client_ErrorOccurred(object sender, ExceptionEventArgs e)
|
private void Client_ErrorOccurred(object sender, ExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
CrestronInvoke.BeginInvoke(o =>
|
CrestronInvoke.BeginInvoke(o =>
|
||||||
{
|
{
|
||||||
@@ -459,7 +476,7 @@ namespace PepperDash.Core
|
|||||||
if (AutoReconnect && ConnectEnabled)
|
if (AutoReconnect && ConnectEnabled)
|
||||||
{
|
{
|
||||||
this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs);
|
this.LogDebug("Checking autoreconnect: {0}, {1}ms", AutoReconnect, AutoReconnectIntervalMs);
|
||||||
ReconnectTimer.Reset(AutoReconnectIntervalMs);
|
StartReconnectTimer();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -467,7 +484,7 @@ namespace PepperDash.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper for ConnectionChange event
|
/// Helper for ConnectionChange event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void OnConnectionChange()
|
private void OnConnectionChange()
|
||||||
{
|
{
|
||||||
ConnectionChange?.Invoke(this, new GenericSocketStatusChageEventArgs(this));
|
ConnectionChange?.Invoke(this, new GenericSocketStatusChageEventArgs(this));
|
||||||
}
|
}
|
||||||
@@ -482,16 +499,12 @@ namespace PepperDash.Core
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Client != null && TheStream != null && IsConnected)
|
if (client != null && shellStream != null && IsConnected)
|
||||||
{
|
{
|
||||||
if (StreamDebugging.TxStreamDebuggingIsEnabled)
|
this.PrintSentText(text);
|
||||||
this.LogInformation(
|
|
||||||
"Sending {length} characters of text: '{text}'",
|
|
||||||
text.Length,
|
|
||||||
ComTextHelper.GetDebugText(text));
|
|
||||||
|
|
||||||
TheStream.Write(text);
|
shellStream.Write(text);
|
||||||
TheStream.Flush();
|
shellStream.Flush();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -503,7 +516,7 @@ namespace PepperDash.Core
|
|||||||
this.LogError("ObjectDisposedException sending '{message}'. Restarting connection...", text.Trim());
|
this.LogError("ObjectDisposedException sending '{message}'. Restarting connection...", text.Trim());
|
||||||
|
|
||||||
KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
|
KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
|
||||||
ReconnectTimer.Reset();
|
StartReconnectTimer();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -519,13 +532,12 @@ namespace PepperDash.Core
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Client != null && TheStream != null && IsConnected)
|
if (client != null && shellStream != null && IsConnected)
|
||||||
{
|
{
|
||||||
if (StreamDebugging.TxStreamDebuggingIsEnabled)
|
this.PrintSentBytes(bytes);
|
||||||
this.LogInformation("Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes));
|
|
||||||
|
|
||||||
TheStream.Write(bytes, 0, bytes.Length);
|
shellStream.Write(bytes, 0, bytes.Length);
|
||||||
TheStream.Flush();
|
shellStream.Flush();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -537,7 +549,7 @@ namespace PepperDash.Core
|
|||||||
this.LogException(ex, "ObjectDisposedException sending {message}", ComTextHelper.GetEscapedText(bytes));
|
this.LogException(ex, "ObjectDisposedException sending {message}", ComTextHelper.GetEscapedText(bytes));
|
||||||
|
|
||||||
KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
|
KillClient(SocketStatus.SOCKET_STATUS_CONNECT_FAILED);
|
||||||
ReconnectTimer.Reset();
|
StartReconnectTimer();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -546,6 +558,83 @@ namespace PepperDash.Core
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Safely starts the reconnect timer with exception handling
|
||||||
|
/// </summary>
|
||||||
|
private void StartReconnectTimer()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
reconnectTimer?.Change(AutoReconnectIntervalMs, System.Threading.Timeout.Infinite);
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
// Timer was disposed, ignore
|
||||||
|
this.LogDebug("Attempted to start timer but it was already disposed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Safely stops the reconnect timer with exception handling
|
||||||
|
/// </summary>
|
||||||
|
private void StopReconnectTimer()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
reconnectTimer?.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
// Timer was disposed, ignore
|
||||||
|
this.LogDebug("Attempted to stop timer but it was already disposed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deactivate method - properly dispose of resources
|
||||||
|
/// </summary>
|
||||||
|
public override bool Deactivate()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.LogDebug("Deactivating SSH client - disposing resources");
|
||||||
|
|
||||||
|
// Stop trying reconnects
|
||||||
|
ConnectEnabled = false;
|
||||||
|
StopReconnectTimer();
|
||||||
|
|
||||||
|
// Disconnect and cleanup client
|
||||||
|
KillClient(SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY);
|
||||||
|
|
||||||
|
// Dispose timer
|
||||||
|
try
|
||||||
|
{
|
||||||
|
reconnectTimer?.Dispose();
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
// Already disposed, ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dispose semaphore
|
||||||
|
try
|
||||||
|
{
|
||||||
|
connectLock?.Dispose();
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
// Already disposed, ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.Deactivate();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
this.LogException(ex, "Error during SSH client deactivation");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************************************************************************************
|
//*****************************************************************************************************
|
||||||
|
|||||||
@@ -19,44 +19,44 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public CommunicationStreamDebugging StreamDebugging { get; private set; }
|
public CommunicationStreamDebugging StreamDebugging { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fires when data is received from the server and returns it as a Byte array
|
/// Fires when data is received from the server and returns it as a Byte array
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<GenericCommMethodReceiveBytesArgs> BytesReceived;
|
public event EventHandler<GenericCommMethodReceiveBytesArgs> BytesReceived;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fires when data is received from the server and returns it as text
|
/// Fires when data is received from the server and returns it as text
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<GenericCommMethodReceiveTextArgs> TextReceived;
|
public event EventHandler<GenericCommMethodReceiveTextArgs> TextReceived;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
//public event GenericSocketStatusChangeEventDelegate SocketStatusChange;
|
//public event GenericSocketStatusChangeEventDelegate SocketStatusChange;
|
||||||
public event EventHandler<GenericSocketStatusChageEventArgs> ConnectionChange;
|
public event EventHandler<GenericSocketStatusChageEventArgs> ConnectionChange;
|
||||||
|
|
||||||
|
|
||||||
private string _hostname;
|
private string _hostname;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Address of server
|
/// Address of server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Hostname
|
public string Hostname
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _hostname;
|
return _hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_hostname = value;
|
_hostname = value;
|
||||||
if (_client != null)
|
if (_client != null)
|
||||||
{
|
{
|
||||||
_client.AddressClientConnectedTo = _hostname;
|
_client.AddressClientConnectedTo = _hostname;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Port
|
/// Gets or sets the Port
|
||||||
@@ -78,19 +78,19 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int BufferSize { get; set; }
|
public int BufferSize { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The actual client class
|
/// The actual client class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private TCPClient _client;
|
private TCPClient _client;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Bool showing if socket is connected
|
/// Bool showing if socket is connected
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsConnected
|
public bool IsConnected
|
||||||
{
|
{
|
||||||
get { return _client != null && _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; }
|
get { return _client != null && _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// S+ helper for IsConnected
|
/// S+ helper for IsConnected
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -99,15 +99,15 @@ namespace PepperDash.Core
|
|||||||
get { return (ushort)(IsConnected ? 1 : 0); }
|
get { return (ushort)(IsConnected ? 1 : 0); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// _client socket status Read only
|
/// _client socket status Read only
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SocketStatus ClientStatus
|
public SocketStatus ClientStatus
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _client == null ? SocketStatus.SOCKET_STATUS_NO_CONNECT : _client.ClientStatus;
|
return _client == null ? SocketStatus.SOCKET_STATUS_NO_CONNECT : _client.ClientStatus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -119,26 +119,26 @@ namespace PepperDash.Core
|
|||||||
get { return (ushort)ClientStatus; }
|
get { return (ushort)ClientStatus; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Status text shows the message associated with socket status
|
/// Status text shows the message associated with socket status
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ClientStatusText { get { return ClientStatus.ToString(); } }
|
public string ClientStatusText { get { return ClientStatus.ToString(); } }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ushort representation of client status
|
/// Ushort representation of client status
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete]
|
[Obsolete]
|
||||||
public ushort UClientStatus { get { return (ushort)ClientStatus; } }
|
public ushort UClientStatus { get { return (ushort)ClientStatus; } }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Connection failure reason
|
/// Connection failure reason
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ConnectionFailure { get { return ClientStatus.ToString(); } }
|
public string ConnectionFailure { get { return ClientStatus.ToString(); } }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the AutoReconnect
|
/// Gets or sets the AutoReconnect
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AutoReconnect { get; set; }
|
public bool AutoReconnect { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// S+ helper for AutoReconnect
|
/// S+ helper for AutoReconnect
|
||||||
@@ -149,29 +149,29 @@ namespace PepperDash.Core
|
|||||||
set { AutoReconnect = value == 1; }
|
set { AutoReconnect = value == 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Milliseconds to wait before attempting to reconnect. Defaults to 5000
|
/// Milliseconds to wait before attempting to reconnect. Defaults to 5000
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int AutoReconnectIntervalMs { get; set; }
|
public int AutoReconnectIntervalMs { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set only when the disconnect method is called
|
/// Set only when the disconnect method is called
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool DisconnectCalledByUser;
|
bool DisconnectCalledByUser;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Connected
|
public bool Connected
|
||||||
{
|
{
|
||||||
get { return _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; }
|
get { return _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; }
|
||||||
}
|
}
|
||||||
|
|
||||||
//Lock object to prevent simulatneous connect/disconnect operations
|
//Lock object to prevent simulatneous connect/disconnect operations
|
||||||
private CCriticalSection connectLock = new CCriticalSection();
|
private CCriticalSection connectLock = new CCriticalSection();
|
||||||
|
|
||||||
// private Timer for auto reconnect
|
// private Timer for auto reconnect
|
||||||
private CTimer RetryTimer;
|
private CTimer RetryTimer;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor
|
/// Constructor
|
||||||
@@ -181,8 +181,8 @@ namespace PepperDash.Core
|
|||||||
/// <param name="port"></param>
|
/// <param name="port"></param>
|
||||||
/// <param name="bufferSize"></param>
|
/// <param name="bufferSize"></param>
|
||||||
public GenericTcpIpClient(string key, string address, int port, int bufferSize)
|
public GenericTcpIpClient(string key, string address, int port, int bufferSize)
|
||||||
: base(key)
|
: base(key)
|
||||||
{
|
{
|
||||||
StreamDebugging = new CommunicationStreamDebugging(key);
|
StreamDebugging = new CommunicationStreamDebugging(key);
|
||||||
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
|
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
|
||||||
AutoReconnectIntervalMs = 5000;
|
AutoReconnectIntervalMs = 5000;
|
||||||
@@ -218,18 +218,18 @@ namespace PepperDash.Core
|
|||||||
/// Default constructor for S+
|
/// Default constructor for S+
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public GenericTcpIpClient()
|
public GenericTcpIpClient()
|
||||||
: base(SplusKey)
|
: base(SplusKey)
|
||||||
{
|
{
|
||||||
StreamDebugging = new CommunicationStreamDebugging(SplusKey);
|
StreamDebugging = new CommunicationStreamDebugging(SplusKey);
|
||||||
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
|
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
|
||||||
AutoReconnectIntervalMs = 5000;
|
AutoReconnectIntervalMs = 5000;
|
||||||
BufferSize = 2000;
|
BufferSize = 2000;
|
||||||
|
|
||||||
RetryTimer = new CTimer(o =>
|
RetryTimer = new CTimer(o =>
|
||||||
{
|
{
|
||||||
Reconnect();
|
Reconnect();
|
||||||
}, Timeout.Infinite);
|
}, Timeout.Infinite);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initialize method
|
/// Initialize method
|
||||||
@@ -255,26 +255,26 @@ namespace PepperDash.Core
|
|||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deactivate method
|
/// Deactivate method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public override bool Deactivate()
|
public override bool Deactivate()
|
||||||
{
|
{
|
||||||
RetryTimer.Stop();
|
RetryTimer.Stop();
|
||||||
RetryTimer.Dispose();
|
RetryTimer.Dispose();
|
||||||
if (_client != null)
|
if (_client != null)
|
||||||
{
|
{
|
||||||
_client.SocketStatusChange -= this.Client_SocketStatusChange;
|
_client.SocketStatusChange -= this.Client_SocketStatusChange;
|
||||||
DisconnectClient();
|
DisconnectClient();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Connect method
|
/// Connect method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Connect()
|
public void Connect()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(Hostname))
|
if (string.IsNullOrEmpty(Hostname))
|
||||||
{
|
{
|
||||||
Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericTcpIpClient '{0}': No address set", Key);
|
Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericTcpIpClient '{0}': No address set", Key);
|
||||||
@@ -310,7 +310,7 @@ namespace PepperDash.Core
|
|||||||
{
|
{
|
||||||
connectLock.Leave();
|
connectLock.Leave();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Reconnect()
|
private void Reconnect()
|
||||||
{
|
{
|
||||||
@@ -337,11 +337,11 @@ namespace PepperDash.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disconnect method
|
/// Disconnect method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Disconnect()
|
public void Disconnect()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
connectLock.Enter();
|
connectLock.Enter();
|
||||||
@@ -355,7 +355,7 @@ namespace PepperDash.Core
|
|||||||
{
|
{
|
||||||
connectLock.Leave();
|
connectLock.Leave();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// DisconnectClient method
|
/// DisconnectClient method
|
||||||
@@ -375,7 +375,7 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="c"></param>
|
/// <param name="c"></param>
|
||||||
void ConnectToServerCallback(TCPClient c)
|
void ConnectToServerCallback(TCPClient c)
|
||||||
{
|
{
|
||||||
if (c.ClientStatus != SocketStatus.SOCKET_STATUS_CONNECTED)
|
if (c.ClientStatus != SocketStatus.SOCKET_STATUS_CONNECTED)
|
||||||
{
|
{
|
||||||
Debug.Console(0, this, "Server connection result: {0}", c.ClientStatus);
|
Debug.Console(0, this, "Server connection result: {0}", c.ClientStatus);
|
||||||
@@ -385,13 +385,13 @@ namespace PepperDash.Core
|
|||||||
{
|
{
|
||||||
Debug.Console(1, this, "Server connection result: {0}", c.ClientStatus);
|
Debug.Console(1, this, "Server connection result: {0}", c.ClientStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disconnects, waits and attemtps to connect again
|
/// Disconnects, waits and attemtps to connect again
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void WaitAndTryReconnect()
|
void WaitAndTryReconnect()
|
||||||
{
|
{
|
||||||
CrestronInvoke.BeginInvoke(o =>
|
CrestronInvoke.BeginInvoke(o =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -409,7 +409,7 @@ namespace PepperDash.Core
|
|||||||
connectLock.Leave();
|
connectLock.Leave();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recieves incoming data
|
/// Recieves incoming data
|
||||||
@@ -417,7 +417,7 @@ namespace PepperDash.Core
|
|||||||
/// <param name="client"></param>
|
/// <param name="client"></param>
|
||||||
/// <param name="numBytes"></param>
|
/// <param name="numBytes"></param>
|
||||||
void Receive(TCPClient client, int numBytes)
|
void Receive(TCPClient client, int numBytes)
|
||||||
{
|
{
|
||||||
if (client != null)
|
if (client != null)
|
||||||
{
|
{
|
||||||
if (numBytes > 0)
|
if (numBytes > 0)
|
||||||
@@ -426,10 +426,7 @@ namespace PepperDash.Core
|
|||||||
var bytesHandler = BytesReceived;
|
var bytesHandler = BytesReceived;
|
||||||
if (bytesHandler != null)
|
if (bytesHandler != null)
|
||||||
{
|
{
|
||||||
if (StreamDebugging.RxStreamDebuggingIsEnabled)
|
this.PrintReceivedBytes(bytes);
|
||||||
{
|
|
||||||
Debug.Console(0, this, "Received {1} bytes: '{0}'", ComTextHelper.GetEscapedText(bytes), bytes.Length);
|
|
||||||
}
|
|
||||||
bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes));
|
bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes));
|
||||||
}
|
}
|
||||||
var textHandler = TextReceived;
|
var textHandler = TextReceived;
|
||||||
@@ -437,58 +434,53 @@ namespace PepperDash.Core
|
|||||||
{
|
{
|
||||||
var str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length);
|
var str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length);
|
||||||
|
|
||||||
if (StreamDebugging.RxStreamDebuggingIsEnabled)
|
this.PrintReceivedText(str);
|
||||||
{
|
|
||||||
Debug.Console(0, this, "Received {1} characters of text: '{0}'", ComTextHelper.GetDebugText(str), str.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
textHandler(this, new GenericCommMethodReceiveTextArgs(str));
|
textHandler(this, new GenericCommMethodReceiveTextArgs(str));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
client.ReceiveDataAsync(Receive);
|
client.ReceiveDataAsync(Receive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SendText method
|
/// SendText method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SendText(string text)
|
public void SendText(string text)
|
||||||
{
|
{
|
||||||
var bytes = Encoding.GetEncoding(28591).GetBytes(text);
|
var bytes = Encoding.GetEncoding(28591).GetBytes(text);
|
||||||
// Check debug level before processing byte array
|
// Check debug level before processing byte array
|
||||||
if (StreamDebugging.TxStreamDebuggingIsEnabled)
|
this.PrintSentText(text);
|
||||||
Debug.Console(0, this, "Sending {0} characters of text: '{1}'", text.Length, ComTextHelper.GetDebugText(text));
|
|
||||||
if (_client != null)
|
if (_client != null)
|
||||||
_client.SendData(bytes, bytes.Length);
|
_client.SendData(bytes, bytes.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SendEscapedText method
|
/// SendEscapedText method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SendEscapedText(string text)
|
public void SendEscapedText(string text)
|
||||||
{
|
{
|
||||||
var unescapedText = Regex.Replace(text, @"\\x([0-9a-fA-F][0-9a-fA-F])", s =>
|
var unescapedText = Regex.Replace(text, @"\\x([0-9a-fA-F][0-9a-fA-F])", s =>
|
||||||
{
|
{
|
||||||
var hex = s.Groups[1].Value;
|
var hex = s.Groups[1].Value;
|
||||||
return ((char)Convert.ToByte(hex, 16)).ToString();
|
return ((char)Convert.ToByte(hex, 16)).ToString();
|
||||||
});
|
});
|
||||||
SendText(unescapedText);
|
SendText(unescapedText);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends Bytes to the server
|
/// Sends Bytes to the server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="bytes"></param>
|
/// <param name="bytes"></param>
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SendBytes method
|
/// SendBytes method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SendBytes(byte[] bytes)
|
public void SendBytes(byte[] bytes)
|
||||||
{
|
{
|
||||||
if (StreamDebugging.TxStreamDebuggingIsEnabled)
|
this.PrintSentBytes(bytes);
|
||||||
Debug.Console(0, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes));
|
|
||||||
if (_client != null)
|
if (_client != null)
|
||||||
_client.SendData(bytes, bytes.Length);
|
_client.SendData(bytes, bytes.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Socket Status Change Handler
|
/// Socket Status Change Handler
|
||||||
@@ -496,7 +488,7 @@ namespace PepperDash.Core
|
|||||||
/// <param name="client"></param>
|
/// <param name="client"></param>
|
||||||
/// <param name="clientSocketStatus"></param>
|
/// <param name="clientSocketStatus"></param>
|
||||||
void Client_SocketStatusChange(TCPClient client, SocketStatus clientSocketStatus)
|
void Client_SocketStatusChange(TCPClient client, SocketStatus clientSocketStatus)
|
||||||
{
|
{
|
||||||
if (clientSocketStatus != SocketStatus.SOCKET_STATUS_CONNECTED)
|
if (clientSocketStatus != SocketStatus.SOCKET_STATUS_CONNECTED)
|
||||||
{
|
{
|
||||||
Debug.Console(0, this, "Socket status change {0} ({1})", clientSocketStatus, ClientStatusText);
|
Debug.Console(0, this, "Socket status change {0} ({1})", clientSocketStatus, ClientStatusText);
|
||||||
@@ -505,68 +497,73 @@ namespace PepperDash.Core
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Console(1, this, "Socket status change {0} ({1})", clientSocketStatus, ClientStatusText);
|
Debug.Console(1, this, "Socket status change {0} ({1})", clientSocketStatus, ClientStatusText);
|
||||||
_client.ReceiveDataAsync(Receive);
|
_client.ReceiveDataAsync(Receive);
|
||||||
}
|
}
|
||||||
|
|
||||||
var handler = ConnectionChange;
|
var handler = ConnectionChange;
|
||||||
if (handler != null)
|
if (handler != null)
|
||||||
ConnectionChange(this, new GenericSocketStatusChageEventArgs(this));
|
ConnectionChange(this, new GenericSocketStatusChageEventArgs(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a TcpSshPropertiesConfig
|
/// Represents a TcpSshPropertiesConfig
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TcpSshPropertiesConfig
|
public class TcpSshPropertiesConfig
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Address to connect to
|
/// Address to connect to
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty(Required = Required.Always)]
|
[JsonProperty(Required = Required.Always)]
|
||||||
public string Address { get; set; }
|
public string Address { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Port to connect to
|
/// Port to connect to
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty(Required = Required.Always)]
|
[JsonProperty(Required = Required.Always)]
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Username credential
|
/// Username credential
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Password
|
/// Gets or sets the Password
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defaults to 32768
|
/// Defaults to 32768
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int BufferSize { get; set; }
|
public int BufferSize { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the AutoReconnect
|
/// Gets or sets the AutoReconnect
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AutoReconnect { get; set; }
|
public bool AutoReconnect { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the AutoReconnectIntervalMs
|
/// Gets or sets the AutoReconnectIntervalMs
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int AutoReconnectIntervalMs { get; set; }
|
public int AutoReconnectIntervalMs { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When true, turns off echo for the SSH session
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("disableSshEcho")]
|
||||||
|
public bool DisableSshEcho { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default constructor
|
/// Default constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TcpSshPropertiesConfig()
|
public TcpSshPropertiesConfig()
|
||||||
{
|
{
|
||||||
BufferSize = 32768;
|
BufferSize = 32768;
|
||||||
AutoReconnect = true;
|
AutoReconnect = true;
|
||||||
AutoReconnectIntervalMs = 5000;
|
AutoReconnectIntervalMs = 5000;
|
||||||
Username = "";
|
Username = "";
|
||||||
Password = "";
|
Password = "";
|
||||||
}
|
DisableSshEcho = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,21 +124,21 @@ namespace PepperDash.Core
|
|||||||
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
|
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
|
||||||
CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler);
|
CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key"></param>
|
/// <param name="key"></param>
|
||||||
/// <param name="address"></param>
|
/// <param name="address"></param>
|
||||||
/// <param name="port"></param>
|
/// <param name="port"></param>
|
||||||
/// <param name="buffefSize"></param>
|
/// <param name="bufferSize"></param>
|
||||||
public GenericUdpServer(string key, string address, int port, int buffefSize)
|
public GenericUdpServer(string key, string address, int port, int bufferSize)
|
||||||
: base(key)
|
: base(key)
|
||||||
{
|
{
|
||||||
StreamDebugging = new CommunicationStreamDebugging(key);
|
StreamDebugging = new CommunicationStreamDebugging(key);
|
||||||
Hostname = address;
|
Hostname = address;
|
||||||
Port = port;
|
Port = port;
|
||||||
BufferSize = buffefSize;
|
BufferSize = bufferSize;
|
||||||
|
|
||||||
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
|
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
|
||||||
CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler);
|
CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler);
|
||||||
@@ -180,7 +180,7 @@ namespace PepperDash.Core
|
|||||||
/// <param name="programEventType"></param>
|
/// <param name="programEventType"></param>
|
||||||
void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
|
void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
|
||||||
{
|
{
|
||||||
if (programEventType != eProgramStatusEventType.Stopping)
|
if (programEventType != eProgramStatusEventType.Stopping)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Debug.Console(1, this, "Program stopping. Disabling Server");
|
Debug.Console(1, this, "Program stopping. Disabling Server");
|
||||||
@@ -194,7 +194,21 @@ namespace PepperDash.Core
|
|||||||
{
|
{
|
||||||
if (Server == null)
|
if (Server == null)
|
||||||
{
|
{
|
||||||
Server = new UDPServer();
|
try
|
||||||
|
{
|
||||||
|
var address = IPAddress.Parse(Hostname);
|
||||||
|
|
||||||
|
Server = new UDPServer(address, Port, BufferSize);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
this.LogError("Error parsing IP Address '{ipAddress}': message: {message}", Hostname, ex.Message);
|
||||||
|
this.LogInformation("Creating UDPServer with default buffersize");
|
||||||
|
|
||||||
|
Server = new UDPServer();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(Hostname))
|
if (string.IsNullOrEmpty(Hostname))
|
||||||
@@ -229,7 +243,7 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void Disconnect()
|
public void Disconnect()
|
||||||
{
|
{
|
||||||
if(Server != null)
|
if (Server != null)
|
||||||
Server.DisableUDPServer();
|
Server.DisableUDPServer();
|
||||||
|
|
||||||
IsConnected = false;
|
IsConnected = false;
|
||||||
@@ -251,7 +265,7 @@ namespace PepperDash.Core
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (numBytes <= 0)
|
if (numBytes <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var sourceIp = Server.IPAddressLastMessageReceivedFrom;
|
var sourceIp = Server.IPAddressLastMessageReceivedFrom;
|
||||||
@@ -267,17 +281,13 @@ namespace PepperDash.Core
|
|||||||
var bytesHandler = BytesReceived;
|
var bytesHandler = BytesReceived;
|
||||||
if (bytesHandler != null)
|
if (bytesHandler != null)
|
||||||
{
|
{
|
||||||
if (StreamDebugging.RxStreamDebuggingIsEnabled)
|
this.PrintReceivedBytes(bytes);
|
||||||
{
|
|
||||||
Debug.Console(0, this, "Received {1} bytes: '{0}'", ComTextHelper.GetEscapedText(bytes), bytes.Length);
|
|
||||||
}
|
|
||||||
bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes));
|
bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes));
|
||||||
}
|
}
|
||||||
var textHandler = TextReceived;
|
var textHandler = TextReceived;
|
||||||
if (textHandler != null)
|
if (textHandler != null)
|
||||||
{
|
{
|
||||||
if (StreamDebugging.RxStreamDebuggingIsEnabled)
|
this.PrintReceivedText(str);
|
||||||
Debug.Console(0, this, "Received {1} characters of text: '{0}'", ComTextHelper.GetDebugText(str), str.Length);
|
|
||||||
textHandler(this, new GenericCommMethodReceiveTextArgs(str));
|
textHandler(this, new GenericCommMethodReceiveTextArgs(str));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -304,8 +314,7 @@ namespace PepperDash.Core
|
|||||||
|
|
||||||
if (IsConnected && Server != null)
|
if (IsConnected && Server != null)
|
||||||
{
|
{
|
||||||
if (StreamDebugging.TxStreamDebuggingIsEnabled)
|
this.PrintSentText(text);
|
||||||
Debug.Console(0, this, "Sending {0} characters of text: '{1}'", text.Length, ComTextHelper.GetDebugText(text));
|
|
||||||
|
|
||||||
Server.SendData(bytes, bytes.Length);
|
Server.SendData(bytes, bytes.Length);
|
||||||
}
|
}
|
||||||
@@ -320,8 +329,7 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void SendBytes(byte[] bytes)
|
public void SendBytes(byte[] bytes)
|
||||||
{
|
{
|
||||||
if (StreamDebugging.TxStreamDebuggingIsEnabled)
|
this.PrintSentBytes(bytes);
|
||||||
Debug.Console(0, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes));
|
|
||||||
|
|
||||||
if (IsConnected && Server != null)
|
if (IsConnected && Server != null)
|
||||||
Server.SendData(bytes, bytes.Length);
|
Server.SendData(bytes, bytes.Length);
|
||||||
@@ -329,11 +337,11 @@ namespace PepperDash.Core
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a GenericUdpReceiveTextExtraArgs
|
/// Represents a GenericUdpReceiveTextExtraArgs
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GenericUdpReceiveTextExtraArgs : EventArgs
|
public class GenericUdpReceiveTextExtraArgs : EventArgs
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -345,7 +353,7 @@ namespace PepperDash.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Port { get; private set; }
|
public int Port { get; private set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -359,18 +367,18 @@ namespace PepperDash.Core
|
|||||||
/// <param name="port"></param>
|
/// <param name="port"></param>
|
||||||
/// <param name="bytes"></param>
|
/// <param name="bytes"></param>
|
||||||
public GenericUdpReceiveTextExtraArgs(string text, string ipAddress, int port, byte[] bytes)
|
public GenericUdpReceiveTextExtraArgs(string text, string ipAddress, int port, byte[] bytes)
|
||||||
{
|
{
|
||||||
Text = text;
|
Text = text;
|
||||||
IpAddress = ipAddress;
|
IpAddress = ipAddress;
|
||||||
Port = port;
|
Port = port;
|
||||||
Bytes = bytes;
|
Bytes = bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stupid S+ Constructor
|
/// Stupid S+ Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public GenericUdpReceiveTextExtraArgs() { }
|
public GenericUdpReceiveTextExtraArgs() { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
|||||||
69
src/PepperDash.Core/Comm/StreamDebuggingExtensions.cs
Normal file
69
src/PepperDash.Core/Comm/StreamDebuggingExtensions.cs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
using System;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
|
||||||
|
namespace PepperDash.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for stream debugging
|
||||||
|
/// </summary>
|
||||||
|
public static class StreamDebuggingExtensions
|
||||||
|
{
|
||||||
|
private static readonly string app = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? $"App {InitialParametersClass.ApplicationNumber}" : $"{InitialParametersClass.RoomId}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Print the sent bytes to the console
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="comms">comms device</param>
|
||||||
|
/// <param name="bytes">bytes to print</param>
|
||||||
|
public static void PrintSentBytes(this IStreamDebugging comms, byte[] bytes)
|
||||||
|
{
|
||||||
|
if (!comms.StreamDebugging.TxStreamDebuggingIsEnabled) return;
|
||||||
|
|
||||||
|
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
|
||||||
|
CrestronConsole.PrintLine($"[{timestamp}][{app}][{comms.Key}] Sending {bytes.Length} bytes: '{ComTextHelper.GetEscapedText(bytes)}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Print the received bytes to the console
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="comms">comms device</param>
|
||||||
|
/// <param name="bytes">bytes to print</param>
|
||||||
|
public static void PrintReceivedBytes(this IStreamDebugging comms, byte[] bytes)
|
||||||
|
{
|
||||||
|
if (!comms.StreamDebugging.RxStreamDebuggingIsEnabled) return;
|
||||||
|
|
||||||
|
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
|
||||||
|
CrestronConsole.PrintLine($"[{timestamp}][{app}][{comms.Key}] Received {bytes.Length} bytes: '{ComTextHelper.GetEscapedText(bytes)}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Print the sent text to the console
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="comms">comms device</param>
|
||||||
|
/// <param name="text">text to print</param>
|
||||||
|
public static void PrintSentText(this IStreamDebugging comms, string text)
|
||||||
|
{
|
||||||
|
if (!comms.StreamDebugging.TxStreamDebuggingIsEnabled) return;
|
||||||
|
|
||||||
|
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
|
||||||
|
CrestronConsole.PrintLine($"[{timestamp}][{app}][{comms.Key}] Sending Text: '{ComTextHelper.GetDebugText(text)}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Print the received text to the console
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="comms">comms device</param>
|
||||||
|
/// <param name="text">text to print</param>
|
||||||
|
public static void PrintReceivedText(this IStreamDebugging comms, string text)
|
||||||
|
{
|
||||||
|
if (!comms.StreamDebugging.RxStreamDebuggingIsEnabled) return;
|
||||||
|
|
||||||
|
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
|
||||||
|
CrestronConsole.PrintLine($"[{timestamp}][{app}][{comms.Key}] Received Text: '{ComTextHelper.GetDebugText(text)}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -74,6 +74,14 @@ namespace PepperDash.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Secure TCP/IP
|
/// Secure TCP/IP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
SecureTcpIp
|
SecureTcpIp,
|
||||||
|
/// <summary>
|
||||||
|
/// Used when comms needs to be handled in SIMPL and bridged opposite the normal direction
|
||||||
|
/// </summary>
|
||||||
|
ComBridge,
|
||||||
|
/// <summary>
|
||||||
|
/// InfinetEX control
|
||||||
|
/// </summary>
|
||||||
|
InfinetEx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
24
src/PepperDash.Core/Comm/eStreamDebuggingDataTypeSettings.cs
Normal file
24
src/PepperDash.Core/Comm/eStreamDebuggingDataTypeSettings.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace PepperDash.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The available settings for stream debugging data format types
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum eStreamDebuggingDataTypeSettings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Debug data in byte format
|
||||||
|
/// </summary>
|
||||||
|
Bytes = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// Debug data in text format
|
||||||
|
/// </summary>
|
||||||
|
Text = 1,
|
||||||
|
/// <summary>
|
||||||
|
/// Debug data in both byte and text formats
|
||||||
|
/// </summary>
|
||||||
|
Both = Bytes | Text
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src/PepperDash.Core/Comm/eStreamDebuggingSetting.cs
Normal file
28
src/PepperDash.Core/Comm/eStreamDebuggingSetting.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace PepperDash.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The available settings for stream debugging
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum eStreamDebuggingSetting
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Debug off
|
||||||
|
/// </summary>
|
||||||
|
Off = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// Debug received data
|
||||||
|
/// </summary>
|
||||||
|
Rx = 1,
|
||||||
|
/// <summary>
|
||||||
|
/// Debug transmitted data
|
||||||
|
/// </summary>
|
||||||
|
Tx = 2,
|
||||||
|
/// <summary>
|
||||||
|
/// Debug both received and transmitted data
|
||||||
|
/// </summary>
|
||||||
|
Both = Rx | Tx
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
using Crestron.SimplSharp.CrestronSockets;
|
using Crestron.SimplSharp.CrestronSockets;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace PepperDash.Core
|
namespace PepperDash.Core
|
||||||
@@ -42,7 +39,7 @@ namespace PepperDash.Core
|
|||||||
/// Defines the contract for IBasicCommunication
|
/// Defines the contract for IBasicCommunication
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IBasicCommunication : ICommunicationReceiver
|
public interface IBasicCommunication : ICommunicationReceiver
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send text to the device
|
/// Send text to the device
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -54,7 +51,7 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="bytes"></param>
|
/// <param name="bytes"></param>
|
||||||
void SendBytes(byte[] bytes);
|
void SendBytes(byte[] bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a device that implements IBasicCommunication and IStreamDebugging
|
/// Represents a device that implements IBasicCommunication and IStreamDebugging
|
||||||
@@ -67,7 +64,7 @@ namespace PepperDash.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a device with stream debugging capablities
|
/// Represents a device with stream debugging capablities
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IStreamDebugging
|
public interface IStreamDebugging : IKeyed
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Object to enable stream debugging
|
/// Object to enable stream debugging
|
||||||
@@ -76,12 +73,12 @@ namespace PepperDash.Core
|
|||||||
CommunicationStreamDebugging StreamDebugging { get; }
|
CommunicationStreamDebugging StreamDebugging { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For IBasicCommunication classes that have SocketStatus. GenericSshClient,
|
/// For IBasicCommunication classes that have SocketStatus. GenericSshClient,
|
||||||
/// GenericTcpIpClient
|
/// GenericTcpIpClient
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISocketStatus : IBasicCommunication
|
public interface ISocketStatus : IBasicCommunication
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Notifies of socket status changes
|
/// Notifies of socket status changes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -93,7 +90,7 @@ namespace PepperDash.Core
|
|||||||
[JsonProperty("clientStatus")]
|
[JsonProperty("clientStatus")]
|
||||||
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
|
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
|
||||||
SocketStatus ClientStatus { get; }
|
SocketStatus ClientStatus { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Describes a device that implements ISocketStatus and IStreamDebugging
|
/// Describes a device that implements ISocketStatus and IStreamDebugging
|
||||||
@@ -107,24 +104,24 @@ namespace PepperDash.Core
|
|||||||
/// Describes a device that can automatically attempt to reconnect
|
/// Describes a device that can automatically attempt to reconnect
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IAutoReconnect
|
public interface IAutoReconnect
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enable automatic recconnect
|
/// Enable automatic recconnect
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("autoReconnect")]
|
[JsonProperty("autoReconnect")]
|
||||||
bool AutoReconnect { get; set; }
|
bool AutoReconnect { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interval in ms to attempt automatic recconnections
|
/// Interval in ms to attempt automatic recconnections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("autoReconnectIntervalMs")]
|
[JsonProperty("autoReconnectIntervalMs")]
|
||||||
int AutoReconnectIntervalMs { get; set; }
|
int AutoReconnectIntervalMs { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum eGenericCommMethodStatusChangeType
|
public enum eGenericCommMethodStatusChangeType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Connected
|
/// Connected
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -133,45 +130,45 @@ namespace PepperDash.Core
|
|||||||
/// Disconnected
|
/// Disconnected
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Disconnected
|
Disconnected
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This delegate defines handler for IBasicCommunication status changes
|
/// This delegate defines handler for IBasicCommunication status changes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="comm">Device firing the status change</param>
|
/// <param name="comm">Device firing the status change</param>
|
||||||
/// <param name="status"></param>
|
/// <param name="status"></param>
|
||||||
public delegate void GenericCommMethodStatusHandler(IBasicCommunication comm, eGenericCommMethodStatusChangeType status);
|
public delegate void GenericCommMethodStatusHandler(IBasicCommunication comm, eGenericCommMethodStatusChangeType status);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GenericCommMethodReceiveBytesArgs : EventArgs
|
public class GenericCommMethodReceiveBytesArgs : EventArgs
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Bytes
|
/// Gets or sets the Bytes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[] Bytes { get; private set; }
|
public byte[] Bytes { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="bytes"></param>
|
/// <param name="bytes"></param>
|
||||||
public GenericCommMethodReceiveBytesArgs(byte[] bytes)
|
public GenericCommMethodReceiveBytesArgs(byte[] bytes)
|
||||||
{
|
{
|
||||||
Bytes = bytes;
|
Bytes = bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// S+ Constructor
|
/// S+ Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public GenericCommMethodReceiveBytesArgs() { }
|
public GenericCommMethodReceiveBytesArgs() { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GenericCommMethodReceiveTextArgs : EventArgs
|
public class GenericCommMethodReceiveTextArgs : EventArgs
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -185,9 +182,9 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text"></param>
|
/// <param name="text"></param>
|
||||||
public GenericCommMethodReceiveTextArgs(string text)
|
public GenericCommMethodReceiveTextArgs(string text)
|
||||||
{
|
{
|
||||||
Text = text;
|
Text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
@@ -195,59 +192,14 @@ namespace PepperDash.Core
|
|||||||
/// <param name="text"></param>
|
/// <param name="text"></param>
|
||||||
/// <param name="delimiter"></param>
|
/// <param name="delimiter"></param>
|
||||||
public GenericCommMethodReceiveTextArgs(string text, string delimiter)
|
public GenericCommMethodReceiveTextArgs(string text, string delimiter)
|
||||||
:this(text)
|
: this(text)
|
||||||
{
|
{
|
||||||
Delimiter = delimiter;
|
Delimiter = delimiter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// S+ Constructor
|
|
||||||
/// </summary>
|
|
||||||
public GenericCommMethodReceiveTextArgs() { }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class ComTextHelper
|
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets escaped text for a byte array
|
/// S+ Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="bytes"></param>
|
public GenericCommMethodReceiveTextArgs() { }
|
||||||
/// <returns></returns>
|
}
|
||||||
public static string GetEscapedText(byte[] bytes)
|
|
||||||
{
|
|
||||||
return String.Concat(bytes.Select(b => string.Format(@"[{0:X2}]", (int)b)).ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets escaped text for a string
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <summary>
|
|
||||||
/// GetEscapedText method
|
|
||||||
/// </summary>
|
|
||||||
public static string GetEscapedText(string text)
|
|
||||||
{
|
|
||||||
var bytes = Encoding.GetEncoding(28591).GetBytes(text);
|
|
||||||
return String.Concat(bytes.Select(b => string.Format(@"[{0:X2}]", (int)b)).ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets debug text for a string
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <summary>
|
|
||||||
/// GetDebugText method
|
|
||||||
/// </summary>
|
|
||||||
public static string GetDebugText(string text)
|
|
||||||
{
|
|
||||||
return Regex.Replace(text, @"[^\u0020-\u007E]", a => GetEscapedText(a.Value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -9,40 +9,59 @@ using Serilog.Events;
|
|||||||
|
|
||||||
namespace PepperDash.Core.Config
|
namespace PepperDash.Core.Config
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads a Portal formatted config file
|
/// Reads a Portal formatted config file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PortalConfigReader
|
public class PortalConfigReader
|
||||||
{
|
{
|
||||||
/// <summary>
|
const string template = "template";
|
||||||
/// Reads the config file, checks if it needs a merge, merges and saves, then returns the merged Object.
|
const string system = "system";
|
||||||
/// </summary>
|
const string systemUrl = "system_url";
|
||||||
/// <returns>JObject of config file</returns>
|
const string templateUrl = "template_url";
|
||||||
public static void ReadAndMergeFileIfNecessary(string filePath, string savePath)
|
const string info = "info";
|
||||||
|
const string devices = "devices";
|
||||||
|
const string rooms = "rooms";
|
||||||
|
const string sourceLists = "sourceLists";
|
||||||
|
const string destinationLists = "destinationLists";
|
||||||
|
const string cameraLists = "cameraLists";
|
||||||
|
const string audioControlPointLists = "audioControlPointLists";
|
||||||
|
|
||||||
|
const string tieLines = "tieLines";
|
||||||
|
const string joinMaps = "joinMaps";
|
||||||
|
const string global = "global";
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads the config file, checks if it needs a merge, merges and saves, then returns the merged Object.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>JObject of config file</returns>
|
||||||
|
public static void ReadAndMergeFileIfNecessary(string filePath, string savePath)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!File.Exists(filePath))
|
if (!File.Exists(filePath))
|
||||||
{
|
{
|
||||||
Debug.Console(1, Debug.ErrorLogLevel.Error,
|
Debug.LogError(
|
||||||
"ERROR: Configuration file not present. Please load file to {0} and reset program", filePath);
|
"ERROR: Configuration file not present. Please load file to {0} and reset program", filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
using (StreamReader fs = new StreamReader(filePath))
|
using (StreamReader fs = new StreamReader(filePath))
|
||||||
{
|
{
|
||||||
var jsonObj = JObject.Parse(fs.ReadToEnd());
|
var jsonObj = JObject.Parse(fs.ReadToEnd());
|
||||||
if(jsonObj["template"] != null && jsonObj["system"] != null)
|
if(jsonObj[template] != null && jsonObj[system] != null)
|
||||||
{
|
{
|
||||||
// it's a double-config, merge it.
|
// it's a double-config, merge it.
|
||||||
var merged = MergeConfigs(jsonObj);
|
var merged = MergeConfigs(jsonObj);
|
||||||
if (jsonObj["system_url"] != null)
|
if (jsonObj[systemUrl] != null)
|
||||||
{
|
{
|
||||||
merged["systemUrl"] = jsonObj["system_url"].Value<string>();
|
merged[systemUrl] = jsonObj[systemUrl].Value<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jsonObj["template_url"] != null)
|
if (jsonObj[templateUrl] != null)
|
||||||
{
|
{
|
||||||
merged["templateUrl"] = jsonObj["template_url"].Value<string>();
|
merged[templateUrl] = jsonObj[templateUrl].Value<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonObj = merged;
|
jsonObj = merged;
|
||||||
@@ -77,62 +96,62 @@ namespace PepperDash.Core.Config
|
|||||||
var merged = new JObject();
|
var merged = new JObject();
|
||||||
|
|
||||||
// Put together top-level objects
|
// Put together top-level objects
|
||||||
if (system["info"] != null)
|
if (system[info] != null)
|
||||||
merged.Add("info", Merge(template["info"], system["info"], "infO"));
|
merged.Add(info, Merge(template[info], system[info], info));
|
||||||
else
|
else
|
||||||
merged.Add("info", template["info"]);
|
merged.Add(info, template[info]);
|
||||||
|
|
||||||
merged.Add("devices", MergeArraysOnTopLevelProperty(template["devices"] as JArray,
|
merged.Add(devices, MergeArraysOnTopLevelProperty(template[devices] as JArray,
|
||||||
system["devices"] as JArray, "key", "devices"));
|
system[devices] as JArray, "key", devices));
|
||||||
|
|
||||||
if (system["rooms"] == null)
|
if (system[rooms] == null)
|
||||||
merged.Add("rooms", template["rooms"]);
|
merged.Add(rooms, template[rooms]);
|
||||||
else
|
else
|
||||||
merged.Add("rooms", MergeArraysOnTopLevelProperty(template["rooms"] as JArray,
|
merged.Add(rooms, MergeArraysOnTopLevelProperty(template[rooms] as JArray,
|
||||||
system["rooms"] as JArray, "key", "rooms"));
|
system[rooms] as JArray, "key", rooms));
|
||||||
|
|
||||||
if (system["sourceLists"] == null)
|
if (system[sourceLists] == null)
|
||||||
merged.Add("sourceLists", template["sourceLists"]);
|
merged.Add(sourceLists, template[sourceLists]);
|
||||||
else
|
else
|
||||||
merged.Add("sourceLists", Merge(template["sourceLists"], system["sourceLists"], "sourceLists"));
|
merged.Add(sourceLists, Merge(template[sourceLists], system[sourceLists], sourceLists));
|
||||||
|
|
||||||
if (system["destinationLists"] == null)
|
if (system[destinationLists] == null)
|
||||||
merged.Add("destinationLists", template["destinationLists"]);
|
merged.Add(destinationLists, template[destinationLists]);
|
||||||
else
|
else
|
||||||
merged.Add("destinationLists",
|
merged.Add(destinationLists,
|
||||||
Merge(template["destinationLists"], system["destinationLists"], "destinationLists"));
|
Merge(template[destinationLists], system[destinationLists], destinationLists));
|
||||||
|
|
||||||
|
|
||||||
if (system["cameraLists"] == null)
|
if (system[cameraLists] == null)
|
||||||
merged.Add("cameraLists", template["cameraLists"]);
|
merged.Add(cameraLists, template[cameraLists]);
|
||||||
else
|
else
|
||||||
merged.Add("cameraLists", Merge(template["cameraLists"], system["cameraLists"], "cameraLists"));
|
merged.Add(cameraLists, Merge(template[cameraLists], system[cameraLists], cameraLists));
|
||||||
|
|
||||||
if (system["audioControlPointLists"] == null)
|
if (system[audioControlPointLists] == null)
|
||||||
merged.Add("audioControlPointLists", template["audioControlPointLists"]);
|
merged.Add(audioControlPointLists, template[audioControlPointLists]);
|
||||||
else
|
else
|
||||||
merged.Add("audioControlPointLists",
|
merged.Add(audioControlPointLists,
|
||||||
Merge(template["audioControlPointLists"], system["audioControlPointLists"], "audioControlPointLists"));
|
Merge(template[audioControlPointLists], system[audioControlPointLists], audioControlPointLists));
|
||||||
|
|
||||||
|
|
||||||
// Template tie lines take precedence. Config tool doesn't do them at system
|
// Template tie lines take precedence. Config tool doesn't do them at system
|
||||||
// level anyway...
|
// level anyway...
|
||||||
if (template["tieLines"] != null)
|
if (template[tieLines] != null)
|
||||||
merged.Add("tieLines", template["tieLines"]);
|
merged.Add(tieLines, template[tieLines]);
|
||||||
else if (system["tieLines"] != null)
|
else if (system[tieLines] != null)
|
||||||
merged.Add("tieLines", system["tieLines"]);
|
merged.Add(tieLines, system[tieLines]);
|
||||||
else
|
else
|
||||||
merged.Add("tieLines", new JArray());
|
merged.Add(tieLines, new JArray());
|
||||||
|
|
||||||
if (template["joinMaps"] != null)
|
if (template[joinMaps] != null)
|
||||||
merged.Add("joinMaps", template["joinMaps"]);
|
merged.Add(joinMaps, template[joinMaps]);
|
||||||
else
|
else
|
||||||
merged.Add("joinMaps", new JObject());
|
merged.Add(joinMaps, new JObject());
|
||||||
|
|
||||||
if (system["global"] != null)
|
if (system[global] != null)
|
||||||
merged.Add("global", Merge(template["global"], system["global"], "global"));
|
merged.Add(global, Merge(template[global], system[global], global));
|
||||||
else
|
else
|
||||||
merged.Add("global", template["global"]);
|
merged.Add(global, template[global]);
|
||||||
|
|
||||||
//Debug.Console(2, "MERGED CONFIG RESULT: \x0d\x0a{0}", merged);
|
//Debug.Console(2, "MERGED CONFIG RESULT: \x0d\x0a{0}", merged);
|
||||||
return merged;
|
return merged;
|
||||||
@@ -228,7 +247,7 @@ namespace PepperDash.Core.Config
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.Console(1, Debug.ErrorLogLevel.Warning, "Cannot merge items at path {0}: \r{1}", propPath, e);
|
Debug.LogError($"Cannot merge items at path {propPath}: \r{e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,20 +40,20 @@ namespace PepperDash.Core
|
|||||||
|
|
||||||
private static ILogger _logger;
|
private static ILogger _logger;
|
||||||
|
|
||||||
private static readonly LoggingLevelSwitch _consoleLoggingLevelSwitch;
|
private static readonly LoggingLevelSwitch _consoleLogLevelSwitch;
|
||||||
|
|
||||||
private static readonly LoggingLevelSwitch _websocketLoggingLevelSwitch;
|
private static readonly LoggingLevelSwitch _websocketLogLevelSwitch;
|
||||||
|
|
||||||
private static readonly LoggingLevelSwitch _errorLogLevelSwitch;
|
private static readonly LoggingLevelSwitch _errorLogLevelSwitch;
|
||||||
|
|
||||||
private static readonly LoggingLevelSwitch _fileLevelSwitch;
|
private static readonly LoggingLevelSwitch _fileLogLevelSwitch;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the minimum log level for the websocket sink.
|
/// Gets the minimum log level for the websocket sink.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static LogEventLevel WebsocketMinimumLogLevel
|
public static LogEventLevel WebsocketMinimumLogLevel
|
||||||
{
|
{
|
||||||
get { return _websocketLoggingLevelSwitch.MinimumLevel; }
|
get { return _websocketLogLevelSwitch.MinimumLevel; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly DebugWebsocketSink _websocketSink;
|
private static readonly DebugWebsocketSink _websocketSink;
|
||||||
@@ -138,13 +138,13 @@ namespace PepperDash.Core
|
|||||||
|
|
||||||
var defaultFileLogLevel = GetStoredLogEventLevel(FileLevelStoreKey);
|
var defaultFileLogLevel = GetStoredLogEventLevel(FileLevelStoreKey);
|
||||||
|
|
||||||
_consoleLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultConsoleLevel);
|
_consoleLogLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultConsoleLevel);
|
||||||
|
|
||||||
_websocketLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultWebsocketLevel);
|
_websocketLogLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultWebsocketLevel);
|
||||||
|
|
||||||
_errorLogLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultErrorLogLevel);
|
_errorLogLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultErrorLogLevel);
|
||||||
|
|
||||||
_fileLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultFileLogLevel);
|
_fileLogLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultFileLogLevel);
|
||||||
|
|
||||||
_websocketSink = new DebugWebsocketSink(new JsonFormatter(renderMessage: true));
|
_websocketSink = new DebugWebsocketSink(new JsonFormatter(renderMessage: true));
|
||||||
|
|
||||||
@@ -162,14 +162,14 @@ namespace PepperDash.Core
|
|||||||
.MinimumLevel.Verbose()
|
.MinimumLevel.Verbose()
|
||||||
.Enrich.FromLogContext()
|
.Enrich.FromLogContext()
|
||||||
.Enrich.With(new CrestronEnricher())
|
.Enrich.With(new CrestronEnricher())
|
||||||
.WriteTo.Sink(new DebugConsoleSink(new ExpressionTemplate("[{@t:yyyy-MM-dd HH:mm:ss.fff}][{@l:u4}][{App}]{#if Key is not null}[{Key}]{#end} {@m}{#if @x is not null}\r\n{@x}{#end}")), levelSwitch: _consoleLoggingLevelSwitch)
|
.WriteTo.Sink(new DebugConsoleSink(new ExpressionTemplate("[{@t:yyyy-MM-dd HH:mm:ss.fff}][{@l:u4}][{App}]{#if Key is not null}[{Key}]{#end} {@m}{#if @x is not null}\r\n{@x}{#end}")), levelSwitch: _consoleLogLevelSwitch)
|
||||||
.WriteTo.Sink(_websocketSink, levelSwitch: _websocketLoggingLevelSwitch)
|
.WriteTo.Sink(_websocketSink, levelSwitch: _websocketLogLevelSwitch)
|
||||||
.WriteTo.Sink(new DebugErrorLogSink(new ExpressionTemplate(errorLogTemplate)), levelSwitch: _errorLogLevelSwitch)
|
.WriteTo.Sink(new DebugErrorLogSink(new ExpressionTemplate(errorLogTemplate)), levelSwitch: _errorLogLevelSwitch)
|
||||||
.WriteTo.File(new RenderedCompactJsonFormatter(), logFilePath,
|
.WriteTo.File(new RenderedCompactJsonFormatter(), logFilePath,
|
||||||
rollingInterval: RollingInterval.Day,
|
rollingInterval: RollingInterval.Day,
|
||||||
restrictedToMinimumLevel: LogEventLevel.Debug,
|
restrictedToMinimumLevel: LogEventLevel.Debug,
|
||||||
retainedFileCountLimit: CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? 30 : 60,
|
retainedFileCountLimit: CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? 7 : 14,
|
||||||
levelSwitch: _fileLevelSwitch
|
levelSwitch: _fileLogLevelSwitch
|
||||||
);
|
);
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -237,10 +237,13 @@ namespace PepperDash.Core
|
|||||||
if (DoNotLoadConfigOnNextBoot)
|
if (DoNotLoadConfigOnNextBoot)
|
||||||
CrestronConsole.PrintLine(string.Format("Program {0} will not load config after next boot. Use console command go:{0} to load the config manually", InitialParametersClass.ApplicationNumber));
|
CrestronConsole.PrintLine(string.Format("Program {0} will not load config after next boot. Use console command go:{0} to load the config manually", InitialParametersClass.ApplicationNumber));
|
||||||
|
|
||||||
_consoleLoggingLevelSwitch.MinimumLevelChanged += (sender, args) =>
|
_errorLogLevelSwitch.MinimumLevelChanged += (sender, args) =>
|
||||||
{
|
{
|
||||||
LogMessage(LogEventLevel.Information, "Console debug level set to {minimumLevel}", _consoleLoggingLevelSwitch.MinimumLevel);
|
LogMessage(LogEventLevel.Information, "Error log debug level set to {minimumLevel}", _errorLogLevelSwitch.MinimumLevel);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Set initial error log level based on platform && stored level. If appliance, use stored level, otherwise default to verbose
|
||||||
|
SetErrorLogMinimumDebugLevel(CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? _errorLogLevelSwitch.MinimumLevel : LogEventLevel.Verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -273,9 +276,9 @@ namespace PepperDash.Core
|
|||||||
{
|
{
|
||||||
CrestronConsole.Print($"Unable to retrieve stored log level for {levelStoreKey}.\r\nError: {result}.\r\nSetting level to {LogEventLevel.Information}\r\n");
|
CrestronConsole.Print($"Unable to retrieve stored log level for {levelStoreKey}.\r\nError: {result}.\r\nSetting level to {LogEventLevel.Information}\r\n");
|
||||||
|
|
||||||
CrestronDataStoreStatic.SetLocalIntValue(levelStoreKey, (int)LogEventLevel.Information);
|
CrestronDataStoreStatic.SetLocalIntValue(levelStoreKey, levelStoreKey == ErrorLogLevelStoreKey ? (int)LogEventLevel.Warning : (int)LogEventLevel.Information);
|
||||||
|
|
||||||
return LogEventLevel.Information;
|
return levelStoreKey == ErrorLogLevelStoreKey ? LogEventLevel.Warning : LogEventLevel.Information;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logLevel < 0 || logLevel > 5)
|
if (logLevel < 0 || logLevel > 5)
|
||||||
@@ -284,6 +287,8 @@ namespace PepperDash.Core
|
|||||||
return LogEventLevel.Information;
|
return LogEventLevel.Information;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CrestronConsole.PrintLine($"Stored log level for {levelStoreKey} is {logLevel}");
|
||||||
|
|
||||||
return (LogEventLevel)logLevel;
|
return (LogEventLevel)logLevel;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -349,7 +354,11 @@ namespace PepperDash.Core
|
|||||||
if (levelString.Trim() == "?")
|
if (levelString.Trim() == "?")
|
||||||
{
|
{
|
||||||
CrestronConsole.ConsoleCommandResponse(
|
CrestronConsole.ConsoleCommandResponse(
|
||||||
"Used to set the minimum level of debug messages to be printed to the console:\r\n" +
|
"Used to set the minimum level of debug messages:\r\n" +
|
||||||
|
"Usage: appdebug:P [sink] [level]\r\n" +
|
||||||
|
" sink: console (default), errorlog, file, all\r\n" +
|
||||||
|
" all: sets all sinks to the specified level\r\n" +
|
||||||
|
" level: 0-5 or LogEventLevel name\r\n" +
|
||||||
$"{_logLevels[0]} = 0\r\n" +
|
$"{_logLevels[0]} = 0\r\n" +
|
||||||
$"{_logLevels[1]} = 1\r\n" +
|
$"{_logLevels[1]} = 1\r\n" +
|
||||||
$"{_logLevels[2]} = 2\r\n" +
|
$"{_logLevels[2]} = 2\r\n" +
|
||||||
@@ -361,32 +370,88 @@ namespace PepperDash.Core
|
|||||||
|
|
||||||
if (string.IsNullOrEmpty(levelString.Trim()))
|
if (string.IsNullOrEmpty(levelString.Trim()))
|
||||||
{
|
{
|
||||||
CrestronConsole.ConsoleCommandResponse("AppDebug level = {0}", _consoleLoggingLevelSwitch.MinimumLevel);
|
CrestronConsole.ConsoleCommandResponse("Console log level = {0}\r\n", _consoleLogLevelSwitch.MinimumLevel);
|
||||||
|
CrestronConsole.ConsoleCommandResponse("File log level = {0}\r\n", _fileLogLevelSwitch.MinimumLevel);
|
||||||
|
CrestronConsole.ConsoleCommandResponse("Error log level = {0}\r\n", _errorLogLevelSwitch.MinimumLevel);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (int.TryParse(levelString, out var levelInt))
|
// Parse tokens: first token is sink (defaults to console), second token is level
|
||||||
|
var tokens = levelString.Trim().Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
string sinkName;
|
||||||
|
string levelToken;
|
||||||
|
|
||||||
|
if (tokens.Length == 1)
|
||||||
|
{
|
||||||
|
// Single token - assume it's a level for console sink
|
||||||
|
sinkName = "console";
|
||||||
|
levelToken = tokens[0];
|
||||||
|
}
|
||||||
|
else if (tokens.Length == 2)
|
||||||
|
{
|
||||||
|
// Two tokens - first is sink, second is level
|
||||||
|
sinkName = tokens[0].ToLowerInvariant();
|
||||||
|
levelToken = tokens[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CrestronConsole.ConsoleCommandResponse("Usage: appdebug:P [sink] [level]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the level using the same logic as before
|
||||||
|
LogEventLevel level;
|
||||||
|
|
||||||
|
if (int.TryParse(levelToken, out var levelInt))
|
||||||
{
|
{
|
||||||
if (levelInt < 0 || levelInt > 5)
|
if (levelInt < 0 || levelInt > 5)
|
||||||
{
|
{
|
||||||
CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level. If using a number, value must be between 0-5");
|
CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelToken} to valid log level. If using a number, value must be between 0-5");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SetDebugLevel((uint)levelInt);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Enum.TryParse<LogEventLevel>(levelString, true, out var levelEnum))
|
if (!_logLevels.TryGetValue((uint)levelInt, out level))
|
||||||
|
{
|
||||||
|
level = LogEventLevel.Information;
|
||||||
|
CrestronConsole.ConsoleCommandResponse($"{levelInt} not valid. Setting level to {level}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Enum.TryParse(levelToken, true, out level))
|
||||||
{
|
{
|
||||||
SetDebugLevel(levelEnum);
|
// Successfully parsed as LogEventLevel enum
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelToken} to valid log level");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level");
|
// Set the level for the specified sink
|
||||||
|
switch (sinkName)
|
||||||
|
{
|
||||||
|
case "console":
|
||||||
|
SetDebugLevel(level);
|
||||||
|
break;
|
||||||
|
case "errorlog":
|
||||||
|
SetErrorLogMinimumDebugLevel(level);
|
||||||
|
break;
|
||||||
|
case "file":
|
||||||
|
SetFileMinimumDebugLevel(level);
|
||||||
|
break;
|
||||||
|
case "all":
|
||||||
|
SetDebugLevel(level);
|
||||||
|
SetErrorLogMinimumDebugLevel(level);
|
||||||
|
SetFileMinimumDebugLevel(level);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
CrestronConsole.ConsoleCommandResponse($"Error: Unknown sink '{sinkName}'. Valid sinks: console, errorlog, file");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
CrestronConsole.ConsoleCommandResponse("Usage: appdebug:P [0-5]");
|
CrestronConsole.ConsoleCommandResponse("Usage: appdebug:P [sink] [level]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,10 +481,10 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static void SetDebugLevel(LogEventLevel level)
|
public static void SetDebugLevel(LogEventLevel level)
|
||||||
{
|
{
|
||||||
_consoleLoggingLevelSwitch.MinimumLevel = level;
|
_consoleLogLevelSwitch.MinimumLevel = level;
|
||||||
|
|
||||||
CrestronConsole.ConsoleCommandResponse("[Application {0}], Debug level set to {1}\r\n",
|
CrestronConsole.ConsoleCommandResponse("[Application {0}] Debug level set to {1}\r\n",
|
||||||
InitialParametersClass.ApplicationNumber, _consoleLoggingLevelSwitch.MinimumLevel);
|
InitialParametersClass.ApplicationNumber, _consoleLogLevelSwitch.MinimumLevel);
|
||||||
|
|
||||||
CrestronConsole.ConsoleCommandResponse($"Storing level {level}:{(int)level}");
|
CrestronConsole.ConsoleCommandResponse($"Storing level {level}:{(int)level}");
|
||||||
|
|
||||||
@@ -436,14 +501,14 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static void SetWebSocketMinimumDebugLevel(LogEventLevel level)
|
public static void SetWebSocketMinimumDebugLevel(LogEventLevel level)
|
||||||
{
|
{
|
||||||
_websocketLoggingLevelSwitch.MinimumLevel = level;
|
_websocketLogLevelSwitch.MinimumLevel = level;
|
||||||
|
|
||||||
var err = CrestronDataStoreStatic.SetLocalUintValue(WebSocketLevelStoreKey, (uint)level);
|
var err = CrestronDataStoreStatic.SetLocalUintValue(WebSocketLevelStoreKey, (uint)level);
|
||||||
|
|
||||||
if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
|
if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
|
||||||
LogMessage(LogEventLevel.Information, "Error saving websocket debug level setting: {erro}", err);
|
LogMessage(LogEventLevel.Information, "Error saving websocket debug level setting: {erro}", err);
|
||||||
|
|
||||||
LogMessage(LogEventLevel.Information, "Websocket debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel);
|
LogMessage(LogEventLevel.Information, "Websocket debug level set to {0}", _websocketLogLevelSwitch.MinimumLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -453,12 +518,17 @@ namespace PepperDash.Core
|
|||||||
{
|
{
|
||||||
_errorLogLevelSwitch.MinimumLevel = level;
|
_errorLogLevelSwitch.MinimumLevel = level;
|
||||||
|
|
||||||
var err = CrestronDataStoreStatic.SetLocalUintValue(ErrorLogLevelStoreKey, (uint)level);
|
CrestronConsole.ConsoleCommandResponse("[Application {0}] Error log level set to {1}\r\n",
|
||||||
|
InitialParametersClass.ApplicationNumber, _errorLogLevelSwitch.MinimumLevel);
|
||||||
|
|
||||||
|
CrestronConsole.ConsoleCommandResponse($"Storing level {level}:{(int)level}");
|
||||||
|
|
||||||
|
var err = CrestronDataStoreStatic.SetLocalIntValue(ErrorLogLevelStoreKey, (int)level);
|
||||||
|
|
||||||
|
CrestronConsole.ConsoleCommandResponse($"Store result: {err}:{(int)level}");
|
||||||
|
|
||||||
if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
|
if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
|
||||||
LogMessage(LogEventLevel.Information, "Error saving Error Log debug level setting: {error}", err);
|
CrestronConsole.PrintLine($"Error saving error log debug level setting: {err}");
|
||||||
|
|
||||||
LogMessage(LogEventLevel.Information, "Error log debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -466,14 +536,19 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static void SetFileMinimumDebugLevel(LogEventLevel level)
|
public static void SetFileMinimumDebugLevel(LogEventLevel level)
|
||||||
{
|
{
|
||||||
_errorLogLevelSwitch.MinimumLevel = level;
|
_fileLogLevelSwitch.MinimumLevel = level;
|
||||||
|
|
||||||
var err = CrestronDataStoreStatic.SetLocalUintValue(ErrorLogLevelStoreKey, (uint)level);
|
CrestronConsole.ConsoleCommandResponse("[Application {0}] File log level set to {1}\r\n",
|
||||||
|
InitialParametersClass.ApplicationNumber, _fileLogLevelSwitch.MinimumLevel);
|
||||||
|
|
||||||
|
CrestronConsole.ConsoleCommandResponse($"Storing level {level}:{(int)level}");
|
||||||
|
|
||||||
|
var err = CrestronDataStoreStatic.SetLocalIntValue(FileLevelStoreKey, (int)level);
|
||||||
|
|
||||||
|
CrestronConsole.ConsoleCommandResponse($"Store result: {err}:{(int)level}");
|
||||||
|
|
||||||
if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
|
if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
|
||||||
LogMessage(LogEventLevel.Information, "Error saving File debug level setting: {error}", err);
|
CrestronConsole.PrintLine($"Error saving file debug level setting: {err}");
|
||||||
|
|
||||||
LogMessage(LogEventLevel.Information, "File debug level set to {0}", _websocketLoggingLevelSwitch.MinimumLevel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1006,9 +1081,6 @@ namespace PepperDash.Core
|
|||||||
/// Logs to Console when at-level, and all messages to error log
|
/// Logs to Console when at-level, and all messages to error log
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")]
|
[Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")]
|
||||||
/// <summary>
|
|
||||||
/// Console method
|
|
||||||
/// </summary>
|
|
||||||
public static void Console(uint level, ErrorLogLevel errorLogLevel,
|
public static void Console(uint level, ErrorLogLevel errorLogLevel,
|
||||||
string format, params object[] items)
|
string format, params object[] items)
|
||||||
{
|
{
|
||||||
@@ -1021,9 +1093,6 @@ namespace PepperDash.Core
|
|||||||
/// it will only be written to the log.
|
/// it will only be written to the log.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")]
|
[Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")]
|
||||||
/// <summary>
|
|
||||||
/// ConsoleWithLog method
|
|
||||||
/// </summary>
|
|
||||||
public static void ConsoleWithLog(uint level, string format, params object[] items)
|
public static void ConsoleWithLog(uint level, string format, params object[] items)
|
||||||
{
|
{
|
||||||
LogMessage(level, format, items);
|
LogMessage(level, format, items);
|
||||||
|
|||||||
@@ -3,26 +3,28 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
using System.Reflection;
|
|
||||||
using Crestron.SimplSharpPro;
|
using Crestron.SimplSharpPro;
|
||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
using Crestron.SimplSharpPro.EthernetCommunication;
|
using Crestron.SimplSharpPro.EthernetCommunication;
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Core.Logging;
|
||||||
using PepperDash.Essentials.Core.Config;
|
using PepperDash.Essentials.Core.Config;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
|
||||||
//using PepperDash.Essentials.Devices.Common.Cameras;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core.Bridges
|
namespace PepperDash.Essentials.Core.Bridges
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base class for bridge API variants
|
/// Base class for bridge API variants
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("Will be removed in v3.0.0")]
|
||||||
public abstract class BridgeApi : EssentialsDevice
|
public abstract class BridgeApi : EssentialsDevice
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Device key</param>
|
||||||
protected BridgeApi(string key) :
|
protected BridgeApi(string key) :
|
||||||
base(key)
|
base(key)
|
||||||
{
|
{
|
||||||
@@ -31,23 +33,36 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a EiscApiAdvanced
|
/// Class to link devices and rooms to an EISC Instance
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class EiscApiAdvanced : BridgeApi, ICommunicationMonitor
|
public class EiscApiAdvanced : BridgeApi, ICommunicationMonitor
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the PropertiesConfig
|
||||||
|
/// </summary>
|
||||||
public EiscApiPropertiesConfig PropertiesConfig { get; private set; }
|
public EiscApiPropertiesConfig PropertiesConfig { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the JoinMaps dictionary
|
||||||
|
/// </summary>
|
||||||
public Dictionary<string, JoinMapBaseAdvanced> JoinMaps { get; private set; }
|
public Dictionary<string, JoinMapBaseAdvanced> JoinMaps { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the EISC instance
|
||||||
|
/// </summary>
|
||||||
public BasicTriList Eisc { get; private set; }
|
public BasicTriList Eisc { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dc">Device configuration</param>
|
||||||
|
/// <param name="eisc">EISC instance</param>
|
||||||
public EiscApiAdvanced(DeviceConfig dc, BasicTriList eisc) :
|
public EiscApiAdvanced(DeviceConfig dc, BasicTriList eisc) :
|
||||||
base(dc.Key)
|
base(dc.Key)
|
||||||
{
|
{
|
||||||
JoinMaps = new Dictionary<string, JoinMapBaseAdvanced>();
|
JoinMaps = new Dictionary<string, JoinMapBaseAdvanced>();
|
||||||
|
|
||||||
PropertiesConfig = dc.Properties.ToObject<EiscApiPropertiesConfig>();
|
PropertiesConfig = dc.Properties.ToObject<EiscApiPropertiesConfig>();
|
||||||
//PropertiesConfig = JsonConvert.DeserializeObject<EiscApiPropertiesConfig>(dc.Properties.ToString());
|
|
||||||
|
|
||||||
Eisc = eisc;
|
Eisc = eisc;
|
||||||
|
|
||||||
@@ -62,8 +77,7 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// CustomActivate method
|
/// CustomActivate method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CustomActivate()
|
public override bool CustomActivate()
|
||||||
{
|
{
|
||||||
CommunicationMonitor.Start();
|
CommunicationMonitor.Start();
|
||||||
@@ -85,7 +99,7 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
|
|
||||||
if (PropertiesConfig.Devices == null)
|
if (PropertiesConfig.Devices == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "No devices linked to this bridge");
|
this.LogDebug("No devices linked to this bridge");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,9 +120,7 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, this,
|
this.LogWarning("{deviceKey} is not compatible with this bridge type. Please update the device.", device.Key);
|
||||||
"{0} is not compatible with this bridge type. Please use 'eiscapi' instead, or updae the device.",
|
|
||||||
device.Key);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,34 +135,31 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
|
|
||||||
if (registerResult != eDeviceRegistrationUnRegistrationResponse.Success)
|
if (registerResult != eDeviceRegistrationUnRegistrationResponse.Success)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "Registration result: {0}", registerResult);
|
this.LogVerbose("Registration result: {registerResult}", registerResult);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "EISC registration successful");
|
this.LogDebug("EISC registration successful");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// LinkRooms method
|
/// Link rooms to this EISC. Rooms MUST implement IBridgeAdvanced
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void LinkRooms()
|
public void LinkRooms()
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Linking Rooms...");
|
this.LogDebug("Linking Rooms...");
|
||||||
|
|
||||||
if (PropertiesConfig.Rooms == null)
|
if (PropertiesConfig.Rooms == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "No rooms linked to this bridge.");
|
this.LogDebug("No rooms linked to this bridge.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var room in PropertiesConfig.Rooms)
|
foreach (var room in PropertiesConfig.Rooms)
|
||||||
{
|
{
|
||||||
var rm = DeviceManager.GetDeviceForKey(room.RoomKey) as IBridgeAdvanced;
|
if (!(DeviceManager.GetDeviceForKey(room.RoomKey) is IBridgeAdvanced rm))
|
||||||
|
|
||||||
if (rm == null)
|
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this,
|
this.LogDebug("Room {roomKey} does not implement IBridgeAdvanced. Skipping...", room.RoomKey);
|
||||||
"Room {0} does not implement IBridgeAdvanced. Skipping...", room.RoomKey);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,11 +170,8 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a join map
|
/// Adds a join map
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="deviceKey"></param>
|
/// <param name="deviceKey">The key of the device to add the join map for</param>
|
||||||
/// <param name="joinMap"></param>
|
/// <param name="joinMap">The join map to add</param>
|
||||||
/// <summary>
|
|
||||||
/// AddJoinMap method
|
|
||||||
/// </summary>
|
|
||||||
public void AddJoinMap(string deviceKey, JoinMapBaseAdvanced joinMap)
|
public void AddJoinMap(string deviceKey, JoinMapBaseAdvanced joinMap)
|
||||||
{
|
{
|
||||||
if (!JoinMaps.ContainsKey(deviceKey))
|
if (!JoinMaps.ContainsKey(deviceKey))
|
||||||
@@ -174,14 +180,13 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "Unable to add join map with key '{0}'. Key already exists in JoinMaps dictionary", deviceKey);
|
this.LogWarning("Unable to add join map with key '{deviceKey}'. Key already exists in JoinMaps dictionary", deviceKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// PrintJoinMaps method
|
/// PrintJoinMaps method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <inheritdoc />
|
|
||||||
public virtual void PrintJoinMaps()
|
public virtual void PrintJoinMaps()
|
||||||
{
|
{
|
||||||
CrestronConsole.ConsoleCommandResponse("Join Maps for EISC IPID: {0}\r\n", Eisc.ID.ToString("X"));
|
CrestronConsole.ConsoleCommandResponse("Join Maps for EISC IPID: {0}\r\n", Eisc.ID.ToString("X"));
|
||||||
@@ -192,17 +197,17 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
joinMap.Value.PrintJoinMapInfo();
|
joinMap.Value.PrintJoinMapInfo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MarkdownForBridge method
|
/// MarkdownForBridge method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <inheritdoc />
|
|
||||||
public virtual void MarkdownForBridge(string bridgeKey)
|
public virtual void MarkdownForBridge(string bridgeKey)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Writing Joinmaps to files for EISC IPID: {0}", Eisc.ID.ToString("X"));
|
this.LogInformation("Writing Joinmaps to files for EISC IPID: {eiscId}", Eisc.ID.ToString("X"));
|
||||||
|
|
||||||
foreach (var joinMap in JoinMaps)
|
foreach (var joinMap in JoinMaps)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Generating markdown for device '{0}':", joinMap.Key);
|
this.LogInformation("Generating markdown for device '{deviceKey}':", joinMap.Key);
|
||||||
joinMap.Value.MarkdownJoinMapInfo(joinMap.Key, bridgeKey);
|
joinMap.Value.MarkdownJoinMapInfo(joinMap.Key, bridgeKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,53 +215,45 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prints the join map for a device by key
|
/// Prints the join map for a device by key
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="deviceKey"></param>
|
/// <param name="deviceKey">The key of the device to print the join map for</param>
|
||||||
/// <summary>
|
|
||||||
/// PrintJoinMapForDevice method
|
|
||||||
/// </summary>
|
|
||||||
public void PrintJoinMapForDevice(string deviceKey)
|
public void PrintJoinMapForDevice(string deviceKey)
|
||||||
{
|
{
|
||||||
var joinMap = JoinMaps[deviceKey];
|
var joinMap = JoinMaps[deviceKey];
|
||||||
|
|
||||||
if (joinMap == null)
|
if (joinMap == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Unable to find joinMap for device with key: '{0}'", deviceKey);
|
this.LogInformation("Unable to find joinMap for device with key: '{deviceKey}'", deviceKey);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Join map for device '{0}' on EISC '{1}':", deviceKey, Key);
|
this.LogInformation("Join map for device '{deviceKey}' on EISC '{eiscKey}':", deviceKey, Key);
|
||||||
joinMap.PrintJoinMapInfo();
|
joinMap.PrintJoinMapInfo();
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prints the join map for a device by key
|
/// Prints the join map for a device by key in Markdown format
|
||||||
/// </summary>
|
|
||||||
/// <param name="deviceKey"></param>
|
|
||||||
/// <summary>
|
|
||||||
/// MarkdownJoinMapForDevice method
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="deviceKey">The key of the device to print the join map for</param>
|
||||||
|
/// <param name="bridgeKey">The key of the bridge to use for the Markdown output</param>
|
||||||
public void MarkdownJoinMapForDevice(string deviceKey, string bridgeKey)
|
public void MarkdownJoinMapForDevice(string deviceKey, string bridgeKey)
|
||||||
{
|
{
|
||||||
var joinMap = JoinMaps[deviceKey];
|
var joinMap = JoinMaps[deviceKey];
|
||||||
|
|
||||||
if (joinMap == null)
|
if (joinMap == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Unable to find joinMap for device with key: '{0}'", deviceKey);
|
this.LogInformation("Unable to find joinMap for device with key: '{deviceKey}'", deviceKey);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Join map for device '{0}' on EISC '{1}':", deviceKey, Key);
|
this.LogInformation("Join map for device '{deviceKey}' on EISC '{eiscKey}':", deviceKey, Key);
|
||||||
joinMap.MarkdownJoinMapInfo(deviceKey, bridgeKey);
|
joinMap.MarkdownJoinMapInfo(deviceKey, bridgeKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used for debugging to trigger an action based on a join number and type
|
/// Used for debugging to trigger an action based on a join number and type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="join"></param>
|
/// <param name="join">The join number to execute the action for</param>
|
||||||
/// <param name="type"></param>
|
/// <param name="type">The type of join (digital, analog, serial)</param>
|
||||||
/// <param name="state"></param>
|
/// <param name="state">The state to pass to the action</param>
|
||||||
/// <summary>
|
|
||||||
/// ExecuteJoinAction method
|
|
||||||
/// </summary>
|
|
||||||
public void ExecuteJoinAction(uint join, string type, object state)
|
public void ExecuteJoinAction(uint join, string type, object state)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -265,78 +262,87 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
{
|
{
|
||||||
case "digital":
|
case "digital":
|
||||||
{
|
{
|
||||||
var uo = Eisc.BooleanOutput[join].UserObject as Action<bool>;
|
if (Eisc.BooleanOutput[join].UserObject is Action<bool> userObject)
|
||||||
if (uo != null)
|
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "Executing Action: {0}", uo.ToString());
|
this.LogVerbose("Executing Boolean Action");
|
||||||
uo(Convert.ToBoolean(state));
|
userObject(Convert.ToBoolean(state));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "User Action is null. Nothing to Execute");
|
this.LogVerbose("User Object is null. Nothing to Execute");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "analog":
|
case "analog":
|
||||||
{
|
{
|
||||||
var uo = Eisc.BooleanOutput[join].UserObject as Action<ushort>;
|
if (Eisc.UShortOutput[join].UserObject is Action<ushort> userObject)
|
||||||
if (uo != null)
|
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "Executing Action: {0}", uo.ToString());
|
this.LogVerbose("Executing Analog Action");
|
||||||
uo(Convert.ToUInt16(state));
|
userObject(Convert.ToUInt16(state));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "User Action is null. Nothing to Execute"); break;
|
this.LogVerbose("User Object is null. Nothing to Execute");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case "serial":
|
case "serial":
|
||||||
{
|
{
|
||||||
var uo = Eisc.BooleanOutput[join].UserObject as Action<string>;
|
if (Eisc.StringOutput[join].UserObject is Action<string> userObject)
|
||||||
if (uo != null)
|
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "Executing Action: {0}", uo.ToString());
|
this.LogVerbose("Executing Serial Action");
|
||||||
uo(Convert.ToString(state));
|
userObject(Convert.ToString(state));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "User Action is null. Nothing to Execute");
|
this.LogVerbose("User Object is null. Nothing to Execute");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "Unknown join type. Use digital/serial/analog");
|
this.LogVerbose("Unknown join type. Use digital/serial/analog");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e);
|
this.LogError("ExecuteJoinAction error: {message}", e.Message);
|
||||||
|
this.LogDebug(e, "Stack Trace: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles incoming sig changes
|
/// Handle incoming sig changes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="currentDevice"></param>
|
/// <param name="currentDevice">BasicTriList device that triggered the event</param>
|
||||||
/// <param name="args"></param>
|
/// <param name="args">Event arguments containing the signal information</param>
|
||||||
protected void Eisc_SigChange(object currentDevice, SigEventArgs args)
|
protected void Eisc_SigChange(object currentDevice, SigEventArgs args)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "EiscApiAdvanced change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
|
this.LogVerbose("EiscApiAdvanced change: {type} {number}={value}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
|
||||||
var uo = args.Sig.UserObject;
|
var userObject = args.Sig.UserObject;
|
||||||
|
|
||||||
if (uo == null) return;
|
if (userObject == null) return;
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Executing Action: {0}", uo.ToString());
|
|
||||||
if (uo is Action<bool>)
|
if (userObject is Action<bool>)
|
||||||
(uo as Action<bool>)(args.Sig.BoolValue);
|
{
|
||||||
else if (uo is Action<ushort>)
|
this.LogDebug("Executing Boolean Action");
|
||||||
(uo as Action<ushort>)(args.Sig.UShortValue);
|
(userObject as Action<bool>)(args.Sig.BoolValue);
|
||||||
else if (uo is Action<string>)
|
}
|
||||||
(uo as Action<string>)(args.Sig.StringValue);
|
else if (userObject is Action<ushort>)
|
||||||
|
{
|
||||||
|
this.LogDebug("Executing Analog Action");
|
||||||
|
(userObject as Action<ushort>)(args.Sig.UShortValue);
|
||||||
|
}
|
||||||
|
else if (userObject is Action<string>)
|
||||||
|
{
|
||||||
|
this.LogDebug("Executing Serial Action");
|
||||||
|
(userObject as Action<string>)(args.Sig.StringValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "Error in Eisc_SigChange handler: {0}", e);
|
this.LogError("Eisc_SigChange handler error: {message}", e.Message);
|
||||||
|
this.LogDebug(e, "Stack Trace: ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,22 +361,22 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class EiscApiPropertiesConfig
|
public class EiscApiPropertiesConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("control")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Control
|
/// Gets or sets the Control
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("control")]
|
||||||
public EssentialsControlPropertiesConfig Control { get; set; }
|
public EssentialsControlPropertiesConfig Control { get; set; }
|
||||||
|
|
||||||
[JsonProperty("devices")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Devices
|
/// Gets or sets the Devices
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("devices")]
|
||||||
public List<ApiDevicePropertiesConfig> Devices { get; set; }
|
public List<ApiDevicePropertiesConfig> Devices { get; set; }
|
||||||
|
|
||||||
[JsonProperty("rooms")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Rooms
|
/// Gets or sets the Rooms
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("rooms")]
|
||||||
public List<ApiRoomPropertiesConfig> Rooms { get; set; }
|
public List<ApiRoomPropertiesConfig> Rooms { get; set; }
|
||||||
|
|
||||||
|
|
||||||
@@ -379,22 +385,22 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ApiDevicePropertiesConfig
|
public class ApiDevicePropertiesConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("deviceKey")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the DeviceKey
|
/// Gets or sets the DeviceKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("deviceKey")]
|
||||||
public string DeviceKey { get; set; }
|
public string DeviceKey { get; set; }
|
||||||
|
|
||||||
[JsonProperty("joinStart")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the JoinStart
|
/// Gets or sets the JoinStart
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("joinStart")]
|
||||||
public uint JoinStart { get; set; }
|
public uint JoinStart { get; set; }
|
||||||
|
|
||||||
[JsonProperty("joinMapKey")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the JoinMapKey
|
/// Gets or sets the JoinMapKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("joinMapKey")]
|
||||||
public string JoinMapKey { get; set; }
|
public string JoinMapKey { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,44 +409,55 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ApiRoomPropertiesConfig
|
public class ApiRoomPropertiesConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("roomKey")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the RoomKey
|
/// Gets or sets the RoomKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("roomKey")]
|
||||||
public string RoomKey { get; set; }
|
public string RoomKey { get; set; }
|
||||||
|
|
||||||
[JsonProperty("joinStart")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the JoinStart
|
/// Gets or sets the JoinStart
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("joinStart")]
|
||||||
public uint JoinStart { get; set; }
|
public uint JoinStart { get; set; }
|
||||||
|
|
||||||
[JsonProperty("joinMapKey")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the JoinMapKey
|
/// Gets or sets the JoinMapKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("joinMapKey")]
|
||||||
public string JoinMapKey { get; set; }
|
public string JoinMapKey { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a EiscApiAdvancedFactory
|
/// Factory class for EiscApiAdvanced devices
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Supported types:
|
||||||
|
/// eiscapiadv - Create a standard EISC client over TCP/IP
|
||||||
|
/// eiscapiadvanced - Create a standard EISC client over TCP/IP
|
||||||
|
/// eiscapiadvancedserver - Create an EISC server
|
||||||
|
/// eiscapiadvancedclient - Create an EISC client
|
||||||
|
/// vceiscapiadv - Create a VC-4 EISC client
|
||||||
|
/// vceiscapiadvanced - Create a VC-4 EISC client
|
||||||
|
/// eiscapiadvudp - Create a standard EISC client over UDP
|
||||||
|
/// eiscapiadvancedudp - Create a standard EISC client over UDP
|
||||||
|
/// </remarks>
|
||||||
public class EiscApiAdvancedFactory : EssentialsDeviceFactory<EiscApiAdvanced>
|
public class EiscApiAdvancedFactory : EssentialsDeviceFactory<EiscApiAdvanced>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
public EiscApiAdvancedFactory()
|
public EiscApiAdvancedFactory()
|
||||||
{
|
{
|
||||||
TypeNames = new List<string> { "eiscapiadv", "eiscapiadvanced", "eiscapiadvancedserver", "eiscapiadvancedclient", "vceiscapiadv", "vceiscapiadvanced" };
|
TypeNames = new List<string> { "eiscapiadv", "eiscapiadvanced", "eiscapiadvancedserver", "eiscapiadvancedclient", "vceiscapiadv", "vceiscapiadvanced", "eiscapiadvudp", "eiscapiadvancedudp" };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// BuildDevice method
|
|
||||||
/// </summary>
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new EiscApiAdvanced Device");
|
Debug.LogDebug("Attempting to create new EiscApiAdvanced Device");
|
||||||
|
|
||||||
var controlProperties = CommFactory.GetControlPropertiesConfig(dc);
|
var controlProperties = CommFactory.GetControlPropertiesConfig(dc);
|
||||||
|
|
||||||
@@ -448,6 +465,13 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
|
|
||||||
switch (dc.Type.ToLower())
|
switch (dc.Type.ToLower())
|
||||||
{
|
{
|
||||||
|
case "eiscapiadvudp":
|
||||||
|
case "eiscapiadvancedudp":
|
||||||
|
{
|
||||||
|
eisc = new EthernetIntersystemCommunications(controlProperties.IpIdInt,
|
||||||
|
controlProperties.TcpSshProperties.Address, Global.ControlSystem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "eiscapiadv":
|
case "eiscapiadv":
|
||||||
case "eiscapiadvanced":
|
case "eiscapiadvanced":
|
||||||
{
|
{
|
||||||
@@ -470,7 +494,7 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(controlProperties.RoomId))
|
if (string.IsNullOrEmpty(controlProperties.RoomId))
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Unable to build VC-4 EISC Client for device {0}. Room ID is missing or empty", dc.Key);
|
Debug.LogInformation("Unable to build VC-4 EISC Client for device {deviceKey}. Room ID is missing or empty", dc.Key);
|
||||||
eisc = null;
|
eisc = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,13 @@ namespace PepperDash.Essentials.Core.Bridges
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IBridgeAdvanced
|
public interface IBridgeAdvanced
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Links the bridge to the API using the provided trilist, join start, join map key, and bridge.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="trilist">The trilist to link to.</param>
|
||||||
|
/// <param name="joinStart">The starting join number.</param>
|
||||||
|
/// <param name="joinMapKey">The key for the join map.</param>
|
||||||
|
/// <param name="bridge">The EISC API bridge.</param>
|
||||||
void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge);
|
void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,15 +12,15 @@ using Serilog.Events;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a CecPortController
|
/// Represents a CecPortController
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CecPortController : Device, IBasicCommunicationWithStreamDebugging
|
public class CecPortController : Device, IBasicCommunicationWithStreamDebugging
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the StreamDebugging
|
/// Gets or sets the StreamDebugging
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CommunicationStreamDebugging StreamDebugging { get; private set; }
|
public CommunicationStreamDebugging StreamDebugging { get; private set; }
|
||||||
|
|
||||||
public event EventHandler<GenericCommMethodReceiveBytesArgs> BytesReceived;
|
public event EventHandler<GenericCommMethodReceiveBytesArgs> BytesReceived;
|
||||||
public event EventHandler<GenericCommMethodReceiveTextArgs> TextReceived;
|
public event EventHandler<GenericCommMethodReceiveTextArgs> TextReceived;
|
||||||
@@ -33,16 +33,16 @@ namespace PepperDash.Essentials.Core
|
|||||||
ICec Port;
|
ICec Port;
|
||||||
|
|
||||||
public CecPortController(string key, Func<EssentialsControlPropertiesConfig, ICec> postActivationFunc,
|
public CecPortController(string key, Func<EssentialsControlPropertiesConfig, ICec> postActivationFunc,
|
||||||
EssentialsControlPropertiesConfig config):base(key)
|
EssentialsControlPropertiesConfig config) : base(key)
|
||||||
{
|
{
|
||||||
StreamDebugging = new CommunicationStreamDebugging(key);
|
StreamDebugging = new CommunicationStreamDebugging(key);
|
||||||
|
|
||||||
AddPostActivationAction(() =>
|
AddPostActivationAction(() =>
|
||||||
{
|
{
|
||||||
Port = postActivationFunc(config);
|
Port = postActivationFunc(config);
|
||||||
|
|
||||||
Port.StreamCec.CecChange += StreamCec_CecChange;
|
Port.StreamCec.CecChange += StreamCec_CecChange;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public CecPortController(string key, ICec port)
|
public CecPortController(string key, ICec port)
|
||||||
@@ -58,27 +58,25 @@ namespace PepperDash.Essentials.Core
|
|||||||
if (args.EventId == CecEventIds.CecMessageReceivedEventId)
|
if (args.EventId == CecEventIds.CecMessageReceivedEventId)
|
||||||
OnDataReceived(cecDevice.Received.StringValue);
|
OnDataReceived(cecDevice.Received.StringValue);
|
||||||
else if (args.EventId == CecEventIds.ErrorFeedbackEventId)
|
else if (args.EventId == CecEventIds.ErrorFeedbackEventId)
|
||||||
if(cecDevice.ErrorFeedback.BoolValue)
|
if (cecDevice.ErrorFeedback.BoolValue)
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "CEC NAK Error");
|
Debug.LogMessage(LogEventLevel.Verbose, this, "CEC NAK Error");
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnDataReceived(string s)
|
void OnDataReceived(string s)
|
||||||
{
|
{
|
||||||
var bytesHandler = BytesReceived;
|
var bytesHandler = BytesReceived;
|
||||||
if (bytesHandler != null)
|
if (bytesHandler != null)
|
||||||
{
|
{
|
||||||
var bytes = Encoding.GetEncoding(28591).GetBytes(s);
|
var bytes = Encoding.GetEncoding(28591).GetBytes(s);
|
||||||
if (StreamDebugging.RxStreamDebuggingIsEnabled)
|
this.PrintReceivedBytes(bytes);
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", ComTextHelper.GetEscapedText(bytes));
|
|
||||||
bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes));
|
bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes));
|
||||||
}
|
}
|
||||||
var textHandler = TextReceived;
|
var textHandler = TextReceived;
|
||||||
if (textHandler != null)
|
if (textHandler != null)
|
||||||
{
|
{
|
||||||
if (StreamDebugging.RxStreamDebuggingIsEnabled)
|
this.PrintReceivedText(s);
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", s);
|
textHandler(this, new GenericCommMethodReceiveTextArgs(s));
|
||||||
textHandler(this, new GenericCommMethodReceiveTextArgs(s));
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IBasicCommunication Members
|
#region IBasicCommunication Members
|
||||||
@@ -90,8 +88,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
{
|
{
|
||||||
if (Port == null)
|
if (Port == null)
|
||||||
return;
|
return;
|
||||||
if (StreamDebugging.TxStreamDebuggingIsEnabled)
|
this.PrintSentText(text);
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Sending {0} characters of text: '{1}'", text.Length, text);
|
|
||||||
Port.StreamCec.Send.StringValue = text;
|
Port.StreamCec.Send.StringValue = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,8 +100,8 @@ namespace PepperDash.Essentials.Core
|
|||||||
if (Port == null)
|
if (Port == null)
|
||||||
return;
|
return;
|
||||||
var text = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length);
|
var text = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length);
|
||||||
if (StreamDebugging.TxStreamDebuggingIsEnabled)
|
this.PrintSentBytes(bytes);
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes));
|
Debug.LogMessage(LogEventLevel.Information, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes));
|
||||||
Port.StreamCec.Send.StringValue = text;
|
Port.StreamCec.Send.StringValue = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,59 +1,78 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
using Crestron.SimplSharpPro;
|
using Crestron.SimplSharpPro;
|
||||||
|
using Crestron.SimplSharpPro.GeneralIO;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Core.Logging;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a ComPortController
|
/// Represents a ComPortController
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ComPortController : Device, IBasicCommunicationWithStreamDebugging
|
public class ComPortController : Device, IBasicCommunicationWithStreamDebugging
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the StreamDebugging
|
/// Gets or sets the StreamDebugging
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CommunicationStreamDebugging StreamDebugging { get; private set; }
|
public CommunicationStreamDebugging StreamDebugging { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event fired when bytes are received
|
||||||
|
/// </summary>
|
||||||
public event EventHandler<GenericCommMethodReceiveBytesArgs> BytesReceived;
|
public event EventHandler<GenericCommMethodReceiveBytesArgs> BytesReceived;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event fired when text is received
|
||||||
|
/// </summary>
|
||||||
public event EventHandler<GenericCommMethodReceiveTextArgs> TextReceived;
|
public event EventHandler<GenericCommMethodReceiveTextArgs> TextReceived;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the IsConnected
|
/// Gets or sets the IsConnected
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsConnected { get { return true; } }
|
public bool IsConnected { get { return true; } }
|
||||||
|
|
||||||
ComPort Port;
|
ComPort Port;
|
||||||
ComPort.ComPortSpec Spec;
|
ComPort.ComPortSpec Spec;
|
||||||
|
|
||||||
public ComPortController(string key, Func<EssentialsControlPropertiesConfig, ComPort> postActivationFunc,
|
/// <summary>
|
||||||
ComPort.ComPortSpec spec, EssentialsControlPropertiesConfig config) : base(key)
|
/// Constructor
|
||||||
{
|
/// </summary>
|
||||||
StreamDebugging = new CommunicationStreamDebugging(key);
|
/// <param name="key"></param>
|
||||||
|
/// <param name="postActivationFunc"></param>
|
||||||
|
/// <param name="spec"></param>
|
||||||
|
/// <param name="config"></param>
|
||||||
|
public ComPortController(string key, Func<EssentialsControlPropertiesConfig, ComPort> postActivationFunc,
|
||||||
|
ComPort.ComPortSpec spec, EssentialsControlPropertiesConfig config) : base(key)
|
||||||
|
{
|
||||||
|
StreamDebugging = new CommunicationStreamDebugging(key);
|
||||||
|
|
||||||
Spec = spec;
|
Spec = spec;
|
||||||
|
|
||||||
AddPostActivationAction(() =>
|
AddPostActivationAction(() =>
|
||||||
{
|
{
|
||||||
Port = postActivationFunc(config);
|
Port = postActivationFunc(config);
|
||||||
|
|
||||||
RegisterAndConfigureComPort();
|
RegisterAndConfigureComPort();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Device key</param>
|
||||||
|
/// <param name="port">COM port instance</param>
|
||||||
|
/// <param name="spec">COM port specification</param>
|
||||||
public ComPortController(string key, ComPort port, ComPort.ComPortSpec spec)
|
public ComPortController(string key, ComPort port, ComPort.ComPortSpec spec)
|
||||||
: base(key)
|
: base(key)
|
||||||
{
|
{
|
||||||
if (port == null)
|
if (port == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "ERROR: Invalid com port, continuing but comms will not function");
|
Debug.LogMessage(LogEventLevel.Information, this, "ERROR: Invalid com port, continuing but comms will not function");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,71 +83,77 @@ namespace PepperDash.Essentials.Core
|
|||||||
RegisterAndConfigureComPort();
|
RegisterAndConfigureComPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RegisterAndConfigureComPort()
|
private void RegisterAndConfigureComPort()
|
||||||
{
|
{
|
||||||
if (Port == null)
|
if (Port == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Configured com Port for this device does not exist.");
|
this.LogInformation($"Configured {Port.Parent.GetType().Name}-comport-{Port.ID} for {Key} does not exist.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Port.Parent is CrestronControlSystem)
|
|
||||||
{
|
|
||||||
var result = Port.Register();
|
|
||||||
if (result != eDeviceRegistrationUnRegistrationResponse.Success)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "ERROR: Cannot register Com port: {0}", result);
|
|
||||||
return; // false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var specResult = Port.SetComPortSpec(Spec);
|
|
||||||
if (specResult != 0)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "WARNING: Cannot set comspec");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Port.SerialDataReceived += Port_SerialDataReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
~ComPortController()
|
if (Port.Parent is CrestronControlSystem || Port.Parent is CenIoCom102)
|
||||||
|
{
|
||||||
|
var result = Port.Register();
|
||||||
|
if (result != eDeviceRegistrationUnRegistrationResponse.Success)
|
||||||
|
{
|
||||||
|
this.LogError($"Cannot register {Key} using {Port.Parent.GetType().Name}-comport-{Port.ID} (result == {result})");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.LogInformation($"Successfully registered {Key} using {Port.Parent.GetType().Name}-comport-{Port.ID} (result == {result})");
|
||||||
|
}
|
||||||
|
|
||||||
|
var specResult = Port.SetComPortSpec(Spec);
|
||||||
|
if (specResult != 0)
|
||||||
|
{
|
||||||
|
this.LogError($"Cannot set comspec for {Key} using {Port.Parent.GetType().Name}-comport-{Port.ID} (result == {specResult})");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.LogInformation($"Successfully set comspec for {Key} using {Port.Parent.GetType().Name}-comport-{Port.ID} (result == {specResult})");
|
||||||
|
|
||||||
|
Port.SerialDataReceived += Port_SerialDataReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Destructor
|
||||||
|
/// </summary>
|
||||||
|
~ComPortController()
|
||||||
{
|
{
|
||||||
Port.SerialDataReceived -= Port_SerialDataReceived;
|
Port.SerialDataReceived -= Port_SerialDataReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Port_SerialDataReceived(ComPort ReceivingComPort, ComPortSerialDataEventArgs args)
|
void Port_SerialDataReceived(ComPort ReceivingComPort, ComPortSerialDataEventArgs args)
|
||||||
{
|
{
|
||||||
OnDataReceived(args.SerialData);
|
OnDataReceived(args.SerialData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnDataReceived(string s)
|
void OnDataReceived(string s)
|
||||||
{
|
{
|
||||||
var eventSubscribed = false;
|
var eventSubscribed = false;
|
||||||
|
|
||||||
var bytesHandler = BytesReceived;
|
var bytesHandler = BytesReceived;
|
||||||
if (bytesHandler != null)
|
if (bytesHandler != null)
|
||||||
{
|
{
|
||||||
var bytes = Encoding.GetEncoding(28591).GetBytes(s);
|
var bytes = Encoding.GetEncoding(28591).GetBytes(s);
|
||||||
if (StreamDebugging.RxStreamDebuggingIsEnabled)
|
this.PrintReceivedBytes(bytes);
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", ComTextHelper.GetEscapedText(bytes));
|
bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes));
|
||||||
bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes));
|
|
||||||
eventSubscribed = true;
|
eventSubscribed = true;
|
||||||
}
|
}
|
||||||
var textHandler = TextReceived;
|
var textHandler = TextReceived;
|
||||||
if (textHandler != null)
|
if (textHandler != null)
|
||||||
{
|
{
|
||||||
if (StreamDebugging.RxStreamDebuggingIsEnabled)
|
this.PrintReceivedText(s);
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", s);
|
textHandler(this, new GenericCommMethodReceiveTextArgs(s));
|
||||||
textHandler(this, new GenericCommMethodReceiveTextArgs(s));
|
|
||||||
eventSubscribed = true;
|
eventSubscribed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!eventSubscribed) 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deactivate method
|
/// Deactivate method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool Deactivate()
|
public override bool Deactivate()
|
||||||
{
|
{
|
||||||
return Port.UnRegister() == eDeviceRegistrationUnRegistrationResponse.Success;
|
return Port.UnRegister() == eDeviceRegistrationUnRegistrationResponse.Success;
|
||||||
@@ -136,70 +161,68 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
#region IBasicCommunication Members
|
#region IBasicCommunication Members
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SendText method
|
/// SendText method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SendText(string text)
|
public void SendText(string text)
|
||||||
{
|
{
|
||||||
if (Port == null)
|
if (Port == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (StreamDebugging.TxStreamDebuggingIsEnabled)
|
this.PrintSentText(text);
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Sending {0} characters of text: '{1}'", text.Length, text);
|
Port.Send(text);
|
||||||
Port.Send(text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SendBytes method
|
/// SendBytes method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SendBytes(byte[] bytes)
|
public void SendBytes(byte[] bytes)
|
||||||
{
|
{
|
||||||
if (Port == null)
|
if (Port == null)
|
||||||
return;
|
return;
|
||||||
var text = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length);
|
var text = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length);
|
||||||
if (StreamDebugging.TxStreamDebuggingIsEnabled)
|
this.PrintSentBytes(bytes);
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes));
|
|
||||||
|
|
||||||
Port.Send(text);
|
Port.Send(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Connect method
|
/// Connect method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Connect()
|
public void Connect()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disconnect method
|
/// Disconnect method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Disconnect()
|
public void Disconnect()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="s"></param>
|
/// <param name="s"></param>
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SimulateReceive method
|
/// SimulateReceive method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SimulateReceive(string s)
|
public void SimulateReceive(string s)
|
||||||
{
|
{
|
||||||
// split out hex chars and build string
|
// split out hex chars and build string
|
||||||
var split = Regex.Split(s, @"(\\[Xx][0-9a-fA-F][0-9a-fA-F])");
|
var split = Regex.Split(s, @"(\\[Xx][0-9a-fA-F][0-9a-fA-F])");
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
foreach (var t in split)
|
foreach (var t in split)
|
||||||
{
|
{
|
||||||
if (t.StartsWith(@"\") && t.Length == 4)
|
if (t.StartsWith(@"\") && t.Length == 4)
|
||||||
b.Append((char)(Convert.ToByte(t.Substring(2, 2), 16)));
|
b.Append((char)(Convert.ToByte(t.Substring(2, 2), 16)));
|
||||||
else
|
else
|
||||||
b.Append(t);
|
b.Append(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
OnDataReceived(b.ToString());
|
OnDataReceived(b.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
138
src/PepperDash.Essentials.Core/Comm and IR/CommBridge.cs
Normal file
138
src/PepperDash.Essentials.Core/Comm and IR/CommBridge.cs
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Crestron.SimplSharp.CrestronSockets;
|
||||||
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Core.Logging;
|
||||||
|
using PepperDash.Essentials.Core.Bridges;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
|
using PepperDash.Essentials.Core.Devices;
|
||||||
|
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Implements IBasicCommunication and sends all communication through an EISC
|
||||||
|
/// </summary>
|
||||||
|
[Description("Generic communication wrapper class for any IBasicCommunication type")]
|
||||||
|
public class CommBridge : EssentialsBridgeableDevice, IBasicCommunication
|
||||||
|
{
|
||||||
|
private EiscApiAdvanced eisc;
|
||||||
|
|
||||||
|
private IBasicCommunicationJoinMap joinMap;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when text is received through the communication bridge.
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<GenericCommMethodReceiveTextArgs> TextReceived;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when bytes are received through the communication bridge.
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<GenericCommMethodReceiveBytesArgs> BytesReceived;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the communication bridge is currently connected.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsConnected { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="CommBridge"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique key for the communication bridge.</param>
|
||||||
|
/// <param name="name">The display name for the communication bridge.</param>
|
||||||
|
public CommBridge(string key, string name)
|
||||||
|
: base(key, name)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a byte array through the communication bridge.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bytes">The byte array to send.</param>
|
||||||
|
public void SendBytes(byte[] bytes)
|
||||||
|
{
|
||||||
|
if (eisc == null)
|
||||||
|
{
|
||||||
|
this.LogWarning("EISC is null, cannot send bytes.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eisc.Eisc.SetString(joinMap.SendText.JoinNumber, Encoding.ASCII.GetString(bytes, 0, bytes.Length));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a text string through the communication bridge.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">The text string to send.</param>
|
||||||
|
public void SendText(string text)
|
||||||
|
{
|
||||||
|
if (eisc == null)
|
||||||
|
{
|
||||||
|
this.LogWarning("EISC is null, cannot send text.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eisc.Eisc.SetString(joinMap.SendText.JoinNumber, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initiates a connection through the communication bridge.
|
||||||
|
/// </summary>
|
||||||
|
public void Connect()
|
||||||
|
{
|
||||||
|
if (eisc == null)
|
||||||
|
{
|
||||||
|
this.LogWarning("EISC is null, cannot connect.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eisc.Eisc.SetBool(joinMap.Connect.JoinNumber, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Terminates the connection through the communication bridge.
|
||||||
|
/// </summary>
|
||||||
|
public void Disconnect()
|
||||||
|
{
|
||||||
|
if (eisc == null)
|
||||||
|
{
|
||||||
|
this.LogWarning("EISC is null, cannot disconnect.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eisc.Eisc.SetBool(joinMap.Connect.JoinNumber, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
|
||||||
|
{
|
||||||
|
joinMap = new IBasicCommunicationJoinMap(joinStart);
|
||||||
|
|
||||||
|
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(joinMapSerialized))
|
||||||
|
joinMap = JsonConvert.DeserializeObject<IBasicCommunicationJoinMap>(joinMapSerialized);
|
||||||
|
|
||||||
|
if (bridge != null)
|
||||||
|
{
|
||||||
|
bridge.AddJoinMap(Key, joinMap);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.LogWarning("Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.LogDebug("Linking to Trilist '{0}'", trilist.ID.ToString("X"));
|
||||||
|
|
||||||
|
eisc = bridge;
|
||||||
|
|
||||||
|
trilist.SetBoolSigAction(joinMap.Connected.JoinNumber, (b) => IsConnected = b);
|
||||||
|
|
||||||
|
trilist.SetStringSigAction(joinMap.TextReceived.JoinNumber, (s) =>
|
||||||
|
{
|
||||||
|
TextReceived?.Invoke(this, new GenericCommMethodReceiveTextArgs(s));
|
||||||
|
BytesReceived?.Invoke(this, new GenericCommMethodReceiveBytesArgs(Encoding.ASCII.GetBytes(s)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using Crestron.SimplSharpPro;
|
using Crestron.SimplSharpPro;
|
||||||
using Crestron.SimplSharpPro.DM;
|
using Crestron.SimplSharpPro.DM;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core.Config;
|
using PepperDash.Essentials.Core.Config;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
@@ -38,9 +36,9 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// Returns a comm method of either com port, TCP, SSH, and puts this into the DeviceManager
|
/// Returns a comm method of either com port, TCP, SSH, and puts this into the DeviceManager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="deviceConfig">The Device config object</param>
|
/// <param name="deviceConfig">The Device config object</param>
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// CreateCommForDevice method
|
/// CreateCommForDevice method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static IBasicCommunication CreateCommForDevice(DeviceConfig deviceConfig)
|
public static IBasicCommunication CreateCommForDevice(DeviceConfig deviceConfig)
|
||||||
{
|
{
|
||||||
EssentialsControlPropertiesConfig controlConfig = GetControlPropertiesConfig(deviceConfig);
|
EssentialsControlPropertiesConfig controlConfig = GetControlPropertiesConfig(deviceConfig);
|
||||||
@@ -56,41 +54,51 @@ namespace PepperDash.Essentials.Core
|
|||||||
case eControlMethod.Com:
|
case eControlMethod.Com:
|
||||||
comm = new ComPortController(deviceConfig.Key + "-com", GetComPort, controlConfig.ComParams.Value, controlConfig);
|
comm = new ComPortController(deviceConfig.Key + "-com", GetComPort, controlConfig.ComParams.Value, controlConfig);
|
||||||
break;
|
break;
|
||||||
case eControlMethod.Cec:
|
case eControlMethod.ComBridge:
|
||||||
comm = new CecPortController(deviceConfig.Key + "-cec", GetCecPort, controlConfig);
|
comm = new CommBridge(deviceConfig.Key + "-simpl", deviceConfig.Name + " Simpl");
|
||||||
break;
|
break;
|
||||||
|
case eControlMethod.Cec:
|
||||||
|
comm = new CecPortController(deviceConfig.Key + "-cec", GetCecPort, controlConfig);
|
||||||
|
break;
|
||||||
case eControlMethod.IR:
|
case eControlMethod.IR:
|
||||||
break;
|
break;
|
||||||
case eControlMethod.Ssh:
|
case eControlMethod.Ssh:
|
||||||
{
|
{
|
||||||
var ssh = new GenericSshClient(deviceConfig.Key + "-ssh", c.Address, c.Port, c.Username, c.Password);
|
var ssh = new GenericSshClient(deviceConfig.Key + "-ssh", c.Address, c.Port, c.Username, c.Password)
|
||||||
ssh.AutoReconnect = c.AutoReconnect;
|
{
|
||||||
if(ssh.AutoReconnect)
|
AutoReconnect = c.AutoReconnect,
|
||||||
ssh.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
|
DisableEcho = c.DisableSshEcho
|
||||||
comm = ssh;
|
};
|
||||||
break;
|
if (ssh.AutoReconnect)
|
||||||
}
|
ssh.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
|
||||||
case eControlMethod.Tcpip:
|
comm = ssh;
|
||||||
{
|
break;
|
||||||
var tcp = new GenericTcpIpClient(deviceConfig.Key + "-tcp", c.Address, c.Port, c.BufferSize);
|
}
|
||||||
tcp.AutoReconnect = c.AutoReconnect;
|
case eControlMethod.Tcpip:
|
||||||
if (tcp.AutoReconnect)
|
{
|
||||||
tcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
|
var tcp = new GenericTcpIpClient(deviceConfig.Key + "-tcp", c.Address, c.Port, c.BufferSize)
|
||||||
comm = tcp;
|
{
|
||||||
break;
|
AutoReconnect = c.AutoReconnect
|
||||||
}
|
};
|
||||||
case eControlMethod.Udp:
|
if (tcp.AutoReconnect)
|
||||||
{
|
tcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
|
||||||
var udp = new GenericUdpServer(deviceConfig.Key + "-udp", c.Address, c.Port, c.BufferSize);
|
comm = tcp;
|
||||||
comm = udp;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
case eControlMethod.Udp:
|
||||||
|
{
|
||||||
|
var udp = new GenericUdpServer(deviceConfig.Key + "-udp", c.Address, c.Port, c.BufferSize);
|
||||||
|
comm = udp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case eControlMethod.Telnet:
|
case eControlMethod.Telnet:
|
||||||
break;
|
break;
|
||||||
case eControlMethod.SecureTcpIp:
|
case eControlMethod.SecureTcpIp:
|
||||||
{
|
{
|
||||||
var secureTcp = new GenericSecureTcpIpClient(deviceConfig.Key + "-secureTcp", c.Address, c.Port, c.BufferSize);
|
var secureTcp = new GenericSecureTcpIpClient(deviceConfig.Key + "-secureTcp", c.Address, c.Port, c.BufferSize)
|
||||||
secureTcp.AutoReconnect = c.AutoReconnect;
|
{
|
||||||
|
AutoReconnect = c.AutoReconnect
|
||||||
|
};
|
||||||
if (secureTcp.AutoReconnect)
|
if (secureTcp.AutoReconnect)
|
||||||
secureTcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
|
secureTcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
|
||||||
comm = secureTcp;
|
comm = secureTcp;
|
||||||
@@ -98,7 +106,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -107,15 +115,14 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
// put it in the device manager if it's the right flavor
|
// put it in the device manager if it's the right flavor
|
||||||
var comDev = comm as Device;
|
if (comm is Device comDev)
|
||||||
if (comDev != null)
|
|
||||||
DeviceManager.AddDevice(comDev);
|
DeviceManager.AddDevice(comDev);
|
||||||
return comm;
|
return comm;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// GetComPort method
|
/// GetComPort method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static ComPort GetComPort(EssentialsControlPropertiesConfig config)
|
public static ComPort GetComPort(EssentialsControlPropertiesConfig config)
|
||||||
{
|
{
|
||||||
var comPar = config.ComParams;
|
var comPar = config.ComParams;
|
||||||
@@ -126,74 +133,74 @@ namespace PepperDash.Essentials.Core
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets an ICec port from a RoutingInput or RoutingOutput on a device
|
/// Gets an ICec port from a RoutingInput or RoutingOutput on a device
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="config"></param>
|
/// <param name="config"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// GetCecPort method
|
/// GetCecPort method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static ICec GetCecPort(ControlPropertiesConfig config)
|
public static ICec GetCecPort(ControlPropertiesConfig config)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey);
|
var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey);
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetCecPort: device '{0}' {1}", config.ControlPortDevKey, dev == null
|
Debug.LogMessage(LogEventLevel.Information, "GetCecPort: device '{0}' {1}", config.ControlPortDevKey, dev == null
|
||||||
? "is not valid, failed to get cec port"
|
? "is not valid, failed to get cec port"
|
||||||
: "found in device manager, attempting to get cec port");
|
: "found in device manager, attempting to get cec port");
|
||||||
|
|
||||||
if (dev == null)
|
if (dev == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (String.IsNullOrEmpty(config.ControlPortName))
|
if (String.IsNullOrEmpty(config.ControlPortName))
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey);
|
Debug.LogMessage(LogEventLevel.Information, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var inputsOutputs = dev as IRoutingInputsOutputs;
|
var inputsOutputs = dev as IRoutingInputsOutputs;
|
||||||
if (inputsOutputs == null)
|
if (inputsOutputs == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetCecPort: Device '{0}' does not support IRoutingInputsOutputs, failed to get CEC port called '{1}'",
|
Debug.LogMessage(LogEventLevel.Information, "GetCecPort: Device '{0}' does not support IRoutingInputsOutputs, failed to get CEC port called '{1}'",
|
||||||
config.ControlPortDevKey, config.ControlPortName);
|
config.ControlPortDevKey, config.ControlPortName);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var inputPort = inputsOutputs.InputPorts[config.ControlPortName];
|
var inputPort = inputsOutputs.InputPorts[config.ControlPortName];
|
||||||
if (inputPort != null && inputPort.Port is ICec)
|
if (inputPort != null && inputPort.Port is ICec)
|
||||||
return inputPort.Port as ICec;
|
return inputPort.Port as ICec;
|
||||||
|
|
||||||
|
|
||||||
var outputPort = inputsOutputs.OutputPorts[config.ControlPortName];
|
|
||||||
if (outputPort != null && outputPort.Port is ICec)
|
var outputPort = inputsOutputs.OutputPorts[config.ControlPortName];
|
||||||
return outputPort.Port as ICec;
|
if (outputPort != null && outputPort.Port is ICec)
|
||||||
}
|
return outputPort.Port as ICec;
|
||||||
catch (Exception ex)
|
}
|
||||||
{
|
catch (Exception ex)
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "GetCecPort Exception Message: {0}", ex.Message);
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, "GetCecPort Exception StackTrace: {0}", ex.StackTrace);
|
Debug.LogMessage(LogEventLevel.Debug, "GetCecPort Exception Message: {0}", ex.Message);
|
||||||
if (ex.InnerException != null)
|
Debug.LogMessage(LogEventLevel.Verbose, "GetCecPort Exception StackTrace: {0}", ex.StackTrace);
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetCecPort Exception InnerException: {0}", ex.InnerException);
|
if (ex.InnerException != null)
|
||||||
}
|
Debug.LogMessage(LogEventLevel.Information, "GetCecPort Exception InnerException: {0}", ex.InnerException);
|
||||||
|
}
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetCecPort: Device '{0}' does not have a CEC port called '{1}'",
|
Debug.LogMessage(LogEventLevel.Information, "GetCecPort: Device '{0}' does not have a CEC port called '{1}'",
|
||||||
config.ControlPortDevKey, config.ControlPortName);
|
config.ControlPortDevKey, config.ControlPortName);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper to grab the IComPorts device for this PortDeviceKey. Key "controlSystem" will
|
/// Helper to grab the IComPorts device for this PortDeviceKey. Key "controlSystem" will
|
||||||
/// return the ControlSystem object from the Global class.
|
/// return the ControlSystem object from the Global class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>IComPorts device or null if the device is not found or does not implement IComPorts</returns>
|
/// <returns>IComPorts device or null if the device is not found or does not implement IComPorts</returns>
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// GetIComPortsDeviceFromManagedDevice method
|
/// GetIComPortsDeviceFromManagedDevice method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static IComPorts GetIComPortsDeviceFromManagedDevice(string ComPortDevKey)
|
public static IComPorts GetIComPortsDeviceFromManagedDevice(string ComPortDevKey)
|
||||||
{
|
{
|
||||||
if ((ComPortDevKey.Equals("controlSystem", System.StringComparison.OrdinalIgnoreCase)
|
if ((ComPortDevKey.Equals("controlSystem", System.StringComparison.OrdinalIgnoreCase)
|
||||||
@@ -210,81 +217,81 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a EssentialsControlPropertiesConfig
|
/// Represents a EssentialsControlPropertiesConfig
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class EssentialsControlPropertiesConfig :
|
public class EssentialsControlPropertiesConfig :
|
||||||
ControlPropertiesConfig
|
ControlPropertiesConfig
|
||||||
{
|
{
|
||||||
|
|
||||||
[JsonProperty("comParams", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("comParams", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
[JsonConverter(typeof(ComSpecJsonConverter))]
|
[JsonConverter(typeof(ComSpecJsonConverter))]
|
||||||
public ComPort.ComPortSpec? ComParams { get; set; }
|
public ComPort.ComPortSpec? ComParams { get; set; }
|
||||||
|
|
||||||
[JsonProperty("cresnetId", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("cresnetId", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string CresnetId { get; set; }
|
public string CresnetId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempts to provide uint conversion of string CresnetId
|
/// Attempts to provide uint conversion of string CresnetId
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public uint CresnetIdInt
|
public uint CresnetIdInt
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return Convert.ToUInt32(CresnetId, 16);
|
return Convert.ToUInt32(CresnetId, 16);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
throw new FormatException(string.Format("ERROR:Unable to convert Cresnet ID: {0} to hex. Error:\n{1}", CresnetId));
|
throw new FormatException(string.Format("ERROR:Unable to convert Cresnet ID: {0} to hex. Error:\n{1}", CresnetId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonProperty("infinetId", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("infinetId", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the InfinetId
|
/// Gets or sets the InfinetId
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string InfinetId { get; set; }
|
public string InfinetId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attepmts to provide uiont conversion of string InifinetId
|
/// Attepmts to provide uiont conversion of string InifinetId
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public uint InfinetIdInt
|
public uint InfinetIdInt
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return Convert.ToUInt32(InfinetId, 16);
|
return Convert.ToUInt32(InfinetId, 16);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
throw new FormatException(string.Format("ERROR:Unable to conver Infinet ID: {0} to hex. Error:\n{1}", InfinetId));
|
throw new FormatException(string.Format("ERROR:Unable to conver Infinet ID: {0} to hex. Error:\n{1}", InfinetId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a IrControlSpec
|
/// Represents a IrControlSpec
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class IrControlSpec
|
public class IrControlSpec
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the PortDeviceKey
|
/// Gets or sets the PortDeviceKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string PortDeviceKey { get; set; }
|
public string PortDeviceKey { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the PortNumber
|
/// Gets or sets the PortNumber
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint PortNumber { get; set; }
|
public uint PortNumber { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the File
|
/// Gets or sets the File
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string File { get; set; }
|
public string File { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,5 +19,11 @@ namespace PepperDash.Essentials.Core.Config
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("multicastAudioAddress", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("multicastAudioAddress", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string MulticastAudioAddress { get; set; }
|
public string MulticastAudioAddress { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The URL for the streaming device's media stream.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("streamUrl", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public string StreamUrl { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,41 +18,41 @@ namespace PepperDash.Essentials.Core.Config
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class DeviceConfig
|
public class DeviceConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("key")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Key
|
/// Gets or sets the Key
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("key")]
|
||||||
public string Key { get; set; }
|
public string Key { get; set; }
|
||||||
|
|
||||||
[JsonProperty("uid")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Uid
|
/// Gets or sets the Uid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("uid")]
|
||||||
public int Uid { get; set; }
|
public int Uid { get; set; }
|
||||||
|
|
||||||
[JsonProperty("name")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Name
|
/// Gets or sets the Name
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("name")]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
[JsonProperty("group")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Group
|
/// Gets or sets the Group
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("group")]
|
||||||
public string Group { get; set; }
|
public string Group { get; set; }
|
||||||
|
|
||||||
[JsonProperty("type")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Type
|
/// Gets or sets the Type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("type")]
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
|
|
||||||
[JsonProperty("properties")]
|
|
||||||
[JsonConverter(typeof(DevicePropertiesConverter))]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Properties
|
/// Gets or sets the Properties
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("properties")]
|
||||||
|
[JsonConverter(typeof(DevicePropertiesConverter))]
|
||||||
public JToken Properties { get; set; }
|
public JToken Properties { get; set; }
|
||||||
|
|
||||||
public DeviceConfig(DeviceConfig dc)
|
public DeviceConfig(DeviceConfig dc)
|
||||||
@@ -68,7 +68,7 @@ namespace PepperDash.Essentials.Core.Config
|
|||||||
//Properties = JToken.FromObject(dc.Properties);
|
//Properties = JToken.FromObject(dc.Properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceConfig() {}
|
public DeviceConfig() { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -124,22 +124,35 @@ namespace PepperDash.Essentials.Core.Config
|
|||||||
Debug.LogMessage(LogEventLevel.Information, "Successfully Loaded Local Config");
|
Debug.LogMessage(LogEventLevel.Information, "Successfully Loaded Local Config");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var doubleObj = JObject.Parse(fs.ReadToEnd());
|
var parsedConfig = JObject.Parse(fs.ReadToEnd());
|
||||||
ConfigObject = PortalConfigReader.MergeConfigs(doubleObj).ToObject<EssentialsConfig>();
|
|
||||||
|
|
||||||
// Extract SystemUrl and TemplateUrl into final config output
|
// Check if it's a v2 config (check for "version" node)
|
||||||
|
// this means it's already merged by the Portal API
|
||||||
if (doubleObj["system_url"] != null)
|
// from the v2 config tool
|
||||||
|
var isV2Config = parsedConfig["versions"] != null;
|
||||||
|
|
||||||
|
if (isV2Config)
|
||||||
{
|
{
|
||||||
ConfigObject.SystemUrl = doubleObj["system_url"].Value<string>();
|
Debug.LogMessage(LogEventLevel.Information, "Config file is a v2 format, no merge necessary.");
|
||||||
|
ConfigObject = parsedConfig.ToObject<EssentialsConfig>();
|
||||||
|
Debug.LogMessage(LogEventLevel.Information, "Successfully Loaded v2 Config");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doubleObj["template_url"] != null)
|
// Extract SystemUrl and TemplateUrl into final config output
|
||||||
|
ConfigObject = PortalConfigReader.MergeConfigs(parsedConfig).ToObject<EssentialsConfig>();
|
||||||
|
|
||||||
|
if (parsedConfig["system_url"] != null)
|
||||||
{
|
{
|
||||||
ConfigObject.TemplateUrl = doubleObj["template_url"].Value<string>();
|
ConfigObject.SystemUrl = parsedConfig["system_url"].Value<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedConfig["template_url"] != null)
|
||||||
|
{
|
||||||
|
ConfigObject.TemplateUrl = parsedConfig["template_url"].Value<string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,86 +11,169 @@ using PepperDash.Core;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core.Config
|
namespace PepperDash.Essentials.Core.Config
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads the ConfigObject from the file
|
/// Loads the ConfigObject from the file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class EssentialsConfig : BasicConfig
|
public class EssentialsConfig : BasicConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("system_url")]
|
/// <summary>
|
||||||
|
/// Gets or sets the SystemUrl
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("system_url")]
|
||||||
public string SystemUrl { get; set; }
|
public string SystemUrl { get; set; }
|
||||||
|
|
||||||
[JsonProperty("template_url")]
|
/// <summary>
|
||||||
|
/// Gets or sets the TemplateUrl
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("template_url")]
|
||||||
public string TemplateUrl { get; set; }
|
public string TemplateUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the SystemUuid extracted from the SystemUrl
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("systemUuid")]
|
[JsonProperty("systemUuid")]
|
||||||
public string SystemUuid
|
public string SystemUuid
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(SystemUrl))
|
string uuid;
|
||||||
return "missing url";
|
|
||||||
|
|
||||||
if (SystemUrl.Contains("#"))
|
if (string.IsNullOrEmpty(SystemUrl))
|
||||||
{
|
{
|
||||||
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/#.*");
|
uuid = "missing url";
|
||||||
string uuid = result.Groups[1].Value;
|
}
|
||||||
return uuid;
|
else if (SystemUrl.Contains("#"))
|
||||||
} else
|
{
|
||||||
{
|
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/#.*");
|
||||||
|
uuid = result.Groups[1].Value;
|
||||||
|
}
|
||||||
|
else if (SystemUrl.Contains("detail"))
|
||||||
|
{
|
||||||
|
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/detail\/(.*)\/.*");
|
||||||
|
uuid = result.Groups[1].Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/.*");
|
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/.*");
|
||||||
string uuid = result.Groups[1].Value;
|
uuid = result.Groups[1].Value;
|
||||||
return uuid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return uuid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the TemplateUuid extracted from the TemplateUrl
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("templateUuid")]
|
[JsonProperty("templateUuid")]
|
||||||
public string TemplateUuid
|
public string TemplateUuid
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(TemplateUrl))
|
string uuid;
|
||||||
return "missing template url";
|
|
||||||
|
|
||||||
if (TemplateUrl.Contains("#"))
|
if (string.IsNullOrEmpty(TemplateUrl))
|
||||||
{
|
{
|
||||||
var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/templates\/(.*)\/#.*");
|
uuid = "missing template url";
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
else if (TemplateUrl.Contains("#"))
|
||||||
|
{
|
||||||
|
var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/templates\/(.*)\/#.*");
|
||||||
|
uuid = result.Groups[1].Value;
|
||||||
|
}
|
||||||
|
else if (TemplateUrl.Contains("detail"))
|
||||||
|
{
|
||||||
|
var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/system-templates\/detail\/(.*)\/system-template-versions\/detail\/(.*)\/.*");
|
||||||
|
uuid = result.Groups[2].Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/system-templates\/(.*)\/system-template-versions\/(.*)\/.*");
|
||||||
|
uuid = result.Groups[2].Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return uuid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonProperty("rooms")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Rooms
|
/// Gets or sets the Rooms
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("rooms")]
|
||||||
public List<DeviceConfig> Rooms { get; set; }
|
public List<DeviceConfig> Rooms { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the Versions
|
||||||
|
/// </summary>
|
||||||
|
public VersionData Versions { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="EssentialsConfig"/> class.
|
||||||
|
/// </summary>
|
||||||
public EssentialsConfig()
|
public EssentialsConfig()
|
||||||
: base()
|
: base()
|
||||||
{
|
{
|
||||||
Rooms = new List<DeviceConfig>();
|
Rooms = new List<DeviceConfig>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a SystemTemplateConfigs
|
/// Represents version data for Essentials and its packages
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SystemTemplateConfigs
|
public class VersionData
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the System
|
/// Gets or sets the Essentials version
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("essentials")]
|
||||||
|
public NugetVersion Essentials { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the list of Packages
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("packages")]
|
||||||
|
public List<NugetVersion> Packages { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="VersionData"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public VersionData()
|
||||||
|
{
|
||||||
|
Packages = new List<NugetVersion>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a NugetVersion
|
||||||
|
/// </summary>
|
||||||
|
public class NugetVersion
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the Version
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("version")]
|
||||||
|
public string Version { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the PackageId
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("packageId")]
|
||||||
|
public string PackageId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a SystemTemplateConfigs
|
||||||
|
/// </summary>
|
||||||
|
public class SystemTemplateConfigs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the System
|
||||||
|
/// </summary>
|
||||||
public EssentialsConfig System { get; set; }
|
public EssentialsConfig System { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the Template
|
||||||
|
/// </summary>
|
||||||
public EssentialsConfig Template { get; set; }
|
public EssentialsConfig Template { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,59 +2,54 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using Crestron.SimplSharpPro;
|
using Crestron.SimplSharpPro;
|
||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Core.Logging;
|
||||||
using PepperDash.Essentials.Core.Bridges;
|
using PepperDash.Essentials.Core.Bridges;
|
||||||
using PepperDash.Essentials.Core.Config;
|
using PepperDash.Essentials.Core.Config;
|
||||||
using Serilog.Events;
|
|
||||||
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core.CrestronIO
|
namespace PepperDash.Essentials.Core.CrestronIO
|
||||||
{
|
{
|
||||||
[Description("Wrapper class for Digital Input")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a GenericDigitalInputDevice
|
/// Represents a GenericDigitalInputDevice
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GenericDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput
|
/// [Description("Wrapper class for Digital Input")]
|
||||||
|
public class GenericDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput, IHasFeedback
|
||||||
{
|
{
|
||||||
/// <summary>
|
private DigitalInput inputPort;
|
||||||
/// Gets or sets the InputPort
|
|
||||||
/// </summary>
|
|
||||||
public DigitalInput InputPort { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the InputStateFeedback
|
/// Gets or sets the InputStateFeedback
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BoolFeedback InputStateFeedback { get; private set; }
|
public BoolFeedback InputStateFeedback { get; private set; }
|
||||||
|
|
||||||
Func<bool> InputStateFeedbackFunc
|
/// <inheritdoc />
|
||||||
{
|
public FeedbackCollection<Feedback> Feedbacks { get; private set; } = new FeedbackCollection<Feedback>();
|
||||||
get
|
|
||||||
{
|
|
||||||
return () => InputPort.State;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="GenericDigitalInputDevice"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">key for device</param>
|
||||||
|
/// <param name="name">name for device</param>
|
||||||
|
/// <param name="postActivationFunc">function to call after activation. Should return the DigitalInput</param>
|
||||||
|
/// <param name="config">config for device</param>
|
||||||
public GenericDigitalInputDevice(string key, string name, Func<IOPortConfig, DigitalInput> postActivationFunc,
|
public GenericDigitalInputDevice(string key, string name, Func<IOPortConfig, DigitalInput> postActivationFunc,
|
||||||
IOPortConfig config)
|
IOPortConfig config)
|
||||||
: base(key, name)
|
: base(key, name)
|
||||||
{
|
{
|
||||||
InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc);
|
InputStateFeedback = new BoolFeedback("inputState", () => inputPort.State);
|
||||||
|
|
||||||
AddPostActivationAction(() =>
|
AddPostActivationAction(() =>
|
||||||
{
|
{
|
||||||
InputPort = postActivationFunc(config);
|
inputPort = postActivationFunc(config);
|
||||||
|
|
||||||
InputPort.Register();
|
inputPort.Register();
|
||||||
|
|
||||||
InputPort.StateChange += InputPort_StateChange;
|
|
||||||
|
|
||||||
|
inputPort.StateChange += InputPort_StateChange;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,41 +66,31 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
|
|
||||||
private static DigitalInput GetDigitalInput(IOPortConfig dc)
|
private static DigitalInput GetDigitalInput(IOPortConfig dc)
|
||||||
{
|
{
|
||||||
IDigitalInputPorts ioPortDevice;
|
|
||||||
|
|
||||||
if (dc.PortDeviceKey.Equals("processor"))
|
if (dc.PortDeviceKey.Equals("processor"))
|
||||||
{
|
{
|
||||||
if (!Global.ControlSystem.SupportsDigitalInput)
|
if (!Global.ControlSystem.SupportsDigitalInput)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetDigitalInput: Processor does not support Digital Inputs");
|
Debug.LogError("GetDigitalInput: Processor does not support Digital Inputs");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ioPortDevice = Global.ControlSystem;
|
|
||||||
|
return Global.ControlSystem.DigitalInputPorts[dc.PortNumber];
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (!(DeviceManager.GetDeviceForKey(dc.PortDeviceKey) is IDigitalInputPorts ioPortDevice))
|
||||||
{
|
{
|
||||||
var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IDigitalInputPorts;
|
Debug.LogError("GetDigitalInput: Device {key} is not a valid device", dc.PortDeviceKey);
|
||||||
if (ioPortDev == null)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetDigitalInput: Device {0} is not a valid device", dc.PortDeviceKey);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ioPortDevice = ioPortDev;
|
|
||||||
}
|
|
||||||
if (ioPortDevice == null)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetDigitalInput: Device '0' is not a valid IDigitalInputPorts Device", dc.PortDeviceKey);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dc.PortNumber > ioPortDevice.NumberOfDigitalInputPorts)
|
if (dc.PortNumber > ioPortDevice.NumberOfDigitalInputPorts)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetDigitalInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber);
|
Debug.LogError("GetDigitalInput: Device {key} does not contain a digital input port {port}", dc.PortDeviceKey, dc.PortNumber);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ioPortDevice.DigitalInputPorts[dc.PortNumber];
|
return ioPortDevice.DigitalInputPorts[dc.PortNumber];
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -131,20 +116,20 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
|
this.LogWarning("Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
|
this.LogDebug("Linking to Trilist '{0}'", trilist.ID.ToString("X"));
|
||||||
|
|
||||||
// Link feedback for input state
|
// Link feedback for input state
|
||||||
InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]);
|
InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Input is null", Key);
|
this.LogError("Unable to link device {key}. {message}", Key, e.Message);
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e);
|
this.LogDebug(e, "Stack Trace: ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,22 +138,22 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
#region Factory
|
#region Factory
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a GenericDigitalInputDeviceFactory
|
/// Factory for creating GenericDigitalInputDevice devices
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GenericDigitalInputDeviceFactory : EssentialsDeviceFactory<GenericDigitalInputDevice>
|
public class GenericDigitalInputDeviceFactory : EssentialsDeviceFactory<GenericDigitalInputDevice>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for GenericDigitalInputDeviceFactory
|
||||||
|
/// </summary>
|
||||||
public GenericDigitalInputDeviceFactory()
|
public GenericDigitalInputDeviceFactory()
|
||||||
{
|
{
|
||||||
TypeNames = new List<string>() { "digitalinput" };
|
TypeNames = new List<string>() { "digitalinput" };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// BuildDevice method
|
|
||||||
/// </summary>
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Digital Input Device");
|
Debug.LogDebug("Factory Attempting to create new Generic Digital Input Device");
|
||||||
|
|
||||||
var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString());
|
var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString());
|
||||||
|
|
||||||
|
|||||||
@@ -2,66 +2,64 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using Crestron.SimplSharpPro;
|
using Crestron.SimplSharpPro;
|
||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
|
|
||||||
using PepperDash.Core;
|
|
||||||
using PepperDash.Essentials.Core.Config;
|
|
||||||
using PepperDash.Essentials.Core.Bridges;
|
|
||||||
|
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Serilog.Events;
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Core.Logging;
|
||||||
|
using PepperDash.Essentials.Core.Bridges;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core.CrestronIO
|
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 GenericVersiportAnalogInputDevice : EssentialsBridgeableDevice, IAnalogInput
|
public class GenericVersiportAnalogInputDevice : EssentialsBridgeableDevice, IAnalogInput, IHasFeedback
|
||||||
{
|
{
|
||||||
public Versiport InputPort { get; private set; }
|
private Versiport inputPort;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public IntFeedback InputValueFeedback { get; private set; }
|
public IntFeedback InputValueFeedback { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the InputMinimumChangeFeedback
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Updates when the analog input minimum change value changes
|
||||||
|
/// </remarks>
|
||||||
public IntFeedback InputMinimumChangeFeedback { get; private set; }
|
public IntFeedback InputMinimumChangeFeedback { get; private set; }
|
||||||
|
|
||||||
Func<int> InputValueFeedbackFunc
|
/// <inheritdoc />
|
||||||
{
|
public FeedbackCollection<Feedback> Feedbacks { get; private set; } = new FeedbackCollection<Feedback>();
|
||||||
get
|
|
||||||
{
|
|
||||||
return () => InputPort.AnalogIn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Func<int> InputMinimumChangeFeedbackFunc
|
|
||||||
{
|
|
||||||
get { return () => InputPort.AnalogMinChange; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="GenericVersiportAnalogInputDevice"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">key for the device</param>
|
||||||
|
/// <param name="name">name for the device</param>
|
||||||
|
/// <param name="postActivationFunc">function to call after activation</param>
|
||||||
|
/// <param name="config">IO port configuration</param>
|
||||||
public GenericVersiportAnalogInputDevice(string key, string name, Func<IOPortConfig, Versiport> postActivationFunc, IOPortConfig config) :
|
public GenericVersiportAnalogInputDevice(string key, string name, Func<IOPortConfig, Versiport> postActivationFunc, IOPortConfig config) :
|
||||||
base(key, name)
|
base(key, name)
|
||||||
{
|
{
|
||||||
InputValueFeedback = new IntFeedback(InputValueFeedbackFunc);
|
InputValueFeedback = new IntFeedback("inputValue", () => inputPort.AnalogIn);
|
||||||
InputMinimumChangeFeedback = new IntFeedback(InputMinimumChangeFeedbackFunc);
|
InputMinimumChangeFeedback = new IntFeedback("inputMinimumChange", () => inputPort.AnalogMinChange);
|
||||||
|
|
||||||
AddPostActivationAction(() =>
|
AddPostActivationAction(() =>
|
||||||
{
|
{
|
||||||
InputPort = postActivationFunc(config);
|
inputPort = postActivationFunc(config);
|
||||||
|
|
||||||
InputPort.Register();
|
inputPort.Register();
|
||||||
|
|
||||||
InputPort.SetVersiportConfiguration(eVersiportConfiguration.AnalogInput);
|
inputPort.SetVersiportConfiguration(eVersiportConfiguration.AnalogInput);
|
||||||
InputPort.AnalogMinChange = (ushort)(config.MinimumChange > 0 ? config.MinimumChange : 655);
|
inputPort.AnalogMinChange = (ushort)(config.MinimumChange > 0 ? config.MinimumChange : 655);
|
||||||
if (config.DisablePullUpResistor)
|
if (config.DisablePullUpResistor)
|
||||||
InputPort.DisablePullUpResistor = true;
|
inputPort.DisablePullUpResistor = true;
|
||||||
|
|
||||||
InputPort.VersiportChange += InputPort_VersiportChange;
|
inputPort.VersiportChange += InputPort_VersiportChange;
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Created GenericVersiportAnalogInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, InputPort.DisablePullUpResistor);
|
|
||||||
|
|
||||||
|
this.LogDebug("Created GenericVersiportAnalogInputDevice on port {port}. DisablePullUpResistor: {pullUpResistorDisabled}", config.PortNumber, inputPort.DisablePullUpResistor);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -69,20 +67,17 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set minimum voltage change for device to update voltage changed method
|
/// Set minimum voltage change for device to update voltage changed method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">valid values range from 0 - 65535, representing the full 100% range of the processor voltage source. Check processor documentation for details</param>
|
/// <param name="value">valid values range from 0 - 65535, representing the full 100% range of the processor voltage source. Check processor documentation for details</param>
|
||||||
/// <summary>
|
|
||||||
/// SetMinimumChange method
|
|
||||||
/// </summary>
|
|
||||||
public void SetMinimumChange(ushort value)
|
public void SetMinimumChange(ushort value)
|
||||||
{
|
{
|
||||||
InputPort.AnalogMinChange = value;
|
inputPort.AnalogMinChange = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputPort_VersiportChange(Versiport port, VersiportEventArgs args)
|
void InputPort_VersiportChange(Versiport port, VersiportEventArgs args)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Versiport change: {0}", args.Event);
|
this.LogDebug("Versiport change: {event}", args.Event);
|
||||||
|
|
||||||
if(args.Event == eVersiportEvent.AnalogInChange)
|
if (args.Event == eVersiportEvent.AnalogInChange)
|
||||||
InputValueFeedback.FireUpdate();
|
InputValueFeedback.FireUpdate();
|
||||||
if (args.Event == eVersiportEvent.AnalogMinChangeChange)
|
if (args.Event == eVersiportEvent.AnalogMinChangeChange)
|
||||||
InputMinimumChangeFeedback.FireUpdate();
|
InputMinimumChangeFeedback.FireUpdate();
|
||||||
@@ -91,9 +86,6 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
|
|
||||||
#region Bridge Linking
|
#region Bridge Linking
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// LinkToApi method
|
|
||||||
/// </summary>
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
|
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
|
||||||
{
|
{
|
||||||
@@ -110,12 +102,12 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
|
this.LogWarning("Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
|
this.LogDebug("Linking to Trilist '{trilistId}'", trilist.ID.ToString("X"));
|
||||||
|
|
||||||
// Link feedback for input state
|
// Link feedback for input state
|
||||||
InputValueFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputValue.JoinNumber]);
|
InputValueFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputValue.JoinNumber]);
|
||||||
@@ -125,8 +117,8 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Input is null", Key);
|
this.LogError("Unable to link device {key}: {message}", Key, e.Message);
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e);
|
this.LogDebug(e, "Stack Trace: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
trilist.OnlineStatusChange += (d, args) =>
|
trilist.OnlineStatusChange += (d, args) =>
|
||||||
@@ -138,11 +130,6 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void trilist_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
@@ -151,70 +138,55 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static Versiport GetVersiportDigitalInput(IOPortConfig dc)
|
public static Versiport GetVersiportDigitalInput(IOPortConfig dc)
|
||||||
{
|
{
|
||||||
|
|
||||||
IIOPorts ioPortDevice;
|
|
||||||
|
|
||||||
if (dc.PortDeviceKey.Equals("processor"))
|
if (dc.PortDeviceKey.Equals("processor"))
|
||||||
{
|
{
|
||||||
if (!Global.ControlSystem.SupportsVersiport)
|
if (!Global.ControlSystem.SupportsVersiport)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Processor does not support Versiports");
|
Debug.LogError("GetVersiportAnalogInput: Processor does not support Versiports");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ioPortDevice = Global.ControlSystem;
|
return Global.ControlSystem.VersiPorts[dc.PortNumber];
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (!(DeviceManager.GetDeviceForKey(dc.PortDeviceKey) is IIOPorts ioPortDevice))
|
||||||
{
|
{
|
||||||
var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts;
|
Debug.LogError("GetVersiportAnalogInput: Device {key} is not a valid device", dc.PortDeviceKey);
|
||||||
if (ioPortDev == null)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Device {0} is not a valid device", dc.PortDeviceKey);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ioPortDevice = ioPortDev;
|
|
||||||
}
|
|
||||||
if (ioPortDevice == null)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Device '0' is not a valid IIOPorts Device", dc.PortDeviceKey);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts)
|
if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber);
|
Debug.LogError("GetVersiportAnalogInput: Device {key} does not contain a port {port}", dc.PortDeviceKey, dc.PortNumber);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if(!ioPortDevice.VersiPorts[dc.PortNumber].SupportsAnalogInput)
|
if (!ioPortDevice.VersiPorts[dc.PortNumber].SupportsAnalogInput)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Device {0} does not support AnalogInput on port {1}", dc.PortDeviceKey, dc.PortNumber);
|
Debug.LogError("GetVersiportAnalogInput: Device {key} does not support AnalogInput on port {port}", dc.PortDeviceKey, dc.PortNumber);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return ioPortDevice.VersiPorts[dc.PortNumber];
|
return ioPortDevice.VersiPorts[dc.PortNumber];
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a GenericVersiportAbalogInputDeviceFactory
|
/// Factory for creating GenericVersiportAnalogInputDevice devices
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GenericVersiportAbalogInputDeviceFactory : EssentialsDeviceFactory<GenericVersiportAnalogInputDevice>
|
public class GenericVersiportAnalogInputDeviceFactory : EssentialsDeviceFactory<GenericVersiportAnalogInputDevice>
|
||||||
{
|
{
|
||||||
public GenericVersiportAbalogInputDeviceFactory()
|
/// <summary>
|
||||||
|
/// Constructor for GenericVersiportAnalogInputDeviceFactory
|
||||||
|
/// </summary>
|
||||||
|
public GenericVersiportAnalogInputDeviceFactory()
|
||||||
{
|
{
|
||||||
TypeNames = new List<string>() { "versiportanaloginput" };
|
TypeNames = new List<string>() { "versiportanaloginput" };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// BuildDevice method
|
|
||||||
/// </summary>
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Versiport Device");
|
Debug.LogDebug("Factory Attempting to create new Generic Versiport Device");
|
||||||
|
|
||||||
var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString());
|
var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString());
|
||||||
|
|
||||||
|
|||||||
@@ -2,78 +2,82 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using Crestron.SimplSharpPro;
|
using Crestron.SimplSharpPro;
|
||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
|
|
||||||
using PepperDash.Core;
|
|
||||||
using PepperDash.Essentials.Core.Config;
|
|
||||||
using PepperDash.Essentials.Core.Bridges;
|
|
||||||
|
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Serilog.Events;
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Core.Logging;
|
||||||
|
using PepperDash.Essentials.Core.Bridges;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core.CrestronIO
|
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, IPartitionStateProvider
|
public class GenericVersiportDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput, IPartitionStateProvider, IHasFeedback
|
||||||
{
|
{
|
||||||
public Versiport InputPort { get; private set; }
|
private Versiport inputPort;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the InputStateFeedback
|
||||||
|
/// </summary>
|
||||||
public BoolFeedback InputStateFeedback { get; private set; }
|
public BoolFeedback InputStateFeedback { get; private set; }
|
||||||
|
|
||||||
Func<bool> InputStateFeedbackFunc
|
/// <inheritdoc />
|
||||||
{
|
public FeedbackCollection<Feedback> Feedbacks { get; private set; } = new FeedbackCollection<Feedback>();
|
||||||
get
|
|
||||||
{
|
|
||||||
return () => InputPort.DigitalIn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the PartitionPresentFeedback
|
/// Gets or sets the PartitionPresentFeedback
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BoolFeedback PartitionPresentFeedback { get; }
|
public BoolFeedback PartitionPresentFeedback { get; }
|
||||||
|
|
||||||
public bool PartitionPresent => !InputStateFeedbackFunc();
|
/// <summary>
|
||||||
|
/// Get partition state
|
||||||
|
/// </summary>
|
||||||
|
public bool PartitionPresent => !inputPort.DigitalIn;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="GenericVersiportDigitalInputDevice"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">key for device</param>
|
||||||
|
/// <param name="name">name for device</param>
|
||||||
|
/// <param name="postActivationFunc">function to call after activation. Should return the Versiport</param>
|
||||||
|
/// <param name="config">config for device</param>
|
||||||
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("inputState", () => inputPort.DigitalIn);
|
||||||
PartitionPresentFeedback = new BoolFeedback(() => !InputStateFeedbackFunc());
|
PartitionPresentFeedback = new BoolFeedback("partitionPresent", () => !inputPort.DigitalIn);
|
||||||
|
|
||||||
AddPostActivationAction(() =>
|
AddPostActivationAction(() =>
|
||||||
{
|
{
|
||||||
InputPort = postActivationFunc(config);
|
inputPort = postActivationFunc(config);
|
||||||
|
|
||||||
InputPort.Register();
|
inputPort.Register();
|
||||||
|
|
||||||
InputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput);
|
inputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput);
|
||||||
if (config.DisablePullUpResistor)
|
if (config.DisablePullUpResistor)
|
||||||
InputPort.DisablePullUpResistor = true;
|
inputPort.DisablePullUpResistor = true;
|
||||||
|
|
||||||
InputPort.VersiportChange += InputPort_VersiportChange;
|
inputPort.VersiportChange += InputPort_VersiportChange;
|
||||||
|
|
||||||
InputStateFeedback.FireUpdate();
|
InputStateFeedback.FireUpdate();
|
||||||
PartitionPresentFeedback.FireUpdate();
|
PartitionPresentFeedback.FireUpdate();
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, InputPort.DisablePullUpResistor);
|
this.LogDebug("Created GenericVersiportDigitalInputDevice for port {port}. DisablePullUpResistor: {pullUpResistorDisable}", config.PortNumber, inputPort.DisablePullUpResistor);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Feedbacks.Add(InputStateFeedback);
|
||||||
|
Feedbacks.Add(PartitionPresentFeedback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputPort_VersiportChange(Versiport port, VersiportEventArgs args)
|
void InputPort_VersiportChange(Versiport port, VersiportEventArgs args)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Versiport change: {0}", args.Event);
|
this.LogDebug("Versiport change: {0}", args.Event);
|
||||||
|
|
||||||
if(args.Event == eVersiportEvent.DigitalInChange)
|
if (args.Event == eVersiportEvent.DigitalInChange)
|
||||||
{
|
{
|
||||||
InputStateFeedback.FireUpdate();
|
InputStateFeedback.FireUpdate();
|
||||||
PartitionPresentFeedback.FireUpdate();
|
PartitionPresentFeedback.FireUpdate();
|
||||||
@@ -102,20 +106,20 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
|
this.LogWarning("Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
|
this.LogDebug("Linking to Trilist '{0}'", trilist.ID.ToString("X"));
|
||||||
|
|
||||||
// Link feedback for input state
|
// Link feedback for input state
|
||||||
InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]);
|
InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Input is null", Key);
|
this.LogError("Unable to link device {key}. Input is null. {message}", Key, e.Message);
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e);
|
this.LogDebug(e, "Stack Trace: ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,63 +131,50 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static Versiport GetVersiportDigitalInput(IOPortConfig dc)
|
public static Versiport GetVersiportDigitalInput(IOPortConfig dc)
|
||||||
{
|
{
|
||||||
|
|
||||||
IIOPorts ioPortDevice;
|
|
||||||
|
|
||||||
if (dc.PortDeviceKey.Equals("processor"))
|
if (dc.PortDeviceKey.Equals("processor"))
|
||||||
{
|
{
|
||||||
if (!Global.ControlSystem.SupportsVersiport)
|
if (!Global.ControlSystem.SupportsVersiport)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalInput: Processor does not support Versiports");
|
Debug.LogError("GetVersiportDigitalInput: Processor does not support Versiports");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ioPortDevice = Global.ControlSystem;
|
return Global.ControlSystem.VersiPorts[dc.PortNumber];
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (!(DeviceManager.GetDeviceForKey(dc.PortDeviceKey) is IIOPorts ioPortDevice))
|
||||||
{
|
{
|
||||||
var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts;
|
Debug.LogError("GetVersiportDigitalInput: Device {key} is not a valid device", dc.PortDeviceKey);
|
||||||
if (ioPortDev == null)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalInput: Device {0} is not a valid device", dc.PortDeviceKey);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ioPortDevice = ioPortDev;
|
|
||||||
}
|
|
||||||
if (ioPortDevice == null)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalInput: Device '0' is not a valid IIOPorts Device", dc.PortDeviceKey);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts)
|
if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber);
|
Debug.LogError("GetVersiportDigitalInput: Device {key} does not contain versiport {port}", dc.PortDeviceKey, dc.PortNumber);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ioPortDevice.VersiPorts[dc.PortNumber];
|
return ioPortDevice.VersiPorts[dc.PortNumber];
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a GenericVersiportDigitalInputDeviceFactory
|
/// Factory class for GenericVersiportDigitalInputDevice
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GenericVersiportDigitalInputDeviceFactory : EssentialsDeviceFactory<GenericVersiportDigitalInputDevice>
|
public class GenericVersiportDigitalInputDeviceFactory : EssentialsDeviceFactory<GenericVersiportDigitalInputDevice>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for GenericVersiportDigitalInputDeviceFactory
|
||||||
|
/// </summary>
|
||||||
public GenericVersiportDigitalInputDeviceFactory()
|
public GenericVersiportDigitalInputDeviceFactory()
|
||||||
{
|
{
|
||||||
TypeNames = new List<string>() { "versiportinput" };
|
TypeNames = new List<string>() { "versiportinput" };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// BuildDevice method
|
|
||||||
/// </summary>
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Versiport Device");
|
Debug.LogDebug("Factory Attempting to create new Generic Versiport Device");
|
||||||
|
|
||||||
var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString());
|
var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString());
|
||||||
|
|
||||||
|
|||||||
@@ -2,18 +2,13 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using Crestron.SimplSharpPro;
|
using Crestron.SimplSharpPro;
|
||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
|
|
||||||
using PepperDash.Core;
|
|
||||||
using PepperDash.Essentials.Core.Config;
|
|
||||||
using PepperDash.Essentials.Core.Bridges;
|
|
||||||
|
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Core.Logging;
|
||||||
|
using PepperDash.Essentials.Core.Bridges;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core.CrestronIO
|
namespace PepperDash.Essentials.Core.CrestronIO
|
||||||
@@ -21,76 +16,68 @@ 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 GenericVersiportDigitalOutputDevice : EssentialsBridgeableDevice, IDigitalOutput
|
public class GenericVersiportDigitalOutputDevice : EssentialsBridgeableDevice, IDigitalOutput, IHasFeedback
|
||||||
{
|
{
|
||||||
public Versiport OutputPort { get; private set; }
|
private Versiport outputPort;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the OutputStateFeedback
|
||||||
|
/// </summary>
|
||||||
public BoolFeedback OutputStateFeedback { get; private set; }
|
public BoolFeedback OutputStateFeedback { get; private set; }
|
||||||
|
|
||||||
Func<bool> OutputStateFeedbackFunc
|
/// <inheritdoc />
|
||||||
{
|
public FeedbackCollection<Feedback> Feedbacks { get; private set; } = new FeedbackCollection<Feedback>();
|
||||||
get
|
|
||||||
{
|
|
||||||
return () => OutputPort.DigitalOut;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="GenericVersiportDigitalOutputDevice"/> class.
|
||||||
|
/// </summary>
|
||||||
public GenericVersiportDigitalOutputDevice(string key, string name, Func<IOPortConfig, Versiport> postActivationFunc, IOPortConfig config) :
|
public GenericVersiportDigitalOutputDevice(string key, string name, Func<IOPortConfig, Versiport> postActivationFunc, IOPortConfig config) :
|
||||||
base(key, name)
|
base(key, name)
|
||||||
{
|
{
|
||||||
OutputStateFeedback = new BoolFeedback(OutputStateFeedbackFunc);
|
OutputStateFeedback = new BoolFeedback("outputState", () => outputPort.DigitalOut);
|
||||||
|
|
||||||
AddPostActivationAction(() =>
|
AddPostActivationAction(() =>
|
||||||
{
|
{
|
||||||
OutputPort = postActivationFunc(config);
|
outputPort = postActivationFunc(config);
|
||||||
|
|
||||||
OutputPort.Register();
|
outputPort.Register();
|
||||||
|
|
||||||
|
|
||||||
if (!OutputPort.SupportsDigitalOutput)
|
if (!outputPort.SupportsDigitalOutput)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Device does not support configuration as a Digital Output");
|
this.LogError("Device does not support configuration as a Digital Output");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalOutput);
|
outputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalOutput);
|
||||||
|
|
||||||
|
|
||||||
OutputPort.VersiportChange += OutputPort_VersiportChange;
|
outputPort.VersiportChange += OutputPort_VersiportChange;
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutputPort_VersiportChange(Versiport port, VersiportEventArgs args)
|
void OutputPort_VersiportChange(Versiport port, VersiportEventArgs args)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Versiport change: {0}", args.Event);
|
this.LogDebug("Versiport change: {event}", args.Event);
|
||||||
|
|
||||||
if(args.Event == eVersiportEvent.DigitalOutChange)
|
if (args.Event == eVersiportEvent.DigitalOutChange)
|
||||||
OutputStateFeedback.FireUpdate();
|
OutputStateFeedback.FireUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set value of the versiport digital output
|
/// Set value of the versiport digital output
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state">value to set the output to</param>
|
/// <param name="state">value to set the output to</param>
|
||||||
/// <summary>
|
|
||||||
/// SetOutput method
|
|
||||||
/// </summary>
|
|
||||||
public void SetOutput(bool state)
|
public void SetOutput(bool state)
|
||||||
{
|
{
|
||||||
if (OutputPort.SupportsDigitalOutput)
|
if (!outputPort.SupportsDigitalOutput)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Passed the Check");
|
this.LogError("Versiport does not support Digital Output Mode");
|
||||||
|
return;
|
||||||
OutputPort.DigitalOut = state;
|
}
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Versiport does not support Digital Output Mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
outputPort.DigitalOut = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Bridge Linking
|
#region Bridge Linking
|
||||||
@@ -114,12 +101,12 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
|
this.LogWarning("Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
|
this.LogDebug("Linking to Trilist '{0}'", trilist.ID.ToString("X"));
|
||||||
|
|
||||||
// Link feedback for input state
|
// Link feedback for input state
|
||||||
OutputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.OutputState.JoinNumber]);
|
OutputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.OutputState.JoinNumber]);
|
||||||
@@ -127,8 +114,8 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Input is null", Key);
|
this.LogError("Unable to link device: {message}", e.Message);
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e);
|
this.LogDebug(e, "Stack Trace: ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,41 +127,28 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static Versiport GetVersiportDigitalOutput(IOPortConfig dc)
|
public static Versiport GetVersiportDigitalOutput(IOPortConfig dc)
|
||||||
{
|
{
|
||||||
|
if (dc.PortDeviceKey.Equals("processor"))
|
||||||
IIOPorts ioPortDevice;
|
{
|
||||||
|
if (!Global.ControlSystem.SupportsVersiport)
|
||||||
if (dc.PortDeviceKey.Equals("processor"))
|
|
||||||
{
|
{
|
||||||
if (!Global.ControlSystem.SupportsVersiport)
|
Debug.LogError("GetVersiportDigitalOutput: Processor does not support Versiports");
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOuptut: Processor does not support Versiports");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ioPortDevice = Global.ControlSystem;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts;
|
|
||||||
if (ioPortDev == null)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOuptut: Device {0} is not a valid device", dc.PortDeviceKey);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ioPortDevice = ioPortDev;
|
|
||||||
}
|
|
||||||
if (ioPortDevice == null)
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOuptut: Device '0' is not a valid IOPorts Device", dc.PortDeviceKey);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
return Global.ControlSystem.VersiPorts[dc.PortNumber];
|
||||||
|
}
|
||||||
|
|
||||||
if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts)
|
if (!(DeviceManager.GetDeviceForKey(dc.PortDeviceKey) is IIOPorts ioPortDevice))
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOuptut: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber);
|
Debug.LogError("GetVersiportDigitalOutput: Device {key} is not a valid device", dc.PortDeviceKey);
|
||||||
}
|
return null;
|
||||||
var port = ioPortDevice.VersiPorts[dc.PortNumber];
|
}
|
||||||
return port;
|
|
||||||
|
|
||||||
|
if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOutput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return ioPortDevice.VersiPorts[dc.PortNumber];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,18 +158,18 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GenericVersiportDigitalOutputDeviceFactory : EssentialsDeviceFactory<GenericVersiportDigitalInputDevice>
|
public class GenericVersiportDigitalOutputDeviceFactory : EssentialsDeviceFactory<GenericVersiportDigitalInputDevice>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initialize a new instance of the <see cref="GenericVersiportDigitalOutputDeviceFactory"/> class.
|
||||||
|
/// </summary>
|
||||||
public GenericVersiportDigitalOutputDeviceFactory()
|
public GenericVersiportDigitalOutputDeviceFactory()
|
||||||
{
|
{
|
||||||
TypeNames = new List<string>() { "versiportoutput" };
|
TypeNames = new List<string>() { "versiportoutput" };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// BuildDevice method
|
|
||||||
/// </summary>
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Versiport Device");
|
Debug.LogDebug("Factory Attempting to create new Generic Versiport Device");
|
||||||
|
|
||||||
var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString());
|
var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString());
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,12 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IAnalogInput
|
public interface IAnalogInput
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get the InputValueFeedback.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Updates when the analog input value changes
|
||||||
|
/// </remarks>
|
||||||
IntFeedback InputValueFeedback { get; }
|
IntFeedback InputValueFeedback { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,25 +14,28 @@ namespace PepperDash.Essentials.Core.CrestronIO
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class IOPortConfig
|
public class IOPortConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("portDeviceKey")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the PortDeviceKey
|
/// Gets or sets the PortDeviceKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("portDeviceKey")]
|
||||||
public string PortDeviceKey { get; set; }
|
public string PortDeviceKey { get; set; }
|
||||||
[JsonProperty("portNumber")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the PortNumber
|
/// Gets or sets the PortNumber
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("portNumber")]
|
||||||
public uint PortNumber { get; set; }
|
public uint PortNumber { get; set; }
|
||||||
[JsonProperty("disablePullUpResistor")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the DisablePullUpResistor
|
/// Gets or sets the DisablePullUpResistor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("disablePullUpResistor")]
|
||||||
public bool DisablePullUpResistor { get; set; }
|
public bool DisablePullUpResistor { get; set; }
|
||||||
[JsonProperty("minimumChange")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the MinimumChange
|
/// Gets or sets the MinimumChange
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("minimumChange")]
|
||||||
public int MinimumChange { get; set; }
|
public int MinimumChange { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace PepperDash.Essentials.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines minimum functionality for an audio zone
|
||||||
|
/// </summary>
|
||||||
|
public interface IAudioZone : IBasicVolumeWithFeedback
|
||||||
|
{
|
||||||
|
void SelectInput(ushort input);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Identifies a device that contains audio zones
|
||||||
|
/// </summary>
|
||||||
|
public interface IAudioZones : IRouting
|
||||||
|
{
|
||||||
|
Dictionary<uint, IAudioZone> Zone { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using PepperDash.Core;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines minimal volume and mute control methods
|
||||||
|
/// </summary>
|
||||||
|
public interface IBasicVolumeControls : IKeyName
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Increases the volume
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pressRelease">Indicates whether the volume change is a press and hold action</param>
|
||||||
|
void VolumeUp(bool pressRelease);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decreases the volume
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pressRelease">Indicates whether the volume change is a press and hold action</param>
|
||||||
|
void VolumeDown(bool pressRelease);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Toggles the mute state
|
||||||
|
/// </summary>
|
||||||
|
void MuteToggle();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace PepperDash.Essentials.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the contract for IBasicVolumeWithFeedback
|
||||||
|
/// </summary>
|
||||||
|
public interface IBasicVolumeWithFeedback : IBasicVolumeControls
|
||||||
|
{
|
||||||
|
BoolFeedback MuteFeedback { get; }
|
||||||
|
void MuteOn();
|
||||||
|
void MuteOff();
|
||||||
|
void SetVolume(ushort level);
|
||||||
|
IntFeedback VolumeLevelFeedback { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace PepperDash.Essentials.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the contract for IBasicVolumeWithFeedbackAdvanced
|
||||||
|
/// </summary>
|
||||||
|
public interface IBasicVolumeWithFeedbackAdvanced : IBasicVolumeWithFeedback
|
||||||
|
{
|
||||||
|
int RawVolumeLevel { get; }
|
||||||
|
|
||||||
|
eVolumeLevelUnits Units { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using PepperDash.Core;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Use this interface on a device or room if it uses custom Mobile Control messengers
|
||||||
|
/// </summary>
|
||||||
|
public interface ICustomMobileControl : IKeyed
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
namespace PepperDash.Essentials.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the contract for IFullAudioSettings
|
||||||
|
/// </summary>
|
||||||
|
public interface IFullAudioSettings : IBasicVolumeWithFeedback
|
||||||
|
{
|
||||||
|
void SetBalance(ushort level);
|
||||||
|
void BalanceLeft(bool pressRelease);
|
||||||
|
void BalanceRight(bool pressRelease);
|
||||||
|
|
||||||
|
void SetBass(ushort level);
|
||||||
|
void BassUp(bool pressRelease);
|
||||||
|
void BassDown(bool pressRelease);
|
||||||
|
|
||||||
|
void SetTreble(ushort level);
|
||||||
|
void TrebleUp(bool pressRelease);
|
||||||
|
void TrebleDown(bool pressRelease);
|
||||||
|
|
||||||
|
bool hasMaxVolume { get; }
|
||||||
|
void SetMaxVolume(ushort level);
|
||||||
|
void MaxVolumeUp(bool pressRelease);
|
||||||
|
void MaxVolumeDown(bool pressRelease);
|
||||||
|
|
||||||
|
bool hasDefaultVolume { get; }
|
||||||
|
void SetDefaultVolume(ushort level);
|
||||||
|
void DefaultVolumeUp(bool pressRelease);
|
||||||
|
void DefaultVolumeDown(bool pressRelease);
|
||||||
|
|
||||||
|
void LoudnessToggle();
|
||||||
|
void MonoToggle();
|
||||||
|
|
||||||
|
BoolFeedback LoudnessFeedback { get; }
|
||||||
|
BoolFeedback MonoFeedback { get; }
|
||||||
|
IntFeedback BalanceFeedback { get; }
|
||||||
|
IntFeedback BassFeedback { get; }
|
||||||
|
IntFeedback TrebleFeedback { get; }
|
||||||
|
IntFeedback MaxVolumeFeedback { get; }
|
||||||
|
IntFeedback DefaultVolumeFeedback { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the contract for IHasCurrentVolumeControls
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasCurrentVolumeControls
|
||||||
|
{
|
||||||
|
IBasicVolumeControls CurrentVolumeControls { get; }
|
||||||
|
event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
|
||||||
|
|
||||||
|
void SetDefaultLevels();
|
||||||
|
|
||||||
|
bool ZeroVolumeWhenSwtichingVolumeDevices { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace PepperDash.Essentials.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines basic mute control methods
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasMuteControl
|
||||||
|
{
|
||||||
|
void MuteToggle();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace PepperDash.Essentials.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines mute control methods and properties with feedback
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasMuteControlWithFeedback : IHasMuteControl
|
||||||
|
{
|
||||||
|
BoolFeedback MuteFeedback { get; }
|
||||||
|
void MuteOn();
|
||||||
|
void MuteOff();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace PepperDash.Essentials.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the contract for IHasVolumeControl
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasVolumeControl
|
||||||
|
{
|
||||||
|
void VolumeUp(bool pressRelease);
|
||||||
|
void VolumeDown(bool pressRelease);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace PepperDash.Essentials.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines volume control methods and properties with feedback
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasVolumeControlWithFeedback : IHasVolumeControl
|
||||||
|
{
|
||||||
|
void SetVolume(ushort level);
|
||||||
|
IntFeedback VolumeLevelFeedback { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace PepperDash.Essentials.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the contract for IHasVolumeDevice
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasVolumeDevice
|
||||||
|
{
|
||||||
|
IBasicVolumeControls VolumeDevice { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,155 +1,72 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using Crestron.SimplSharpPro;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Use this interface on a device or room if it uses custom Mobile Control messengers
|
|
||||||
/// </summary>
|
|
||||||
public interface ICustomMobileControl : IKeyed
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*/// <summary>
|
|
||||||
/// Describes a MobileControlSystemController
|
|
||||||
/// </summary>
|
|
||||||
public interface IMobileControl : IKeyed
|
|
||||||
{
|
|
||||||
void CreateMobileControlRoomBridge(IEssentialsRoom room, IMobileControl parent);
|
|
||||||
|
|
||||||
void LinkSystemMonitorToAppServer();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the contract for IMobileControl
|
/// Defines the contract for IMobileControl
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IMobileControl : IKeyed
|
public interface IMobileControl : IKeyed
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Host
|
||||||
|
/// </summary>
|
||||||
string Host { get; }
|
string Host { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Client App URL
|
||||||
|
/// </summary>
|
||||||
string ClientAppUrl { get; }
|
string ClientAppUrl { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the System UUID
|
||||||
|
/// </summary>
|
||||||
string SystemUuid { get; }
|
string SystemUuid { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the ApiOnlineAndAuthorized feedback
|
||||||
|
/// </summary>
|
||||||
BoolFeedback ApiOnlineAndAuthorized { get; }
|
BoolFeedback ApiOnlineAndAuthorized { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends the message object to the AppServer
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="o">Message to send</param>
|
||||||
void SendMessageObject(IMobileControlMessage o);
|
void SendMessageObject(IMobileControlMessage o);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds an action for a messenger
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Messenger type. Must implement IMobileControlMessenger</typeparam>
|
||||||
|
/// <param name="messenger">messenger to register</param>
|
||||||
|
/// <param name="action">action to add</param>
|
||||||
void AddAction<T>(T messenger, Action<string, string, JToken> action) where T : IMobileControlMessenger;
|
void AddAction<T>(T messenger, Action<string, string, JToken> action) where T : IMobileControlMessenger;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes an action for a messenger
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">key for action</param>
|
||||||
void RemoveAction(string key);
|
void RemoveAction(string key);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a device messenger
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="messenger">Messenger to add</param>
|
||||||
void AddDeviceMessenger(IMobileControlMessenger messenger);
|
void AddDeviceMessenger(IMobileControlMessenger messenger);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if a device messenger exists
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Messenger key to find</param>
|
||||||
bool CheckForDeviceMessenger(string key);
|
bool CheckForDeviceMessenger(string key);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a Room Messenger by key
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">messenger key to find</param>
|
||||||
|
/// <returns>Messenger if found, null otherwise</returns>
|
||||||
IMobileControlRoomMessenger GetRoomMessenger(string key);
|
IMobileControlRoomMessenger GetRoomMessenger(string key);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the contract for IMobileControlMessenger
|
|
||||||
/// </summary>
|
|
||||||
public interface IMobileControlMessenger : IKeyed
|
|
||||||
{
|
|
||||||
IMobileControl AppServerController { get; }
|
|
||||||
string MessagePath { get; }
|
|
||||||
|
|
||||||
string DeviceKey { get; }
|
|
||||||
void RegisterWithAppServer(IMobileControl appServerController);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IMobileControlMessage
|
|
||||||
{
|
|
||||||
[JsonProperty("type")]
|
|
||||||
string Type { get; }
|
|
||||||
|
|
||||||
[JsonProperty("clientId", NullValueHandling = NullValueHandling.Ignore)]
|
|
||||||
string ClientId { get; }
|
|
||||||
|
|
||||||
[JsonProperty("content", NullValueHandling = NullValueHandling.Ignore)]
|
|
||||||
JToken Content { get; }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the contract for IMobileControlRoomMessenger
|
|
||||||
/// </summary>
|
|
||||||
public interface IMobileControlRoomMessenger : IKeyed
|
|
||||||
{
|
|
||||||
event EventHandler<EventArgs> UserCodeChanged;
|
|
||||||
|
|
||||||
event EventHandler<EventArgs> UserPromptedForCode;
|
|
||||||
|
|
||||||
event EventHandler<EventArgs> ClientJoined;
|
|
||||||
|
|
||||||
event EventHandler<EventArgs> AppUrlChanged;
|
|
||||||
|
|
||||||
string UserCode { get; }
|
|
||||||
|
|
||||||
string QrCodeUrl { get; }
|
|
||||||
|
|
||||||
string QrCodeChecksum { get; }
|
|
||||||
|
|
||||||
string McServerUrl { get; }
|
|
||||||
|
|
||||||
string RoomName { get; }
|
|
||||||
|
|
||||||
string AppUrl { get; }
|
|
||||||
|
|
||||||
void UpdateAppUrl(string url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the contract for IMobileControlAction
|
|
||||||
/// </summary>
|
|
||||||
public interface IMobileControlAction
|
|
||||||
{
|
|
||||||
IMobileControlMessenger Messenger { get; }
|
|
||||||
|
|
||||||
Action<string, string, JToken> Action { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the contract for IMobileControlTouchpanelController
|
|
||||||
/// </summary>
|
|
||||||
public interface IMobileControlTouchpanelController : IKeyed
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The default room key for the controller
|
|
||||||
/// </summary>
|
|
||||||
string DefaultRoomKey { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the application URL for the controller
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="url">The application URL</param>
|
|
||||||
void SetAppUrl(string url);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates whether the controller uses a direct server connection
|
|
||||||
/// </summary>
|
|
||||||
bool UseDirectServer { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates whether the controller is a Zoom Room controller
|
|
||||||
/// </summary>
|
|
||||||
bool ZoomRoomController { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Describes a MobileControl Crestron Touchpanel Controller
|
|
||||||
/// This interface extends the IMobileControlTouchpanelController to include connected IP information
|
|
||||||
/// </summary>
|
|
||||||
public interface IMobileControlCrestronTouchpanelController : IMobileControlTouchpanelController
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a collection of connected IP information for the touchpanel controller
|
|
||||||
/// </summary>
|
|
||||||
ReadOnlyCollection<ConnectedIpInformation> ConnectedIps { get; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the contract for IMobileControlAction
|
||||||
|
/// </summary>
|
||||||
|
public interface IMobileControlAction
|
||||||
|
{
|
||||||
|
IMobileControlMessenger Messenger { get; }
|
||||||
|
|
||||||
|
Action<string, string, JToken> Action { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using Crestron.SimplSharpPro;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Describes a MobileControl Crestron Touchpanel Controller
|
||||||
|
/// This interface extends the IMobileControlTouchpanelController to include connected IP information
|
||||||
|
/// </summary>
|
||||||
|
public interface IMobileControlCrestronTouchpanelController : IMobileControlTouchpanelController
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a collection of connected IP information for the touchpanel controller
|
||||||
|
/// </summary>
|
||||||
|
ReadOnlyCollection<ConnectedIpInformation> ConnectedIps { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||||
|
{
|
||||||
|
public interface IMobileControlMessage
|
||||||
|
{
|
||||||
|
[JsonProperty("type")]
|
||||||
|
string Type { get; }
|
||||||
|
|
||||||
|
[JsonProperty("clientId", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
string ClientId { get; }
|
||||||
|
|
||||||
|
[JsonProperty("content", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
JToken Content { get; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using PepperDash.Core;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the contract for IMobileControlMessenger
|
||||||
|
/// </summary>
|
||||||
|
public interface IMobileControlMessenger : IKeyed
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Parent controller for this messenger
|
||||||
|
/// </summary>
|
||||||
|
IMobileControl AppServerController { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Path to listen for messages
|
||||||
|
/// </summary>
|
||||||
|
string MessagePath { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Key of the device this messenger is associated with
|
||||||
|
/// </summary>
|
||||||
|
string DeviceKey { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Register this messenger with the AppServerController
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="appServerController"></param>
|
||||||
|
void RegisterWithAppServer(IMobileControl appServerController);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using PepperDash.Core;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the contract for IMobileControlMessenger
|
||||||
|
/// </summary>
|
||||||
|
public interface IMobileControlMessengerWithSubscriptions : IMobileControlMessenger
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unsubscribe a client from this messenger
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientId"></param>
|
||||||
|
void UnsubscribeClient(string clientId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Register this messenger with the AppServerController
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="appServerController">parent for this messenger</param>
|
||||||
|
/// <param name="enableMessengerSubscriptions">Enable messenger subscriptions</param>
|
||||||
|
void RegisterWithAppServer(IMobileControl appServerController, bool enableMessengerSubscriptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using PepperDash.Core;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the contract for IMobileControlRoomMessenger
|
||||||
|
/// </summary>
|
||||||
|
public interface IMobileControlRoomMessenger : IKeyed
|
||||||
|
{
|
||||||
|
event EventHandler<EventArgs> UserCodeChanged;
|
||||||
|
|
||||||
|
event EventHandler<EventArgs> UserPromptedForCode;
|
||||||
|
|
||||||
|
event EventHandler<EventArgs> ClientJoined;
|
||||||
|
|
||||||
|
event EventHandler<EventArgs> AppUrlChanged;
|
||||||
|
|
||||||
|
string UserCode { get; }
|
||||||
|
|
||||||
|
string QrCodeUrl { get; }
|
||||||
|
|
||||||
|
string QrCodeChecksum { get; }
|
||||||
|
|
||||||
|
string McServerUrl { get; }
|
||||||
|
|
||||||
|
string RoomName { get; }
|
||||||
|
|
||||||
|
string AppUrl { get; }
|
||||||
|
|
||||||
|
void UpdateAppUrl(string url);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using PepperDash.Core;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the contract for IMobileControlTouchpanelController
|
||||||
|
/// </summary>
|
||||||
|
public interface IMobileControlTouchpanelController : IKeyed
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The default room key for the controller
|
||||||
|
/// </summary>
|
||||||
|
string DefaultRoomKey { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the application URL for the controller
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="url">The application URL</param>
|
||||||
|
void SetAppUrl(string url);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the controller uses a direct server connection
|
||||||
|
/// </summary>
|
||||||
|
bool UseDirectServer { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the controller is a Zoom Room controller
|
||||||
|
/// </summary>
|
||||||
|
bool ZoomRoomController { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using Crestron.SimplSharpPro.DM.Streaming;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Crestron.SimplSharpPro.DM.Streaming;
|
||||||
|
using PepperDash.Core;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
@@ -11,7 +12,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// subscribers when the port information is updated. Implementations of this interface should ensure that the <see
|
/// subscribers when the port information is updated. Implementations of this interface should ensure that the <see
|
||||||
/// cref="PortInformationChanged"/> event is raised whenever the <see cref="NetworkPorts"/> collection
|
/// cref="PortInformationChanged"/> event is raised whenever the <see cref="NetworkPorts"/> collection
|
||||||
/// changes.</remarks>
|
/// changes.</remarks>
|
||||||
public interface INvxNetworkPortInformation
|
public interface INvxNetworkPortInformation : IKeyed
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when the port information changes.
|
/// Occurs when the port information changes.
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace PepperDash.Essentials.Core
|
||||||
|
{
|
||||||
|
public enum eVolumeLevelUnits
|
||||||
|
{
|
||||||
|
Decibels,
|
||||||
|
Percent,
|
||||||
|
Relative,
|
||||||
|
Absolute
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -60,9 +60,9 @@ namespace PepperDash.Essentials.Core
|
|||||||
ConsoleAccessLevelEnum.AccessOperator);
|
ConsoleAccessLevelEnum.AccessOperator);
|
||||||
CrestronConsole.AddNewConsoleCommand(DeviceJsonApi.DoDeviceActionWithJson, "devjson", "",
|
CrestronConsole.AddNewConsoleCommand(DeviceJsonApi.DoDeviceActionWithJson, "devjson", "",
|
||||||
ConsoleAccessLevelEnum.AccessOperator);
|
ConsoleAccessLevelEnum.AccessOperator);
|
||||||
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetProperties(s)), "devprops", "", ConsoleAccessLevelEnum.AccessOperator);
|
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetProperties(s).Replace(Environment.NewLine, "\r\n")), "devprops", "", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetMethods(s)), "devmethods", "", ConsoleAccessLevelEnum.AccessOperator);
|
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetMethods(s).Replace(Environment.NewLine, "\r\n")), "devmethods", "", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s)), "apimethods", "", ConsoleAccessLevelEnum.AccessOperator);
|
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s).Replace(Environment.NewLine, "\r\n")), "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);
|
||||||
|
|
||||||
@@ -202,14 +202,15 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
private static void ListDevices(string s)
|
private static void ListDevices(string s)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "{0} Devices registered with Device Manager:", Devices.Count);
|
CrestronConsole.ConsoleCommandResponse($"{Devices.Count} Devices registered with Device Manager:\r\n");
|
||||||
|
|
||||||
var sorted = Devices.Values.ToList();
|
var sorted = Devices.Values.ToList();
|
||||||
sorted.Sort((a, b) => a.Key.CompareTo(b.Key));
|
sorted.Sort((a, b) => a.Key.CompareTo(b.Key));
|
||||||
|
|
||||||
foreach (var d in sorted)
|
foreach (var d in sorted)
|
||||||
{
|
{
|
||||||
var name = d is IKeyName ? (d as IKeyName).Name : "---";
|
var name = d is IKeyName ? (d as IKeyName).Name : "---";
|
||||||
Debug.LogMessage(LogEventLevel.Information, " [{0}] {1}", d.Key, name);
|
CrestronConsole.ConsoleCommandResponse($" [{d.Key}] {name}\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,28 +219,17 @@ namespace PepperDash.Essentials.Core
|
|||||||
var dev = GetDeviceForKey(devKey);
|
var dev = GetDeviceForKey(devKey);
|
||||||
if (dev == null)
|
if (dev == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Device '{0}' not found", devKey);
|
CrestronConsole.ConsoleCommandResponse($"Device '{devKey}' not found\r\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!(dev is IHasFeedback statusDev))
|
if (!(dev is IHasFeedback statusDev))
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Device '{0}' does not have visible feedbacks", devKey);
|
CrestronConsole.ConsoleCommandResponse($"Device '{devKey}' does not have visible feedbacks\r\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
statusDev.DumpFeedbacksToConsole(true);
|
statusDev.DumpFeedbacksToConsole(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//static void ListDeviceCommands(string devKey)
|
|
||||||
//{
|
|
||||||
// var dev = GetDeviceForKey(devKey);
|
|
||||||
// if (dev == null)
|
|
||||||
// {
|
|
||||||
// Debug.LogMessage(LogEventLevel.Information, "Device '{0}' not found", devKey);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// Debug.LogMessage(LogEventLevel.Information, "This needs to be reworked. Stay tuned.", devKey);
|
|
||||||
//}
|
|
||||||
|
|
||||||
private static void ListDeviceCommStatuses(string input)
|
private static void ListDeviceCommStatuses(string input)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -249,12 +239,6 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//static void DoDeviceCommand(string command)
|
|
||||||
//{
|
|
||||||
// Debug.LogMessage(LogEventLevel.Information, "Not yet implemented. Stay tuned");
|
|
||||||
//}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// AddDevice method
|
/// AddDevice method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -3,16 +3,29 @@ using PepperDash.Essentials.Core.Bridges;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
public abstract class EssentialsBridgeableDevice:EssentialsDevice, IBridgeAdvanced
|
/// <summary>
|
||||||
|
/// Base class for devices that can be bridged to an EISC API.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class EssentialsBridgeableDevice : EssentialsDevice, IBridgeAdvanced
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="EssentialsBridgeableDevice"/> class with the specified key.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique key for the device.</param>
|
||||||
protected EssentialsBridgeableDevice(string key) : base(key)
|
protected EssentialsBridgeableDevice(string key) : base(key)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="EssentialsBridgeableDevice"/> class with the specified key and name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique key for the device.</param>
|
||||||
|
/// <param name="name">The display name for the device.</param>
|
||||||
protected EssentialsBridgeableDevice(string key, string name) : base(key, name)
|
protected EssentialsBridgeableDevice(string key, string name) : base(key, name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge);
|
public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
public List<string> TypeNames { get; protected set; }
|
public List<string> TypeNames { get; protected set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The method that will build the device
|
/// Build the device using the configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dc">The device config</param>
|
/// <param name="dc">The device config</param>
|
||||||
/// <returns>An instance of the device</returns>
|
/// <returns>An instance of the device</returns>
|
||||||
|
|||||||
@@ -1,65 +1,90 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the contract for IHasFeedback
|
/// Defines the contract for IHasFeedback
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IHasFeedback : IKeyed
|
public interface IHasFeedback : IKeyed
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This method shall return a list of all Output objects on a device,
|
/// This method returns a list of all Output objects on a device,
|
||||||
/// including all "aggregate" devices.
|
/// including all "aggregate" devices.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
FeedbackCollection<Feedback> Feedbacks { get; }
|
FeedbackCollection<Feedback> Feedbacks { get; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for IHasFeedback
|
||||||
|
/// </summary>
|
||||||
public static class IHasFeedbackExtensions
|
public static class IHasFeedbackExtensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the feedback type name for sorting purposes
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="feedback">The feedback to get the type name for</param>
|
||||||
|
/// <returns>A string representing the feedback type</returns>
|
||||||
|
private static string GetFeedbackTypeName(Feedback feedback)
|
||||||
|
{
|
||||||
|
if (feedback is BoolFeedback)
|
||||||
|
return "boolean";
|
||||||
|
else if (feedback is IntFeedback)
|
||||||
|
return "integer";
|
||||||
|
else if (feedback is StringFeedback)
|
||||||
|
return "string";
|
||||||
|
else
|
||||||
|
return feedback.GetType().Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dumps the feedbacks to the console
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source"></param>
|
||||||
|
/// <param name="getCurrentStates"></param>
|
||||||
public static void DumpFeedbacksToConsole(this IHasFeedback source, bool getCurrentStates)
|
public static void DumpFeedbacksToConsole(this IHasFeedback source, bool getCurrentStates)
|
||||||
{
|
{
|
||||||
Type t = source.GetType();
|
|
||||||
// get the properties and set them into a new collection of NameType wrappers
|
|
||||||
var props = t.GetProperties().Select(p => new PropertyNameType(p, t));
|
|
||||||
|
|
||||||
var feedbacks = source.Feedbacks;
|
var feedbacks = source.Feedbacks;
|
||||||
if (feedbacks != null)
|
|
||||||
|
if (feedbacks == null || feedbacks.Count == 0)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, source, "\n\nAvailable feedbacks:");
|
CrestronConsole.ConsoleCommandResponse("No available feedbacks\r\n");
|
||||||
foreach (var f in feedbacks)
|
return;
|
||||||
{
|
}
|
||||||
string val = "";
|
|
||||||
string type = "";
|
CrestronConsole.ConsoleCommandResponse("Available feedbacks:\r\n");
|
||||||
if (getCurrentStates)
|
|
||||||
{
|
// Sort feedbacks by type first, then by key
|
||||||
if (f is BoolFeedback)
|
var sortedFeedbacks = feedbacks.OrderBy(f => GetFeedbackTypeName(f)).ThenBy(f => string.IsNullOrEmpty(f.Key) ? "" : f.Key);
|
||||||
{
|
|
||||||
val = f.BoolValue.ToString();
|
foreach (var feedback in sortedFeedbacks)
|
||||||
type = "boolean";
|
{
|
||||||
}
|
string value = "";
|
||||||
else if (f is IntFeedback)
|
string type = "";
|
||||||
{
|
if (getCurrentStates)
|
||||||
val = f.IntValue.ToString();
|
{
|
||||||
type = "integer";
|
if (feedback is BoolFeedback)
|
||||||
}
|
{
|
||||||
else if (f is StringFeedback)
|
value = feedback.BoolValue.ToString();
|
||||||
{
|
type = "boolean";
|
||||||
val = f.StringValue;
|
}
|
||||||
type = "string";
|
else if (feedback is IntFeedback)
|
||||||
}
|
{
|
||||||
}
|
value = feedback.IntValue.ToString();
|
||||||
Debug.LogMessage(LogEventLevel.Information, "{0,-12} {1, -25} {2}", type,
|
type = "integer";
|
||||||
(string.IsNullOrEmpty(f.Key) ? "-no key-" : f.Key), val);
|
}
|
||||||
}
|
else if (feedback is StringFeedback)
|
||||||
|
{
|
||||||
|
value = feedback.StringValue;
|
||||||
|
type = "string";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CrestronConsole.ConsoleCommandResponse($" {type,-12} {(string.IsNullOrEmpty(feedback.Key) ? "-no key-" : feedback.Key),-25} {value}\r\n");
|
||||||
}
|
}
|
||||||
else
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, source, "No available outputs:");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Defines minimal volume and mute control methods
|
|
||||||
/// </summary>
|
|
||||||
public interface IBasicVolumeControls
|
|
||||||
{
|
|
||||||
void VolumeUp(bool pressRelease);
|
|
||||||
void VolumeDown(bool pressRelease);
|
|
||||||
void MuteToggle();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the contract for IHasVolumeControl
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasVolumeControl
|
|
||||||
{
|
|
||||||
void VolumeUp(bool pressRelease);
|
|
||||||
void VolumeDown(bool pressRelease);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines volume control methods and properties with feedback
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasVolumeControlWithFeedback : IHasVolumeControl
|
|
||||||
{
|
|
||||||
void SetVolume(ushort level);
|
|
||||||
IntFeedback VolumeLevelFeedback { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines basic mute control methods
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasMuteControl
|
|
||||||
{
|
|
||||||
void MuteToggle();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines mute control methods and properties with feedback
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasMuteControlWithFeedback : IHasMuteControl
|
|
||||||
{
|
|
||||||
BoolFeedback MuteFeedback { get; }
|
|
||||||
void MuteOn();
|
|
||||||
void MuteOff();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the contract for IBasicVolumeWithFeedback
|
|
||||||
/// </summary>
|
|
||||||
public interface IBasicVolumeWithFeedback : IBasicVolumeControls
|
|
||||||
{
|
|
||||||
BoolFeedback MuteFeedback { get; }
|
|
||||||
void MuteOn();
|
|
||||||
void MuteOff();
|
|
||||||
void SetVolume(ushort level);
|
|
||||||
IntFeedback VolumeLevelFeedback { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the contract for IBasicVolumeWithFeedbackAdvanced
|
|
||||||
/// </summary>
|
|
||||||
public interface IBasicVolumeWithFeedbackAdvanced : IBasicVolumeWithFeedback
|
|
||||||
{
|
|
||||||
int RawVolumeLevel { get; }
|
|
||||||
|
|
||||||
eVolumeLevelUnits Units { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum eVolumeLevelUnits
|
|
||||||
{
|
|
||||||
Decibels,
|
|
||||||
Percent,
|
|
||||||
Relative,
|
|
||||||
Absolute
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the contract for IHasCurrentVolumeControls
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasCurrentVolumeControls
|
|
||||||
{
|
|
||||||
IBasicVolumeControls CurrentVolumeControls { get; }
|
|
||||||
event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
|
|
||||||
|
|
||||||
void SetDefaultLevels();
|
|
||||||
|
|
||||||
bool ZeroVolumeWhenSwtichingVolumeDevices { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the contract for IFullAudioSettings
|
|
||||||
/// </summary>
|
|
||||||
public interface IFullAudioSettings : IBasicVolumeWithFeedback
|
|
||||||
{
|
|
||||||
void SetBalance(ushort level);
|
|
||||||
void BalanceLeft(bool pressRelease);
|
|
||||||
void BalanceRight(bool pressRelease);
|
|
||||||
|
|
||||||
void SetBass(ushort level);
|
|
||||||
void BassUp(bool pressRelease);
|
|
||||||
void BassDown(bool pressRelease);
|
|
||||||
|
|
||||||
void SetTreble(ushort level);
|
|
||||||
void TrebleUp(bool pressRelease);
|
|
||||||
void TrebleDown(bool pressRelease);
|
|
||||||
|
|
||||||
bool hasMaxVolume { get; }
|
|
||||||
void SetMaxVolume(ushort level);
|
|
||||||
void MaxVolumeUp(bool pressRelease);
|
|
||||||
void MaxVolumeDown(bool pressRelease);
|
|
||||||
|
|
||||||
bool hasDefaultVolume { get; }
|
|
||||||
void SetDefaultVolume(ushort level);
|
|
||||||
void DefaultVolumeUp(bool pressRelease);
|
|
||||||
void DefaultVolumeDown(bool pressRelease);
|
|
||||||
|
|
||||||
void LoudnessToggle();
|
|
||||||
void MonoToggle();
|
|
||||||
|
|
||||||
BoolFeedback LoudnessFeedback { get; }
|
|
||||||
BoolFeedback MonoFeedback { get; }
|
|
||||||
IntFeedback BalanceFeedback { get; }
|
|
||||||
IntFeedback BassFeedback { get; }
|
|
||||||
IntFeedback TrebleFeedback { get; }
|
|
||||||
IntFeedback MaxVolumeFeedback { get; }
|
|
||||||
IntFeedback DefaultVolumeFeedback { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the contract for IHasVolumeDevice
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasVolumeDevice
|
|
||||||
{
|
|
||||||
IBasicVolumeControls VolumeDevice { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Identifies a device that contains audio zones
|
|
||||||
/// </summary>
|
|
||||||
public interface IAudioZones : IRouting
|
|
||||||
{
|
|
||||||
Dictionary<uint, IAudioZone> Zone { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines minimum functionality for an audio zone
|
|
||||||
/// </summary>
|
|
||||||
public interface IAudioZone : IBasicVolumeWithFeedback
|
|
||||||
{
|
|
||||||
void SelectInput(ushort input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -77,9 +77,6 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// A name that will override the source's name on the UI
|
/// A name that will override the source's name on the UI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("name")]
|
[JsonProperty("name")]
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the Name
|
|
||||||
/// </summary>
|
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -16,121 +16,201 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
{
|
{
|
||||||
|
|
||||||
// Processor Attributes
|
// Processor Attributes
|
||||||
|
/// <summary>
|
||||||
|
/// Processor IP 1
|
||||||
|
/// </summary>
|
||||||
[JoinName("ProcessorIp1")]
|
[JoinName("ProcessorIp1")]
|
||||||
public JoinDataComplete ProcessorIp1 = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1, AttributeName = "Info - Processor - IP 1" },
|
public JoinDataComplete ProcessorIp1 = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1, AttributeName = "Info - Processor - IP 1" },
|
||||||
new JoinMetadata { Description = "Info - Processor - IP 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
new JoinMetadata { Description = "Info - Processor - IP 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processor IP 2
|
||||||
|
/// </summary>
|
||||||
[JoinName("ProcessorIp2")]
|
[JoinName("ProcessorIp2")]
|
||||||
public JoinDataComplete ProcessorIp2 = new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1, AttributeName = "Info - Processor - IP 2" },
|
public JoinDataComplete ProcessorIp2 = new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1, AttributeName = "Info - Processor - IP 2" },
|
||||||
new JoinMetadata { Description = "Info - Processor - IP 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
new JoinMetadata { Description = "Info - Processor - IP 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processor Gateway
|
||||||
|
/// </summary>
|
||||||
[JoinName("ProcessorGateway")]
|
[JoinName("ProcessorGateway")]
|
||||||
public JoinDataComplete ProcessorGateway = new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1, AttributeName = "Info - Processor - Gateway" },
|
public JoinDataComplete ProcessorGateway = new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1, AttributeName = "Info - Processor - Gateway" },
|
||||||
new JoinMetadata { Description = "Info - Processor - Gateway", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
new JoinMetadata { Description = "Info - Processor - Gateway", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processor Hostname
|
||||||
|
/// </summary>
|
||||||
[JoinName("ProcessorHostname")]
|
[JoinName("ProcessorHostname")]
|
||||||
public JoinDataComplete ProcessorHostname = new JoinDataComplete(new JoinData { JoinNumber = 53, JoinSpan = 1, AttributeName = "Info - Processor - Hostname" },
|
public JoinDataComplete ProcessorHostname = new JoinDataComplete(new JoinData { JoinNumber = 53, JoinSpan = 1, AttributeName = "Info - Processor - Hostname" },
|
||||||
new JoinMetadata { Description = "Info - Processor - Hostname", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
new JoinMetadata { Description = "Info - Processor - Hostname", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processor Domain
|
||||||
|
/// </summary>
|
||||||
[JoinName("ProcessorDomain")]
|
[JoinName("ProcessorDomain")]
|
||||||
public JoinDataComplete ProcessorDomain = new JoinDataComplete(new JoinData { JoinNumber = 54, JoinSpan = 1, AttributeName = "Info - Processor - Domain" },
|
public JoinDataComplete ProcessorDomain = new JoinDataComplete(new JoinData { JoinNumber = 54, JoinSpan = 1, AttributeName = "Info - Processor - Domain" },
|
||||||
new JoinMetadata { Description = "Info - Processor - Domain", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
new JoinMetadata { Description = "Info - Processor - Domain", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processor DNS 1
|
||||||
|
/// </summary>
|
||||||
[JoinName("ProcessorDns1")]
|
[JoinName("ProcessorDns1")]
|
||||||
public JoinDataComplete ProcessorDns1 = new JoinDataComplete(new JoinData { JoinNumber = 55, JoinSpan = 1, AttributeName = "Info - Processor - DNS 1" },
|
public JoinDataComplete ProcessorDns1 = new JoinDataComplete(new JoinData { JoinNumber = 55, JoinSpan = 1, AttributeName = "Info - Processor - DNS 1" },
|
||||||
new JoinMetadata { Description = "Info - Processor - DNS 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
new JoinMetadata { Description = "Info - Processor - DNS 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processor DNS 2
|
||||||
|
/// </summary>
|
||||||
[JoinName("ProcessorDns2")]
|
[JoinName("ProcessorDns2")]
|
||||||
public JoinDataComplete ProcessorDns2 = new JoinDataComplete(new JoinData { JoinNumber = 56, JoinSpan = 1, AttributeName = "Info - Processor - DNS 2" },
|
public JoinDataComplete ProcessorDns2 = new JoinDataComplete(new JoinData { JoinNumber = 56, JoinSpan = 1, AttributeName = "Info - Processor - DNS 2" },
|
||||||
new JoinMetadata { Description = "Info - Processor - DNS 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
new JoinMetadata { Description = "Info - Processor - DNS 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processor MAC 1
|
||||||
|
/// </summary>
|
||||||
[JoinName("ProcessorMac1")]
|
[JoinName("ProcessorMac1")]
|
||||||
public JoinDataComplete ProcessorMac1 = new JoinDataComplete(new JoinData { JoinNumber = 57, JoinSpan = 1, AttributeName = "Info - Processor - MAC 1" },
|
public JoinDataComplete ProcessorMac1 = new JoinDataComplete(new JoinData { JoinNumber = 57, JoinSpan = 1, AttributeName = "Info - Processor - MAC 1" },
|
||||||
new JoinMetadata { Description = "Info - Processor - MAC 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
new JoinMetadata { Description = "Info - Processor - MAC 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processor MAC 2
|
||||||
|
/// </summary>
|
||||||
[JoinName("ProcessorMac2")]
|
[JoinName("ProcessorMac2")]
|
||||||
public JoinDataComplete ProcessorMac2 = new JoinDataComplete(new JoinData { JoinNumber = 58, JoinSpan = 1, AttributeName = "Info - Processor - MAC 2" },
|
public JoinDataComplete ProcessorMac2 = new JoinDataComplete(new JoinData { JoinNumber = 58, JoinSpan = 1, AttributeName = "Info - Processor - MAC 2" },
|
||||||
new JoinMetadata { Description = "Info - Processor - MAC 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
new JoinMetadata { Description = "Info - Processor - MAC 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processor Net Mask 1
|
||||||
|
/// </summary>
|
||||||
[JoinName("ProcessorNetMask1")]
|
[JoinName("ProcessorNetMask1")]
|
||||||
public JoinDataComplete ProcessorNetMask1 = new JoinDataComplete(new JoinData { JoinNumber = 59, JoinSpan = 1, AttributeName = "Info - Processor - Net Mask 1" },
|
public JoinDataComplete ProcessorNetMask1 = new JoinDataComplete(new JoinData { JoinNumber = 59, JoinSpan = 1, AttributeName = "Info - Processor - Net Mask 1" },
|
||||||
new JoinMetadata { Description = "Info - Processor - Net Mask 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
new JoinMetadata { Description = "Info - Processor - Net Mask 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processor Net Mask 2
|
||||||
|
/// </summary>
|
||||||
[JoinName("ProcessorNetMask2")]
|
[JoinName("ProcessorNetMask2")]
|
||||||
public JoinDataComplete ProcessorNetMask2 = new JoinDataComplete(new JoinData { JoinNumber = 60, JoinSpan = 1, AttributeName = "Info - Processor - Net Mask 2" },
|
public JoinDataComplete ProcessorNetMask2 = new JoinDataComplete(new JoinData { JoinNumber = 60, JoinSpan = 1, AttributeName = "Info - Processor - Net Mask 2" },
|
||||||
new JoinMetadata { Description = "Info - Processor - Net Mask 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
new JoinMetadata { Description = "Info - Processor - Net Mask 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processor Firmware
|
||||||
|
/// </summary>
|
||||||
[JoinName("ProcessorFirmware")]
|
[JoinName("ProcessorFirmware")]
|
||||||
public JoinDataComplete ProcessorFirmware = new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1, AttributeName = "Info - Processor - Firmware" },
|
public JoinDataComplete ProcessorFirmware = new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1, AttributeName = "Info - Processor - Firmware" },
|
||||||
new JoinMetadata { Description = "Info - Processor - Firmware", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
new JoinMetadata { Description = "Info - Processor - Firmware", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Program Name Start
|
||||||
|
/// </summary>
|
||||||
[JoinName("ProgramNameStart")]
|
[JoinName("ProgramNameStart")]
|
||||||
public JoinDataComplete ProgramNameStart = new JoinDataComplete(new JoinData { JoinNumber = 62, JoinSpan = 10, AttributeName = "Info - Processor - Program" },
|
public JoinDataComplete ProgramNameStart = new JoinDataComplete(new JoinData { JoinNumber = 62, JoinSpan = 10, AttributeName = "Info - Processor - Program" },
|
||||||
new JoinMetadata { Description = "Info - Processor - Program", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
new JoinMetadata { Description = "Info - Processor - Program", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processor Reboot
|
||||||
|
/// </summary>
|
||||||
[JoinName("ProcessorReboot")]
|
[JoinName("ProcessorReboot")]
|
||||||
public JoinDataComplete ProcessorReboot = new JoinDataComplete(new JoinData { JoinNumber = 74, JoinSpan = 1, AttributeName = "Processor - Reboot" },
|
public JoinDataComplete ProcessorReboot = new JoinDataComplete(new JoinData { JoinNumber = 74, JoinSpan = 1, AttributeName = "Processor - Reboot" },
|
||||||
new JoinMetadata { Description = "Processor - Reboot", JoinCapabilities = eJoinCapabilities.FromFusion, JoinType = eJoinType.Digital });
|
new JoinMetadata { Description = "Processor - Reboot", JoinCapabilities = eJoinCapabilities.FromFusion, JoinType = eJoinType.Digital });
|
||||||
|
|
||||||
// Volume Controls
|
// Volume Controls
|
||||||
|
/// <summary>
|
||||||
|
/// Volume Fader 1
|
||||||
|
/// </summary>
|
||||||
[JoinName("VolumeFader1")]
|
[JoinName("VolumeFader1")]
|
||||||
public JoinDataComplete VolumeFader1 = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1, AttributeName = "Volume - Fader01" },
|
public JoinDataComplete VolumeFader1 = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1, AttributeName = "Volume - Fader01" },
|
||||||
new JoinMetadata { Description = "Volume - Fader01", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Analog });
|
new JoinMetadata { Description = "Volume - Fader01", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Analog });
|
||||||
|
|
||||||
// Codec Info
|
// Codec Info
|
||||||
|
/// <summary>
|
||||||
|
/// VC Codec In Call
|
||||||
|
/// </summary>
|
||||||
[JoinName("VcCodecInCall")]
|
[JoinName("VcCodecInCall")]
|
||||||
public JoinDataComplete VcCodecInCall = new JoinDataComplete(new JoinData { JoinNumber = 69, JoinSpan = 1, AttributeName = "Conf - VC 1 In Call" },
|
public JoinDataComplete VcCodecInCall = new JoinDataComplete(new JoinData { JoinNumber = 69, JoinSpan = 1, AttributeName = "Conf - VC 1 In Call" },
|
||||||
new JoinMetadata { Description = "Conf - VC 1 In Call", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
|
new JoinMetadata { Description = "Conf - VC 1 In Call", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// VC Codec Online
|
||||||
|
/// </summary>
|
||||||
[JoinName("VcCodecOnline")]
|
[JoinName("VcCodecOnline")]
|
||||||
public JoinDataComplete VcCodecOnline = new JoinDataComplete(new JoinData { JoinNumber = 122, JoinSpan = 1, AttributeName = "Online - VC 1" },
|
public JoinDataComplete VcCodecOnline = new JoinDataComplete(new JoinData { JoinNumber = 122, JoinSpan = 1, AttributeName = "Online - VC 1" },
|
||||||
new JoinMetadata { Description = "Online - VC 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
|
new JoinMetadata { Description = "Online - VC 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// VC Codec IP Address
|
||||||
|
/// </summary>
|
||||||
[JoinName("VcCodecIpAddress")]
|
[JoinName("VcCodecIpAddress")]
|
||||||
public JoinDataComplete VcCodecIpAddress = new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1, AttributeName = "IP Address - VC" },
|
public JoinDataComplete VcCodecIpAddress = new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1, AttributeName = "IP Address - VC" },
|
||||||
new JoinMetadata { Description = "IP Address - VC", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
new JoinMetadata { Description = "IP Address - VC", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// VC Codec IP Port
|
||||||
|
/// </summary>
|
||||||
[JoinName("VcCodecIpPort")]
|
[JoinName("VcCodecIpPort")]
|
||||||
public JoinDataComplete VcCodecIpPort = new JoinDataComplete(new JoinData { JoinNumber = 150, JoinSpan = 1, AttributeName = "IP Port - VC" },
|
public JoinDataComplete VcCodecIpPort = new JoinDataComplete(new JoinData { JoinNumber = 150, JoinSpan = 1, AttributeName = "IP Port - VC" },
|
||||||
new JoinMetadata { Description = "IP Port - VC", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
new JoinMetadata { Description = "IP Port - VC", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
||||||
|
|
||||||
// Source Attributes
|
// Source Attributes
|
||||||
|
/// <summary>
|
||||||
|
/// Display 1 Current Source Name
|
||||||
|
/// </summary>
|
||||||
[JoinName("Display1CurrentSourceName")]
|
[JoinName("Display1CurrentSourceName")]
|
||||||
public JoinDataComplete Display1CurrentSourceName = new JoinDataComplete(new JoinData { JoinNumber = 84, JoinSpan = 1, AttributeName = "Display 1 - Current Source" },
|
public JoinDataComplete Display1CurrentSourceName = new JoinDataComplete(new JoinData { JoinNumber = 84, JoinSpan = 1, AttributeName = "Display 1 - Current Source" },
|
||||||
new JoinMetadata { Description = "Display 1 - Current Source", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
new JoinMetadata { Description = "Display 1 - Current Source", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
|
||||||
|
|
||||||
|
|
||||||
// Device Online Status
|
// Device Online Status
|
||||||
|
/// <summary>
|
||||||
|
/// Touchpanel Online Start
|
||||||
|
/// </summary>
|
||||||
[JoinName("TouchpanelOnlineStart")]
|
[JoinName("TouchpanelOnlineStart")]
|
||||||
public JoinDataComplete TouchpanelOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 150, JoinSpan = 10, AttributeName = "Online - Touch Panel" },
|
public JoinDataComplete TouchpanelOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 150, JoinSpan = 10, AttributeName = "Online - Touch Panel" },
|
||||||
new JoinMetadata { Description = "Online - Touch Panel", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
|
new JoinMetadata { Description = "Online - Touch Panel", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Xpanel Online Start
|
||||||
|
/// </summary>
|
||||||
[JoinName("XpanelOnlineStart")]
|
[JoinName("XpanelOnlineStart")]
|
||||||
public JoinDataComplete XpanelOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 160, JoinSpan = 5, AttributeName = "Online - XPanel" },
|
public JoinDataComplete XpanelOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 160, JoinSpan = 5, AttributeName = "Online - XPanel" },
|
||||||
new JoinMetadata { Description = "Online - XPanel", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
|
new JoinMetadata { Description = "Online - XPanel", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Display Online Start
|
||||||
|
/// </summary>
|
||||||
[JoinName("DisplayOnlineStart")]
|
[JoinName("DisplayOnlineStart")]
|
||||||
public JoinDataComplete DisplayOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 170, JoinSpan = 10, AttributeName = "Online - Display" },
|
public JoinDataComplete DisplayOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 170, JoinSpan = 10, AttributeName = "Online - Display" },
|
||||||
new JoinMetadata { Description = "Online - Display", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
|
new JoinMetadata { Description = "Online - Display", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Display 1 Laptop Source Start
|
||||||
|
/// </summary>
|
||||||
[JoinName("Display1LaptopSourceStart")]
|
[JoinName("Display1LaptopSourceStart")]
|
||||||
public JoinDataComplete Display1LaptopSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 166, JoinSpan = 5, AttributeName = "Display 1 - Source Laptop" },
|
public JoinDataComplete Display1LaptopSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 165, JoinSpan = 5, AttributeName = "Display 1 - Source Laptop" },
|
||||||
new JoinMetadata { Description = "Display 1 - Source Laptop", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital });
|
new JoinMetadata { Description = "Display 1 - Source Laptop", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Display 1 Disc Player Source Start
|
||||||
|
/// </summary>
|
||||||
[JoinName("Display1DiscPlayerSourceStart")]
|
[JoinName("Display1DiscPlayerSourceStart")]
|
||||||
public JoinDataComplete Display1DiscPlayerSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 181, JoinSpan = 5, AttributeName = "Display 1 - Source Disc Player" },
|
public JoinDataComplete Display1DiscPlayerSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 180, JoinSpan = 5, AttributeName = "Display 1 - Source Disc Player" },
|
||||||
new JoinMetadata { Description = "Display 1 - Source Disc Player", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital });
|
new JoinMetadata { Description = "Display 1 - Source Disc Player", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital });
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Display 1 Set Top Box Source Start
|
||||||
|
/// </summary>
|
||||||
[JoinName("Display1SetTopBoxSourceStart")]
|
[JoinName("Display1SetTopBoxSourceStart")]
|
||||||
public JoinDataComplete Display1SetTopBoxSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 188, JoinSpan = 5, AttributeName = "Display 1 - Source TV" },
|
public JoinDataComplete Display1SetTopBoxSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 185, JoinSpan = 5, AttributeName = "Display 1 - Source TV" },
|
||||||
new JoinMetadata { Description = "Display 1 - Source TV", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital });
|
new JoinMetadata { Description = "Display 1 - Source TV", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital });
|
||||||
|
|
||||||
// Display 1
|
// Display 1
|
||||||
|
/// <summary>
|
||||||
|
/// Display 1 Start
|
||||||
|
/// </summary>
|
||||||
[JoinName("Display1Start")]
|
[JoinName("Display1Start")]
|
||||||
public JoinDataComplete Display1Start = new JoinDataComplete(new JoinData { JoinNumber = 158, JoinSpan = 1 },
|
public JoinDataComplete Display1Start = new JoinDataComplete(new JoinData { JoinNumber = 190, JoinSpan = 1 },
|
||||||
new JoinMetadata { Description = "Display 1 Start", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital });
|
new JoinMetadata { Description = "Display 1 Start", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital });
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor to use when instantiating this Join Map without inheriting from it
|
/// Constructor to use when instantiating this Join Map without inheriting from it
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
|
||||||
using PepperDash.Essentials.Core.Config;
|
|
||||||
using PepperDash.Essentials.Core.Devices;
|
using PepperDash.Essentials.Core.Devices;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
|
||||||
@@ -25,17 +19,25 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Evaluates the room info and custom properties from Fusion and updates the system properties aa needed
|
/// Evaluates the room info and custom properties from Fusion and updates the system properties aa needed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="roomInfo"></param>
|
/// <param name="room">The room associated with this Fusion instance</param>
|
||||||
public void EvaluateRoomInfo(string roomKey, RoomInformation roomInfo)
|
/// <param name="roomInfo">The room information from Fusion</param>
|
||||||
|
/// <param name="useFusionRoomName"></param>
|
||||||
|
public void EvaluateRoomInfo(IEssentialsRoom room, RoomInformation roomInfo, bool useFusionRoomName)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var reconfigurableDevices = DeviceManager.AllDevices.Where(d => d is ReconfigurableDevice);
|
var reconfigurableDevices = DeviceManager.AllDevices.OfType<ReconfigurableDevice>();
|
||||||
|
|
||||||
foreach (var device in reconfigurableDevices)
|
foreach (var device in reconfigurableDevices)
|
||||||
{
|
{
|
||||||
// Get the current device config so new values can be overwritten over existing
|
// Get the current device config so new values can be overwritten over existing
|
||||||
var deviceConfig = (device as ReconfigurableDevice).Config;
|
var deviceConfig = device.Config;
|
||||||
|
|
||||||
|
if (device is IEssentialsRoom)
|
||||||
|
{
|
||||||
|
// Skipping room name as this will affect ALL room instances in the configuration and cause unintended consequences when multiple rooms are present and multiple Fusion instances are used
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (device is RoomOnToDefaultSourceWhenOccupied)
|
if (device is RoomOnToDefaultSourceWhenOccupied)
|
||||||
{
|
{
|
||||||
@@ -85,36 +87,49 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
|
|
||||||
deviceConfig.Properties = JToken.FromObject(devProps);
|
deviceConfig.Properties = JToken.FromObject(devProps);
|
||||||
}
|
}
|
||||||
else if (device is IEssentialsRoom)
|
|
||||||
{
|
|
||||||
// Set the room name
|
|
||||||
if (!string.IsNullOrEmpty(roomInfo.Name))
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Current Room Name: {0}. New Room Name: {1}", deviceConfig.Name, roomInfo.Name);
|
|
||||||
// Set the name in config
|
|
||||||
deviceConfig.Name = roomInfo.Name;
|
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Room Name Successfully Changed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the help message
|
|
||||||
var helpMessage = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("RoomHelpMessage"));
|
|
||||||
if (helpMessage != null)
|
|
||||||
{
|
|
||||||
//Debug.LogMessage(LogEventLevel.Debug, "Current Help Message: {0}. New Help Message: {1}", deviceConfig.Properties["help"]["message"].Value<string>(ToString()), helpMessage.CustomFieldValue);
|
|
||||||
deviceConfig.Properties["helpMessage"] = (string)helpMessage.CustomFieldValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the config on the device
|
// Set the config on the device
|
||||||
(device as ReconfigurableDevice).SetConfig(deviceConfig);
|
device.SetConfig(deviceConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(room is ReconfigurableDevice reconfigurable))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("FusionCustomPropertiesBridge: Room is not a ReconfigurableDevice. Cannot map custom properties.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var roomConfig = reconfigurable.Config;
|
||||||
|
|
||||||
|
var updateConfig = false;
|
||||||
|
|
||||||
|
// Set the room name
|
||||||
|
if (!string.IsNullOrEmpty(roomInfo.Name) && useFusionRoomName)
|
||||||
|
{
|
||||||
|
Debug.LogDebug("Current Room Name: {currentName}. New Room Name: {fusionName}", roomConfig.Name, roomInfo.Name);
|
||||||
|
// Set the name in config
|
||||||
|
roomConfig.Name = roomInfo.Name;
|
||||||
|
updateConfig = true;
|
||||||
|
|
||||||
|
Debug.LogDebug("Room Name Successfully Changed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the help message
|
||||||
|
var helpMessage = roomInfo.FusionCustomProperties.FirstOrDefault(p => p.ID.Equals("RoomHelpMessage"));
|
||||||
|
if (helpMessage != null)
|
||||||
|
{
|
||||||
|
roomConfig.Properties["helpMessage"] = helpMessage.CustomFieldValue;
|
||||||
|
updateConfig = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateConfig)
|
||||||
|
{
|
||||||
|
reconfigurable.SetConfig(roomConfig);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "FusionCustomPropetiesBridge: Error mapping properties: {0}", e);
|
Debug.LogError("FusionCustomPropetiesBridge: Exception mapping properties for {roomKey}: {message}", room.Key, e.Message);
|
||||||
|
Debug.LogDebug(e, "Stack Trace: ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Timers;
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
using Crestron.SimplSharp.CrestronIO;
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
using Crestron.SimplSharp.CrestronXml;
|
using Crestron.SimplSharp.CrestronXml;
|
||||||
@@ -8,39 +11,52 @@ using Crestron.SimplSharpPro;
|
|||||||
using Crestron.SimplSharpPro.Fusion;
|
using Crestron.SimplSharpPro.Fusion;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Core.Logging;
|
||||||
using PepperDash.Essentials.Core.Config;
|
using PepperDash.Essentials.Core.Config;
|
||||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core.Fusion
|
namespace PepperDash.Essentials.Core.Fusion
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a EssentialsHuddleSpaceFusionSystemControllerBase
|
/// Represents a EssentialsHuddleSpaceFusionSystemControllerBase
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class EssentialsHuddleSpaceFusionSystemControllerBase : Device, IOccupancyStatusProvider
|
public class IEssentialsRoomFusionController : EssentialsDevice, IOccupancyStatusProvider, IFusionHelpRequest, IHasFeedback
|
||||||
{
|
{
|
||||||
private readonly EssentialsHuddleSpaceRoomFusionRoomJoinMap JoinMap;
|
private IEssentialsRoomFusionControllerPropertiesConfig _config;
|
||||||
|
|
||||||
|
private EssentialsHuddleSpaceRoomFusionRoomJoinMap JoinMap;
|
||||||
|
|
||||||
private const string RemoteOccupancyXml = "<Occupancy><Type>Local</Type><State>{0}</State></Occupancy>";
|
private const string RemoteOccupancyXml = "<Occupancy><Type>Local</Type><State>{0}</State></Occupancy>";
|
||||||
private readonly bool _guidFileExists;
|
private bool _guidFileExists;
|
||||||
|
|
||||||
private readonly Dictionary<Device, BoolInputSig> _sourceToFeedbackSigs =
|
private readonly Dictionary<Device, BoolInputSig> _sourceToFeedbackSigs =
|
||||||
new Dictionary<Device, BoolInputSig>();
|
new Dictionary<Device, BoolInputSig>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the CurrentRoomSourceNameSig
|
||||||
|
/// </summary>
|
||||||
protected StringSigData CurrentRoomSourceNameSig;
|
protected StringSigData CurrentRoomSourceNameSig;
|
||||||
|
|
||||||
private readonly FusionCustomPropertiesBridge CustomPropertiesBridge = new FusionCustomPropertiesBridge();
|
private readonly FusionCustomPropertiesBridge CustomPropertiesBridge = new FusionCustomPropertiesBridge();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the FusionOccSensor
|
||||||
|
/// </summary>
|
||||||
protected FusionOccupancySensorAsset FusionOccSensor;
|
protected FusionOccupancySensorAsset FusionOccSensor;
|
||||||
private readonly FusionRemoteOccupancySensor FusionRemoteOccSensor;
|
private readonly FusionRemoteOccupancySensor FusionRemoteOccSensor;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the FusionRoom
|
||||||
|
/// </summary>
|
||||||
protected FusionRoom FusionRoom;
|
protected FusionRoom FusionRoom;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the FusionStaticAssets
|
||||||
|
/// </summary>
|
||||||
protected Dictionary<int, FusionAsset> FusionStaticAssets;
|
protected Dictionary<int, FusionAsset> FusionStaticAssets;
|
||||||
private readonly long PushNotificationTimeout = 5000;
|
private readonly long PushNotificationTimeout = 5000;
|
||||||
private readonly IEssentialsRoom Room;
|
private IEssentialsRoom Room;
|
||||||
private readonly long SchedulePollInterval = 300000;
|
private readonly long SchedulePollInterval = 300000;
|
||||||
|
|
||||||
private Event _currentMeeting;
|
private Event _currentMeeting;
|
||||||
@@ -48,8 +64,7 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
private CTimer _dailyTimeRequestTimer;
|
private CTimer _dailyTimeRequestTimer;
|
||||||
private StatusMonitorCollection _errorMessageRollUp;
|
private StatusMonitorCollection _errorMessageRollUp;
|
||||||
|
|
||||||
private FusionRoomGuids _guiDs;
|
private FusionRoomGuids _guids;
|
||||||
private uint _ipId;
|
|
||||||
|
|
||||||
private bool _isRegisteredForSchedulePushNotifications;
|
private bool _isRegisteredForSchedulePushNotifications;
|
||||||
private Event _nextMeeting;
|
private Event _nextMeeting;
|
||||||
@@ -60,14 +75,30 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
|
|
||||||
private string _roomOccupancyRemoteString;
|
private string _roomOccupancyRemoteString;
|
||||||
|
|
||||||
#region System Info Sigs
|
private bool _helpRequestSent;
|
||||||
|
|
||||||
//StringSigData SystemName;
|
private eFusionHelpResponse _helpRequestStatus;
|
||||||
//StringSigData Model;
|
|
||||||
//StringSigData SerialNumber;
|
|
||||||
//StringSigData Uptime;
|
|
||||||
|
|
||||||
#endregion
|
/// <inheritdoc />
|
||||||
|
public StringFeedback HelpRequestResponseFeedback { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public BoolFeedback HelpRequestSentFeedback { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public StringFeedback HelpRequestStatusFeedback { get; private set; }
|
||||||
|
|
||||||
|
private Timer _helpRequestTimeoutTimer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the DefaultHelpRequestTimeoutMs
|
||||||
|
/// </summary>
|
||||||
|
public int HelpRequestTimeoutMs => _config.HelpRequestTimeoutMs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether to use a timer for help requests
|
||||||
|
/// </summary>
|
||||||
|
public bool UseHelpRequestTimer => _config.UseTimeoutForHelpRequests;
|
||||||
|
|
||||||
#region Processor Info Sigs
|
#region Processor Info Sigs
|
||||||
|
|
||||||
@@ -93,71 +124,110 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public EssentialsHuddleSpaceFusionSystemControllerBase(IEssentialsRoom room, uint ipId, string joinMapKey)
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
|
public IEssentialsRoomFusionController(string key, string name, IEssentialsRoomFusionControllerPropertiesConfig config)
|
||||||
|
: base(key, name)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
|
||||||
|
AddPostActivationAction(() =>
|
||||||
|
{
|
||||||
|
var room = DeviceManager.GetDeviceForKey<IEssentialsRoom>(_config.RoomKey);
|
||||||
|
|
||||||
|
if (room == null)
|
||||||
|
{
|
||||||
|
this.LogError("Error Creating Fusion Room Controller. No room found with key '{0}'", _config.RoomKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.LogInformation("Creating Fusion Room Controller for room '{0}' at IPID: {1:X2}", room.Key, _config.IpIdInt);
|
||||||
|
|
||||||
|
ConstructorHelper(room, _config.IpIdInt, _config.JoinMapKey);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="room"></param>
|
||||||
|
/// <param name="ipId"></param>
|
||||||
|
/// <param name="joinMapKey"></param>
|
||||||
|
public IEssentialsRoomFusionController(IEssentialsRoom room, string ipId, string joinMapKey)
|
||||||
: base(room.Key + "-fusion")
|
: base(room.Key + "-fusion")
|
||||||
|
{
|
||||||
|
_config = new IEssentialsRoomFusionControllerPropertiesConfig()
|
||||||
|
{
|
||||||
|
IpId = ipId,
|
||||||
|
RoomKey = room.Key,
|
||||||
|
JoinMapKey = joinMapKey
|
||||||
|
};
|
||||||
|
|
||||||
|
ConstructorHelper(room, _config.IpIdInt, joinMapKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConstructorHelper(IEssentialsRoom room, uint ipId, string joinMapKey)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
this.LogDebug("ConstructorHelper called for Fusion Room Controller for room '{0}' with IPID {1:X2}", room.Key, ipId);
|
||||||
|
|
||||||
|
this.LogDebug("JoinMap Key: {0}", joinMapKey);
|
||||||
|
|
||||||
JoinMap = new EssentialsHuddleSpaceRoomFusionRoomJoinMap(1);
|
JoinMap = new EssentialsHuddleSpaceRoomFusionRoomJoinMap(1);
|
||||||
|
|
||||||
CrestronConsole.AddNewConsoleCommand((o) => JoinMap.PrintJoinMapInfo(), string.Format("ptjnmp-{0}", Key), "Prints Attribute Join Map", ConsoleAccessLevelEnum.AccessOperator);
|
this.LogDebug("JoinMap created");
|
||||||
|
|
||||||
|
CrestronConsole.AddNewConsoleCommand((o) =>
|
||||||
|
{
|
||||||
|
if (o is string deviceKey)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(deviceKey) || deviceKey == "?")
|
||||||
|
{
|
||||||
|
CrestronConsole.ConsoleCommandResponse("Please provide a device key for a Fusion Room instance");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (deviceKey != this.Key)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CrestronConsole.ConsoleCommandResponse("Invalid parameter. Please provide a device key for a Fusion Room instance");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JoinMap.PrintJoinMapInfo();
|
||||||
|
}, "printfusionjoinmap", "Prints Attribute Join Map", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(joinMapKey))
|
if (!string.IsNullOrEmpty(joinMapKey))
|
||||||
{
|
{
|
||||||
|
// this.LogDebug("Attempting to get custom join map for key: {0}", joinMapKey);
|
||||||
var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey);
|
var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey);
|
||||||
if (customJoins != null)
|
if (customJoins != null)
|
||||||
{
|
{
|
||||||
JoinMap.SetCustomJoinData(customJoins);
|
JoinMap.SetCustomJoinData(customJoins);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Room = room;
|
Room = room;
|
||||||
|
|
||||||
_ipId = ipId;
|
this.LogDebug("Room found: {0}", Room.Key);
|
||||||
|
|
||||||
FusionStaticAssets = new Dictionary<int, FusionAsset>();
|
FusionStaticAssets = new Dictionary<int, FusionAsset>();
|
||||||
|
|
||||||
_guiDs = new FusionRoomGuids();
|
this.LogDebug("FusionStaticAssets dictionary created");
|
||||||
|
|
||||||
var mac =
|
_guids = new FusionRoomGuids();
|
||||||
CrestronEthernetHelper.GetEthernetParameter(
|
|
||||||
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0);
|
|
||||||
|
|
||||||
var slot = Global.ControlSystem.ProgramNumber;
|
|
||||||
|
|
||||||
var guidFilePath = Global.FilePathPrefix +
|
|
||||||
string.Format(@"{0}-FusionGuids-{1:X2}.json", InitialParametersClass.ProgramIDTag, _ipId);
|
|
||||||
|
|
||||||
var oldGuidFilePath = Global.FilePathPrefix +
|
|
||||||
string.Format(@"{0}-FusionGuids.json", InitialParametersClass.ProgramIDTag);
|
|
||||||
|
|
||||||
if (File.Exists(oldGuidFilePath))
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Migrating from old Fusion GUID file to new Fusion GUID File");
|
|
||||||
|
|
||||||
File.Copy(oldGuidFilePath, guidFilePath);
|
|
||||||
|
|
||||||
File.Delete(oldGuidFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
_guidFileExists = File.Exists(guidFilePath);
|
|
||||||
|
|
||||||
// Check if file exists
|
|
||||||
if (!_guidFileExists)
|
|
||||||
{
|
|
||||||
// Does not exist. Create GUIDs
|
|
||||||
_guiDs = new FusionRoomGuids(Room.Name, ipId, _guiDs.GenerateNewRoomGuid(slot, mac),
|
|
||||||
FusionStaticAssets);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Exists. Read GUIDs
|
|
||||||
ReadGuidFile(guidFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
this.LogDebug("FusionRoomGuids created");
|
||||||
|
|
||||||
if (Room is IRoomOccupancy occupancyRoom)
|
if (Room is IRoomOccupancy occupancyRoom)
|
||||||
{
|
{
|
||||||
|
Debug.LogDebug(this, "Room '{0}' supports IRoomOccupancy", Room.Key);
|
||||||
if (occupancyRoom.RoomOccupancy != null)
|
if (occupancyRoom.RoomOccupancy != null)
|
||||||
{
|
{
|
||||||
if (occupancyRoom.OccupancyStatusProviderIsRemote)
|
if (occupancyRoom.OccupancyStatusProviderIsRemote)
|
||||||
@@ -171,8 +241,21 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.LogDebug("Occupancy setup complete");
|
||||||
|
|
||||||
|
HelpRequestResponseFeedback = new StringFeedback("HelpRequestResponse", () => FusionRoom.Help.OutputSig.StringValue);
|
||||||
|
|
||||||
|
HelpRequestSentFeedback = new BoolFeedback("HelpRequestSent", () => _helpRequestSent);
|
||||||
|
HelpRequestStatusFeedback = new StringFeedback("HelpRequestStatus", () => _helpRequestStatus.ToString());
|
||||||
|
|
||||||
|
Feedbacks.Add(HelpRequestResponseFeedback);
|
||||||
|
Feedbacks.Add(HelpRequestSentFeedback);
|
||||||
|
Feedbacks.Add(HelpRequestStatusFeedback);
|
||||||
|
if (RoomOccupancyRemoteStringFeedback != null)
|
||||||
|
Feedbacks.Add(RoomOccupancyRemoteStringFeedback);
|
||||||
|
if (RoomIsOccupiedFeedback != null)
|
||||||
|
Feedbacks.Add(RoomIsOccupiedFeedback);
|
||||||
|
|
||||||
AddPostActivationAction(() => PostActivate(guidFilePath));
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -180,9 +263,54 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PostActivate(string guidFilePath)
|
private string GetGuidFilePath(uint ipId)
|
||||||
{
|
{
|
||||||
CreateSymbolAndBasicSigs(_ipId);
|
var mac =
|
||||||
|
CrestronEthernetHelper.GetEthernetParameter(
|
||||||
|
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0);
|
||||||
|
|
||||||
|
var slot = Global.ControlSystem.ProgramNumber;
|
||||||
|
|
||||||
|
var guidFilePath = Global.FilePathPrefix +
|
||||||
|
string.Format(@"{0}-FusionGuids-{1:X2}.json", InitialParametersClass.ProgramIDTag, _config.IpIdInt);
|
||||||
|
|
||||||
|
var oldGuidFilePath = Global.FilePathPrefix +
|
||||||
|
string.Format(@"{0}-FusionGuids.json", InitialParametersClass.ProgramIDTag);
|
||||||
|
|
||||||
|
if (File.Exists(oldGuidFilePath))
|
||||||
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Information, this, "Migrating from old Fusion GUID file to new Fusion GUID File");
|
||||||
|
|
||||||
|
File.Copy(oldGuidFilePath, guidFilePath);
|
||||||
|
|
||||||
|
File.Delete(oldGuidFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
_guidFileExists = File.Exists(guidFilePath);
|
||||||
|
|
||||||
|
// Check if file exists
|
||||||
|
if (!_guidFileExists)
|
||||||
|
{
|
||||||
|
// Does not exist. Create GUIDs
|
||||||
|
_guids = new FusionRoomGuids(Room.Name, ipId, _guids.GenerateNewRoomGuid(slot, mac),
|
||||||
|
FusionStaticAssets);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Exists. Read GUIDs
|
||||||
|
ReadGuidFile(guidFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return guidFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
|
||||||
|
GenerateGuidFile(GetGuidFilePath(_config.IpIdInt));
|
||||||
|
|
||||||
|
CreateSymbolAndBasicSigs(_config.IpIdInt);
|
||||||
SetUpSources();
|
SetUpSources();
|
||||||
SetUpCommunitcationMonitors();
|
SetUpCommunitcationMonitors();
|
||||||
SetUpDisplay();
|
SetUpDisplay();
|
||||||
@@ -191,12 +319,14 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
|
|
||||||
FusionRVI.GenerateFileForAllFusionDevices();
|
FusionRVI.GenerateFileForAllFusionDevices();
|
||||||
|
|
||||||
GenerateGuidFile(guidFilePath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the RoomGuid
|
||||||
|
/// </summary>
|
||||||
protected string RoomGuid
|
protected string RoomGuid
|
||||||
{
|
{
|
||||||
get { return _guiDs.RoomGuid; }
|
get { return _guids.RoomGuid; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -204,6 +334,9 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public StringFeedback RoomOccupancyRemoteStringFeedback { get; private set; }
|
public StringFeedback RoomOccupancyRemoteStringFeedback { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the RoomIsOccupiedFeedbackFunc
|
||||||
|
/// </summary>
|
||||||
protected Func<bool> RoomIsOccupiedFeedbackFunc
|
protected Func<bool> RoomIsOccupiedFeedbackFunc
|
||||||
{
|
{
|
||||||
get { return () => FusionRemoteOccSensor.RoomOccupied.OutputSig.BoolValue; }
|
get { return () => FusionRemoteOccSensor.RoomOccupied.OutputSig.BoolValue; }
|
||||||
@@ -218,10 +351,21 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public FeedbackCollection<Feedback> Feedbacks { get; private set; } = new FeedbackCollection<Feedback>();
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ScheduleChange event
|
||||||
|
/// </summary>
|
||||||
public event EventHandler<ScheduleChangeEventArgs> ScheduleChange;
|
public event EventHandler<ScheduleChangeEventArgs> ScheduleChange;
|
||||||
//public event EventHandler<MeetingChangeEventArgs> MeetingEndWarning;
|
//public event EventHandler<MeetingChangeEventArgs> MeetingEndWarning;
|
||||||
//public event EventHandler<MeetingChangeEventArgs> NextMeetingBeginWarning;
|
//public event EventHandler<MeetingChangeEventArgs> NextMeetingBeginWarning;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// RoomInfoChange event
|
||||||
|
/// </summary>
|
||||||
public event EventHandler<EventArgs> RoomInfoChange;
|
public event EventHandler<EventArgs> RoomInfoChange;
|
||||||
|
|
||||||
//ScheduleResponseEvent NextMeeting;
|
//ScheduleResponseEvent NextMeeting;
|
||||||
@@ -258,11 +402,11 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Writing GUIDs to file");
|
Debug.LogMessage(LogEventLevel.Debug, this, "Writing GUIDs to file");
|
||||||
|
|
||||||
_guiDs = FusionOccSensor == null
|
_guids = FusionOccSensor == null
|
||||||
? new FusionRoomGuids(Room.Name, _ipId, RoomGuid, FusionStaticAssets)
|
? new FusionRoomGuids(Room.Name, _config.IpIdInt, RoomGuid, FusionStaticAssets)
|
||||||
: new FusionRoomGuids(Room.Name, _ipId, RoomGuid, FusionStaticAssets, FusionOccSensor);
|
: new FusionRoomGuids(Room.Name, _config.IpIdInt, RoomGuid, FusionStaticAssets, FusionOccSensor);
|
||||||
|
|
||||||
var json = JsonConvert.SerializeObject(_guiDs, Newtonsoft.Json.Formatting.Indented);
|
var json = JsonConvert.SerializeObject(_guids, Newtonsoft.Json.Formatting.Indented);
|
||||||
|
|
||||||
using (var sw = new StreamWriter(filePath))
|
using (var sw = new StreamWriter(filePath))
|
||||||
{
|
{
|
||||||
@@ -312,17 +456,17 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
{
|
{
|
||||||
var json = File.ReadToEnd(filePath, Encoding.ASCII);
|
var json = File.ReadToEnd(filePath, Encoding.ASCII);
|
||||||
|
|
||||||
_guiDs = JsonConvert.DeserializeObject<FusionRoomGuids>(json);
|
_guids = JsonConvert.DeserializeObject<FusionRoomGuids>(json);
|
||||||
|
|
||||||
_ipId = _guiDs.IpId;
|
// _config.IpId = _guids.IpId;
|
||||||
|
|
||||||
FusionStaticAssets = _guiDs.StaticAssets;
|
FusionStaticAssets = _guids.StaticAssets;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Fusion Guids successfully read from file: {0}",
|
Debug.LogMessage(LogEventLevel.Information, this, "Fusion Guids successfully read from file: {0}",
|
||||||
filePath);
|
filePath);
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "\r\n********************\r\n\tRoom Name: {0}\r\n\tIPID: {1:X}\r\n\tRoomGuid: {2}\r\n*******************", Room.Name, _ipId, RoomGuid);
|
Debug.LogMessage(LogEventLevel.Debug, this, "\r\n********************\r\n\tRoom Name: {0}\r\n\tIPID: {1:X}\r\n\tRoomGuid: {2}\r\n*******************", Room.Name, _config.IpIdInt, RoomGuid);
|
||||||
|
|
||||||
foreach (var item in FusionStaticAssets)
|
foreach (var item in FusionStaticAssets)
|
||||||
{
|
{
|
||||||
@@ -343,6 +487,10 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// CreateSymbolAndBasicSigs method
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ipId"></param>
|
||||||
protected virtual void CreateSymbolAndBasicSigs(uint ipId)
|
protected virtual void CreateSymbolAndBasicSigs(uint ipId)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Creating Fusion Room symbol with GUID: {0} and IP-ID {1:X2}", RoomGuid, ipId);
|
Debug.LogMessage(LogEventLevel.Information, this, "Creating Fusion Room symbol with GUID: {0} and IP-ID {1:X2}", RoomGuid, ipId);
|
||||||
@@ -405,6 +553,10 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
|
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// CrestronEnvironment_EthernetEventHandler method
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ethernetEventArgs"></param>
|
||||||
protected void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs ethernetEventArgs)
|
protected void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs ethernetEventArgs)
|
||||||
{
|
{
|
||||||
if (ethernetEventArgs.EthernetEventType == eEthernetEventType.LinkUp)
|
if (ethernetEventArgs.EthernetEventType == eEthernetEventType.LinkUp)
|
||||||
@@ -413,6 +565,9 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GetSystemInfo method
|
||||||
|
/// </summary>
|
||||||
protected void GetSystemInfo()
|
protected void GetSystemInfo()
|
||||||
{
|
{
|
||||||
//SystemName.InputSig.StringValue = Room.Name;
|
//SystemName.InputSig.StringValue = Room.Name;
|
||||||
@@ -426,6 +581,9 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
() => CrestronConsole.SendControlSystemCommand("reboot", ref response));
|
() => CrestronConsole.SendControlSystemCommand("reboot", ref response));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SetUpEthernetValues method
|
||||||
|
/// </summary>
|
||||||
protected void SetUpEthernetValues()
|
protected void SetUpEthernetValues()
|
||||||
{
|
{
|
||||||
_ip1 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorIp1.JoinNumber, JoinMap.ProcessorIp1.AttributeName, eSigIoMask.InputSigOnly);
|
_ip1 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorIp1.JoinNumber, JoinMap.ProcessorIp1.AttributeName, eSigIoMask.InputSigOnly);
|
||||||
@@ -441,6 +599,9 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
_netMask2 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorNetMask2.JoinNumber, JoinMap.ProcessorNetMask2.AttributeName, eSigIoMask.InputSigOnly);
|
_netMask2 = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorNetMask2.JoinNumber, JoinMap.ProcessorNetMask2.AttributeName, eSigIoMask.InputSigOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GetProcessorEthernetValues method
|
||||||
|
/// </summary>
|
||||||
protected void GetProcessorEthernetValues()
|
protected void GetProcessorEthernetValues()
|
||||||
{
|
{
|
||||||
_ip1.InputSig.StringValue =
|
_ip1.InputSig.StringValue =
|
||||||
@@ -475,7 +636,7 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
// Interface 1
|
// Interface 1
|
||||||
|
|
||||||
if (InitialParametersClass.NumberOfEthernetInterfaces > 1)
|
if (InitialParametersClass.NumberOfEthernetInterfaces > 1)
|
||||||
// Only get these values if the processor has more than 1 NIC
|
// Only get these values if the processor has more than 1 NIC
|
||||||
{
|
{
|
||||||
_ip2.InputSig.StringValue =
|
_ip2.InputSig.StringValue =
|
||||||
CrestronEthernetHelper.GetEthernetParameter(
|
CrestronEthernetHelper.GetEthernetParameter(
|
||||||
@@ -489,6 +650,9 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GetProcessorInfo method
|
||||||
|
/// </summary>
|
||||||
protected void GetProcessorInfo()
|
protected void GetProcessorInfo()
|
||||||
{
|
{
|
||||||
_firmware = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorFirmware.JoinNumber, JoinMap.ProcessorFirmware.AttributeName, eSigIoMask.InputSigOnly);
|
_firmware = FusionRoom.CreateOffsetStringSig(JoinMap.ProcessorFirmware.JoinNumber, JoinMap.ProcessorFirmware.AttributeName, eSigIoMask.InputSigOnly);
|
||||||
@@ -499,7 +663,7 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
{
|
{
|
||||||
var join = JoinMap.ProgramNameStart.JoinNumber + i;
|
var join = JoinMap.ProgramNameStart.JoinNumber + i;
|
||||||
var progNum = i + 1;
|
var progNum = i + 1;
|
||||||
_program[i] = FusionRoom.CreateOffsetStringSig((uint) join,
|
_program[i] = FusionRoom.CreateOffsetStringSig((uint)join,
|
||||||
string.Format("{0} {1}", JoinMap.ProgramNameStart.AttributeName, progNum), eSigIoMask.InputSigOnly);
|
string.Format("{0} {1}", JoinMap.ProgramNameStart.AttributeName, progNum), eSigIoMask.InputSigOnly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -507,6 +671,9 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
_firmware.InputSig.StringValue = InitialParametersClass.FirmwareVersion;
|
_firmware.InputSig.StringValue = InitialParametersClass.FirmwareVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GetCustomProperties method
|
||||||
|
/// </summary>
|
||||||
protected void GetCustomProperties()
|
protected void GetCustomProperties()
|
||||||
{
|
{
|
||||||
if (FusionRoom.IsOnline)
|
if (FusionRoom.IsOnline)
|
||||||
@@ -524,11 +691,16 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
// TODO: Get IP and Project Name from TP
|
// TODO: Get IP and Project Name from TP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// FusionRoom_OnlineStatusChange method
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="currentDevice"></param>
|
||||||
|
/// <param name="args"></param>
|
||||||
protected void FusionRoom_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
|
protected void FusionRoom_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
|
||||||
{
|
{
|
||||||
if (args.DeviceOnLine)
|
if (args.DeviceOnLine)
|
||||||
{
|
{
|
||||||
CrestronInvoke.BeginInvoke( (o) =>
|
CrestronInvoke.BeginInvoke((o) =>
|
||||||
{
|
{
|
||||||
CrestronEnvironment.Sleep(200);
|
CrestronEnvironment.Sleep(200);
|
||||||
|
|
||||||
@@ -676,7 +848,7 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
var extendTime = _currentMeeting.dtEnd - DateTime.Now;
|
var extendTime = _currentMeeting.dtEnd - DateTime.Now;
|
||||||
var extendMinutesRaw = extendTime.TotalMinutes;
|
var extendMinutesRaw = extendTime.TotalMinutes;
|
||||||
|
|
||||||
extendMinutes += (int) Math.Round(extendMinutesRaw);
|
extendMinutes += (int)Math.Round(extendMinutesRaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -784,11 +956,11 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
var parameters = actionResponse["Parameters"];
|
var parameters = actionResponse["Parameters"];
|
||||||
|
|
||||||
foreach (var isRegistered in from XmlElement parameter in parameters
|
foreach (var isRegistered in from XmlElement parameter in parameters
|
||||||
where parameter.HasAttributes
|
where parameter.HasAttributes
|
||||||
select parameter.Attributes
|
select parameter.Attributes
|
||||||
into attributes
|
into attributes
|
||||||
where attributes["ID"].Value == "Registered"
|
where attributes["ID"].Value == "Registered"
|
||||||
select Int32.Parse(attributes["Value"].Value))
|
select Int32.Parse(attributes["Value"].Value))
|
||||||
{
|
{
|
||||||
switch (isRegistered)
|
switch (isRegistered)
|
||||||
{
|
{
|
||||||
@@ -845,9 +1017,9 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
Debug.LogMessage(LogEventLevel.Debug, this, "DateTime from Fusion Server: {0}", currentTime);
|
Debug.LogMessage(LogEventLevel.Debug, this, "DateTime from Fusion Server: {0}", currentTime);
|
||||||
|
|
||||||
// Parse time and date from response and insert values
|
// Parse time and date from response and insert values
|
||||||
CrestronEnvironment.SetTimeAndDate((ushort) currentTime.Hour, (ushort) currentTime.Minute,
|
CrestronEnvironment.SetTimeAndDate((ushort)currentTime.Hour, (ushort)currentTime.Minute,
|
||||||
(ushort) currentTime.Second, (ushort) currentTime.Month, (ushort) currentTime.Day,
|
(ushort)currentTime.Second, (ushort)currentTime.Month, (ushort)currentTime.Day,
|
||||||
(ushort) currentTime.Year);
|
(ushort)currentTime.Year);
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Processor time set to {0}", CrestronEnvironment.GetLocalTime());
|
Debug.LogMessage(LogEventLevel.Debug, this, "Processor time set to {0}", CrestronEnvironment.GetLocalTime());
|
||||||
}
|
}
|
||||||
@@ -919,7 +1091,7 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
}
|
}
|
||||||
RoomInfoChange?.Invoke(this, new EventArgs());
|
RoomInfoChange?.Invoke(this, new EventArgs());
|
||||||
|
|
||||||
CustomPropertiesBridge.EvaluateRoomInfo(Room.Key, roomInformation);
|
CustomPropertiesBridge.EvaluateRoomInfo(Room, roomInformation, _config.UseFusionRoomName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -1065,6 +1237,9 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SetUpSources method
|
||||||
|
/// </summary>
|
||||||
protected virtual void SetUpSources()
|
protected virtual void SetUpSources()
|
||||||
{
|
{
|
||||||
// Sources
|
// Sources
|
||||||
@@ -1074,10 +1249,10 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
// NEW PROCESS:
|
// NEW PROCESS:
|
||||||
// Make these lists and insert the fusion attributes by iterating these
|
// Make these lists and insert the fusion attributes by iterating these
|
||||||
var setTopBoxes = dict.Where(d => d.Value.SourceDevice is ISetTopBoxControls);
|
var setTopBoxes = dict.Where(d => d.Value.SourceDevice is ISetTopBoxControls);
|
||||||
uint i = 1;
|
uint i = 0;
|
||||||
foreach (var kvp in setTopBoxes)
|
foreach (var kvp in setTopBoxes)
|
||||||
{
|
{
|
||||||
TryAddRouteActionSigs(JoinMap.Display1SetTopBoxSourceStart.AttributeName + " " + i, JoinMap.Display1SetTopBoxSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice);
|
TryAddRouteActionSigs(JoinMap.Display1SetTopBoxSourceStart.AttributeName + " " + (i + 1), JoinMap.Display1SetTopBoxSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice);
|
||||||
i++;
|
i++;
|
||||||
if (i > JoinMap.Display1SetTopBoxSourceStart.JoinSpan) // We only have five spots
|
if (i > JoinMap.Display1SetTopBoxSourceStart.JoinSpan) // We only have five spots
|
||||||
{
|
{
|
||||||
@@ -1086,10 +1261,10 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
}
|
}
|
||||||
|
|
||||||
var discPlayers = dict.Where(d => d.Value.SourceDevice is IDiscPlayerControls);
|
var discPlayers = dict.Where(d => d.Value.SourceDevice is IDiscPlayerControls);
|
||||||
i = 1;
|
i = 0;
|
||||||
foreach (var kvp in discPlayers)
|
foreach (var kvp in discPlayers)
|
||||||
{
|
{
|
||||||
TryAddRouteActionSigs(JoinMap.Display1DiscPlayerSourceStart.AttributeName + " " + i, JoinMap.Display1DiscPlayerSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice);
|
TryAddRouteActionSigs(JoinMap.Display1DiscPlayerSourceStart.AttributeName + " " + (i + 1), JoinMap.Display1DiscPlayerSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice);
|
||||||
i++;
|
i++;
|
||||||
if (i > JoinMap.Display1DiscPlayerSourceStart.JoinSpan) // We only have five spots
|
if (i > JoinMap.Display1DiscPlayerSourceStart.JoinSpan) // We only have five spots
|
||||||
{
|
{
|
||||||
@@ -1098,10 +1273,10 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
}
|
}
|
||||||
|
|
||||||
var laptops = dict.Where(d => d.Value.SourceDevice is IRoutingSource);
|
var laptops = dict.Where(d => d.Value.SourceDevice is IRoutingSource);
|
||||||
i = 1;
|
i = 0;
|
||||||
foreach (var kvp in laptops)
|
foreach (var kvp in laptops)
|
||||||
{
|
{
|
||||||
TryAddRouteActionSigs(JoinMap.Display1LaptopSourceStart.AttributeName + " " + i, JoinMap.Display1LaptopSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice);
|
TryAddRouteActionSigs(JoinMap.Display1LaptopSourceStart.AttributeName + " " + (i + 1), JoinMap.Display1LaptopSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice);
|
||||||
i++;
|
i++;
|
||||||
if (i > JoinMap.Display1LaptopSourceStart.JoinSpan) // We only have ten spots???
|
if (i > JoinMap.Display1LaptopSourceStart.JoinSpan) // We only have ten spots???
|
||||||
{
|
{
|
||||||
@@ -1111,7 +1286,7 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
|
|
||||||
foreach (var usageDevice in dict.Select(kvp => kvp.Value.SourceDevice).OfType<IUsageTracking>())
|
foreach (var usageDevice in dict.Select(kvp => kvp.Value.SourceDevice).OfType<IUsageTracking>())
|
||||||
{
|
{
|
||||||
usageDevice.UsageTracker = new UsageTracking(usageDevice as Device) {UsageIsTracked = true};
|
usageDevice.UsageTracker = new UsageTracking(usageDevice as Device) { UsageIsTracked = true };
|
||||||
usageDevice.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
|
usageDevice.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1157,17 +1332,31 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Device usage string: {0}", deviceUsage);
|
Debug.LogMessage(LogEventLevel.Debug, this, "Device usage string: {0}", deviceUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to add route action sigs for a source
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="attrName"></param>
|
||||||
|
/// <param name="attrNum"></param>
|
||||||
|
/// <param name="routeKey"></param>
|
||||||
|
/// <param name="pSrc"></param>
|
||||||
protected void TryAddRouteActionSigs(string attrName, uint attrNum, string routeKey, Device pSrc)
|
protected void TryAddRouteActionSigs(string attrName, uint attrNum, string routeKey, Device pSrc)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "Creating attribute '{0}' with join {1} for source {2}",
|
this.LogVerbose("Creating attribute '{0}' with join {1} for source {2}",
|
||||||
attrName, attrNum, pSrc.Key);
|
attrName, attrNum, pSrc.Key);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var sigD = FusionRoom.CreateOffsetBoolSig(attrNum, attrName, eSigIoMask.InputOutputSig);
|
var sigD = FusionRoom.CreateOffsetBoolSig(attrNum, attrName, eSigIoMask.InputOutputSig);
|
||||||
// Need feedback when this source is selected
|
// Need feedback when this source is selected
|
||||||
// Event handler, added below, will compare source changes with this sig dict
|
// Event handler, added below, will compare source changes with this sig dict
|
||||||
_sourceToFeedbackSigs.Add(pSrc, sigD.InputSig);
|
if (!_sourceToFeedbackSigs.ContainsKey(pSrc))
|
||||||
|
{
|
||||||
|
_sourceToFeedbackSigs.Add(pSrc, sigD.InputSig);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.LogWarning("Source '{0}' already has a feedback sig mapped. Overwriting.", pSrc.Key);
|
||||||
|
_sourceToFeedbackSigs[pSrc] = sigD.InputSig;
|
||||||
|
}
|
||||||
|
|
||||||
// And respond to selection in Fusion
|
// And respond to selection in Fusion
|
||||||
sigD.OutputSig.SetSigFalseAction(() =>
|
sigD.OutputSig.SetSigFalseAction(() =>
|
||||||
@@ -1180,14 +1369,12 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "Error creating Fusion signal {0} {1} for device '{2}'. THIS NEEDS REWORKING",
|
this.LogVerbose("Error creating Fusion signal {0} {1} for device '{2}'. THIS NEEDS REWORKING",
|
||||||
attrNum, attrName, pSrc.Key);
|
attrNum, attrName, pSrc.Key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
private void SetUpCommunitcationMonitors()
|
private void SetUpCommunitcationMonitors()
|
||||||
{
|
{
|
||||||
uint displayNum = 0;
|
uint displayNum = 0;
|
||||||
@@ -1274,6 +1461,8 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
|
|
||||||
if (attrName != null)
|
if (attrName != null)
|
||||||
{
|
{
|
||||||
|
this.LogDebug("Linking communication monitor for device '{0}' to Fusion attribute '{1}' at join {2}",
|
||||||
|
dev.Key, attrName, attrNum);
|
||||||
// Link comm status to sig and update
|
// Link comm status to sig and update
|
||||||
var sigD = FusionRoom.CreateOffsetBoolSig(attrNum, attrName, eSigIoMask.InputSigOnly);
|
var sigD = FusionRoom.CreateOffsetBoolSig(attrNum, attrName, eSigIoMask.InputSigOnly);
|
||||||
var smd = dev as ICommunicationMonitor;
|
var smd = dev as ICommunicationMonitor;
|
||||||
@@ -1285,6 +1474,9 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SetUpDisplay method
|
||||||
|
/// </summary>
|
||||||
protected virtual void SetUpDisplay()
|
protected virtual void SetUpDisplay()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -1297,7 +1489,7 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
|
|
||||||
foreach (var display in displays.Cast<IDisplay>())
|
foreach (var display in displays.Cast<IDisplay>())
|
||||||
{
|
{
|
||||||
display.UsageTracker = new UsageTracking(display as Device) {UsageIsTracked = true};
|
display.UsageTracker = new UsageTracking(display as Device) { UsageIsTracked = true };
|
||||||
display.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
|
display.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1410,7 +1602,7 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
|
|
||||||
|
|
||||||
// Power on
|
// Power on
|
||||||
var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint) joinOffset, displayName + "Power On",
|
var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On",
|
||||||
eSigIoMask.InputOutputSig);
|
eSigIoMask.InputOutputSig);
|
||||||
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b =>
|
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b =>
|
||||||
{
|
{
|
||||||
@@ -1421,7 +1613,7 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Power Off
|
// Power Off
|
||||||
var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint) joinOffset + 1, displayName + "Power Off",
|
var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off",
|
||||||
eSigIoMask.InputOutputSig);
|
eSigIoMask.InputOutputSig);
|
||||||
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b =>
|
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b =>
|
||||||
{
|
{
|
||||||
@@ -1439,7 +1631,7 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Current Source
|
// Current Source
|
||||||
var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint) joinOffset + 8,
|
var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8,
|
||||||
displayName + "Source None", eSigIoMask.InputOutputSig);
|
displayName + "Source None", eSigIoMask.InputOutputSig);
|
||||||
defaultDisplaySourceNone.OutputSig.UserObject = new Action<bool>(b =>
|
defaultDisplaySourceNone.OutputSig.UserObject = new Action<bool>(b =>
|
||||||
{
|
{
|
||||||
@@ -1507,7 +1699,7 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
//if (Room.OccupancyObj != null)
|
//if (Room.OccupancyObj != null)
|
||||||
//{
|
//{
|
||||||
|
|
||||||
var tempOccAsset = _guiDs.OccupancyAsset;
|
var tempOccAsset = _guids.OccupancyAsset;
|
||||||
|
|
||||||
if (tempOccAsset == null)
|
if (tempOccAsset == null)
|
||||||
{
|
{
|
||||||
@@ -1532,7 +1724,7 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
occRoom.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
|
occRoom.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
|
||||||
}
|
}
|
||||||
RoomOccupancyRemoteStringFeedback = new StringFeedback(() => _roomOccupancyRemoteString);
|
RoomOccupancyRemoteStringFeedback = new StringFeedback(() => _roomOccupancyRemoteString);
|
||||||
|
|
||||||
RoomOccupancyRemoteStringFeedback.LinkInputSig(occSensorAsset.RoomOccupancyInfo.InputSig);
|
RoomOccupancyRemoteStringFeedback.LinkInputSig(occSensorAsset.RoomOccupancyInfo.InputSig);
|
||||||
|
|
||||||
//}
|
//}
|
||||||
@@ -1588,12 +1780,82 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event handler for Fusion state changes
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="device"></param>
|
||||||
|
/// <param name="args"></param>
|
||||||
protected void FusionRoom_FusionStateChange(FusionBase device, FusionStateEventArgs args)
|
protected void FusionRoom_FusionStateChange(FusionBase device, FusionStateEventArgs args)
|
||||||
{
|
{
|
||||||
|
if (args.EventId == FusionEventIds.HelpMessageReceivedEventId)
|
||||||
|
{
|
||||||
|
this.LogInformation("Help message received from Fusion for room '{0}'",
|
||||||
|
Room.Name);
|
||||||
|
|
||||||
|
this.LogDebug("Help message content: {0}", FusionRoom.Help.OutputSig.StringValue);
|
||||||
|
// Fire help request event
|
||||||
|
HelpRequestResponseFeedback.FireUpdate();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(FusionRoom.Help.OutputSig.StringValue))
|
||||||
|
{
|
||||||
|
switch (FusionRoom.Help.OutputSig.StringValue)
|
||||||
|
{
|
||||||
|
case "Please wait, a technician is on his / her way.":
|
||||||
|
// this.LogInformation("Please wait, a technician is on his / her way.",
|
||||||
|
// Room.Name);
|
||||||
|
|
||||||
|
_helpRequestStatus = eFusionHelpResponse.HelpOnTheWay;
|
||||||
|
break;
|
||||||
|
case "Please call the helpdesk.":
|
||||||
|
// this.LogInformation("Please call the helpdesk.");
|
||||||
|
_helpRequestStatus = eFusionHelpResponse.CallHelpDesk;
|
||||||
|
break;
|
||||||
|
case "Please wait, I will reschedule your meeting to a different room.":
|
||||||
|
// this.LogInformation("Please wait, I will reschedule your meeting to a different room.",
|
||||||
|
// Room.Name);
|
||||||
|
|
||||||
|
_helpRequestStatus = eFusionHelpResponse.ReschedulingMeeting;
|
||||||
|
break;
|
||||||
|
case "I will be taking control of your system. Please be patient while I adjust the settings.":
|
||||||
|
// this.LogInformation("I will be taking control of your system. Please be patient while I adjust the settings.",
|
||||||
|
// Room.Name);
|
||||||
|
|
||||||
|
_helpRequestStatus = eFusionHelpResponse.TakingControl;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// this.LogInformation("Unknown help request code received from Fusion for room '{0}'",
|
||||||
|
// Room.Name);
|
||||||
|
|
||||||
|
_helpRequestStatus = eFusionHelpResponse.None;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_helpRequestStatus = eFusionHelpResponse.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_helpRequestStatus == eFusionHelpResponse.None)
|
||||||
|
{
|
||||||
|
_helpRequestSent = false;
|
||||||
|
HelpRequestSentFeedback.FireUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
HelpRequestStatusFeedback.FireUpdate();
|
||||||
|
|
||||||
|
if (_helpRequestTimeoutTimer != null)
|
||||||
|
{
|
||||||
|
_helpRequestTimeoutTimer.Stop();
|
||||||
|
_helpRequestTimeoutTimer.Elapsed -= OnTimedEvent;
|
||||||
|
_helpRequestTimeoutTimer.Dispose();
|
||||||
|
_helpRequestTimeoutTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// The sig/UO method: Need separate handlers for fixed and user sigs, all flavors,
|
// The sig/UO method: Need separate handlers for fixed and user sigs, all flavors,
|
||||||
// even though they all contain sigs.
|
// even though they all contain sigs.
|
||||||
|
|
||||||
|
|
||||||
BoolOutputSig outSig;
|
BoolOutputSig outSig;
|
||||||
if (args.UserConfiguredSigDetail is BooleanSigDataFixedName sigData)
|
if (args.UserConfiguredSigDetail is BooleanSigDataFixedName sigData)
|
||||||
{
|
{
|
||||||
@@ -1632,9 +1894,102 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
(outSig.UserObject as Action<string>).Invoke(outSig.StringValue);
|
(outSig.UserObject as Action<string>).Invoke(outSig.StringValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void SendHelpRequest()
|
||||||
|
{
|
||||||
|
|
||||||
|
var now = DateTime.Now;
|
||||||
|
|
||||||
|
var breakString = _config.UseHtmlFormatForHelpRequests ? "<BR>" : "\r\n";
|
||||||
|
|
||||||
|
var date = now.ToString("MMMM dd, yyyy");
|
||||||
|
var time = now.ToString("hh:mm tt");
|
||||||
|
if (_config.Use24HourTimeFormat)
|
||||||
|
{
|
||||||
|
time = now.ToString("HH:mm");
|
||||||
|
}
|
||||||
|
|
||||||
|
var requestString = $"HR00: {breakString} Assistance has been requested from room {Room.Name}{breakString}on {date} at {time}";
|
||||||
|
|
||||||
|
FusionRoom.Help.InputSig.StringValue = requestString;
|
||||||
|
|
||||||
|
this.LogInformation("Help request sent to Fusion from room '{0}'", Room.Name);
|
||||||
|
this.LogDebug("Help request content: {0}", FusionRoom.Help.InputSig.StringValue);
|
||||||
|
|
||||||
|
_helpRequestSent = true;
|
||||||
|
HelpRequestSentFeedback.FireUpdate();
|
||||||
|
|
||||||
|
if (UseHelpRequestTimer)
|
||||||
|
{
|
||||||
|
if (_helpRequestTimeoutTimer == null)
|
||||||
|
{
|
||||||
|
_helpRequestTimeoutTimer = new Timer(HelpRequestTimeoutMs);
|
||||||
|
_helpRequestTimeoutTimer.AutoReset = false;
|
||||||
|
_helpRequestTimeoutTimer.Enabled = true;
|
||||||
|
|
||||||
|
_helpRequestTimeoutTimer.Elapsed += OnTimedEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
_helpRequestTimeoutTimer.Interval = HelpRequestTimeoutMs;
|
||||||
|
_helpRequestTimeoutTimer.Start();
|
||||||
|
|
||||||
|
this.LogDebug("Help request timeout timer started for room '{0}' with timeout of {1} ms.",
|
||||||
|
Room.Name, HelpRequestTimeoutMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
_helpRequestStatus = eFusionHelpResponse.HelpRequested;
|
||||||
|
HelpRequestStatusFeedback.FireUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTimedEvent(object source, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
this.LogInformation("Help request timeout reached for room '{0}'. Cancelling help request.", Room.Name);
|
||||||
|
CancelHelpRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void CancelHelpRequest()
|
||||||
|
{
|
||||||
|
if (_helpRequestSent)
|
||||||
|
{
|
||||||
|
FusionRoom.Help.InputSig.StringValue = "";
|
||||||
|
_helpRequestSent = false;
|
||||||
|
HelpRequestSentFeedback.FireUpdate();
|
||||||
|
_helpRequestStatus = eFusionHelpResponse.None;
|
||||||
|
HelpRequestStatusFeedback.FireUpdate();
|
||||||
|
Debug.LogMessage(LogEventLevel.Information, this, "Help request cancelled for room '{0}'", Room.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_helpRequestTimeoutTimer != null)
|
||||||
|
{
|
||||||
|
_helpRequestTimeoutTimer.Stop();
|
||||||
|
_helpRequestTimeoutTimer.Elapsed -= OnTimedEvent;
|
||||||
|
_helpRequestTimeoutTimer.Dispose();
|
||||||
|
_helpRequestTimeoutTimer = null;
|
||||||
|
this.LogDebug("Help request timeout timer stopped for room '{0}'.", Room.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void ToggleHelpRequest()
|
||||||
|
{
|
||||||
|
if (_helpRequestSent)
|
||||||
|
{
|
||||||
|
CancelHelpRequest();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendHelpRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extensions to enhance Fusion room, asset and signal creation.
|
||||||
|
/// </summary>
|
||||||
public static class FusionRoomExtensions
|
public static class FusionRoomExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1648,6 +2003,8 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static BooleanSigData CreateOffsetBoolSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
|
public static BooleanSigData CreateOffsetBoolSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
|
||||||
{
|
{
|
||||||
|
Debug.LogDebug("Creating Offset Bool Sig: {0} at Join {1}", name, number);
|
||||||
|
|
||||||
if (number < 50)
|
if (number < 50)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
|
throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
|
||||||
@@ -1668,6 +2025,8 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static UShortSigData CreateOffsetUshortSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
|
public static UShortSigData CreateOffsetUshortSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
|
||||||
{
|
{
|
||||||
|
Debug.LogDebug("Creating Offset UShort Sig: {0} at Join {1}", name, number);
|
||||||
|
|
||||||
if (number < 50)
|
if (number < 50)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
|
throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
|
||||||
@@ -1688,6 +2047,8 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static StringSigData CreateOffsetStringSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
|
public static StringSigData CreateOffsetStringSig(this FusionRoom fr, uint number, string name, eSigIoMask mask)
|
||||||
{
|
{
|
||||||
|
Debug.LogDebug("Creating Offset String Sig: {0} at Join {1}", name, number);
|
||||||
|
|
||||||
if (number < 50)
|
if (number < 50)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
|
throw new ArgumentOutOfRangeException("number", "Cannot be less than 50");
|
||||||
@@ -1803,6 +2164,9 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class RoomInformation
|
public class RoomInformation
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
public RoomInformation()
|
public RoomInformation()
|
||||||
{
|
{
|
||||||
FusionCustomProperties = new List<FusionCustomProperty>();
|
FusionCustomProperties = new List<FusionCustomProperty>();
|
||||||
@@ -1855,10 +2219,17 @@ namespace PepperDash.Essentials.Core.Fusion
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class FusionCustomProperty
|
public class FusionCustomProperty
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
public FusionCustomProperty()
|
public FusionCustomProperty()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor with id
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
public FusionCustomProperty(string id)
|
public FusionCustomProperty(string id)
|
||||||
{
|
{
|
||||||
ID = id;
|
ID = id;
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core;
|
||||||
|
using PepperDash.Essentials.Core.Fusion;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Factory for creating IEssentialsRoomFusionController devices
|
||||||
|
/// </summary>
|
||||||
|
public class IEssentialsRoomFusionControllerFactory : EssentialsDeviceFactory<IEssentialsRoomFusionController>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
|
public IEssentialsRoomFusionControllerFactory()
|
||||||
|
{
|
||||||
|
TypeNames = new List<string>() { "fusionRoom" };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Builds the device
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dc"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override EssentialsDevice BuildDevice(PepperDash.Essentials.Core.Config.DeviceConfig dc)
|
||||||
|
{
|
||||||
|
Debug.LogDebug("Factory Attempting to create new IEssentialsRoomFusionController Device");
|
||||||
|
|
||||||
|
|
||||||
|
var properties = dc.Properties.ToObject<IEssentialsRoomFusionControllerPropertiesConfig>();
|
||||||
|
|
||||||
|
return new IEssentialsRoomFusionController(dc.Key, dc.Name, properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using PepperDash.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Config properties for an IEssentialsRoomFusionController device
|
||||||
|
/// </summary>
|
||||||
|
public class IEssentialsRoomFusionControllerPropertiesConfig
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the IP ID of the Fusion Room Controller
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("ipId")]
|
||||||
|
public string IpId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the IP ID as a UInt16
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public uint IpIdInt
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// Try to parse the IpId string to UInt16 as hex
|
||||||
|
if (ushort.TryParse(IpId, System.Globalization.NumberStyles.HexNumber, null, out ushort result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Failed to parse IpId '{0}' as UInt16", IpId);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the join map key
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("joinMapKey")]
|
||||||
|
public string JoinMapKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the room key associated with this Fusion Room Controller
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("roomKey")]
|
||||||
|
public string RoomKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets whether to use the Fusion room name for this room
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Defaults to true to preserve current behavior. Set to false to skip updating the room name from Fusion</remarks>
|
||||||
|
[JsonProperty("useFusionRoomName")]
|
||||||
|
public bool UseFusionRoomName { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets whether to use HTML format for help requests
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("useHtmlFormatForHelpRequests")]
|
||||||
|
public bool UseHtmlFormatForHelpRequests { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets whether to use 24-hour time format
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("use24HourTimeFormat")]
|
||||||
|
public bool Use24HourTimeFormat { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets whether to use a timeout for help requests
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("useTimeoutForHelpRequests")]
|
||||||
|
public bool UseTimeoutForHelpRequests { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the timeout duration for help requests in milliseconds
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("helpRequestTimeoutMs")]
|
||||||
|
public int HelpRequestTimeoutMs { get; set; } = 30000;
|
||||||
|
}
|
||||||
44
src/PepperDash.Essentials.Core/Fusion/IFusionHelpRequest.cs
Normal file
44
src/PepperDash.Essentials.Core/Fusion/IFusionHelpRequest.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.Fusion
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents Fusion Help Request functionality
|
||||||
|
/// </summary>
|
||||||
|
public interface IFusionHelpRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Feedback containing the response to a help request
|
||||||
|
/// </summary>
|
||||||
|
StringFeedback HelpRequestResponseFeedback { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether a help request has been sent
|
||||||
|
/// </summary>
|
||||||
|
BoolFeedback HelpRequestSentFeedback { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Feedback containing the current status of the help request
|
||||||
|
/// </summary>
|
||||||
|
StringFeedback HelpRequestStatusFeedback { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a help request
|
||||||
|
/// </summary>
|
||||||
|
void SendHelpRequest();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears the current help request status
|
||||||
|
/// </summary>
|
||||||
|
void CancelHelpRequest();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Toggles between sending and cancelling a help request
|
||||||
|
/// </summary>
|
||||||
|
void ToggleHelpRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/PepperDash.Essentials.Core/Fusion/eFusionHelpResponse.cs
Normal file
37
src/PepperDash.Essentials.Core/Fusion/eFusionHelpResponse.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Core.Fusion
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Enumeration of possible Fusion Help Responses based on the standard responses from Fusion
|
||||||
|
/// </summary>
|
||||||
|
public enum eFusionHelpResponse
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// No help response
|
||||||
|
/// </summary>
|
||||||
|
None,
|
||||||
|
/// <summary>
|
||||||
|
/// Help has been requested
|
||||||
|
/// </summary>
|
||||||
|
HelpRequested,
|
||||||
|
/// <summary>
|
||||||
|
/// Help is on the way
|
||||||
|
/// </summary>
|
||||||
|
HelpOnTheWay,
|
||||||
|
/// <summary>
|
||||||
|
/// Please call the helpdesk.
|
||||||
|
/// </summary>
|
||||||
|
CallHelpDesk,
|
||||||
|
/// <summary>
|
||||||
|
/// Rescheduling meeting.
|
||||||
|
/// </summary>
|
||||||
|
ReschedulingMeeting,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Technician taking control.
|
||||||
|
/// </summary>
|
||||||
|
TakingControl,
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -49,7 +49,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public IRoomOccupancy Room { get; private set; }
|
public IRoomOccupancy Room { get; private set; }
|
||||||
|
|
||||||
private Fusion.EssentialsHuddleSpaceFusionSystemControllerBase FusionRoom;
|
private Fusion.IEssentialsRoomFusionController FusionRoom;
|
||||||
|
|
||||||
public RoomOnToDefaultSourceWhenOccupied(DeviceConfig config) :
|
public RoomOnToDefaultSourceWhenOccupied(DeviceConfig config) :
|
||||||
base (config)
|
base (config)
|
||||||
@@ -74,7 +74,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
var fusionRoomKey = PropertiesConfig.RoomKey + "-fusion";
|
var fusionRoomKey = PropertiesConfig.RoomKey + "-fusion";
|
||||||
|
|
||||||
FusionRoom = DeviceManager.GetDeviceForKey(fusionRoomKey) as Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase;
|
FusionRoom = DeviceManager.GetDeviceForKey(fusionRoomKey) as Core.Fusion.IEssentialsRoomFusionController;
|
||||||
|
|
||||||
if (FusionRoom == null)
|
if (FusionRoom == null)
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "Unable to get Fusion Room from Device Manager with key: {0}", fusionRoomKey);
|
Debug.LogMessage(LogEventLevel.Debug, this, "Unable to get Fusion Room from Device Manager with key: {0}", fusionRoomKey);
|
||||||
|
|||||||
@@ -103,6 +103,12 @@ namespace PepperDash.Essentials.Core
|
|||||||
[JsonProperty("name")]
|
[JsonProperty("name")]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether to hide this scenario in the UI.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("hideInUi", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public bool HideInUi { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the collection of partition states.
|
/// Gets or sets the collection of partition states.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -109,6 +109,12 @@ namespace PepperDash.Essentials.Core
|
|||||||
[JsonProperty("isActive")]
|
[JsonProperty("isActive")]
|
||||||
bool IsActive { get; }
|
bool IsActive { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether this scenario should be hidden in the UI.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("hideInUi")]
|
||||||
|
bool HideInUi { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Activates this room combination scenario
|
/// Activates this room combination scenario
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -14,18 +14,40 @@ namespace PepperDash.Essentials.Core
|
|||||||
{
|
{
|
||||||
private RoomCombinationScenarioConfig _config;
|
private RoomCombinationScenarioConfig _config;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the key associated with the object.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("key")]
|
[JsonProperty("key")]
|
||||||
public string Key { get; set; }
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name associated with the object.
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("name")]
|
[JsonProperty("name")]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
[JsonProperty("partitionStates")]
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether to hide this scenario in the UI.
|
||||||
|
/// </summary>
|
||||||
|
///
|
||||||
|
[JsonProperty("hideInUi")]
|
||||||
|
|
||||||
|
public bool HideInUi
|
||||||
|
{
|
||||||
|
get { return _config.HideInUi; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the PartitionStates
|
/// Gets or sets the PartitionStates
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
///
|
||||||
|
[JsonProperty("partitionStates")]
|
||||||
|
|
||||||
public List<PartitionState> PartitionStates { get; private set; }
|
public List<PartitionState> PartitionStates { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines which UI devices get mapped to which room in this scenario. The Key should be the key of the UI device and the Value should be the key of the room to map to
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("uiMap")]
|
[JsonProperty("uiMap")]
|
||||||
public Dictionary<string, string> UiMap { get; set; }
|
public Dictionary<string, string> UiMap { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ using Serilog.Events;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Room.Config
|
namespace PepperDash.Essentials.Room.Config
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a EssentialsRoomConfigHelper
|
/// Represents a EssentialsRoomConfigHelper
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class EssentialsRoomConfigHelper
|
public class EssentialsRoomConfigHelper
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// GetEmergency method
|
/// GetEmergency method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -31,100 +31,109 @@ namespace PepperDash.Essentials.Room.Config
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="props"></param>
|
/// <param name="props"></param>
|
||||||
/// <param name="room"></param>
|
/// <param name="room"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// GetMicrophonePrivacy method
|
/// GetMicrophonePrivacy method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static MicrophonePrivacyController GetMicrophonePrivacy(
|
public static MicrophonePrivacyController GetMicrophonePrivacy(
|
||||||
EssentialsRoomPropertiesConfig props, IPrivacy room)
|
EssentialsRoomPropertiesConfig props, IPrivacy room)
|
||||||
{
|
{
|
||||||
var microphonePrivacy = props.MicrophonePrivacy;
|
var microphonePrivacy = props.MicrophonePrivacy;
|
||||||
if (microphonePrivacy == null)
|
if (microphonePrivacy == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "Cannot create microphone privacy with null properties");
|
Debug.LogMessage(LogEventLevel.Information, "Cannot create microphone privacy with null properties");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Get the MicrophonePrivacy device from the device manager
|
// Get the MicrophonePrivacy device from the device manager
|
||||||
var mP = (DeviceManager.GetDeviceForKey(props.MicrophonePrivacy.DeviceKey) as MicrophonePrivacyController);
|
var mP = (DeviceManager.GetDeviceForKey(props.MicrophonePrivacy.DeviceKey) as MicrophonePrivacyController);
|
||||||
// Set this room as the IPrivacy device
|
// Set this room as the IPrivacy device
|
||||||
if (mP == null)
|
if (mP == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "ERROR: Selected device {0} is not MicrophonePrivacyController", props.MicrophonePrivacy.DeviceKey);
|
Debug.LogMessage(LogEventLevel.Information, "ERROR: Selected device {0} is not MicrophonePrivacyController", props.MicrophonePrivacy.DeviceKey);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
mP.SetPrivacyDevice(room);
|
mP.SetPrivacyDevice(room);
|
||||||
|
|
||||||
var behaviour = props.MicrophonePrivacy.Behaviour.ToLower();
|
var behaviour = props.MicrophonePrivacy.Behaviour.ToLower();
|
||||||
|
|
||||||
if (behaviour == null)
|
if (behaviour == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, "WARNING: No behaviour defined for MicrophonePrivacyController");
|
Debug.LogMessage(LogEventLevel.Information, "WARNING: No behaviour defined for MicrophonePrivacyController");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (behaviour == "trackroomstate")
|
if (behaviour == "trackroomstate")
|
||||||
{
|
{
|
||||||
// Tie LED enable to room power state
|
// Tie LED enable to room power state
|
||||||
var essRoom = room as IEssentialsRoom;
|
var essRoom = room as IEssentialsRoom;
|
||||||
essRoom.OnFeedback.OutputChange += (o, a) =>
|
essRoom.OnFeedback.OutputChange += (o, a) =>
|
||||||
{
|
{
|
||||||
if (essRoom.OnFeedback.BoolValue)
|
if (essRoom.OnFeedback.BoolValue)
|
||||||
mP.EnableLeds = true;
|
mP.EnableLeds = true;
|
||||||
else
|
else
|
||||||
mP.EnableLeds = false;
|
mP.EnableLeds = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
mP.EnableLeds = essRoom.OnFeedback.BoolValue;
|
mP.EnableLeds = essRoom.OnFeedback.BoolValue;
|
||||||
}
|
}
|
||||||
else if (behaviour == "trackcallstate")
|
else if (behaviour == "trackcallstate")
|
||||||
{
|
{
|
||||||
// Tie LED enable to room power state
|
// Tie LED enable to room power state
|
||||||
var inCallRoom = room as IHasInCallFeedback;
|
var inCallRoom = room as IHasInCallFeedback;
|
||||||
inCallRoom.InCallFeedback.OutputChange += (o, a) =>
|
inCallRoom.InCallFeedback.OutputChange += (o, a) =>
|
||||||
{
|
{
|
||||||
if (inCallRoom.InCallFeedback.BoolValue)
|
if (inCallRoom.InCallFeedback.BoolValue)
|
||||||
mP.EnableLeds = true;
|
mP.EnableLeds = true;
|
||||||
else
|
else
|
||||||
mP.EnableLeds = false;
|
mP.EnableLeds = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
mP.EnableLeds = inCallRoom.InCallFeedback.BoolValue;
|
mP.EnableLeds = inCallRoom.InCallFeedback.BoolValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mP;
|
return mP;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
}
|
||||||
/// Represents a EssentialsRoomPropertiesConfig
|
|
||||||
/// </summary>
|
|
||||||
public class EssentialsRoomPropertiesConfig
|
|
||||||
{
|
|
||||||
[JsonProperty("addresses")]
|
|
||||||
public EssentialsRoomAddressPropertiesConfig Addresses { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("description")]
|
/// <summary>
|
||||||
public string Description { get; set; }
|
/// Represents a EssentialsRoomPropertiesConfig
|
||||||
|
/// </summary>
|
||||||
|
public class EssentialsRoomPropertiesConfig
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the Addresses
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("addresses")]
|
||||||
|
public EssentialsRoomAddressPropertiesConfig Addresses { get; set; }
|
||||||
|
|
||||||
[JsonProperty("emergency")]
|
/// <summary>
|
||||||
public EssentialsRoomEmergencyConfig Emergency { get; set; }
|
/// Gets or sets the Description
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("description")]
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
[JsonProperty("help")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the Emergency
|
||||||
/// Gets or sets the Help
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("emergency")]
|
||||||
public EssentialsHelpPropertiesConfig Help { get; set; }
|
public EssentialsRoomEmergencyConfig Emergency { get; set; }
|
||||||
|
|
||||||
[JsonProperty("helpMessage")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the Help
|
||||||
/// Gets or sets the HelpMessage
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("help")]
|
||||||
public string HelpMessage { get; set; }
|
public EssentialsHelpPropertiesConfig Help { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the HelpMessage
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("helpMessage")]
|
||||||
|
public string HelpMessage { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Read this value to get the help message. It checks for the old and new config format.
|
/// Read this value to get the help message. It checks for the old and new config format.
|
||||||
@@ -133,120 +142,120 @@ namespace PepperDash.Essentials.Room.Config
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if(Help != null && !string.IsNullOrEmpty(Help.Message))
|
if (Help != null && !string.IsNullOrEmpty(Help.Message))
|
||||||
{
|
{
|
||||||
return Help.Message;
|
return Help.Message;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return HelpMessage;
|
return HelpMessage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonProperty("environment")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the Environment
|
||||||
/// Gets or sets the Environment
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("environment")]
|
||||||
public EssentialsEnvironmentPropertiesConfig Environment { get; set; }
|
public EssentialsEnvironmentPropertiesConfig Environment { get; set; }
|
||||||
|
|
||||||
[JsonProperty("logo")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the LogoLight
|
||||||
/// Gets or sets the LogoLight
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("logo")]
|
||||||
public EssentialsLogoPropertiesConfig LogoLight { get; set; }
|
public EssentialsLogoPropertiesConfig LogoLight { get; set; }
|
||||||
|
|
||||||
[JsonProperty("logoDark")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the LogoDark
|
/// Gets or sets the LogoDark
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("logoDark")]
|
||||||
public EssentialsLogoPropertiesConfig LogoDark { get; set; }
|
public EssentialsLogoPropertiesConfig LogoDark { get; set; }
|
||||||
|
|
||||||
[JsonProperty("microphonePrivacy")]
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the MicrophonePrivacy
|
|
||||||
/// </summary>
|
|
||||||
public EssentialsRoomMicrophonePrivacyConfig MicrophonePrivacy { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("occupancy")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the MicrophonePrivacy
|
||||||
/// Gets or sets the Occupancy
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("microphonePrivacy")]
|
||||||
public EssentialsRoomOccSensorConfig Occupancy { get; set; }
|
public EssentialsRoomMicrophonePrivacyConfig MicrophonePrivacy { get; set; }
|
||||||
|
|
||||||
[JsonProperty("oneButtonMeeting")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the Occupancy
|
||||||
/// Gets or sets the OneButtonMeeting
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("occupancy")]
|
||||||
public EssentialsOneButtonMeetingPropertiesConfig OneButtonMeeting { get; set; }
|
public EssentialsRoomOccSensorConfig Occupancy { get; set; }
|
||||||
|
|
||||||
[JsonProperty("shutdownVacancySeconds")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the OneButtonMeeting
|
||||||
/// Gets or sets the ShutdownVacancySeconds
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("oneButtonMeeting")]
|
||||||
public int ShutdownVacancySeconds { get; set; }
|
public EssentialsOneButtonMeetingPropertiesConfig OneButtonMeeting { get; set; }
|
||||||
|
|
||||||
[JsonProperty("shutdownPromptSeconds")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the ShutdownVacancySeconds
|
||||||
/// Gets or sets the ShutdownPromptSeconds
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("shutdownVacancySeconds")]
|
||||||
public int ShutdownPromptSeconds { get; set; }
|
public int ShutdownVacancySeconds { get; set; }
|
||||||
|
|
||||||
[JsonProperty("tech")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the ShutdownPromptSeconds
|
||||||
/// Gets or sets the Tech
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("shutdownPromptSeconds")]
|
||||||
public EssentialsRoomTechConfig Tech { get; set; }
|
public int ShutdownPromptSeconds { get; set; }
|
||||||
|
|
||||||
[JsonProperty("volumes")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the Tech
|
||||||
/// Gets or sets the Volumes
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("tech")]
|
||||||
public EssentialsRoomVolumesConfig Volumes { get; set; }
|
public EssentialsRoomTechConfig Tech { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the Volumes
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("volumes")]
|
||||||
|
public EssentialsRoomVolumesConfig Volumes { get; set; }
|
||||||
|
|
||||||
[JsonProperty("fusion")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Fusion
|
/// Gets or sets the Fusion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("fusion")]
|
||||||
public EssentialsRoomFusionConfig Fusion { get; set; }
|
public EssentialsRoomFusionConfig Fusion { get; set; }
|
||||||
|
|
||||||
[JsonProperty("essentialsRoomUiBehaviorConfig", NullValueHandling=NullValueHandling.Ignore)]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the UiBehavior
|
/// Gets or sets the UiBehavior
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("essentialsRoomUiBehaviorConfig", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public EssentialsRoomUiBehaviorConfig UiBehavior { get; set; }
|
public EssentialsRoomUiBehaviorConfig UiBehavior { get; set; }
|
||||||
|
|
||||||
[JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the ZeroVolumeWhenSwtichingVolumeDevices
|
||||||
/// Gets or sets the ZeroVolumeWhenSwtichingVolumeDevices
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")]
|
||||||
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; }
|
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates if this room represents a combination of other rooms
|
/// Indicates if this room represents a combination of other rooms
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("isRoomCombinationScenario")]
|
[JsonProperty("isRoomCombinationScenario")]
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the IsRoomCombinationScenario
|
|
||||||
/// </summary>
|
|
||||||
public bool IsRoomCombinationScenario { get; set; }
|
public bool IsRoomCombinationScenario { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
public EssentialsRoomPropertiesConfig()
|
public EssentialsRoomPropertiesConfig()
|
||||||
{
|
{
|
||||||
LogoLight = new EssentialsLogoPropertiesConfig();
|
LogoLight = new EssentialsLogoPropertiesConfig();
|
||||||
LogoDark = new EssentialsLogoPropertiesConfig();
|
LogoDark = new EssentialsLogoPropertiesConfig();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a EssentialsRoomUiBehaviorConfig
|
/// Represents a EssentialsRoomUiBehaviorConfig
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class EssentialsRoomUiBehaviorConfig
|
public class EssentialsRoomUiBehaviorConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("disableActivityButtonsWhileWarmingCooling")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the DisableActivityButtonsWhileWarmingCooling
|
/// Gets or sets the DisableActivityButtonsWhileWarmingCooling
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("disableActivityButtonsWhileWarmingCooling")]
|
||||||
public bool DisableActivityButtonsWhileWarmingCooling { get; set; }
|
public bool DisableActivityButtonsWhileWarmingCooling { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,111 +264,129 @@ namespace PepperDash.Essentials.Room.Config
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class EssentialsAvRoomPropertiesConfig : EssentialsRoomPropertiesConfig
|
public class EssentialsAvRoomPropertiesConfig : EssentialsRoomPropertiesConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("defaultAudioKey")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the DefaultAudioKey
|
/// Gets or sets the DefaultAudioKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("defaultAudioKey")]
|
||||||
public string DefaultAudioKey { get; set; }
|
public string DefaultAudioKey { get; set; }
|
||||||
[JsonProperty("sourceListKey")]
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the DefaultOnDspPresetKey
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("defaultOnDspPresetKey")]
|
||||||
|
public string DefaultOnDspPresetKey { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the DefaultOffDspPresetKey
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("defaultOffDspPresetKey")]
|
||||||
|
public string DefaultOffDspPresetKey { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the SourceListKey
|
/// Gets or sets the SourceListKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("sourceListKey")]
|
||||||
public string SourceListKey { get; set; }
|
public string SourceListKey { get; set; }
|
||||||
[JsonProperty("destinationListKey")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the DestinationListKey
|
/// Gets or sets the DestinationListKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("destinationListKey")]
|
||||||
public string DestinationListKey { get; set; }
|
public string DestinationListKey { get; set; }
|
||||||
[JsonProperty("audioControlPointListKey")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the AudioControlPointListKey
|
/// Gets or sets the AudioControlPointListKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("audioControlPointListKey")]
|
||||||
public string AudioControlPointListKey { get; set; }
|
public string AudioControlPointListKey { get; set; }
|
||||||
[JsonProperty("cameraListKey")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the CameraListKey
|
/// Gets or sets the CameraListKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("cameraListKey")]
|
||||||
public string CameraListKey { get; set; }
|
public string CameraListKey { get; set; }
|
||||||
|
|
||||||
|
|
||||||
[JsonProperty("defaultSourceItem")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the DefaultSourceItem
|
/// Gets or sets the DefaultSourceItem
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("defaultSourceItem")]
|
||||||
public string DefaultSourceItem { get; set; }
|
public string DefaultSourceItem { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates if the room supports advanced sharing
|
/// Indicates if the room supports advanced sharing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("supportsAdvancedSharing")]
|
[JsonProperty("supportsAdvancedSharing")]
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the SupportsAdvancedSharing
|
|
||||||
/// </summary>
|
|
||||||
public bool SupportsAdvancedSharing { get; set; }
|
public bool SupportsAdvancedSharing { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates if non-tech users can change the share mode
|
/// Indicates if non-tech users can change the share mode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("userCanChangeShareMode")]
|
[JsonProperty("userCanChangeShareMode")]
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the UserCanChangeShareMode
|
|
||||||
/// </summary>
|
|
||||||
public bool UserCanChangeShareMode { get; set; }
|
public bool UserCanChangeShareMode { get; set; }
|
||||||
|
|
||||||
|
|
||||||
[JsonProperty("matrixRoutingKey", NullValueHandling = NullValueHandling.Ignore)]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the MatrixRoutingKey
|
/// Gets or sets the MatrixRoutingKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("matrixRoutingKey", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string MatrixRoutingKey { get; set; }
|
public string MatrixRoutingKey { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a EssentialsConferenceRoomPropertiesConfig
|
||||||
|
/// </summary>
|
||||||
public class EssentialsConferenceRoomPropertiesConfig : EssentialsAvRoomPropertiesConfig
|
public class EssentialsConferenceRoomPropertiesConfig : EssentialsAvRoomPropertiesConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("videoCodecKey")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the VideoCodecKey
|
/// Gets or sets the VideoCodecKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("videoCodecKey")]
|
||||||
public string VideoCodecKey { get; set; }
|
public string VideoCodecKey { get; set; }
|
||||||
[JsonProperty("audioCodecKey")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the AudioCodecKey
|
/// Gets or sets the AudioCodecKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("audioCodecKey")]
|
||||||
public string AudioCodecKey { get; set; }
|
public string AudioCodecKey { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a EssentialsEnvironmentPropertiesConfig
|
/// Represents a EssentialsEnvironmentPropertiesConfig
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class EssentialsEnvironmentPropertiesConfig
|
public class EssentialsEnvironmentPropertiesConfig
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Enabled
|
/// Gets or sets the Enabled
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Enabled { get; set; }
|
public bool Enabled { get; set; }
|
||||||
|
|
||||||
[JsonProperty("deviceKeys")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the DeviceKeys
|
/// Gets or sets the DeviceKeys
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("deviceKeys")]
|
||||||
public List<string> DeviceKeys { get; set; }
|
public List<string> DeviceKeys { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
public EssentialsEnvironmentPropertiesConfig()
|
public EssentialsEnvironmentPropertiesConfig()
|
||||||
{
|
{
|
||||||
DeviceKeys = new List<string>();
|
DeviceKeys = new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a EssentialsRoomFusionConfig
|
/// Represents a EssentialsRoomFusionConfig
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class EssentialsRoomFusionConfig
|
public class EssentialsRoomFusionConfig
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the the IpId as a UInt16
|
||||||
|
/// </summary>
|
||||||
public uint IpIdInt
|
public uint IpIdInt
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return Convert.ToUInt32(IpId, 16);
|
return Convert.ToUInt32(IpId, 16);
|
||||||
}
|
}
|
||||||
@@ -367,20 +394,20 @@ namespace PepperDash.Essentials.Room.Config
|
|||||||
{
|
{
|
||||||
throw new FormatException(string.Format("ERROR:Unable to convert IP ID: {0} to hex. Error:\n{1}", IpId));
|
throw new FormatException(string.Format("ERROR:Unable to convert IP ID: {0} to hex. Error:\n{1}", IpId));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonProperty("ipId")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the IpId
|
/// Gets or sets the IpId
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("ipId")]
|
||||||
public string IpId { get; set; }
|
public string IpId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("joinMapKey")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the JoinMapKey
|
/// Gets or sets the JoinMapKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("joinMapKey")]
|
||||||
public string JoinMapKey { get; set; }
|
public string JoinMapKey { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -390,17 +417,17 @@ namespace PepperDash.Essentials.Room.Config
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class EssentialsRoomMicrophonePrivacyConfig
|
public class EssentialsRoomMicrophonePrivacyConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("deviceKey")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the DeviceKey
|
||||||
/// Gets or sets the DeviceKey
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("deviceKey")]
|
||||||
public string DeviceKey { get; set; }
|
public string DeviceKey { get; set; }
|
||||||
|
|
||||||
[JsonProperty("behaviour")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the Behaviour
|
||||||
/// Gets or sets the Behaviour
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("behaviour")]
|
||||||
public string Behaviour { get; set; }
|
public string Behaviour { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -408,24 +435,27 @@ namespace PepperDash.Essentials.Room.Config
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class EssentialsHelpPropertiesConfig
|
public class EssentialsHelpPropertiesConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("message")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the Message
|
||||||
/// Gets or sets the Message
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("message")]
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
|
|
||||||
[JsonProperty("showCallButton")]
|
/// <summary>
|
||||||
public bool ShowCallButton { get; set; }
|
/// Gets or sets the ShowCallButton
|
||||||
|
/// </summary>
|
||||||
/// <summary>
|
[JsonProperty("showCallButton")]
|
||||||
|
public bool ShowCallButton { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
/// Defaults to "Call Help Desk"
|
/// Defaults to "Call Help Desk"
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("callButtonText")]
|
[JsonProperty("callButtonText")]
|
||||||
/// <summary>
|
public string CallButtonText { get; set; }
|
||||||
/// Gets or sets the CallButtonText
|
|
||||||
/// </summary>
|
|
||||||
public string CallButtonText { get; set; }
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
public EssentialsHelpPropertiesConfig()
|
public EssentialsHelpPropertiesConfig()
|
||||||
{
|
{
|
||||||
CallButtonText = "Call Help Desk";
|
CallButtonText = "Call Help Desk";
|
||||||
@@ -437,23 +467,29 @@ namespace PepperDash.Essentials.Room.Config
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class EssentialsOneButtonMeetingPropertiesConfig
|
public class EssentialsOneButtonMeetingPropertiesConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("enable")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the Enable
|
||||||
/// Gets or sets the Enable
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("enable")]
|
||||||
public bool Enable { get; set; }
|
public bool Enable { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a EssentialsRoomAddressPropertiesConfig
|
||||||
|
/// </summary>
|
||||||
public class EssentialsRoomAddressPropertiesConfig
|
public class EssentialsRoomAddressPropertiesConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("phoneNumber")]
|
/// <summary>
|
||||||
public string PhoneNumber { get; set; }
|
/// Gets or sets the PhoneNumber
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("phoneNumber")]
|
||||||
|
public string PhoneNumber { get; set; }
|
||||||
|
|
||||||
[JsonProperty("sipAddress")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the SipAddress
|
||||||
/// Gets or sets the SipAddress
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("sipAddress")]
|
||||||
public string SipAddress { get; set; }
|
public string SipAddress { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -462,14 +498,18 @@ namespace PepperDash.Essentials.Room.Config
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class EssentialsLogoPropertiesConfig
|
public class EssentialsLogoPropertiesConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("type")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the Type
|
||||||
/// Gets or sets the Type
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("type")]
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the Url
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("url")]
|
||||||
|
public string Url { get; set; }
|
||||||
|
|
||||||
[JsonProperty("url")]
|
|
||||||
public string Url { get; set; }
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// GetLogoUrlLight method
|
/// GetLogoUrlLight method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -478,7 +518,7 @@ namespace PepperDash.Essentials.Room.Config
|
|||||||
if (Type == "url")
|
if (Type == "url")
|
||||||
return Url;
|
return Url;
|
||||||
if (Type == "system")
|
if (Type == "system")
|
||||||
return string.Format("http://{0}:8080/logo.png",
|
return string.Format("http://{0}:8080/logo.png",
|
||||||
CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0));
|
CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -502,22 +542,28 @@ namespace PepperDash.Essentials.Room.Config
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class EssentialsRoomOccSensorConfig
|
public class EssentialsRoomOccSensorConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("deviceKey")]
|
/// <summary>
|
||||||
/// <summary>
|
/// Gets or sets the DeviceKey
|
||||||
/// Gets or sets the DeviceKey
|
/// </summary>
|
||||||
/// </summary>
|
[JsonProperty("deviceKey")]
|
||||||
public string DeviceKey { get; set; }
|
public string DeviceKey { get; set; }
|
||||||
|
|
||||||
[JsonProperty("timeoutMinutes")]
|
/// <summary>
|
||||||
public int TimeoutMinutes { get; set; }
|
/// Gets or sets the TimeoutMinutes
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("timeoutMinutes")]
|
||||||
|
public int TimeoutMinutes { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class EssentialsRoomTechConfig
|
/// <summary>
|
||||||
{
|
/// Represents a EssentialsRoomTechConfig
|
||||||
[JsonProperty("password")]
|
/// </summary>
|
||||||
/// <summary>
|
public class EssentialsRoomTechConfig
|
||||||
/// Gets or sets the Password
|
{
|
||||||
/// </summary>
|
/// <summary>
|
||||||
public string Password { get; set; }
|
/// Gets or sets the Password
|
||||||
}
|
/// </summary>
|
||||||
|
[JsonProperty("password")]
|
||||||
|
public string Password { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -408,7 +408,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
Debug.LogMessage(LogEventLevel.Information, this, "Timeout Minutes from Config is: {0}", timeoutMinutes);
|
Debug.LogMessage(LogEventLevel.Information, this, "Timeout Minutes from Config is: {0}", timeoutMinutes);
|
||||||
|
|
||||||
// If status provider is fusion, set flag to remote
|
// If status provider is fusion, set flag to remote
|
||||||
if (statusProvider is Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase)
|
if (statusProvider is Core.Fusion.IEssentialsRoomFusionController)
|
||||||
OccupancyStatusProviderIsRemote = true;
|
OccupancyStatusProviderIsRemote = true;
|
||||||
|
|
||||||
if(timeoutMinutes > 0)
|
if(timeoutMinutes > 0)
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
using Crestron.SimplSharpPro.Keypads;
|
using System;
|
||||||
using PepperDash.Essentials.Core.Queues;
|
|
||||||
using PepperDash.Essentials.Core.Routing;
|
|
||||||
using Serilog.Events;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Crestron.SimplSharpPro.Keypads;
|
||||||
|
using PepperDash.Essentials.Core.Queues;
|
||||||
|
using PepperDash.Essentials.Core.Routing;
|
||||||
|
using Serilog.Events;
|
||||||
using Debug = PepperDash.Core.Debug;
|
using Debug = PepperDash.Core.Debug;
|
||||||
|
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
public static (RouteDescriptor, RouteDescriptor) GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort, RoutingOutputPort sourcePort)
|
public static (RouteDescriptor, RouteDescriptor) GetRouteToSource(this IRoutingInputs destination, IRoutingOutputs source, eRoutingSignalType signalType, RoutingInputPort destinationPort, RoutingOutputPort sourcePort)
|
||||||
{
|
{
|
||||||
// if it's a single signal type, find the route
|
// if it's a single signal type, find the route
|
||||||
if (!signalType.HasFlag(eRoutingSignalType.AudioVideo) &&
|
if (!signalType.HasFlag(eRoutingSignalType.AudioVideo) &&
|
||||||
!(signalType.HasFlag(eRoutingSignalType.Video) && signalType.HasFlag(eRoutingSignalType.SecondaryAudio)))
|
!(signalType.HasFlag(eRoutingSignalType.Video) && signalType.HasFlag(eRoutingSignalType.SecondaryAudio)))
|
||||||
{
|
{
|
||||||
var singleTypeRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, signalType);
|
var singleTypeRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, signalType);
|
||||||
@@ -134,14 +134,15 @@ namespace PepperDash.Essentials.Core
|
|||||||
}
|
}
|
||||||
// otherwise, audioVideo needs to be handled as two steps.
|
// otherwise, audioVideo needs to be handled as two steps.
|
||||||
|
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {sourceKey} of type {type}", destination, source.Key);
|
Debug.LogMessage(LogEventLevel.Debug, "Attempting to build source route from {destinationKey} to {sourceKey} of type {type}", destination, source.Key, signalType);
|
||||||
|
|
||||||
RouteDescriptor audioRouteDescriptor;
|
RouteDescriptor audioRouteDescriptor;
|
||||||
|
|
||||||
if (signalType.HasFlag(eRoutingSignalType.SecondaryAudio))
|
if (signalType.HasFlag(eRoutingSignalType.SecondaryAudio))
|
||||||
{
|
{
|
||||||
audioRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, eRoutingSignalType.SecondaryAudio);
|
audioRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, eRoutingSignalType.SecondaryAudio);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
audioRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, eRoutingSignalType.Audio);
|
audioRouteDescriptor = new RouteDescriptor(source, destination, destinationPort, eRoutingSignalType.Audio);
|
||||||
}
|
}
|
||||||
@@ -199,13 +200,13 @@ namespace PepperDash.Essentials.Core
|
|||||||
Source = source,
|
Source = source,
|
||||||
SourcePort = sourcePort,
|
SourcePort = sourcePort,
|
||||||
SignalType = signalType
|
SignalType = signalType
|
||||||
};
|
};
|
||||||
|
|
||||||
var coolingDevice = destination as IWarmingCooling;
|
var coolingDevice = destination as IWarmingCooling;
|
||||||
|
|
||||||
//We already have a route request for this device, and it's a cooling device and is cooling
|
//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)
|
if (RouteRequests.TryGetValue(destination.Key, out RouteRequest existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true)
|
||||||
{
|
{
|
||||||
coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown;
|
coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown;
|
||||||
|
|
||||||
coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown;
|
coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown;
|
||||||
@@ -219,7 +220,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
//New Request
|
//New Request
|
||||||
if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true)
|
if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true)
|
||||||
{
|
{
|
||||||
coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown;
|
coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown;
|
||||||
|
|
||||||
RouteRequests.Add(destination.Key, routeRequest);
|
RouteRequests.Add(destination.Key, routeRequest);
|
||||||
@@ -239,9 +240,9 @@ namespace PepperDash.Essentials.Core
|
|||||||
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);
|
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, false));
|
routeRequestQueue.Enqueue(new ReleaseRouteQueueItem(ReleaseRouteInternal, destination, destinationPort?.Key ?? string.Empty, false));
|
||||||
|
|
||||||
routeRequestQueue.Enqueue(new RouteRequestQueueItem(RunRouteRequest, routeRequest));
|
routeRequestQueue.Enqueue(new RouteRequestQueueItem(RunRouteRequest, routeRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -272,7 +273,8 @@ namespace PepperDash.Essentials.Core
|
|||||||
|
|
||||||
audioOrSingleRoute.ExecuteRoutes();
|
audioOrSingleRoute.ExecuteRoutes();
|
||||||
videoRoute?.ExecuteRoutes();
|
videoRoute?.ExecuteRoutes();
|
||||||
} catch(Exception ex)
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(ex, "Exception Running Route Request {request}", null, request);
|
Debug.LogMessage(ex, "Exception Running Route Request {request}", null, request);
|
||||||
}
|
}
|
||||||
@@ -305,9 +307,10 @@ namespace PepperDash.Essentials.Core
|
|||||||
Debug.LogMessage(LogEventLevel.Information, "Releasing current route: {0}", destination, current.Source.Key);
|
Debug.LogMessage(LogEventLevel.Information, "Releasing current route: {0}", destination, current.Source.Key);
|
||||||
current.ReleaseRoutes(clearRoute);
|
current.ReleaseRoutes(clearRoute);
|
||||||
}
|
}
|
||||||
} catch (Exception ex)
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(ex, "Exception releasing route for '{destination}':'{inputPortKey}'",null, destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
|
Debug.LogMessage(ex, "Exception releasing route for '{destination}':'{inputPortKey}'", null, destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using PepperDash.Core;
|
using System;
|
||||||
using PepperDash.Essentials.Core.Config;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core.Routing
|
namespace PepperDash.Essentials.Core.Routing
|
||||||
{
|
{
|
||||||
@@ -9,20 +9,20 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
/// Manages routing feedback by subscribing to route changes on midpoint and sink devices,
|
/// Manages routing feedback by subscribing to route changes on midpoint and sink devices,
|
||||||
/// tracing the route back to the original source, and updating the CurrentSourceInfo on sink devices.
|
/// tracing the route back to the original source, and updating the CurrentSourceInfo on sink devices.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class RoutingFeedbackManager:EssentialsDevice
|
public class RoutingFeedbackManager : EssentialsDevice
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="RoutingFeedbackManager"/> class.
|
/// Initializes a new instance of the <see cref="RoutingFeedbackManager"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">The unique key for this manager device.</param>
|
/// <param name="key">The unique key for this manager device.</param>
|
||||||
/// <param name="name">The name of this manager device.</param>
|
/// <param name="name">The name of this manager device.</param>
|
||||||
public RoutingFeedbackManager(string key, string name): base(key, name)
|
public RoutingFeedbackManager(string key, string name)
|
||||||
{
|
: base(key, name)
|
||||||
|
{
|
||||||
AddPreActivationAction(SubscribeForMidpointFeedback);
|
AddPreActivationAction(SubscribeForMidpointFeedback);
|
||||||
AddPreActivationAction(SubscribeForSinkFeedback);
|
AddPreActivationAction(SubscribeForSinkFeedback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Subscribes to the RouteChanged event on all devices implementing <see cref="IRoutingWithFeedback"/>.
|
/// Subscribes to the RouteChanged event on all devices implementing <see cref="IRoutingWithFeedback"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -41,12 +41,13 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void SubscribeForSinkFeedback()
|
private void SubscribeForSinkFeedback()
|
||||||
{
|
{
|
||||||
var sinkDevices = DeviceManager.AllDevices.OfType<IRoutingSinkWithSwitchingWithInputPort>();
|
var sinkDevices =
|
||||||
|
DeviceManager.AllDevices.OfType<IRoutingSinkWithSwitchingWithInputPort>();
|
||||||
|
|
||||||
foreach (var device in sinkDevices)
|
foreach (var device in sinkDevices)
|
||||||
{
|
{
|
||||||
device.InputChanged += HandleSinkUpdate;
|
device.InputChanged += HandleSinkUpdate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -55,11 +56,15 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="midpoint">The midpoint device that reported a route change.</param>
|
/// <param name="midpoint">The midpoint device that reported a route change.</param>
|
||||||
/// <param name="newRoute">The descriptor of the new route.</param>
|
/// <param name="newRoute">The descriptor of the new route.</param>
|
||||||
private void HandleMidpointUpdate(IRoutingWithFeedback midpoint, RouteSwitchDescriptor newRoute)
|
private void HandleMidpointUpdate(
|
||||||
|
IRoutingWithFeedback midpoint,
|
||||||
|
RouteSwitchDescriptor newRoute
|
||||||
|
)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var devices = DeviceManager.AllDevices.OfType<IRoutingSinkWithSwitchingWithInputPort>();
|
var devices =
|
||||||
|
DeviceManager.AllDevices.OfType<IRoutingSinkWithSwitchingWithInputPort>();
|
||||||
|
|
||||||
foreach (var device in devices)
|
foreach (var device in devices)
|
||||||
{
|
{
|
||||||
@@ -68,7 +73,13 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(ex, "Error handling midpoint update from {midpointKey}:{Exception}", this, midpoint.Key, ex);
|
Debug.LogMessage(
|
||||||
|
ex,
|
||||||
|
"Error handling midpoint update from {midpointKey}:{Exception}",
|
||||||
|
this,
|
||||||
|
midpoint.Key,
|
||||||
|
ex
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +89,10 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender">The sink device that reported an input change.</param>
|
/// <param name="sender">The sink device that reported an input change.</param>
|
||||||
/// <param name="currentInputPort">The new input port selected on the sink device.</param>
|
/// <param name="currentInputPort">The new input port selected on the sink device.</param>
|
||||||
private void HandleSinkUpdate(IRoutingSinkWithSwitching sender, RoutingInputPort currentInputPort)
|
private void HandleSinkUpdate(
|
||||||
|
IRoutingSinkWithSwitching sender,
|
||||||
|
RoutingInputPort currentInputPort
|
||||||
|
)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -86,7 +100,13 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(ex, "Error handling Sink update from {senderKey}:{Exception}", this, sender.Key, ex);
|
Debug.LogMessage(
|
||||||
|
ex,
|
||||||
|
"Error handling Sink update from {senderKey}:{Exception}",
|
||||||
|
this,
|
||||||
|
sender.Key,
|
||||||
|
ex
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,13 +116,27 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="destination">The destination sink device to update.</param>
|
/// <param name="destination">The destination sink device to update.</param>
|
||||||
/// <param name="inputPort">The currently selected input port on the destination device.</param>
|
/// <param name="inputPort">The currently selected input port on the destination device.</param>
|
||||||
private void UpdateDestination(IRoutingSinkWithSwitching destination, RoutingInputPort inputPort)
|
private void UpdateDestination(
|
||||||
{
|
IRoutingSinkWithSwitching destination,
|
||||||
// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Updating destination {destination} with inputPort {inputPort}", this,destination?.Key, inputPort?.Key);
|
RoutingInputPort inputPort
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Debug.LogMessage(
|
||||||
|
Serilog.Events.LogEventLevel.Debug,
|
||||||
|
"Updating destination {destination} with inputPort {inputPort}",
|
||||||
|
this,
|
||||||
|
destination?.Key,
|
||||||
|
inputPort?.Key
|
||||||
|
);
|
||||||
|
|
||||||
if(inputPort == null)
|
if (inputPort == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "Destination {destination} has not reported an input port yet", this,destination.Key);
|
Debug.LogMessage(
|
||||||
|
Serilog.Events.LogEventLevel.Debug,
|
||||||
|
"Destination {destination} has not reported an input port yet",
|
||||||
|
this,
|
||||||
|
destination.Key
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,11 +145,19 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
{
|
{
|
||||||
var tieLines = TieLineCollection.Default;
|
var tieLines = TieLineCollection.Default;
|
||||||
|
|
||||||
firstTieLine = tieLines.FirstOrDefault(tl => tl.DestinationPort.Key == inputPort.Key && tl.DestinationPort.ParentDevice.Key == inputPort.ParentDevice.Key);
|
firstTieLine = tieLines.FirstOrDefault(tl =>
|
||||||
|
tl.DestinationPort.Key == inputPort.Key
|
||||||
|
&& tl.DestinationPort.ParentDevice.Key == inputPort.ParentDevice.Key
|
||||||
|
);
|
||||||
|
|
||||||
if (firstTieLine == null)
|
if (firstTieLine == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No tieline found for inputPort {inputPort}. Clearing current source", this, inputPort);
|
Debug.LogMessage(
|
||||||
|
Serilog.Events.LogEventLevel.Debug,
|
||||||
|
"No tieline found for inputPort {inputPort}. Clearing current source",
|
||||||
|
this,
|
||||||
|
inputPort
|
||||||
|
);
|
||||||
|
|
||||||
var tempSourceListItem = new SourceListItem
|
var tempSourceListItem = new SourceListItem
|
||||||
{
|
{
|
||||||
@@ -123,12 +165,13 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
Name = inputPort.Key,
|
Name = inputPort.Key,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
destination.CurrentSourceInfo = tempSourceListItem;
|
||||||
destination.CurrentSourceInfo = tempSourceListItem; ;
|
;
|
||||||
destination.CurrentSourceInfoKey = "$transient";
|
destination.CurrentSourceInfoKey = "$transient";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (Exception ex)
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(ex, "Error getting first tieline: {Exception}", this, ex);
|
Debug.LogMessage(ex, "Error getting first tieline: {Exception}", this, ex);
|
||||||
return;
|
return;
|
||||||
@@ -143,7 +186,12 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
|
|
||||||
if (sourceTieLine == null)
|
if (sourceTieLine == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No route found to source for inputPort {inputPort}. Clearing current source", this, inputPort);
|
Debug.LogMessage(
|
||||||
|
Serilog.Events.LogEventLevel.Debug,
|
||||||
|
"No route found to source for inputPort {inputPort}. Clearing current source",
|
||||||
|
this,
|
||||||
|
inputPort
|
||||||
|
);
|
||||||
|
|
||||||
var tempSourceListItem = new SourceListItem
|
var tempSourceListItem = new SourceListItem
|
||||||
{
|
{
|
||||||
@@ -155,32 +203,45 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
destination.CurrentSourceInfoKey = string.Empty;
|
destination.CurrentSourceInfoKey = string.Empty;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch(Exception ex)
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(ex, "Error getting sourceTieLine: {Exception}", this, ex);
|
Debug.LogMessage(ex, "Error getting sourceTieLine: {Exception}", this, ex);
|
||||||
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
|
||||||
if(r is IHasMultipleDisplays roomMultipleDisplays)
|
.AllDevices.OfType<IEssentialsRoom>()
|
||||||
{
|
.FirstOrDefault(
|
||||||
return roomMultipleDisplays.Displays.Any(d => d.Value.Key == destination.Key);
|
(r) =>
|
||||||
}
|
{
|
||||||
|
if (r is IHasMultipleDisplays roomMultipleDisplays)
|
||||||
|
{
|
||||||
|
return roomMultipleDisplays.Displays.Any(d =>
|
||||||
|
d.Value.Key == destination.Key
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if(r is IHasDefaultDisplay roomDefaultDisplay)
|
if (r is IHasDefaultDisplay roomDefaultDisplay)
|
||||||
{
|
{
|
||||||
return roomDefaultDisplay.DefaultDisplay.Key == destination.Key;
|
return roomDefaultDisplay.DefaultDisplay.Key == destination.Key;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
if(room == null)
|
|
||||||
|
if (room == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "No room found for display {destination}", this, destination.Key);
|
Debug.LogMessage(
|
||||||
|
Serilog.Events.LogEventLevel.Debug,
|
||||||
|
"No room found for display {destination}",
|
||||||
|
this,
|
||||||
|
destination.Key
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,29 +251,45 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
|
|
||||||
if (sourceList == null)
|
if (sourceList == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Warning, "No source list found for source list key {key}. Unable to find source for tieLine {sourceTieLine}", this, room.SourceListKey, sourceTieLine);
|
Debug.LogMessage(
|
||||||
|
Serilog.Events.LogEventLevel.Debug,
|
||||||
|
"No source list found for source list key {key}. Unable to find source for tieLine {sourceTieLine}",
|
||||||
|
this,
|
||||||
|
room.SourceListKey,
|
||||||
|
sourceTieLine
|
||||||
|
);
|
||||||
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,
|
{
|
||||||
// "SourceListItem {sourceListItem}:{sourceKey} tieLine sourceport device key {sourcePortDeviceKey}",
|
//// Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose,
|
||||||
// this,
|
// "SourceListItem {sourceListItem}:{sourceKey} tieLine sourceport device key {sourcePortDeviceKey}",
|
||||||
// sli.Key,
|
// this,
|
||||||
// sli.Value.SourceKey,
|
// sli.Key,
|
||||||
// sourceTieLine.SourcePort.ParentDevice.Key);
|
// sli.Value.SourceKey,
|
||||||
|
// 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;
|
var sourceKey = sourceListItem.Key;
|
||||||
|
|
||||||
if (source == null)
|
if (source == null)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No source found for device {key}. Creating transient source for {destination}", this, sourceTieLine.SourcePort.ParentDevice.Key, destination);
|
Debug.LogMessage(
|
||||||
|
Serilog.Events.LogEventLevel.Debug,
|
||||||
|
"No source found for device {key}. Creating transient source for {destination}",
|
||||||
|
this,
|
||||||
|
sourceTieLine.SourcePort.ParentDevice.Key,
|
||||||
|
destination
|
||||||
|
);
|
||||||
|
|
||||||
var tempSourceListItem = new SourceListItem
|
var tempSourceListItem = new SourceListItem
|
||||||
{
|
{
|
||||||
@@ -221,7 +298,7 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
};
|
};
|
||||||
|
|
||||||
destination.CurrentSourceInfoKey = "$transient";
|
destination.CurrentSourceInfoKey = "$transient";
|
||||||
destination.CurrentSourceInfo = tempSourceListItem;
|
destination.CurrentSourceInfo = tempSourceListItem;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,7 +306,6 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
|
|
||||||
destination.CurrentSourceInfoKey = sourceKey;
|
destination.CurrentSourceInfoKey = sourceKey;
|
||||||
destination.CurrentSourceInfo = source;
|
destination.CurrentSourceInfo = source;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -249,29 +325,49 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
{
|
{
|
||||||
// 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)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "Midpoint {midpointKey} has no routes",this, midpoint.Key);
|
Debug.LogMessage(
|
||||||
|
Serilog.Events.LogEventLevel.Debug,
|
||||||
|
"Midpoint {midpointKey} has no routes",
|
||||||
|
this,
|
||||||
|
midpoint.Key
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 != null && route.InputPort != null && 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)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(Serilog.Events.LogEventLevel.Information, "No route through midpoint {midpoint} for outputPort {outputPort}", this, midpoint.Key, tieLine.SourcePort);
|
Debug.LogMessage(
|
||||||
|
Serilog.Events.LogEventLevel.Debug,
|
||||||
|
"No route through midpoint {midpoint} for outputPort {outputPort}",
|
||||||
|
this,
|
||||||
|
midpoint.Key,
|
||||||
|
tieLine.SourcePort
|
||||||
|
);
|
||||||
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)
|
||||||
{
|
{
|
||||||
@@ -286,19 +382,26 @@ namespace PepperDash.Essentials.Core.Routing
|
|||||||
//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;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextTieLine = TieLineCollection.Default.FirstOrDefault(tl => tl.DestinationPort.Key == tieLine.SourcePort.Key && tl.DestinationPort.ParentDevice.Key == tieLine.SourcePort.ParentDevice.Key );
|
nextTieLine = TieLineCollection.Default.FirstOrDefault(tl =>
|
||||||
|
tl.DestinationPort.Key == tieLine.SourcePort.Key
|
||||||
|
&& tl.DestinationPort.ParentDevice.Key == tieLine.SourcePort.ParentDevice.Key
|
||||||
|
);
|
||||||
|
|
||||||
if (nextTieLine != null)
|
if (nextTieLine != null)
|
||||||
{
|
{
|
||||||
return GetRootTieLine(nextTieLine);
|
return GetRootTieLine(nextTieLine);
|
||||||
}
|
}
|
||||||
} catch (Exception ex)
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(ex, "Error walking tieLines: {Exception}", this, ex);
|
Debug.LogMessage(ex, "Error walking tieLines: {Exception}", this, ex);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -14,14 +14,14 @@ using Serilog.Events;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
////*****************************************************************************
|
////*****************************************************************************
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// Base class for all subpage reference list controllers
|
///// Base class for all subpage reference list controllers
|
||||||
/// </summary>
|
///// </summary>
|
||||||
//public class SubpageReferenceListController
|
//public class SubpageReferenceListController
|
||||||
//{
|
//{
|
||||||
// public SubpageReferenceList TheList { get; protected set; }
|
// public SubpageReferenceList TheList { get; protected set; }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -34,26 +34,26 @@ namespace PepperDash.Essentials.Core
|
|||||||
public ushort Count
|
public ushort Count
|
||||||
{
|
{
|
||||||
get { return SetNumberOfItemsSig.UShortValue; }
|
get { return SetNumberOfItemsSig.UShortValue; }
|
||||||
set { SetNumberOfItemsSig.UShortValue = value; }
|
set { SetNumberOfItemsSig.UShortValue = value; }
|
||||||
}
|
}
|
||||||
public ushort MaxDefinedItems { get; private set; }
|
public ushort MaxDefinedItems { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the ScrollToItemSig
|
/// Gets or sets the ScrollToItemSig
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public UShortInputSig ScrollToItemSig { get; private set; }
|
public UShortInputSig ScrollToItemSig { get; private set; }
|
||||||
UShortInputSig SetNumberOfItemsSig;
|
UShortInputSig SetNumberOfItemsSig;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the BoolIncrement
|
/// Gets or sets the BoolIncrement
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint BoolIncrement { get; protected set; }
|
public uint BoolIncrement { get; protected set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the UShortIncrement
|
/// Gets or sets the UShortIncrement
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint UShortIncrement { get; protected set; }
|
public uint UShortIncrement { get; protected set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the StringIncrement
|
/// Gets or sets the StringIncrement
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint StringIncrement { get; protected set; }
|
public uint StringIncrement { get; protected set; }
|
||||||
|
|
||||||
protected readonly SmartObject SRL;
|
protected readonly SmartObject SRL;
|
||||||
@@ -87,8 +87,8 @@ namespace PepperDash.Essentials.Core
|
|||||||
SRL.SigChange += new SmartObjectSigChangeEventHandler(SRL_SigChange);
|
SRL.SigChange += new SmartObjectSigChangeEventHandler(SRL_SigChange);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Debug.LogMessage(LogEventLevel.Information, "ERROR: TriList 0x{0:X2} Cannot load smart object {1}. Verify correct SGD file is loaded",
|
Debug.LogMessage(LogEventLevel.Information, "ERROR: TriList 0x{0:X2} Cannot load smart object {1}. Verify correct SGD file is loaded",
|
||||||
triList.ID, smartObjectId);
|
triList.ID, smartObjectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -96,17 +96,17 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// DOES NOT adjust Count
|
/// DOES NOT adjust Count
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// AddItem method
|
/// AddItem method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void AddItem(SubpageReferenceListItem item)
|
public void AddItem(SubpageReferenceListItem item)
|
||||||
{
|
{
|
||||||
Items.Add(item);
|
Items.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clear method
|
/// Clear method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
// If a line item needs to disconnect an CueActionPair or do something to release RAM
|
// If a line item needs to disconnect an CueActionPair or do something to release RAM
|
||||||
@@ -116,12 +116,12 @@ namespace PepperDash.Essentials.Core
|
|||||||
// Clean up the SRL
|
// Clean up the SRL
|
||||||
Count = 1;
|
Count = 1;
|
||||||
|
|
||||||
ScrollToItemSig.UShortValue = 1;
|
ScrollToItemSig.UShortValue = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Refresh method
|
/// Refresh method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Refresh()
|
public void Refresh()
|
||||||
{
|
{
|
||||||
foreach (var item in Items) item.Refresh();
|
foreach (var item in Items) item.Refresh();
|
||||||
@@ -157,7 +157,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
public UShortOutputSig GetUShortOutputSig(uint index, uint sigNum)
|
public UShortOutputSig GetUShortOutputSig(uint index, uint sigNum)
|
||||||
{
|
{
|
||||||
if (sigNum > UShortIncrement) return null;
|
if (sigNum > UShortIncrement) return null;
|
||||||
return SRL.UShortOutput.FirstOrDefault(s => s.Name.Equals(GetUShortOutputSigName(index, sigNum)));
|
return SRL.UShortOutput.FirstOrDefault(s => s.Name.Equals(GetUShortOutputSigName(index, sigNum)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -172,7 +172,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
public StringOutputSig GetStringOutputSig(uint index, uint sigNum)
|
public StringOutputSig GetStringOutputSig(uint index, uint sigNum)
|
||||||
{
|
{
|
||||||
if (sigNum > StringIncrement) return null;
|
if (sigNum > StringIncrement) return null;
|
||||||
return SRL.StringOutput.FirstOrDefault(s => s.Name.Equals(GetStringOutputSigName(index, sigNum)));
|
return SRL.StringOutput.FirstOrDefault(s => s.Name.Equals(GetStringOutputSigName(index, sigNum)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -263,9 +263,9 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="currentDevice"></param>
|
/// <param name="currentDevice"></param>
|
||||||
/// <param name="args"></param>
|
/// <param name="args"></param>
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SRL_SigChange method
|
/// SRL_SigChange method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void SRL_SigChange(GenericBase currentDevice, SmartObjectEventArgs args)
|
public static void SRL_SigChange(GenericBase currentDevice, SmartObjectEventArgs args)
|
||||||
{
|
{
|
||||||
var uo = args.Sig.UserObject;
|
var uo = args.Sig.UserObject;
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ using Serilog.Events;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core
|
namespace PepperDash.Essentials.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a ModalDialog
|
/// Represents a ModalDialog
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ModalDialog
|
public class ModalDialog
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -19,10 +19,10 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// Bool press 3992
|
/// Bool press 3992
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const uint Button2Join = 3992;
|
public const uint Button2Join = 3992;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 3993
|
/// 3993
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const uint CancelButtonJoin = 3993;
|
public const uint CancelButtonJoin = 3993;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///For visibility of single button. Bool feedback 3994
|
///For visibility of single button. Bool feedback 3994
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -35,19 +35,19 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// Shows the timer guage if in use. Bool feedback 3996
|
/// Shows the timer guage if in use. Bool feedback 3996
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const uint TimerVisibleJoin = 3996;
|
public const uint TimerVisibleJoin = 3996;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Visibility join to show "X" button 3997
|
/// Visibility join to show "X" button 3997
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const uint CancelVisibleJoin = 3997;
|
public const uint CancelVisibleJoin = 3997;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shows the modal subpage. Boolean feeback join 3999
|
/// Shows the modal subpage. Boolean feeback join 3999
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const uint ModalVisibleJoin = 3999;
|
public const uint ModalVisibleJoin = 3999;
|
||||||
|
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// The seconds value of the countdown timer. Ushort join 3991
|
///// The seconds value of the countdown timer. Ushort join 3991
|
||||||
/// </summary>
|
///// </summary>
|
||||||
//public const uint TimerSecondsJoin = 3991;
|
//public const uint TimerSecondsJoin = 3991;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The full ushort value of the countdown timer for a gauge. Ushort join 3992
|
/// The full ushort value of the countdown timer for a gauge. Ushort join 3992
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -77,15 +77,15 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns true when modal is showing
|
/// Returns true when modal is showing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ModalIsVisible
|
public bool ModalIsVisible
|
||||||
{
|
{
|
||||||
get { return TriList.BooleanInput[ModalVisibleJoin].BoolValue; }
|
get { return TriList.BooleanInput[ModalVisibleJoin].BoolValue; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool CanCancel { get; private set; }
|
public bool CanCancel { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
BasicTriList TriList;
|
BasicTriList TriList;
|
||||||
@@ -103,10 +103,10 @@ namespace PepperDash.Essentials.Core
|
|||||||
TriList = triList;
|
TriList = triList;
|
||||||
// Attach actions to buttons
|
// Attach actions to buttons
|
||||||
|
|
||||||
triList.SetSigFalseAction(Button1Join, () => OnModalComplete(1));
|
triList.SetSigFalseAction(Button1Join, () => OnModalComplete(1));
|
||||||
triList.SetSigFalseAction(Button2Join, () => OnModalComplete(2));
|
triList.SetSigFalseAction(Button2Join, () => OnModalComplete(2));
|
||||||
triList.SetSigFalseAction(CancelButtonJoin, () => { if (CanCancel) CancelDialog(); });
|
triList.SetSigFalseAction(CancelButtonJoin, () => { if (CanCancel) CancelDialog(); });
|
||||||
CanCancel = true;
|
CanCancel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -117,7 +117,7 @@ namespace PepperDash.Essentials.Core
|
|||||||
/// <param name="decreasingGauge">If the progress bar gauge needs to count down instead of up</param>
|
/// <param name="decreasingGauge">If the progress bar gauge needs to count down instead of up</param>
|
||||||
/// <param name="completeAction">The action to run when the dialog is dismissed. Parameter will be 1 or 2 if button pressed, or 0 if dialog times out</param>
|
/// <param name="completeAction">The action to run when the dialog is dismissed. Parameter will be 1 or 2 if button pressed, or 0 if dialog times out</param>
|
||||||
/// <returns>True when modal is created.</returns>
|
/// <returns>True when modal is created.</returns>
|
||||||
public bool PresentModalDialog(uint numberOfButtons, string title, string iconName,
|
public bool PresentModalDialog(uint numberOfButtons, string title, string iconName,
|
||||||
string message, string button1Text,
|
string message, string button1Text,
|
||||||
string button2Text, bool showGauge, bool showCancel, Action<uint> completeAction)
|
string button2Text, bool showGauge, bool showCancel, Action<uint> completeAction)
|
||||||
{
|
{
|
||||||
@@ -151,15 +151,15 @@ namespace PepperDash.Essentials.Core
|
|||||||
TriList.StringInput[Button2TextJoin].StringValue = button2Text;
|
TriList.StringInput[Button2TextJoin].StringValue = button2Text;
|
||||||
}
|
}
|
||||||
// Show/hide guage
|
// Show/hide guage
|
||||||
TriList.BooleanInput[TimerVisibleJoin].BoolValue = showGauge;
|
TriList.BooleanInput[TimerVisibleJoin].BoolValue = showGauge;
|
||||||
|
|
||||||
CanCancel = showCancel;
|
CanCancel = showCancel;
|
||||||
TriList.BooleanInput[CancelVisibleJoin].BoolValue = showCancel;
|
TriList.BooleanInput[CancelVisibleJoin].BoolValue = showCancel;
|
||||||
|
|
||||||
//Reveal and activate
|
//Reveal and activate
|
||||||
TriList.BooleanInput[ModalVisibleJoin].BoolValue = true;
|
TriList.BooleanInput[ModalVisibleJoin].BoolValue = true;
|
||||||
|
|
||||||
WakePanel();
|
WakePanel();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -167,48 +167,48 @@ namespace PepperDash.Essentials.Core
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// WakePanel method
|
/// WakePanel method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void WakePanel()
|
public void WakePanel()
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var panel = TriList as TswFt5Button;
|
|
||||||
|
|
||||||
if (panel != null && panel.ExtenderSystemReservedSigs.BacklightOffFeedback.BoolValue)
|
|
||||||
panel.ExtenderSystemReservedSigs.BacklightOn();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Error Waking Panel. Maybe testing with Xpanel?");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// CancelDialog method
|
|
||||||
/// </summary>
|
|
||||||
public void CancelDialog()
|
|
||||||
{
|
{
|
||||||
OnModalComplete(0);
|
try
|
||||||
|
{
|
||||||
|
var panel = TriList as TswFt5Button;
|
||||||
|
|
||||||
|
if (panel != null && panel.ExtenderSystemReservedSigs.BacklightOffFeedback.BoolValue)
|
||||||
|
panel.ExtenderSystemReservedSigs.BacklightOn();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Debug, "Error Waking Panel. Maybe testing with Xpanel?");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hides dialog. Fires no action
|
/// CancelDialog method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void HideDialog()
|
public void CancelDialog()
|
||||||
{
|
{
|
||||||
TriList.BooleanInput[ModalVisibleJoin].BoolValue = false;
|
OnModalComplete(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hides dialog. Fires no action
|
||||||
|
/// </summary>
|
||||||
|
public void HideDialog()
|
||||||
|
{
|
||||||
|
TriList.BooleanInput[ModalVisibleJoin].BoolValue = false;
|
||||||
|
}
|
||||||
|
|
||||||
// When the modal is cleared or times out, clean up the various bits
|
// When the modal is cleared or times out, clean up the various bits
|
||||||
void OnModalComplete(uint buttonNum)
|
void OnModalComplete(uint buttonNum)
|
||||||
{
|
{
|
||||||
TriList.BooleanInput[ModalVisibleJoin].BoolValue = false;
|
TriList.BooleanInput[ModalVisibleJoin].BoolValue = false;
|
||||||
|
|
||||||
var action = ModalCompleteAction;
|
var action = ModalCompleteAction;
|
||||||
if (action != null)
|
if (action != null)
|
||||||
action(buttonNum);
|
action(buttonNum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using PepperDash.Essentials.Core;
|
|
||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
|
||||||
using PepperDash.Core;
|
|
||||||
using Crestron.SimplSharpPro.UI;
|
|
||||||
using Crestron.SimplSharp.CrestronIO;
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
using Crestron.SimplSharpPro;
|
using Crestron.SimplSharpPro;
|
||||||
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Core.Logging;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Core.UI
|
namespace PepperDash.Essentials.Core.UI
|
||||||
{
|
{
|
||||||
public abstract class TouchpanelBase: EssentialsDevice, IHasBasicTriListWithSmartObject
|
/// <summary>
|
||||||
|
/// Base class for Touchpanel devices
|
||||||
|
/// </summary>
|
||||||
|
public abstract class TouchpanelBase : EssentialsDevice, IHasBasicTriListWithSmartObject
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the configuration for the Crestron touchpanel.
|
||||||
|
/// </summary>
|
||||||
protected CrestronTouchpanelPropertiesConfig _config;
|
protected CrestronTouchpanelPropertiesConfig _config;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Panel
|
/// Gets or sets the Panel
|
||||||
@@ -27,12 +29,11 @@ namespace PepperDash.Essentials.Core.UI
|
|||||||
/// is provided.
|
/// is provided.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">Essentials Device Key</param>
|
/// <param name="key">Essentials Device Key</param>
|
||||||
/// <param name="name">Essentials Device Name</param>
|
/// <param name="name">Essentials Device Name</param>
|
||||||
/// <param name="type">Touchpanel Type to build</param>
|
/// <param name="panel">Crestron Touchpanel Device</param>
|
||||||
/// <param name="config">Touchpanel Configuration</param>
|
/// <param name="config">Touchpanel Configuration</param>
|
||||||
/// <param name="id">IP-ID to use for touch panel</param>
|
|
||||||
protected TouchpanelBase(string key, string name, BasicTriListWithSmartObject panel, CrestronTouchpanelPropertiesConfig config)
|
protected TouchpanelBase(string key, string name, BasicTriListWithSmartObject panel, CrestronTouchpanelPropertiesConfig config)
|
||||||
:base(key, name)
|
: base(key, name)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (panel == null)
|
if (panel == null)
|
||||||
@@ -55,23 +56,21 @@ namespace PepperDash.Essentials.Core.UI
|
|||||||
tsw.ButtonStateChange += Tsw_ButtonStateChange;
|
tsw.ButtonStateChange += Tsw_ButtonStateChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
_config = config;
|
_config = config;
|
||||||
|
|
||||||
AddPreActivationAction(() => {
|
|
||||||
if (Panel.Register() != eDeviceRegistrationUnRegistrationResponse.Success)
|
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "WARNING: Registration failed. Continuing, but panel may not function: {0}", Panel.RegistrationFailureReason);
|
|
||||||
|
|
||||||
|
AddPreActivationAction(() =>
|
||||||
|
{
|
||||||
// Give up cleanly if SGD is not present.
|
// Give up cleanly if SGD is not present.
|
||||||
var sgdName = Global.FilePathPrefix + "sgd" + Global.DirectorySeparator + _config.SgdFile;
|
var sgdName = Global.FilePathPrefix + "sgd" + Global.DirectorySeparator + _config.SgdFile;
|
||||||
if (!File.Exists(sgdName))
|
if (!File.Exists(sgdName))
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Smart object file '{0}' not present in User folder. Looking for embedded file", sgdName);
|
this.LogInformation("Smart object file '{0}' not present in User folder. Looking for embedded file", sgdName);
|
||||||
|
|
||||||
sgdName = Global.ApplicationDirectoryPathPrefix + Global.DirectorySeparator + "SGD" + Global.DirectorySeparator + _config.SgdFile;
|
sgdName = Global.ApplicationDirectoryPathPrefix + Global.DirectorySeparator + "SGD" + Global.DirectorySeparator + _config.SgdFile;
|
||||||
|
|
||||||
if (!File.Exists(sgdName))
|
if (!File.Exists(sgdName))
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Information, this, "Unable to find SGD file '{0}' in User sgd or application SGD folder. Exiting touchpanel load.", sgdName);
|
this.LogWarning("Unable to find SGD file '{0}' in User sgd or application SGD folder. Exiting touchpanel load.", sgdName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,12 +81,11 @@ namespace PepperDash.Essentials.Core.UI
|
|||||||
AddPostActivationAction(() =>
|
AddPostActivationAction(() =>
|
||||||
{
|
{
|
||||||
// Check for IEssentialsRoomCombiner in DeviceManager and if found, subscribe to its event
|
// Check for IEssentialsRoomCombiner in DeviceManager and if found, subscribe to its event
|
||||||
var roomCombiner = DeviceManager.AllDevices.FirstOrDefault((d) => d is IEssentialsRoomCombiner) as IEssentialsRoomCombiner;
|
|
||||||
|
|
||||||
if (roomCombiner != null)
|
if (DeviceManager.AllDevices.FirstOrDefault((d) => d is IEssentialsRoomCombiner) is IEssentialsRoomCombiner roomCombiner)
|
||||||
{
|
{
|
||||||
// Subscribe to the even
|
// Subscribe to the even
|
||||||
roomCombiner.RoomCombinationScenarioChanged += new EventHandler<EventArgs>(roomCombiner_RoomCombinationScenarioChanged);
|
roomCombiner.RoomCombinationScenarioChanged += new EventHandler<EventArgs>(RoomCombiner_RoomCombinationScenarioChanged);
|
||||||
|
|
||||||
// Connect to the initial roomKey
|
// Connect to the initial roomKey
|
||||||
if (roomCombiner.CurrentScenario != null)
|
if (roomCombiner.CurrentScenario != null)
|
||||||
@@ -106,6 +104,11 @@ namespace PepperDash.Essentials.Core.UI
|
|||||||
// No room combiner, use the default key
|
// No room combiner, use the default key
|
||||||
SetupPanelDrivers(_config.DefaultRoomKey);
|
SetupPanelDrivers(_config.DefaultRoomKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var panelRegistrationResponse = Panel.Register();
|
||||||
|
|
||||||
|
if (panelRegistrationResponse != eDeviceRegistrationUnRegistrationResponse.Success)
|
||||||
|
this.LogInformation("WARNING: Registration failed. Continuing, but panel may not function: {0}", Panel.RegistrationFailureReason);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +118,6 @@ namespace PepperDash.Essentials.Core.UI
|
|||||||
/// <param name="roomKey">Room Key for this panel</param>
|
/// <param name="roomKey">Room Key for this panel</param>
|
||||||
protected abstract void SetupPanelDrivers(string roomKey);
|
protected abstract void SetupPanelDrivers(string roomKey);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event handler for System Extender Events
|
/// Event handler for System Extender Events
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -129,7 +131,7 @@ namespace PepperDash.Essentials.Core.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender"></param>
|
/// <param name="sender"></param>
|
||||||
/// <param name="e"></param>
|
/// <param name="e"></param>
|
||||||
protected virtual void roomCombiner_RoomCombinationScenarioChanged(object sender, EventArgs e)
|
protected virtual void RoomCombiner_RoomCombinationScenarioChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var roomCombiner = sender as IEssentialsRoomCombiner;
|
var roomCombiner = sender as IEssentialsRoomCombiner;
|
||||||
|
|
||||||
@@ -156,23 +158,23 @@ namespace PepperDash.Essentials.Core.UI
|
|||||||
SetupPanelDrivers(newRoomKey);
|
SetupPanelDrivers(newRoomKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Panel_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args)
|
private void Panel_SigChange(object currentDevice, SigEventArgs args)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "Sig change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
|
this.LogVerbose("Sig change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
|
||||||
var uo = args.Sig.UserObject;
|
var uo = args.Sig.UserObject;
|
||||||
if (uo is Action<bool>)
|
if (uo is Action<bool>)
|
||||||
(uo as Action<bool>)(args.Sig.BoolValue);
|
(uo as Action<bool>)(args.Sig.BoolValue);
|
||||||
else if (uo is Action<ushort>)
|
else if (uo is Action<ushort>)
|
||||||
(uo as Action<ushort>)(args.Sig.UShortValue);
|
(uo as Action<ushort>)(args.Sig.UShortValue);
|
||||||
else if (uo is Action<string>)
|
else if (uo is Action<string>)
|
||||||
(uo as Action<string>)(args.Sig.StringValue);
|
(uo as Action<string>)(args.Sig.StringValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args)
|
private void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args)
|
||||||
{
|
{
|
||||||
var uo = args.Button.UserObject;
|
var uo = args.Button.UserObject;
|
||||||
if(uo is Action<bool>)
|
if (uo is Action<bool>)
|
||||||
(uo as Action<bool>)(args.Button.State == eButtonState.Pressed);
|
(uo as Action<bool>)(args.Button.State == eButtonState.Pressed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,9 +6,9 @@ using PepperDash.Core.Web.RequestHandlers;
|
|||||||
|
|
||||||
namespace PepperDash.Essentials.Core.Web.RequestHandlers
|
namespace PepperDash.Essentials.Core.Web.RequestHandlers
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a SetDeviceStreamDebugRequestHandler
|
/// Represents a SetDeviceStreamDebugRequestHandler
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SetDeviceStreamDebugRequestHandler : WebApiBaseRequestHandler
|
public class SetDeviceStreamDebugRequestHandler : WebApiBaseRequestHandler
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -122,23 +122,23 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(DeviceManager.GetDeviceForKey(body.DeviceKey) is IStreamDebugging device))
|
if (!(DeviceManager.GetDeviceForKey(body.DeviceKey) is IStreamDebugging device))
|
||||||
{
|
{
|
||||||
context.Response.StatusCode = 404;
|
context.Response.StatusCode = 404;
|
||||||
context.Response.StatusDescription = "Not Found";
|
context.Response.StatusDescription = "Not Found";
|
||||||
context.Response.End();
|
context.Response.End();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
eStreamDebuggingSetting debugSetting;
|
eStreamDebuggingSetting debugSetting;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
debugSetting = (eStreamDebuggingSetting) Enum.Parse(typeof (eStreamDebuggingSetting), body.Setting, true);
|
debugSetting = (eStreamDebuggingSetting)Enum.Parse(typeof(eStreamDebuggingSetting), body.Setting, true);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(ex, "Exception handling set debug request");
|
Debug.LogMessage(ex, "Exception handling set debug request");
|
||||||
context.Response.StatusCode = 500;
|
context.Response.StatusCode = 500;
|
||||||
context.Response.StatusDescription = "Internal Server Error";
|
context.Response.StatusDescription = "Internal Server Error";
|
||||||
context.Response.End();
|
context.Response.End();
|
||||||
@@ -164,7 +164,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(ex, "Exception handling set debug request");
|
Debug.LogMessage(ex, "Exception handling set debug request");
|
||||||
context.Response.StatusCode = 500;
|
context.Response.StatusCode = 500;
|
||||||
context.Response.StatusDescription = "Internal Server Error";
|
context.Response.StatusDescription = "Internal Server Error";
|
||||||
context.Response.End();
|
context.Response.End();
|
||||||
@@ -198,21 +198,21 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers
|
|||||||
public class SetDeviceStreamDebugConfig
|
public class SetDeviceStreamDebugConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("deviceKey", NullValueHandling = NullValueHandling.Include)]
|
[JsonProperty("deviceKey", NullValueHandling = NullValueHandling.Include)]
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the DeviceKey
|
/// Gets or sets the DeviceKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string DeviceKey { get; set; }
|
public string DeviceKey { get; set; }
|
||||||
|
|
||||||
[JsonProperty("setting", NullValueHandling = NullValueHandling.Include)]
|
[JsonProperty("setting", NullValueHandling = NullValueHandling.Include)]
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Setting
|
/// Gets or sets the Setting
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Setting { get; set; }
|
public string Setting { get; set; }
|
||||||
|
|
||||||
[JsonProperty("timeout")]
|
[JsonProperty("timeout")]
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Timeout
|
/// Gets or sets the Timeout
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Timeout { get; set; }
|
public int Timeout { get; set; }
|
||||||
|
|
||||||
public SetDeviceStreamDebugConfig()
|
public SetDeviceStreamDebugConfig()
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
@@ -17,48 +13,68 @@ namespace PepperDash.Essentials.Devices.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GenericAudioOut : EssentialsDevice, IRoutingSink
|
public class GenericAudioOut : EssentialsDevice, IRoutingSink
|
||||||
{
|
{
|
||||||
public RoutingInputPort CurrentInputPort => AnyAudioIn;
|
/// <summary>
|
||||||
|
/// Gets the current input port
|
||||||
|
/// </summary>
|
||||||
|
public RoutingInputPort CurrentInputPort => AnyAudioIn;
|
||||||
|
|
||||||
public event SourceInfoChangeHandler CurrentSourceChange;
|
/// <summary>
|
||||||
|
/// Event fired when the current source changes
|
||||||
|
/// </summary>
|
||||||
|
public event SourceInfoChangeHandler CurrentSourceChange;
|
||||||
|
|
||||||
public string CurrentSourceInfoKey { get; set; }
|
/// <summary>
|
||||||
public SourceListItem CurrentSourceInfo
|
/// Gets or sets the current source info key
|
||||||
{
|
/// </summary>
|
||||||
get
|
public string CurrentSourceInfoKey { get; set; }
|
||||||
{
|
/// <summary>
|
||||||
return _CurrentSourceInfo;
|
/// Gets or sets the current source info
|
||||||
}
|
/// </summary>
|
||||||
set
|
public SourceListItem CurrentSourceInfo
|
||||||
{
|
{
|
||||||
if (value == _CurrentSourceInfo) return;
|
get
|
||||||
|
{
|
||||||
|
return _CurrentSourceInfo;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == _CurrentSourceInfo) return;
|
||||||
|
|
||||||
var handler = CurrentSourceChange;
|
var handler = CurrentSourceChange;
|
||||||
|
|
||||||
if (handler != null)
|
if (handler != null)
|
||||||
handler(_CurrentSourceInfo, ChangeType.WillChange);
|
handler(_CurrentSourceInfo, ChangeType.WillChange);
|
||||||
|
|
||||||
_CurrentSourceInfo = value;
|
_CurrentSourceInfo = value;
|
||||||
|
|
||||||
if (handler != null)
|
if (handler != null)
|
||||||
handler(_CurrentSourceInfo, ChangeType.DidChange);
|
handler(_CurrentSourceInfo, ChangeType.DidChange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SourceListItem _CurrentSourceInfo;
|
SourceListItem _CurrentSourceInfo;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the AnyAudioIn
|
/// Gets or sets the AnyAudioIn
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public RoutingInputPort AnyAudioIn { get; private set; }
|
public RoutingInputPort AnyAudioIn { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for GenericAudioOut
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Device key</param>
|
||||||
|
/// <param name="name">Device name</param>
|
||||||
public GenericAudioOut(string key, string name)
|
public GenericAudioOut(string key, string name)
|
||||||
: base(key, name)
|
: base(key, name)
|
||||||
{
|
{
|
||||||
AnyAudioIn = new RoutingInputPort(RoutingPortNames.AnyAudioIn, eRoutingSignalType.Audio,
|
AnyAudioIn = new RoutingInputPort(RoutingPortNames.AnyAudioIn, eRoutingSignalType.Audio,
|
||||||
eRoutingPortConnectionType.LineAudio, null, this);
|
eRoutingPortConnectionType.LineAudio, null, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IRoutingInputs Members
|
#region IRoutingInputs Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the collection of input ports
|
||||||
|
/// </summary>
|
||||||
public RoutingPortCollection<RoutingInputPort> InputPorts
|
public RoutingPortCollection<RoutingInputPort> InputPorts
|
||||||
{
|
{
|
||||||
get { return new RoutingPortCollection<RoutingInputPort> { AnyAudioIn }; }
|
get { return new RoutingPortCollection<RoutingInputPort> { AnyAudioIn }; }
|
||||||
@@ -68,23 +84,32 @@ namespace PepperDash.Essentials.Devices.Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a GenericAudioOutWithVolume
|
/// Represents a GenericAudioOutWithVolume
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GenericAudioOutWithVolume : GenericAudioOut, IHasVolumeDevice
|
public class GenericAudioOutWithVolume : GenericAudioOut, IHasVolumeDevice
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the volume device key
|
||||||
|
/// </summary>
|
||||||
public string VolumeDeviceKey { get; private set; }
|
public string VolumeDeviceKey { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the volume zone
|
||||||
|
/// </summary>
|
||||||
public uint VolumeZone { get; private set; }
|
public uint VolumeZone { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the volume device
|
||||||
|
/// </summary>
|
||||||
public IBasicVolumeControls VolumeDevice
|
public IBasicVolumeControls VolumeDevice
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var dev = DeviceManager.GetDeviceForKey(VolumeDeviceKey);
|
var dev = DeviceManager.GetDeviceForKey(VolumeDeviceKey);
|
||||||
if (dev is IAudioZones)
|
if (dev is IAudioZones)
|
||||||
return (dev as IAudioZones).Zone[VolumeZone];
|
return (dev as IAudioZones).Zone[VolumeZone];
|
||||||
else return dev as IBasicVolumeControls;
|
else return dev as IBasicVolumeControls;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -103,24 +128,30 @@ namespace PepperDash.Essentials.Devices.Common
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GenericAudioOutWithVolumeFactory : EssentialsDeviceFactory<GenericAudioOutWithVolume>
|
/// <summary>
|
||||||
{
|
/// Factory for creating GenericAudioOutWithVolume devices
|
||||||
public GenericAudioOutWithVolumeFactory()
|
/// </summary>
|
||||||
{
|
public class GenericAudioOutWithVolumeFactory : EssentialsDeviceFactory<GenericAudioOutWithVolume>
|
||||||
TypeNames = new List<string>() { "genericaudiooutwithvolume" };
|
{
|
||||||
}
|
/// <summary>
|
||||||
|
/// Constructor for GenericAudioOutWithVolumeFactory
|
||||||
|
/// </summary>
|
||||||
|
public GenericAudioOutWithVolumeFactory()
|
||||||
|
{
|
||||||
|
TypeNames = new List<string>() { "genericaudiooutwithvolume" };
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// BuildDevice method
|
/// BuildDevice method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new GenericAudioOutWithVolumeFactory Device");
|
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new GenericAudioOutWithVolumeFactory Device");
|
||||||
var zone = dc.Properties.Value<uint>("zone");
|
var zone = dc.Properties.Value<uint>("zone");
|
||||||
return new GenericAudioOutWithVolume(dc.Key, dc.Name,
|
return new GenericAudioOutWithVolume(dc.Key, dc.Name,
|
||||||
dc.Properties.Value<string>("volumeDeviceKey"), zone);
|
dc.Properties.Value<string>("volumeDeviceKey"), zone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,20 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
|
|
||||||
using PepperDash.Core;
|
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using PepperDash.Essentials.Devices.Common.Codec;
|
using PepperDash.Essentials.Devices.Common.Codec;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Abstract base class for audio codec devices
|
||||||
|
/// </summary>
|
||||||
public abstract class AudioCodecBase : EssentialsDevice, IHasDialer, IUsageTracking, IAudioCodecInfo
|
public abstract class AudioCodecBase : EssentialsDevice, IHasDialer, IUsageTracking, IAudioCodecInfo
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event fired when call status changes
|
||||||
|
/// </summary>
|
||||||
public event EventHandler<CodecCallStatusItemChangeEventArgs> CallStatusChange;
|
public event EventHandler<CodecCallStatusItemChangeEventArgs> CallStatusChange;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -52,6 +54,11 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public List<CodecActiveCallItem> ActiveCalls { get; set; }
|
public List<CodecActiveCallItem> ActiveCalls { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for AudioCodecBase
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Device key</param>
|
||||||
|
/// <param name="name">Device name</param>
|
||||||
public AudioCodecBase(string key, string name)
|
public AudioCodecBase(string key, string name)
|
||||||
: base(key, name)
|
: base(key, name)
|
||||||
{
|
{
|
||||||
@@ -70,11 +77,9 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Handles call status change events
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="previousStatus"></param>
|
/// <param name="item">The call item that changed status</param>
|
||||||
/// <param name="newStatus"></param>
|
|
||||||
/// <param name="item"></param>
|
|
||||||
protected void OnCallStatusChange(CodecActiveCallItem item)
|
protected void OnCallStatusChange(CodecActiveCallItem item)
|
||||||
{
|
{
|
||||||
var handler = CallStatusChange;
|
var handler = CallStatusChange;
|
||||||
@@ -92,16 +97,22 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
|||||||
|
|
||||||
#region IHasDialer Members
|
#region IHasDialer Members
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public abstract void Dial(string number);
|
public abstract void Dial(string number);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public abstract void EndCall(CodecActiveCallItem activeCall);
|
public abstract void EndCall(CodecActiveCallItem activeCall);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public abstract void EndAllCalls();
|
public abstract void EndAllCalls();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public abstract void AcceptCall(CodecActiveCallItem item);
|
public abstract void AcceptCall(CodecActiveCallItem item);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public abstract void RejectCall(CodecActiveCallItem item);
|
public abstract void RejectCall(CodecActiveCallItem item);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public abstract void SendDtmf(string digit);
|
public abstract void SendDtmf(string digit);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
using System;
|
namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implements a common set of data about a codec
|
/// Implements a common set of data about a codec
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IAudioCodecInfo
|
public interface IAudioCodecInfo
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the codec information
|
||||||
|
/// </summary>
|
||||||
AudioCodecInfo CodecInfo { get; }
|
AudioCodecInfo CodecInfo { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,6 +16,9 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class AudioCodecInfo
|
public abstract class AudioCodecInfo
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the phone number
|
||||||
|
/// </summary>
|
||||||
public abstract string PhoneNumber { get; set; }
|
public abstract string PhoneNumber { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,17 @@
|
|||||||
using System;
|
using PepperDash.Essentials.Core;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
|
|
||||||
using PepperDash.Essentials.Core;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For rooms that have audio codec
|
/// For rooms that have audio codec
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IHasAudioCodec:IHasInCallFeedback
|
public interface IHasAudioCodec : IHasInCallFeedback
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the audio codec device
|
||||||
|
/// </summary>
|
||||||
AudioCodecBase AudioCodec { get; }
|
AudioCodecBase AudioCodec { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Make this more specific
|
|
||||||
/// </summary>
|
|
||||||
//List<PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem> ActiveCalls { get; }
|
//List<PepperDash.Essentials.Devices.Common.Codec.CodecActiveCallItem> ActiveCalls { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
|
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
@@ -17,6 +13,12 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class MockAC : AudioCodecBase
|
public class MockAC : AudioCodecBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for MockAC
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">Device key</param>
|
||||||
|
/// <param name="name">Device name</param>
|
||||||
|
/// <param name="props">MockAC properties configuration</param>
|
||||||
public MockAC(string key, string name, MockAcPropertiesConfig props)
|
public MockAC(string key, string name, MockAcPropertiesConfig props)
|
||||||
: base(key, name)
|
: base(key, name)
|
||||||
{
|
{
|
||||||
@@ -109,13 +111,10 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
|||||||
Debug.LogMessage(LogEventLevel.Debug, this, "BEEP BOOP SendDTMF: {0}", s);
|
Debug.LogMessage(LogEventLevel.Debug, this, "BEEP BOOP SendDTMF: {0}", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="url"></param>
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TestIncomingAudioCall method
|
/// TestIncomingAudioCall method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="number">Phone number to call from</param>
|
||||||
public void TestIncomingAudioCall(string number)
|
public void TestIncomingAudioCall(string number)
|
||||||
{
|
{
|
||||||
Debug.LogMessage(LogEventLevel.Debug, this, "TestIncomingAudioCall from {0}", number);
|
Debug.LogMessage(LogEventLevel.Debug, this, "TestIncomingAudioCall from {0}", number);
|
||||||
@@ -133,6 +132,7 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
|||||||
{
|
{
|
||||||
string _phoneNumber;
|
string _phoneNumber;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override string PhoneNumber
|
public override string PhoneNumber
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -151,6 +151,9 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class MockACFactory : EssentialsDeviceFactory<MockAC>
|
public class MockACFactory : EssentialsDeviceFactory<MockAC>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for MockACFactory
|
||||||
|
/// </summary>
|
||||||
public MockACFactory()
|
public MockACFactory()
|
||||||
{
|
{
|
||||||
TypeNames = new List<string>() { "mockac" };
|
TypeNames = new List<string>() { "mockac" };
|
||||||
|
|||||||
@@ -1,12 +1,4 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
||||||
{
|
{
|
||||||
@@ -15,10 +7,10 @@ namespace PepperDash.Essentials.Devices.Common.AudioCodec
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class MockAcPropertiesConfig
|
public class MockAcPropertiesConfig
|
||||||
{
|
{
|
||||||
[JsonProperty("phoneNumber")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the PhoneNumber
|
/// Gets or sets the PhoneNumber
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("phoneNumber")]
|
||||||
public string PhoneNumber { get; set; }
|
public string PhoneNumber { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,20 +3,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using System.Reflection;
|
|
||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using PepperDash.Essentials.Core.Devices;
|
|
||||||
using PepperDash.Essentials.Core.Config;
|
|
||||||
using PepperDash.Essentials.Core.Bridges;
|
using PepperDash.Essentials.Core.Bridges;
|
||||||
|
using PepperDash.Essentials.Core.Config;
|
||||||
|
using PepperDash.Essentials.Core.Devices;
|
||||||
using PepperDash.Essentials.Core.Presets;
|
using PepperDash.Essentials.Core.Presets;
|
||||||
using PepperDash.Essentials.Devices.Common.Codec;
|
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.Cameras
|
namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||||
@@ -26,31 +20,52 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public enum eCameraCapabilities
|
public enum eCameraCapabilities
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// No camera capabilities
|
||||||
|
/// </summary>
|
||||||
None = 0,
|
None = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// Camera supports pan movement
|
||||||
|
/// </summary>
|
||||||
Pan = 1,
|
Pan = 1,
|
||||||
Tilt = 2,
|
/// <summary>
|
||||||
|
/// Camera supports tilt movement
|
||||||
|
/// </summary>
|
||||||
|
Tilt = 2,
|
||||||
|
/// <summary>
|
||||||
|
/// Camera supports zoom functionality
|
||||||
|
/// </summary>
|
||||||
Zoom = 4,
|
Zoom = 4,
|
||||||
|
/// <summary>
|
||||||
|
/// Camera supports focus adjustment
|
||||||
|
/// </summary>
|
||||||
Focus = 8
|
Focus = 8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Abstract base class for camera devices that provides common camera functionality and capabilities
|
||||||
|
/// </summary>
|
||||||
public abstract class CameraBase : ReconfigurableDevice, IRoutingOutputs
|
public abstract class CameraBase : ReconfigurableDevice, IRoutingOutputs
|
||||||
{
|
{
|
||||||
[JsonProperty("controlMode", NullValueHandling = NullValueHandling.Ignore)]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the ControlMode
|
/// Gets or sets the ControlMode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("controlMode", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public eCameraControlMode ControlMode { get; protected set; }
|
public eCameraControlMode ControlMode { get; protected set; }
|
||||||
|
|
||||||
#region IRoutingOutputs Members
|
#region IRoutingOutputs Members
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the OutputPorts
|
/// Gets or sets the OutputPorts
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; protected set; }
|
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; protected set; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether this camera supports pan movement
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool CanPan
|
public bool CanPan
|
||||||
{
|
{
|
||||||
@@ -59,6 +74,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
return (Capabilities & eCameraCapabilities.Pan) == eCameraCapabilities.Pan;
|
return (Capabilities & eCameraCapabilities.Pan) == eCameraCapabilities.Pan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether this camera supports tilt movement
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool CanTilt
|
public bool CanTilt
|
||||||
{
|
{
|
||||||
@@ -67,6 +86,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
return (Capabilities & eCameraCapabilities.Tilt) == eCameraCapabilities.Tilt;
|
return (Capabilities & eCameraCapabilities.Tilt) == eCameraCapabilities.Tilt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether this camera supports zoom functionality
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool CanZoom
|
public bool CanZoom
|
||||||
{
|
{
|
||||||
@@ -75,6 +98,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
return (Capabilities & eCameraCapabilities.Zoom) == eCameraCapabilities.Zoom;
|
return (Capabilities & eCameraCapabilities.Zoom) == eCameraCapabilities.Zoom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether this camera supports focus adjustment
|
||||||
|
/// </summary>
|
||||||
[JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public bool CanFocus
|
public bool CanFocus
|
||||||
{
|
{
|
||||||
@@ -84,23 +111,42 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A bitmasked value to indicate the movement capabilites of this camera
|
/// <summary>
|
||||||
|
/// Gets or sets a bitmasked value to indicate the movement capabilities of this camera
|
||||||
|
/// </summary>
|
||||||
protected eCameraCapabilities Capabilities { get; set; }
|
protected eCameraCapabilities Capabilities { get; set; }
|
||||||
|
|
||||||
protected CameraBase(DeviceConfig config) : base(config)
|
/// <summary>
|
||||||
{
|
/// Initializes a new instance of the CameraBase class with the specified device configuration
|
||||||
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
|
/// </summary>
|
||||||
|
/// <param name="config">The device configuration</param>
|
||||||
ControlMode = eCameraControlMode.Manual;
|
protected CameraBase(DeviceConfig config) : base(config)
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected CameraBase(string key, string name) :
|
|
||||||
this (new DeviceConfig{Name = name, Key = key})
|
|
||||||
{
|
{
|
||||||
|
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
|
||||||
|
|
||||||
|
ControlMode = eCameraControlMode.Manual;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the CameraBase class with the specified key and name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique key for this camera device</param>
|
||||||
|
/// <param name="name">The friendly name for this camera device</param>
|
||||||
|
protected CameraBase(string key, string name) :
|
||||||
|
this(new DeviceConfig { Name = name, Key = key })
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Links the camera device to the API bridge for control and feedback
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cameraDevice">The camera device to link</param>
|
||||||
|
/// <param name="trilist">The trilist for communication</param>
|
||||||
|
/// <param name="joinStart">The starting join number for the camera controls</param>
|
||||||
|
/// <param name="joinMapKey">The join map key for custom join mappings</param>
|
||||||
|
/// <param name="bridge">The EiscApiAdvanced bridge for advanced join mapping</param>
|
||||||
protected void LinkCameraToApi(CameraBase cameraDevice, BasicTriList trilist, uint joinStart, string joinMapKey,
|
protected void LinkCameraToApi(CameraBase cameraDevice, BasicTriList trilist, uint joinStart, string joinMapKey,
|
||||||
EiscApiAdvanced bridge)
|
EiscApiAdvanced bridge)
|
||||||
{
|
{
|
||||||
@@ -240,13 +286,13 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
{
|
{
|
||||||
int tempNum = i;
|
int tempNum = i;
|
||||||
|
|
||||||
trilist.SetSigTrueAction((ushort) (joinMap.PresetRecallStart.JoinNumber + tempNum), () =>
|
trilist.SetSigTrueAction((ushort)(joinMap.PresetRecallStart.JoinNumber + tempNum), () =>
|
||||||
{
|
{
|
||||||
presetsCamera.PresetSelect(tempNum);
|
presetsCamera.PresetSelect(tempNum);
|
||||||
});
|
});
|
||||||
trilist.SetSigTrueAction((ushort) (joinMap.PresetSaveStart.JoinNumber + tempNum), () =>
|
trilist.SetSigTrueAction((ushort)(joinMap.PresetSaveStart.JoinNumber + tempNum), () =>
|
||||||
{
|
{
|
||||||
var label = trilist.GetString((ushort) (joinMap.PresetLabelStart.JoinNumber + tempNum));
|
var label = trilist.GetString((ushort)(joinMap.PresetLabelStart.JoinNumber + tempNum));
|
||||||
|
|
||||||
presetsCamera.PresetStore(tempNum, label);
|
presetsCamera.PresetStore(tempNum, label);
|
||||||
});
|
});
|
||||||
@@ -277,7 +323,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
trilist.SetString((ushort)(joinMap.PresetLabelStart.JoinNumber + tempNum), label);
|
trilist.SetString((ushort)(joinMap.PresetLabelStart.JoinNumber + tempNum), label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -285,6 +331,13 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CameraPreset : PresetBase
|
public class CameraPreset : PresetBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the CameraPreset class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The preset ID</param>
|
||||||
|
/// <param name="description">The preset description</param>
|
||||||
|
/// <param name="isDefined">Whether the preset is defined</param>
|
||||||
|
/// <param name="isDefinable">Whether the preset can be defined</param>
|
||||||
public CameraPreset(int id, string description, bool isDefined, bool isDefinable)
|
public CameraPreset(int id, string description, bool isDefined, bool isDefinable)
|
||||||
: base(id, description, isDefined, isDefinable)
|
: base(id, description, isDefined, isDefinable)
|
||||||
{
|
{
|
||||||
@@ -293,37 +346,37 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a CameraPropertiesConfig
|
/// Represents a CameraPropertiesConfig
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CameraPropertiesConfig
|
public class CameraPropertiesConfig
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the CommunicationMonitorProperties
|
/// Gets or sets the CommunicationMonitorProperties
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Control
|
/// Gets or sets the Control
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ControlPropertiesConfig Control { get; set; }
|
public ControlPropertiesConfig Control { get; set; }
|
||||||
|
|
||||||
[JsonProperty("supportsAutoMode")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the SupportsAutoMode
|
/// Gets or sets the SupportsAutoMode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("supportsAutoMode")]
|
||||||
public bool SupportsAutoMode { get; set; }
|
public bool SupportsAutoMode { get; set; }
|
||||||
|
|
||||||
[JsonProperty("supportsOffMode")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the SupportsOffMode
|
/// Gets or sets the SupportsOffMode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("supportsOffMode")]
|
||||||
public bool SupportsOffMode { get; set; }
|
public bool SupportsOffMode { get; set; }
|
||||||
|
|
||||||
[JsonProperty("presets")]
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Presets
|
/// Gets or sets the Presets
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("presets")]
|
||||||
public List<CameraPreset> Presets { get; set; }
|
public List<CameraPreset> Presets { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,326 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using PepperDash.Core;
|
|
||||||
using PepperDash.Essentials.Core;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.Cameras
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Enum for camera control modes
|
|
||||||
/// </summary>
|
|
||||||
public enum eCameraControlMode
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Manual control mode, where the camera is controlled directly by the user or system
|
|
||||||
/// </summary>
|
|
||||||
Manual = 0,
|
|
||||||
/// <summary>
|
|
||||||
/// Off control mode, where the camera is turned off or disabled
|
|
||||||
/// </summary>
|
|
||||||
Off,
|
|
||||||
/// <summary>
|
|
||||||
/// Auto control mode, where the camera automatically adjusts settings based on the environment or conditions
|
|
||||||
/// </summary>
|
|
||||||
Auto
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interface for devices that have cameras
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasCameras : IKeyName
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Event that is raised when a camera is selected
|
|
||||||
/// </summary>
|
|
||||||
event EventHandler<CameraSelectedEventArgs> CameraSelected;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// List of cameras on the device. This should be a list of CameraBase objects
|
|
||||||
/// </summary>
|
|
||||||
List<CameraBase> Cameras { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The currently selected camera. This should be a CameraBase object
|
|
||||||
/// </summary>
|
|
||||||
CameraBase SelectedCamera { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Feedback that indicates the currently selected camera
|
|
||||||
/// </summary>
|
|
||||||
StringFeedback SelectedCameraFeedback { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Selects a camera from the list of available cameras based on the provided key.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key">The unique identifier or name of the camera to select.</param>
|
|
||||||
void SelectCamera(string key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the contract for IHasCodecCameras
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasCodecCameras : IHasCameras, IHasFarEndCameraControl
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// To be implmented on codecs that can disable their camera(s) to blank the near end video
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasCameraOff
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Feedback that indicates whether the camera is off
|
|
||||||
/// </summary>
|
|
||||||
BoolFeedback CameraIsOffFeedback { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Turns the camera off, blanking the near end video
|
|
||||||
/// </summary>
|
|
||||||
void CameraOff();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Describes the ability to mute and unmute camera video
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasCameraMute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Feedback that indicates whether the camera is muted
|
|
||||||
/// </summary>
|
|
||||||
BoolFeedback CameraIsMutedFeedback { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Mutes the camera video, preventing it from being sent to the far end
|
|
||||||
/// </summary>
|
|
||||||
void CameraMuteOn();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Unmutes the camera video, allowing it to be sent to the far end
|
|
||||||
/// </summary>
|
|
||||||
void CameraMuteOff();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Toggles the camera mute state. If the camera is muted, it will be unmuted, and vice versa.
|
|
||||||
/// </summary>
|
|
||||||
void CameraMuteToggle();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interface for devices that can mute and unmute their camera video, with an event for unmute requests
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasCameraMuteWithUnmuteReqeust : IHasCameraMute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Event that is raised when a video unmute is requested, typically by the far end
|
|
||||||
/// </summary>
|
|
||||||
event EventHandler VideoUnmuteRequested;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event arguments for the CameraSelected event
|
|
||||||
/// </summary>
|
|
||||||
public class CameraSelectedEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the SelectedCamera
|
|
||||||
/// </summary>
|
|
||||||
public CameraBase SelectedCamera { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor for CameraSelectedEventArgs
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="camera"></param>
|
|
||||||
public CameraSelectedEventArgs(CameraBase camera)
|
|
||||||
{
|
|
||||||
SelectedCamera = camera;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interface for devices that have a far end camera control
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasFarEndCameraControl
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the far end camera, which is typically a CameraBase object that represents the camera at the far end of a call
|
|
||||||
/// </summary>
|
|
||||||
CameraBase FarEndCamera { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Feedback that indicates whether the far end camera is being controlled
|
|
||||||
/// </summary>
|
|
||||||
BoolFeedback ControllingFarEndCameraFeedback { get; }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the contract for IAmFarEndCamera
|
|
||||||
/// </summary>
|
|
||||||
public interface IAmFarEndCamera
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interface for devices that have camera controls
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasCameraControls
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the contract for IHasCameraPtzControl
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasCameraPtzControl : IHasCameraPanControl, IHasCameraTiltControl, IHasCameraZoomControl
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Resets the camera position
|
|
||||||
/// </summary>
|
|
||||||
void PositionHome();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interface for camera pan control
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasCameraPanControl : IHasCameraControls
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Pans the camera left
|
|
||||||
/// </summary>
|
|
||||||
void PanLeft();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pans the camera right
|
|
||||||
/// </summary>
|
|
||||||
void PanRight();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Stops the camera pan movement
|
|
||||||
/// </summary>
|
|
||||||
void PanStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the contract for IHasCameraTiltControl
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasCameraTiltControl : IHasCameraControls
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Tilts the camera down
|
|
||||||
/// </summary>
|
|
||||||
void TiltDown();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tilts the camera up
|
|
||||||
/// </summary>
|
|
||||||
void TiltUp();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Stops the camera tilt movement
|
|
||||||
/// </summary>
|
|
||||||
void TiltStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the contract for IHasCameraZoomControl
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasCameraZoomControl : IHasCameraControls
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Zooms the camera in
|
|
||||||
/// </summary>
|
|
||||||
void ZoomIn();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Zooms the camera out
|
|
||||||
/// </summary>
|
|
||||||
void ZoomOut();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Stops the camera zoom movement
|
|
||||||
/// </summary>
|
|
||||||
void ZoomStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the contract for IHasCameraFocusControl
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasCameraFocusControl : IHasCameraControls
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Focuses the camera near
|
|
||||||
/// </summary>
|
|
||||||
void FocusNear();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Focuses the camera far
|
|
||||||
/// </summary>
|
|
||||||
void FocusFar();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Stops the camera focus movement
|
|
||||||
/// </summary>
|
|
||||||
void FocusStop();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Triggers the camera's auto focus functionality, if available.
|
|
||||||
/// </summary>
|
|
||||||
void TriggerAutoFocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interface for devices that have auto focus mode control
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasAutoFocusMode
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the focus mode to auto or manual, or toggles between them.
|
|
||||||
/// </summary>
|
|
||||||
void SetFocusModeAuto();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the focus mode to manual, allowing for manual focus adjustments.
|
|
||||||
/// </summary>
|
|
||||||
void SetFocusModeManual();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Toggles the focus mode between auto and manual.
|
|
||||||
/// </summary>
|
|
||||||
void ToggleFocusMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interface for devices that have camera auto mode control
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasCameraAutoMode : IHasCameraControls
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Enables or disables the camera's auto mode, which may include automatic adjustments for focus, exposure, and other settings.
|
|
||||||
/// </summary>
|
|
||||||
void CameraAutoModeOn();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disables the camera's auto mode, allowing for manual control of camera settings.
|
|
||||||
/// </summary>
|
|
||||||
void CameraAutoModeOff();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Toggles the camera's auto mode state. If the camera is in auto mode, it will switch to manual mode, and vice versa.
|
|
||||||
/// </summary>
|
|
||||||
void CameraAutoModeToggle();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Feedback that indicates whether the camera's auto mode is currently enabled.
|
|
||||||
/// </summary>
|
|
||||||
BoolFeedback CameraAutoModeIsOnFeedback { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -3,38 +3,33 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
using Crestron.SimplSharpPro.DeviceSupport;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using PepperDash.Core;
|
using PepperDash.Core;
|
||||||
using PepperDash.Essentials.Core;
|
using PepperDash.Essentials.Core;
|
||||||
using PepperDash.Essentials.Core.Bridges;
|
using PepperDash.Essentials.Core.Bridges;
|
||||||
using PepperDash.Essentials.Core.Config;
|
using PepperDash.Essentials.Core.Config;
|
||||||
using PepperDash.Essentials.Devices.Common.Codec;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.Cameras
|
namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a CameraVisca
|
/// Represents a CameraVisca
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IHasPowerControlWithFeedback, IBridgeAdvanced, IHasCameraFocusControl, IHasAutoFocusMode
|
public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IHasPowerControlWithFeedback, IBridgeAdvanced, IHasCameraFocusControl, IHasAutoFocusMode
|
||||||
{
|
{
|
||||||
private readonly CameraViscaPropertiesConfig PropertiesConfig;
|
private readonly CameraViscaPropertiesConfig PropertiesConfig;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Communication
|
/// Gets or sets the Communication
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IBasicCommunication Communication { get; private set; }
|
public IBasicCommunication Communication { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the CommunicationMonitor
|
/// Gets or sets the CommunicationMonitor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to store the actions to parse inquiry responses as the inquiries are sent
|
/// Used to store the actions to parse inquiry responses as the inquiries are sent
|
||||||
@@ -45,20 +40,41 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
/// Camera ID (Default 1)
|
/// Camera ID (Default 1)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte ID = 0x01;
|
public byte ID = 0x01;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Response ID used for VISCA communication
|
||||||
|
/// </summary>
|
||||||
public byte ResponseID;
|
public byte ResponseID;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Slow speed value for pan movement
|
||||||
|
/// </summary>
|
||||||
|
public byte PanSpeedSlow = 0x10;
|
||||||
|
|
||||||
public byte PanSpeedSlow = 0x10;
|
/// <summary>
|
||||||
public byte TiltSpeedSlow = 0x10;
|
/// Slow speed value for tilt movement
|
||||||
|
/// </summary>
|
||||||
|
public byte TiltSpeedSlow = 0x10;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fast speed value for pan movement
|
||||||
|
/// </summary>
|
||||||
public byte PanSpeedFast = 0x13;
|
public byte PanSpeedFast = 0x13;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fast speed value for tilt movement
|
||||||
|
/// </summary>
|
||||||
public byte TiltSpeedFast = 0x13;
|
public byte TiltSpeedFast = 0x13;
|
||||||
|
|
||||||
// private bool IsMoving;
|
// private bool IsMoving;
|
||||||
private bool IsZooming;
|
private bool IsZooming;
|
||||||
|
|
||||||
bool _powerIsOn;
|
bool _powerIsOn;
|
||||||
public bool PowerIsOn
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether the camera power is on
|
||||||
|
/// </summary>
|
||||||
|
public bool PowerIsOn
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@@ -87,12 +103,23 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
|
|
||||||
long FastSpeedHoldTimeMs = 2000;
|
long FastSpeedHoldTimeMs = 2000;
|
||||||
|
|
||||||
byte[] IncomingBuffer = new byte[] { };
|
byte[] IncomingBuffer = new byte[] { };
|
||||||
public BoolFeedback PowerIsOnFeedback { get; private set; }
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Feedback indicating whether the camera power is on
|
||||||
|
/// </summary>
|
||||||
|
public BoolFeedback PowerIsOnFeedback { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the CameraVisca class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The unique key for this camera device</param>
|
||||||
|
/// <param name="name">The friendly name for this camera device</param>
|
||||||
|
/// <param name="comm">The communication interface for VISCA protocol</param>
|
||||||
|
/// <param name="props">The camera properties configuration</param>
|
||||||
public CameraVisca(string key, string name, IBasicCommunication comm, CameraViscaPropertiesConfig props) :
|
public CameraVisca(string key, string name, IBasicCommunication comm, CameraViscaPropertiesConfig props) :
|
||||||
base(key, name)
|
base(key, name)
|
||||||
{
|
{
|
||||||
InquiryResponseQueue = new CrestronQueue<Action<byte[]>>(15);
|
InquiryResponseQueue = new CrestronQueue<Action<byte[]>>(15);
|
||||||
|
|
||||||
Presets = props.Presets;
|
Presets = props.Presets;
|
||||||
@@ -107,8 +134,8 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
OutputPorts.Add(new RoutingOutputPort("videoOut", eRoutingSignalType.Video, eRoutingPortConnectionType.None, null, this, true));
|
OutputPorts.Add(new RoutingOutputPort("videoOut", eRoutingSignalType.Video, eRoutingPortConnectionType.None, null, this, true));
|
||||||
|
|
||||||
// Default to all capabilties
|
// Default to all capabilties
|
||||||
Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom | eCameraCapabilities.Focus;
|
Capabilities = eCameraCapabilities.Pan | eCameraCapabilities.Tilt | eCameraCapabilities.Zoom | eCameraCapabilities.Focus;
|
||||||
|
|
||||||
Communication = comm;
|
Communication = comm;
|
||||||
if (comm is ISocketStatus socket)
|
if (comm is ISocketStatus socket)
|
||||||
{
|
{
|
||||||
@@ -121,19 +148,19 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
}
|
}
|
||||||
|
|
||||||
Communication.BytesReceived += new EventHandler<GenericCommMethodReceiveBytesArgs>(Communication_BytesReceived);
|
Communication.BytesReceived += new EventHandler<GenericCommMethodReceiveBytesArgs>(Communication_BytesReceived);
|
||||||
PowerIsOnFeedback = new BoolFeedback(() => { return PowerIsOn; });
|
PowerIsOnFeedback = new BoolFeedback("powerIsOn", () => { return PowerIsOn; });
|
||||||
CameraIsOffFeedback = new BoolFeedback(() => { return !PowerIsOn; });
|
CameraIsOffFeedback = new BoolFeedback("cameraIsOff", () => { return !PowerIsOn; });
|
||||||
|
|
||||||
if (props.CommunicationMonitorProperties != null)
|
if (props.CommunicationMonitorProperties != null)
|
||||||
{
|
{
|
||||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties);
|
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 20000, 120000, 300000, "\x81\x09\x04\x00\xFF");
|
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 20000, 120000, 300000, "\x81\x09\x04\x00\xFF");
|
||||||
}
|
}
|
||||||
DeviceManager.AddDevice(CommunicationMonitor);
|
DeviceManager.AddDevice(CommunicationMonitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -165,57 +192,57 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// CustomActivate method
|
/// CustomActivate method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool CustomActivate()
|
public override bool CustomActivate()
|
||||||
{
|
{
|
||||||
Communication.Connect();
|
Communication.Connect();
|
||||||
|
|
||||||
|
|
||||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.LogMessage(LogEventLevel.Verbose, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
|
||||||
CommunicationMonitor.Start();
|
|
||||||
|
|
||||||
|
|
||||||
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
CommunicationMonitor.StatusChange += (o, a) => { Debug.LogMessage(LogEventLevel.Verbose, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
||||||
return true;
|
CommunicationMonitor.Start();
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// LinkToApi method
|
|
||||||
/// </summary>
|
|
||||||
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
|
|
||||||
{
|
|
||||||
LinkCameraToApi(this, trilist, joinStart, joinMapKey, bridge);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
||||||
{
|
return true;
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
|
}
|
||||||
|
|
||||||
if (e.Client.IsConnected)
|
/// <summary>
|
||||||
{
|
/// LinkToApi method
|
||||||
|
/// </summary>
|
||||||
}
|
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
|
||||||
else
|
{
|
||||||
{
|
LinkCameraToApi(this, trilist, joinStart, joinMapKey, bridge);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
void Socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
||||||
}
|
{
|
||||||
|
Debug.LogMessage(LogEventLevel.Verbose, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
|
||||||
|
|
||||||
void SendBytes(byte[] b)
|
if (e.Client.IsConnected)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
|
|
||||||
Debug.LogMessage(LogEventLevel.Verbose, this, "Sending:{0}", ComTextHelper.GetEscapedText(b));
|
|
||||||
|
|
||||||
Communication.SendBytes(b);
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
|
||||||
void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e)
|
}
|
||||||
{
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SendBytes(byte[] b)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1
|
||||||
|
Debug.LogMessage(LogEventLevel.Verbose, this, "Sending:{0}", ComTextHelper.GetEscapedText(b));
|
||||||
|
|
||||||
|
Communication.SendBytes(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e)
|
||||||
|
{
|
||||||
var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length];
|
var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length];
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -355,10 +382,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends a pan/tilt command. If the command is not for fastSpeed then it starts a timer to initiate fast speed.
|
/// Sends a pan/tilt command. If the command is not for fastSpeed then it starts a timer to initiate fast speed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cmd"></param>
|
/// <param name="cmd">The VISCA command to send</param>
|
||||||
/// <param name="fastSpeed"></param>
|
/// <param name="fastSpeedEnabled">Whether fast speed is enabled for this command</param>
|
||||||
private void SendPanTiltCommand (byte[] cmd, bool fastSpeedEnabled)
|
private void SendPanTiltCommand(byte[] cmd, bool fastSpeedEnabled)
|
||||||
{
|
{
|
||||||
SendBytes(GetPanTiltCommand(cmd, fastSpeedEnabled));
|
SendBytes(GetPanTiltCommand(cmd, fastSpeedEnabled));
|
||||||
|
|
||||||
if (!fastSpeedEnabled)
|
if (!fastSpeedEnabled)
|
||||||
@@ -372,7 +399,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
SpeedTimer = new CTimer((o) => SendPanTiltCommand(GetPanTiltCommand(cmd, true), true), FastSpeedHoldTimeMs);
|
SpeedTimer = new CTimer((o) => SendPanTiltCommand(GetPanTiltCommand(cmd, true), true), FastSpeedHoldTimeMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StopSpeedTimer()
|
private void StopSpeedTimer()
|
||||||
{
|
{
|
||||||
@@ -381,7 +408,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
SpeedTimer.Stop();
|
SpeedTimer.Stop();
|
||||||
SpeedTimer.Dispose();
|
SpeedTimer.Dispose();
|
||||||
SpeedTimer = null;
|
SpeedTimer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -424,14 +451,14 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
InquiryResponseQueue.Enqueue(HandlePowerResponse);
|
InquiryResponseQueue.Enqueue(HandlePowerResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// PowerOn method
|
/// PowerOn method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void PowerOn()
|
public void PowerOn()
|
||||||
{
|
{
|
||||||
SendBytes(new byte[] { ID, 0x01, 0x04, 0x00, 0x02, 0xFF });
|
SendBytes(new byte[] { ID, 0x01, 0x04, 0x00, 0x02, 0xFF });
|
||||||
SendPowerQuery();
|
SendPowerQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandlePowerResponse(byte[] response)
|
void HandlePowerResponse(byte[] response)
|
||||||
{
|
{
|
||||||
@@ -450,12 +477,12 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// PowerOff method
|
/// PowerOff method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void PowerOff()
|
public void PowerOff()
|
||||||
{
|
{
|
||||||
SendBytes(new byte[] {ID, 0x01, 0x04, 0x00, 0x03, 0xFF});
|
SendBytes(new byte[] { ID, 0x01, 0x04, 0x00, 0x03, 0xFF });
|
||||||
SendPowerQuery();
|
SendPowerQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,22 +497,22 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
PowerOn();
|
PowerOn();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// PanLeft method
|
/// PanLeft method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void PanLeft()
|
public void PanLeft()
|
||||||
{
|
{
|
||||||
SendPanTiltCommand(new byte[] {0x01, 0x03}, false);
|
SendPanTiltCommand(new byte[] { 0x01, 0x03 }, false);
|
||||||
// IsMoving = true;
|
// IsMoving = true;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// PanRight method
|
/// PanRight method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void PanRight()
|
public void PanRight()
|
||||||
{
|
{
|
||||||
SendPanTiltCommand(new byte[] { 0x02, 0x03 }, false);
|
SendPanTiltCommand(new byte[] { 0x02, 0x03 }, false);
|
||||||
// IsMoving = true;
|
// IsMoving = true;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// PanStop method
|
/// PanStop method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -493,22 +520,22 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
{
|
{
|
||||||
Stop();
|
Stop();
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TiltDown method
|
/// TiltDown method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void TiltDown()
|
public void TiltDown()
|
||||||
{
|
{
|
||||||
SendPanTiltCommand(new byte[] { 0x03, 0x02 }, false);
|
SendPanTiltCommand(new byte[] { 0x03, 0x02 }, false);
|
||||||
// IsMoving = true;
|
// IsMoving = true;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TiltUp method
|
/// TiltUp method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void TiltUp()
|
public void TiltUp()
|
||||||
{
|
{
|
||||||
SendPanTiltCommand(new byte[] { 0x03, 0x01 }, false);
|
SendPanTiltCommand(new byte[] { 0x03, 0x01 }, false);
|
||||||
// IsMoving = true;
|
// IsMoving = true;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TiltStop method
|
/// TiltStop method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -517,28 +544,28 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
Stop();
|
Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendZoomCommand (byte cmd)
|
private void SendZoomCommand(byte cmd)
|
||||||
{
|
{
|
||||||
SendBytes(new byte[] {ID, 0x01, 0x04, 0x07, cmd, 0xFF} );
|
SendBytes(new byte[] { ID, 0x01, 0x04, 0x07, cmd, 0xFF });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ZoomIn method
|
/// ZoomIn method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ZoomIn()
|
public void ZoomIn()
|
||||||
{
|
{
|
||||||
SendZoomCommand(ZoomInCmd);
|
SendZoomCommand(ZoomInCmd);
|
||||||
IsZooming = true;
|
IsZooming = true;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ZoomOut method
|
/// ZoomOut method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ZoomOut()
|
public void ZoomOut()
|
||||||
{
|
{
|
||||||
SendZoomCommand(ZoomOutCmd);
|
SendZoomCommand(ZoomOutCmd);
|
||||||
IsZooming = true;
|
IsZooming = true;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ZoomStop method
|
/// ZoomStop method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -547,23 +574,23 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
Stop();
|
Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stop method
|
/// Stop method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
if (IsZooming)
|
if (IsZooming)
|
||||||
{
|
{
|
||||||
SendZoomCommand(ZoomStopCmd);
|
SendZoomCommand(ZoomStopCmd);
|
||||||
IsZooming = false;
|
IsZooming = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
StopSpeedTimer();
|
StopSpeedTimer();
|
||||||
SendPanTiltCommand(new byte[] { 0x03, 0x03 }, false);
|
SendPanTiltCommand(new byte[] { 0x03, 0x03 }, false);
|
||||||
// IsMoving = false;
|
// IsMoving = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// PositionHome method
|
/// PositionHome method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -572,33 +599,39 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
SendBytes(new byte[] { ID, 0x01, 0x06, 0x02, PanSpeedFast, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF });
|
SendBytes(new byte[] { ID, 0x01, 0x06, 0x02, PanSpeedFast, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF });
|
||||||
SendBytes(new byte[] { ID, 0x01, 0x04, 0x47, 0x00, 0x00, 0x00, 0x00, 0xFF });
|
SendBytes(new byte[] { ID, 0x01, 0x04, 0x47, 0x00, 0x00, 0x00, 0x00, 0xFF });
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// RecallPreset method
|
/// RecallPreset method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void RecallPreset(int presetNumber)
|
public void RecallPreset(int presetNumber)
|
||||||
{
|
{
|
||||||
SendBytes(new byte[] {ID, 0x01, 0x04, 0x3F, 0x02, (byte)presetNumber, 0xFF} );
|
SendBytes(new byte[] { ID, 0x01, 0x04, 0x3F, 0x02, (byte)presetNumber, 0xFF });
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SavePreset method
|
/// SavePreset method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SavePreset(int presetNumber)
|
public void SavePreset(int presetNumber)
|
||||||
{
|
{
|
||||||
SendBytes(new byte[] { ID, 0x01, 0x04, 0x3F, 0x01, (byte)presetNumber, 0xFF });
|
SendBytes(new byte[] { ID, 0x01, 0x04, 0x3F, 0x01, (byte)presetNumber, 0xFF });
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IHasCameraPresets Members
|
#region IHasCameraPresets Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event that is raised when the presets list has changed
|
||||||
|
/// </summary>
|
||||||
public event EventHandler<EventArgs> PresetsListHasChanged;
|
public event EventHandler<EventArgs> PresetsListHasChanged;
|
||||||
|
|
||||||
protected void OnPresetsListHasChanged()
|
/// <summary>
|
||||||
{
|
/// Raises the PresetsListHasChanged event
|
||||||
var handler = PresetsListHasChanged;
|
/// </summary>
|
||||||
if (handler == null)
|
protected void OnPresetsListHasChanged()
|
||||||
return;
|
{
|
||||||
|
var handler = PresetsListHasChanged;
|
||||||
|
if (handler == null)
|
||||||
|
return;
|
||||||
|
|
||||||
handler.Invoke(this, EventArgs.Empty);
|
handler.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Presets
|
/// Gets or sets the Presets
|
||||||
@@ -741,6 +774,9 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CameraViscaFactory : EssentialsDeviceFactory<CameraVisca>
|
public class CameraViscaFactory : EssentialsDeviceFactory<CameraVisca>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the CameraViscaFactory class
|
||||||
|
/// </summary>
|
||||||
public CameraViscaFactory()
|
public CameraViscaFactory()
|
||||||
{
|
{
|
||||||
TypeNames = new List<string>() { "cameravisca" };
|
TypeNames = new List<string>() { "cameravisca" };
|
||||||
@@ -768,11 +804,9 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Control ID of the camera (1-7)
|
/// Control ID of the camera (1-7)
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("id")]
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the Id
|
/// Gets or sets the Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[JsonProperty("id")]
|
||||||
public uint Id { get; set; }
|
public uint Id { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -790,7 +824,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Slow tilt speed (0-18)
|
/// Slow tilt speed (0-18)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("tiltSpeedSlow")]
|
[JsonProperty("tiltSpeedSlow")]
|
||||||
public uint TiltSpeedSlow { get; set; }
|
public uint TiltSpeedSlow { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.Cameras
|
namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||||
{
|
{
|
||||||
@@ -11,12 +8,27 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IHasCameraPresets
|
public interface IHasCameraPresets
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Event that is raised when the presets list has changed
|
||||||
|
/// </summary>
|
||||||
event EventHandler<EventArgs> PresetsListHasChanged;
|
event EventHandler<EventArgs> PresetsListHasChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of camera presets
|
||||||
|
/// </summary>
|
||||||
List<CameraPreset> Presets { get; }
|
List<CameraPreset> Presets { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Selects the specified preset
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="preset">The preset number to select</param>
|
||||||
void PresetSelect(int preset);
|
void PresetSelect(int preset);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stores a preset at the specified location with the given description
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="preset">The preset number to store</param>
|
||||||
|
/// <param name="description">The description for the preset</param>
|
||||||
void PresetStore(int preset, string description);
|
void PresetStore(int preset, string description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Event arguments for the CameraSelected event
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("Use CameraSelectedEventArgs<T> instead. This class will be removed in a future version")]
|
||||||
|
public class CameraSelectedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
/// Gets or sets the SelectedCamera
|
||||||
|
/// </summary>
|
||||||
|
public CameraBase SelectedCamera { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for CameraSelectedEventArgs
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="camera"></param>
|
||||||
|
public CameraSelectedEventArgs(CameraBase camera)
|
||||||
|
{
|
||||||
|
SelectedCamera = camera;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event arguments for the CameraSelected event
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
public class CameraSelectedEventArgs<T> : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the SelectedCamera
|
||||||
|
/// </summary>
|
||||||
|
public T SelectedCamera { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for CameraSelectedEventArgs
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="camera"></param>
|
||||||
|
public CameraSelectedEventArgs(T camera)
|
||||||
|
{
|
||||||
|
SelectedCamera = camera;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using PepperDash.Core;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the contract for IAmFarEndCamera
|
||||||
|
/// </summary>
|
||||||
|
public interface IAmFarEndCamera : IKeyName
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using PepperDash.Core;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for camera capabilities
|
||||||
|
/// </summary>
|
||||||
|
public interface ICameraCapabilities: IKeyName
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera can pan
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
bool CanPan { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera can tilt
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
bool CanTilt { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera can zoom
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
bool CanZoom { get; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera can focus
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
bool CanFocus { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates the capabilities of a camera
|
||||||
|
/// </summary>
|
||||||
|
public class CameraCapabilities : ICameraCapabilities
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unique Key
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Isn't it obvious :)
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera can pan
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public bool CanPan { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera can tilt
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public bool CanTilt { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera can zoom
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public bool CanZoom { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the camera can focus
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public bool CanFocus { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for devices that have auto focus mode control
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasAutoFocusMode : IHasCameraControls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the focus mode to auto or manual, or toggles between them.
|
||||||
|
/// </summary>
|
||||||
|
void SetFocusModeAuto();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the focus mode to manual, allowing for manual focus adjustments.
|
||||||
|
/// </summary>
|
||||||
|
void SetFocusModeManual();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Toggles the focus mode between auto and manual.
|
||||||
|
/// </summary>
|
||||||
|
void ToggleFocusMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using PepperDash.Essentials.Core;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for devices that have camera auto mode control
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasCameraAutoMode : IHasCameraControls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Enables or disables the camera's auto mode, which may include automatic adjustments for focus, exposure, and other settings.
|
||||||
|
/// </summary>
|
||||||
|
void CameraAutoModeOn();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disables the camera's auto mode, allowing for manual control of camera settings.
|
||||||
|
/// </summary>
|
||||||
|
void CameraAutoModeOff();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Toggles the camera's auto mode state. If the camera is in auto mode, it will switch to manual mode, and vice versa.
|
||||||
|
/// </summary>
|
||||||
|
void CameraAutoModeToggle();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Feedback that indicates whether the camera's auto mode is currently enabled.
|
||||||
|
/// </summary>
|
||||||
|
BoolFeedback CameraAutoModeIsOnFeedback { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using PepperDash.Core;
|
||||||
|
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for devices that have camera controls
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasCameraControls : IKeyName
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the contract for IHasCameraFocusControl
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasCameraFocusControl : IHasCameraControls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Focuses the camera near
|
||||||
|
/// </summary>
|
||||||
|
void FocusNear();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Focuses the camera far
|
||||||
|
/// </summary>
|
||||||
|
void FocusFar();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stops the camera focus movement
|
||||||
|
/// </summary>
|
||||||
|
void FocusStop();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Triggers the camera's auto focus functionality, if available.
|
||||||
|
/// </summary>
|
||||||
|
void TriggerAutoFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using PepperDash.Core;
|
||||||
|
using PepperDash.Essentials.Core;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the ability to mute and unmute camera video
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasCameraMute : IKeyName
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Feedback that indicates whether the camera is muted
|
||||||
|
/// </summary>
|
||||||
|
BoolFeedback CameraIsMutedFeedback { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mutes the camera video, preventing it from being sent to the far end
|
||||||
|
/// </summary>
|
||||||
|
void CameraMuteOn();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unmutes the camera video, allowing it to be sent to the far end
|
||||||
|
/// </summary>
|
||||||
|
void CameraMuteOff();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Toggles the camera mute state. If the camera is muted, it will be unmuted, and vice versa.
|
||||||
|
/// </summary>
|
||||||
|
void CameraMuteToggle();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for devices that can mute and unmute their camera video, with an event for unmute requests
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasCameraMuteWithUnmuteReqeust : IHasCameraMute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Event that is raised when a video unmute is requested, typically by the far end
|
||||||
|
/// </summary>
|
||||||
|
event EventHandler VideoUnmuteRequested;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using PepperDash.Essentials.Core;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.Devices.Common.Cameras
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// To be implmented on codecs that can disable their camera(s) to blank the near end video
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasCameraOff : IHasCameraControls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Feedback that indicates whether the camera is off
|
||||||
|
/// </summary>
|
||||||
|
BoolFeedback CameraIsOffFeedback { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Turns the camera off, blanking the near end video
|
||||||
|
/// </summary>
|
||||||
|
void CameraOff();
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user