static Task <int> CleanAsync( StringLocalizer stringLocalizer, InvocationContext invocationContext, CancellationToken _) { var console = invocationContext.Console; var reporter = new NvmeSmartAttributesReporter(stringLocalizer); try { try { console.Out.Write(stringLocalizer["LOG_UNREGISTERING_PERFORMANCE_COUNTERS"]); reporter.DeleteCategory(); } finally { console.Out.Write(stringLocalizer["LOG_QUITTING"]); } } catch (Exception exception) { console.Error.Write($"{stringLocalizer["ERROR"]}: {exception}\n"); return(Task.FromResult(1)); } return(Task.FromResult(0)); }
static async Task <int> WatchAsync( StringLocalizer stringLocalizer, InvocationContext invocationContext, CancellationToken terminationToken, uint interval, bool plot, bool scan, byte scanRange, byte[] skip, bool hydra) { var console = new VirtualTerminal(invocationContext.Console, VirtualTerminalMode.TryEnable()); var reporter = new NvmeSmartAttributesReporter(stringLocalizer); var attributesProviderMap = new Dictionary <int, NvmeSmartAttributesProvider>(); try { try { if (!scan) { console.Out.Write(stringLocalizer["LOG_REGISTERING_PERFORMANCE_COUNTERS"]); reporter.CreateCategory(); } console.Out.Write(stringLocalizer["LOG_DETECTING_NVME_DRIVES"]); for (ushort driveNumber = 0; driveNumber < scanRange; ++driveNumber) { if (skip.Contains((byte)driveNumber)) { continue; } var attributesProvider = NvmeSmartAttributesProvider.Create((byte)driveNumber); if (attributesProvider == null) { continue; } if (attributesProvider.Query(out var _)) { attributesProviderMap.Add(driveNumber, attributesProvider); if (!scan) { reporter.AddInstance(attributesProvider.Moniker, attributesProvider.Model, attributesProvider.SerialNumber); } console.Out.Write($"\t{attributesProvider.Moniker.Replace("_", string.Empty)}: {attributesProvider.Model ?? stringLocalizer["NOT_AVAILABLE"]} (S/N: {attributesProvider.SerialNumber ?? stringLocalizer["NOT_AVAILABLE"]})\r\n"); } else { attributesProvider.Dispose(); } } if (attributesProviderMap.Count == 0) { console.Out.Write(stringLocalizer["LOG_CANNOT_DETECT_ANY_NVME_DRIVES"]); return(1); } if (scan) { return(0); } console.Out.Write(stringLocalizer["LOG_START_MONITORING"]); if (plot) { if (console is ITerminal terminal) { terminal.Clear(); terminal.SetCursorPosition(0, 0); terminal.HideCursor(); } var renderer = new ConsoleRenderer(console, invocationContext.BindingContext.OutputMode(), true); var table = new TableView <NvmeSmartAttributesReporterInstance>() { Items = reporter.Instances }; table.AddColumn(item => item.Moniker.Replace("_", string.Empty), new ContentView("#".Underline())); table.AddColumn(item => item.Model, new ContentView("Model".Underline())); table.AddColumn(item => item.SerialNumber, new ContentView("S/N".Underline())); table.AddColumn(item => ContentView.FromObservable(item.PercentageUsedEstimate, value => $"{value}%"), new ContentView("PUE".Underline())); table.AddColumn(item => ContentView.FromObservable(item.TemperatureDegCelsius, value => $"{value}°C"), new ContentView("CTemp".Underline())); table.AddColumn(item => ContentView.FromObservable(item.WarningCompositeTemperatureTime, value => $"{value} mins."), new ContentView("WCTemp".Underline())); table.AddColumn(item => ContentView.FromObservable(item.CriticalCompositeTemperatureTime, value => $"{value} mins."), new ContentView("CCTemp".Underline())); table.AddColumn(item => ContentView.FromObservable(item.HostReadCommands), new ContentView("HRC".Underline())); table.AddColumn(item => ContentView.FromObservable(item.HostWriteCommands), new ContentView("HWC".Underline())); table.AddColumn(item => ContentView.FromObservable(item.DataUnitsRead), new ContentView("DUR".Underline())); table.AddColumn(item => ContentView.FromObservable(item.DataUnitsWrite), new ContentView("DUW".Underline())); table.AddColumn(item => ContentView.FromObservable(item.MediaErrors), new ContentView("ME".Underline())); table.AddColumn(item => ContentView.FromObservable(item.NumberOfErrorInformationLogEntries), new ContentView("EE".Underline())); var screen = new ScreenView(renderer, console) { Child = table }; var region = new Region(0, 0, Console.WindowWidth, Console.WindowHeight, true); screen.Render(region); } while (!terminationToken.IsCancellationRequested) { foreach (var driveNumber in attributesProviderMap.Keys) { var attributesProvider = attributesProviderMap[driveNumber]; if (!attributesProvider.Query(out var attributes)) { console.Error.Write($"\t{attributesProvider.Moniker}: {stringLocalizer["LOG_FAILED_TO_QUERY_SMART"]}\n"); continue; } reporter.Next(attributesProvider.Moniker, attributes); } await Task.Delay((int)interval, terminationToken); } } finally { if (plot) { if (console is ITerminal terminal) { terminal.Clear(); terminal.SetCursorPosition(0, 0); terminal.ShowCursor(); } } console.Out.Write(stringLocalizer["LOG_QUITTING"]); if (!hydra) { reporter.DeleteCategory(); } reporter.Dispose(); foreach (var attributesProvider in attributesProviderMap.Values) { attributesProvider.Dispose(); } } } catch (TaskCanceledException) { } return(0); }