From e6281b7048b4e8666714322b22181a8f465045ab Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Mon, 19 Jun 2017 23:56:10 -0600 Subject: [PATCH] Working bridge class for room source messages and POST responses to server --- .../PepperDash_Essentials_Core.projectinfo | Bin 1285 -> 1287 bytes .../Essentials_DM/Essentials_DM.projectinfo | Bin 1138 -> 1139 bytes .../Essentials Devices Common.projectinfo | Bin 1159 -> 1164 bytes .../Config/ConfigReader.cs | 2 + .../Config/DeviceFactory.cs | 6 + .../Config/EssentialsConfig.cs | 4 + .../PepperDashEssentials/ControlSystem.cs | 21 +- .../PepperDashEssentials.csproj | 4 +- .../PepperDashEssentials.projectinfo | Bin 1865 -> 1858 bytes .../Room/Cotija/CotijaConfig.cs | 14 + .../Room/Cotija/CotijaSystemController.cs | 336 ++++++++++++++++++ .../UI/CotijaInterfaceController.cs | 147 -------- 12 files changed, 379 insertions(+), 155 deletions(-) create mode 100644 Essentials/PepperDashEssentials/Room/Cotija/CotijaConfig.cs create mode 100644 Essentials/PepperDashEssentials/Room/Cotija/CotijaSystemController.cs delete mode 100644 Essentials/PepperDashEssentials/UI/CotijaInterfaceController.cs diff --git a/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo b/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo index 33a0466539677930ef71927ce856b90af56fb709..aedc307daf0c36e4dec7a7ba6d2b75b35d3fa13e 100644 GIT binary patch delta 647 zcmV;20(kv}3Wo}iycFGsZ+1U@bpPPd{k`$S`#YcR?(MPAE&+e;-vbA92-c<4w+SMB zw)5cL?9=;`>A|O;?tOax>A~K^-3JeLKb_1z-PybM=^l`gxw_Sel<+qC@oB!wm$Q61rLI4E^gS~h_ruvZscE|FYB_#gELP>~c~-ATe8*4o%VL_pUawYF z-6}vO@HETv{mFm+-u;JJcK+$^!=3vN&v&x?-v0iBdz16oo=@QSfG+RczK`3@%%k_f z;Dw{B?rM3qZ1WoQ2&W^zcYc15&nA=XV1GKD zJ=nc}fAa9*!G8YfgZ+bpN#I7`25c}dw*da$^D^A^|C=Z1-p~ZS{)y+`&P(cLV1CYb zruTR5&t~~_c91 z?GMe>)2z+Lv#fQqbFjBF`E+->e=t4B_NFvgiu3P3$nzPo`@IJbrUQl~M#EbZyF<$e hdcWlRzvP#2{-QWnzn8|jE?XJ){{!2z3kgRR001Hmd=&ry delta 645 zcmV;00($+23WW-gycC^-H@o|f_U}E~{dD~B(|h-KAMCNvE&+e`m;*Wl>r(351Q7`D zpYMG-yEoh2eULxc+uPlH`0&AGb}!$b&i3~AckWY5nX6lkNC|&)!{^mBD}N}{bTeNH z8K35>d^yXPQ|kJoN8dBE0Rs3kRMT|V)pGp0Sggv|^Q>Nx_>Q0Em&G)HybNm z;AxiS`;+~>`wxG!?EKT+hdcKlp6_J&z5V?M_a^7FJ)gku0bSm?eIK`*nMdz|!4G)~ z`&0D&(MPZHhUvh6{*sZIv`=q0XE5ULr=Q;2 zfB0bc;r-qHojm{ae0Q>+Pp0?po!`&12e+7~jok!ucZ<$GZ0 zn|CHKBa@SpO#^Wt!DN4TdT^fS2cPaucJF_BuzP><>GXVhelUHov$OxHliUM7e+7>5 z257+q+ydq;CtyR5|8Jg!y`fonm7kXgyQ}5dvdwGIBb<)>-ud}KKATLkgZ=4r_F(t^ z{mH|J2mAS_5B3iZCV?A$8?eE=+yeM}&&zPv|8Jh4dqWfS`X`=$J1?o1f%!S#ncm;I zKbz&#*+KT;;NEP1^5Fj7?t}X~Z@bgUbUv_i)kze% zu|3V&Y&^?a&yeixOg`P6?jKAKvb`w{_F(Vf{ReqIBX+;{;K6jjki=+sYhrh38A0!t feE*mH63$-~=j!*;IM-z>!~TB&)6kAMM->17_!)5v diff --git a/Essentials DM/Essentials_DM/Essentials_DM.projectinfo b/Essentials DM/Essentials_DM/Essentials_DM.projectinfo index dbf3a423d0306338bed46ce1e6715331e698ef2e..0c8e39d275e5daedae369ad1bfc8c9e017c04d21 100644 GIT binary patch delta 879 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 diff --git a/Essentials/PepperDashEssentials/Config/ConfigReader.cs b/Essentials/PepperDashEssentials/Config/ConfigReader.cs index abf788f6..b633f40d 100644 --- a/Essentials/PepperDashEssentials/Config/ConfigReader.cs +++ b/Essentials/PepperDashEssentials/Config/ConfigReader.cs @@ -37,6 +37,8 @@ namespace PepperDash.Essentials { ConfigObject.TemplateUrl= doubleObj["template_url"].Value(); } + + } } catch (Exception e) diff --git a/Essentials/PepperDashEssentials/Config/DeviceFactory.cs b/Essentials/PepperDashEssentials/Config/DeviceFactory.cs index c5cd8686..0a3bc4f6 100644 --- a/Essentials/PepperDashEssentials/Config/DeviceFactory.cs +++ b/Essentials/PepperDashEssentials/Config/DeviceFactory.cs @@ -54,6 +54,12 @@ namespace PepperDash.Essentials var props = JsonConvert.DeserializeObject( properties.ToString()); return new ConsoleCommMockDevice(key, name, props, comm); + } + + else if (typeName == "webserver") + { + var props = JsonConvert.DeserializeObject(properties.ToString()); + return new CotijaSystemController(key, name, props); } return null; diff --git a/Essentials/PepperDashEssentials/Config/EssentialsConfig.cs b/Essentials/PepperDashEssentials/Config/EssentialsConfig.cs index e158c810..b9ba2bc8 100644 --- a/Essentials/PepperDashEssentials/Config/EssentialsConfig.cs +++ b/Essentials/PepperDashEssentials/Config/EssentialsConfig.cs @@ -17,6 +17,8 @@ namespace PepperDash.Essentials public string SystemUrl { get; set; } public string TemplateUrl { get; set; } + public CotijaConfig Cotija { get; private set; } + public string SystemUuid { get @@ -53,5 +55,7 @@ namespace PepperDash.Essentials public EssentialsConfig System { get; set; } public EssentialsConfig Template { get; set; } + + //public CotijaConfig Cotija { get; set; } } } \ No newline at end of file diff --git a/Essentials/PepperDashEssentials/ControlSystem.cs b/Essentials/PepperDashEssentials/ControlSystem.cs index 7080c443..4a270d62 100644 --- a/Essentials/PepperDashEssentials/ControlSystem.cs +++ b/Essentials/PepperDashEssentials/ControlSystem.cs @@ -29,8 +29,8 @@ namespace PepperDash.Essentials /// public override void InitializeSystem() { - CrestronConsole.AddNewConsoleCommand(s => GoWithLoad(), "go", "Reloads configuration file", - ConsoleAccessLevelEnum.AccessOperator); + //CrestronConsole.AddNewConsoleCommand(s => GoWithLoad(), "go", "Reloads configuration file", + // ConsoleAccessLevelEnum.AccessOperator); //CrestronConsole.AddNewConsoleCommand(s => TearDown(), "ungo", "Reloads configuration file", // ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(s => @@ -57,11 +57,6 @@ namespace PepperDash.Essentials //PortalSync = new PepperDashPortalSyncClient(); - //Temp Cotija testing - CotijaInterfaceController CotijaInterface = new CotijaInterfaceController("WebClient1"); - - //CotijaInterface.InitializeClientAndEventStream("http://localhost:3000/api/system/stream/abcdefgh"); - Debug.Console(0, "Starting Essentials load from configuration"); ConfigReader.LoadConfig2(); LoadDevices(); @@ -69,6 +64,10 @@ namespace PepperDash.Essentials LoadRooms(); // FUSION - should go per room I believe. See CreateSystems in original Configuration.cs // ??? + + //Temp Cotija testing + //CotijaSystemController CotijaInterface = new CotijaSystemController("WebClient1"); + DeviceManager.ActivateAll(); Debug.Console(0, "Essentials load complete\r" + "-------------------------------------------------------------"); @@ -103,6 +102,7 @@ namespace PepperDash.Essentials Debug.Console(0, "Tear down COMPLETE"); } + /// /// Reads all devices from config and adds them to DeviceManager /// @@ -164,6 +164,13 @@ namespace PepperDash.Essentials { Debug.Console(1, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion"); DeviceManager.AddDevice(new EssentialsHuddleSpaceFusionSystemController((EssentialsHuddleSpaceRoom)room, 0xf1)); + + var cotija = DeviceManager.GetDeviceForKey("cotijaServer") as CotijaSystemController; + + if (cotija != null) + { + cotija.CotijaRooms.Add(new CotijaEssentialsHuddleSpaceRoomBridge(cotija, room as EssentialsHuddleSpaceRoom)); + } } else { diff --git a/Essentials/PepperDashEssentials/PepperDashEssentials.csproj b/Essentials/PepperDashEssentials/PepperDashEssentials.csproj index 00ef6d37..d56aabed 100644 --- a/Essentials/PepperDashEssentials/PepperDashEssentials.csproj +++ b/Essentials/PepperDashEssentials/PepperDashEssentials.csproj @@ -140,6 +140,8 @@ + + @@ -164,7 +166,7 @@ - + diff --git a/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo b/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo index e2cb3d80008506d9f6e89b712ccdfe50f7c62ae0..b9a1020ba8e8df3518c5758f9f73d2dfc9feb4c7 100644 GIT binary patch delta 1697 zcmV;S244Be4#EzQwST)0-|T++=>Ee;JNx5L5B5Gi;Ex~e>`=QowL5wA`~JS)t?IYM z@*;g&)cLfn>LPD`-{05u^!xt4uYdga{e5%W-|zeTy1xB({-={-8UJcLUHyQ%F6_u( z*40l_uV>5i>RD0d%WRSV?4cFKXeAgFgaKi8)=+=#wV99C*MCi$FJ1^%1JtJ>T-4d( zZ1yI*xUtnDuVt2wXS1R$s%2JU?DE-3wOA1mW?wFEIfdqhpMBEZG^3}BNj`gBt?Oxi zTu4vG-k$;gD%VYX*F)6RzyZiKw zH!IQiXJtvPf-%#7dj}65U~W64>C)ue1dBd9c(^yazq7mZFn{=P|6#tfH`#kI*}b)mgo#*v3Z^^bS*2`j=!AcnsRPx>XH2?I|d;1R`>^{7|yT6m?pPuhd_VdZ~{=M`2 zdG_EI^RlsUg`ul(3B-{%p!2vy~>ii|S@LBo#dN~c};9)komrth|@#y~EgX!MR{eyd- zPCw1>ou402&=**X8z2T#a0|FMO~DP_{l9Pq21E1TA0r3}|LKh4=*iB`gPlqKV1NI? z?BL!s-#@>%yFVpYbZ>euPIwVc^tLQVE(P~8tFpWeTpoj=^!*?;{spG`Aj z=}#vQ2d3r*;GuoKxr_Iho*R1pf8i8$B5XI7Z|5a}ADEadpFP;iCp$SMj40nqS)xxL z>>QBA{d9l-{%jg3ubV)I0o=`iZ$BOJ{{G)L345J*+Ku2ve$`UGtUB-H(;rSriQJ#v z+nEu;W;1dn?@#Z2noTDd=YP&DSd-WQts@CH!n{4{dtLp%km{X?IgB#%cex|?Ir%a< z1+5Q1rRa5bu(v~*pZ&ev2b9>(@;p0_liPs_=zI%cx2Ln~sR@Ci3QFgkTaBy$7KY4JUc$U^hr<2Kpf%zDO8p^}Xux~#d zgI)f=W;Qw>*tyvsnwzItn~i5#>t=&=#^lr8>Hfj=AlsYL7%9-Y{~*uFjhWti@L=lC r#t_YJrfP?15rlrp_Zol6FX7eo;#^mDXk_cMm4W_0FOq4*h$8?1y0y#u delta 1704 zcmV;Z23PsQ4#^IXwSPMYZ+7<|?caN}_vv`=-u}JagMIq=(asLFn^U`!N5Ajy``xO3 zTP!cqr$wDl+o~?|=J)-5T~EL7@B8}4f8XCXxBdOTzpv}tZ|8qHDVFiC#?#dgsO!Rx z{AFGJH1&G6Jg=S=WxmW7`Oh9&QH)lCK|vT0W@ioc*It|Xcz=D}wE5zNU^PH}8p1`L zEzV|dvWpvAE%I7s>3B9P+M-%!CB`nFom7hz5n=Y_@|II*UijH3-Ayxkx|rm%*VVe7 z=EwDPUR>sOichN5^_%KhRnGFd`RI|6fW41?$>^gmie<4_FP;_k;wr22pQIK<6UfJS zXXhdPfA1jy|9^7buGa0#to>PIS?c7AY+0P=P3thcN1tw(dL8)}S+P8(4;Pd2+P%9^ z-*~eUeScP#)G8P={kOOOU>#52w>lXXpF(_Vyo6?@tbPrh5-2 z5ARPtogEw;oKs7gmCb`t+HPp^yqad^&*l_t;xVDr(|>%GFK793N_~Cw=zE6L_d`;j z)HI28wH&`L7OV30JgZkEd*i41WiicPuUD(8ZWW-?aGGWL{$zje{=+Og|8)1^&i#ky zJ6V2jfB(U~$@y&0r{Q}*mv?U8#|?Av=smjr;Y?P4O1?k(=vChExcSdtGBT6&>Fp-z zi*RNpvw!pZ+4MXkrk>uLOb#BL@9oa=$-%?j-Mxd!?(8-*V?YMeaSOm-cREae|L>cF z2e+Do({`TM%e*DqvRE&RX$C80L{Q0h@6-I#Pw(wNe6aiQ{_g%xo_~72JK4`C)BE?% z@8{WrTg=PGZi2bGMQ2}gt~TQE|GxPHg%?>BCR&W#@ad^V?{+0BkTnw*dY%=O^g%|9$iE@K*EjdDiAv*>y*P9_;P!<$Jq( zS$6M$O!wYFc7OJ8mk9ak!QR93gX|VF(g7UI$t}Qt%{l4x`v1OJ+1`= zZ#5@horTk}bMWvU@$k-cvNPGgfA7K0gS{Ckeu{$f2fO*sZKlJ53})gMfWPKU*#7=s zI0<{fHsL)f()pFWuEo>OEoJ%6}=zW-plvzOWOi`xJo|L#;eY)wz`Frr7%?9EOwndetH= zyqaI1E!(_4&!!!5n9cSdJlxF=KAnAf{^^6+YQwodyiMSo$U_NdE z{-*i3U9bNyoR&^F?TusIwAJFcZR=vPCbxQEYKTyi{n`HX{_excr}yt?=YJ1(c6L9_ zXVYwN_UWgShXYe{1Mtv3-`vG}OwSEH|G#jGIuW)T%eV8Azz4|WbF`GZgQ_wUc9fya6i$S{Dr8Sw3=Bi`Tt`zB$p6HmJlyvVOw%9mB=oqYPk zDJhZrvwJ%;BG_z3uH^mcy?;-$=>+54nFS_%1GJ7L+z9jbr0;e0|3a#FBIYp4%-`jX z+~?f4(!lzjJ>!%crx0?7_jk+5Y6ged5{sJG;}# ActionDictionary; + + CTimer Heartbeat; + + CTimer Reconnect; + + string SystemUuid; + + public List CotijaRooms { get; private set; } + + public CotijaSystemController(string key, string name, CotijaConfig config) : base(key, name) + { + Config = config; + + ActionDictionary = new Dictionary(); + + CotijaRooms = new List(); + + CrestronConsole.AddNewConsoleCommand(ConnectSseClient, "InitializeHttpClient", "Initializes a new HTTP client connection to a specified URL", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(DisconnectSseClient, "CloseHttpClient", "Closes the active HTTP client", ConsoleAccessLevelEnum.AccessOperator); + + AddPostActivationAction(() => RegisterSystemToServer(null)); + } + + public void AddAction(string key, object action) + { + // This might blow up if an action with that key already exists + ActionDictionary.Add(key, action); + } + + public void RemoveAction(string key) + { + if (ActionDictionary.ContainsKey(key)) + ActionDictionary.Remove(key); + } + + void ReconnectToServer(object o) + { + RegisterSystemToServer(null); + } + + /// + /// Registers the room with the server + /// + /// URL of the server, including the port number, if not 80. Format: "serverUrlOrIp:port" + void RegisterSystemToServer(string command) + { + try + { + string filePath = string.Format(@"\NVRAM\Program{0}\configurationFile.json", Global.ControlSystem.ProgramNumber); + string postBody = null; + + if (string.IsNullOrEmpty(filePath)) + { + Debug.Console(0, this, "Error reading file. No path specified."); + return; + } + + FileLock = new CCriticalSection(); + + if (FileLock.TryEnter()) + { + Debug.Console(1, this, "Reading Configuration File"); + + postBody = File.ReadToEnd(filePath, Encoding.ASCII); + + Debug.Console(2, this, "{0}", postBody); + + FileLock.Leave(); + } + + if (string.IsNullOrEmpty(postBody)) + { + Debug.Console(1, "Post Body is null or empty"); + } + else + { + Client = new HttpClient(); + + HttpClientRequest request = new HttpClientRequest(); + + Client.Verbose = true; + Client.KeepAlive = true; + + SystemUuid = Essentials.ConfigReader.ConfigObject.SystemUuid; + + string url = string.Format("http://{0}/api/system/join/{1}", Config.serverUrl, SystemUuid); + + request.Url.Parse(url); + request.RequestType = RequestType.Post; + request.Header.SetHeaderValue("Content-Type", "application/json"); + request.ContentString = postBody; + + Client.DispatchAsync(request, PostConnectionCallback); + } + + } + catch (Exception e) + { + Debug.Console(0, this, "Error Initilizing Room: {0}", e); + } + + } + + /// + /// Posts a message to the server from a room + /// + /// room from which the message originates + /// object to be serialized and sent in post body + public void PostToServer(EssentialsRoomBase room, JObject o) + { + if(Client == null) + Client = new HttpClient(); + + HttpClientRequest request = new HttpClientRequest(); + + Client.Verbose = true; + Client.KeepAlive = true; + + string url = string.Format("http://{0}/api/room/{1}", Config.serverUrl, string.Format("{0}-{1}", SystemUuid, room.Key)); + + request.Url.Parse(url); + request.RequestType = RequestType.Post; + request.Header.SetHeaderValue("Content-Type", "application/json"); + request.ContentString = o.ToString(); + + Client.DispatchAsync(request, PostConnectionCallback); + } + + /// + /// Disconnects the SSE Client and stops the heartbeat timer + /// + /// + void DisconnectSseClient(string command) + { + if(SseClient != null) + SseClient.Disconnect(); + + if (Heartbeat != null) + { + Heartbeat.Stop(); + + Heartbeat = null; + } + } + + /// + /// The callback that fires when we get a response from our registration attempt + /// + /// + /// + void PostConnectionCallback(HttpClientResponse resp, HTTP_CALLBACK_ERROR err) + { + try + { + if (resp != null && resp.Code == 200) + { + if (SseClient == null) + { + ConnectSseClient(null); + } + } + else + { + Debug.Console(0, this, "Unable to initialize SSE Client"); + } + } + catch (Exception e) + { + Debug.Console(1, this, "Error Initializeing SSE Client: {0}", e); + } + } + + /// + /// Executes when we don't get a heartbeat message in time. Triggers reconnect. + /// + /// + void HeartbeatExpired(object o) + { + if (Heartbeat != null) + { + Heartbeat.Stop(); + + Heartbeat = null; + } + + // Start the reconnect timer + Reconnect = new CTimer(ReconnectToServer, null, 5000, 5000); + + Reconnect.Reset(5000, 5000); + } + + + /// + /// Connects the SSE Client + /// + /// + void ConnectSseClient(object o) + { + Debug.Console(0, this, "Initializing SSE Client."); + + if (SseClient == null) + { + SseClient = new GenericHttpSseClient(string.Format("{0}-SseClient", Key), Name); + + CommunicationGather LineGathered = new CommunicationGather(SseClient, "\x0d\x0a"); + + LineGathered.LineReceived += new EventHandler(LineGathered_LineReceived); + } + else + { + if (SseClient.IsConnected) + { + SseClient.Disconnect(); + } + } + + string uuid = Essentials.ConfigReader.ConfigObject.SystemUuid; + + SseClient.Url = string.Format("http://{0}/api/system/stream/{1}", Config.serverUrl, uuid); + + SseClient.Connect(); + + //Heartbeat = new CTimer(HeartbeatExpired, null, 20000, 20000); + + //Heartbeat.Reset(20000, 20000); + } + + void LineGathered_LineReceived(object sender, GenericCommMethodReceiveTextArgs e) + { + //Debug.Console(1, this, "Received from Server: '{0}'", e.Text); + + if(e.Text.IndexOf("data:") > -1) + { + var message = e.Text.Substring(6); + + string roomId = null; + + Debug.Console(1, this, "Message: '{0}'", message); + + try + { + var messageObj = JObject.Parse(message); + + var type = messageObj["type"].Value(); + + if(type == "/system/hearbeat") + { + //Heartbeat.Reset(20000, 20000); + } + else if(type == "close") + { + SseClient.Disconnect(); + + // Start the reconnect timer + Reconnect = new CTimer(ConnectSseClient, null, 5000, 5000); + + Reconnect.Reset(5000, 5000); + } + else + { + + + // Check path against Action dictionary + if (ActionDictionary.ContainsKey(type)) + { + var action = ActionDictionary[type]; + + if (action is Action) + { + var stateString = messageObj["content"]["state"].Value(); + + // Look for a button press event + if(!string.IsNullOrEmpty(stateString)) + { +#warning deal with held state later + if (stateString == "held") + return; + + (action as Action)(stateString == "true"); + } + } + else if (action is Action) + { + (action as Action)(messageObj["content"]["value"].Value()); + } + else if (action is Action) + { + (action as Action)(messageObj["content"]["value"].Value()); + } + else if (action is Action) + { + (action as Action)(messageObj["content"] + .ToObject()); + } + } + + } + + } + catch (Exception err) + { + Debug.Console(1, this, "Unable to parse message: {0}", err); + } + } + } + } + + +} \ No newline at end of file diff --git a/Essentials/PepperDashEssentials/UI/CotijaInterfaceController.cs b/Essentials/PepperDashEssentials/UI/CotijaInterfaceController.cs deleted file mode 100644 index 8f8bfc9c..00000000 --- a/Essentials/PepperDashEssentials/UI/CotijaInterfaceController.cs +++ /dev/null @@ -1,147 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharp.CrestronIO; -using Crestron.SimplSharpPro; -using Crestron.SimplSharp.Net.Http; -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.PageManagers; - -namespace PepperDash.Essentials -{ - public class CotijaInterfaceController : Device - { - GenericHttpSseClient SseClient; - - CCriticalSection FileLock; - - string ServerUrl; - - public CotijaInterfaceController(string key) : base(key) - { - CrestronConsole.AddNewConsoleCommand(RegisterRoomToServer, "InitializeHttpClient", "Initializes a new HTTP client connection to a specified URL", ConsoleAccessLevelEnum.AccessOperator); - } - - /// - /// Registers the room with the server - /// - /// URL of the server, including the port number, if not 80. Format: "serverUrlOrIp:port" - void RegisterRoomToServer(string url) - { - try - { - ServerUrl = url; - - string filePath = string.Format(@"\NVRAM\Program{0}\configurationFile.json", Global.ControlSystem.ProgramNumber); - string postBody = null; - - if (string.IsNullOrEmpty(filePath)) - { - Debug.Console(0, this, "Error reading file. No path specified."); - return; - } - - FileLock = new CCriticalSection(); - - if (FileLock.TryEnter()) - { - Debug.Console(1, this, "Reading Configuration File"); - - postBody = File.ReadToEnd(filePath, Encoding.ASCII); - - Debug.Console(2, this, "{0}", postBody); - - FileLock.Leave(); - } - - if (string.IsNullOrEmpty(postBody)) - { - Debug.Console(1, "Post Body is null or empty"); - } - else - { - HttpClient Client = new HttpClient(); - - HttpClientRequest Request = new HttpClientRequest(); - - Client.Verbose = true; - Client.KeepAlive = true; - - string uuid = Essentials.ConfigReader.ConfigObject.SystemUuid; - - url = string.Format("http://{0}/api/system/join/{1}", ServerUrl, uuid); - - Request.Url.Parse(url); - Request.RequestType = RequestType.Post; - Request.Header.SetHeaderValue("Content-Type", "application/json"); - Request.ContentString = postBody; - - Client.DispatchAsync(Request, PostConnectionCallback); - } - - } - catch (Exception e) - { - Debug.Console(0, this, "Error Initilizing Room: {0}", e); - } - - } - - /// - /// The callback that fires when we get a response from our registration attempt - /// - /// - /// - void PostConnectionCallback(HttpClientResponse resp, HTTP_CALLBACK_ERROR err) - { - try - { - if (resp.Code == 200) - { - Debug.Console(0, this, "Initializing SSE Client."); - - if (SseClient == null) - { - SseClient = new GenericHttpSseClient(string.Format("{0}-SseClient", Key), Name); - } - else - { - if (SseClient.IsConnected) - { - SseClient.Disconnect(); - } - - string uuid = Essentials.ConfigReader.ConfigObject.SystemUuid; - - SseClient.Url = string.Format("http://{0}/api/system/stream/{1}", ServerUrl, uuid); - - SseClient.Connect(); - } - - CommunicationGather LineGathered = new CommunicationGather(SseClient, "\x0d\x0a"); - - LineGathered.LineReceived += new EventHandler(LineGathered_LineReceived); - - - } - else - { - Debug.Console(0, this, "Unable to initialize SSE Client"); - } - } - catch (Exception e) - { - Debug.Console(1, this, "Error Initializeing SSE Client: {0}", e); - } - } - - void LineGathered_LineReceived(object sender, GenericCommMethodReceiveTextArgs e) - { - Debug.Console(1, this, "Received from Node Server: '{0}'", e.Text); - } - - } -} \ No newline at end of file