mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-04 15:25:11 +00:00
When Essentials moved to using `System.Reflection` instead of the Crestron classes, there were some leftover `GetType` calls that were no longer necessary. These extra calls were preventing things from getting the correct type. Join Map printing was also fixed to print out in an actual readable fashion.
425 lines
15 KiB
C#
425 lines
15 KiB
C#
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using Crestron.SimplSharp;
|
|
using System.Reflection;
|
|
using Crestron.SimplSharpPro;
|
|
using Crestron.SimplSharpPro.DeviceSupport;
|
|
using Crestron.SimplSharpPro.EthernetCommunication;
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
using PepperDash.Core;
|
|
using PepperDash.Essentials.Core.Config;
|
|
using Serilog.Events;
|
|
|
|
//using PepperDash.Essentials.Devices.Common.Cameras;
|
|
|
|
namespace PepperDash.Essentials.Core.Bridges
|
|
{
|
|
/// <summary>
|
|
/// Base class for bridge API variants
|
|
/// </summary>
|
|
public abstract class BridgeApi : EssentialsDevice
|
|
{
|
|
protected BridgeApi(string key) :
|
|
base(key)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bridge API using EISC
|
|
/// </summary>
|
|
public class EiscApiAdvanced : BridgeApi, ICommunicationMonitor
|
|
{
|
|
public EiscApiPropertiesConfig PropertiesConfig { get; private set; }
|
|
|
|
public Dictionary<string, JoinMapBaseAdvanced> JoinMaps { get; private set; }
|
|
|
|
public BasicTriList Eisc { get; private set; }
|
|
|
|
public EiscApiAdvanced(DeviceConfig dc, BasicTriList eisc) :
|
|
base(dc.Key)
|
|
{
|
|
JoinMaps = new Dictionary<string, JoinMapBaseAdvanced>();
|
|
|
|
PropertiesConfig = dc.Properties.ToObject<EiscApiPropertiesConfig>();
|
|
//PropertiesConfig = JsonConvert.DeserializeObject<EiscApiPropertiesConfig>(dc.Properties.ToString());
|
|
|
|
Eisc = eisc;
|
|
|
|
Eisc.SigChange += Eisc_SigChange;
|
|
|
|
CommunicationMonitor = new CrestronGenericBaseCommunicationMonitor(this, Eisc, 120000, 300000);
|
|
|
|
AddPostActivationAction(LinkDevices);
|
|
AddPostActivationAction(LinkRooms);
|
|
AddPostActivationAction(RegisterEisc);
|
|
}
|
|
|
|
public override bool CustomActivate()
|
|
{
|
|
CommunicationMonitor.Start();
|
|
return base.CustomActivate();
|
|
}
|
|
|
|
public override bool Deactivate()
|
|
{
|
|
CommunicationMonitor.Stop();
|
|
return base.Deactivate();
|
|
}
|
|
|
|
private void LinkDevices()
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Debug, this, "Linking Devices...");
|
|
|
|
if (PropertiesConfig.Devices == null)
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Debug, this, "No devices linked to this bridge");
|
|
return;
|
|
}
|
|
|
|
foreach (var d in PropertiesConfig.Devices)
|
|
{
|
|
var device = DeviceManager.GetDeviceForKey(d.DeviceKey);
|
|
|
|
if (device == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Debug.LogMessage(LogEventLevel.Debug, this, "Linking Device: '{0}'", device.Key);
|
|
|
|
if (device is IBridgeAdvanced bridge)
|
|
{
|
|
bridge.LinkToApi(Eisc, d.JoinStart, d.JoinMapKey, this);
|
|
continue;
|
|
}
|
|
|
|
Debug.LogMessage(LogEventLevel.Information, this,
|
|
"{0} is not compatible with this bridge type. Please use 'eiscapi' instead, or updae the device.",
|
|
device.Key);
|
|
}
|
|
}
|
|
|
|
private void RegisterEisc()
|
|
{
|
|
if (Eisc.Registered)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var registerResult = Eisc.Register();
|
|
|
|
if (registerResult != eDeviceRegistrationUnRegistrationResponse.Success)
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Verbose, this, "Registration result: {0}", registerResult);
|
|
return;
|
|
}
|
|
|
|
Debug.LogMessage(LogEventLevel.Debug, this, "EISC registration successful");
|
|
}
|
|
|
|
public void LinkRooms()
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Debug, this, "Linking Rooms...");
|
|
|
|
if (PropertiesConfig.Rooms == null)
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Debug, this, "No rooms linked to this bridge.");
|
|
return;
|
|
}
|
|
|
|
foreach (var room in PropertiesConfig.Rooms)
|
|
{
|
|
var rm = DeviceManager.GetDeviceForKey(room.RoomKey) as IBridgeAdvanced;
|
|
|
|
if (rm == null)
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Debug, this,
|
|
"Room {0} does not implement IBridgeAdvanced. Skipping...", room.RoomKey);
|
|
continue;
|
|
}
|
|
|
|
rm.LinkToApi(Eisc, room.JoinStart, room.JoinMapKey, this);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a join map
|
|
/// </summary>
|
|
/// <param name="deviceKey"></param>
|
|
/// <param name="joinMap"></param>
|
|
public void AddJoinMap(string deviceKey, JoinMapBaseAdvanced joinMap)
|
|
{
|
|
if (!JoinMaps.ContainsKey(deviceKey))
|
|
{
|
|
JoinMaps.Add(deviceKey, joinMap);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Verbose, this, "Unable to add join map with key '{0}'. Key already exists in JoinMaps dictionary", deviceKey);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prints all the join maps on this bridge
|
|
/// </summary>
|
|
public virtual void PrintJoinMaps()
|
|
{
|
|
CrestronConsole.ConsoleCommandResponse("Join Maps for EISC IPID: {0}\r\n", Eisc.ID.ToString("X"));
|
|
|
|
foreach (var joinMap in JoinMaps)
|
|
{
|
|
CrestronConsole.ConsoleCommandResponse("Join map for device '{0}':", joinMap.Key);
|
|
joinMap.Value.PrintJoinMapInfo();
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Generates markdown for all join maps on this bridge
|
|
/// </summary>
|
|
public virtual void MarkdownForBridge(string bridgeKey)
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Information, this, "Writing Joinmaps to files for EISC IPID: {0}", Eisc.ID.ToString("X"));
|
|
|
|
foreach (var joinMap in JoinMaps)
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Information, "Generating markdown for device '{0}':", joinMap.Key);
|
|
joinMap.Value.MarkdownJoinMapInfo(joinMap.Key, bridgeKey);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prints the join map for a device by key
|
|
/// </summary>
|
|
/// <param name="deviceKey"></param>
|
|
public void PrintJoinMapForDevice(string deviceKey)
|
|
{
|
|
var joinMap = JoinMaps[deviceKey];
|
|
|
|
if (joinMap == null)
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Information, this, "Unable to find joinMap for device with key: '{0}'", deviceKey);
|
|
return;
|
|
}
|
|
|
|
Debug.LogMessage(LogEventLevel.Information, "Join map for device '{0}' on EISC '{1}':", deviceKey, Key);
|
|
joinMap.PrintJoinMapInfo();
|
|
}
|
|
/// <summary>
|
|
/// Prints the join map for a device by key
|
|
/// </summary>
|
|
/// <param name="deviceKey"></param>
|
|
public void MarkdownJoinMapForDevice(string deviceKey, string bridgeKey)
|
|
{
|
|
var joinMap = JoinMaps[deviceKey];
|
|
|
|
if (joinMap == null)
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Information, this, "Unable to find joinMap for device with key: '{0}'", deviceKey);
|
|
return;
|
|
}
|
|
|
|
Debug.LogMessage(LogEventLevel.Information, "Join map for device '{0}' on EISC '{1}':", deviceKey, Key);
|
|
joinMap.MarkdownJoinMapInfo(deviceKey, bridgeKey);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Used for debugging to trigger an action based on a join number and type
|
|
/// </summary>
|
|
/// <param name="join"></param>
|
|
/// <param name="type"></param>
|
|
/// <param name="state"></param>
|
|
public void ExecuteJoinAction(uint join, string type, object state)
|
|
{
|
|
try
|
|
{
|
|
switch (type.ToLower())
|
|
{
|
|
case "digital":
|
|
{
|
|
var uo = Eisc.BooleanOutput[join].UserObject as Action<bool>;
|
|
if (uo != null)
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Verbose, this, "Executing Action: {0}", uo.ToString());
|
|
uo(Convert.ToBoolean(state));
|
|
}
|
|
else
|
|
Debug.LogMessage(LogEventLevel.Verbose, this, "User Action is null. Nothing to Execute");
|
|
break;
|
|
}
|
|
case "analog":
|
|
{
|
|
var uo = Eisc.BooleanOutput[join].UserObject as Action<ushort>;
|
|
if (uo != null)
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Verbose, this, "Executing Action: {0}", uo.ToString());
|
|
uo(Convert.ToUInt16(state));
|
|
}
|
|
else
|
|
Debug.LogMessage(LogEventLevel.Verbose, this, "User Action is null. Nothing to Execute"); break;
|
|
}
|
|
case "serial":
|
|
{
|
|
var uo = Eisc.BooleanOutput[join].UserObject as Action<string>;
|
|
if (uo != null)
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Verbose, this, "Executing Action: {0}", uo.ToString());
|
|
uo(Convert.ToString(state));
|
|
}
|
|
else
|
|
Debug.LogMessage(LogEventLevel.Verbose, this, "User Action is null. Nothing to Execute");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Verbose, "Unknown join type. Use digital/serial/analog");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e);
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handles incoming sig changes
|
|
/// </summary>
|
|
/// <param name="currentDevice"></param>
|
|
/// <param name="args"></param>
|
|
protected void Eisc_SigChange(object currentDevice, SigEventArgs args)
|
|
{
|
|
try
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Verbose, this, "EiscApiAdvanced change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
|
|
var uo = args.Sig.UserObject;
|
|
|
|
if (uo == null) return;
|
|
|
|
Debug.LogMessage(LogEventLevel.Debug, this, "Executing Action: {0}", uo.ToString());
|
|
if (uo is Action<bool>)
|
|
(uo as Action<bool>)(args.Sig.BoolValue);
|
|
else if (uo is Action<ushort>)
|
|
(uo as Action<ushort>)(args.Sig.UShortValue);
|
|
else if (uo is Action<string>)
|
|
(uo as Action<string>)(args.Sig.StringValue);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Verbose, this, "Error in Eisc_SigChange handler: {0}", e);
|
|
}
|
|
}
|
|
|
|
#region Implementation of ICommunicationMonitor
|
|
|
|
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
|
|
|
#endregion
|
|
}
|
|
|
|
public class EiscApiPropertiesConfig
|
|
{
|
|
[JsonProperty("control")]
|
|
public EssentialsControlPropertiesConfig Control { get; set; }
|
|
|
|
[JsonProperty("devices")]
|
|
public List<ApiDevicePropertiesConfig> Devices { get; set; }
|
|
|
|
[JsonProperty("rooms")]
|
|
public List<ApiRoomPropertiesConfig> Rooms { get; set; }
|
|
|
|
|
|
public class ApiDevicePropertiesConfig
|
|
{
|
|
[JsonProperty("deviceKey")]
|
|
public string DeviceKey { get; set; }
|
|
|
|
[JsonProperty("joinStart")]
|
|
public uint JoinStart { get; set; }
|
|
|
|
[JsonProperty("joinMapKey")]
|
|
public string JoinMapKey { get; set; }
|
|
}
|
|
|
|
public class ApiRoomPropertiesConfig
|
|
{
|
|
[JsonProperty("roomKey")]
|
|
public string RoomKey { get; set; }
|
|
|
|
[JsonProperty("joinStart")]
|
|
public uint JoinStart { get; set; }
|
|
|
|
[JsonProperty("joinMapKey")]
|
|
public string JoinMapKey { get; set; }
|
|
}
|
|
|
|
}
|
|
|
|
public class EiscApiAdvancedFactory : EssentialsDeviceFactory<EiscApiAdvanced>
|
|
{
|
|
public EiscApiAdvancedFactory()
|
|
{
|
|
TypeNames = new List<string> { "eiscapiadv", "eiscapiadvanced", "eiscapiadvancedserver", "eiscapiadvancedclient", "vceiscapiadv", "vceiscapiadvanced" };
|
|
}
|
|
|
|
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new EiscApiAdvanced Device");
|
|
|
|
var controlProperties = CommFactory.GetControlPropertiesConfig(dc);
|
|
|
|
BasicTriList eisc;
|
|
|
|
switch (dc.Type.ToLower())
|
|
{
|
|
case "eiscapiadv":
|
|
case "eiscapiadvanced":
|
|
{
|
|
eisc = new ThreeSeriesTcpIpEthernetIntersystemCommunications(controlProperties.IpIdInt,
|
|
controlProperties.TcpSshProperties.Address, Global.ControlSystem);
|
|
break;
|
|
}
|
|
case "eiscapiadvancedserver":
|
|
{
|
|
eisc = new EISCServer(controlProperties.IpIdInt, Global.ControlSystem);
|
|
break;
|
|
}
|
|
case "eiscapiadvancedclient":
|
|
{
|
|
eisc = new EISCClient(controlProperties.IpIdInt, controlProperties.TcpSshProperties.Address, Global.ControlSystem);
|
|
break;
|
|
}
|
|
case "vceiscapiadv":
|
|
case "vceiscapiadvanced":
|
|
{
|
|
if (string.IsNullOrEmpty(controlProperties.RoomId))
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Information, "Unable to build VC-4 EISC Client for device {0}. Room ID is missing or empty", dc.Key);
|
|
eisc = null;
|
|
break;
|
|
}
|
|
eisc = new VirtualControlEISCClient(controlProperties.IpIdInt, controlProperties.RoomId,
|
|
Global.ControlSystem);
|
|
break;
|
|
}
|
|
default:
|
|
eisc = null;
|
|
break;
|
|
}
|
|
|
|
if (eisc == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return new EiscApiAdvanced(dc, eisc);
|
|
}
|
|
}
|
|
|
|
} |