using System; using System.Collections.Generic; using System.Linq; using System.Text; using Crestron.SimplSharp; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.EthernetCommunication; using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Devices.Common.Codec; namespace PepperDash.Essentials.AppServer.Messengers { public class Ddvc01VtcMessenger : MessengerBase { BasicTriList EISC; /********* Bools *********/ /// /// 724 /// const uint BDialHangup = 724; /// /// 750 /// const uint BCallIncoming = 750; /// /// 751 /// const uint BIncomingAnswer = 751; /// /// 752 /// const uint BIncomingReject = 752; /// /// 741 /// const uint BSpeedDial1 = 741; /// /// 742 /// const uint BSpeedDial2 = 742; /// /// 743 /// const uint BSpeedDial3 = 743; /// /// 744 /// const uint BSpeedDial4 = 744; /// /// 800 /// const uint BDirectorySearchBusy = 800; /// /// 801 /// const uint BDirectoryLineSelected = 801; /// /// 801 when selected entry is a contact /// const uint BDirectoryEntryIsContact = 801; /// /// 802 To show/hide back button /// const uint BDirectoryIsRoot = 802; /// /// 803 Pulse from system to inform us when directory is ready /// const uint DDirectoryHasChanged = 803; /// /// 804 /// const uint BDirectoryRoot = 804; /// /// 805 /// const uint BDirectoryFolderBack = 805; /// /// 806 /// const uint BDirectoryDialSelectedLine = 806; /// /// 811 /// const uint BCameraControlUp = 811; /// /// 812 /// const uint BCameraControlDown = 812; /// /// 813 /// const uint BCameraControlLeft = 813; /// /// 814 /// const uint BCameraControlRight = 814; /// /// 815 /// const uint BCameraControlZoomIn = 815; /// /// 816 /// const uint BCameraControlZoomOut = 816; /// /// 821 - 826 /// const uint BCameraPresetStart = 821; /// /// 831 /// const uint BCameraModeAuto = 831; /// /// 832 /// const uint BCameraModeManual = 832; /// /// 833 /// const uint BCameraModeOff = 833; /// /// 841 /// const uint BCameraSelfView = 841; /// /// 842 /// const uint BCameraLayout = 842; /// /// 843 /// const uint BCameraSupportsAutoMode = 843; /// /// 844 /// const uint BCameraSupportsOffMode = 844; /********* Ushorts *********/ /// /// 760 /// const uint UCameraNumberSelect = 760; /// /// 801 /// const uint UDirectorySelectRow = 801; /// /// 801 /// const uint UDirectoryRowCount = 801; /********* Strings *********/ /// /// 701 /// const uint SCurrentDialString = 701; /// /// 702 /// const uint SCurrentCallName = 702; /// /// 703 /// const uint SCurrentCallNumber = 703; /// /// 731 /// const uint SHookState = 731; /// /// 722 /// const uint SCallDirection = 722; /// /// 751 /// const uint SIncomingCallName = 751; /// /// 752 /// const uint SIncomingCallNumber = 752; /// /// 800 /// const uint SDirectorySearchString = 800; /// /// 801-1055 /// const uint SDirectoryEntriesStart = 801; /// /// 1056 /// const uint SDirectoryEntrySelectedName = 1056; /// /// 1057 /// const uint SDirectoryEntrySelectedNumber = 1057; /// /// 1058 /// const uint SDirectorySelectedFolderName = 1058; /// /// 701-712 0-9*# /// Dictionary DTMFMap = new Dictionary { { "1", 701 }, { "2", 702 }, { "3", 703 }, { "4", 704 }, { "5", 705 }, { "6", 706 }, { "7", 707 }, { "8", 708 }, { "9", 709 }, { "0", 710 }, { "*", 711 }, { "#", 712 }, }; CodecActiveCallItem CurrentCallItem; CodecActiveCallItem IncomingCallItem; ushort PreviousDirectoryLength = 0; /// /// /// /// /// public Ddvc01VtcMessenger(string key, BasicTriList eisc, string messagePath) : base(key, messagePath) { EISC = eisc; CurrentCallItem = new CodecActiveCallItem(); CurrentCallItem.Type = eCodecCallType.Video; CurrentCallItem.Id = "-video-"; } /// /// /// /// protected override void CustomRegisterWithAppServer(CotijaSystemController appServerController) { var asc = appServerController; EISC.SetStringSigAction(SHookState, s => { CurrentCallItem.Status = (eCodecCallStatus)Enum.Parse(typeof(eCodecCallStatus), s, true); PostFullStatus(); // SendCallsList(); }); EISC.SetStringSigAction(SCurrentCallNumber, s => { CurrentCallItem.Number = s; PostCallsList(); }); EISC.SetStringSigAction(SCurrentCallName, s => { CurrentCallItem.Name = s; PostCallsList(); }); EISC.SetStringSigAction(SCallDirection, s => { CurrentCallItem.Direction = (eCodecCallDirection)Enum.Parse(typeof(eCodecCallDirection), s, true); PostCallsList(); }); EISC.SetBoolSigAction(BCallIncoming, b => { if (b) { var ica = new CodecActiveCallItem() { Direction = eCodecCallDirection.Incoming, Id = "-video-incoming", Name = EISC.GetString(SIncomingCallName), Number = EISC.GetString(SIncomingCallNumber), Status = eCodecCallStatus.Ringing, Type = eCodecCallType.Video }; IncomingCallItem = ica; } else { IncomingCallItem = null; } PostCallsList(); }); EISC.SetBoolSigAction(BCameraSupportsAutoMode, b => { PostStatusMessage(new { cameraSupportsAutoMode = b }); }); EISC.SetBoolSigAction(BCameraSupportsOffMode, b => { PostStatusMessage(new { cameraSupportsOffMode = b }); }); // Directory insanity EISC.SetUShortSigAction(UDirectoryRowCount, u => { // The length of the list comes in before the list does. // Splice the sig change operation onto the last string sig that will be changing // when the directory entries make it through. if (PreviousDirectoryLength > 0) { EISC.ClearStringSigAction(SDirectoryEntriesStart + PreviousDirectoryLength - 1); } EISC.SetStringSigAction(SDirectoryEntriesStart + u - 1, s => PostDirectory()); PreviousDirectoryLength = u; }); EISC.SetStringSigAction(SDirectoryEntrySelectedName, s => { PostStatusMessage(new { directoryContactSelected = new { name = EISC.GetString(SDirectoryEntrySelectedName), } }); }); EISC.SetStringSigAction(SDirectoryEntrySelectedNumber, s => { PostStatusMessage(new { directoryContactSelected = new { number = EISC.GetString(SDirectoryEntrySelectedNumber), } }); }); EISC.SetStringSigAction(SDirectorySelectedFolderName, s => PostStatusMessage(new { directorySelectedFolderName = EISC.GetString(SDirectorySelectedFolderName) })); EISC.SetSigTrueAction(BCameraModeAuto, () => PostCameraMode()); EISC.SetSigTrueAction(BCameraModeManual, () => PostCameraMode()); EISC.SetSigTrueAction(BCameraModeOff, () => PostCameraMode()); EISC.SetBoolSigAction(BCameraSelfView, b => PostStatusMessage(new { cameraSelfView = b })); EISC.SetUShortSigAction(UCameraNumberSelect, (u) => PostSelectedCamera()); // Add press and holds using helper action Action addPHAction = (s, u) => AppServerController.AddAction(MessagePath + s, new PressAndHoldAction(b => EISC.SetBool(u, b))); addPHAction("/cameraUp", BCameraControlUp); addPHAction("/cameraDown", BCameraControlDown); addPHAction("/cameraLeft", BCameraControlLeft); addPHAction("/cameraRight", BCameraControlRight); addPHAction("/cameraZoomIn", BCameraControlZoomIn); addPHAction("/cameraZoomOut", BCameraControlZoomOut); // Add straight pulse calls using helper action Action addAction = (s, u) => AppServerController.AddAction(MessagePath + s, new Action(() => EISC.PulseBool(u, 100))); addAction("/endCallById", BDialHangup); addAction("/endAllCalls", BDialHangup); addAction("/acceptById", BIncomingAnswer); addAction("/rejectById", BIncomingReject); addAction("/speedDial1", BSpeedDial1); addAction("/speedDial2", BSpeedDial2); addAction("/speedDial3", BSpeedDial3); addAction("/speedDial4", BSpeedDial4); addAction("/cameraModeAuto", BCameraModeAuto); addAction("/cameraModeManual", BCameraModeManual); addAction("/cameraModeOff", BCameraModeOff); addAction("/cameraSelfView", BCameraSelfView); addAction("/cameraLayout", BCameraLayout); asc.AddAction("/cameraSelect", new Action(SelectCamera)); // camera presets for(uint i = 0; i < 6; i++) { addAction("/cameraPreset" + (i + 1), BCameraPresetStart + i); } asc.AddAction(MessagePath + "/isReady", new Action(PostIsReady)); // Get status asc.AddAction(MessagePath + "/fullStatus", new Action(PostFullStatus)); // Dial on string asc.AddAction(MessagePath + "/dial", new Action(s => EISC.SetString(SCurrentDialString, s))); // Pulse DTMF asc.AddAction(MessagePath + "/dtmf", new Action(s => { if (DTMFMap.ContainsKey(s)) { EISC.PulseBool(DTMFMap[s], 100); } })); // Directory madness asc.AddAction(MessagePath + "/directoryRoot", new Action(() => EISC.PulseBool(BDirectoryRoot))); asc.AddAction(MessagePath + "/directoryBack", new Action(() => EISC.PulseBool(BDirectoryFolderBack))); asc.AddAction(MessagePath + "/directoryById", new Action(s => { // the id should contain the line number to forward to simpl try { var u = ushort.Parse(s); EISC.SetUshort(UDirectorySelectRow, u); EISC.PulseBool(BDirectoryLineSelected); } catch (Exception) { Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "/directoryById request contains non-numeric ID incompatible with DDVC bridge"); } })); asc.AddAction(MessagePath + "/directorySelectContact", new Action(s => { try { var u = ushort.Parse(s); EISC.SetUshort(UDirectorySelectRow, u); EISC.PulseBool(BDirectoryLineSelected); } catch { } })); asc.AddAction(MessagePath + "/directoryDialContact", new Action(() => { EISC.PulseBool(BDirectoryDialSelectedLine); })); asc.AddAction(MessagePath + "/getDirectory", new Action(() => { if (EISC.GetUshort(UDirectoryRowCount) > 0) { PostDirectory(); } else { EISC.PulseBool(BDirectoryRoot); } })); } /// /// /// void PostFullStatus() { this.PostStatusMessage(new { calls = GetCurrentCallList(), cameraMode = GetCameraMode(), cameraSelfView = EISC.GetBool(BCameraSelfView), cameraSupportsAutoMode = EISC.GetBool(BCameraSupportsAutoMode), cameraSupportsOffMode = EISC.GetBool(BCameraSupportsOffMode), currentCallString = EISC.GetString(SCurrentCallNumber), currentDialString = EISC.GetString(SCurrentDialString), directoryContactSelected = new { name = EISC.GetString(SDirectoryEntrySelectedName), number = EISC.GetString(SDirectoryEntrySelectedNumber) }, directorySelectedFolderName = EISC.GetString(SDirectorySelectedFolderName), isInCall = EISC.GetString(SHookState) == "Connected", hasDirectory = true, hasDirectorySearch = false, hasRecents = !EISC.BooleanOutput[502].BoolValue, hasCameras = true, showCamerasWhenNotInCall = EISC.BooleanOutput[503].BoolValue, selectedCamera = GetSelectedCamera(), }); } /// /// /// void PostDirectory() { var u = EISC.GetUshort(UDirectoryRowCount); var items = new List(); for (uint i = 0; i < u; i++) { var name = EISC.GetString(SDirectoryEntriesStart + i); var id = (i + 1).ToString(); // is folder or contact? if (name.StartsWith("[+]")) { items.Add(new { folderId = id, name = name }); } else { items.Add(new { contactId = id, name = name }); } } var directoryMessage = new { currentDirectory = new { isRootDirectory = EISC.GetBool(BDirectoryIsRoot), directoryResults = items } }; PostStatusMessage(directoryMessage); } /// /// /// void PostCameraMode() { PostStatusMessage(new { cameraMode = GetCameraMode() }); } /// /// /// /// string GetCameraMode() { string m; if (EISC.GetBool(BCameraModeAuto)) m = "auto"; else if (EISC.GetBool(BCameraModeManual)) m = "manual"; else m = "off"; return m; } void PostSelectedCamera() { PostStatusMessage(new { selectedCamera = GetSelectedCamera() }); } /// /// /// string GetSelectedCamera() { var num = EISC.GetUshort(UCameraNumberSelect); string m; if (num == 100) { m = "cameraFar"; } else { m = "camera" + num; } return m; } /// /// /// void PostIsReady() { PostStatusMessage(new { isReady = true }); } /// /// /// void PostCallsList() { PostStatusMessage(new { calls = GetCurrentCallList(), }); } /// /// /// /// void SelectCamera(string s) { var cam = s.Substring(6); if (cam.ToLower() == "far") { EISC.SetUshort(UCameraNumberSelect, 100); } else { EISC.SetUshort(UCameraNumberSelect, UInt16.Parse(cam)); } } /// /// Turns the /// /// List GetCurrentCallList() { var list = new List(); if (CurrentCallItem.Status != eCodecCallStatus.Disconnected) { list.Add(CurrentCallItem); } if (EISC.GetBool(BCallIncoming)) { } return list; } } }