public MainWindow() { InitializeComponent(); // Start the CDEngine communication channels StartCDEngineHost(); TheBaseEngine.WaitForEnginesStartedAsync().ContinueWith(t => { try { // Express our interest in the EngineName used for the chat, so that a subscription to the cloud is established even though the engine has not matching plug-in on this node TheCDEngines.RegisterNewMiniRelay(strChatEngine); // Intercept any messages sent to the chat engine var chatEngine = TheThingRegistry.GetBaseEngine(strChatEngine); chatEngine.RegisterEvent(eEngineEvents.IncomingMessage, HandleMessage); // Intercept any messages sent to the ContentService (we will use that as the originating thing, and acknowledge messages will come back to it) TheThingRegistry.GetBaseEngineAsThing(eEngineName.ThingService).RegisterEvent(eThingEvents.IncomingMessage, HandleMessage); } catch { } }); }
private static IServiceCollection AddCdePubSubServices(this IServiceCollection collection) { collection.AddSingleton(sp => { sp.UseCde(); var engines = TheThingRegistry.GetBaseEngines(false); var engine = engines.FirstOrDefault(e => e.GetEngineName() == InfrastructureEngine); if (engine != null) { return(engine.GetBaseThing()); } if (!TheCDEngines.RegisterNewMiniRelay(InfrastructureEngine)) { throw new InvalidOperationException("Failed to register CDE infrastructure engine"); } engine = TheThingRegistry.GetBaseEngine(InfrastructureEngine, false); return(engine.GetBaseThing()); }); collection.AddSingleton(sp => new Publisher(Operator.GetLine(sp.GetRequiredService <TheThing>())).ConnectAsync().Result as Publisher) .AddSingleton(sp => sp.GetRequiredService <Publisher>() as IPublisher); collection.AddSingleton(sp => new Subscriber(Operator.GetLine(sp.GetRequiredService <TheThing>()), sp.GetRequiredService <Publisher>())) .AddSingleton(sp => sp.GetRequiredService <Subscriber>() as ISubscriber); return(collection); }
internal void InterceptRSSEvtRequest(TheRequestData pRequest) { if (pRequest == null) { return; } try { TheStorageMirror <TheEventLogData> tEventLog = TheCDEngines.GetStorageMirror("EventLog") as TheStorageMirror <TheEventLogData>; if (tEventLog != null) { CreateEvtLogFeed(pRequest, tEventLog?.TheValues.OrderByDescending(s => s.cdeCTIM).ThenByDescending(s => s.cdeCTIM.Millisecond).ToList(), 200); } else { TheRSSGenerator.CreateRSS(pRequest, new List <TheEventLogData>() { new TheEventLogData() { EventName = "No Eventlog on this Node" } }, 1); } } catch { //ignored } }
async void sinkReady() { TheCDEngines.RegisterNewMiniRelay("CHATSTER"); var tThing = TheThingRegistry.GetBaseEngine("CHATSTER"); tThing.RegisterEvent(eEngineEvents.IncomingMessage, HandleMessageAsync); await UpdateLog("SYSTEM: Connected to Cloud"); }
/// <summary> /// Add the current station DeviceID to the list of Originators /// </summary> public bool AddHopToOrigin() { if (!DoesORGContain(TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID)) { if (string.IsNullOrEmpty(ORG)) { ORG = TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID.ToString(); } else { ORG += ";" + TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID.ToString(); } if (TheBaseAssets.MyServiceHostInfo.EnableCosting) { TheCDEngines.updateCosting(this); } return(true); } return(false); }
public static void CreateSysLogFeed(TheRequestData pRequest, int MaxCnt) { if (pRequest.RequestUri != null && !string.IsNullOrEmpty(pRequest.RequestUri.Query) && pRequest.RequestUri.Query.Length > 1) { var QParts = TheCommonUtils.ParseQueryString(pRequest.RequestUri.Query); //.Split('='); //if (QParts.ContainsKey("SID") && (!TheScopeManager.IsValidScopeID(TheScopeManager.GetScrambledScopeIDFromEasyID(QParts["SID"])) || QParts.ContainsKey("NID"))) //{ // pRequest.SessionState.SScopeID = TheScopeManager.GetScrambledScopeIDFromEasyID(QParts["SID"]); // Guid tTarget = Guid.Empty; // if (QParts.ContainsKey("NID")) // tTarget = TheCommonUtils.CGuid(QParts["NID"]); // Communication.HttpService.TheHttpService.cdeStreamFile(pRequest, true, 10, tTarget); // if (pRequest.ResponseBuffer == null) // TheRSSGenerator.CreateRSS(pRequest, new List<TheEventLogData>() { new TheEventLogData() { EventName = "Relay did not answer" } }, 1); // return; //} } TheStorageMirror <TheEventLogEntry> tEventLog = TheCDEngines.GetStorageMirror($"{typeof(TheEventLogEntry)}") as TheStorageMirror <TheEventLogEntry>; TheRSSGenerator.CreateRSS(pRequest, tEventLog.TheValues.OrderByDescending(s => s.cdeCTIM).ThenByDescending(s => s.cdeCTIM.Millisecond).ToList(), MaxCnt); }
static void Main(string[] args) { Thread.CurrentThread.Name = "Main thread"; // Helps Debugging //SDK Non-Commercial ID. FOR COMMERCIAL APP GET THIS ID FROM C-LABS! TheScopeManager.SetApplicationID("/cVjzPfjlO;{@QMj:jWpW]HKKEmed[llSlNUAtoE`]G?"); // // Establish service parameters // TheBaseAssets.MyServiceHostInfo = new TheServiceHostInfo(cdeHostType.Application) { // TODO: Generate host service unique ID cdeMID = TheCommonUtils.CGuid("{65CB9142-7D26-40E4-AE54-3E4DD75B3760}"), // TCP/IP Port Assignments MyStationPort = 8720, // Port for REST access to this node. // If your PC already uses port 80 for another webserver, change this port. // We recommend using Port 8700 and higher for UPnP to work properly. MyStationWSPort = 8721, // Enables WebSockets on the station port. // If UseRandomDeviceID is false, this Value cannot be changed here once the // app runs for the first time. // On Windows 8 and later, MyStationPort and MyStationWSPort // can be the same port if running as Administrator. ISMMainExecutable = "MyTestHost2", // Name of the executable (without .exe) ApplicationName = "My-Relay", // Friendly Name of Application Title = "My-Relay (C) 2020 ", // Title of this Host Service ApplicationTitle = "My-Relay Portal", // Title visible in the NMI Portal SiteName = "http://cloud.c-labs.com", // Link to the main Cloud Node of this host. // Not required, for documentation only CurrentVersion = 1.0001, // Service version of this Service. // Increase when you publish a new version so the // online store can display the correct update icon DebugLevel = eDEBUG_LEVELS.OFF, // Define a DebugLevel for the SystemLog output. ServiceRoute = "wss://cloud.c-labs.com", // Points at the cloud }; // Generate random Scope ID every time we run. strScope = TheScopeManager.GenerateNewScopeID(); // TIP: instead of creating a new random ID every // time your host starts, you can put a breakpoint in the // next line, record the ID and feed it in the "SetScopeIDFromEasyID". // Or even set a fixed ScopeID here. (FOR TESTING ONLY!!) TheScopeManager.SetScopeIDFromEasyID("1234"); // Set a ScopeID - the security context of this node. // Replace strScope with any random 8 characters or numbers // // Create dictionary to hold configuration settings. // #region Args Parsing ArgList = new Dictionary <string, string>(); for (int i = 0; i < args.Length; i++) { string[] tArgs = args[i].Split('='); if (tArgs.Length == 2) { string key = tArgs[0].ToUpper(); ArgList[key] = tArgs[1]; } } #endregion ArgList["DontVerifyTrust"] = "True"; // When "false", all plugins have to be signed with the // same certificate as the host application or C-DEngine.DLL. // When "true", ignore code signing security check (dev only!) ArgList["UseRandomDeviceID"] = "True"; // When "true", assigns a new device ID everytime // the host starts. No configuration data retained on disk. // When "false", enables persistence between system starts ArgList["ScopeUserLevel"] = "255"; // Set the Scope Access Level // Create a new Base (C-DEngine IoT) Application MyBaseApplication = new TheBaseApplication(); // Start the C-DEngine Host Application. // If a PluginService class is added DIRECTLY to the host project you can // instantiate the Service here. Replace null with "new cdePluginService1()" if (!MyBaseApplication.StartBaseApplication(null, ArgList)) { // If the Application fails to start, quit the app. // StartBaseApplication returns very fast because all // C-DEngine code is running asynchronously return; } // (Optional) Whether to use Universal Plug // and Play (UPnP) to find devices. // MyBaseApplication.MyCommonDisco.RegisterUPnPUID("*", null); // Set up URL for our node. string strStationURL = TheBaseAssets.MyServiceHostInfo.GetPrimaryStationURL(false); strStationURL = String.Format("{0}/lnmi", strStationURL); // Set up messaging (for basic sample) TheCDEngines.RegisterPubSubTopic("MyTestEngine"); // The engine for MyTestHost IBaseEngine eng = TheCDEngines.RegisterPubSubTopic("MyTestEngine2"); // The engine for THIS host eng.RegisterEvent(eEngineEvents.IncomingMessage, HandleMessage); #region Waiting for ESC Key pressed try { // User input loop while (true) { Console.WriteLine("\r\nStation URL: " + strStationURL); Console.WriteLine("\r\nScope ID: " + strScope); Console.WriteLine("\r\n[Esc] key to quit. 'B' (or 'b') to launch browser"); // Loop until (1) C-DEngine master switch, or (2) Keyboard input while (TheBaseAssets.MasterSwitch && Console.KeyAvailable == false) // Console.KeyAvailable throws exception in Docker { Thread.Sleep(250); } // Check C-DEngine master switch. if (!TheBaseAssets.MasterSwitch) { // Exit user input loop. break; } ConsoleKeyInfo key = Console.ReadKey(); if (key.Key == ConsoleKey.Escape) { break; } if (key.KeyChar == 'b' || key.KeyChar == 'B') { try { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { strStationURL = strStationURL.Replace("&", "^&"); Process.Start(new ProcessStartInfo("cmd.exe", $"/c start {strStationURL}") { CreateNoWindow = true }); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { System.Diagnostics.Process.Start("xdg-open", strStationURL); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { System.Diagnostics.Process.Start("open", strStationURL); } else { Console.WriteLine($"Error launching browser for URL {strStationURL}"); } } catch (Exception e) { Console.WriteLine($"Error launching browser for URL {strStationURL}"); Console.WriteLine($"Exception details: {e.ToString()}"); } } } // while (true) } catch (InvalidOperationException) { TheBaseAssets.MasterSwitchCancelationToken.WaitHandle.WaitOne(); } MyBaseApplication.Shutdown(true); #endregion }
/// <summary> /// Processes incoming Messages /// If a Batch comes in, only the first message must have a valid NPA Path /// </summary> internal static void ProcessClientDeviceMessage(TheQueuedSender MyQSender, TheRequestData pRequestData, List <TheDeviceMessage> tDevList) { var toRemove = new List <TheDeviceMessage>(); foreach (TheDeviceMessage tDev in tDevList) { if (string.IsNullOrEmpty(tDev.NPA)) { return; // CODE REVIEW: Really stop processing all subsequent TDMs here (malformed TDM -> security)? } string NPA = tDev.NPA.Substring(4); if (NPA.EndsWith(".ashx", StringComparison.OrdinalIgnoreCase)) { NPA = NPA.Substring(0, NPA.Length - 5); } if (TheBaseAssets.MyScopeManager.ParseISBPath(NPA, out Guid? ttSessionID, out cdeSenderType tSenderType, out long tFID, out string tVersion)) { Guid tSessionID = TheCommonUtils.CGuid(ttSessionID); Guid tDeviceID = TheCommonUtils.CGuid(tDev.DID); lock (TheBaseAssets.MySession.GetLock()) //CODE-REVIEW: VERY expensive lock! Really necessary? { var myTargetNodeChannel = MyQSender.MyTargetNodeChannel; if (MyQSender.IsConnected && myTargetNodeChannel.MySessionState != null) //!=null new in 3.2 { if (!tSessionID.Equals(myTargetNodeChannel.MySessionState.cdeMID)) { Guid tOldID = myTargetNodeChannel.MySessionState.cdeMID; myTargetNodeChannel.MySessionState = TheBaseAssets.MySession.ValidateSEID(tSessionID); //Measure Frequency if (myTargetNodeChannel.MySessionState == null) { TheBaseAssets.MySYSLOG.WriteToLog(243, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("CoreComm", $"No exiting session for remote node found. Using new session (possible reason: fast cloud reconnect) ...new: {tSessionID} old: {tOldID}", eMsgLevel.l2_Warning), true); myTargetNodeChannel.MySessionState = pRequestData.SessionState; } else { TheBaseAssets.MySession.RemoveSessionByID(tOldID); } } } if (tDeviceID != Guid.Empty && tDeviceID != myTargetNodeChannel.cdeMID) { if (myTargetNodeChannel.SenderType == cdeSenderType.CDE_CUSTOMISB) { if (myTargetNodeChannel.TruDID != tDeviceID) { myTargetNodeChannel.TruDID = tDeviceID; TheBaseAssets.MySYSLOG.WriteToLog(243, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("CoreComm", $"Custom ISB sets TruDID to: {TheCommonUtils.GetDeviceIDML(tDeviceID)} for MTNC: {myTargetNodeChannel.ToMLString()}", eMsgLevel.l4_Message), true); } } else { TheBaseAssets.MySYSLOG.WriteToLog(243, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("CoreComm", $"Different DeviceIDs received ...new: {TheCommonUtils.GetDeviceIDML(tDeviceID)} old: {TheCommonUtils.GetDeviceIDML(myTargetNodeChannel.cdeMID)} {(myTargetNodeChannel.SenderType == cdeSenderType.CDE_CLOUDROUTE ? "For CloudRoute and Service normal" : "")}", eMsgLevel.l2_Warning), true); TheBaseAssets.MySession.RemoveSessionsByDeviceID(myTargetNodeChannel.cdeMID, Guid.Empty); TheQueuedSenderRegistry.UpdateQSenderID(myTargetNodeChannel.cdeMID, tDeviceID); myTargetNodeChannel.cdeMID = tDeviceID; if (pRequestData.DeviceID != tDeviceID) { TheBaseAssets.MySYSLOG.WriteToLog(243, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM("CoreComm", $"Different DeviceIDs in DID and Request ...DID: {TheCommonUtils.GetDeviceIDML(tDeviceID)} Request: {TheCommonUtils.GetDeviceIDML(myTargetNodeChannel.cdeMID)}", eMsgLevel.l2_Warning), true); pRequestData.DeviceID = tDeviceID; } switch (pRequestData.ResponseMimeType) { case "cde/mini": myTargetNodeChannel.SenderType = cdeSenderType.CDE_MINI; break; } } } if (myTargetNodeChannel.MySessionState == null) { myTargetNodeChannel.MySessionState = TheBaseAssets.MySession.GetOrCreateSessionState(tSessionID, pRequestData); } myTargetNodeChannel.MySessionState.SiteVersion = tVersion; myTargetNodeChannel.MySessionState.cdeMID = tSessionID; myTargetNodeChannel.MySessionState.CurrentURL = myTargetNodeChannel.TargetUrl; // Keep the RSA public key of the other party, so we can use it to encrypt data when sending to that party in the future if (!String.IsNullOrEmpty(tDev.RSA)) { myTargetNodeChannel.MySessionState.RSAPublicSend = tDev.RSA; } if (MyQSender.IsConnecting && !MyQSender.IsConnected) { MyQSender.IsConnected = true; if (myTargetNodeChannel.SenderType == cdeSenderType.CDE_CLOUDROUTE) { if (TheBaseAssets.MyServiceHostInfo.IsIsolated && TheBaseAssets.MyServiceHostInfo.MasterNode == Guid.Empty) { TheBaseAssets.MyServiceHostInfo.MasterNode = myTargetNodeChannel.cdeMID; TheQueuedSenderRegistry.SendMasterNodeQueue(); } MyQSender.StartHeartBeat(); TheBaseAssets.MySYSLOG.WriteToLog(23055, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("CoreComm", $"Cloud Route is back up to {myTargetNodeChannel.ToMLString()}", eMsgLevel.l4_Message)); if (TheQueuedSenderRegistry.eventCloudIsBackUp != null) { TheCommonUtils.cdeRunAsync("QS-StartEngineNU", true, o => { TheQueuedSenderRegistry.eventCloudIsBackUp(TheCDEngines.MyContentEngine, myTargetNodeChannel); }); } } if (MyQSender.eventConnected != null) { TheCommonUtils.cdeRunAsync("QueueConnected", true, (p) => { MyQSender.eventConnected(MyQSender, myTargetNodeChannel); }); } MyQSender.MyISBlock?.FireEvent("Connected"); } pRequestData.SessionState = myTargetNodeChannel.MySessionState; MyQSender?.SetLastHeartbeat(myTargetNodeChannel.MySessionState); } if (!string.IsNullOrEmpty(tDev.TOP) && tDev.TOP.StartsWith("CDE_CONNECT")) { string[] tP = TheCommonUtils.cdeSplit(tDev.TOP, ";:;", true, true); if (tP.Length > 1) { string tEngs = tP[1]; TheCommonUtils.cdeRunAsync("QS-StartEngineNU", false, o => { TheCDEngines.StartEngineWithNewUrl(MyQSender?.MyTargetNodeChannel, tEngs); }); } if (tDevList.Count > 1) { if (toRemove == null) { toRemove = new List <TheDeviceMessage>(); } toRemove.Add(tDev); continue; } else { return; } } if (string.IsNullOrEmpty(tDev.TOP) || tDev.TOP.StartsWith("CDE_PICKUP") || tDev.TOP.StartsWith("CDE_WSINIT")) { TheBaseAssets.MySYSLOG.WriteToLog(23056, TSM.L(eDEBUG_LEVELS.FULLVERBOSE) ? null : new TSM("CoreComm", $"Heartbeat received {MyQSender?.MyTargetNodeChannel?.ToMLString()}", eMsgLevel.l4_Message)); if (tDevList.Count > 1) { if (toRemove == null) { toRemove = new List <TheDeviceMessage>(); } toRemove.Add(tDev); continue; } else { return; } } break; //Found valid path and can go out } } if (toRemove != null) { foreach (var tDev in toRemove) { tDevList.Remove(tDev); } } TheCommonUtils.cdeRunAsync("QS-UpCo2Exec", false, o => { pRequestData.ResponseBuffer = null; DoExecuteCommand(null, MyQSender, false, pRequestData, tDevList); }, tDevList); }
public override bool Init() { TT.SetSafePropertyNumber(MyBaseThing, "ManufacturingCarbonFootprint", 0.001); //1KG if not specified TheCDEngines.RegisterNewMiniRelay("EnergyMessages"); return(base.Init()); }
private IEnumerable <TheThing> GetMatchingThings(Subscription subscription) { var things = new List <TheThing>(); if (_thingReference.ThingMID.HasValue && _thingReference.ThingMID != Guid.Empty) { var thing = TheThingRegistry.GetThingByMID(_thingReference.ThingMID.Value, true); if (thing != null) { things.Add(thing); } return(things); } IBaseEngine baseEngine = null; List <TheThing> matchingThings = null; if (!string.IsNullOrEmpty(_thingReference.EngineName)) { baseEngine = TheThingRegistry.GetBaseEngine(_thingReference.EngineName); if (baseEngine == null) { TheCDEngines.RegisterNewMiniRelay(_thingReference.EngineName); baseEngine = TheThingRegistry.GetBaseEngine(_thingReference.EngineName); } if (baseEngine != null) { subscription?.AddSubscription(baseEngine, this); matchingThings = TheThingRegistry.GetThingsOfEngine(_thingReference.EngineName, true, true); } } else { object deviceTypeObj = null; if (_thingReference.PropertiesToMatch?.TryGetValue("DeviceType", out deviceTypeObj) == true) { var deviceType = TheCommonUtils.CStr(deviceTypeObj); if (!string.IsNullOrEmpty(deviceType)) { matchingThings = TheThingRegistry.GetThingsByFunc("*", t => t.DeviceType.Equals(deviceType, StringComparison.Ordinal), true); } } } if (matchingThings != null) { foreach (var thing in matchingThings) { if (Matches(thing)) { if (baseEngine == null) { subscription?.AddSubscription(thing.GetBaseEngine(), this); } things.Add(thing); } } } return(things); }
/// <summary> /// Shutsdown the C-DEngine and all plugins /// Applications can override this function to add custom shutdown code /// </summary> /// <param name="ForceExit">If True and the C-DEngine will Stop or restart the hosting application. If it is hosted in IIS, the Application Pool hosting the app will be Stopped or Restarted depending on the next parameter</param> /// <param name="waitIfPending">Waits in case The shutdown is already initiated</param> public virtual void Shutdown(bool ForceExit, bool waitIfPending = false) { if (!waitIfPending) { if (!TheBaseAssets.MasterSwitch || TheCommonUtils.cdeIsLocked(ShutdownLock)) { return; //Make sure we dont do this twice } } lock (ShutdownLock) { if (TheBaseAssets.MasterSwitch) { if (TheBaseAssets.IsStarting) { TheBaseAssets.MySYSLOG?.WriteToLog(3, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM(TheBaseAssets.MyServiceHostInfo.ApplicationName, "Shutdown was requested, but startup has not finished. Waiting for startup to finish.", eMsgLevel.l3_ImportantMessage)); // Ensure we wait for user manager so CUOFS first-run-only settings are applied var sw = System.Diagnostics.Stopwatch.StartNew(); while (TheBaseAssets.IsStarting && sw.ElapsedMilliseconds < 60000) { Thread.Sleep(100); } if (TheBaseAssets.IsStarting) { TheBaseAssets.MySYSLOG?.WriteToLog(3, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(TheBaseAssets.MyServiceHostInfo.ApplicationName, "Shutdown was requested, but startup has not finished after wait time (60 seconds). Shutting down regardless. Some first-run-only settings may not have been applied.", eMsgLevel.l1_Error)); } } if (TheBaseAssets.MyServiceHostInfo.PreShutDownDelay > 0) { var tcsPreHandlers = new TaskCompletionSource <bool>(); TheCommonUtils.cdeRunAsync("PreShutdownHandlers", true, (o) => { TheCDEngines.MyContentEngine?.FireEvent(eEngineEvents.PreShutdown, null, TheBaseAssets.MyServiceHostInfo.PreShutDownDelay, false); tcsPreHandlers.TrySetResult(true); }); tcsPreHandlers.Task.Wait(TheBaseAssets.MyServiceHostInfo.PreShutDownDelay); } while (Interlocked.Read(ref TheBaseAssets.DelayShutDownCount) > 0) { TheCommonUtils.SleepOneEye(100, 100); } TheBaseAssets.MySYSLOG?.WriteToLog(3, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM(TheBaseAssets.MyServiceHostInfo.ApplicationName, TheBaseAssets.MyServiceHostInfo.ApplicationTitle + " Initiating shutdown at : " + TheCommonUtils.GetDateTimeString(DateTimeOffset.Now), eMsgLevel.l6_Debug)); TheBaseAssets.MasterSwitch = false; TheBaseAssets.ForceShutdown = ForceExit; TheCDEngines.StopAllEngines(); TheBaseAssets.MySYSLOG?.WriteToLog(3, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM(TheBaseAssets.MyServiceHostInfo.ApplicationName, TheBaseAssets.MyServiceHostInfo.ApplicationTitle + " Shutdown: Engines stopped at: " + TheCommonUtils.GetDateTimeString(DateTimeOffset.Now), eMsgLevel.l6_Debug)); TheCommCore.StopCommunication(); TheBaseAssets.MySYSLOG?.WriteToLog(3, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM(TheBaseAssets.MyServiceHostInfo.ApplicationName, TheBaseAssets.MyServiceHostInfo.ApplicationTitle + " Shutdown: Communications stopped at: " + TheCommonUtils.GetDateTimeString(DateTimeOffset.Now), eMsgLevel.l6_Debug)); if (MyCommonDisco != null) { MyCommonDisco.ShutdownDiscoService(); TheBaseAssets.MySYSLOG?.WriteToLog(3, TSM.L(eDEBUG_LEVELS.VERBOSE) ? null : new TSM(TheBaseAssets.MyServiceHostInfo.ApplicationName, TheBaseAssets.MyServiceHostInfo.ApplicationTitle + " Shutdown: Discovery Service stopped at: " + TheCommonUtils.GetDateTimeString(DateTimeOffset.Now), eMsgLevel.l6_Debug)); } if (TheBaseAssets.MySYSLOG != null) { string iis = ""; switch (TheBaseAssets.MyServiceHostInfo.cdeHostingType) { case cdeHostType.IIS: iis = " (Hosted in IIS)"; break; case cdeHostType.ASPCore: iis = " (Hosted in ASP.NET Core)"; break; } TheBaseAssets.MySYSLOG.WriteToLog(3, new TSM(TheBaseAssets.MyServiceHostInfo.ApplicationName, TheBaseAssets.MyServiceHostInfo.ApplicationTitle + iis + " Stopped at : " + TheCommonUtils.GetDateTimeString(DateTimeOffset.Now), eMsgLevel.l4_Message)); //Log Entry that service has been started TheBaseAssets.MySYSLOG.Shutdown(); } } } }
/// <summary> /// Override to initalize the app with custom values but still call the base! /// </summary> /// <param name="pPlugInLst">List if ICDEPlugin instances</param> /// <param name="ArgList">Additional Parameters of the Application</param> /// <returns>True if all went well during startup</returns> public virtual bool StartBaseApplication2(List <ICDEPlugin> pPlugInLst, IDictionary <string, string> ArgList) { if (TheBaseAssets.MasterSwitch) { return(false); //SECURITY REVIEW: do not allow to call StartBaseApplication twice } TheBaseAssets.MasterSwitch = true; if (TheBaseAssets.MyServiceHostInfo == null) { TheBaseAssets.MasterSwitch = false; TheSystemMessageLog.ToCo("MyServiceHostInfo is not set! Exiting..."); //Will becalled because if MyServiceHostInfo==null TOCO will be called return(false); } if (TheBaseAssets.CryptoLoadMessage != null) { TheBaseAssets.MasterSwitch = false; TheSystemMessageLog.ToCo($"Security initialization failed with {TheBaseAssets.CryptoLoadMessage}. Exiting..."); return(false); } try { TheBaseAssets.IsStarting = true; //AppDomain.CurrentDomain.UnhandledException += MyUnhandledExceptionHandler; if (ArgList == null) { ArgList = new Dictionary <string, string>(); //DIC-Allowed! } if (!TheBaseAssets.MySettings.ReadAllAppSettings(ref ArgList)) { TheSystemMessageLog.ToCo("Not reading app.config: not supported by platform."); //Will never be called! } if (!TheBaseAssets.MasterSwitch) { return(false); } TheBaseAssets.MyCmdArgs = ArgList; //MyCmdArgs ONLY contains "public" settings coming from app.config or via the host MyUserManager = new TheUserManager(); TheBaseAssets.InitAssets(this); if (!TheBaseAssets.MasterSwitch) { return(false); } TheBaseAssets.MyScopeManager.RegisterScopeChanged(EventScopeChanged); TheBaseAssets.MySYSLOG.WriteToLog(4140, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseApplication", "Assets and SystemLog Initialized", eMsgLevel.l3_ImportantMessage)); int minWorker = -1, minCompletionPort = -1, maxWorker = -1, maxCompletionPort = -1; try { System.Threading.ThreadPool.GetMinThreads(out minWorker, out minCompletionPort); System.Threading.ThreadPool.GetMaxThreads(out maxWorker, out maxCompletionPort); } catch { }; #if CDE_STANDARD var largeObjectHeapCompactionMode = System.Runtime.GCSettings.LargeObjectHeapCompactionMode; #else const string largeObjectHeapCompactionMode = "n/a"; #endif TheBaseAssets.MySYSLOG.WriteToLog(4144, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(eEngineName.ContentService, $"CLR Info", eMsgLevel.l4_Message, $"Server GC: {System.Runtime.GCSettings.IsServerGC}. GC Latency Mode: {System.Runtime.GCSettings.LatencyMode}. LOHC Mode: {largeObjectHeapCompactionMode}. Bitness: {System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)) * 8}. Threads Min W/CP, Max W/CP: {minWorker}/{minCompletionPort},{maxWorker}/{maxCompletionPort}. GC TotalMemory: {GC.GetTotalMemory(false)}")); if (!TheBaseAssets.MyActivationManager.InitializeLicenses()) { Shutdown(true); TheBaseAssets.MySYSLOG.WriteToLog(4145, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseApplication", "Licensing error", eMsgLevel.l3_ImportantMessage)); return(false); } //4.304: Workitem #2289 - Removed from OSS Release (as CheckLicense is always returning true in the CoreCrypto Lib if (!TheBaseAssets.MyActivationManager.CheckLicense(new Guid("{5737240C-AA66-417C-9B66-3919E18F9F4A}"), "", null, 1, false)) { if (TheBaseAssets.MyServiceHostInfo.ShutdownOnLicenseFailure) { TheBaseAssets.MySYSLOG.WriteToLog(4146, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseApplication", "Licensing error: no activated license for Thing Service. Shutting down immediately as configured.", eMsgLevel.l2_Warning)); return(false); } else { TheBaseAssets.MySYSLOG.WriteToLog(4147, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseApplication", "Licensing error: no activated license for Thing Service. Will shut down in 60 minutes if not activated.", eMsgLevel.l2_Warning)); TheCommonUtils.cdeRunAsync("LicenseCheck", true, (o) => { TheCommonUtils.TaskDelayOneEye(60 * 60 * 1000, 100).ContinueWith((t) => { if (TheBaseAssets.MasterSwitch) { if (!TheBaseAssets.MyActivationManager.CheckLicense(new Guid("{5737240C-AA66-417C-9B66-3919E18F9F4A}"), "", null, 1, false)) { TheBaseAssets.MySYSLOG.WriteToLog(4148, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseApplication", "Licensing error: no activated license for Thing Service. Shutting down.", eMsgLevel.l1_Error)); if (TheBaseAssets.IsInAgentStartup) { MyISMRoot?.Restart(true); } else { Shutdown(true); } } } }); }); } } TheCommCore.MyHttpService = new TheHttpService(); TheBaseAssets.MySYSLOG.WriteToLog(4141, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseApplication", "HttpService created", eMsgLevel.l3_ImportantMessage)); if (TheBaseAssets.MyServiceHostInfo.StartISM && MyISMRoot == null && !string.IsNullOrEmpty(TheBaseAssets.MyServiceHostInfo.BaseDirectory)) { MyISMRoot = new TheISMManager { eventShutdownRequired = sinkAppShutdown }; MyISMRoot.InitISM("", "", "", TheBaseAssets.MyServiceHostInfo.CurrentVersion, TheBaseAssets.MyServiceHostInfo.ISMScanForUpdatesOnUSB, TheBaseAssets.MyServiceHostInfo.ISMScanOnStartup); TheBaseAssets.MySYSLOG.WriteToLog(4142, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseApplication", "ISM Started", eMsgLevel.l3_ImportantMessage)); } else { TheBaseAssets.MyServiceHostInfo.StartISM = false; } if (!TheBaseAssets.MasterSwitch) { return(false); } if (MyCommonDisco == null) { if (!TheBaseAssets.MyServiceHostInfo.IsIsolated && (TheCommonUtils.IsHostADevice() || TheBaseAssets.MyServiceHostInfo.cdeNodeType == cdeNodeType.Active)) { TheBaseAssets.MySettings.SetSetting("DISCO_IsClientOnly", "True"); } MyCommonDisco = new TheCommonDisco(); // Initialized the Discovery Service } TheCDEngines.eventAllEnginesStarted += sinkEnginesStarted; if (!TheCDEngines.StartEngines(pPlugInLst, null)) //Starts all SubEngines and Plugins. MyCmdArgs is a copy of the tParas sent to the Init Assets Function and can be used to set parameters for each engine during startup { Shutdown(true); TheBaseAssets.MySYSLOG.WriteToLog(4149, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseApplication", "Failed to start engines", eMsgLevel.l3_ImportantMessage)); return(false); } return(true); } finally { TheBaseAssets.IsStarting = false; } }
private async Task RunPlaybackAsync(IEnumerable <cdeP> allProperties, IEnumerable <object> thingUpdates, TimeSpan startupDelayRange, bool bFromAutoStart, double propCountBefore) { for (int j = 1; j <= ReplayCount; j++) { playbackCancel?.Cancel(); playbackCancel = new CancellationTokenSource(); var cancelCombined = CancellationTokenSource.CreateLinkedTokenSource(playbackCancel.Token, TheBaseAssets.MasterSwitchCancelationToken); IsStarted = true; MyBaseThing.StatusLevel = 1; MyBaseThing.LastMessage = $"Playback started: {ItemCount} items. {ParallelPlaybackCount} things."; for (int i = 1; i <= ParallelPlaybackCount; i++) { TheThing tThingOverride = null; if (!string.IsNullOrEmpty(PlaybackEngineName)) { if (TheThingRegistry.GetBaseEngine(PlaybackEngineName) == null) { TheCDEngines.RegisterNewMiniRelay(PlaybackEngineName); } var thingName = $"{MyBaseThing.FriendlyName}{i:D6}"; tThingOverride = TheThingRegistry.GetThingByID(PlaybackEngineName, thingName, true); if (tThingOverride == null) { tThingOverride = new TheThing { FriendlyName = thingName, ID = thingName, EngineName = PlaybackEngineName, DeviceType = PlaybackDeviceType, }; foreach (var prop in allProperties) { tThingOverride.SetProperty(prop.Name, prop.Value, prop.cdeT); } TheThingRegistry.RegisterThing(tThingOverride); } // This only works if the plug-in is actually installed, not with mini relay //var createThingInfo = new TheThingRegistry.MsgCreateThingRequestV1 //{ // EngineName = PlaybackEngineName, // DeviceType = PlaybackDeviceType, // InstanceId = thingName, // FriendlyName = thingName, // CreateIfNotExist = true, // DoNotModifyIfExists = true, // OwnerAddress = MyBaseThing, // Properties = new Dictionary<string, object> { { "ID", thingName } }, //}; //tThingOverride = await TheThingRegistry.CreateOwnedThingAsync(createThingInfo, new TimeSpan(0, 1, 0)); if (tThingOverride == null) { MyBaseThing.LastMessage = "Error creating playback thing"; break; } } var playbackTask = TheCommonUtils.cdeRunTaskChainAsync($"Playback{i}", o => PlaybackLoop(tThingOverride, cancelCombined.Token, thingUpdates, startupDelayRange, bFromAutoStart), true); playbackTasks.Add(playbackTask); } _ = await TheCommonUtils.TaskWhenAll(playbackTasks).ContinueWith(async(t) => { try { PlaybackDuration = sw.Elapsed; sw.Stop(); OnKpiUpdate(null); var propCount = Gen_Stats_PropertyCounter - propCountBefore; var message = $"Playback done. {propCount} props in {PlaybackDuration}. {propCount / PlaybackDuration.TotalSeconds} props/s. {ItemCount * ParallelPlaybackCount / PlaybackDuration.TotalSeconds} items/s."; //MyBaseThing.LastMessage = message; TheBaseAssets.MySYSLOG.WriteToLog(700, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM(MyBaseThing.EngineName, message, eMsgLevel.l6_Debug)); await StopPlaybackAsync(message); _ = new CDMyMeshManager.Contracts.MsgReportTestStatus { NodeId = TheBaseAssets.MyServiceHostInfo.MyDeviceInfo.DeviceID, PercentCompleted = (j * 1.0 / ReplayCount) * 100, SuccessRate = 100, Status = j == ReplayCount ? CDMyMeshManager.Contracts.eTestStatus.Success : CDMyMeshManager.Contracts.eTestStatus.Running, TestRunId = TheCommonUtils.CGuid(TheBaseAssets.MySettings.GetSetting("TestRunID")), Timestamp = DateTimeOffset.Now, ResultDetails = new Dictionary <string, object> { { "Message", message }, { "PropertyCount", propCount }, { "DurationInSeconds", PlaybackDuration.TotalSeconds } }, }.Publish().Result; } catch { } }, TaskContinuationOptions.OnlyOnRanToCompletion); } }
public override bool Init() { TheCDEngines.RegisterNewMiniRelay("EnergyMessages"); return(base.Init()); }
public override void HandleMessage(ICDEThing sender, object pIncoming) { if (TheCDEngines.MyIStorageService == null) { return; //No processing if Storage is not active } TheProcessMessage pMsg = pIncoming as TheProcessMessage; if (pMsg == null) { return; } if (!mIsInitialized) { //InitializeStores(); //V4.106: we dont allow this anymore during runtime - the store is either initialized during startup or never available return; } if (MyBaseEngine.GetEngineState().IsService) { var tCmd = pMsg.Message.TXT.Split(':'); switch (tCmd[0]) { case "NEW_SENSOR_VALUE": TheSensorValue tData = TheCommonUtils.DeserializeJSONStringToObject <TheSensorValue>(pMsg.Message.PLS); if (tData != null && MySensorStore != null) { //TODO: tCmd[1] has the "ChartToken" that allows to put the value into different tables/charts. For now just one table for all charts MySensorStore.AddAnItem(tData); } break; default: ProcessStorageServiceCommands(pMsg.Message, pMsg.LocalCallback, false); break; } return; } //CM: Next section is about Remote Storage Services. This will come in a later step string[] reqGuid = pMsg.Message.TXT.Split(':'); TheTimedCallback tCall = null; if (reqGuid.Length > 1 && (tCall = MyTimedCallbacks.MyMirrorCache.GetEntryByID(TheCommonUtils.CGuid(reqGuid[1]))) != null) { tCall.MyCallback?.Invoke(pMsg.Message); MyTimedCallbacks.RemoveAnItem(tCall, null); } else { object tStorageMirror = TheCDEngines.GetStorageMirror(pMsg.Topic); //, out tStorageMirror); if (tStorageMirror != null) { Type magicType = tStorageMirror.GetType(); #if CDE_STANDARD MethodInfo magicMethod = magicType.GetTypeInfo().GetDeclaredMethod("sinkProcessServiceMessages"); #else MethodInfo magicMethod = magicType.GetMethod("sinkProcessServiceMessages"); #endif if (magicMethod != null) { magicMethod.Invoke(tStorageMirror, new object[] { pMsg.Message }); //object magicValue = } } } }