fix(essentials): #901 Overhaul's feedback processing for efficiency

Updates to address changes to ZRAAPI v1.1 and ZoomRooms 5.9.4
This commit is contained in:
Neil Dorin
2022-02-10 15:49:53 -07:00
parent d0097089e6
commit 79a3a8ed7e
2 changed files with 152 additions and 24 deletions

View File

@@ -32,8 +32,20 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private const long MeetingRefreshTimer = 60000; private const long MeetingRefreshTimer = 60000;
public uint DefaultMeetingDurationMin { get; private set; } public uint DefaultMeetingDurationMin { get; private set; }
private const string Delimiter = "\x0D\x0A"; /// <summary>
/// CR LF
/// </summary>
private const string EchoDelimiter = "\x0D\x0A\x0D\x0A";
private const string SendDelimiter = "\x0D";
/// <summary>
/// CR LF } CR LF
/// </summary>
private const string JsonDelimiter = "\x0D\x0A\x7D\x0D\x0A";
private string[] Delimiters = new string[] { EchoDelimiter, JsonDelimiter, "OK\x0D\x0A", "end\x0D\x0A" };
//"echo off\x0D\x0A\x0A\x0D\x0A"
private readonly GenericQueue _receiveQueue; private readonly GenericQueue _receiveQueue;
//private readonly CrestronQueue<string> _receiveQueue; //private readonly CrestronQueue<string> _receiveQueue;
@@ -71,7 +83,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
else else
{ {
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000,
"zStatus SystemUnit\r"); "zStatus SystemUnit" + SendDelimiter);
} }
DeviceManager.AddDevice(CommunicationMonitor); DeviceManager.AddDevice(CommunicationMonitor);
@@ -86,9 +98,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
_syncState.InitialSyncCompleted += SyncState_InitialSyncCompleted; _syncState.InitialSyncCompleted += SyncState_InitialSyncCompleted;
_syncState.FirstJsonResponseReceived += (o, a) => SetUpSyncQueries();
PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync"); PhonebookSyncState = new CodecPhonebookSyncState(Key + "--PhonebookSync");
PortGather = new CommunicationGather(Communication, "\x0A") {IncludeDelimiter = true}; PortGather = new CommunicationGather(Communication, Delimiters) {IncludeDelimiter = true};
PortGather.LineReceived += Port_LineReceived; PortGather.LineReceived += Port_LineReceived;
CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd, CodecOsdIn = new RoutingInputPort(RoutingPortNames.CodecOsd,
@@ -904,7 +918,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
Debug.Console(1, this, "Sending: '{0}'", command); Debug.Console(1, this, "Sending: '{0}'", command);
} }
Communication.SendText(command + Delimiter); Communication.SendText(command + SendDelimiter);
} }
/// <summary> /// <summary>
@@ -914,13 +928,28 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
/// <param name="args"></param> /// <param name="args"></param>
private void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args) private void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
{ {
//if (CommDebuggingIsOn) //Debug.Console(0, this, "Port_LineReceived");
// Debug.Console(1, this, "Gathered: '{0}'", args.Text);
_receiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessMessage)); if (args.Delimiter != JsonDelimiter)
{
// Debug.Console(0, this,
//@"Non JSON response:
//Delimiter: {0}
//{1}", ComTextHelper.GetDebugText(args.Delimiter), args.Text);
ProcessNonJsonResponse(args.Text);
return;
}
else
{
// Debug.Console(0, this,
//@"JSON response:
//Delimiter: {0}
//{1}", ComTextHelper.GetDebugText(args.Delimiter), args.Text);
_receiveQueue.Enqueue(new ProcessStringMessage(args.Text, DeserializeResponse));
//_receiveQueue.Enqueue(new ProcessStringMessage(args.Text, ProcessMessage));
}
} }
/// <summary> /// <summary>
/// Queues the initial queries to be sent upon connection /// Queues the initial queries to be sent upon connection
/// </summary> /// </summary>
@@ -979,6 +1008,84 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
_syncState.StartSync(); _syncState.StartSync();
} }
private void SetupSession()
{
// disable echo of commands
SendText("echo off");
// switch to json format
// set feedback exclusions
// Currently the feedback exclusions don't work when using the API in JSON response mode
// But leave these here in case the API gets updated in the future
// These may work as of 5.9.4
if (_props.DisablePhonebookAutoDownload)
{
SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact");
}
SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list");
SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callout_country_list");
SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist");
SendText("zStatus SystemUnit");
}
/// <summary>
/// Processes non-JSON responses as their are received
/// </summary>
/// <param name="response"></param>
private void ProcessNonJsonResponse(string response)
{
if (response.Contains("client_loop: send disconnect: Broken pipe"))
{
Debug.Console(1, this, Debug.ErrorLogLevel.Error,
"Zoom Room Controller or App connected. Essentials will NOT control the Zoom Room until it is disconnected.");
return;
}
if (!_syncState.InitialSyncComplete)
{
if(response.ToLower().Contains("*r login successful"))
{
_syncState.LoginResponseReceived();
SendText("format json");
SetupSession();
}
//switch (response.Trim().ToLower()) // remove the whitespace
//{
// case "*r login successful":
// {
// _syncState.LoginMessageReceived();
// //// Fire up a thread to send the intial commands.
// //CrestronInvoke.BeginInvoke(o =>
// //{
// // disable echo of commands
// SendText("echo off");
// // switch to json format
// SendText("format json");
// // set feedback exclusions
// // Currently the feedback exclusions don't work when using the API in JSON response mode
// // But leave these here in case the API gets updated in the future
// // These may work as of 5.9.4
// if (_props.DisablePhonebookAutoDownload)
// {
// SendText("zFeedback Register Op: ex Path: /Event/Phonebook/AddedContact");
// }
// SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callin_country_list");
// SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/callout_country_list");
// SendText("zFeedback Register Op: ex Path: /Event/InfoResult/Info/toll_free_callinLlist");
// //});
// break;
// }
//}
}
}
/// <summary> /// <summary>
/// Processes messages as they are dequeued /// Processes messages as they are dequeued
/// </summary> /// </summary>
@@ -1006,7 +1113,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
//Debug.Console(2, this, "JSON Curly Brace Count: {0}", _jsonCurlyBraceCounter); //Debug.Console(2, this, "JSON Curly Brace Count: {0}", _jsonCurlyBraceCounter);
if (!_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + Delimiter) if (!_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "{" + EchoDelimiter)
// Check for the beginning of a new JSON message // Check for the beginning of a new JSON message
{ {
_jsonFeedbackMessageIsIncoming = true; _jsonFeedbackMessageIsIncoming = true;
@@ -1023,7 +1130,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
return; return;
} }
if (_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + Delimiter) if (_jsonFeedbackMessageIsIncoming && message.Trim('\x20') == "}" + EchoDelimiter)
// Check for the end of a JSON message // Check for the end of a JSON message
{ {
_jsonMessage.Append(message); _jsonMessage.Append(message);
@@ -1068,7 +1175,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
case "*r login successful": case "*r login successful":
{ {
_syncState.LoginMessageReceived(); _syncState.LoginResponseReceived();
// Fire up a thread to send the intial commands. // Fire up a thread to send the intial commands.
@@ -1121,6 +1228,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
var message = JObject.Parse(trimmedResponse); var message = JObject.Parse(trimmedResponse);
if (!_syncState.FirstJsonResponseWasReceived)
{
_syncState.ReceivedFirstJsonResponse();
}
var eType = var eType =
(eZoomRoomResponseType) (eZoomRoomResponseType)
Enum.Parse(typeof (eZoomRoomResponseType), message["type"].Value<string>(), true); Enum.Parse(typeof (eZoomRoomResponseType), message["type"].Value<string>(), true);
@@ -1642,19 +1754,17 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
{ {
case "login": case "login":
{ {
_syncState.LoginMessageReceived(); _syncState.LoginResponseReceived();
if (!_syncState.InitialQueryMessagesWereSent) SetupSession();
{
SetUpSyncQueries();
}
JsonConvert.PopulateObject(responseObj.ToString(), Status.Login); JsonConvert.PopulateObject(responseObj.ToString(), Status.Login);
break; break;
} }
case "systemunit": case "systemunit":
{ {
JsonConvert.PopulateObject(responseObj.ToString(), Status.SystemUnit); JsonConvert.PopulateObject(responseObj.ToString(), Status.SystemUnit);
break; break;
@@ -3437,7 +3547,9 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
} }
} }
public bool LoginMessageWasReceived { get; private set; } public bool LoginResponseWasReceived { get; private set; }
public bool FirstJsonResponseWasReceived { get; private set; }
public bool InitialQueryMessagesWereSent { get; private set; } public bool InitialQueryMessagesWereSent { get; private set; }
@@ -3453,6 +3565,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public event EventHandler<EventArgs> InitialSyncCompleted; public event EventHandler<EventArgs> InitialSyncCompleted;
public event EventHandler FirstJsonResponseReceived;
public void StartSync() public void StartSync()
{ {
DequeueQueries(); DequeueQueries();
@@ -3475,13 +3589,26 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
_syncQueries.Enqueue(query); _syncQueries.Enqueue(query);
} }
public void LoginMessageReceived() public void LoginResponseReceived()
{ {
LoginMessageWasReceived = true; LoginResponseWasReceived = true;
Debug.Console(1, this, "Login Message Received."); Debug.Console(1, this, "Login Rsponse Received.");
CheckSyncStatus(); CheckSyncStatus();
} }
public void ReceivedFirstJsonResponse()
{
FirstJsonResponseWasReceived = true;
Debug.Console(1, this, "First JSON Response Received.");
var handler = FirstJsonResponseReceived;
if (handler != null)
{
handler(this, null);
}
CheckSyncStatus();
}
public void InitialQueryMessagesSent() public void InitialQueryMessagesSent()
{ {
InitialQueryMessagesWereSent = true; InitialQueryMessagesWereSent = true;
@@ -3506,7 +3633,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public void CodecDisconnected() public void CodecDisconnected()
{ {
_syncQueries.Clear(); _syncQueries.Clear();
LoginMessageWasReceived = false; LoginResponseWasReceived = false;
FirstJsonResponseWasReceived = false;
InitialQueryMessagesWereSent = false; InitialQueryMessagesWereSent = false;
LastQueryResponseWasReceived = false; LastQueryResponseWasReceived = false;
CamerasHaveBeenSetUp = false; CamerasHaveBeenSetUp = false;
@@ -3515,7 +3643,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
private void CheckSyncStatus() private void CheckSyncStatus()
{ {
if (LoginMessageWasReceived && InitialQueryMessagesWereSent && LastQueryResponseWasReceived && if (LoginResponseWasReceived && FirstJsonResponseWasReceived && InitialQueryMessagesWereSent && LastQueryResponseWasReceived &&
CamerasHaveBeenSetUp) CamerasHaveBeenSetUp)
{ {
InitialSyncComplete = true; InitialSyncComplete = true;

View File

@@ -1,3 +1,3 @@
<packages> <packages>
<package id="PepperDashCore" version="1.1.0" targetFramework="net35" allowedVersions="[1.0,2.0)"/> <package id="PepperDashCore" version="1.1.1-rc-247" targetFramework="net35" allowedVersions="[1.0,2.0)"/>
</packages> </packages>