diff --git a/ccMonitor.sln b/ccMonitor.sln index 995995e..a31d9e4 100644 --- a/ccMonitor.sln +++ b/ccMonitor.sln @@ -1,10 +1,15 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +VisualStudioVersion = 12.0.21005.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ccMonitor", "ccMonitor\ccMonitor.csproj", "{35A80F48-FF06-40FC-B048-DBBD911C2FA9}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{57664A89-6876-4345-A9D9-1FD64A128E49}" + ProjectSection(SolutionItems) = preProject + Performance1.psess = Performance1.psess + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -19,4 +24,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection EndGlobal diff --git a/ccMonitor/Api/PruvotApi.cs b/ccMonitor/Api/PruvotApi.cs index dc89778..94c5427 100644 --- a/ccMonitor/Api/PruvotApi.cs +++ b/ccMonitor/Api/PruvotApi.cs @@ -44,6 +44,7 @@ public static T GetDictValue(Dictionary dictionary, string ke return (T) Convert.ChangeType(value, typeof (T), CultureInfo.InvariantCulture); } + // Unsigneds can't be negative if (typeof(T) == typeof(uint)) return (T)Convert.ChangeType(9001, typeof(T), CultureInfo.InvariantCulture); return (T) Convert.ChangeType(-1, typeof (T), CultureInfo.InvariantCulture); } @@ -83,7 +84,23 @@ public static string GetDictValue(Dictionary dictionary, string public static Dictionary[] GetHistory(string ip = "127.0.0.1", int port = 4068, int minerMap = -1) { - return minerMap == -1 ? Request(ip, port, "histo") : Request(ip, port, "histo|" + minerMap); + Dictionary[] histo = Request(ip, port, "histo"); + + if (histo == null) return null; + + bool existsInHisto = false; + foreach (Dictionary log in histo) + { + if (GetDictValue(log, "GPU") == minerMap) + { + existsInHisto = true; + break; + } + } + + if(existsInHisto) return minerMap == -1 ? histo : Request(ip, port, "histo|" + minerMap); + + return null; } public static Dictionary[] GetPoolInfo(string ip = "127.0.0.1", int port = 4068) diff --git a/ccMonitor/GpuLogger.cs b/ccMonitor/GpuLogger.cs index 6680a2c..821c5f0 100644 --- a/ccMonitor/GpuLogger.cs +++ b/ccMonitor/GpuLogger.cs @@ -18,8 +18,34 @@ public class GpuInfo public int MinerMap { get; set; } public uint ComputeCapability { get; set; } - - public bool Available { get; set; } + + private bool _available; + public List> AvailableTimeStamps { get; set; } + // long: unix timestamp, bool: availability + public bool Available + { + get { return _available; } + set + { + long unixTimeStamp = UnixTimeStamp(); + if (AvailableTimeStamps == null) + { + AvailableTimeStamps = new List>() + { + new Tuple(unixTimeStamp, value) + }; + } + else + { + Tuple prevAvailableTimeStamp = AvailableTimeStamps[AvailableTimeStamps.Count - 1]; + if (prevAvailableTimeStamp.Item1 != unixTimeStamp && prevAvailableTimeStamp.Item2 != value) + { + AvailableTimeStamps.Add(new Tuple(unixTimeStamp, value)); + } + } + _available = value; + } + } public override string ToString() { diff --git a/ccMonitor/Gui/BenchmarkDetails.cs b/ccMonitor/Gui/BenchmarkDetails.cs index ad04cfe..6b3bc69 100644 --- a/ccMonitor/Gui/BenchmarkDetails.cs +++ b/ccMonitor/Gui/BenchmarkDetails.cs @@ -1,5 +1,6 @@ using System; using System.Globalization; +using System.IO; using System.Windows.Forms; namespace ccMonitor.Gui @@ -12,10 +13,12 @@ public partial class BenchmarkDetails : UserControl public BenchmarkDetails(GpuLogger.GpuInfo gpuInfo ,int rowsInLogViews = 5) { + GpuInfo = gpuInfo; _rowsInLogViews = rowsInLogViews; InitializeComponent(); InitHashesAndSensors(); + } private void InitHashesAndSensors() @@ -26,6 +29,7 @@ private void InitHashesAndSensors() public void UpdateStats(GpuLogger.Benchmark benchmark) { + if (benchmark == null) return; UpdateSpread(benchmark.Statistic); UpdateLogs(benchmark); UpdateTextBoxes(benchmark); diff --git a/ccMonitor/Gui/BenchmarkOverview.cs b/ccMonitor/Gui/BenchmarkOverview.cs index e6a6fd2..0077e94 100644 --- a/ccMonitor/Gui/BenchmarkOverview.cs +++ b/ccMonitor/Gui/BenchmarkOverview.cs @@ -18,7 +18,7 @@ public BenchmarkOverview(GpuLogger.Benchmark benchmark, GpuLogger.GpuInfo gpuInf tabHashCharts.Controls.Add(hashChart); SensorChart sensorChart = new SensorChart(9001) {Dock = DockStyle.Fill}; - sensorChart.UpdateCharts(benchmark.SensorLog, benchmark.MinerSetup.OperatingSystem); + sensorChart.UpdateCharts(benchmark.SensorLog, gpuInfo.AvailableTimeStamps, benchmark.MinerSetup.OperatingSystem); tabSensorCharts.Controls.Add(sensorChart); } diff --git a/ccMonitor/Gui/GpuTab.cs b/ccMonitor/Gui/GpuTab.cs index 458fd4d..6929d1e 100644 --- a/ccMonitor/Gui/GpuTab.cs +++ b/ccMonitor/Gui/GpuTab.cs @@ -48,31 +48,34 @@ private void InitGpuDetails() public void UpdateGui() { - UpdateInternalControls(); - - UserFriendlyBenchmarks = new List(Gpu.BenchLogs.Count); - foreach (GpuLogger.Benchmark benchmark in Gpu.BenchLogs) + if (Gpu.CurrentBenchmark != null && Gpu.BenchLogs != null && Gpu.BenchLogs.Count > 0) { - UserFriendlyBenchmark userFriendlyBenchmark = new UserFriendlyBenchmark + UpdateInternalControls(); + + UserFriendlyBenchmarks = new List(Gpu.BenchLogs.Count); + foreach (GpuLogger.Benchmark benchmark in Gpu.BenchLogs) { - TimeStarted = GuiHelper.UnixTimeStampToDateTime(benchmark.TimeStamp).ToString("g"), - TimeLastUpdate = GuiHelper.UnixTimeStampToDateTime(benchmark.SensorLog - [benchmark.SensorLog.Count - 1].TimeStamp).ToString("g"), - Algorithm = benchmark.Algorithm, - AverageHashRate = GuiHelper.GetRightMagnitude(benchmark.Statistic.AverageHashRate, "H"), - StandardDeviation = GuiHelper.GetRightMagnitude(benchmark.Statistic.StandardDeviation, "H"), - HashCount = GuiHelper.GetRightMagnitude(benchmark.Statistic.TotalHashCount), - AverageTemperature = benchmark.Statistic.AverageTemperature.ToString("##.##") + " °C", - MinerNameVersion = benchmark.MinerSetup.ToString(), - Stratum = benchmark.MinerSetup.MiningUrl - }; + UserFriendlyBenchmark userFriendlyBenchmark = new UserFriendlyBenchmark + { + TimeStarted = GuiHelper.UnixTimeStampToDateTime(benchmark.TimeStamp).ToString("g"), + TimeLastUpdate = GuiHelper.UnixTimeStampToDateTime(benchmark.SensorLog + [benchmark.SensorLog.Count - 1].TimeStamp).ToString("g"), + Algorithm = benchmark.Algorithm, + AverageHashRate = GuiHelper.GetRightMagnitude(benchmark.Statistic.AverageHashRate, "H"), + StandardDeviation = GuiHelper.GetRightMagnitude(benchmark.Statistic.StandardDeviation, "H"), + HashCount = GuiHelper.GetRightMagnitude(benchmark.Statistic.TotalHashCount), + AverageTemperature = benchmark.Statistic.AverageTemperature.ToString("##.##") + " °C", + MinerNameVersion = benchmark.MinerSetup.ToString(), + Stratum = benchmark.MinerSetup.MiningUrl + }; - UserFriendlyBenchmarks.Insert(0, userFriendlyBenchmark); - } + UserFriendlyBenchmarks.Insert(0, userFriendlyBenchmark); + } - int rowIndex = dgvBenchmarks.SelectedRows.Count > 0 ? dgvBenchmarks.SelectedRows[0].Index : 0; - dgvBenchmarks.DataSource = UserFriendlyBenchmarks; - if(dgvBenchmarks.Rows.Count > 0) dgvBenchmarks.CurrentCell = dgvBenchmarks.Rows[rowIndex].Cells[0]; + int rowIndex = dgvBenchmarks.SelectedRows.Count > 0 ? dgvBenchmarks.SelectedRows[0].Index : 0; + dgvBenchmarks.DataSource = new SortableBindingList(UserFriendlyBenchmarks); + if (dgvBenchmarks.Rows.Count > 0) dgvBenchmarks.CurrentCell = dgvBenchmarks.Rows[rowIndex].Cells[0]; + } } private void UpdateInternalControls() @@ -94,10 +97,11 @@ private void UpdateInternalControls() foreach (object control in tabSensorCharts.Controls) { - SensorChart hashChart = control as SensorChart; - if (hashChart != null) + SensorChart sensorChartChart = control as SensorChart; + if (sensorChartChart != null) { - hashChart.UpdateCharts(Gpu.CurrentBenchmark.SensorLog, Gpu.CurrentBenchmark.MinerSetup.OperatingSystem); + sensorChartChart.UpdateCharts(Gpu.CurrentBenchmark.SensorLog, + Gpu.Info.AvailableTimeStamps, Gpu.CurrentBenchmark.MinerSetup.OperatingSystem); } } } @@ -106,7 +110,6 @@ private void dgvBenchmarks_CellMouseDoubleClick(object sender, DataGridViewCellM { int rowIndex = e.RowIndex; if(rowIndex<0) return; - BenchmarkOverview form = new BenchmarkOverview(Gpu.BenchLogs[Gpu.BenchLogs.Count - rowIndex - 1], Gpu.Info) { diff --git a/ccMonitor/Gui/GuiHelper.cs b/ccMonitor/Gui/GuiHelper.cs index cff81bd..ec43beb 100644 --- a/ccMonitor/Gui/GuiHelper.cs +++ b/ccMonitor/Gui/GuiHelper.cs @@ -1,6 +1,4 @@ using System; -using System.Runtime.InteropServices; -using System.Windows.Forms; namespace ccMonitor.Gui { @@ -31,7 +29,7 @@ public static long GetCurrentUnixTimeStamp() return (long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; } - [DllImport("user32.dll")] + /*[DllImport("user32.dll")] private static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam); private const int WmSetredraw = 11; @@ -46,5 +44,14 @@ public static void ResumeDrawing(Control parent) SendMessage(parent.Handle, WmSetredraw, true, 0); parent.Refresh(); } + + public static void ApplyAll(Control control, Action action) + { + action(control); + foreach (Control child in control.Controls) + { + ApplyAll(child, action); + } + }*/ } } diff --git a/ccMonitor/Gui/HashChart.Designer.cs b/ccMonitor/Gui/HashChart.Designer.cs index 689bb1b..d5564ec 100644 --- a/ccMonitor/Gui/HashChart.Designer.cs +++ b/ccMonitor/Gui/HashChart.Designer.cs @@ -125,7 +125,7 @@ private void InitializeComponent() this.chartHash.Name = "chartHash"; series1.ChartArea = "ChartAreaFoundHashrate"; series1.Color = System.Drawing.Color.Goldenrod; - series1.CustomProperties = "EmptyPointValue=Zero, PointWidth=0.5"; + series1.CustomProperties = "EmptyPointValue=Zero, PointWidth=1"; series1.Legend = "LegendFoundHashrate"; series1.LegendText = "Found"; series1.Name = "FoundSeries"; @@ -137,7 +137,7 @@ private void InitializeComponent() series2.ChartArea = "ChartAreaFoundHashrate"; series2.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine; series2.Color = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(192)))), ((int)(((byte)(0))))); - series2.CustomProperties = "IsXAxisQuantitative=False, LineTension=0.1"; + series2.CustomProperties = "IsXAxisQuantitative=True"; series2.Legend = "LegendFoundHashrate"; series2.LegendText = "Hashrate"; series2.Name = "HashrateSeries"; @@ -146,6 +146,7 @@ private void InitializeComponent() series2.YValueMembers = "HashRate"; series3.ChartArea = "ChartAreaDifficultyHashcount"; series3.Color = System.Drawing.Color.Navy; + series3.CustomProperties = "EmptyPointValue=Zero, PointWidth=1"; series3.Legend = "LegendDifficultyHashcount"; series3.LegendText = "Hash count"; series3.Name = "HashcountSeries"; diff --git a/ccMonitor/Gui/HashChart.cs b/ccMonitor/Gui/HashChart.cs index b1baacf..557e67e 100644 --- a/ccMonitor/Gui/HashChart.cs +++ b/ccMonitor/Gui/HashChart.cs @@ -43,6 +43,38 @@ public void UpdateCharts(HashSet hashLogs) chartHash.DataSource = chartFriendlyHashEntries; chartHash.DataBind(); + + AutoFormatXAxis(chartFriendlyHashEntries); + } + + private void AutoFormatXAxis(List chartHashEntries) + { + int hours = _hours; + if (hours > 9000) + { + hours = (int)Math.Round((chartHashEntries[chartHashEntries.Count - 1].TimeStamp - + chartHashEntries[0].TimeStamp).TotalHours, MidpointRounding.AwayFromZero); + } + + foreach (ChartArea chartArea in chartHash.ChartAreas) + { + if (hours < 6) + { + chartArea.AxisX.LabelStyle.Format = "ddd HH:mm:ss"; + } + else if (hours < 320) + { + chartArea.AxisX.LabelStyle.Format = "MMM dd HH:mm"; + } + else if (hours < 4600) + { + chartArea.AxisX.LabelStyle.Format = "MMM dd YY HH"; + } + else + { + chartArea.AxisX.LabelStyle.Format = "MMM dd YYYY"; + } + } } private void chart_MouseWheel(object sender, MouseEventArgs e) diff --git a/ccMonitor/Gui/HashLogView.cs b/ccMonitor/Gui/HashLogView.cs index f0c67ca..33d1647 100644 --- a/ccMonitor/Gui/HashLogView.cs +++ b/ccMonitor/Gui/HashLogView.cs @@ -55,7 +55,7 @@ public void UpdateLogs(HashSet hashLogs) userFriendlyHashEntries.Add(userFriendlyHashEntry); } - dgvHashLogs.DataSource = userFriendlyHashEntries; + dgvHashLogs.DataSource = new SortableBindingList(userFriendlyHashEntries); } } } diff --git a/ccMonitor/Gui/Monitor.cs b/ccMonitor/Gui/Monitor.cs index 6f1bd0b..d6cfea8 100644 --- a/ccMonitor/Gui/Monitor.cs +++ b/ccMonitor/Gui/Monitor.cs @@ -21,6 +21,7 @@ public partial class Monitor : Form public Monitor() { + InitializeComponent(); LoadSettings(); @@ -43,6 +44,7 @@ private void InitTimers() _guiTimer = new System.Windows.Forms.Timer {Interval = 5000}; _guiTimer.Tick += GuiTimerTick; _guiTimer.Start(); + UpdateGui(); } @@ -87,7 +89,7 @@ private void UpdateGui() lstGeneralOverview.BeginUpdate(); // Grabs all the selected items in the General Overview List int[] selectedIndexes = new int[lstGeneralOverview.SelectedIndices.Count]; - if (selectedIndexes.Length > 0) + if (lstGeneralOverview.SelectedIndices.Count > 0) { for (int i = 0; i < selectedIndexes.Length; i++) { @@ -101,6 +103,7 @@ private void UpdateGui() foreach (RigController.RigInfo rig in _controller.RigLogs) { + // Makes sure all rigs that are in the logs are shown in RigStats // And updates them bool tabPageExists = false; @@ -129,6 +132,7 @@ private void UpdateGui() tbcMonitor.TabPages.Add(tabPage); } + // Adds the controller info to the listview ListViewGroup lvg = new ListViewGroup(rig.UserFriendlyName); lstGeneralOverview.Groups.Add(lvg); @@ -137,29 +141,57 @@ private void UpdateGui() foreach (GpuLogger gpu in rig.GpuLogs) { lvi = new ListViewItem(gpu.Info.MinerMap.ToString(CultureInfo.InvariantCulture), lvg); + if(gpu.Info.Available == false) lvi.BackColor = Color.DarkOrange; lvi.SubItems.Add(gpu.Info.Name); lvi.SubItems.Add(string.Empty); - lvi.SubItems.Add(GuiHelper.GetRightMagnitude(gpu.CurrentBenchmark.Statistic.AverageHashRate, "H")); - lvi.SubItems.Add(GuiHelper.GetRightMagnitude(gpu.CurrentBenchmark.Statistic.StandardDeviation, "H")); - lvi.SubItems.Add(GuiHelper.GetRightMagnitude(gpu.CurrentBenchmark.Statistic.TotalHashCount)); - lvi.SubItems.Add(gpu.CurrentBenchmark.Statistic.Accepts.ToString(CultureInfo.InvariantCulture)); - lvi.SubItems.Add(string.Empty); - lvi.SubItems.Add(gpu.CurrentBenchmark.SensorLog[gpu.CurrentBenchmark.SensorLog.Count -1] - .Temperature.ToString(CultureInfo.InvariantCulture) + " °C"); + if (gpu.CurrentBenchmark == null) + { + lvi.SubItems.Add(string.Empty); + lvi.SubItems.Add(string.Empty); + lvi.SubItems.Add(string.Empty); + lvi.SubItems.Add(string.Empty); + lvi.SubItems.Add(string.Empty); + lvi.SubItems.Add(string.Empty); + } + else + { + lvi.SubItems.Add(GuiHelper.GetRightMagnitude(gpu.CurrentBenchmark.Statistic.AverageHashRate, "H")); + lvi.SubItems.Add(GuiHelper.GetRightMagnitude(gpu.CurrentBenchmark.Statistic.StandardDeviation, "H")); + lvi.SubItems.Add(GuiHelper.GetRightMagnitude(gpu.CurrentBenchmark.Statistic.TotalHashCount)); + lvi.SubItems.Add(gpu.CurrentBenchmark.Statistic.Accepts.ToString(CultureInfo.InvariantCulture)); + lvi.SubItems.Add(string.Empty); + lvi.SubItems.Add(gpu.CurrentBenchmark.SensorLog[gpu.CurrentBenchmark.SensorLog.Count - 1] + .Temperature.ToString(CultureInfo.InvariantCulture) + " °C"); + } lvi.SubItems.Add(string.Empty); lstGeneralOverview.Items.Add(lvi); } lvi = new ListViewItem(string.Empty, lvg); lvi.SubItems.Add("Total"); - lvi.SubItems.Add(rig.CurrentStatistic.Algorithm); - lvi.SubItems.Add(GuiHelper.GetRightMagnitude(rig.CurrentStatistic.TotalHashRate, "H")); - lvi.SubItems.Add(GuiHelper.GetRightMagnitude(rig.CurrentStatistic.AverageStandardDeviation, "H")); - lvi.SubItems.Add(GuiHelper.GetRightMagnitude(rig.CurrentStatistic.TotalHashCount)); - lvi.SubItems.Add(rig.CurrentStatistic.Accepts.ToString(CultureInfo.InvariantCulture)); - lvi.SubItems.Add(rig.CurrentStatistic.Rejects.ToString(CultureInfo.InvariantCulture)); - lvi.SubItems.Add(string.Empty); - lvi.SubItems.Add(rig.CurrentStatistic.ShareAnswerPing.ToString(CultureInfo.InvariantCulture)); + if (rig.CurrentStatistic == null) + { + lvi.SubItems.Add(string.Empty); + lvi.SubItems.Add(string.Empty); + lvi.SubItems.Add(string.Empty); + lvi.SubItems.Add(string.Empty); + lvi.SubItems.Add(string.Empty); + lvi.SubItems.Add(string.Empty); + lvi.SubItems.Add(string.Empty); + lvi.SubItems.Add(string.Empty); + } + else + { + lvi.SubItems.Add(rig.CurrentStatistic.Algorithm); + lvi.SubItems.Add(GuiHelper.GetRightMagnitude(rig.CurrentStatistic.TotalHashRate, "H")); + lvi.SubItems.Add(GuiHelper.GetRightMagnitude(rig.CurrentStatistic.AverageStandardDeviation, "H")); + lvi.SubItems.Add(GuiHelper.GetRightMagnitude(rig.CurrentStatistic.TotalHashCount)); + lvi.SubItems.Add(rig.CurrentStatistic.Accepts.ToString(CultureInfo.InvariantCulture)); + lvi.SubItems.Add(rig.CurrentStatistic.Rejects.ToString(CultureInfo.InvariantCulture)); + lvi.SubItems.Add(string.Empty); + lvi.SubItems.Add(rig.CurrentStatistic.ShareAnswerPing.ToString(CultureInfo.InvariantCulture)); + } + lstGeneralOverview.Items.Add(lvi); } @@ -196,6 +228,13 @@ private void LoadLogs() private void Monitor_FormClosing(object sender, FormClosingEventArgs e) { + foreach (RigController.RigInfo rig in _controller.RigLogs) + { + foreach (GpuLogger gpu in rig.GpuLogs) + { + gpu.Info.Available = false; + } + } SaveLogs(); SaveSettings(); } diff --git a/ccMonitor/Gui/RigTab.cs b/ccMonitor/Gui/RigTab.cs index ffee957..4ab3007 100644 --- a/ccMonitor/Gui/RigTab.cs +++ b/ccMonitor/Gui/RigTab.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using System.Windows.Forms; using ccMonitor.Api; @@ -13,7 +12,7 @@ public partial class RigTab : UserControl { private RigController.RigInfo Rig { get; set; } - private List _apiCommands; + private readonly List _apiCommands; private int _apiCommandsIndex; private string _stringBeforeUpOrDown; @@ -47,9 +46,9 @@ public void UpdateGui() if (!found) { TabPage tabPage = new TabPage(gpu.Info.ToString()); - GpuTab gpuGpuTab = new GpuTab(gpu) { Dock = DockStyle.Fill }; - gpuGpuTab.UpdateGui(); - tabPage.Controls.Add(gpuGpuTab); + GpuTab gpuTab = new GpuTab(gpu) { Dock = DockStyle.Fill }; + gpuTab.UpdateGui(); + tabPage.Controls.Add(gpuTab); tbcRig.TabPages.Add(tabPage); } } @@ -85,26 +84,55 @@ public void UpdateGui() private void txtApiConsole_KeyDown(object sender, KeyEventArgs e) { + // Always go to the end of the textbox, never type in the middle + txtApiConsole.SelectionStart = txtApiConsole.TextLength; + txtApiConsole.ScrollToCaret(); + + // Never remove the last > + if (e.KeyCode == Keys.Back) + { + if (txtApiConsole.Text[txtApiConsole.TextLength - 1] == '>') + { + e.SuppressKeyPress = true; + } + } + if (e.KeyCode == Keys.Enter) { string[] splitStrings = txtApiConsole.Text.Split('>'); string trimmed = splitStrings[splitStrings.Length - 1].Trim(); - _apiCommands.Insert(0, trimmed); + // Only the last line starting with a > is needed - Dictionary[] request = PruvotApi.Request(Rig.IpAddress, Rig.Port, trimmed); - if (request != null) + // Avoid sending empty requests + if (trimmed != string.Empty) { - txtApiConsole.AppendText(Environment.NewLine + JsonConvert.SerializeObject(request, Formatting.Indented) - + Environment.NewLine + " > "); - e.SuppressKeyPress = true; - _apiCommandsIndex = 0; + _apiCommands.Insert(0, trimmed); + + Dictionary[] request = PruvotApi.Request(Rig.IpAddress, Rig.Port, trimmed); + if (request != null) + { + txtApiConsole.AppendText(Environment.NewLine + + JsonConvert.SerializeObject(request, Formatting.Indented) + + Environment.NewLine + " > "); + _apiCommandsIndex = 0; + } } + else + { + txtApiConsole.AppendText(Environment.NewLine + " > "); + } + + e.SuppressKeyPress = true; } if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down) { - if (_stringBeforeUpOrDown == string.Empty) + if (string.IsNullOrEmpty(_stringBeforeUpOrDown)) + { _stringBeforeUpOrDown = txtApiConsole.Lines[txtApiConsole.Lines.Length - 1]; + // Keep the current string in memory when browsing through history of commands + } + StringBuilder sb = new StringBuilder(txtApiConsole.TextLength); for (int index = 0; index < txtApiConsole.Lines.Length - 1; index++) { @@ -125,7 +153,8 @@ private void txtApiConsole_KeyDown(object sender, KeyEventArgs e) else { _apiCommandsIndex -= 2; - if (_apiCommandsIndex < 0) + // -2 seems to give the most normal behavior + if ( _apiCommandsIndex < 0) { _apiCommandsIndex = -1; sb.AppendLine(_stringBeforeUpOrDown); @@ -137,8 +166,6 @@ private void txtApiConsole_KeyDown(object sender, KeyEventArgs e) } _apiCommandsIndex++; - - } else { diff --git a/ccMonitor/Gui/SensorChart.Designer.cs b/ccMonitor/Gui/SensorChart.Designer.cs index de900db..55d7000 100644 --- a/ccMonitor/Gui/SensorChart.Designer.cs +++ b/ccMonitor/Gui/SensorChart.Designer.cs @@ -39,6 +39,8 @@ private void InitializeComponent() System.Windows.Forms.DataVisualization.Charting.Series series5 = new System.Windows.Forms.DataVisualization.Charting.Series(); System.Windows.Forms.DataVisualization.Charting.Series series6 = new System.Windows.Forms.DataVisualization.Charting.Series(); System.Windows.Forms.DataVisualization.Charting.Series series7 = new System.Windows.Forms.DataVisualization.Charting.Series(); + System.Windows.Forms.DataVisualization.Charting.Series series8 = new System.Windows.Forms.DataVisualization.Charting.Series(); + System.Windows.Forms.DataVisualization.Charting.Series series9 = new System.Windows.Forms.DataVisualization.Charting.Series(); this.chartSensor = new System.Windows.Forms.DataVisualization.Charting.Chart(); ((System.ComponentModel.ISupportInitialize)(this.chartSensor)).BeginInit(); this.SuspendLayout(); @@ -48,7 +50,7 @@ private void InitializeComponent() chartArea1.AxisX.IntervalAutoMode = System.Windows.Forms.DataVisualization.Charting.IntervalAutoMode.VariableCount; chartArea1.AxisX.IsMarginVisible = false; chartArea1.AxisX.IsStartedFromZero = false; - chartArea1.AxisX.LabelStyle.Format = "g"; + chartArea1.AxisX.LabelStyle.Format = "MMM dd HH:mm:ss"; chartArea1.AxisX.ScaleView.MinSizeType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Minutes; chartArea1.AxisX.ScaleView.SmallScrollMinSizeType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Minutes; chartArea1.AxisX.ScaleView.SmallScrollSize = 1D; @@ -96,7 +98,7 @@ private void InitializeComponent() chartArea2.CursorX.IsUserEnabled = true; chartArea2.CursorX.IsUserSelectionEnabled = true; chartArea2.IsSameFontSizeForAllAxes = true; - chartArea2.Name = "ChartAreaCoreclockMemoryclock"; + chartArea2.Name = "ChartAreaPingFrequency"; chartArea2.Position.Auto = false; chartArea2.Position.Height = 39.55485F; chartArea2.Position.Width = 100F; @@ -114,7 +116,7 @@ private void InitializeComponent() legend2.Alignment = System.Drawing.StringAlignment.Far; legend2.BorderColor = System.Drawing.Color.Transparent; legend2.BorderDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.NotSet; - legend2.DockedToChartArea = "ChartAreaCoreclockMemoryclock"; + legend2.DockedToChartArea = "ChartAreaPingFrequency"; legend2.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top; legend2.IsDockedInsideChartArea = false; legend2.LegendItemOrder = System.Windows.Forms.DataVisualization.Charting.LegendItemOrder.SameAsSeriesOrder; @@ -124,83 +126,90 @@ private void InitializeComponent() this.chartSensor.Location = new System.Drawing.Point(0, 0); this.chartSensor.Margin = new System.Windows.Forms.Padding(0); this.chartSensor.Name = "chartSensor"; - series1.BorderWidth = 2; series1.ChartArea = "ChartAreaTemperatureFan"; - series1.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine; - series1.Color = System.Drawing.SystemColors.MenuHighlight; - series1.CustomProperties = "EmptyPointValue=Zero, PointWidth=0.5"; - series1.Legend = "LegendTemperatureFan"; - series1.LegendText = "Fan"; - series1.Name = "FanSeries"; - series1.XValueMember = "TimeStamp"; + series1.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Area; + series1.IsVisibleInLegend = false; + series1.Legend = "LegendCoreclockMemoryclock"; + series1.Name = "AvailabilityTemperatureSeries"; series1.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.DateTime; - series1.YAxisType = System.Windows.Forms.DataVisualization.Charting.AxisType.Secondary; - series1.YValueMembers = "Fan"; series2.BorderWidth = 2; series2.ChartArea = "ChartAreaTemperatureFan"; series2.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine; - series2.Color = System.Drawing.Color.Red; - series2.CustomProperties = "IsXAxisQuantitative=False, LineTension=0.1"; + series2.Color = System.Drawing.SystemColors.MenuHighlight; series2.Legend = "LegendTemperatureFan"; - series2.LegendText = "Temperature"; - series2.Name = "TemperatureSeries"; + series2.LegendText = "Fan"; + series2.Name = "FanSeries"; series2.XValueMember = "TimeStamp"; series2.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.DateTime; - series2.YValueMembers = "Temperature"; - series3.BorderWidth = 2; - series3.ChartArea = "ChartAreaCoreclockMemoryclock"; + series2.YAxisType = System.Windows.Forms.DataVisualization.Charting.AxisType.Secondary; + series2.YValueMembers = "Fan"; + series3.ChartArea = "ChartAreaTemperatureFan"; series3.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine; - series3.Color = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(192)))), ((int)(((byte)(0))))); - series3.CustomProperties = "DrawSideBySide=True"; - series3.Legend = "LegendCoreclockMemoryclock"; - series3.LegendText = "Core frequency"; - series3.Name = "CoreclockSeries"; + series3.Color = System.Drawing.Color.Red; + series3.Legend = "LegendTemperatureFan"; + series3.LegendText = "Temperature"; + series3.Name = "TemperatureSeries"; series3.XValueMember = "TimeStamp"; series3.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.DateTime; - series3.YAxisType = System.Windows.Forms.DataVisualization.Charting.AxisType.Secondary; - series3.YValueMembers = "CoreClockFrequency"; - series4.BorderWidth = 2; - series4.ChartArea = "ChartAreaCoreclockMemoryclock"; - series4.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine; - series4.Color = System.Drawing.Color.SaddleBrown; - series4.CustomProperties = "DrawSideBySide=True"; - series4.Legend = "LegendCoreclockMemoryclock"; - series4.LegendText = "Memory frequency"; - series4.Name = "MemoryclockSeries"; - series4.XValueMember = "TimeStamp"; + series3.YValueMembers = "Temperature"; + series4.ChartArea = "ChartAreaPingFrequency"; + series4.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Area; + series4.IsVisibleInLegend = false; + series4.Legend = "LegendTemperatureFan"; + series4.Name = "AvailabilityPingSeries"; series4.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.DateTime; - series4.YAxisType = System.Windows.Forms.DataVisualization.Charting.AxisType.Secondary; - series4.YValueMembers = "MemoryClockFrequency"; series5.BorderWidth = 2; - series5.ChartArea = "ChartAreaCoreclockMemoryclock"; + series5.ChartArea = "ChartAreaPingFrequency"; series5.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine; - series5.Color = System.Drawing.Color.Fuchsia; + series5.Color = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(192)))), ((int)(((byte)(0))))); series5.Legend = "LegendCoreclockMemoryclock"; - series5.LegendText = "Ping: This to miner"; - series5.Name = "NetworkpingSeries"; + series5.LegendText = "Core frequency"; + series5.Name = "CoreclockSeries"; series5.XValueMember = "TimeStamp"; series5.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.DateTime; - series5.YValueMembers = "NetworkRigPing"; + series5.YAxisType = System.Windows.Forms.DataVisualization.Charting.AxisType.Secondary; + series5.YValueMembers = "CoreClockFrequency"; series6.BorderWidth = 2; - series6.ChartArea = "ChartAreaCoreclockMemoryclock"; + series6.ChartArea = "ChartAreaPingFrequency"; series6.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine; - series6.Color = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(128)))), ((int)(((byte)(0))))); + series6.Color = System.Drawing.Color.SaddleBrown; series6.Legend = "LegendCoreclockMemoryclock"; - series6.LegendText = "Ping: This to URL"; - series6.Name = "MiningpingSeries"; + series6.LegendText = "Memory frequency"; + series6.Name = "MemoryclockSeries"; series6.XValueMember = "TimeStamp"; series6.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.DateTime; - series6.YValueMembers = "MiningUrlPing"; + series6.YAxisType = System.Windows.Forms.DataVisualization.Charting.AxisType.Secondary; + series6.YValueMembers = "MemoryClockFrequency"; series7.BorderWidth = 2; - series7.ChartArea = "ChartAreaCoreclockMemoryclock"; + series7.ChartArea = "ChartAreaPingFrequency"; series7.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine; - series7.Color = System.Drawing.Color.Indigo; + series7.Color = System.Drawing.Color.Fuchsia; series7.Legend = "LegendCoreclockMemoryclock"; - series7.LegendText = "Ping: Miner to URL"; - series7.Name = "SharepingSeries"; + series7.LegendText = "Ping: This to miner"; + series7.Name = "NetworkpingSeries"; series7.XValueMember = "TimeStamp"; series7.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.DateTime; - series7.YValueMembers = "ShareAnswerPing"; + series7.YValueMembers = "NetworkRigPing"; + series8.BorderWidth = 2; + series8.ChartArea = "ChartAreaPingFrequency"; + series8.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine; + series8.Color = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(128)))), ((int)(((byte)(0))))); + series8.Legend = "LegendCoreclockMemoryclock"; + series8.LegendText = "Ping: This to URL"; + series8.Name = "MiningpingSeries"; + series8.XValueMember = "TimeStamp"; + series8.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.DateTime; + series8.YValueMembers = "MiningUrlPing"; + series9.BorderWidth = 2; + series9.ChartArea = "ChartAreaPingFrequency"; + series9.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastLine; + series9.Color = System.Drawing.Color.Indigo; + series9.Legend = "LegendCoreclockMemoryclock"; + series9.LegendText = "Ping: Miner to URL"; + series9.Name = "SharepingSeries"; + series9.XValueMember = "TimeStamp"; + series9.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.DateTime; + series9.YValueMembers = "ShareAnswerPing"; this.chartSensor.Series.Add(series1); this.chartSensor.Series.Add(series2); this.chartSensor.Series.Add(series3); @@ -208,6 +217,8 @@ private void InitializeComponent() this.chartSensor.Series.Add(series5); this.chartSensor.Series.Add(series6); this.chartSensor.Series.Add(series7); + this.chartSensor.Series.Add(series8); + this.chartSensor.Series.Add(series9); this.chartSensor.Size = new System.Drawing.Size(1150, 525); this.chartSensor.TabIndex = 0; this.chartSensor.Text = "chartSensor"; diff --git a/ccMonitor/Gui/SensorChart.cs b/ccMonitor/Gui/SensorChart.cs index bcc157a..902d867 100644 --- a/ccMonitor/Gui/SensorChart.cs +++ b/ccMonitor/Gui/SensorChart.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; using System.Windows.Forms; using System.Windows.Forms.DataVisualization.Charting; @@ -20,6 +21,8 @@ private class ChartFriendlySensorValue public int NetworkRigPing { get; set; } } + + private readonly int _hours; public SensorChart(int hours = 1) @@ -29,9 +32,11 @@ public SensorChart(int hours = 1) InitializeComponent(); chartSensor.MouseWheel += chart_MouseWheel; + chartSensor.Series["AvailabilityTemperatureSeries"].Color = Color.FromArgb(100, Color.Red); + chartSensor.Series["AvailabilityPingSeries"].Color = Color.FromArgb(100, Color.Red); } - public void UpdateCharts(List sensorValues, string os) + public void UpdateCharts(List sensorValues, List> availabilityTimeStamps , string os) { List chartFriendlySensorValues = new List(sensorValues.Count); DateTime now = DateTime.Now; @@ -40,7 +45,8 @@ public void UpdateCharts(List sensorValues, str bool windows = os.StartsWith("windows"); chartSensor.ChartAreas["ChartAreaTemperatureFan"].AxisY2.Title = windows ? "Fan (RPM)" : "Fan (%)"; - chartFriendlySensorValues.AddRange(sensorValues.OrderBy(value => value.TimeStamp).Select(sensorValue => new ChartFriendlySensorValue + IEnumerable friendlySensorValues = sensorValues + .OrderBy(value => value.TimeStamp).Select(sensorValue => new ChartFriendlySensorValue { TimeStamp = GuiHelper.UnixTimeStampToDateTime(sensorValue.TimeStamp), Temperature = sensorValue.Temperature, @@ -50,10 +56,94 @@ public void UpdateCharts(List sensorValues, str ShareAnswerPing = sensorValue.ShareAnswerPing, MiningUrlPing = sensorValue.MiningUrlPing, NetworkRigPing = sensorValue.NetworkRigPing, - }).Where(chartFriendlySensorValue => _hours > 9000 || chartFriendlySensorValue.TimeStamp > (now - start))); + }).Where(chartFriendlySensorValue => _hours > 9000 || chartFriendlySensorValue.TimeStamp > (now - start)); + IList values = friendlySensorValues as IList ?? friendlySensorValues.ToList(); + chartFriendlySensorValues.AddRange(values); + chartSensor.DataSource = chartFriendlySensorValues; chartSensor.DataBind(); + + UpdateAvailabilityCharts(availabilityTimeStamps, values); + + AutoFormatXAxis(chartFriendlySensorValues); + } + + private void UpdateAvailabilityCharts(List> availabilityTimeStamps, IList friendlySensorValues) + { + chartSensor.Series["AvailabilityTemperatureSeries"].Points.Clear(); + chartSensor.Series["AvailabilityPingSeries"].Points.Clear(); + DateTime firstTimeStamp = friendlySensorValues.First().TimeStamp; + double chartTempMaximum = friendlySensorValues.Max(value => value.Temperature)*1.2; + double chartTempMinimum = friendlySensorValues.Min(value => value.Temperature)*0.8; + double chartPingMaximum = + friendlySensorValues.SelectMany( + value => new[] {value.MiningUrlPing, value.NetworkRigPing, value.ShareAnswerPing}).Max()*1.2; + double chartPingMinimum = -2; + + for (int index = 0; index < availabilityTimeStamps.Count - 1; index++) + { + Tuple availabilityTimeStamp = availabilityTimeStamps[index]; + DateTime dateTime = GuiHelper.UnixTimeStampToDateTime(availabilityTimeStamp.Item1); + if (!availabilityTimeStamp.Item2 && dateTime > firstTimeStamp) + { + Tuple nextAvailabilityTimeStamp = availabilityTimeStamps[index + 1]; + + DateTime nextDateTime = GuiHelper.UnixTimeStampToDateTime(nextAvailabilityTimeStamp.Item1); + + chartSensor.Series["AvailabilityTemperatureSeries"].Points.AddXY(dateTime + new TimeSpan(0, 0, 1), + chartTempMinimum); + chartSensor.Series["AvailabilityTemperatureSeries"].Points.AddXY(dateTime + new TimeSpan(0, 0, 1), + chartTempMaximum + 1); + chartSensor.Series["AvailabilityTemperatureSeries"].Points.AddXY(nextDateTime - new TimeSpan(0, 0, 1), + chartTempMaximum + 1); + chartSensor.Series["AvailabilityTemperatureSeries"].Points.AddXY(nextDateTime - new TimeSpan(0, 0, 1), + chartTempMinimum); + + chartSensor.Series["AvailabilityPingSeries"].Points.AddXY(dateTime + new TimeSpan(0, 0, 1), + chartPingMinimum); + chartSensor.Series["AvailabilityPingSeries"].Points.AddXY(dateTime + new TimeSpan(0, 0, 1), + chartPingMaximum + 1); + chartSensor.Series["AvailabilityPingSeries"].Points.AddXY(nextDateTime - new TimeSpan(0, 0, 1), + chartPingMaximum + 1); + chartSensor.Series["AvailabilityPingSeries"].Points.AddXY(nextDateTime - new TimeSpan(0, 0, 1), + chartPingMinimum); + } + } + + chartSensor.ChartAreas["ChartAreaTemperatureFan"].AxisY.Maximum = chartTempMaximum; + chartSensor.ChartAreas["ChartAreaTemperatureFan"].AxisY.Minimum = chartTempMinimum; + chartSensor.ChartAreas["ChartAreaPingFrequency"].AxisY.Maximum = chartPingMaximum; + chartSensor.ChartAreas["ChartAreaPingFrequency"].AxisY.Minimum = chartPingMinimum; + } + + private void AutoFormatXAxis(List chartFriendlySensorValues) + { + int hours = _hours; + if (hours > 9000) + { + hours = (int) Math.Round((chartFriendlySensorValues[chartFriendlySensorValues.Count - 1].TimeStamp - + chartFriendlySensorValues[0].TimeStamp).TotalHours, MidpointRounding.AwayFromZero); + } + foreach (ChartArea chartArea in chartSensor.ChartAreas) + { + if (hours < 6) + { + chartArea.AxisX.LabelStyle.Format = "ddd HH:mm:ss"; + } + else if (hours < 320) + { + chartArea.AxisX.LabelStyle.Format = "MMM dd HH:mm"; + } + else if (hours < 4600) + { + chartArea.AxisX.LabelStyle.Format = "MMM dd YY HH"; + } + else + { + chartArea.AxisX.LabelStyle.Format = "MMM dd YYYY"; + } + } } private void chart_MouseWheel(object sender, MouseEventArgs e) diff --git a/ccMonitor/Gui/SensorLogView.cs b/ccMonitor/Gui/SensorLogView.cs index c52f79f..af58db9 100644 --- a/ccMonitor/Gui/SensorLogView.cs +++ b/ccMonitor/Gui/SensorLogView.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.ComponentModel; using System.Globalization; using System.Linq; using System.Windows.Forms; @@ -58,7 +59,7 @@ public void UpdateLogs(List sensorLog) userFriendlySensorValues.Add(userFriendlySensorValue); } - dgvSensorLogs.DataSource = userFriendlySensorValues; + dgvSensorLogs.DataSource = new SortableBindingList(userFriendlySensorValues); } } } diff --git a/ccMonitor/Gui/SortableBindingList.cs b/ccMonitor/Gui/SortableBindingList.cs new file mode 100644 index 0000000..6aa98fc --- /dev/null +++ b/ccMonitor/Gui/SortableBindingList.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; + +namespace ccMonitor.Gui +{ + /// + /// Provides a generic collection that supports data binding and additionally supports sorting. + /// See http://msdn.microsoft.com/en-us/library/ms993236.aspx + /// If the elements are IComparable it uses that; otherwise compares the ToString() + /// http://www.martinwilley.com/net/code/forms/sortablebindinglist.html + /// + /// The type of elements in the list. + public class SortableBindingList : BindingList where T : class + { + private bool _isSorted; + private ListSortDirection _sortDirection = ListSortDirection.Ascending; + private PropertyDescriptor _sortProperty; + + /* + /// + /// Initializes a new instance of the class. + /// + public SortableBindingList() + { + }*/ + + /// + /// Initializes a new instance of the class. + /// + /// An of items to be contained in the . + public SortableBindingList(IList list) + : base(list) + { + } + + /// + /// Gets a value indicating whether the list supports sorting. + /// + protected override bool SupportsSortingCore + { + get { return true; } + } + + /// + /// Gets a value indicating whether the list is sorted. + /// + protected override bool IsSortedCore + { + get { return _isSorted; } + } + + /// + /// Gets the direction the list is sorted. + /// + protected override ListSortDirection SortDirectionCore + { + get { return _sortDirection; } + } + + /// + /// Gets the property descriptor that is used for sorting the list if sorting is implemented in a derived class; otherwise, returns null + /// + protected override PropertyDescriptor SortPropertyCore + { + get { return _sortProperty; } + } + + /// + /// Removes any sort applied with ApplySortCore if sorting is implemented + /// + protected override void RemoveSortCore() + { + _sortDirection = ListSortDirection.Ascending; + _sortProperty = null; + _isSorted = false; //thanks Luca + } + + /// + /// Sorts the items if overridden in a derived class + /// + /// + /// + protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction) + { + _sortProperty = prop; + _sortDirection = direction; + + List list = Items as List; + if (list == null) return; + + list.Sort(Compare); + + _isSorted = true; + //fire an event that the list has been changed. + OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); + } + + + private int Compare(T lhs, T rhs) + { + var result = OnComparison(lhs, rhs); + //invert if descending + if (_sortDirection == ListSortDirection.Descending) + result = -result; + return result; + } + + private int OnComparison(T lhs, T rhs) + { + object lhsValue = lhs == null ? null : _sortProperty.GetValue(lhs); + object rhsValue = rhs == null ? null : _sortProperty.GetValue(rhs); + if (lhsValue == null) + { + return (rhsValue == null) ? 0 : -1; //nulls are equal + } + if (rhsValue == null) + { + return 1; //first has value, second doesn't + } + + var value = lhsValue as IComparable; + if (value != null) + { + return value.CompareTo(rhsValue); + } + if (lhsValue.Equals(rhsValue)) + { + return 0; //both are the same + } + //not comparable, compare ToString + return String.Compare(lhsValue.ToString(), rhsValue.ToString(), StringComparison.Ordinal); + } + } +} diff --git a/ccMonitor/Program.cs b/ccMonitor/Program.cs index c032a6f..e19edda 100644 --- a/ccMonitor/Program.cs +++ b/ccMonitor/Program.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; @@ -17,7 +18,22 @@ static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); + + TextBox t = new TextBox {Multiline = true, ScrollBars = ScrollBars.Both, Dock = DockStyle.Fill}; + Form f = new Form(); + f.Controls.Add(t); + try + { Application.Run(new Monitor()); + } + catch (Exception ex) + { + t.Text = ex.TargetSite + Environment.NewLine + ex.Data + Environment.NewLine + ex.StackTrace + + Environment.NewLine + ex.ToString() + Environment.NewLine + ex.GetType() + Environment.NewLine + + ex.GetBaseException() + Environment.NewLine + ex.InnerException; + f.Show(); + File.WriteAllText("error.txt", t.Text); + } } } } diff --git a/ccMonitor/RigController.cs b/ccMonitor/RigController.cs index 9911458..9ed118f 100644 --- a/ccMonitor/RigController.cs +++ b/ccMonitor/RigController.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using System.Net.NetworkInformation; using System.Text; +using System.Windows.Forms; using ccMonitor.Api; namespace ccMonitor @@ -117,10 +118,11 @@ public void Update() ? PruvotApi.GetHistory(rig.IpAddress, rig.Port, gpu.Info.MinerMap) : new Dictionary[0]; - if (allApiResults[3] != null && gpu.Info.Available) + gpu.Info.Available = allApiResults[3] != null; + if (gpu.Info.Available) { gpu.Update(allApiResults, pingTimes); - + // While we're at it, calculate the total stats for the rig totalHashCount += gpu.CurrentBenchmark.Statistic.TotalHashCount; totalAverageHashRate += gpu.CurrentBenchmark.Statistic.AverageHashRate; @@ -161,10 +163,19 @@ public void Update() for (int i = 0; i < 4; i++) { - rig.CurrentStatistic.AverageGaussianPercentiles[i] = totalGaussianPercentiles[i] / rig.GpuLogs.Count; + rig.CurrentStatistic.AverageGaussianPercentiles[i] = totalGaussianPercentiles[i]/ + rig.GpuLogs.Count; } } } + else + { + foreach (GpuLogger gpu in rig.GpuLogs) + { + gpu.Info.Available = false; + MessageBox.Show("Disabled because of apiresults1,2,3 erroring out"); + } + } } } @@ -206,7 +217,7 @@ private static void CheckLiveGpus(Dictionary[][] allApiResults, { foreach (GpuLogger gpu in rig.GpuLogs) { - // Let's loop again, but now only check for "old" GPUs on that bus + // Let's loop again, but now only check for "old" GPUs on that specific bus // Don't delete them, just make them unavailable if (gpu.Info.Bus == newGpu.Info.Bus) { diff --git a/ccMonitor/ccMonitor.csproj b/ccMonitor/ccMonitor.csproj index 66fdc22..112455d 100644 --- a/ccMonitor/ccMonitor.csproj +++ b/ccMonitor/ccMonitor.csproj @@ -127,6 +127,7 @@ SensorLogView.cs +