using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Edge.Core.Processor; using Edge.Core.Database; using System.Diagnostics; using System.Threading; using System.Xml; using System.Security.Cryptography; using System.Text; using System.Runtime.InteropServices; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using LiteFccCoreMain.Service; using System.IO.Ports; using System.Runtime.Loader; using System.Threading.Tasks; using System.IO; using MQTTnet.Server; using MQTTnet.Protocol; using MQTTnet.Diagnostics; using Microsoft.EntityFrameworkCore; using Edge.Core.Configuration; using System.Text.RegularExpressions; using Edge.Core.Processor.Dispatcher; using Edge.Core.UniversalApi; namespace LiteFccCoreMain { class Program { static ILogger mainLogger;//= NLog.LogManager.LoadConfiguration("nlog.config").GetLogger("Main"); static DefaultDispatcher processorsDispatcher = null; public static async Task Main(string[] args) { Console.WriteLine("LiteFccCore is starting..."); var services = ServiceBuilder.Build(); var loggerFactory = services.GetRequiredService(); mainLogger = loggerFactory.CreateLogger("Main"); string coreVersionStr = $"{Assembly.GetAssembly(typeof(IProcessor)).GetName().Version.ToString()}(core), " + $"{Assembly.GetAssembly(typeof(Program)).GetName().Version.ToString()}(entry)"; IEnumerable processorInstances = null; #region pre-Setup AppDomain.CurrentDomain.UnhandledException += (sender, arg) => { mainLogger.LogError(string.Format("Unhandled exception from AppDomain.UnhandledException event:\r\n {0}", arg.ExceptionObject)); NLog.LogManager.Shutdown(); }; AppDomain.CurrentDomain.ProcessExit += (s, a) => { mainLogger.LogCritical("!!!!!! Process is exiting... !!!!!!"); Console.WriteLine("Stopping processors..."); mainLogger.LogInformation("Stopping processors..."); var stopResults = processorsDispatcher?.StopProcessorsAsync(processorInstances, "Process is Exiting...")?.Result; Console.WriteLine("Stopped processors."); mainLogger.LogInformation("Stopped processors." + Environment.NewLine + Environment.NewLine + Environment.NewLine); NLog.LogManager.Shutdown(); }; Console.CancelKeyPress += (sender, arg) => { Console.WriteLine("Cancel key: " + arg.SpecialKey + " pressed, will exit whole application..."); mainLogger.LogInformation("Cancel key: " + arg.SpecialKey + " pressed, will exit whole application..."); //shutdown the while LiteFccCore process Environment.Exit(-1); }; Console.WriteLine($"Version: {coreVersionStr}"); mainLogger.LogInformation($"Version: {coreVersionStr}"); PerformanceMonitor.Logger = loggerFactory.CreateLogger("Performance"); PerformanceMonitor.Start(); #endregion var configurator = services.GetService(); #region Migrating database mainLogger.LogInformation("Migrating database..."); Console.WriteLine("Migrating database..."); var migrateDbContext = services.GetRequiredService(); try { migrateDbContext.Database.Migrate(); } catch (Exception exx) { string migrationsStr = ""; string pendingMigrationsStr = ""; string appliedMigrationsStr = ""; try { migrationsStr = migrateDbContext.Database?.GetMigrations()?.Aggregate((acc, n) => acc + ", " + n) ?? ""; pendingMigrationsStr = migrateDbContext.Database?.GetPendingMigrations()?.Aggregate((acc, n) => acc + ", " + n) ?? ""; appliedMigrationsStr = migrateDbContext.Database?.GetAppliedMigrations()?.Aggregate((acc, n) => acc + ", " + n) ?? ""; } catch { mainLogger.LogError("Starting LiteFccCore Exceptioned when Migrating the database, detail: " + exx + System.Environment.NewLine + "migrations are: " + migrationsStr + System.Environment.NewLine + ", pendingMigrations are: " + pendingMigrationsStr + System.Environment.NewLine + ", appliedMigrations are: " + appliedMigrationsStr); } throw new InvalidOperationException("Starting LiteFccCore Exceptioned when Migrating the database"); } mainLogger.LogInformation(" Migrate finished."); Console.WriteLine($" Migrate finished.{Environment.NewLine}"); #endregion try { processorsDispatcher = new DefaultDispatcher(services); IEnumerable instantiateResults = null; if (args?.Any(g => g.Equals("--enable-safeboot", StringComparison.OrdinalIgnoreCase)) ?? false) { mainLogger.LogInformation("Enabling Safe Boot, Only Loading Core Moduels..."); Console.BackgroundColor = ConsoleColor.Yellow; Console.ForegroundColor = ConsoleColor.Black; Console.WriteLine("Enabling Safe Boot, Only Loading Core Moduels..."); Console.ResetColor(); instantiateResults = await processorsDispatcher.CreateProcessorsAsync("Main starting with enabling SafeBoot", true); } else instantiateResults = await processorsDispatcher.CreateProcessorsAsync("Main starting", false); var startResults = await processorsDispatcher.StartProcessorsAsync( instantiateResults.Where(r => r.Succeed).Select(r => r.ProcessorInstance), "Main starting"); processorInstances = startResults.Select(r => r.ProcessorInstance); processorsDispatcher.OnProcessorInstantiated += (__, arg) => { processorInstances = arg.OperationResults.Select(r => r.ProcessorInstance); instantiateResults = null; startResults = null; }; mainLogger.LogInformation("LiteFccCore is running..."); Console.BackgroundColor = ConsoleColor.Green; Console.ForegroundColor = ConsoleColor.Black; Console.WriteLine($"LiteFccCore with version: {coreVersionStr} is running..."); Console.ResetColor(); } catch (Exception exx) { mainLogger.LogError("******Start LiteFccCore internal error!\r\n" + exx.ToString()); Console.BackgroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Black; Console.WriteLine("******Start LiteFccCore internal error: " + exx.ToString().Substring(0, 70) + "..."); Console.ResetColor(); } while (true) { // in ARM Linux deamon mode, it always can read an empty line, here have to sleep to avoid quit. Thread.Sleep(1000); var read = Console.ReadLine(); } } } }