public void IncomingMessageEventTest() { var contentServiceThing = TheThingRegistry.GetBaseEngineAsThing(eEngineName.ContentService); var contentServiceEng = contentServiceThing.GetBaseEngine(); int numberOfMessages = 0; string txt = "TEST_TXT"; string payload = "TestPayload"; TSM testMsg = new TSM(eEngineName.ContentService, txt, payload); contentServiceEng?.RegisterEvent(eEngineEvents.IncomingMessage, (t, o) => { numberOfMessages++; if (o is TheProcessMessage msg) { Assert.AreEqual(msg.Message.TXT, txt); Assert.AreEqual(msg.Message.PLS, payload); Assert.AreEqual(msg.Message.ENG, contentServiceEng.GetEngineName()); testMsg.PLS = "TestPayload2"; //Assert.AreNotEqual(msg.Message.PLS, testMsg.PLS); // This fails } if (t is ICDEThing thing) { Assert.AreEqual(thing.GetBaseThing().cdeMID, contentServiceThing.cdeMID); } }); TheCommCore.PublishCentral(testMsg, true); TheCommonUtils.SleepOneEye(5000, 1000); Assert.AreEqual(numberOfMessages, 1); }
public void StartPropertyUpdateLoop() { testThing = new TheThing() { FriendlyName = "MyTestSensor" }; TheThingRegistry.RegisterThing(testThing); Random rand = new Random(); // Used for generating "fake" sensor values cdeP[] props = new cdeP[propertyCount]; // Run the loop on another thread TheCommonUtils.cdeRunAsync("PropertyUpdateLoop", true, (o) => { while (TheBaseAssets.MasterSwitch) { // Set the properties and log props[0] = testThing.SetProperty(properties[0], rand.Next(25, 51)); props[1] = testThing.SetProperty(properties[1], rand.NextDouble()); props[2] = testThing.SetProperty(properties[2], rand.Next(10000, 50000)); LogChanges(false, props); // Wait timeout of 1 second between property updates TheCommonUtils.SleepOneEye(1000, 500); } }); }
void sinkError(TheRequestData pData) { eventMessage?.Invoke(pData.ErrorDescription, pData); if (IsConnected && mRetryOnError > 0) { TheCommonUtils.SleepOneEye(mRetryOnError, 100); GetDevices(); } }
public bool PostToWeb(Uri pUrl, string tPost, Action <TheRequestData> pCallback, string MimeTypeOverride = null, cdeConcurrentDictionary <string, string> paddHeader = null, string pMethodOveride = "POST") { if (!IsConnected || !TheBaseAssets.MasterSwitch || MyRequestData == null || pUrl == null) { return(false); } TheRequestData tD = MyRequestData; if (!string.IsNullOrEmpty(tPost)) { tD.PostData = TheCommonUtils.CUTF8String2Array(tPost); } else { tD.PostData = null; } tD.RequestUri = pUrl; // new Uri($"https://ptdevices.com{Url}"); tD.HttpMethod = pMethodOveride; tD.Header = null; if (paddHeader != null) { tD.Header = new cdeConcurrentDictionary <string, string>(); foreach (string key in paddHeader.Keys) { tD.Header.TryAdd(key, paddHeader[key]); } } tD.DisableRedirect = true; tD.RequestCookies = MyRequestData?.SessionState?.StateCookies; if (!string.IsNullOrEmpty(MimeTypeOverride)) { tD.ResponseMimeType = MimeTypeOverride; // "application/x-www-form-urlencoded; charset=UTF-8"; } else { tD.ResponseMimeType = mPostMimeType; // "application/x-www-form-urlencoded; charset=UTF-8"; } while (MyRest.IsPosting > 1 && IsConnected) { TheCommonUtils.SleepOneEye(1000, 100); } if (IsConnected) { MyRest.PostRESTAsync(tD, pCallback, sinkError); } return(true); }
public void IncomingMessage2EventTest() { var contentServiceThing = TheThingRegistry.GetBaseEngineAsThing(eEngineName.ContentService); var contentServiceEng = contentServiceThing.GetBaseEngine(); int numberOfMessages = 0; string txt = "CDE_GET_SERVICEINFO"; string payload = "CHNL"; TSM testMsg = new TSM(eEngineName.ContentService, txt, payload); contentServiceThing?.RegisterEvent(eEngineEvents.IncomingEngineMessage, (t, o) => { // Two messages should be received here - The first intercepts the CDE_GET_SERVICEINFO // The second intercepts the CDE_SERVICEINFO response (since originator Thing was set to ContentService) numberOfMessages++; }); testMsg.SetOriginatorThing(contentServiceThing); TheCommCore.PublishCentral(testMsg, true); TheCommonUtils.SleepOneEye(5000, 1000); Assert.AreEqual(numberOfMessages, 2); }
void ParseDevices(TheRequestData pdata) { MyRequestData = pdata; var tRes = TheCommonUtils.CArray2UTF8String(pdata.ResponseBuffer); eventDeviceDataReceived?.Invoke(tRes, pdata); if (IsConnected) { do { TheCommonUtils.SleepOneEye(mReadyEvery, 100); //TheCommonUtils.CUInt(TheThing.GetSafePropertyNumber(MyBaseThing, "ReadEvery")) if (WasDisconnected || !TheBaseAssets.MasterSwitch) { WasDisconnected = false; return; } } while (WaitForService); GetDevices(); } }
public void ProcessHttpRequest(HttpListenerContext mContext) { TheRequestData tRequestData = new TheRequestData(); try { tRequestData.RequestUri = mContext.Request.Url; // TheSystemMessageLog.ToCo(tRequestData.RequestUri.ToString(), true); tRequestData.UserAgent = mContext.Request.UserAgent; tRequestData.ServerTags = null; tRequestData.HttpMethod = mContext.Request.HttpMethod; //NEW 3.200 tRequestData.Header = TheCommonUtils.cdeNameValueToDirectory(mContext.Request.Headers); tRequestData.ResponseMimeType = mContext.Request.ContentType; tRequestData.ClientCert = mContext.Request.GetClientCertificate(); if (TheCommCore.MyHttpService != null && TheBaseAssets.MyServiceHostInfo.ClientCertificateUsage > 1) //If CDE requires a certificate, terminate all incoming requests before any processing { var err = TheCommCore.MyHttpService.ValidateCertificateRoot(tRequestData); if (TheBaseAssets.MyServiceHostInfo.DisableNMI && !string.IsNullOrEmpty(err)) { mContext.Response.StatusCode = (int)eHttpStatusCode.NotAcceptable; mContext.Response.OutputStream.Close(); return; } } if (mContext.Request.InputStream != null) { #if CDE_NET4 || CDE_NET45 using (MemoryStream ms = new MemoryStream()) { mContext.Request.InputStream.CopyTo(ms); tRequestData.PostData = ms.ToArray(); } #else byte[] buffer = new byte[TheBaseAssets.MAX_MessageSize[0]]; using (MemoryStream ms = new MemoryStream()) { int read; while ((read = mContext.Request.InputStream.Read(buffer, 0, buffer.Length)) > 0) { ms.Write(buffer, 0, read); } tRequestData.PostData = ms.ToArray(); } #endif tRequestData.PostDataLength = tRequestData.PostData.Length; } if (TheCommCore.MyHttpService != null) { TheCommCore.MyHttpService.cdeProcessPost(tRequestData); } } catch (Exception e) { TheBaseAssets.MySYSLOG.WriteToLog(4350, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("HttpMidiServer", "ProcessRequest Error:" + firstRequestLine, eMsgLevel.l1_Error, e.ToString())); tRequestData.ResponseBuffer = TheCommonUtils.CUTF8String2Array(e.ToString()); tRequestData.StatusCode = (int)eHttpStatusCode.ServerError; } if ((tRequestData.ResponseBuffer == null && tRequestData.StatusCode != 200) || tRequestData.StatusCode == 404) //NEW:UPNP { tRequestData.ResponseBufferStr = "<html><head><meta http-equiv=\"Expires\" content=\"0\" /><meta http-equiv=\"Cache-Control\" content=\"no-cache\" /><meta http-equiv=\"Pragma\" content=\"no-cache\" /></html><body style=\"background-color: " + TheBaseAssets.MyServiceHostInfo.BaseBackgroundColor + ";\"><table width=\"100%\" style=\"height:100%;\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\"><tr><td style=\"text-align:center;\"><p style=\"color: " + TheBaseAssets.MyServiceHostInfo.BaseForegroundColor + "; font-family: Arial; font-size: 36px\">"; tRequestData.ResponseBufferStr += string.Format("Resource {0} not found", tRequestData.RequestUri); tRequestData.ResponseBufferStr += "</p></td></tr></table></body></HTML>"; tRequestData.ResponseMimeType = "text/html"; tRequestData.ResponseBuffer = TheCommonUtils.CUTF8String2Array(tRequestData.ResponseBufferStr); tRequestData.StatusCode = (int)eHttpStatusCode.NotFound; } try { if (tRequestData.AllowStatePush && tRequestData.ResponseBuffer != null && (tRequestData.StatusCode == (int)eHttpStatusCode.OK || tRequestData.StatusCode == (int)eHttpStatusCode.PermanentMoved)) { if (tRequestData.SessionState != null && tRequestData.SessionState.StateCookies != null && tRequestData.SessionState.StateCookies.Count > 0) { string tCookie = ""; foreach (string nam in tRequestData.SessionState.StateCookies.Keys) { try { if (tCookie.Length > 0) { tCookie += ";"; } string[] cp = tRequestData.SessionState.StateCookies[nam].Split(';'); tCookie = ""; tCookie += $"{nam}={cp[0]}; SameSite=none; Secure"; mContext.Response.Headers.Add(HttpResponseHeader.SetCookie, tCookie); } catch { //ignored } } } } else { if (!string.IsNullOrEmpty(tRequestData.cdeRealPage) && tRequestData.cdeRealPage.StartsWith("/cdeClean", StringComparison.OrdinalIgnoreCase) && tRequestData.Header != null && tRequestData.Header.ContainsKey("Cookie")) { string cookieDate = DateTime.UtcNow.AddMilliseconds(100).ToString("ddd, dd-MMM-yyyy H:mm:ss"); //Offset not needed string cookieHeader = tRequestData.Header.cdeSafeGetValue("Cookie"); if (!string.IsNullOrEmpty(cookieHeader)) { string tCookie = ""; List <string> tCookies = TheCommonUtils.CStringToList(cookieHeader, ';'); foreach (string t in tCookies) { if (tCookie.Length > 0) { tCookie += ";"; } string[] tc = t.Split('='); tCookie += string.Format("{0}=;Path=/;Expires={1} GMT", tc[0], cookieDate); } mContext.Response.Headers.Add(HttpResponseHeader.SetCookie, tCookie); } } } if (!tRequestData.DontCompress) { if (tRequestData.AllowCaching && !TheBaseAssets.MyServiceHostInfo.DisableCache) { mContext.Response.AddHeader("Cache-Control", $"max-age={TheBaseAssets.MyServiceHostInfo.CacheMaxAge}, public"); } else { mContext.Response.AddHeader("Cache-Control", "no-cache"); } mContext.Response.AddHeader("cdeDeviceID", TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID.ToString()); if (tRequestData.StatusCode > 300 && tRequestData.StatusCode < 400 && tRequestData.Header != null) { mContext.Response.AddHeader("Location", tRequestData.Header.cdeSafeGetValue("Location")); } } else { mContext.Response.Headers.Clear(); } mContext.Response.Headers.Set(HttpResponseHeader.Server, "C-DEngine V4"); if (TheBaseAssets.MyServiceHostInfo.IsSSLEnforced) { mContext.Response.Headers.Set("Strict-Transport-Security", "max-age=298000; includeSubDomains; preload"); //HSTS Header for SSL sites...test still required mContext.Response.Headers.Set("X-Frame-Options", "sameorigin"); //iFrame protection Header for SSL sites...test still required } var tCors = TheBaseAssets.MySettings.GetSetting("Access-Control-Allow-Origin"); if (!string.IsNullOrEmpty(tCors)) { mContext.Response.AppendHeader("Access-Control-Allow-Origin", tCors); } if (!string.IsNullOrEmpty(tRequestData.AllowedMethods)) { mContext.Response.AppendHeader("Access-Control-Allow-Methods", tRequestData.AllowedMethods); } if (!string.IsNullOrEmpty(tRequestData.AllowedMethods)) { mContext.Response.AppendHeader("Access-Control-Allow-Headers", tRequestData.AllowedHeaders); } mContext.Response.StatusCode = tRequestData.StatusCode; if (tRequestData.StatusCode != 200) { TheCDEKPIs.IncrementKPI(eKPINames.BruteDelay); //Security Fix: ID#770 - wait 200 ms before returning anything with error code to limit BruteForce TheCommonUtils.SleepOneEye(200, 100); } mContext.Response.ContentType = tRequestData.ResponseMimeType; if (tRequestData.ResponseBuffer != null) { if (!tRequestData.DontCompress && (TheBaseAssets.MyServiceHostInfo.IsOutputCompressed || (tRequestData.Header != null && tRequestData.Header.ContainsKey("Accept-Encoding") && tRequestData.Header["Accept-Encoding"].Contains("gzip")))) { byte[] bBuffer = TheCommonUtils.cdeCompressBuffer(tRequestData.ResponseBuffer, 0, tRequestData.ResponseBuffer.Length); mContext.Response.AddHeader("Content-Encoding", "gzip"); mContext.Response.ContentLength64 = bBuffer.Length; mContext.Response.OutputStream.Write(bBuffer, 0, bBuffer.Length); } else { if (!string.IsNullOrEmpty(tRequestData.ResponseEncoding)) { mContext.Response.AddHeader("Content-Encoding", tRequestData.ResponseEncoding); } mContext.Response.ContentLength64 = tRequestData.ResponseBuffer.Length; mContext.Response.OutputStream.Write(tRequestData.ResponseBuffer, 0, tRequestData.ResponseBuffer.Length); } } if (tRequestData.DisableChunking) { mContext.Response.SendChunked = false; } if (tRequestData.DisableKeepAlive) { mContext.Response.KeepAlive = false; } mContext.Response.OutputStream.Close(); } catch (Exception ee) { TheBaseAssets.MySYSLOG.WriteToLog(4351, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM("HttpMidiServer", "HttpWriteResponse Error", eMsgLevel.l1_Error, ee.ToString())); } }
private bool WriteLogToFile(TheEventLogData pLogItem, bool WaitForLock) { if (pLogItem == null || string.IsNullOrEmpty(pLogItem.EventCategory)) { return(false); } if (mWriteToConsole) { Console.WriteLine($"{pLogItem.EventCategory} : {TheCommonUtils.GetDateTimeString(pLogItem.EventTime, -1)} : {pLogItem.EventName} : {pLogItem.EventString}"); } if (string.IsNullOrEmpty(mLogFilePath) && string.IsNullOrEmpty(TheThing.GetSafePropertyString(MyBaseThing, "LogFilePath"))) { return(false); } if (EachCategoryInOwnFile) { //TODO: Tune with array of EventCategory Log file names //MyCurLog = mLogFilePath + string.Format("\\{1}_{0:yyyMMdd_HHmmss}.txt", DateTime.Now,pLogItem.EventCategory); //MyCurLog = TheCommonUtils.cdeFixupFileName(MyCurLog); //TheCommonUtils.CreateDirectories(MyCurLog); } if (EachDayInOwnFile && mLogFileDate.Day != DateTimeOffset.Now.Day) { LogFilePath = MyCurLog = TheCommonUtils.cdeFixupFileName(mLogFilePath + string.Format("\\LOG_{0:yyyMMdd_HHmmss}.txt", DateTime.Now)); LogFileDate = mLogFileDate = DateTimeOffset.Now; } // ReSharper disable once EmptyEmbeddedStatement if (WaitForLock) { while (TheCommonUtils.cdeIsLocked(writeLock)) { TheCommonUtils.SleepOneEye(50, 50); } } if (!TheCommonUtils.cdeIsLocked(writeLock)) { lock (writeLock) { var bLogFileExists = System.IO.File.Exists(MyCurLog); if (mMaxLogFileSize > 0 && bLogFileExists) { try { System.IO.FileInfo f2 = new System.IO.FileInfo(MyCurLog); if (f2.Length > mMaxLogFileSize * (1024 * 1024)) { MyCurLog = LogFilePath = TheCommonUtils.cdeFixupFileName(mLogFilePath + string.Format("\\LOG_{0:yyyMMdd_HHmmss}.txt", DateTime.Now)); LogFileDate = mLogFileDate = DateTimeOffset.Now; } } catch { //ignored } bLogFileExists = System.IO.File.Exists(MyCurLog); } try { using (System.IO.StreamWriter fs = new System.IO.StreamWriter(MyCurLog, bLogFileExists)) { if (EachCategoryInOwnFile) { fs.WriteLine($"{pLogItem.EventTime} : {TheCommonUtils.GetDateTimeString(pLogItem.EventTime, -1)} : {pLogItem.EventString}"); } else { fs.WriteLine($"{pLogItem.EventCategory} : {TheCommonUtils.GetDateTimeString(pLogItem.EventTime,-1)} : {pLogItem.EventName} : {pLogItem.EventString}"); } } } catch { //ignored } } } return(true); }
public void GetDevices(Uri pDeviceURL = null, string tPost = null, cdeConcurrentDictionary <string, string> addHeader = null) { if (!IsConnected || !TheBaseAssets.MasterSwitch) { return; } if (pDeviceURL != null) { mDeviceUrl = pDeviceURL; } if (tPost != null) { mDevicePost = tPost; } if (addHeader != null) { mAddHeader = addHeader; } if (mDevicePost == null) { TheRequestData tRequest = new TheRequestData { RequestUri = mDeviceUrl, RequestCookies = MyRequestData?.SessionState?.StateCookies }; if (mAddHeader != null) { tRequest.Header = new cdeConcurrentDictionary <string, string>(); foreach (string key in mAddHeader.Keys) { tRequest.Header.TryAdd(key, mAddHeader[key]); } } TheREST.GetRESTAsync(tRequest, ParseDevices, sinkError); } else { MyRequestData.RequestUri = mDeviceUrl; // new Uri("https://ptdevices.com/device/all"); //tPost = $"_token={WebSocketSharp.Ext.UrlEncode(mToken)}"; MyRequestData.PostData = TheCommonUtils.CUTF8String2Array(mDevicePost); MyRequestData.HttpMethod = "POST"; MyRequestData.Header = null; if (mAddHeader != null) { MyRequestData.Header = new cdeConcurrentDictionary <string, string>(); foreach (string key in mAddHeader.Keys) { MyRequestData.Header.TryAdd(key, mAddHeader[key]); } } MyRequestData.RequestCookies = MyRequestData?.SessionState?.StateCookies; MyRequestData.ResponseMimeType = mPostMimeType; // "application/x-www-form-urlencoded; charset=UTF-8"; while (MyRest.IsPosting > 1 && IsConnected) { TheCommonUtils.SleepOneEye(1000, 100); } if (IsConnected) { MyRest.PostRESTAsync(MyRequestData, ParseDevices, sinkError); } } }
public void TheRESTSenderThread() { if (IsSenderThreadRunning) { return; } try { TheDiagnostics.SetThreadName($"QSender:{MyTargetNodeChannel} SenderThread", true); MyREST = new TheREST(); IsSenderThreadRunning = true; StringBuilder tSendBufferStr = new StringBuilder(TheBaseAssets.MyServiceHostInfo?.IsMemoryOptimized == true ? 1024 : TheBaseAssets.MAX_MessageSize[(int)MyTargetNodeChannel.SenderType] * 2); TargetUri = TheCommonUtils.CUri(MyTargetNodeChannel.TargetUrl, true); TargetUriPath = TargetUri.AbsolutePath; int QDelay = TheCommonUtils.CInt(TheBaseAssets.MySettings.GetSetting("ThrottleWS")); if (QDelay < 2) { QDelay = 2; } if (MyTargetNodeChannel.SenderType == cdeSenderType.CDE_JAVAJASON && TheBaseAssets.MyServiceHostInfo.WsJsThrottle > QDelay) { QDelay = TheBaseAssets.MyServiceHostInfo.WsJsThrottle; } mre = new ManualResetEvent(false); if (eventSenderThreadRunning != null) { TheCommonUtils.cdeRunAsync("EventSenderThreadRunning", true, (p) => { eventSenderThreadRunning(this); }); } MyISBlock?.FireEvent("SenderThreadCreated"); while (TheBaseAssets.MasterSwitch && IsAlive && IsSenderThreadRunning) { if (QDelay > 2) { mre.WaitOne(QDelay); //Throtteling should be here not in the wait loop } int WaitCounter = 0; while (TheBaseAssets.MasterSwitch && IsAlive && IsSenderThreadRunning && ((MyCoreQueue.Count == 0 && IsConnected) || IsConnecting || IsInPost || MyREST.IsPosting > (IsConnected?TheBaseAssets.MyServiceHostInfo.ParallelPosts:0))) { // CODE REVIEW: This was seen looping after service route to local node was closed (due to node shutdown): IsCOnnecting/IsConnected/IsInPost were false; ISAlive true. MyREST.IsPosting was 8. Queue count ~345 // This should be fixed now with IsSenderThreadRunning in the loop (I was wrong :) this happens only with cloud connections where POST fails and the IsPosting was not reset properly). // Update: If found the same problem. Sometime IsPosting is not reduced properly when a Timeout or other error occured during Posting if (IsInPost && MyCoreQueue.Count > 100) { TheBaseAssets.MySYSLOG.WriteToLog(235, new TSM("QueuedSender", $"IsInPost was still on and has been reset for {MyTargetNodeChannel?.ToMLString()}", eMsgLevel.l2_Warning)); IsInPost = false; } if (!IsConnected) { if (IsConnecting && MyREST.IsPosting == 0) { TheBaseAssets.MySYSLOG.WriteToLog(235, new TSM("QueuedSender", $"IsConnecting is set but no Pending Post {MyTargetNodeChannel?.ToMLString()} - resetting IsConnecting", eMsgLevel.l2_Warning)); IsConnecting = false; } if (!IsConnecting && MyREST.IsPosting > (IsConnected ? 10 : 0)) { WaitCounter++; if (WaitCounter > (10000 / QDelay)) { TheBaseAssets.MySYSLOG.WriteToLog(235, new TSM("QueuedSender", $"MyREST.IsPosting ({MyREST.IsPosting}) was higher then expected...possible POST problem. Resetting POST Counter for {MyTargetNodeChannel?.ToMLString()}", eMsgLevel.l2_Warning)); MyREST.IsPosting = 0; } } } mre.WaitOne(QDelay); } if (!TheBaseAssets.MasterSwitch || !IsAlive || !IsSenderThreadRunning) { IsInPost = false; break; } IsInPost = true; if (MyTargetNodeChannel.SenderType == cdeSenderType.CDE_BACKCHANNEL || MyTargetNodeChannel.SenderType == cdeSenderType.CDE_PHONE || MyTargetNodeChannel.SenderType == cdeSenderType.CDE_DEVICE || MyTargetNodeChannel.SenderType == cdeSenderType.CDE_JAVAJASON) { TheBaseAssets.MySYSLOG.WriteToLog(235, new TSM("QueuedSender", $"QSender Should NEVER GO HERE because SenderType is {MyTargetNodeChannel?.ToMLString()}", eMsgLevel.l1_Error)); IsInPost = false; IsSenderThreadRunning = false; return; } //NEW3.124: Sender Loop has to terminate if Cloud was Disabled. if (MyTargetNodeChannel.SenderType == cdeSenderType.CDE_CLOUDROUTE && (TheBaseAssets.MyServiceHostInfo.IsCloudDisabled || string.IsNullOrEmpty(TheBaseAssets.MyServiceHostInfo.ServiceRoute) || !TheBaseAssets.MyServiceHostInfo.HasServiceRoute(TargetUri))) //ServiceRoute can contain multiple routes... { break; } TheCoreQueueContent tQueued = null; int MCQCount = 0; int IsBatchOn = 0; #if CDE_NET35 tSendBufferStr = new StringBuilder(TheBaseAssets.MAX_MessageSize[(int)MyTargetNodeChannel.SenderType] * 2); #else tSendBufferStr.Clear(); #endif tSendBufferStr.Append("["); byte[] BinSendBuffer = null; do { if (!IsConnected) { tQueued = new TheCoreQueueContent(); IsConnecting = true; ConnectRetries = 0; if (CloudInRetry) { var count = Interlocked.Increment(ref CloudRetryCount); if (count > 10) { int delaySeconds = TheBaseAssets.MyServiceHostInfo.HeartbeatDelay * TheBaseAssets.MyServiceHostInfo.TO.HeartBeatRate; TheBaseAssets.MySYSLOG.WriteToLog(235, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("QueuedSender", $"Too many retries for {MyTargetNodeChannel?.ToMLString()}: {count}. Waiting {delaySeconds} seconds.", eMsgLevel.l2_Warning)); TheCommonUtils.SleepOneEye((uint)delaySeconds * 1000, 100); Interlocked.Exchange(ref CloudRetryCount, 0); } if (!TheBaseAssets.MasterSwitch || !IsAlive || !IsSenderThreadRunning || (MyTargetNodeChannel.SenderType == cdeSenderType.CDE_CLOUDROUTE && (TheBaseAssets.MyServiceHostInfo.IsCloudDisabled || string.IsNullOrEmpty(TheBaseAssets.MyServiceHostInfo.ServiceRoute) || !TheBaseAssets.MyServiceHostInfo.HasServiceRoute(TargetUri)))) { //Very rare but required after Sleep throw new Exception("QSender had to be terminated in Cloud Retry due to disabling of ServiceRoute or C-DEngine Shutdown"); } }//NEW3.124: Sender Loop has to terminate if Cloud was Disabled. if (MyTargetNodeChannel.SenderType == cdeSenderType.CDE_CLOUDROUTE && (TheBaseAssets.MyServiceHostInfo.IsCloudDisabled || string.IsNullOrEmpty(TheBaseAssets.MyServiceHostInfo.ServiceRoute) || !TheBaseAssets.MyServiceHostInfo.HasServiceRoute(TargetUri))) { break; } } else { if (CloudInRetry) { CloudInRetry = false; IsInPost = false; continue; } tQueued = GetNextMessage(out MCQCount); } if (tQueued != null) { TheCDEKPIs.IncrementKPI(eKPINames.QSSent); if (tQueued.OrgMessage == null && !IsConnecting) { if (MySubscriptions.Count == 0) { if (IsBatchOn == 0) //Only jump out if no telegrams are in batch.. { IsInPost = false; continue; } } if (IsBatchOn == 0) //If telegrams are in the batch dont send short message { BinSendBuffer = new byte[1]; BinSendBuffer[0] = (byte)((int)(TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.SenderType)).ToString()[0]; break; } } if (tQueued.OrgMessage != null && tQueued.OrgMessage.ToCloudOnly() && MyTargetNodeChannel.SenderType == cdeSenderType.CDE_CLOUDROUTE) { tQueued.OrgMessage.SetToCloudOnly(false); } TheDeviceMessage tDev = new TheDeviceMessage { DID = TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID.ToString() // MyTargetNodeChannel.cdeMID.ToString(); }; if (MyTargetNodeChannel.MySessionState != null) { //BUGFIX: After fast Cloud Disconnect/reconnect-Relay lost Scopeing because it Scope was not properly stored in SessionState if (string.IsNullOrEmpty(MyTargetNodeChannel.MySessionState.SScopeID) && TheBaseAssets.MyScopeManager.IsScopingEnabled) { MyTargetNodeChannel.MySessionState.SScopeID = TheBaseAssets.MyScopeManager.GetScrambledScopeID(); //GRSI: rare } if (TheBaseAssets.MyServiceHostInfo.EnableFastSecurity) { tDev.SID = MyTargetNodeChannel.MySessionState.SScopeID; } else { tDev.SID = TheBaseAssets.MyScopeManager.GetScrambledScopeID(MyTargetNodeChannel.MySessionState.SScopeID, false); //GRSI: high frequency! } } else { tDev.SID = TheBaseAssets.MyScopeManager.GetScrambledScopeID(); //GRSI: rare } tDev.MSG = tQueued.OrgMessage; tDev.FID = "1"; if (IsConnecting) { tDev.TOP = TheCommCore.SetConnectingBufferStr(MyTargetNodeChannel, null); } else { tDev.TOP = tQueued.Topic; tQueued.OrgMessage?.GetNextSerial(tQueued.SubMsgCnt); if (MyTargetNodeChannel.MySessionState != null) { tDev.FID = MyTargetNodeChannel.MySessionState.GetNextSerial().ToString(); //(SendCounter + 1).ToString(); //V3B3: New was empty //V4.1010: Same as WS now } } #region Batch Serialization IsBatchOn++; if (MCQCount == 0 || IsBatchOn > TheBaseAssets.MyServiceHostInfo.MaxBatchedTelegrams || tQueued.IsChunked) { if (MCQCount != 0) { tDev.CNT = MCQCount; } IsBatchOn = 0; } else { if (tSendBufferStr.Length > TheBaseAssets.MAX_MessageSize[(int)MyTargetNodeChannel.SenderType]) { tDev.CNT = MCQCount; IsBatchOn = 0; } } if (tSendBufferStr.Length > 1) { tSendBufferStr.Append(","); } tSendBufferStr.Append(TheCommonUtils.SerializeObjectToJSONString(tDev)); #endregion } else { IsBatchOn = 0; } } while (IsBatchOn > 0 && IsInPost && TheBaseAssets.MasterSwitch); if ((!IsInPost || tSendBufferStr.Length < 2) && BinSendBuffer == null) { IsInPost = false; continue; } string tMimeType = "application/octet-stream"; if (BinSendBuffer == null) { tSendBufferStr.Append("]"); if (MyTargetNodeChannel.SenderType == cdeSenderType.CDE_MINI || TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.SenderType == cdeSenderType.CDE_MINI) { tMimeType = "application/json"; BinSendBuffer = TheCommonUtils.CUTF8String2Array(tSendBufferStr.ToString()); } else { tMimeType = "application/x-gzip"; BinSendBuffer = TheCommonUtils.cdeCompressString(tSendBufferStr.ToString()); } } if (MyTargetNodeChannel == null) { TheBaseAssets.MySYSLOG.WriteToLog(235, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("QueuedSender", $"Channel was deleted - exiting SenderThread", eMsgLevel.l2_Warning)); IsInPost = false; break; } string ISBPath = new Uri(TargetUri, TheBaseAssets.MyScopeManager.GetISBPath(TargetUriPath, TheCommonUtils.GetOriginST(MyTargetNodeChannel), MyTargetNodeChannel.SenderType, MyTargetNodeChannel.MySessionState == null? 1: MyTargetNodeChannel.MySessionState.FID /*Interlocked.Increment(ref SendCounter)*/, (MyTargetNodeChannel.MySessionState == null || !IsConnected) ?Guid.Empty: MyTargetNodeChannel.MySessionState.cdeMID, MyTargetNodeChannel.IsWebSocket)).ToString(); //V3B4: changed from TheBaseAssets.MyServiceHostInfo.MyDeviceInfo TheRequestData pData = new TheRequestData { RemoteAddress = TheBaseAssets.MyServiceHostInfo.GetPrimaryStationURL(false), RequestUri = new Uri(ISBPath), PostData = BinSendBuffer, ResponseMimeType = tMimeType, DeviceID = TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID, HttpMethod = "POST" }; if (!TheCertificates.SetClientCert(pData, MyTargetNodeChannel?.ClientCertificateThumb)) { throw new Exception("Client Certificate could not be added"); } MyREST.PostRESTAsync(pData, sinkUploadDataCompleted, FireSenderProblem); if (BinSendBuffer != null) { TheCDEKPIs.IncrementKPI(eKPINames.QKBSent, BinSendBuffer.Length); } IsInPost = false; } FlushQueue(); TheBaseAssets.MySYSLOG.WriteToLog(235, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("QueuedSender", $"QSenderThread was closed for {MyTargetNodeChannel?.ToMLString()}", eMsgLevel.l6_Debug)); } catch (Exception e) { IsInPost = false; TheBaseAssets.MySYSLOG.WriteToLog(235, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("QueuedSender", "Exception in jcSenderThread.", eMsgLevel.l1_Error, "Error:" + e)); if (MyTargetNodeChannel?.SenderType != cdeSenderType.CDE_BACKCHANNEL) { FireSenderProblem(new TheRequestData() { ErrorDescription = $"1308:{e}" }); } } finally { IsSenderThreadRunning = false; IsAlive = false; IsInPost = false; CloudInRetry = false; StopHeartBeat(); } }
public void CreateOPCWizard() { TheFieldInfo tTargetButton = null; var flds = TheNMIEngine.AddNewWizard <TheOPCSetClass>(new Guid("{56565656-6AD1-45AE-BE61-96AF02329614}"), Guid.Empty, TheNMIEngine.GetEngineDashBoardByThing(MyBaseThing).cdeMID, "Welcome to the OPC Wizard", new nmiCtrlWizard { PanelTitle = "<i class='fa faIcon fa-3x'></i></br>New OPC Client", SideBarTitle = "New OPC Client Wizard", SideBarIconFA = "", TileThumbnail = "FA5:f545" }, (myClass, pClientInfo) => { myClass.cdeMID = Guid.Empty; TheThing tMemTag = null; if (myClass.CreateMemoryTag) { var tReq = new TheThingRegistry.MsgCreateThingRequestV1() { EngineName = "CDMyVThings.TheVThings", DeviceType = "Memory Tag", FriendlyName = myClass.ClientName, OwnerAddress = MyBaseThing, InstanceId = Guid.NewGuid().ToString(), CreateIfNotExist = true }; tMemTag = TheThingRegistry.CreateOwnedThingAsync(tReq).Result; } var tOPCReq = new TheThingRegistry.MsgCreateThingRequestV1() { EngineName = "CDMyOPCUAClient.cdeOPCUaClient", DeviceType = "OPC-UA Remote Server", FriendlyName = myClass.ClientName, Address = myClass.OPCAddress, OwnerAddress = MyBaseThing, InstanceId = Guid.NewGuid().ToString(), CreateIfNotExist = true }; tOPCReq.Properties = new Dictionary <string, object>(); //tOPCReq.Properties["ID"] = Guid.NewGuid().ToString(); tOPCReq.Properties["AutoConnect"] = myClass.AutoConnect; tOPCReq.Properties["SendOpcDataType"] = true; if (!myClass.DisableSecurity) { tOPCReq.Properties["DisableSecurity"] = true; tOPCReq.Properties["AcceptUntrustedCertificate"] = true; tOPCReq.Properties["DisableDomainCheck"] = true; tOPCReq.Properties["AcceptInvalidCertificate"] = true; tOPCReq.Properties["Anonymous"] = true; } if (tMemTag != null) { tOPCReq.Properties["TagHostThingForSubscribeAll"] = tMemTag.cdeMID; } var tOPCServer = TheThingRegistry.CreateOwnedThingAsync(tOPCReq).Result; try { if (tOPCServer != null && myClass.Prop2Tag && myClass.AutoConnect) { var response = TheCommRequestResponse.PublishRequestJSonAsync <MsgOPCUAConnect, MsgOPCUAConnectResponse>(MyBaseThing, tOPCServer, new MsgOPCUAConnect { LogEssentialOnly = true, WaitUntilConnected = true }).Result; if (response != null && string.IsNullOrEmpty(response.Error)) { var tBrowseResponse = TheCommRequestResponse.PublishRequestJSonAsync <MsgOPCUABrowse, MsgOPCUABrowseResponse>(MyBaseThing, tOPCServer, new MsgOPCUABrowse()).Result; if (string.IsNullOrEmpty(tBrowseResponse.Error)) { TheCommCore.PublishToNode(pClientInfo.NodeID, new TSM(eEngineName.NMIService, "NMI_TOAST", $"OPC UA Client browse error: {tBrowseResponse.Error}")); return; } else { List <MsgOPCUACreateTags.TagInfo> tTagList = tBrowseResponse.Tags; if (tTagList != null && tTagList.Count > 0) { var tres = TheCommRequestResponse.PublishRequestJSonAsync <MsgOPCUACreateTags, MsgOPCUACreateTagsResponse>(MyBaseThing, tOPCServer, new MsgOPCUACreateTags { Tags = tTagList, BulkApply = true }).Result; if (tres != null && string.IsNullOrEmpty(tres.Error)) { TheCommCore.PublishToNode(pClientInfo.NodeID, new TSM(eEngineName.NMIService, "NMI_TOAST", "OPC UA Client Created and memory tag ready")); } } } } } TheCommCore.PublishToNode(pClientInfo.NodeID, new TSM(eEngineName.NMIService, "NMI_TOAST", "OPC UA Client Created and ready")); } catch (Exception) { TheCommCore.PublishToNode(pClientInfo.NodeID, new TSM(eEngineName.NMIService, "NMI_TOAST", "Something went wrong! Check the OPC and Memory Tag settings")); } tTargetButton.SetUXProperty(pClientInfo.NodeID, $"OnClick=TTS:{tOPCServer.GetBaseThing().cdeMID}"); TheCommonUtils.SleepOneEye(2000, 100); }); var tMyForm2 = flds["Form"] as TheFormInfo; var tFlds = TheNMIEngine.AddNewWizardPage(MyBaseThing, tMyForm2, 0, 1, 2, null /*"Name and Address"*/); TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SingleEnded, 1, 1, 2, 0, "Connection Name", "ClientName", new TheNMIBaseControl { Explainer = "1. Enter name for the new OPC connection.", }); TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SingleEnded, 1, 2, 2, 0, "OPC Server Address", "OPCAddress", new TheNMIBaseControl { Explainer = "1. Enter address of the OPC server.", }); tFlds = TheNMIEngine.AddNewWizardPage(MyBaseThing, tMyForm2, 1, 2, 3, null /* "Settings"*/); TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SingleCheck, 2, 1, 2, 0, "OPC Server requires Security", "DisableSecurity", new nmiCtrlSingleCheck { Explainer = "Check if the OPC Server requires security" }); TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SingleCheck, 2, 2, 2, 0, "Create a Memory Tag", "CreateMemoryTag", new nmiCtrlSingleCheck { TileWidth = 3, Explainer = "Check to create a Memory Tag and check to subscribes all Tags into it" }); TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SingleCheck, 2, 3, 2, 0, "All Tags in Memory Tag", "Prop2Tag", new nmiCtrlSingleCheck { TileWidth = 3 }); TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SingleCheck, 2, 4, 2, 0, "Auto Connect to Server", "AutoConnect", new nmiCtrlSingleCheck { TileWidth = 3, Explainer = "Don't select this if your server requires security settings" }); tFlds = TheNMIEngine.AddNewWizardPage(MyBaseThing, tMyForm2, 2, 3, 0, null /*"Final Settings"*/); TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SmartLabel, 3, 2, 0, 0, null, null, new nmiCtrlSmartLabel { Text = "Once you click finish, the Wizard will create the items you requested. It will notify you with a toast when its done", TileHeight = 5, TileWidth = 7, NoTE = true }); //HELP SECTION final step help section TheNMIEngine.AddWizardProcessPage(MyBaseThing, tMyForm2, 4); TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SmartLabel, 4, 1, 0, 0, null, null, new nmiCtrlSmartLabel { NoTE = true, TileWidth = 7, Text = "Creating the new instance..please wait", TileHeight = 2 }); TheNMIEngine.AddWizardFinishPage(MyBaseThing, tMyForm2, 5); TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.SmartLabel, 5, 1, 0, 0, null, null, new nmiCtrlSmartLabel { NoTE = true, TileWidth = 7, Text = "Done...what do you want to do next?", TileHeight = 2 }); TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.TileGroup, 5, 2, 0, 0, null, null, new nmiCtrlTileGroup { TileWidth = 1, TileHeight = 2, TileFactorX = 2 }); TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.TileButton, 5, 3, 2, 0, "Go to Dashboard", null, new nmiCtrlTileButton { NoTE = true, TileHeight = 2, TileWidth = 3, OnClick = $"TTS:{mMyDashboard.cdeMID}", ClassName = "cdeTransitButton" }); TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.TileGroup, 5, 4, 0, 0, null, null, new nmiCtrlTileGroup { TileWidth = 1, TileHeight = 2 }); tTargetButton = TheNMIEngine.AddWizardControl(MyBaseThing, tMyForm2, eFieldType.TileButton, 5, 5, 2, 0, "Go to New OPC Client", null, new nmiCtrlTileButton { NoTE = true, TileHeight = 2, TileWidth = 3, ClassName = "cdeTransitButton" }); }
static void sinkReady() { Debug.WriteLine("Registering events for engine... "); TheCDEngines.MyContentEngine.RegisterEvent(eEngineEvents.IncomingMessage, sinkIncoming); if (TheCDEngines.MyNMIService != null) { TheCDEngines.MyNMIService.RegisterEvent(eEngineEvents.IncomingMessage, sinkIncoming); //TheCDEngines.MyContentEngine.RegisterEvent(eEngineEvents.ChannelConnected, sinkEstablished); } TheCommonUtils.cdeRunAsync("LoopDiDoop", true, (o) => { TheThing tTimer = null; TheThing GoogleDNS = null; TheThing ThingBar = null; while (TheBaseAssets.MasterSwitch) { TheCommonUtils.SleepOneEye(5000, 100); if (ThingBar == null) { ThingBar = TheThingRegistry.GetThingByProperty("*", Guid.Empty, "FriendlyName", "ThingBar"); if (ThingBar != null) { TheThingRegistry.RegisterEventOfThing(ThingBar, eThingEvents.ValueChanged, (sender, para) => { TSM tTSM2 = new TSM(eEngineName.ContentService, "UNITY:GAUGE", para.ToString()); TheCommCore.PublishCentral(tTSM2); }); } } if (tTimer == null) { tTimer = TheThingRegistry.GetThingByProperty("*", Guid.Empty, "DeviceType", "Timer"); if (tTimer != null) { TheThingRegistry.RegisterEventOfThing(tTimer, eThingEvents.ValueChanged, (sender, para) => { TSM tTSM2 = new TSM(eEngineName.ContentService, "UNITY:TIMER", para.ToString()); TheCommCore.PublishCentral(tTSM2); }); } } if (GoogleDNS == null) { GoogleDNS = TheThingRegistry.GetThingByProperty("*", Guid.Empty, "FriendlyName", "Google DNS"); if (GoogleDNS != null) { TheThingRegistry.RegisterEventOfThing(GoogleDNS, eThingEvents.PropertyChanged, (sender, para) => { cdeP tP = para as cdeP; if (tP != null && tP.Name == "RoundTripTime") { TSM tTSM2 = new TSM(eEngineName.ContentService, "UNITY:HEART", para.ToString()); TheCommCore.PublishCentral(tTSM2); } }); } } if (GoogleDNS != null && tTimer != null && ThingBar != null) { break; } } }); }