diff --git a/OmniLinkBridge/CoreServer.cs b/OmniLinkBridge/CoreServer.cs index 3d52b94..f00ecf1 100644 --- a/OmniLinkBridge/CoreServer.cs +++ b/OmniLinkBridge/CoreServer.cs @@ -44,9 +44,11 @@ private void Server() startTime = DateTime.Now; + Program.ShowSendLogsWarning(); + using (LogContext.PushProperty("Telemetry", "Startup")) - log.Information("Started version {Version} on {OperatingSystem} with {Modules}", - Assembly.GetExecutingAssembly().GetName().Version, Environment.OSVersion, modules); + log.Information("Started version {Version} in {Environment} on {OperatingSystem} with {Modules}", + Assembly.GetExecutingAssembly().GetName().Version, Program.GetEnvironment(), Environment.OSVersion, modules); // Startup modules foreach (IModule module in modules) diff --git a/OmniLinkBridge/Extensions.cs b/OmniLinkBridge/Extensions.cs index 7c6420a..231e974 100644 --- a/OmniLinkBridge/Extensions.cs +++ b/OmniLinkBridge/Extensions.cs @@ -9,6 +9,11 @@ namespace OmniLinkBridge { public static class Extensions { + public static string Truncate(this string value, int maxLength) + { + return value?.Length > maxLength ? value.Substring(0, maxLength) : value; + } + public static double ToCelsius(this double f) { // Convert to celsius diff --git a/OmniLinkBridge/Global.cs b/OmniLinkBridge/Global.cs index 0c4dd5f..6356fd7 100644 --- a/OmniLinkBridge/Global.cs +++ b/OmniLinkBridge/Global.cs @@ -10,6 +10,8 @@ public abstract class Global { public static bool DebugSettings { get; set; } public static bool UseEnvironment { get; set; } + public static bool SendLogs { get; set; } + public static Guid SessionID { get; } = Guid.NewGuid(); // HAI / Leviton Omni Controller public static string controller_address; diff --git a/OmniLinkBridge/Modules/MQTTModule.cs b/OmniLinkBridge/Modules/MQTTModule.cs index f0d8732..f79da85 100644 --- a/OmniLinkBridge/Modules/MQTTModule.cs +++ b/OmniLinkBridge/Modules/MQTTModule.cs @@ -402,6 +402,9 @@ private void PublishButtons() { log.Debug("Publishing {type}", "buttons"); + if (Global.mqtt_discovery_button_type == typeof(Switch)) + log.Information("See {setting} for new option when publishing {type}", "mqtt_discovery_button_type", "buttons"); + for (ushort i = 1; i <= OmniLink.Controller.Buttons.Count; i++) { clsButton button = OmniLink.Controller.Buttons[i]; @@ -421,8 +424,6 @@ private void PublishButtons() if (Global.mqtt_discovery_button_type == typeof(Switch)) { - log.Information("See {setting} for new option when publishing {type}", "mqtt_discovery_button_type", "buttons"); - PublishAsync($"{Global.mqtt_discovery_prefix}/button/{Global.mqtt_prefix}/button{i}/config", null); PublishAsync($"{Global.mqtt_discovery_prefix}/switch/{Global.mqtt_prefix}/button{i}/config", JsonConvert.SerializeObject(button.ToConfigSwitch())); diff --git a/OmniLinkBridge/Modules/OmniLinkII.cs b/OmniLinkBridge/Modules/OmniLinkII.cs index 62f4a38..6a9e463 100644 --- a/OmniLinkBridge/Modules/OmniLinkII.cs +++ b/OmniLinkBridge/Modules/OmniLinkII.cs @@ -201,6 +201,8 @@ private async Task ConnectedAsync() tstat_timer.Start(); OnConnect?.Invoke(this, new EventArgs()); + + Program.ShowSendLogsWarning(); } #endregion @@ -231,7 +233,8 @@ private async Task GetSystemFormats() await Task.Run(() => { - nameWait.WaitOne(new TimeSpan(0, 0, 10)); + if(!nameWait.WaitOne(new TimeSpan(0, 0, 10))) + log.Error("Timeout occurred waiting system formats"); }); } @@ -244,7 +247,8 @@ private async Task GetSystemTroubles() await Task.Run(() => { - nameWait.WaitOne(new TimeSpan(0, 0, 10)); + if(!nameWait.WaitOne(new TimeSpan(0, 0, 10))) + log.Error("Timeout occurred waiting for system troubles"); }); } @@ -256,7 +260,8 @@ private async Task GetNamed(enuObjectType type) await Task.Run(() => { - nameWait.WaitOne(new TimeSpan(0, 0, 10)); + if (!nameWait.WaitOne(new TimeSpan(0, 0, 30))) + log.Error("Timeout occurred waiting for named units {unitType}", type.ToString()); }); } diff --git a/OmniLinkBridge/Program.cs b/OmniLinkBridge/Program.cs index 75278ff..9f592d9 100644 --- a/OmniLinkBridge/Program.cs +++ b/OmniLinkBridge/Program.cs @@ -4,7 +4,9 @@ using Serilog.Filters; using Serilog.Formatting.Compact; using System; +using System.Diagnostics; using System.IO; +using System.Linq; using System.Net; using System.Reflection; using System.ServiceProcess; @@ -12,11 +14,11 @@ namespace OmniLinkBridge { - class Program + internal class Program { - static CoreServer server; + private static CoreServer server; - static int Main(string[] args) + private static int Main(string[] args) { bool interactive = false; @@ -55,6 +57,10 @@ static int Main(string[] args) case "-ll": Enum.TryParse(args[++i], out log_level); break; + case "-ld": + Global.DebugSettings = true; + Global.SendLogs = true; + break; case "-s": Global.webapi_subscriptions_file = args[++i]; break; @@ -64,6 +70,12 @@ static int Main(string[] args) } } + if (string.Compare(Environment.GetEnvironmentVariable("SEND_LOGS"), "1") == 0) + { + Global.DebugSettings = true; + Global.SendLogs = true; + } + config_file = GetFullPath(config_file); Global.webapi_subscriptions_file = GetFullPath(Global.webapi_subscriptions_file ?? "WebSubscriptions.json"); @@ -76,7 +88,7 @@ static int Main(string[] args) var log_config = new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.WithProperty("Application", "OmniLinkBridge") - .Enrich.WithProperty("Session", Guid.NewGuid()) + .Enrich.WithProperty("Session", Global.SessionID) .Enrich.With() .Enrich.FromLogContext(); @@ -92,7 +104,10 @@ static int Main(string[] args) rollingInterval: RollingInterval.Day, retainedFileCountLimit: 15)); } - if (UseTelemetry()) + if (Global.SendLogs) + log_config = log_config.WriteTo.Logger(lc => lc + .WriteTo.Http("https://telemetry.excalibur-partners.com")); + else if (UseTelemetry()) log_config = log_config.WriteTo.Logger(lc => lc .Filter.ByIncludingOnly(Matching.WithProperty("Telemetry")) .WriteTo.Http("https://telemetry.excalibur-partners.com")); @@ -155,7 +170,7 @@ static int Main(string[] args) return 0; } - static string GetFullPath(string file) + private static string GetFullPath(string file) { if (Path.IsPathRooted(file)) return file; @@ -169,21 +184,38 @@ protected static void myHandler(object sender, ConsoleCancelEventArgs args) args.Cancel = true; } - static bool IsRunningOnMono() + private static bool IsRunningOnMono() { return Type.GetType("Mono.Runtime") != null; } - static bool UseTelemetry() + 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() { return string.Compare(Environment.GetEnvironmentVariable("TELEMETRY_OPTOUT"), "1") != 0; } - static void ShowHelp() + 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() { Console.WriteLine( AppDomain.CurrentDomain.FriendlyName + " [-c config_file] [-e] [-d] [-j] [-s subscriptions_file]\n" + - "\t[-lf log_file|disable] [-lj [-ll verbose|debug|information|warning|error] [-i]\n" + + "\t[-lf log_file|disable] [-lj [-ll verbose|debug|information|warning|error] [-ld] [-i]\n" + "\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" + @@ -191,8 +223,14 @@ static void ShowHelp() "\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" + + "\t-ld Send logs to developer. ONLY USE WHEN ASKED.\n" + + "\t Also enabled by setting a SEND_LOGS environment variable to 1.\n" + "\t-i Run in interactive mode"); + Console.WriteLine( + "\nVersion: " + Assembly.GetExecutingAssembly().GetName().Version + + "\nEnvironment: " + GetEnvironment()); + 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."); diff --git a/OmniLinkBridge/Properties/AssemblyInfo.cs b/OmniLinkBridge/Properties/AssemblyInfo.cs index 7348a72..ae19c83 100644 --- a/OmniLinkBridge/Properties/AssemblyInfo.cs +++ b/OmniLinkBridge/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.1.17.0")] -[assembly: AssemblyFileVersion("1.1.17.0")] +[assembly: AssemblyVersion("1.1.18.0")] +[assembly: AssemblyFileVersion("1.1.18.0")] diff --git a/OmniLinkBridge/Settings.cs b/OmniLinkBridge/Settings.cs index 87197b7..c8c161f 100644 --- a/OmniLinkBridge/Settings.cs +++ b/OmniLinkBridge/Settings.cs @@ -59,7 +59,7 @@ public static void LoadSettings(NameValueCollection settings) // mySQL Logging Global.mysql_logging = settings.ValidateBool("mysql_logging"); - Global.mysql_connection = settings.CheckEnv("mysql_connection"); + Global.mysql_connection = settings.CheckEnv("mysql_connection", true); // Web Service Global.webapi_enabled = settings.ValidateBool("webapi_enabled"); @@ -77,8 +77,8 @@ public static void LoadSettings(NameValueCollection settings) { Global.mqtt_server = settings.CheckEnv("mqtt_server"); Global.mqtt_port = settings.ValidatePort("mqtt_port"); - Global.mqtt_username = settings.CheckEnv("mqtt_username"); - Global.mqtt_password = settings.CheckEnv("mqtt_password"); + Global.mqtt_username = settings.CheckEnv("mqtt_username", true); + Global.mqtt_password = settings.CheckEnv("mqtt_password", true); Global.mqtt_prefix = settings.CheckEnv("mqtt_prefix") ?? "omnilink"; Global.mqtt_discovery_prefix = settings.CheckEnv("mqtt_discovery_prefix") ?? "homeassistant"; Global.mqtt_discovery_name_prefix = settings.CheckEnv("mqtt_discovery_name_prefix") ?? string.Empty; @@ -107,27 +107,29 @@ public static void LoadSettings(NameValueCollection settings) { Global.mail_tls = settings.ValidateBool("mail_tls"); Global.mail_port = settings.ValidatePort("mail_port"); - Global.mail_username = settings.CheckEnv("mail_username"); - Global.mail_password = settings.CheckEnv("mail_password"); + Global.mail_username = settings.CheckEnv("mail_username", true); + Global.mail_password = settings.CheckEnv("mail_password", true); Global.mail_from = settings.ValidateMailFrom("mail_from"); Global.mail_to = settings.ValidateMailTo("mail_to"); } // Prowl Notifications - Global.prowl_key = settings.ValidateMultipleStrings("prowl_key"); + Global.prowl_key = settings.ValidateMultipleStrings("prowl_key", true); // Pushover Notifications - Global.pushover_token = settings.CheckEnv("pushover_token"); - Global.pushover_user = settings.ValidateMultipleStrings("pushover_user"); + Global.pushover_token = settings.CheckEnv("pushover_token", true); + Global.pushover_user = settings.ValidateMultipleStrings("pushover_user", true); } - private static string CheckEnv(this NameValueCollection settings, string name) + private static string CheckEnv(this NameValueCollection settings, string name, bool sensitive = false) { string env = Global.UseEnvironment ? Environment.GetEnvironmentVariable(name.ToUpper()) : null; string value = !string.IsNullOrEmpty(env) ? env : settings[name]; if (Global.DebugSettings) - log.Debug((!string.IsNullOrEmpty(env) ? "ENV" : "CONF").PadRight(5) + $"{name}: {value}"); + log.Debug("{ConfigType} {ConfigName}: {ConfigValue}", + (!string.IsNullOrEmpty(env) ? "ENV" : "CONF").PadRight(4), name, + sensitive && value != null ? value.Truncate(3) + "***MASKED***" : value); return value; } @@ -242,7 +244,7 @@ private static string ValidateHasValue(this NameValueCollection settings, string private static string ValidateEncryptionKey(this NameValueCollection settings, string section) { - string value = settings.CheckEnv(section).Replace("-",""); + string value = settings.CheckEnv(section, true).Replace("-",""); if (string.IsNullOrEmpty(value) || value.Length != 16) { @@ -339,14 +341,14 @@ private static MailAddress[] ValidateMailTo(this NameValueCollection settings, s } } - private static string[] ValidateMultipleStrings(this NameValueCollection settings, string section) + private static string[] ValidateMultipleStrings(this NameValueCollection settings, string section, bool sensitive = false) { try { - if (settings.CheckEnv(section) == null) + if (settings.CheckEnv(section, true) == null) return new string[] { }; - return settings.CheckEnv(section).Split(','); + return settings.CheckEnv(section, sensitive).Split(','); } catch { diff --git a/OmniLinkBridge/WebService/DeviceType.cs b/OmniLinkBridge/WebService/DeviceType.cs index 96074d9..3586f11 100644 --- a/OmniLinkBridge/WebService/DeviceType.cs +++ b/OmniLinkBridge/WebService/DeviceType.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace OmniLinkBridge.WebAPI +namespace OmniLinkBridge.WebAPI { public enum DeviceType { diff --git a/OmniLinkBridge/WebService/MappingExtensions.cs b/OmniLinkBridge/WebService/MappingExtensions.cs index 021cd79..f1ff952 100644 --- a/OmniLinkBridge/WebService/MappingExtensions.cs +++ b/OmniLinkBridge/WebService/MappingExtensions.cs @@ -1,9 +1,4 @@ using HAI_Shared; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace OmniLinkBridge.WebAPI { diff --git a/OmniLinkBridge/WebService/OmniLinkService.cs b/OmniLinkBridge/WebService/OmniLinkService.cs index 3dd1470..aa22c6f 100644 --- a/OmniLinkBridge/WebService/OmniLinkService.cs +++ b/OmniLinkBridge/WebService/OmniLinkService.cs @@ -1,5 +1,4 @@ using HAI_Shared; -using OmniLinkBridge.WebAPI; using Serilog; using System; using System.Collections.Generic; diff --git a/OmniLinkBridge/WebService/OverrideZone.cs b/OmniLinkBridge/WebService/OverrideZone.cs index b0c1e52..0e12c0f 100644 --- a/OmniLinkBridge/WebService/OverrideZone.cs +++ b/OmniLinkBridge/WebService/OverrideZone.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace OmniLinkBridge.WebAPI +namespace OmniLinkBridge.WebAPI { public class OverrideZone {