2019-11-23 02:26:34 +00:00
|
|
|
|
using Mono.Unix;
|
2020-01-06 02:34:03 +00:00
|
|
|
|
using Serilog;
|
|
|
|
|
using Serilog.Events;
|
|
|
|
|
using Serilog.Filters;
|
|
|
|
|
using Serilog.Formatting.Compact;
|
2019-11-23 02:26:34 +00:00
|
|
|
|
using System;
|
2024-05-08 21:57:14 +00:00
|
|
|
|
using System.Diagnostics;
|
2016-11-30 03:58:51 +00:00
|
|
|
|
using System.IO;
|
2024-05-08 21:57:14 +00:00
|
|
|
|
using System.Linq;
|
2020-01-06 02:34:03 +00:00
|
|
|
|
using System.Net;
|
2016-11-30 03:58:51 +00:00
|
|
|
|
using System.Reflection;
|
2016-11-15 17:37:56 +00:00
|
|
|
|
using System.ServiceProcess;
|
2019-11-23 02:26:34 +00:00
|
|
|
|
using System.Threading.Tasks;
|
2016-11-15 17:37:56 +00:00
|
|
|
|
|
2018-10-13 21:28:47 +00:00
|
|
|
|
namespace OmniLinkBridge
|
2016-11-15 17:37:56 +00:00
|
|
|
|
{
|
2024-05-08 21:57:14 +00:00
|
|
|
|
internal class Program
|
2016-11-15 17:37:56 +00:00
|
|
|
|
{
|
2024-05-08 21:57:14 +00:00
|
|
|
|
private static CoreServer server;
|
2016-11-15 17:37:56 +00:00
|
|
|
|
|
2024-05-08 21:57:14 +00:00
|
|
|
|
private static int Main(string[] args)
|
2016-11-15 17:37:56 +00:00
|
|
|
|
{
|
2016-11-26 04:06:46 +00:00
|
|
|
|
bool interactive = false;
|
|
|
|
|
|
2020-01-06 02:34:03 +00:00
|
|
|
|
string config_file = "OmniLinkBridge.ini";
|
|
|
|
|
string log_file = "log.txt";
|
|
|
|
|
bool log_clef = false;
|
|
|
|
|
LogEventLevel log_level = LogEventLevel.Information;
|
|
|
|
|
|
2016-11-15 17:37:56 +00:00
|
|
|
|
for (int i = 0; i < args.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
switch (args[i])
|
|
|
|
|
{
|
2016-11-26 04:06:46 +00:00
|
|
|
|
case "/?":
|
|
|
|
|
case "-h":
|
|
|
|
|
case "-help":
|
|
|
|
|
ShowHelp();
|
2020-01-06 02:34:03 +00:00
|
|
|
|
return 0;
|
2016-11-15 17:37:56 +00:00
|
|
|
|
case "-c":
|
2020-01-06 02:34:03 +00:00
|
|
|
|
config_file = args[++i];
|
2016-11-30 03:58:51 +00:00
|
|
|
|
break;
|
2019-12-27 03:14:58 +00:00
|
|
|
|
case "-e":
|
2020-01-06 02:34:03 +00:00
|
|
|
|
Global.UseEnvironment = true;
|
2019-12-27 03:14:58 +00:00
|
|
|
|
break;
|
|
|
|
|
case "-d":
|
2020-01-06 02:34:03 +00:00
|
|
|
|
Global.DebugSettings = true;
|
|
|
|
|
break;
|
|
|
|
|
case "-lf":
|
|
|
|
|
log_file = args[++i];
|
|
|
|
|
|
|
|
|
|
if (string.Compare(log_file, "disable", true) == 0)
|
|
|
|
|
log_file = null;
|
|
|
|
|
break;
|
|
|
|
|
case "-lj":
|
|
|
|
|
log_clef = true;
|
|
|
|
|
break;
|
|
|
|
|
case "-ll":
|
|
|
|
|
Enum.TryParse(args[++i], out log_level);
|
2019-12-27 03:14:58 +00:00
|
|
|
|
break;
|
2024-05-08 21:57:14 +00:00
|
|
|
|
case "-ld":
|
|
|
|
|
Global.DebugSettings = true;
|
|
|
|
|
Global.SendLogs = true;
|
|
|
|
|
break;
|
2018-10-13 21:28:47 +00:00
|
|
|
|
case "-s":
|
|
|
|
|
Global.webapi_subscriptions_file = args[++i];
|
2016-11-15 17:37:56 +00:00
|
|
|
|
break;
|
2016-11-26 04:06:46 +00:00
|
|
|
|
case "-i":
|
|
|
|
|
interactive = true;
|
|
|
|
|
break;
|
2016-11-15 17:37:56 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-08 21:57:14 +00:00
|
|
|
|
if (string.Compare(Environment.GetEnvironmentVariable("SEND_LOGS"), "1") == 0)
|
|
|
|
|
{
|
|
|
|
|
Global.DebugSettings = true;
|
|
|
|
|
Global.SendLogs = true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-06 02:34:03 +00:00
|
|
|
|
config_file = GetFullPath(config_file);
|
|
|
|
|
|
|
|
|
|
Global.webapi_subscriptions_file = GetFullPath(Global.webapi_subscriptions_file ?? "WebSubscriptions.json");
|
2018-10-13 21:28:47 +00:00
|
|
|
|
|
2020-01-06 02:34:03 +00:00
|
|
|
|
// Use TLS 1.2 as default connection
|
|
|
|
|
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
|
2016-11-30 03:58:51 +00:00
|
|
|
|
|
2020-01-06 02:34:03 +00:00
|
|
|
|
string log_format = "{Timestamp:yyyy-MM-dd HH:mm:ss} [{SourceContext} {Level:u3}] {Message:lj}{NewLine}{Exception}";
|
2016-11-30 03:58:51 +00:00
|
|
|
|
|
2020-01-06 02:34:03 +00:00
|
|
|
|
var log_config = new LoggerConfiguration()
|
|
|
|
|
.MinimumLevel.Verbose()
|
|
|
|
|
.Enrich.WithProperty("Application", "OmniLinkBridge")
|
2024-05-08 21:57:14 +00:00
|
|
|
|
.Enrich.WithProperty("Session", Global.SessionID)
|
2024-04-12 01:40:08 +00:00
|
|
|
|
.Enrich.With<ControllerEnricher>()
|
2020-01-06 02:34:03 +00:00
|
|
|
|
.Enrich.FromLogContext();
|
|
|
|
|
|
|
|
|
|
if (log_file != null)
|
|
|
|
|
{
|
|
|
|
|
log_file = GetFullPath(log_file);
|
|
|
|
|
|
|
|
|
|
if (log_clef)
|
|
|
|
|
log_config = log_config.WriteTo.Async(a => a.File(new CompactJsonFormatter(), log_file, log_level,
|
|
|
|
|
rollingInterval: RollingInterval.Day, retainedFileCountLimit: 15));
|
|
|
|
|
else
|
|
|
|
|
log_config = log_config.WriteTo.Async(a => a.File(log_file, log_level, log_format,
|
|
|
|
|
rollingInterval: RollingInterval.Day, retainedFileCountLimit: 15));
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-08 21:57:14 +00:00
|
|
|
|
if (Global.SendLogs)
|
|
|
|
|
log_config = log_config.WriteTo.Logger(lc => lc
|
|
|
|
|
.WriteTo.Http("https://telemetry.excalibur-partners.com"));
|
|
|
|
|
else if (UseTelemetry())
|
2020-01-06 02:34:03 +00:00
|
|
|
|
log_config = log_config.WriteTo.Logger(lc => lc
|
|
|
|
|
.Filter.ByIncludingOnly(Matching.WithProperty("Telemetry"))
|
|
|
|
|
.WriteTo.Http("https://telemetry.excalibur-partners.com"));
|
|
|
|
|
|
|
|
|
|
if (Environment.UserInteractive || interactive)
|
|
|
|
|
log_config = log_config.WriteTo.Console(outputTemplate: log_format);
|
|
|
|
|
|
|
|
|
|
Log.Logger = log_config.CreateLogger();
|
2019-12-27 03:14:58 +00:00
|
|
|
|
|
2016-11-30 03:58:51 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
2020-01-06 02:34:03 +00:00
|
|
|
|
Settings.LoadSettings(config_file);
|
2016-11-30 03:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
// Errors are logged in LoadSettings();
|
2020-01-06 02:34:03 +00:00
|
|
|
|
Log.CloseAndFlush();
|
|
|
|
|
return -1;
|
2016-11-30 03:58:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-26 04:06:46 +00:00
|
|
|
|
if (Environment.UserInteractive || interactive)
|
2016-11-15 17:37:56 +00:00
|
|
|
|
{
|
2019-11-23 02:26:34 +00:00
|
|
|
|
if (IsRunningOnMono())
|
|
|
|
|
{
|
|
|
|
|
UnixSignal[] signals = new UnixSignal[]{
|
|
|
|
|
new UnixSignal(Mono.Unix.Native.Signum.SIGTERM),
|
|
|
|
|
new UnixSignal(Mono.Unix.Native.Signum.SIGINT),
|
|
|
|
|
new UnixSignal(Mono.Unix.Native.Signum.SIGUSR1)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Task.Factory.StartNew(() =>
|
|
|
|
|
{
|
|
|
|
|
// Blocking call to wait for any kill signal
|
|
|
|
|
int index = UnixSignal.WaitAny(signals, -1);
|
|
|
|
|
|
|
|
|
|
server.Shutdown();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-15 17:37:56 +00:00
|
|
|
|
Console.TreatControlCAsInput = false;
|
|
|
|
|
Console.CancelKeyPress += new ConsoleCancelEventHandler(myHandler);
|
|
|
|
|
|
|
|
|
|
server = new CoreServer();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ServiceBase[] ServicesToRun;
|
|
|
|
|
|
|
|
|
|
// More than one user Service may run within the same process. To add
|
|
|
|
|
// another service to this process, change the following line to
|
|
|
|
|
// create a second service object. For example,
|
|
|
|
|
//
|
|
|
|
|
// ServicesToRun = new ServiceBase[] {new Service1(), new MySecondUserService()};
|
|
|
|
|
//
|
|
|
|
|
ServicesToRun = new ServiceBase[] { new Service() };
|
|
|
|
|
|
|
|
|
|
ServiceBase.Run(ServicesToRun);
|
|
|
|
|
}
|
2020-01-06 02:34:03 +00:00
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-08 21:57:14 +00:00
|
|
|
|
private static string GetFullPath(string file)
|
2020-01-06 02:34:03 +00:00
|
|
|
|
{
|
|
|
|
|
if (Path.IsPathRooted(file))
|
|
|
|
|
return file;
|
|
|
|
|
|
|
|
|
|
return Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), file);
|
2016-11-15 17:37:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected static void myHandler(object sender, ConsoleCancelEventArgs args)
|
|
|
|
|
{
|
|
|
|
|
server.Shutdown();
|
|
|
|
|
args.Cancel = true;
|
|
|
|
|
}
|
2016-11-26 04:06:46 +00:00
|
|
|
|
|
2024-05-08 21:57:14 +00:00
|
|
|
|
private static bool IsRunningOnMono()
|
2019-11-23 02:26:34 +00:00
|
|
|
|
{
|
|
|
|
|
return Type.GetType("Mono.Runtime") != null;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-08 21:57:14 +00:00
|
|
|
|
public static string GetEnvironment()
|
|
|
|
|
{
|
|
|
|
|
if (Environment.GetEnvironmentVariable("HASSIO_TOKEN") != null)
|
|
|
|
|
return "Home Assistant";
|
|
|
|
|
else if (IsRunningOnMono())
|
|
|
|
|
return Process.GetProcesses().Any(w => w.Id == 2) ? "Mono" : "Docker";
|
|
|
|
|
else
|
|
|
|
|
return "Native";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool UseTelemetry()
|
2020-01-06 02:34:03 +00:00
|
|
|
|
{
|
|
|
|
|
return string.Compare(Environment.GetEnvironmentVariable("TELEMETRY_OPTOUT"), "1") != 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-08 21:57:14 +00:00
|
|
|
|
public static void ShowSendLogsWarning()
|
|
|
|
|
{
|
|
|
|
|
if (Global.SendLogs)
|
|
|
|
|
Log.Warning("SENDING LOGS TO DEVELOPER Controller: {ControllerID}, Session: {Session}",
|
|
|
|
|
Global.controller_id, Global.SessionID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void ShowHelp()
|
2016-11-26 04:06:46 +00:00
|
|
|
|
{
|
|
|
|
|
Console.WriteLine(
|
2020-01-06 02:34:03 +00:00
|
|
|
|
AppDomain.CurrentDomain.FriendlyName + " [-c config_file] [-e] [-d] [-j] [-s subscriptions_file]\n" +
|
2024-05-08 21:57:14 +00:00
|
|
|
|
"\t[-lf log_file|disable] [-lj [-ll verbose|debug|information|warning|error] [-ld] [-i]\n" +
|
2020-01-06 02:34:03 +00:00
|
|
|
|
"\t-c Specifies the configuration file. Default is OmniLinkBridge.ini\n" +
|
|
|
|
|
"\t-e Check environment variables for configuration settings\n" +
|
|
|
|
|
"\t-d Show debug ouput for configuration loading\n" +
|
|
|
|
|
"\t-s Specifies the web api subscriptions file. Default is WebSubscriptions.json\n" +
|
|
|
|
|
"\t-lf Specifies the rolling log file. Retention is 15 days. Default is log.txt.\n" +
|
|
|
|
|
"\t-lj Write logs as CLEF (compact log event format) JSON.\n" +
|
|
|
|
|
"\t-ll Minimum level at which events will be logged. Default is information.\n" +
|
2024-05-08 21:57:14 +00:00
|
|
|
|
"\t-ld Send logs to developer. ONLY USE WHEN ASKED.\n" +
|
|
|
|
|
"\t Also enabled by setting a SEND_LOGS environment variable to 1.\n" +
|
2020-01-06 02:34:03 +00:00
|
|
|
|
"\t-i Run in interactive mode");
|
|
|
|
|
|
2024-05-08 21:57:14 +00:00
|
|
|
|
Console.WriteLine(
|
|
|
|
|
"\nVersion: " + Assembly.GetExecutingAssembly().GetName().Version +
|
|
|
|
|
"\nEnvironment: " + GetEnvironment());
|
|
|
|
|
|
2020-01-06 02:34:03 +00:00
|
|
|
|
Console.WriteLine(
|
|
|
|
|
"\nOmniLink Bridge collects anonymous telemetry data to help improve the software.\n" +
|
|
|
|
|
"You can opt of telemetry by setting a TELEMETRY_OPTOUT environment variable to 1.");
|
2016-11-26 04:06:46 +00:00
|
|
|
|
}
|
2016-11-15 17:37:56 +00:00
|
|
|
|
}
|
|
|
|
|
}
|