add phone call logic and commands to Zoom Room

This commit is contained in:
Andrew Welker
2020-10-08 17:09:59 -06:00
parent cdc9cdbe95
commit 1676f5a956
6 changed files with 232 additions and 11 deletions

View File

@@ -760,6 +760,46 @@ namespace PepperDash_Essentials_Core.Bridges.JoinMaps
JoinType = eJoinType.Digital JoinType = eJoinType.Digital
}); });
[JoinName("DialPhoneCall")]
public JoinDataComplete DialPhone =
new JoinDataComplete(new JoinData { JoinNumber = 72, JoinSpan = 1 },
new JoinMetadata
{
Description = "Dial Phone",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("PhoneHookState")]
public JoinDataComplete PhoneHookState =
new JoinDataComplete(new JoinData { JoinNumber = 72, JoinSpan = 1 },
new JoinMetadata
{
Description = "Dial Phone",
JoinCapabilities = eJoinCapabilities.ToSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("EndPhoneCall")]
public JoinDataComplete HangUpPhone =
new JoinDataComplete(new JoinData { JoinNumber = 73, JoinSpan = 1 },
new JoinMetadata
{
Description = "Hang Up PHone",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Digital
});
[JoinName("PhoneString")]
public JoinDataComplete PhoneDialString =
new JoinDataComplete(new JoinData { JoinNumber = 2, JoinSpan = 1 },
new JoinMetadata
{
Description = "Phone Dial String",
JoinCapabilities = eJoinCapabilities.FromSIMPL,
JoinType = eJoinType.Serial
});
public VideoCodecControllerJoinMap(uint joinStart) : base(joinStart, typeof (VideoCodecControllerJoinMap)) public VideoCodecControllerJoinMap(uint joinStart) : base(joinStart, typeof (VideoCodecControllerJoinMap))
{ {
} }

View File

@@ -0,0 +1,14 @@
using PepperDash.Essentials.Core;
namespace PepperDash_Essentials_Core.DeviceTypeInterfaces
{
public interface IHasPhoneDialing
{
BoolFeedback PhoneOffHookFeedback { get; }
StringFeedback CallerIdNameFeedback { get; }
StringFeedback CallerIdNumberFeedback { get; }
void DialPhoneCall(string number);
void EndPhoneCall();
void SendDtmfToPhone(string digit);
}
}

View File

@@ -197,6 +197,7 @@
<Compile Include="Devices\VolumeDeviceChangeEventArgs.cs" /> <Compile Include="Devices\VolumeDeviceChangeEventArgs.cs" />
<Compile Include="DeviceTypeInterfaces\IHasBranding.cs" /> <Compile Include="DeviceTypeInterfaces\IHasBranding.cs" />
<Compile Include="DeviceTypeInterfaces\IHasFarEndContentStatus.cs" /> <Compile Include="DeviceTypeInterfaces\IHasFarEndContentStatus.cs" />
<Compile Include="DeviceTypeInterfaces\IHasPhoneDialing.cs" />
<Compile Include="DeviceTypeInterfaces\IMobileControl.cs" /> <Compile Include="DeviceTypeInterfaces\IMobileControl.cs" />
<Compile Include="Factory\DeviceFactory.cs" /> <Compile Include="Factory\DeviceFactory.cs" />
<Compile Include="Factory\IDeviceFactory.cs" /> <Compile Include="Factory\IDeviceFactory.cs" />

View File

@@ -19,6 +19,7 @@ using PepperDash.Essentials.Devices.Common.Cameras;
using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces;
using PepperDash_Essentials_Core.Bridges.JoinMaps; using PepperDash_Essentials_Core.Bridges.JoinMaps;
using PepperDash_Essentials_Core.DeviceTypeInterfaces;
using Feedback = PepperDash.Essentials.Core.Feedback; using Feedback = PepperDash.Essentials.Core.Feedback;
namespace PepperDash.Essentials.Devices.Common.VideoCodec namespace PepperDash.Essentials.Devices.Common.VideoCodec
@@ -348,6 +349,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
(codec as IHasFarEndContentStatus).ReceivingContent.LinkInputSig(trilist.BooleanInput[joinMap.RecievingContent.JoinNumber]); (codec as IHasFarEndContentStatus).ReceivingContent.LinkInputSig(trilist.BooleanInput[joinMap.RecievingContent.JoinNumber]);
} }
if (codec is IHasPhoneDialing)
{
LinkVideoCodecPhoneToApi(codec as IHasPhoneDialing, trilist, joinMap);
}
trilist.OnlineStatusChange += (device, args) => trilist.OnlineStatusChange += (device, args) =>
{ {
if (!args.DeviceOnLine) return; if (!args.DeviceOnLine) return;
@@ -389,6 +395,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
(codec as IHasCameraOff).CameraIsOffFeedback.FireUpdate(); (codec as IHasCameraOff).CameraIsOffFeedback.FireUpdate();
} }
if (codec is IHasPhoneDialing)
{
(codec as IHasPhoneDialing).PhoneOffHookFeedback.FireUpdate();
}
SharingContentIsOnFeedback.FireUpdate(); SharingContentIsOnFeedback.FireUpdate();
trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall); trilist.SetBool(joinMap.HookState.JoinNumber, IsInCall);
@@ -397,6 +408,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
}; };
} }
private void LinkVideoCodecPhoneToApi(IHasPhoneDialing codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{
codec.PhoneOffHookFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PhoneHookState.JoinNumber]);
trilist.SetSigFalseAction(joinMap.DialPhone.JoinNumber,
() => codec.DialPhoneCall(trilist.StringOutput[joinMap.PhoneDialString.JoinNumber].StringValue));
trilist.SetSigFalseAction(joinMap.HangUpPhone.JoinNumber, codec.EndPhoneCall);
}
private void LinkVideoCodecSelfviewPositionToApi(IHasSelfviewPosition codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap) private void LinkVideoCodecSelfviewPositionToApi(IHasSelfviewPosition codec, BasicTriList trilist, VideoCodecControllerJoinMap joinMap)
{ {
trilist.SetSigFalseAction(joinMap.SelfviewPosition.JoinNumber, codec.SelfviewPipPositionToggle); trilist.SetSigFalseAction(joinMap.SelfviewPosition.JoinNumber, codec.SelfviewPipPositionToggle);

View File

@@ -58,6 +58,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public List<zStatus.AudioVideoInputOutputLineItem> AudioInputs { get; set; } public List<zStatus.AudioVideoInputOutputLineItem> AudioInputs { get; set; }
public List<zStatus.AudioVideoInputOutputLineItem> AudioOuputs { get; set; } public List<zStatus.AudioVideoInputOutputLineItem> AudioOuputs { get; set; }
public List<zStatus.AudioVideoInputOutputLineItem> Cameras { get; set; } public List<zStatus.AudioVideoInputOutputLineItem> Cameras { get; set; }
public zEvent.PhoneCallStatus PhoneCall { get; set; }
public ZoomRoomStatus() public ZoomRoomStatus()
{ {
@@ -74,6 +75,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
AudioInputs = new List<zStatus.AudioVideoInputOutputLineItem>(); AudioInputs = new List<zStatus.AudioVideoInputOutputLineItem>();
AudioOuputs = new List<zStatus.AudioVideoInputOutputLineItem>(); AudioOuputs = new List<zStatus.AudioVideoInputOutputLineItem>();
Cameras = new List<zStatus.AudioVideoInputOutputLineItem>(); Cameras = new List<zStatus.AudioVideoInputOutputLineItem>();
PhoneCall = new zEvent.PhoneCallStatus();
} }
} }
@@ -700,6 +702,84 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
[JsonProperty("why_cannot_pin_share")] [JsonProperty("why_cannot_pin_share")]
public string WhyCannotPinShare { get; set; } public string WhyCannotPinShare { get; set; }
} }
public class PhoneCallStatus:NotifiableObject
{
private bool _isIncomingCall;
private string _peerDisplayName;
private string _peerNumber;
private bool _offHook;
public string CallId { get; set; }
public bool IsIncomingCall {
get { return _isIncomingCall; }
set
{
if(value == _isIncomingCall) return;
_isIncomingCall = value;
NotifyPropertyChanged("IsIncomingCall");
} }
public string PeerDisplayName
{
get { return _peerDisplayName; }
set
{
if (value == _peerDisplayName) return;
_peerDisplayName = value;
NotifyPropertyChanged("PeerDisplayName");
}
}
public string PeerNumber
{
get { return _peerNumber; }
set
{
if (value == _peerNumber) return;
_peerNumber = value;
NotifyPropertyChanged("PeerNumber");
}
}
public string PeerUri { get; set; }
private ePhoneCallStatus _status;
public ePhoneCallStatus Status
{
get { return _status; }
set
{
_status = value;
OffHook = _status == ePhoneCallStatus.PhoneCallStatus_Accepted ||
_status == ePhoneCallStatus.PhoneCallStatus_InCall ||
_status == ePhoneCallStatus.PhoneCallStatus_Init;
}
}
public bool OffHook
{
get { return _offHook; }
set
{
if (value == _offHook) return;
_offHook = value;
NotifyPropertyChanged("OffHook");
}
}
}
public enum ePhoneCallStatus
{
PhoneCallStatus_Terminated,
PhoneCallStatus_Accepted,
PhoneCallStatus_InCall,
PhoneCallStatus_Init,
}
} }
/// <summary> /// <summary>

View File

@@ -17,12 +17,14 @@ using PepperDash.Essentials.Devices.Common.Cameras;
using PepperDash.Essentials.Devices.Common.Codec; using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco; using PepperDash.Essentials.Devices.Common.VideoCodec.Cisco;
using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces; using PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces;
using PepperDash_Essentials_Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor, public class ZoomRoom : VideoCodecBase, IHasCodecSelfView, IHasDirectoryHistoryStack, ICommunicationMonitor,
IRouting, IRouting,
IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraAutoMode, IHasFarEndContentStatus, IHasSelfviewPosition IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraAutoMode,
IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing
{ {
private const long MeetingRefreshTimer = 60000; private const long MeetingRefreshTimer = 60000;
private const uint DefaultMeetingDurationMin = 30; private const uint DefaultMeetingDurationMin = 30;
@@ -114,6 +116,10 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
SupportsCameraOff = _props.SupportsCameraOff; SupportsCameraOff = _props.SupportsCameraOff;
SupportsCameraAutoMode = _props.SupportsCameraAutoMode; SupportsCameraAutoMode = _props.SupportsCameraAutoMode;
PhoneOffHookFeedback = new BoolFeedback(PhoneOffHookFeedbackFunc);
CallerIdNameFeedback = new StringFeedback(CallerIdNameFeedbackFunc);
CallerIdNumberFeedback = new StringFeedback(CallerIdNumberFeedbackFunc);
} }
public CommunicationGather PortGather { get; private set; } public CommunicationGather PortGather { get; private set; }
@@ -195,7 +201,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
protected Func<bool> CameraAutoModeIsOnFeedbackFunc protected Func<bool> CameraAutoModeIsOnFeedbackFunc
{ {
get { return () => false; } get { return () => false; }
} }
protected Func<string> SelfviewPipPositionFeedbackFunc protected Func<string> SelfviewPipPositionFeedbackFunc
{ {
@@ -506,6 +512,28 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
break; break;
} }
}; };
Status.PhoneCall.PropertyChanged += (o, a) =>
{
switch (a.PropertyName)
{
case "IsIncomingCall":
Debug.Console(1, this, "Incoming Phone Call: {0}", Status.PhoneCall.IsIncomingCall);
break;
case "PeerDisplayName":
Debug.Console(1, this, "Peer Display Name: {0}", Status.PhoneCall.PeerDisplayName);
CallerIdNameFeedback.FireUpdate();
break;
case "PeerNumber":
Debug.Console(1, this, "Peer Number: {0}", Status.PhoneCall.PeerNumber);
CallerIdNumberFeedback.FireUpdate();
break;
case "OffHook":
Debug.Console(1, this, "Phone is OffHook: {0}", Status.PhoneCall.OffHook);
PhoneOffHookFeedback.FireUpdate();
break;
}
};
} }
private void SetUpDirectory() private void SetUpDirectory()
@@ -555,8 +583,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (!_props.DisablePhonebookAutoDownload) if (!_props.DisablePhonebookAutoDownload)
{ {
CrestronConsole.AddNewConsoleCommand(s => SendText("zCommand Phonebook List Offset: 0 Limit: 512"), CrestronConsole.AddNewConsoleCommand(s => SendText("zCommand Phonebook List Offset: 0 Limit: 512"),
"GetZoomRoomContacts", "Triggers a refresh of the codec phonebook", "GetZoomRoomContacts", "Triggers a refresh of the codec phonebook",
ConsoleAccessLevelEnum.AccessOperator); ConsoleAccessLevelEnum.AccessOperator);
} }
CrestronConsole.AddNewConsoleCommand(s => GetBookings(), "GetZoomRoomBookings", CrestronConsole.AddNewConsoleCommand(s => GetBookings(), "GetZoomRoomBookings",
@@ -1066,7 +1094,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
case "sharingstate": case "sharingstate":
{ {
JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Sharing); JsonConvert.PopulateObject(responseObj.ToString(), Status.Call.Sharing);
SetLayout(); SetLayout();
break; break;
@@ -1181,6 +1209,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
break; break;
} }
case "phonecallstatus":
{
JsonConvert.PopulateObject(responseObj.ToString(), Status.PhoneCall);
break;
}
default: default:
{ {
break; break;
@@ -1294,8 +1327,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private void SetLayout() private void SetLayout()
{ {
if(!_props.AutoDefaultLayouts) return; if (!_props.AutoDefaultLayouts) return;
if ( if (
(Status.Call.Sharing.State == zEvent.eSharingState.Receiving || (Status.Call.Sharing.State == zEvent.eSharingState.Receiving ||
Status.Call.Sharing.State == zEvent.eSharingState.Sending)) Status.Call.Sharing.State == zEvent.eSharingState.Sending))
@@ -1354,7 +1387,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
if (ActiveCalls.Count == 0) if (ActiveCalls.Count == 0)
{ {
if (callStatus == zStatus.eCallStatus.CONNECTING_MEETING || callStatus == zStatus.eCallStatus.IN_MEETING ) if (callStatus == zStatus.eCallStatus.CONNECTING_MEETING ||
callStatus == zStatus.eCallStatus.IN_MEETING)
{ {
var newStatus = eCodecCallStatus.Unknown; var newStatus = eCodecCallStatus.Unknown;
@@ -1431,6 +1465,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
SetLayout(); SetLayout();
} }
} }
public override void StartSharing() public override void StartSharing()
{ {
SendText("zCommand Call Sharing HDMI Start"); SendText("zCommand Call Sharing HDMI Start");
@@ -1633,7 +1668,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public override void SendDtmf(string s) public override void SendDtmf(string s)
{ {
throw new NotImplementedException(); SendDtmfToPhone(s);
} }
/// <summary> /// <summary>
@@ -1713,6 +1748,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
#endregion #endregion
#region Implementation of IHasCameraAutoMode #region Implementation of IHasCameraAutoMode
//Zoom doesn't support camera auto modes. Setting this to just unmute video //Zoom doesn't support camera auto modes. Setting this to just unmute video
public void CameraAutoModeOn() public void CameraAutoModeOn()
{ {
@@ -1757,7 +1793,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
var nextPipPositionIndex = SelfviewPipPositions.IndexOf(_currentSelfviewPipPosition) + 1; var nextPipPositionIndex = SelfviewPipPositions.IndexOf(_currentSelfviewPipPosition) + 1;
if (nextPipPositionIndex >= SelfviewPipPositions.Count) // Check if we need to loop back to the first item in the list if (nextPipPositionIndex >= SelfviewPipPositions.Count)
// Check if we need to loop back to the first item in the list
nextPipPositionIndex = 0; nextPipPositionIndex = 0;
SelfviewPipPositionSet(SelfviewPipPositions[nextPipPositionIndex]); SelfviewPipPositionSet(SelfviewPipPositions[nextPipPositionIndex]);
@@ -1772,12 +1809,40 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
new CodecCommandWithLabel("DownLeft", "Lower Left") new CodecCommandWithLabel("DownLeft", "Lower Left")
}; };
void ComputeSelfviewPipStatus() private void ComputeSelfviewPipStatus()
{ {
_currentSelfviewPipPosition = _currentSelfviewPipPosition =
SelfviewPipPositions.FirstOrDefault( SelfviewPipPositions.FirstOrDefault(
p => p.Command.ToLower().Equals(Configuration.Call.Layout.Position.ToString().ToLower())); p => p.Command.ToLower().Equals(Configuration.Call.Layout.Position.ToString().ToLower()));
} }
#endregion
#region Implementation of IHasPhoneDialing
private Func<bool> PhoneOffHookFeedbackFunc {get {return () => Status.PhoneCall.OffHook; }}
private Func<string> CallerIdNameFeedbackFunc { get { return () => Status.PhoneCall.PeerDisplayName; } }
private Func<string> CallerIdNumberFeedbackFunc { get { return () => Status.PhoneCall.PeerNumber; } }
public BoolFeedback PhoneOffHookFeedback { get; private set; }
public StringFeedback CallerIdNameFeedback { get; private set; }
public StringFeedback CallerIdNumberFeedback { get; private set; }
public void DialPhoneCall(string number)
{
SendText(String.Format("zCommand Dial PhoneCallOut Number: {0}", number));
}
public void EndPhoneCall()
{
SendText(String.Format("zCommand Dial PhoneHangUp CallId: {0}", Status.PhoneCall.CallId));
}
public void SendDtmfToPhone(string digit)
{
SendText(String.Format("zCommand SendSipDTMF CallId: {0} Key: {1}", Status.PhoneCall.CallId, digit));
}
#endregion #endregion
} }