From 1cb9fb605801f2525a5dd61ea4d2486f2d7a4245 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Tue, 10 Nov 2020 09:29:37 -0700 Subject: [PATCH 1/6] Removes unnecessary null check in SendDtmf method --- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index ce748699..4e94daef 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -1339,10 +1339,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public override void SendDtmf(string s) { - if (CallFavorites != null) - { - SendText(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", GetCallId(), s)); - } + SendText(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", GetCallId(), s)); + } public void SelectPresentationSource(int source) From 0d7d5fe38065963bfe4a9a7993528dcb4552f430 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 9 Sep 2020 17:44:48 -0600 Subject: [PATCH 2/6] Adds feedback parsing to CameraVisca as well as some new focus controls. --- .../Cameras/CameraControl.cs | 7 + .../Cameras/CameraVisca.cs | 434 ++++++++++++++++-- 2 files changed, 410 insertions(+), 31 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs index 89b6002a..8262bf2f 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs @@ -135,6 +135,13 @@ namespace PepperDash.Essentials.Devices.Common.Cameras void TriggerAutoFocus(); } + public interface IHasAutoFocusMode + { + void SetFocusModeAuto(); + void SetFocusModeManual(); + void ToggleFocusMode(); + } + public interface IHasCameraAutoMode : IHasCameraControls { void CameraAutoModeOn(); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs index 2966bde4..e516da20 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs @@ -12,29 +12,86 @@ using PepperDash.Essentials.Devices.Common.Codec; using System.Text.RegularExpressions; using Crestron.SimplSharp.Reflection; +using Newtonsoft.Json; + namespace PepperDash.Essentials.Devices.Common.Cameras { - public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IHasPowerControlWithFeedback, IBridgeAdvanced + public class CameraVisca : CameraBase, IHasCameraPtzControl, ICommunicationMonitor, IHasCameraPresets, IHasPowerControlWithFeedback, IBridgeAdvanced, IHasCameraFocusControl, IHasAutoFocusMode { + CameraViscaPropertiesConfig PropertiesConfig; + public IBasicCommunication Communication { get; private set; } - public CommunicationGather PortGather { get; private set; } public StatusMonitorBase CommunicationMonitor { get; private set; } - public byte PanSpeed = 0x10; - public byte TiltSpeed = 0x10; + /// + /// Used to store the actions to parse inquiry responses as the inquiries are sent + /// + private CrestronQueue> InquiryResponseQueue; + + /// + /// Camera ID (Default 1) + /// + public byte ID = 0x01; + public byte ResponseID; + + + public byte PanSpeedSlow = 0x10; + public byte TiltSpeedSlow = 0x10; + public byte ZoomSpeedSlow = 0x03; + + public byte PanSpeedFast = 0x13; + public byte TiltSpeedFast = 0x13; + public byte ZoomSpeedFast = 0x05; + private bool IsMoving; private bool IsZooming; - public bool PowerIsOn { get; private set; } + + bool _powerIsOn; + public bool PowerIsOn + { + get + { + return _powerIsOn; + } + private set + { + if (value != _powerIsOn) + { + _powerIsOn = value; + PowerIsOnFeedback.FireUpdate(); + } + } + } + + const byte ZoomInCmd = 0x02; + const byte ZoomOutCmd = 0x03; + const byte ZoomStopCmd = 0x00; + + /// + /// Used to determine when to move the camera at a faster speed if a direction is held + /// + CTimer SpeedTimer; + + long FastSpeedHoldTimeMs = 2000; byte[] IncomingBuffer = new byte[] { }; public BoolFeedback PowerIsOnFeedback { get; private set; } - public CameraVisca(string key, string name, IBasicCommunication comm, CameraPropertiesConfig props) : + public CameraVisca(string key, string name, IBasicCommunication comm, CameraViscaPropertiesConfig props) : base(key, name) { + InquiryResponseQueue = new CrestronQueue>(15); + Presets = props.Presets; + PropertiesConfig = props; + + ID = (byte)(props.Id + 0x80); + ResponseID = (byte)((props.Id * 0x10) + 0x80); + + SetupCameraSpeeds(); + OutputPorts.Add(new RoutingOutputPort("videoOut", eRoutingSignalType.Video, eRoutingPortConnectionType.None, null, this, true)); // Default to all capabilties @@ -51,8 +108,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras { // This instance uses RS-232 control } - PortGather = new CommunicationGather(Communication, "\xFF"); - Communication.BytesReceived += new EventHandler(Communication_BytesReceived); PowerIsOnFeedback = new BoolFeedback(() => { return PowerIsOn; }); @@ -66,9 +121,47 @@ namespace PepperDash.Essentials.Devices.Common.Cameras CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 20000, 120000, 300000, "\x81\x09\x04\x00\xFF"); } DeviceManager.AddDevice(CommunicationMonitor); - - } + + + /// + /// Sets up camera speed values based on config + /// + void SetupCameraSpeeds() + { + if (PropertiesConfig.FastSpeedHoldTimeMs > 0) + { + FastSpeedHoldTimeMs = PropertiesConfig.FastSpeedHoldTimeMs; + } + + if (PropertiesConfig.PanSpeedSlow > 0) + { + PanSpeedSlow = (byte)PropertiesConfig.PanSpeedSlow; + } + if (PropertiesConfig.PanSpeedFast > 0) + { + PanSpeedFast = (byte)PropertiesConfig.PanSpeedFast; + } + + if (PropertiesConfig.TiltSpeedSlow > 0) + { + TiltSpeedSlow = (byte)PropertiesConfig.TiltSpeedSlow; + } + if (PropertiesConfig.TiltSpeedFast > 0) + { + TiltSpeedFast = (byte)PropertiesConfig.TiltSpeedFast; + } + + if (PropertiesConfig.ZoomSpeedSlow > 0) + { + ZoomSpeedSlow = (byte)PropertiesConfig.ZoomSpeedSlow; + } + if (PropertiesConfig.ZoomSpeedFast > 0) + { + ZoomSpeedFast = (byte)PropertiesConfig.ZoomSpeedFast; + } + } + public override bool CustomActivate() { Communication.Connect(); @@ -110,21 +203,148 @@ namespace PepperDash.Essentials.Devices.Common.Cameras Communication.SendBytes(b); } + void Communication_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e) { - // This is probably not thread-safe buffering - // Append the incoming bytes with whatever is in the buffer - var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length]; - IncomingBuffer.CopyTo(newBytes, 0); - e.Bytes.CopyTo(newBytes, IncomingBuffer.Length); - if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1 - Debug.Console(2, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes)); - } + var newBytes = new byte[IncomingBuffer.Length + e.Bytes.Length]; + try + { + // This is probably not thread-safe buffering + // Append the incoming bytes with whatever is in the buffer + IncomingBuffer.CopyTo(newBytes, 0); + e.Bytes.CopyTo(newBytes, IncomingBuffer.Length); + if (Debug.Level == 2) // This check is here to prevent following string format from building unnecessarily on level 0 or 1 + Debug.Console(2, this, "Received:{0}", ComTextHelper.GetEscapedText(newBytes)); + + byte[] message = new byte[] { }; + + // Search for the delimiter 0xFF character + for (int i = 0; i < newBytes.Length; i++) + { + if (newBytes[i] == 0xFF) + { + // i will be the index of the delmiter character + message = newBytes.Take(i).ToArray(); + // Skip over what we just took and save the rest for next time + newBytes = newBytes.Skip(i).ToArray(); + } + } + + if (message.Length > 0) + { + // Check for matching ID + if (message[0] != ResponseID) + { + return; + } + + switch (message[1]) + { + case 0x40: + { + // ACK received + Debug.Console(2, this, "ACK Received"); + break; + } + case 0x50: + { + + if (message[2] == 0xFF) + { + // Completion received + Debug.Console(2, this, "Completion Received"); + } + else + { + // Inquiry response received. Dequeue the next response handler and invoke it + if (InquiryResponseQueue.Count > 0) + { + var inquiryAction = InquiryResponseQueue.Dequeue(); + + inquiryAction.Invoke(message.Skip(2).ToArray()); + } + else + { + Debug.Console(2, this, "Response Queue is empty. Nothing to dequeue."); + } + } + + break; + } + case 0x60: + { + // Error message + + switch (message[2]) + { + case 0x01: + { + // Message Length Error + Debug.Console(2, this, "Error from device: Message Length Error"); + break; + } + case 0x02: + { + // Syntax Error + Debug.Console(2, this, "Error from device: Syntax Error"); + break; + } + case 0x03: + { + // Command Buffer Full + Debug.Console(2, this, "Error from device: Command Buffer Full"); + break; + } + case 0x04: + { + // Command Cancelled + Debug.Console(2, this, "Error from device: Command Cancelled"); + break; + } + case 0x05: + { + // No Socket + Debug.Console(2, this, "Error from device: No Socket"); + break; + } + case 0x41: + { + // Command not executable + Debug.Console(2, this, "Error from device: Command not executable"); + break; + } + } + break; + } + } + + if (message == new byte[] { ResponseID, 0x50, 0x02, 0xFF }) + { + PowerIsOn = true; + } + else if (message == new byte[] { ResponseID, 0x50, 0x03, 0xFF }) + { + PowerIsOn = false; + } + + } + + } + catch (Exception err) + { + Debug.Console(2, this, "Error parsing feedback: {0}", err); + } + finally + { + // Save whatever partial message is here + IncomingBuffer = newBytes; + } + } private void SendPanTiltCommand (byte[] cmd) { - var temp = new Byte[] { 0x81, 0x01, 0x06, 0x01, PanSpeed, TiltSpeed }; + var temp = new byte[] { ID, 0x01, 0x06, 0x01, PanSpeedSlow, TiltSpeedSlow }; int length = temp.Length + cmd.Length + 1; byte[] sum = new byte[length]; @@ -134,16 +354,40 @@ namespace PepperDash.Essentials.Devices.Common.Cameras SendBytes(sum); } + void SendPowerQuery() + { + SendBytes(new byte[] { ID, 0x09, 0x04, 0x00, 0xFF }); + InquiryResponseQueue.Enqueue(HandlePowerResponse); + } + public void PowerOn() { - - SendBytes(new Byte[] { 0x81, 0x01, 0x04, 0x00, 0x02, 0xFF }); + SendBytes(new byte[] { ID, 0x01, 0x04, 0x00, 0x02, 0xFF }); + SendPowerQuery(); } + void HandlePowerResponse(byte[] response) + { + switch (response[0]) + { + case 0x02: + { + PowerIsOn = true; + break; + } + case 0x03: + { + PowerIsOn = false; + break; + } + } + } + public void PowerOff() { - SendBytes(new Byte[] {0x81, 0x01, 0x04, 0x00, 0x03, 0xFF}); - } + SendBytes(new byte[] {ID, 0x01, 0x04, 0x00, 0x03, 0xFF}); + SendPowerQuery(); + } public void PowerToggle() { @@ -153,6 +397,8 @@ namespace PepperDash.Essentials.Devices.Common.Cameras PowerOn(); } + + public void PanLeft() { SendPanTiltCommand(new byte[] {0x01, 0x03}); @@ -184,16 +430,16 @@ namespace PepperDash.Essentials.Devices.Common.Cameras private void SendZoomCommand (byte cmd) { - SendBytes(new byte[] {0x81, 0x01, 0x04, 0x07, cmd, 0xFF} ); + SendBytes(new byte[] {ID, 0x01, 0x04, 0x07, cmd, 0xFF} ); } public void ZoomIn() { - SendZoomCommand(0x02); + SendZoomCommand(ZoomInCmd); IsZooming = true; } public void ZoomOut() { - SendZoomCommand(0x03); + SendZoomCommand(ZoomOutCmd); IsZooming = true; } public void ZoomStop() @@ -205,7 +451,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras { if (IsZooming) { - SendZoomCommand(0x00); + SendZoomCommand(ZoomStopCmd); IsZooming = false; } else @@ -216,15 +462,16 @@ namespace PepperDash.Essentials.Devices.Common.Cameras } public void PositionHome() { - throw new NotImplementedException(); + SendBytes(new byte[] { ID, 0x01, 0x06, 0x02, PanSpeedFast, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }); + SendBytes(new byte[] { ID, 0x01, 0x04, 0x47, 0x00, 0x00, 0x00, 0x00, 0xFF }); } public void RecallPreset(int presetNumber) { - SendBytes(new byte[] {0x81, 0x01, 0x04, 0x3F, 0x02, (byte)presetNumber, 0xFF} ); + SendBytes(new byte[] {ID, 0x01, 0x04, 0x3F, 0x02, (byte)presetNumber, 0xFF} ); } public void SavePreset(int presetNumber) { - SendBytes(new byte[] { 0x81, 0x01, 0x04, 0x3F, 0x01, (byte)presetNumber, 0xFF }); + SendBytes(new byte[] { ID, 0x01, 0x04, 0x3F, 0x01, (byte)presetNumber, 0xFF }); } #region IHasCameraPresets Members @@ -244,6 +491,78 @@ namespace PepperDash.Essentials.Devices.Common.Cameras } #endregion + + #region IHasCameraFocusControl Members + + public void FocusNear() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x03, 0xFF }); + } + + public void FocusFar() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x02, 0xFF }); + } + + public void FocusStop() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x08, 0x00, 0xFF }); + } + + public void TriggerAutoFocus() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x18, 0x01, 0xFF }); + SendAutoFocusQuery(); + } + + #endregion + + #region IHasAutoFocus Members + + public void SetFocusModeAuto() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x02, 0xFF }); + SendAutoFocusQuery(); + } + + public void SetFocusModeManual() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x03, 0xFF }); + SendAutoFocusQuery(); + } + + public void ToggleFocusMode() + { + SendBytes(new byte[] { ID, 0x01, 0x04, 0x38, 0x10, 0xFF }); + SendAutoFocusQuery(); + } + + #endregion + + void SendAutoFocusQuery() + { + SendBytes(new byte[] { ID, 0x09, 0x04, 0x38, 0xFF }); + InquiryResponseQueue.Enqueue(HandleAutoFocusResponse); + } + + void HandleAutoFocusResponse(byte[] response) + { + switch (response[0]) + { + case 0x02: + { + // Auto Mode + PowerIsOn = true; + break; + } + case 0x03: + { + // Manual Mode + PowerIsOn = false; + break; + } + } + } } public class CameraViscaFactory : EssentialsDeviceFactory @@ -257,10 +576,63 @@ namespace PepperDash.Essentials.Devices.Common.Cameras { Debug.Console(1, "Factory Attempting to create new CameraVisca Device"); var comm = CommFactory.CreateCommForDevice(dc); - var props = Newtonsoft.Json.JsonConvert.DeserializeObject( + var props = Newtonsoft.Json.JsonConvert.DeserializeObject( dc.Properties.ToString()); return new Cameras.CameraVisca(dc.Key, dc.Name, comm, props); } } + + public class CameraViscaPropertiesConfig : CameraPropertiesConfig + { + /// + /// Control ID of the camera (1-7) + /// + [JsonProperty("id")] + public uint Id { get; set; } + + /// + /// Slow Pan speed (0-18) + /// + [JsonProperty("panSpeedSlow")] + public uint PanSpeedSlow { get; set; } + + /// + /// Fast Pan speed (0-18) + /// + [JsonProperty("panSpeedFast")] + public uint PanSpeedFast { get; set; } + + /// + /// Slow tilt speed (0-18) + /// + [JsonProperty("tiltSpeedSlow")] + public uint TiltSpeedSlow { get; set; } + + /// + /// Fast tilt speed (0-18) + /// + [JsonProperty("tiltSpeedFast")] + public uint TiltSpeedFast { get; set; } + + /// + /// Slow zoom speed (0-7) + /// + [JsonProperty("zoomSpeedSlow")] + public uint ZoomSpeedSlow { get; set; } + + /// + /// Fast zoom speed (0-7) + /// + [JsonProperty("zoomSpeedFast")] + public uint ZoomSpeedFast { get; set; } + + /// + /// Time a button must be held before fast speed is engaged (Milliseconds) + /// + [JsonProperty("fastSpeedHoldTimeMs")] + public uint FastSpeedHoldTimeMs { get; set; } + + } + } \ No newline at end of file From 0098401584ddeae40bd19e1e5bfc7c14cb179613 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 10 Sep 2020 15:24:08 -0600 Subject: [PATCH 3/6] Adds SpeedTimer implmentation to CameraVisca --- .../Cameras/CameraControl.cs | 6 -- .../Cameras/CameraVisca.cs | 88 +++++++++++++++---- 2 files changed, 72 insertions(+), 22 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs index 8262bf2f..c0a0442c 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraControl.cs @@ -92,8 +92,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras /// public interface IHasCameraPanControl : IHasCameraControls { - // void PanLeft(bool pressRelease); - // void PanRight(bool pressRelease); void PanLeft(); void PanRight(); void PanStop(); @@ -104,8 +102,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras /// public interface IHasCameraTiltControl : IHasCameraControls { - // void TiltDown(bool pressRelease); - // void TildUp(bool pressRelease); void TiltDown(); void TiltUp(); void TiltStop(); @@ -116,8 +112,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras /// public interface IHasCameraZoomControl : IHasCameraControls { - // void ZoomIn(bool pressRelease); - // void ZoomOut(bool pressRelease); void ZoomIn(); void ZoomOut(); void ZoomStop(); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs index e516da20..68aace0a 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs @@ -72,6 +72,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras /// Used to determine when to move the camera at a faster speed if a direction is held /// CTimer SpeedTimer; + // TODO: Implment speed timer for PTZ controls long FastSpeedHoldTimeMs = 2000; @@ -342,18 +343,72 @@ namespace PepperDash.Essentials.Devices.Common.Cameras } } - private void SendPanTiltCommand (byte[] cmd) + /// + /// Sends a pan/tilt command. If the command is not for fastSpeed then it starts a timer to initiate fast speed. + /// + /// + /// + private void SendPanTiltCommand (byte[] cmd, bool fastSpeedEnabled) { - var temp = new byte[] { ID, 0x01, 0x06, 0x01, PanSpeedSlow, TiltSpeedSlow }; - int length = temp.Length + cmd.Length + 1; - - byte[] sum = new byte[length]; - temp.CopyTo(sum, 0); - cmd.CopyTo(sum, temp.Length); - sum[length - 1] = 0xFF; - SendBytes(sum); + SendBytes(GetPanTiltCommand(cmd, fastSpeedEnabled)); + + if (!fastSpeedEnabled) + { + if (SpeedTimer != null) + { + StopSpeedTimer(); + } + + // Start the timer to send fast speed if still moving after FastSpeedHoldTime elapses + SpeedTimer = new CTimer((o) => SendPanTiltCommand(GetPanTiltCommand(cmd, true), true), FastSpeedHoldTimeMs); + } + } + private void StopSpeedTimer() + { + if (SpeedTimer != null) + { + SpeedTimer.Stop(); + SpeedTimer.Dispose(); + SpeedTimer = null; + } + } + + /// + /// Generates the pan/tilt command with either slow or fast speed + /// + /// + /// + /// + private byte[] GetPanTiltCommand(byte[] cmd, bool fastSpeed) + { + byte panSpeed; + byte tiltSpeed; + + if (!fastSpeed) + { + panSpeed = PanSpeedSlow; + tiltSpeed = TiltSpeedSlow; + } + else + { + panSpeed = PanSpeedFast; + tiltSpeed = TiltSpeedFast; + } + + var temp = new byte[] { ID, 0x01, 0x06, 0x01, panSpeed, tiltSpeed }; + int length = temp.Length + cmd.Length + 1; + + byte[] sum = new byte[length]; + temp.CopyTo(sum, 0); + cmd.CopyTo(sum, temp.Length); + sum[length - 1] = 0xFF; + + return sum; + } + + void SendPowerQuery() { SendBytes(new byte[] { ID, 0x09, 0x04, 0x00, 0xFF }); @@ -397,16 +452,14 @@ namespace PepperDash.Essentials.Devices.Common.Cameras PowerOn(); } - - public void PanLeft() { - SendPanTiltCommand(new byte[] {0x01, 0x03}); + SendPanTiltCommand(new byte[] {0x01, 0x03}, false); IsMoving = true; } public void PanRight() { - SendPanTiltCommand(new byte[] { 0x02, 0x03 }); + SendPanTiltCommand(new byte[] { 0x02, 0x03 }, false); IsMoving = true; } public void PanStop() @@ -415,12 +468,12 @@ namespace PepperDash.Essentials.Devices.Common.Cameras } public void TiltDown() { - SendPanTiltCommand(new byte[] { 0x03, 0x02 }); + SendPanTiltCommand(new byte[] { 0x03, 0x02 }, false); IsMoving = true; } public void TiltUp() { - SendPanTiltCommand(new byte[] { 0x03, 0x01 }); + SendPanTiltCommand(new byte[] { 0x03, 0x01 }, false); IsMoving = true; } public void TiltStop() @@ -432,6 +485,8 @@ namespace PepperDash.Essentials.Devices.Common.Cameras { SendBytes(new byte[] {ID, 0x01, 0x04, 0x07, cmd, 0xFF} ); } + + public void ZoomIn() { SendZoomCommand(ZoomInCmd); @@ -456,7 +511,8 @@ namespace PepperDash.Essentials.Devices.Common.Cameras } else { - SendPanTiltCommand(new byte[] {0x03, 0x03}); + StopSpeedTimer(); + SendPanTiltCommand(new byte[] { 0x03, 0x03 }, false); IsMoving = false; } } From d074be323ceb112671696e9cdefa4f480f7ad23d Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Thu, 10 Sep 2020 15:34:28 -0600 Subject: [PATCH 4/6] Remove zoom speeds --- .../Cameras/CameraVisca.cs | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs index 68aace0a..af12834c 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs @@ -38,11 +38,9 @@ namespace PepperDash.Essentials.Devices.Common.Cameras public byte PanSpeedSlow = 0x10; public byte TiltSpeedSlow = 0x10; - public byte ZoomSpeedSlow = 0x03; public byte PanSpeedFast = 0x13; public byte TiltSpeedFast = 0x13; - public byte ZoomSpeedFast = 0x05; private bool IsMoving; private bool IsZooming; @@ -152,15 +150,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras { TiltSpeedFast = (byte)PropertiesConfig.TiltSpeedFast; } - - if (PropertiesConfig.ZoomSpeedSlow > 0) - { - ZoomSpeedSlow = (byte)PropertiesConfig.ZoomSpeedSlow; - } - if (PropertiesConfig.ZoomSpeedFast > 0) - { - ZoomSpeedFast = (byte)PropertiesConfig.ZoomSpeedFast; - } } public override bool CustomActivate() @@ -671,18 +660,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras [JsonProperty("tiltSpeedFast")] public uint TiltSpeedFast { get; set; } - /// - /// Slow zoom speed (0-7) - /// - [JsonProperty("zoomSpeedSlow")] - public uint ZoomSpeedSlow { get; set; } - - /// - /// Fast zoom speed (0-7) - /// - [JsonProperty("zoomSpeedFast")] - public uint ZoomSpeedFast { get; set; } - /// /// Time a button must be held before fast speed is engaged (Milliseconds) /// From 944b72e2a821fd0a944e9b8044fa1ddab98f40ea Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 9 Nov 2020 10:13:53 -0700 Subject: [PATCH 5/6] Adds IHasCameraOff to CameraVisca --- PepperDashEssentials/PepperDashEssentials.csproj | 2 +- .../PepperDash_Essentials_Core.csproj | 2 +- .../Essentials_DM/PepperDash_Essentials_DM.csproj | 2 +- .../Cameras/CameraVisca.cs | 14 ++++++++++++++ .../Essentials Devices Common.csproj | 2 +- 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/PepperDashEssentials/PepperDashEssentials.csproj b/PepperDashEssentials/PepperDashEssentials.csproj index cd8062ce..42d0e288 100644 --- a/PepperDashEssentials/PepperDashEssentials.csproj +++ b/PepperDashEssentials/PepperDashEssentials.csproj @@ -71,7 +71,7 @@ ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll - + False ..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 2b45030c..e2e6519e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -83,7 +83,7 @@ ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll - + False ..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll diff --git a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj index 7d6b7bde..69045ea5 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj +++ b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj @@ -59,7 +59,7 @@ ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll - + False ..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs index af12834c..fb8ae79c 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Cameras/CameraVisca.cs @@ -58,6 +58,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras { _powerIsOn = value; PowerIsOnFeedback.FireUpdate(); + CameraIsOffFeedback.FireUpdate(); } } } @@ -110,6 +111,7 @@ namespace PepperDash.Essentials.Devices.Common.Cameras Communication.BytesReceived += new EventHandler(Communication_BytesReceived); PowerIsOnFeedback = new BoolFeedback(() => { return PowerIsOn; }); + CameraIsOffFeedback = new BoolFeedback(() => { return !PowerIsOn; }); if (props.CommunicationMonitorProperties != null) { @@ -608,6 +610,18 @@ namespace PepperDash.Essentials.Devices.Common.Cameras } } } + + #region IHasCameraOff Members + + public BoolFeedback CameraIsOffFeedback { get; private set; } + + + public void CameraOff() + { + PowerOff(); + } + + #endregion } public class CameraViscaFactory : EssentialsDeviceFactory diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index f115f401..54d37613 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -63,7 +63,7 @@ ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Lighting.dll - + False ..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll From 7d72d5486238eb26245c956150bb8a833e489b45 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 11 Nov 2020 12:08:30 -0700 Subject: [PATCH 6/6] Gets ExternalSourceSwitching feedback working --- PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs | 2 +- .../VideoCodec/CiscoCodec/CiscoSparkCodec.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index 1b936420..ffc6a4db 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -194,7 +194,7 @@ namespace PepperDash.Essentials var vc = VideoCodec as IHasExternalSourceSwitching; if (vc != null) { - vc.SetSelectedSource(_CurrentSourceInfo.SourceKey); + vc.SetSelectedSource(CurrentSourceInfoKey); } } } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs index 4e94daef..429794bc 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/CiscoSparkCodec.cs @@ -1340,7 +1340,6 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco public override void SendDtmf(string s) { SendText(string.Format("xCommand Call DTMFSend CallId: {0} DTMFString: \"{1}\"", GetCallId(), s)); - } public void SelectPresentationSource(int source)