using System; using System.Collections.Generic; using System.Linq; using Crestron.SimplSharpPro.DeviceSupport; using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Devices; using PepperDash.Essentials.Core.Presets; using Serilog.Events; namespace PepperDash.Essentials.Devices.Common.Cameras { /// /// Enumeration of eCameraCapabilities values /// public enum eCameraCapabilities { /// /// No camera capabilities /// None = 0, /// /// Camera supports pan movement /// Pan = 1, /// /// Camera supports tilt movement /// Tilt = 2, /// /// Camera supports zoom functionality /// Zoom = 4, /// /// Camera supports focus adjustment /// Focus = 8 } /// /// Abstract base class for camera devices that provides common camera functionality and capabilities /// public abstract class CameraBase : ReconfigurableDevice, IRoutingOutputs { /// /// Gets or sets the ControlMode /// [JsonProperty("controlMode", NullValueHandling = NullValueHandling.Ignore)] public eCameraControlMode ControlMode { get; protected set; } #region IRoutingOutputs Members /// /// Gets or sets the OutputPorts /// [JsonIgnore] public RoutingPortCollection OutputPorts { get; protected set; } #endregion /// /// Gets a value indicating whether this camera supports pan movement /// [JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)] public bool CanPan { get { return (Capabilities & eCameraCapabilities.Pan) == eCameraCapabilities.Pan; } } /// /// Gets a value indicating whether this camera supports tilt movement /// [JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)] public bool CanTilt { get { return (Capabilities & eCameraCapabilities.Tilt) == eCameraCapabilities.Tilt; } } /// /// Gets a value indicating whether this camera supports zoom functionality /// [JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)] public bool CanZoom { get { return (Capabilities & eCameraCapabilities.Zoom) == eCameraCapabilities.Zoom; } } /// /// Gets a value indicating whether this camera supports focus adjustment /// [JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)] public bool CanFocus { get { return (Capabilities & eCameraCapabilities.Focus) == eCameraCapabilities.Focus; } } /// /// Gets or sets a bitmasked value to indicate the movement capabilities of this camera /// protected eCameraCapabilities Capabilities { get; set; } /// /// Initializes a new instance of the CameraBase class with the specified device configuration /// /// The device configuration protected CameraBase(DeviceConfig config) : base(config) { OutputPorts = new RoutingPortCollection(); ControlMode = eCameraControlMode.Manual; } /// /// Initializes a new instance of the CameraBase class with the specified key and name /// /// The unique key for this camera device /// The friendly name for this camera device protected CameraBase(string key, string name) : this(new DeviceConfig { Name = name, Key = key }) { } /// /// Links the camera device to the API bridge for control and feedback /// /// The camera device to link /// The trilist for communication /// The starting join number for the camera controls /// The join map key for custom join mappings /// The EiscApiAdvanced bridge for advanced join mapping protected void LinkCameraToApi(CameraBase cameraDevice, BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) { CameraControllerJoinMap joinMap = new CameraControllerJoinMap(joinStart); if (bridge != null) { bridge.AddJoinMap(Key, joinMap); } else { Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); } var customJoins = JoinMapHelper.TryGetJoinMapAdvancedForDevice(joinMapKey); if (customJoins != null) { joinMap.SetCustomJoinData(customJoins); } Debug.LogMessage(LogEventLevel.Debug, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); Debug.LogMessage(LogEventLevel.Information, "Linking to Bridge Type {0}", cameraDevice.GetType().Name.ToString()); var commMonitor = cameraDevice as ICommunicationMonitor; commMonitor.CommunicationMonitor.IsOnlineFeedback.LinkInputSig( trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); var ptzCamera = cameraDevice as IHasCameraPtzControl; if (ptzCamera != null) { trilist.SetBoolSigAction(joinMap.PanLeft.JoinNumber, (b) => { if (b) { ptzCamera.PanLeft(); } else { ptzCamera.PanStop(); } }); trilist.SetBoolSigAction(joinMap.PanRight.JoinNumber, (b) => { if (b) { ptzCamera.PanRight(); } else { ptzCamera.PanStop(); } }); trilist.SetBoolSigAction(joinMap.TiltUp.JoinNumber, (b) => { if (b) { ptzCamera.TiltUp(); } else { ptzCamera.TiltStop(); } }); trilist.SetBoolSigAction(joinMap.TiltDown.JoinNumber, (b) => { if (b) { ptzCamera.TiltDown(); } else { ptzCamera.TiltStop(); } }); trilist.SetBoolSigAction(joinMap.ZoomIn.JoinNumber, (b) => { if (b) { ptzCamera.ZoomIn(); } else { ptzCamera.ZoomStop(); } }); trilist.SetBoolSigAction(joinMap.ZoomOut.JoinNumber, (b) => { if (b) { ptzCamera.ZoomOut(); } else { ptzCamera.ZoomStop(); } }); } var powerCamera = cameraDevice as IHasPowerControl; if (powerCamera != null) { trilist.SetSigTrueAction(joinMap.PowerOn.JoinNumber, () => powerCamera.PowerOn()); trilist.SetSigTrueAction(joinMap.PowerOff.JoinNumber, () => powerCamera.PowerOff()); var powerFbCamera = powerCamera as IHasPowerControlWithFeedback; if (powerFbCamera != null) { powerFbCamera.PowerIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PowerOn.JoinNumber]); powerFbCamera.PowerIsOnFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.PowerOff.JoinNumber]); } } if (cameraDevice is ICommunicationMonitor) { var monitoredCamera = cameraDevice as ICommunicationMonitor; monitoredCamera.CommunicationMonitor.IsOnlineFeedback.LinkInputSig( trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); } if (cameraDevice is IHasCameraPresets) { // Set the preset lables when they change var presetsCamera = cameraDevice as IHasCameraPresets; presetsCamera.PresetsListHasChanged += new EventHandler((o, a) => { SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist); }); SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist); for (int i = 0; i < joinMap.PresetRecallStart.JoinSpan; i++) { int tempNum = i; trilist.SetSigTrueAction((ushort)(joinMap.PresetRecallStart.JoinNumber + tempNum), () => { presetsCamera.PresetSelect(tempNum); }); trilist.SetSigTrueAction((ushort)(joinMap.PresetSaveStart.JoinNumber + tempNum), () => { var label = trilist.GetString((ushort)(joinMap.PresetLabelStart.JoinNumber + tempNum)); presetsCamera.PresetStore(tempNum, label); }); } trilist.OnlineStatusChange += (sender, args) => { if (!args.DeviceOnLine) { return; } SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist); }; } } private void SendCameraPresetNamesToApi(IHasCameraPresets presetsCamera, CameraControllerJoinMap joinMap, BasicTriList trilist) { for (int i = 1; i <= joinMap.NumberOfPresets.JoinNumber; i++) { int tempNum = i - 1; string label = ""; var preset = presetsCamera.Presets.FirstOrDefault(p => p.ID.Equals(i)); if (preset != null) label = preset.Description; trilist.SetString((ushort)(joinMap.PresetLabelStart.JoinNumber + tempNum), label); } } } /// /// Represents a CameraPreset /// public class CameraPreset : PresetBase { /// /// Initializes a new instance of the CameraPreset class /// /// The preset ID /// The preset description /// Whether the preset is defined /// Whether the preset can be defined public CameraPreset(int id, string description, bool isDefined, bool isDefinable) : base(id, description, isDefined, isDefinable) { } } /// /// Represents a CameraPropertiesConfig /// public class CameraPropertiesConfig { /// /// Gets or sets the CommunicationMonitorProperties /// public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; } /// /// Gets or sets the Control /// public ControlPropertiesConfig Control { get; set; } /// /// Gets or sets the SupportsAutoMode /// [JsonProperty("supportsAutoMode")] public bool SupportsAutoMode { get; set; } /// /// Gets or sets the SupportsOffMode /// [JsonProperty("supportsOffMode")] public bool SupportsOffMode { get; set; } /// /// Gets or sets the Presets /// [JsonProperty("presets")] public List Presets { get; set; } } }