From f1ea5f38725a5b6e153b2719f9912aa12235ed40 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 12 May 2017 08:31:04 -0600 Subject: [PATCH] Resolves ECS-318 and resolves ECS-314. Storing GUIDs to JSON file in NVRAM and reading them on boot if file exists to ensure consitent GUIDs for each system. --- .../PepperDash_Essentials_Core.projectinfo | Bin 1281 -> 1285 bytes .../Essentials_DM/Essentials_DM.projectinfo | Bin 1134 -> 1136 bytes .../Essentials Devices Common.projectinfo | Bin 1157 -> 1161 bytes .../PepperDashEssentials/ControlSystem.cs | 2 +- .../Fusion/FusionSystemController.cs | 465 ++++++++++++++---- .../PepperDashEssentials.projectinfo | Bin 1861 -> 1868 bytes 6 files changed, 362 insertions(+), 105 deletions(-) diff --git a/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo b/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo index b84c3a2c26ad765e436b0ff7eaebd2919f5a0cd5..0c3778c83af7257fd5f99b352a029a16aa3ff423 100644 GIT binary patch delta 1138 zcmV-&1daQF3WW-gg@5wVqqbhtFH`#JWxiVF_0z1G|Nf^^ z)PR1R%a05CvA47PV0-8O_U_)Bor6bv^uPV_{d+r~?%lt)z4Pg#ogHd7r*n0V01hb+50RHeb9DBsWeGjq9S$7H6|J*~Kl}F7jF?^msNa z+M-%!CCDP5om7hz(P#GM@|Lr0UicwW^_G)=x|rm%*VVe7=EwDPUR>su8&0a#^_%Kh zRnGFd`RI`mq`i-R$>^gmie<4_FP;_k;wr22pQIKti$*?TZ~xcBhk!+SdiJ9`iI&UYTnrn~0{dk=Q@sHM!+twyAT zzq#S_YMPZllxez|FNJ@MPxDp2oaM_Yb^Xz!@0r=SAI`=}P19Xh%kk@Cu_|BBvwB71 zJARs97SsIodbO(RRskx3r&*ToPxkljKg_c8Pj?^g+<$n!ljZmJ_aEGwoX-LRzXx=A z=k|TvZe||62L?anDeOr-K2dH&eVToc78vbo@WO;)9Jm* zi-tH`)96a3J-8-1<&TcbP24pZjw*dTs(_^~*fAO3=xYeATw)4DR<}I18#d=vx zGZ?}qoTq!A=AV9gZ~x(g-G}#g_jmIA)AQZQem?s& zh|2$q=kwrJ^Z9=&UsP@0nZWFP@6&u|vUhK1fA3-b>BGJ0?B4yIeER9V>BF4|ll&GF z7{U!^>=w{JY{tUA|6e>s4{tR^U!8@svvct9-tJzuGo9>A_V3?&u=8MVMhw4qZ$E#q zoA2Cab}YzXVr~KW!zRXd`~TuO+1&{z#T%;Uj2MdT%yxe#4`&At9^AYC@ZkRW{`n-| zpU&>zpYBcW@3WsDbIv?K;RM_a?v@h}@9h80WZw&t|jpgNOI0_dd<0lk;qv@67J|wBGWb3$OC?5@C0> zJX^MT4SIis(~;jhKR?K4lSy{4Kb_7V?B2gWdHC>PKmYW>{=vZ{aHDSnHkg-N0Dtd! z8SeW3%@cHQXo6n<#Pe_GCG|2eKj%Bs`#bk%vwS)`$Q~Tro9#~?+~3=MaDRs)%*lg+ z`5A;7OwTP~zxVVE_Wb|8+39>>=W2gwuAXLXHl9jlt(%>Ly`9OYyVL!H=|Q$PrNJKT zJ-q)Q&u7H$_Z~c$4j7Uc4R1~C4lN_-{gUthl3&94i{f1UUK;1RY-QO04|lEQf=3kq E0F3pMApigX delta 1134 zcmV-!1d;oN3V{lcg@0myo6>hL^VKS^pJvVc_dji#eAyQC-S2-=)j7R1yQx7=4d}v07yZ`9k{YSey<4-?*uzPT@z4Pg#ogHd6r)DRQe&65syH)+R zSYD)0i#ngSRbAxG@B90@?tb6j_w|qezQ1p7`}}=>U)O(%{uuqn?yDzRL*Gn_rT=vo z_3?C7{(w*^EG?5D0V02k?(6HO%@;2O%Z*b+1G}iR#o6plc5%zLi@cTzJ)X^qwy2g_ z3A)H0@9obH9_IP}{k=VEDRXtJ5h>wsZuq>K zX5|lMnr`MxA>)73e3dU}`Ep8KfAr{kW;X7JvvE?>bl25#{JL1I%GdL(UXk>UpXQgv zG=IHbt*W|JfJ)$LmgW1C{k{7Sv+VrS-G@8(AD-`I`Mv%92lpoDvw*rNAP4k`EeV_Ilpam0f3z)Z@fDJwVzj+q+hGyYaeqJK%u9j!ZHm^aC za5{hTd*|l|`D`-D4)&+h*@NBt_a_e@9_;6zKG;7vm;`S0ZNLWeatq+^Jukyu|G#;H z?hQ@Q>z{c3?YyL32Il8{XL^6<{%n>{X9wAXgL||6$%FfQyAST~>`o_>2Ltmn2sN0V zTflzr=^5<#|9!L5`M}OqCsE+W_B3m=@hnPf-RvCf?My!1o$en@53;=}4fbH~;r$1B zJ|lL&_u#>Fz>vgfcxz&JXcJs(5LCJp zCWJ5QY;iVwlU)pdy~t~sg5%k&Xp3r@l^CLYc2X@?G}hUd%UjNmdEsZ5Lc`N_x|rm% z*VVe7=EwDPUVmKXcK%MP)%Ba|Syj&Ry7}mlVdK4ze#z*gFN$TcSTCLx_2Me4^Pi*^ zLQxLh9g)Y+0P=P3y3`N1y8SI=H`obm(7X#qyZG zSWL=m2VkGR@g`#s$gC`>WiW91Z};B*eL(2Yr%RY`6MsDV?EcPd_x#h{{e$VJ4v~(VDG_BpoeaR z84&*#kl&a1@m~MmH4hKNd2k~7BEM>@WmBDZEWyL+&co^b*}a`vmd|Fh^Mi-?r}sY1 zrhk+3Y?|-P?)x*a0a`%&Tfn>(?KkxI|1PTU?hKLrReoN=!>*QR%Qmk;fRO(Az4P;f zd^VY62m90M?7{B+`;&(c5BBpiuO_ML%f@%a05CvA47PV0-8O z_RhmMyZevs-G8+E>3Hwnr=K3|(`TPP+S#FYb82_;==c47zgyLBi{(Z7w5aoGTh&G0 z{Jy{M%Y3!U>!(>W|9yYo*FXOI{=T{G^7s9HUH9qJFZ@4$e}DWrDVCkj#?w{#1M0A_ z1AAFlKTUm|EzhfGMVT+NMgFscOo+!yx-F<%Lg%cZPTFgW)a&b}%@;2OmoAA3=HLcs48AqFQDp#weeiRErf2cJ}4+mJ?)N_}L}V@O+&vCi(1jwXUc6 zaXp^!9Z?>!{oU#{ELx_z0oKPzlV9ej~3i}So`9d`HVQ=MK1_xFzu{fn$v9@7_#NqOx6 z?9(^iWDEkCl_j+d22TI&?eE`z@KKLGUBY~u;Ni2~$$$RN-sIDJJ9~TQ_s$>O3U<&dzLi@^E(W;K9B74-f92?|+|9^8M-T{{89Rh73&xoP#J$Nv^*+P7f l-ycEkmwf-1{1T34it}QcK@@0=>#~(0|36Y@(d5Js000LEI?n(A diff --git a/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.projectinfo b/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.projectinfo index 5725875d1b74316cc82a975d26ed8c1aab0b87f2..64d5ed77c0ebe519fcadc0577ae6f3508f799a74 100644 GIT binary patch delta 939 zcmV;c162Hl35f}ig-`O)qqbhtFH`#Jv}y8XThKS@)BLiS=1qE1Ef&?1UYP~o|Ni>@ z?|(vH<@6Q(IF}z6^kZ*l_rdng{q5boH#-N9_UL~P#t%Qe_u&4+-I38v0hp5?0V03q z@%44n=8G4C?xqQ)0bbPE;%xRNy9k;FbE~Zuc`dVhJew75Q7y9)l#$N}kib=9V>1s@3(I>RDCJ^1AuxkrAxDkABJMqc4hO zu~;vj74_mOtMi|v7DO$G-FRo`A^m@U?;!#Ia^0@h?aQqFp$Y+Y{6)4b&hw^qSl^>h zZ{ik1lP|Jjc}$HKlk(a@*r#v2nH+{PD@$q`kc9r*y|;gV@1q{&x+MEHk%2y&e!82T z@9o_C^xn?F!^wX3VD{<$?EW;HetLe8?|%yJl1aPGcyt18Z1=pHX5|liwr+o9R3Ycn ze3dU}`Ep7~eDvshW>W5llX6niq}TM)>teAgU(d68MUp)hh_BbHRaLhN&=5My^8LyF z-u;JJcK+$^!=3vN&v&x?-v0iBdz16oo=@oafG+RczK>f?(WCc3;OA~G`;+zk(MPZH zhAF~-{*sZIzE5v8eV=D-ewBY+H{r}Z*xTRB_jdQP?B2oty}iAI?EdWGZa(?+(}TT- z=Lgv>X08J`n6z7f|DZ|h^!@*h`Faq}m&51xKdI_GoS&VY+3w`w?BKzJd-oq6+&|wx zpXB?~+5P*|y~+Lkoj`@f0R{7M3vjoak9c4I-=P1&ApKn*k*V07PWFE%dk-cL_Z~ic zNET&h@4?>r&V$)>_xxb*!A_v$ZiE@k$}J$j_pHRb{r|=UJq#zviTsQFs;!nyb>6W* z52rg1r}t;~c4k>Vo6XJ-9^Rkc`!t(Q&a-L0GrR9k%?4<}q}&4L?IvYIhyUN0j@_N1 z`FNF|mk2JZ<=L{$YfyhCoS6LHIk{T1$s{}2pH62FcJJSxJbZYtpMUyb|KMN}$joiP z1~YUE;O{#_!#)3hWU6+Drt0-iJpXoH5_SVKb-pvbzjJ>!%crx0?7_jk+5Y6g{k`1> z_jgD;O&$!))F9MgqHY2EeJ5(L!a?My!1o$en@ z53)T9WpZ+)?mx)$8HvEX2M?zHJZ+}tZK>WNY6Q7o^8H`(OE^|5&WmXV>7h}s%T@;c N{{YOumsm^^001+E9X|j7 delta 935 zcmV;Y16cft355xeg-l|9o6>iuO_ML%f<8!}=9k4ZZ_<-$v8a~x&Mf%;_t)=#{}cKu zr?2S8x%{}GAA38y54LyiZ|^*Ov%CN3-u*|r_r~`>efVJS;lq*CO#zRSA^{?Q5r2K% zwE5zN;Jax?X@nPbwm6%;$u5GX!Q^VIMPAGF9?xb)TU5)e1Zm_m0=Xg@&AwdTa_-Fw zKR1-U9V?tJCi(1jwXUc6aXp!{oU#{ELx_z0oKU688j=#v3#d+Se4(ogL=}p{X zX!1o?ERU(tVp3i^2>bMnHXH~DmSzJKpvx^w?vGJUXnPAz59ZZjU8fE(LAucle~!=9~w8yQu|`7~eU z%UQmh5)vOh`kt8-P}CQ%nkK!bmtGf(Rrz|J)hm+hu|RyiUahLSRe(z9X_n>tll{H> z53}t2)7^(V_aC0`Wcj`Q{Rj6Z=d(SZ(C-0V-no4rx0<3y?}5P2-CXu3>-(dRUgZr_ zg#Y{{BQt%U-fH?j&)WQdD!XpNnR~FeznAar?q%7%gZ+DZdk5M5*~8s@0;zd;evsW_ z<~o3bNxKF351O=2-~Zp3uLt3LIedQqld8_c`Ptc-?M@!f4jw$XcmLtR{qz0vNxnaw z-M>HGo7~@L18L_c4k(z9TY$UWe8l_u{|5aJ2I=qmh)l&U5ij3=xtH%9Jlvgpn(cl1 z@O<|0-u~?1VV>{b-wTx7jWB~*xdr6+o|SmF|KFIPhv5V{k$;h2wbinz&O7$!;dJNW z^#1JL&MeDkv)TEj@c$drvAZ)gAFuNB z646DqJX^MT4a$Un6O-RNKR?K4lSy{4Kb_7V?B2gWdHC>PKmYW>{=vZ{keSe9YBU?Ki&Z~pOFaMd+=cD&(mgV-j?beqDGMWCEx!gzl3A8;=Gt diff --git a/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs b/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs index 6b79c2f7..29fc2643 100644 --- a/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs +++ b/Essentials/PepperDashEssentials/Fusion/FusionSystemController.cs @@ -11,6 +11,8 @@ using Crestron.SimplSharp.CrestronXmlLinq; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.Fusion; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using PepperDash.Essentials.Core; @@ -19,6 +21,7 @@ using PepperDash.Essentials; using PepperDash.Essentials.Devices.Common; + namespace PepperDash.Essentials.Fusion { public class EssentialsHuddleSpaceFusionSystemController : Device @@ -34,7 +37,17 @@ namespace PepperDash.Essentials.Fusion ScheduleResponse CurrentSchedule; - string GUID; + Event NextMeeting; + + Event CurrentMeeting; + + string RoomGuid; + + uint IpId; + + bool GuidFileExists; + + List StaticAssets; //ScheduleResponseEvent NextMeeting; @@ -43,44 +56,189 @@ namespace PepperDash.Essentials.Fusion { Room = room; + IpId = ipId; + + StaticAssets = new List(); + var mac = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, 0); var slot = Global.ControlSystem.ProgramNumber; - //adminvar guid = new Guid(); + string guidFilePath = string.Format(@"\NVRAM\Program{0}\{1}-FusionGuids.json", Global.ControlSystem.ProgramNumber, InitialParametersClass.ProgramIDTag); - GUID = string.Format("{0}-{1}-{2}", slot, mac, Room.Name.Replace(" ", String.Empty)); + GuidFileExists = File.Exists(guidFilePath); - CreateSymbolAndBasicSigs(ipId); + if (GuidFileExists) + { + ReadGuidFile(guidFilePath); + } + else + { + IpId = ipId; + + Guid roomGuid = Guid.NewGuid(); + + RoomGuid = string.Format("{0}-{1}-{2}", slot, mac, roomGuid.ToString()); + } + + CreateSymbolAndBasicSigs(IpId); SetUpSources(); SetUpCommunitcationMonitors(); SetUpDisplay(); SetUpError(); // test assets --- THESE ARE BOTH WIRED TO AssetUsage somewhere internally. - var ta1 = FusionRoom.CreateStaticAsset(1, "Test asset 1", "Awesome Asset", "Awesome123"); - ta1.AssetError.InputSig.StringValue = "This should be error"; + var tempAsset1 = new StaticAsset(); + var tempAsset2 = new StaticAsset(); - var ta2 = FusionRoom.CreateStaticAsset(2, "Test asset 2", "Awesome Asset", "Awesome1232"); - ta2.AssetUsage.InputSig.StringValue = "This should be usage"; + //Check for existing GUID + if (GuidFileExists) + { + tempAsset1 = StaticAssets.FirstOrDefault(a => a.Number.Equals(1)); - // Make it so! - FusionRVI.GenerateFileForAllFusionDevices(); + tempAsset2 = StaticAssets.FirstOrDefault(a => a.Number.Equals(2)); + } + else + { + tempAsset1 = new StaticAsset(1, "Test Asset 1", "Test Asset 1", ""); + StaticAssets.Add(tempAsset1); + + tempAsset2 = new StaticAsset(2, "Test Asset 2", "Test Asset 2", ""); + StaticAssets.Add(tempAsset2); + } + + var ta1 = FusionRoom.CreateStaticAsset(tempAsset1.Number, tempAsset1.Name, tempAsset1.Type, tempAsset1.InstanceID); + ta1.AssetError.InputSig.StringValue = "This should be error"; + + var ta2 = FusionRoom.CreateStaticAsset(tempAsset2.Number, tempAsset2.Name, tempAsset2.Type, tempAsset2.InstanceID); + ta2.AssetUsage.InputSig.StringValue = "This should be usage"; + + // Make it so! + FusionRVI.GenerateFileForAllFusionDevices(); + + GenerateGuidFile(guidFilePath); } + /// + /// Generates the guid file in NVRAM + /// + /// path for the file + void GenerateGuidFile(string filePath) + { + if (string.IsNullOrEmpty(filePath)) + { + Debug.Console(0, this, "Error writing guid file. No path specified."); + return; + } + + CCriticalSection _fileLock = new CCriticalSection(); + + try + { + if (_fileLock == null || _fileLock.Disposed) + return; + + _fileLock.Enter(); + + Debug.Console(1, this, "Writing GUIDs to file"); + + var GUIDs = new FusionRoomGuids(Room.Name, IpId, RoomGuid, StaticAssets); + + var JSON = JsonConvert.SerializeObject(GUIDs, Newtonsoft.Json.Formatting.Indented); + + using (StreamWriter sw = new StreamWriter(filePath)) + { + sw.Write(JSON); + sw.Flush(); + } + + Debug.Console(1, this, "Guids successfully written to file '{0}'", filePath); + + } + catch (Exception e) + { + Debug.Console(0, this, "Error writing guid file: {0}", e); + } + finally + { + if (_fileLock != null && !_fileLock.Disposed) + _fileLock.Leave(); + } + } + + /// + /// Reads the guid file from NVRAM + /// + /// path for te file + void ReadGuidFile(string filePath) + { + if(string.IsNullOrEmpty(filePath)) + { + Debug.Console(0, this, "Error reading guid file. No path specified."); + return; + } + + CCriticalSection _fileLock = new CCriticalSection(); + + try + { + if(_fileLock == null || _fileLock.Disposed) + return; + + _fileLock.Enter(); + + if(File.Exists(filePath)) + { + var JSON = File.ReadToEnd(filePath, Encoding.ASCII); + + var GUIDs = JsonConvert.DeserializeObject(JSON); + + IpId = GUIDs.IpId; + + RoomGuid = GUIDs.RoomGuid; + + StaticAssets = GUIDs.StaticAssets; + + } + + Debug.Console(0, this, "Fusion Guids successfully read from file:"); + + Debug.Console(1, this, "\nRoom Name: {0}\nIPID: {1}\n RoomGuid: {2}", Room.Name, IpId, RoomGuid); + + foreach (StaticAsset asset in StaticAssets) + { + Debug.Console(1, this, "\nAsset Name: {0}\nAsset No: {1}\n Guid: {2}", asset.Name, asset.Number, asset.InstanceID); + } + } + catch (Exception e) + { + Debug.Console(0, this, "Error reading guid file: {0}", e); + } + finally + { + if(_fileLock != null && !_fileLock.Disposed) + _fileLock.Leave(); + } + + } + + void CreateSymbolAndBasicSigs(uint ipId) { - Debug.Console(1, this, "Creating Fusion Room symbol with GUID: {0}", GUID); + Debug.Console(1, this, "Creating Fusion Room symbol with GUID: {0}", RoomGuid); - FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, GUID); + FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid); FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use(); + FusionRoom.ExtenderFusionRoomDataReservedSigs.Use(); FusionRoom.Register(); - FusionRoom.FusionStateChange += new FusionStateEventHandler(FusionRoom_FusionStateChange); + FusionRoom.FusionStateChange += new FusionStateEventHandler(FusionRoom_FusionStateChange); FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.DeviceExtenderSigChange += new DeviceExtenderJoinChangeEventHandler(FusionRoomSchedule_DeviceExtenderSigChange); + FusionRoom.ExtenderFusionRoomDataReservedSigs.DeviceExtenderSigChange += new DeviceExtenderJoinChangeEventHandler(ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange); + FusionRoom.OnlineStatusChange += new OnlineStatusChangeEventHandler(FusionRoom_OnlineStatusChange); CrestronConsole.AddNewConsoleCommand(RequestFullRoomSchedule, "FusReqRoomSchedule", "Requests schedule of the room for the next 24 hours", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(ModifyMeetingEndTimeConsoleHelper, "FusReqRoomSchMod", "Ends or extends a meeting by the specified time", ConsoleAccessLevelEnum.AccessOperator); @@ -98,33 +256,57 @@ namespace PepperDash.Essentials.Fusion FusionRoom.ErrorMessage.InputSig.StringValue = "3: 7 Errors: This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;"; + } + void FusionRoom_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args) + { + if (args.DeviceOnLine) + { + // Send Push Notification Action request: + + string requestID = "InitialPushRequest"; + + + string actionRequest = + string.Format("{0}{1}", requestID, RoomGuid) + + "RegisterPushModel" + + "" + + "" + + "" + + "" + + "" + + "'"; + + Debug.Console(1, this, "Sending Fusion ScheduleQuery: \n{0}", actionRequest); + + FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = actionRequest; + } + + } + + /// /// Generates a room schedule request for this room for the next 24 hours. /// /// string identifying this request. Used with a corresponding ScheduleResponse value public void RequestFullRoomSchedule(string requestID) { - //Need to see if we can omit the XML declaration + DateTime now = DateTime.Today; - //XmlWriterSettings settings = new XmlWriterSettings(); - //settings.OmitXmlDeclaration = true; + //string currentTime = string.Format("Current time: {0:D4}-{1:D2}-{2:D2}T{3:D2}:{4:D2}:{5:D2}", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second); - //StringBuilder builder = new StringBuilder(); + string currentTime = now.ToString("s"); - //XmlWriter xmlWriter = new XmlWriter(builder, settings); + Debug.Console(1, this, "Current time: {0}", currentTime); - //RequestSchedule request = new RequestSchedule(requestID, GUID); + //Debug.Console(1, this, "Current time: {0}", now.ToString("d")); - //CrestronXMLSerialization.SerializeObject(xmlWriter, request); - - DateTime now = DateTime.UtcNow; - - Debug.Console(1, this, "Current time: {0}-{1}-{2}T{3}:{4}:{5}", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second); + //string requestTest = + // string.Format("{0}{1}2017-05-02T00:00:0024", requestID, GUID); string requestTest = - string.Format("{0}{1}2017-05-02T00:00:0024", requestID, GUID); + string.Format("{0}{1}{2}24", requestID, RoomGuid, currentTime); Debug.Console(1, this, "Sending Fusion ScheduleQuery: \n{0}", requestTest); @@ -170,103 +352,114 @@ namespace PepperDash.Essentials.Fusion /// Number of minutes to extend the meeting. A value of 0 will end the meeting. public void ModifyMeetingEndTime(string requestID, PepperDash.Essentials.Fusion.Event meeting, int extendMinutes) { - //StringWriter stringWriter = new StringWriter(); - - //List parameters = new List(); - - //parameters.Add( new Parameter { ID = "MeetingID", Value = meeting.MeetingID }); - - //parameters.Add( new Parameter { ID = "EndTime", Value = extendMinutes.ToString()}); - - //RequestAction request = new RequestAction(GUID, "MeetingChange", parameters); - - //CrestronXMLSerialization.SerializeObject(stringWriter, request); - string requestTest = string.Format( - "{0}{1}MeetingChange" - , requestID, GUID, meeting.MeetingID, extendMinutes); + "{0}{1}MeetingChange" + , requestID, RoomGuid, meeting.MeetingID, extendMinutes); Debug.Console(1, this, "Sending MeetingChange Request: \n{0}", requestTest); - FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleQuery.StringValue = requestTest; + //FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleQuery.StringValue = requestTest; + + FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = requestTest; } - void FusionRoomSchedule_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args) + + void ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args) { Debug.Console(1, this, "Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, args.Sig.Name, args.Sig.StringValue); - if (args.Sig == FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleResponse) + if (args.Sig == FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQueryResponse) { try - { - ScheduleResponse scheduleResponse = new ScheduleResponse(); - - XmlDocument message = new XmlDocument(); - - message.LoadXml(args.Sig.StringValue); - - if (message.FirstChild.Name == "ScheduleResponse") - { - foreach (XmlElement element in message.FirstChild.ChildNodes) - { - if (element.Name == "RequestID") - { - scheduleResponse.RequestID = element.InnerText; - } - else if (element.Name == "RoomID") - { - scheduleResponse.RoomID = element.InnerText; - } - else if (element.Name == "RoomName") - { - scheduleResponse.RoomName = element.InnerText; - } - else if (element.Name == "Event") - { - Debug.Console(1, this, "Event Found:\n{0}", element.OuterXml); - - XmlReader reader = new XmlReader(element.OuterXml); - - Event tempEvent = new Event(); - - tempEvent = CrestronXMLSerialization.DeSerializeObject(reader); - - scheduleResponse.Events.Add(tempEvent); - } - - } - } - - //XmlReader reader = new XmlReader(args.Sig.StringValue); - - //scheduleResponse = CrestronXMLSerialization.DeSerializeObject(reader); - - //Debug.Console(1, this, "ScheduleResponse DeSerialization Successful for Room: '{0}'", scheduleResponse.RoomName); - - if (scheduleResponse.Events.Count > 0) - { - Debug.Console(1, this, "Meetings Count: {0}\n", scheduleResponse.Events.Count); - - foreach (Event e in scheduleResponse.Events) - { - Debug.Console(1, this, "Subject: {0}", e.Subject); - Debug.Console(1, this, "MeetingID: {0}", e.MeetingID); - Debug.Console(1, this, "Start Time: {0}", e.dtStart); - Debug.Console(1, this, "End Time: {0}\n", e.dtEnd); - } - } - - CurrentSchedule = scheduleResponse; + { } catch (Exception e) { - Debug.Console(1, this, "Error parsing ScheduleResponse: {0}", e); + Debug.Console(1, this, "Error parsing ActionQueryResponse: {0}", e); } } } + void FusionRoomSchedule_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args) + { + Debug.Console(1, this, "Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, args.Sig.Name, args.Sig.StringValue); + + + if (args.Sig == FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.ScheduleResponse) + { + try + { + ScheduleResponse scheduleResponse = new ScheduleResponse(); + + XmlDocument message = new XmlDocument(); + + message.LoadXml(args.Sig.StringValue); + + if (message.FirstChild.Name == "ScheduleResponse") + { + foreach (XmlElement element in message.FirstChild.ChildNodes) + { + if (element.Name == "RequestID") + { + scheduleResponse.RequestID = element.InnerText; + } + else if (element.Name == "RoomID") + { + scheduleResponse.RoomID = element.InnerText; + } + else if (element.Name == "RoomName") + { + scheduleResponse.RoomName = element.InnerText; + } + else if (element.Name == "Event") + { + Debug.Console(1, this, "Event Found:\n{0}", element.OuterXml); + + XmlReader reader = new XmlReader(element.OuterXml); + + Event tempEvent = new Event(); + + tempEvent = CrestronXMLSerialization.DeSerializeObject(reader); + + scheduleResponse.Events.Add(tempEvent); + } + + } + } + + //XmlReader reader = new XmlReader(args.Sig.StringValue); + + //scheduleResponse = CrestronXMLSerialization.DeSerializeObject(reader); + + //Debug.Console(1, this, "ScheduleResponse DeSerialization Successful for Room: '{0}'", scheduleResponse.RoomName); + + if (scheduleResponse.Events.Count > 0) + { + Debug.Console(1, this, "Meetings Count: {0}\n", scheduleResponse.Events.Count); + + foreach (Event e in scheduleResponse.Events) + { + Debug.Console(1, this, "Subject: {0}", e.Subject); + Debug.Console(1, this, "MeetingID: {0}", e.MeetingID); + Debug.Console(1, this, "Start Time: {0}", e.dtStart); + Debug.Console(1, this, "End Time: {0}\n", e.dtEnd); + var duration = e.dtEnd.Subtract(e.dtStart); + Debug.Console(1, this, "Duration: {0} minutes", duration.Minutes); + } + } + + CurrentSchedule = scheduleResponse; + + } + catch (Exception e) + { + Debug.Console(1, this, "Error parsing ScheduleResponse: {0}", e); + } + } + } + void SetUpSources() { // Sources @@ -420,7 +613,16 @@ namespace PepperDash.Essentials.Fusion // static assets --------------- testing // Make a display asset - var dispAsset = FusionRoom.CreateStaticAsset(3, display.Name, "Display", "awesomeDisplayId" + Room.Key); + string dispAssetInstanceId; + + //Check for existing GUID + var tempAsset = StaticAssets.FirstOrDefault(a => a.Number.Equals(3)); + if(tempAsset != null) + dispAssetInstanceId = tempAsset.InstanceID; + else + dispAssetInstanceId = ""; + + var dispAsset = FusionRoom.CreateStaticAsset(3, display.Name, "Display", dispAssetInstanceId); dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction; dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction; display.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig); @@ -576,7 +778,12 @@ namespace PepperDash.Essentials.Fusion /// /// the new asset public static FusionStaticAsset CreateStaticAsset(this FusionRoom fr, uint number, string name, string type, string instanceId) - { + { + //if(string.IsNullOrEmpty(instanceId)) + // instanceId = Guid.NewGuid().ToString(); + + Debug.Console(0, "Creating Fusion Static Asset '{0}' with GUID: '{1}'", name, instanceId); + fr.AddAsset(eAssetType.StaticAsset, number, name, type, instanceId); return fr.UserConfigurableAssetDetails[number].Asset as FusionStaticAsset; } @@ -628,6 +835,56 @@ namespace PepperDash.Essentials.Fusion } } + // Helper Classes for GUIDs + + /// + /// Stores GUIDs to be written to a file in NVRAM + /// + public class FusionRoomGuids + { + public string RoomName { get; set; } + public uint IpId { get; set; } + public string RoomGuid { get; set; } + public List StaticAssets { get; set; } + + public FusionRoomGuids(string roomName, uint ipId, string roomGuid, List staticAssets) + { + RoomName = roomName; + IpId = ipId; + RoomGuid = roomGuid; + + StaticAssets = new List(staticAssets); + } + } + + public class StaticAsset + { + public uint Number { get; set; } + public string Name { get; set; } + public string Type { get; set; } + public string InstanceID { get; set; } + + public StaticAsset() + { + + } + + public StaticAsset(uint slotNum, string assetName, string type, string instanceID) + { + Number = slotNum; + Name = assetName; + Type = type; + if(string.IsNullOrEmpty(instanceID)) + { + InstanceID = Guid.NewGuid().ToString(); + } + else + { + InstanceID = instanceID; + } + } + } + //**************************************************************************************************** // Helper Classes for XML API diff --git a/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo b/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo index 3503082a554e86d81e122dd6eb1b9cdbb053ea75..d3ee2011e0f0ea580804e530108b27f2f61c46f2 100644 GIT binary patch delta 1755 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