ntminer 4 年之前
父节点
当前提交
a4f080ed24
共有 100 个文件被更改,包括 948 次插入763 次删除
  1. 2 1
      docs/Index.md
  2. 4 0
      src/AppModels/AppModels.csproj
  3. 8 36
      src/AppModels/AppRoot.cs
  4. 1 1
      src/AppModels/AppRoot.partials.DriveSetViewModel.cs
  5. 2 2
      src/AppModels/AppRoot.partials.FragmentWriterViewModels.cs
  6. 44 98
      src/AppModels/AppStatic.cs
  7. 1 1
      src/AppModels/MinerStudio/Impl/LocalMinerStudioService.cs
  8. 1 1
      src/AppModels/MinerStudio/Vms/CalcConfigViewModels.cs
  9. 6 0
      src/AppModels/MinerStudio/Vms/VirtualMemoryViewModel.cs
  10. 0 25
      src/AppModels/RemoteDesktop/Firewall.cs
  11. 10 0
      src/AppModels/Vms/MinerProfileViewModel.cs
  12. 8 1
      src/AppModels/Vms/ServerMessagesViewModel.cs
  13. 12 0
      src/AppModels/Vms/SpeedTableViewModel.cs
  14. 2 8
      src/AppModels/Vms/ToolboxViewModel.cs
  15. 2 1
      src/AppViews0/MinerStudio/Views/MinerClientsWindow.xaml
  16. 11 1
      src/AppViews0/MinerStudio/Views/Ucs/VirtualMemory.xaml
  17. 0 14
      src/AppViews0/Views/ConsoleWindow.xaml
  18. 6 4
      src/AppViews0/Views/ConsoleWindow.xaml.cs
  19. 1 1
      src/AppViews0/Views/MainWindow.xaml
  20. 15 1
      src/AppViews0/Views/MainWindow.xaml.cs
  21. 3 3
      src/AppViews0/Views/Ucs/Calc.xaml
  22. 13 8
      src/AppViews0/Views/Ucs/CoinKernelEdit.xaml
  23. 3 3
      src/AppViews0/Views/Ucs/InputSegmentEdit.xaml
  24. 1 1
      src/AppViews0/Views/Ucs/KernelInputEdit.xaml
  25. 6 1
      src/AppViews0/Views/Ucs/MainMenu.xaml
  26. 8 0
      src/AppViews0/Views/Ucs/MainMenu.xaml.cs
  27. 9 3
      src/AppViews0/Views/Ucs/MinerProfileDual.xaml
  28. 8 0
      src/AppViews0/Views/Ucs/MinerProfileDual.xaml.cs
  29. 16 5
      src/AppViews0/Views/Ucs/MinerProfileIndex.xaml
  30. 8 1
      src/AppViews0/Views/Ucs/MinerProfileIndex.xaml.cs
  31. 9 0
      src/AppViews0/Views/Ucs/MinerProfileOption.xaml
  32. 20 0
      src/AppViews0/Views/Ucs/ServerMessages.xaml
  33. 38 2
      src/AppViews0/Views/Ucs/SpeedTable.xaml
  34. 21 0
      src/AppViews0/Views/Ucs/SpeedTable.xaml.cs
  35. 1 1
      src/BlankWindow/GlowWindow.xaml.cs
  36. 7 7
      src/BlankWindow/Microsoft.Windows.Shell/Standard/DpiHelper.cs
  37. 11 0
      src/MinerClient/Daemon/NTMinerDaemon.exe.config
  38. 2 2
      src/MinerClient/MinerClient.csproj
  39. 2 2
      src/MinerClient/packages.config
  40. 0 4
      src/MinerClientFinder/Views/MainWindow.xaml.cs
  41. 5 5
      src/MinerClientFinder/Vms/MainWindowViewModel.cs
  42. 2 2
      src/MinerClientSelfHost/MinerClientSelfHost.csproj
  43. 2 2
      src/MinerClientSelfHost/packages.config
  44. 2 2
      src/MinerStudio/MinerStudio.csproj
  45. 2 2
      src/MinerStudio/packages.config
  46. 2 2
      src/MinerStudioSelfHost/MinerStudioSelfHost.csproj
  47. 2 2
      src/MinerStudioSelfHost/packages.config
  48. 9 0
      src/NTMiner.Controllers/IFileUrlController.cs
  49. 0 9
      src/NTMiner.Controllers/IWsServerNodeController.cs
  50. 7 6
      src/NTMinerClient/Core/Impl/SysDicItemSet.cs
  51. 1 1
      src/NTMinerClient/Core/Kernels/Impl/KernelOutputTranslaterSet.cs
  52. 2 0
      src/NTMinerClient/Core/MineContextExtension.cs
  53. 8 2
      src/NTMinerClient/Gpus/EmptyGpuSet.cs
  54. 2 1
      src/NTMinerClient/Gpus/IGpuSet.cs
  55. 15 8
      src/NTMinerClient/Gpus/Impl/AMDGpuSet.cs
  56. 6 6
      src/NTMinerClient/Gpus/Impl/EmptyOverClock.cs
  57. 1 2
      src/NTMinerClient/Gpus/Impl/GpuOverClock.cs
  58. 1 1
      src/NTMinerClient/Gpus/Impl/GpusSpeed.cs
  59. 16 6
      src/NTMinerClient/Gpus/Impl/NVIDIAGpuSet.cs
  60. 4 0
      src/NTMinerClient/INTMinerContext.cs
  61. 10 0
      src/NTMinerClient/Messages.cs
  62. 15 3
      src/NTMinerClient/Mine/MineContext.cs
  63. 7 2
      src/NTMinerClient/NTMinerClient.csproj
  64. 18 1
      src/NTMinerClient/NTMinerContext.cs
  65. 6 1
      src/NTMinerClient/NTMinerContext.partials.CreateMineContext.cs
  66. 1 1
      src/NTMinerClient/Report/ReportDataProvider.cs
  67. 36 0
      src/NTMinerClient/SysDicItemSetExtension.cs
  68. 30 0
      src/NTMinerClient/Windows/Crash.cs
  69. 1 1
      src/NTMinerClient/Windows/Power.cs
  70. 3 2
      src/NTMinerClient/packages.config
  71. 5 2
      src/NTMinerDaemon/NTMinerDaemon.csproj
  72. 6 3
      src/NTMinerDaemon/Ws/AbstractWsClient.cs
  73. 2 2
      src/NTMinerDaemon/packages.config
  74. 6 4
      src/NTMinerDataSchemas/Core/IKernelOutputTranslater.cs
  75. 2 2
      src/NTMinerDataSchemas/Core/InputSegment.cs
  76. 21 21
      src/NTMinerDataSchemas/Core/MinerServer/ClientData.cs
  77. 3 3
      src/NTMinerDataSchemas/Core/MinerServer/QueryClientsResponse.cs
  78. 2 2
      src/NTMinerDataSchemas/NTKeyword.cs
  79. 26 10
      src/NTMinerGpus/Gpus/Adl/AdlNativeMethods.cs
  80. 1 43
      src/NTMinerGpus/Gpus/Adl/AdlTypes.cs
  81. 215 259
      src/NTMinerGpus/Gpus/AdlHelper.cs
  82. 2 1
      src/NTMinerGpus/Gpus/NvapiHelper.cs
  83. 26 34
      src/NTMinerGpus/Gpus/NvmlHelper.cs
  84. 10 8
      src/NTMinerGpus/Gpus/PInvokeDelegateFactory.cs
  85. 0 16
      src/NTMinerLogging/CommandLineArgs.cs
  86. 17 1
      src/NTMinerLogging/Impl/Log4NetLoggingService.cs
  87. 4 1
      src/NTMinerNoDevFee/NTMinerNoDevFee.csproj
  88. 3 3
      src/NTMinerNoDevFee/NoDevFee/NoDevFeeUtil.cs
  89. 1 1
      src/NTMinerNoDevFee/packages.config
  90. 8 3
      src/NTMinerRpcClient/BinaryRequestJsonResponseRpcRoot.cs
  91. 3 1
      src/NTMinerRpcClient/HttpRpcRoot.cs
  92. 3 3
      src/NTMinerRpcClient/Impl/ServerMessageSet.cs
  93. 17 7
      src/NTMinerRpcClient/JsonRequestBinaryResponseRpcRoot.cs
  94. 9 4
      src/NTMinerRpcClient/JsonRpcRoot.cs
  95. 12 3
      src/NTMinerRpcClient/JsonRpcRoot.partial.cs
  96. 1 1
      src/NTMinerRpcClient/NTMinerRpcClient.csproj
  97. 1 1
      src/NTMinerRpcClient/RpcRoot.cs
  98. 0 10
      src/NTMinerRpcClient/Services/Official/WsServerNodeService.cs
  99. 1 1
      src/NTMinerRpcClient/packages.config
  100. 3 4
      src/NTMinerServer/Core/IWsServerNodeAddressSet.cs

+ 2 - 1
docs/Index.md

@@ -14,4 +14,5 @@
 * 确保不要在Xaml中构建任何ViewModel对象,确保视图类型(Window、Uc)的Vm属性不是通过转型它的DataContext得到的,从而避免访问Vm的时候访问到UI对象造成在非UI线程访问UI对象的异常。
 * 局部性是好事,但也有利弊,凡是有可能变化的事物在开源矿工中都具有唯一性,它们都挂载在VirtualRoot、NTMinerRoot、RpcRoot、AppRoot上,也就是说此类对象不会注入到当地也不允许当地持有对此类对象的引用,只允许在过程中(方法或函数)从Root根开始索引。
 * 新版本的C#语法不要求对只读属性声明private set访问器,这不是一个好特性,开源矿工不会使用这个语法,因为没有private set访问器的声明就没法在set上右键查找引用位置了。
-* 用属性不要用字段,因为字段上没有IDE提供的引用计数信息。
+* 用属性不要用字段,因为字段上没有IDE提供的引用计数信息。
+* 数据常驻内存,数据在内存中列表、字典排布。内存中是存在形如Dictionary<TId, List<TValue>>类型的数据的,其中的List<TValue>可能会直接以引用的形式返回给调用者,调用者拿到后可能会foreach,但List<TValue>可能会在foreach期间被另外的线程修改,所以这里需要两点约定:1,使用数组传达不可变性;2,枚举List前应ToArray个快照,枚举快照。

+ 4 - 0
src/AppModels/AppModels.csproj

@@ -245,6 +245,10 @@
       <Project>{defc7387-f9fa-4651-a281-6612efb7fbb6}</Project>
       <Name>NTMinerDataSchemas</Name>
     </ProjectReference>
+    <ProjectReference Include="..\NTMinerGpus\NTMinerGpus.csproj">
+      <Project>{035c9774-01fc-4df2-8225-769542a9fd5e}</Project>
+      <Name>NTMinerGpus</Name>
+    </ProjectReference>
     <ProjectReference Include="..\NTMinerHub\NTMinerHub.csproj">
       <Project>{e17f278a-e393-403e-9d37-e371036d7a02}</Project>
       <Name>NTMinerHub</Name>

+ 8 - 36
src/AppModels/AppRoot.cs

@@ -88,33 +88,6 @@ namespace NTMiner {
         #endregion
 
         #region 字典项
-        public static Version MinAmdDriverVersion {
-            get {
-                if (WpfUtil.IsInDesignMode) {
-                    return new Version();
-                }
-                if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "MinAmdDriverVersion", out ISysDicItem dicItem)) {
-                    if (Version.TryParse(dicItem.Value, out Version version)) {
-                        return version;
-                    }
-                }
-                return new Version(17, 10, 2, 0);
-            }
-        }
-
-        public static Version MinNvidiaDriverVersion {
-            get {
-                if (WpfUtil.IsInDesignMode) {
-                    return new Version();
-                }
-                if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "MinNvidiaDriverVersion", out ISysDicItem dicItem)) {
-                    if (Version.TryParse(dicItem.Value, out Version version)) {
-                        return version;
-                    }
-                }
-                return new Version(399, 24);
-            }
-        }
 
         public static string NppPackageUrl {
             get {
@@ -122,10 +95,7 @@ namespace NTMiner {
                 if (WpfUtil.IsDevMode) {
                     return url;
                 }
-                if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem("Tool", "npp", out ISysDicItem dicItem)) {
-                    return dicItem.Value;
-                }
-                return url;
+                return NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue("Tool", "npp", defaultValue: url);
             }
         }
         #endregion
@@ -136,11 +106,13 @@ namespace NTMiner {
                 if (WpfUtil.IsDevMode) {
                     return value;
                 }
-                if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "OsVmPerGpu", out ISysDicItem dicItem)
-                    && double.TryParse(dicItem.Value, out value)) {
-                    return value;
-                }
-                return value;
+                return NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "OsVmPerGpu", value);
+            }
+        }
+
+        public static string VirtualMemoryDescription {
+            get {
+                return $"挖 ETH 每卡至少设置 {OsVmPerGpu.ToString("f1")}G 虚拟内存,建议按虚拟内存比显存 1 比 1 设置。比如 6 张 6G 的 1066 显卡建议设置 6 x 6 = 36G。";
             }
         }
 

+ 1 - 1
src/AppModels/AppRoot.partials.DriveSetViewModel.cs

@@ -50,7 +50,7 @@ namespace NTMiner {
 
             public string Description {
                 get {
-                    return $"挖 ETH 每卡至少设置 {OsVmPerGpu.ToString("f1")}G 虚拟内存,建议按虚拟内存比显存 1 比 1 设置。比如 6 张 6G 的 1066 显卡建议设置 6 x 6 = 36G。";
+                    return AppRoot.VirtualMemoryDescription;
                 }
             }
         }

+ 2 - 2
src/AppModels/AppRoot.partials.FragmentWriterViewModels.cs

@@ -29,8 +29,8 @@ namespace NTMiner {
                 AddEventPath<FragmentWriterAddedEvent>("添加了命令行片段书写器后调整VM内存", LogEnum.DevConsole,
                     action: (message) => {
                         if (!_dicById.ContainsKey(message.Source.GetId())) {
-                            FragmentWriterViewModel groupVm = new FragmentWriterViewModel(message.Source);
-                            _dicById.Add(message.Source.GetId(), groupVm);
+                            FragmentWriterViewModel vm = new FragmentWriterViewModel(message.Source);
+                            _dicById.Add(message.Source.GetId(), vm);
                             OnPropertyChangeds();
                         }
                     }, location: this.GetType());

+ 44 - 98
src/AppModels/AppStatic.cs

@@ -7,7 +7,6 @@ using NTMiner.Vms;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
-using System.Linq;
 using System.Windows;
 using System.Windows.Input;
 using System.Windows.Media;
@@ -244,6 +243,15 @@ namespace NTMiner {
         }
         #endregion
 
+        public static Visibility IsMixedGpuVisible {
+            get {
+                if (WpfUtil.IsInDesignMode) {
+                    return Visibility.Visible;
+                }
+                return NTMinerContext.Instance.GpuSet.GpuType == GpuType.NVIDIA && AdlHelper.IsHasATIGpu ? Visibility.Visible : Visibility.Collapsed;
+            }
+        }
+
         #region IsBrand
         public static bool IsPoolBrand {
             get {
@@ -380,13 +388,13 @@ namespace NTMiner {
         #region Gpu
         public static Version MinAmdDriverVersion {
             get {
-                return AppRoot.MinAmdDriverVersion;
+                return NTMinerContext.Instance.MinAmdDriverVersion;
             }
         }
 
         public static Version MinNvidiaDriverVersion {
             get {
-                return AppRoot.MinNvidiaDriverVersion;
+                return NTMinerContext.Instance.MinNvidiaDriverVersion;
             }
         }
 
@@ -405,13 +413,7 @@ namespace NTMiner {
                     return "0.0";
                 }
                 var gpuSet = NTMinerContext.Instance.GpuSet;
-                if (gpuSet.GpuType == GpuType.NVIDIA) {
-                    var cudaVersion = gpuSet.Properties.FirstOrDefault(a => a.Code == NTKeyword.CudaVersionSysDicCode);
-                    if (cudaVersion != null) {
-                        return $"{gpuSet.DriverVersion}_{cudaVersion.Value}";
-                    }
-                }
-                return gpuSet.DriverVersion.ToString();
+                return gpuSet.DriverVersion;
             }
         }
 
@@ -421,17 +423,8 @@ namespace NTMiner {
                     return WpfUtil.RedBrush;
                 }
                 var gpuSet = NTMinerContext.Instance.GpuSet;
-                switch (gpuSet.GpuType) {
-                    case GpuType.NVIDIA:
-                        if (gpuSet.DriverVersion < AppRoot.MinNvidiaDriverVersion) {
-                            return WpfUtil.RedBrush;
-                        }
-                        break;
-                    case GpuType.AMD:
-                        if (gpuSet.DriverVersion < AppRoot.MinAmdDriverVersion) {
-                            return WpfUtil.RedBrush;
-                        }
-                        break;
+                if (gpuSet.IsLowDriverVersion) {
+                    return WpfUtil.RedBrush;
                 }
                 return AppUtil.GetResource<SolidColorBrush>("LableColor");
             }
@@ -443,20 +436,7 @@ namespace NTMiner {
                     return string.Empty;
                 }
                 var gpuSet = NTMinerContext.Instance.GpuSet;
-                bool isTooLow = false;
-                switch (gpuSet.GpuType) {
-                    case GpuType.NVIDIA:
-                        if (gpuSet.DriverVersion < AppRoot.MinNvidiaDriverVersion) {
-                            isTooLow = true;
-                        }
-                        break;
-                    case GpuType.AMD:
-                        if (gpuSet.DriverVersion < AppRoot.MinAmdDriverVersion) {
-                            isTooLow = true;
-                        }
-                        break;
-                }
-                if (isTooLow) {
+                if (gpuSet.IsLowDriverVersion) {
                     return "显卡驱动版本较低,工具箱里有驱动下载地址";
                 }
                 return "显卡驱动版本";
@@ -627,27 +607,21 @@ namespace NTMiner {
 
         public static ICommand JoinQQGroup { get; private set; } = new DelegateCommand(() => {
             string url = "https://jq.qq.com/?_wv=1027&k=5ZPsuCk";
-            if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "QQGroupJoinUrl", out ISysDicItem dicItem)) {
-                url = dicItem.Value;
-            }
+            url = NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "QQGroupJoinUrl", defaultValue: url);
             VirtualRoot.Execute(new UnTopmostCommand());
             Process.Start(url);
         });
 
         public static ICommand ShareTutorial { get; private set; } = new DelegateCommand(() => {
             string url = "https://zhuanlan.zhihu.com/p/161614545";
-            if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "ShareTutorial", out ISysDicItem dicItem)) {
-                url = dicItem.Value;
-            }
+            url = NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "ShareTutorial", defaultValue: url);
             VirtualRoot.Execute(new UnTopmostCommand());
             Process.Start(url);
         });
 
         public static ICommand SpeedTutorial { get; private set; } = new DelegateCommand(() => {
             string url = "https://zhuanlan.zhihu.com/p/161614356";
-            if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "SpeedTutorial", out ISysDicItem dicItem)) {
-                url = dicItem.Value;
-            }
+            url = NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "SpeedTutorial", defaultValue: url);
             VirtualRoot.Execute(new UnTopmostCommand());
             Process.Start(url);
         });
@@ -725,9 +699,7 @@ namespace NTMiner {
         });
         public static ICommand ShowHelp { get; private set; } = new DelegateCommand(() => {
             string url = "http://ntminer.com/";
-            if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "HelpUrl", out ISysDicItem dicItem)) {
-                url = dicItem.Value;
-            }
+            url = NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "HelpUrl", defaultValue: url);
             VirtualRoot.Execute(new UnTopmostCommand());
             Process.Start(url);
         });
@@ -763,18 +735,14 @@ namespace NTMiner {
 
         public static ICommand OpenWindowsAutoLogonMoreInfo { get; private set; } = new DelegateCommand(() => {
             string url = "https://support.microsoft.com/zh-cn/help/324737/how-to-turn-on-automatic-logon-in-windows";
-            if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "WindowsAutoLogonMoreInfo", out ISysDicItem dicItem)) {
-                url = dicItem.Value;
-            }
+            url = NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "WindowsAutoLogonMoreInfo", defaultValue: url);
             VirtualRoot.Execute(new UnTopmostCommand());
             Process.Start(url);
         });
 
         public static ICommand OpenOfficialSite { get; private set; } = new DelegateCommand(() => {
             string url = "http://ntminer.com/";
-            if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "HomePageUrl", out ISysDicItem dicItem)) {
-                url = dicItem.Value;
-            }
+            url = NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "HomePageUrl", defaultValue: url);
             VirtualRoot.Execute(new UnTopmostCommand());
             Process.Start(url);
         });
@@ -784,28 +752,29 @@ namespace NTMiner {
                 if (WpfUtil.IsInDesignMode) {
                     return string.Empty;
                 }
-                if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "QQGroup", out ISysDicItem dicItem)) {
-                    return dicItem.Value;
-                }
-                return "863725136";
+                return NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "QQGroup", defaultValue: "863725136");
             }
         }
 
         public static string OfficialSiteName {
             get {
-                const string txt = "NTMiner.com";
+                string url = "NTMiner.com";
                 if (WpfUtil.IsDevMode) {
-                    return txt;
+                    return url;
+                }
+                string dicItemValue = NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "HomePageUrl", defaultValue: url);
+                if (!string.IsNullOrEmpty(dicItemValue)) {
+                    url = dicItemValue;
                 }
-                if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "HomePageUrl", out ISysDicItem dicItem) && !string.IsNullOrEmpty(dicItem.Value)) {
-                    if (dicItem.Value.StartsWith("https://")) {
-                        return dicItem.Value.Substring("https://".Length);
+                if (!string.IsNullOrEmpty(url)) {
+                    if (url.StartsWith("https://")) {
+                        return url.Substring("https://".Length);
                     }
-                    if (dicItem.Value.StartsWith("http://")) {
-                        return dicItem.Value.Substring("http://".Length);
+                    if (url.StartsWith("http://")) {
+                        return url.Substring("http://".Length);
                     }
                 }
-                return txt;
+                return url;
             }
         }
 
@@ -815,10 +784,7 @@ namespace NTMiner {
                 if (WpfUtil.IsDevMode) {
                     return txt;
                 }
-                if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "AppMinerName", out ISysDicItem dicItem)) {
-                    return dicItem.Value;
-                }
-                return txt;
+                return NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "AppMinerName", txt);
             }
         }
 
@@ -828,10 +794,7 @@ namespace NTMiner {
                 if (WpfUtil.IsDevMode) {
                     return txt;
                 }
-                if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "AppMinerName", out ISysDicItem dicItem)) {
-                    return " - " + dicItem.Description;
-                }
-                return txt;
+                return NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemDescription(NTKeyword.ThisSystemSysDicCode, "AppMinerName", txt);
             }
         }
 
@@ -841,72 +804,55 @@ namespace NTMiner {
                 if (WpfUtil.IsDevMode) {
                     return txt;
                 }
-                if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "AppMinerIntro", out ISysDicItem dicItem)) {
-                    return dicItem.Value;
-                }
-                return txt;
+                return NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "AppMinerIntro", txt);
             }
         }
 
         public static ICommand BusinessModel { get; private set; } = new DelegateCommand(() => {
             string url = "https://zhuanlan.zhihu.com/p/161614178";
-            if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "BusinessModelUrl", out ISysDicItem dicItem)) {
-                url = dicItem.Value;
-            }
+            url = NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "BusinessModelUrl", url);
             VirtualRoot.Execute(new UnTopmostCommand());
             Process.Start(url);
         });
 
         public static ICommand OpenGithub { get; private set; } = new DelegateCommand(() => {
             string url = "https://github.com/ntminer/NtMiner";
-            if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "GithubUrl", out ISysDicItem dicItem)) {
-                url = dicItem.Value;
-            }
+            url = NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "GithubUrl", url);
             VirtualRoot.Execute(new UnTopmostCommand());
             Process.Start(url);
         });
 
         public static ICommand OpenLGPL { get; private set; } = new DelegateCommand(() => {
             string url = "https://minerjson.oss-cn-beijing.aliyuncs.com/LGPL.png";
-            if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "LGPL", out ISysDicItem dicItem)) {
-                url = dicItem.Value;
-            }
+            url = NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "LGPL", url);
             VirtualRoot.Execute(new UnTopmostCommand());
             Process.Start(url);
         });
 
         public static ICommand OpenDiscussSite { get; private set; } = new DelegateCommand(() => {
             string url = "https://github.com/ntminer/NtMiner/issues";
-            if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "DiscussUrl", out ISysDicItem dicItem)) {
-                url = dicItem.Value;
-            }
+            url = NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "DiscussUrl", url);
             VirtualRoot.Execute(new UnTopmostCommand());
             Process.Start(url);
         });
 
         public static ICommand MinerStudioTutorial { get; private set; } = new DelegateCommand(() => {
             string url = "https://zhuanlan.zhihu.com/p/137759804";
-            if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "MinerStudioTutorial", out ISysDicItem dicItem)) {
-                url = dicItem.Value;
-            }
+            url = NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "MinerStudioTutorial", url);
             VirtualRoot.Execute(new UnTopmostCommand());
             Process.Start(url);
         });
 
         public static ICommand DownloadMinerStudio { get; private set; } = new DelegateCommand(() => {
             string url = "https://zhuanlan.zhihu.com/p/138095293";
-            if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "DownloadMinerStudio", out ISysDicItem dicItem)) {
-                url = dicItem.Value;
-            }
+            url = NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "DownloadMinerStudio", url);
             VirtualRoot.Execute(new UnTopmostCommand());
             Process.Start(url);
         });
 
         public static ICommand WindowsZoomBug { get; private set; } = new DelegateCommand(() => {
             string url = "https://zhuanlan.zhihu.com/p/161613889";
-            if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "WindowsZoomBug", out ISysDicItem dicItem)) {
-                url = dicItem.Value;
-            }
+            url = NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "WindowsZoomBug", url);
             VirtualRoot.Execute(new UnTopmostCommand());
             Process.Start(url);
         });

+ 1 - 1
src/AppModels/MinerStudio/Impl/LocalMinerStudioService.cs

@@ -63,7 +63,7 @@ namespace NTMiner.MinerStudio.Impl {
                     user: null,
                     query,
                     out int total,
-                    out List<CoinSnapshotData> latestSnapshots,
+                    out CoinSnapshotData[] latestSnapshots,
                     out int totalOnlineCount,
                     out int totalMiningCount);
                 VirtualRoot.RaiseEvent(new QueryClientsResponseEvent(QueryClientsResponse.Ok(data, total, latestSnapshots, totalMiningCount, totalOnlineCount)));

+ 1 - 1
src/AppModels/MinerStudio/Vms/CalcConfigViewModels.cs

@@ -24,7 +24,7 @@ namespace NTMiner.MinerStudio.Vms {
 
         public void Refresh() {
             var list = new List<CalcConfigViewModel>();
-            foreach (var item in NTMinerContext.Instance.CalcConfigSet.AsEnumerable()) {
+            foreach (var item in NTMinerContext.Instance.CalcConfigSet.AsEnumerable().ToArray()) {
                 list.Add(new CalcConfigViewModel(item));
             }
             CalcConfigVms = list;

+ 6 - 0
src/AppModels/MinerStudio/Vms/VirtualMemoryViewModel.cs

@@ -67,5 +67,11 @@ namespace NTMiner.MinerStudio.Vms {
                 return _drives.Sum(a => a.VirtualMemoryMaxSizeMb);
             }
         }
+
+        public string Description {
+            get {
+                return AppRoot.VirtualMemoryDescription;
+            }
+        }
     }
 }

+ 0 - 25
src/AppModels/RemoteDesktop/Firewall.cs

@@ -24,7 +24,6 @@ namespace NTMiner.RemoteDesktop {
         private const NET_FW_SCOPE_ MinerClientScope = NET_FW_SCOPE_.NET_FW_SCOPE_ALL;
         private const string MinerClientRuleName = "MinerClient";
         private const string NTMinerDaemonRuleName = "NTMinerDaemon";
-        private const string WsServerRuleName = "WsServer";
 
         #region DisableFirewall
         public static bool DisableFirewall() {
@@ -89,10 +88,6 @@ namespace NTMiner.RemoteDesktop {
         }
 
         public static void AddMinerClientRule() {
-            FirewallStatus state = Status(FirewallDomain.Domain);
-            if (state == RemoteDesktop.FirewallStatus.Disabled) {
-                return;
-            }
             try {
                 OpenPort($"{MinerClientRuleName}_TCP", NTKeyword.MinerClientPort, NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP, MinerClientScope);
                 OpenPort($"{MinerClientRuleName}_UDP", NTKeyword.MinerClientPort, NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_UDP, MinerClientScope);
@@ -109,10 +104,6 @@ namespace NTMiner.RemoteDesktop {
         /// 仅供单元测试
         /// </summary>
         public static void RemoveMinerClientRule() {
-            FirewallStatus state = Status(FirewallDomain.Domain);
-            if (state == RemoteDesktop.FirewallStatus.Disabled) {
-                return;
-            }
             try {
                 INetFwOpenPorts openPorts = GetOpenPorts();
                 openPorts.Remove(NTKeyword.MinerClientPort, NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP);
@@ -131,10 +122,6 @@ namespace NTMiner.RemoteDesktop {
         }
 
         public static bool IsMinerClientRuleExists() {
-            FirewallStatus state = Status(FirewallDomain.Domain);
-            if (state == RemoteDesktop.FirewallStatus.Disabled) {
-                return true;
-            }
             try {
                 INetFwPolicy2 policyManager = GetPolicyManager();
                 return
@@ -148,10 +135,6 @@ namespace NTMiner.RemoteDesktop {
         }
 
         public static void AddRdpRule() {
-            FirewallStatus state = Status(FirewallDomain.Domain);
-            if (state == RemoteDesktop.FirewallStatus.Disabled) {
-                return;
-            }
             try {
                 OpenPort($"{RdpRuleName}_TCP", RdpTcpPort, NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP, RdpScope);
                 OpenPort($"{RdpRuleName}_UDP", RdpUdpPort, NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_UDP, RdpScope);
@@ -165,10 +148,6 @@ namespace NTMiner.RemoteDesktop {
         /// 仅供单元测试
         /// </summary>
         public static void RemoveRdpRule() {
-            FirewallStatus state = Status(FirewallDomain.Domain);
-            if (state == RemoteDesktop.FirewallStatus.Disabled) {
-                return;
-            }
             try {
                 INetFwOpenPorts openPorts = GetOpenPorts();
                 openPorts.Remove(RdpTcpPort, NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP);
@@ -186,10 +165,6 @@ namespace NTMiner.RemoteDesktop {
         /// 仅供单元测试
         /// </summary>
         public static bool IsRdpRuleExists() {
-            FirewallStatus state = Status(FirewallDomain.Domain);
-            if (state == RemoteDesktop.FirewallStatus.Disabled) {
-                return true;
-            }
             try {
                 INetFwPolicy2 policyManager = GetPolicyManager();
                 return policyManager.Rules.OfType<INetFwRule>().Any(x => x.Name.StartsWith(RdpRuleName));

+ 10 - 0
src/AppModels/Vms/MinerProfileViewModel.cs

@@ -998,5 +998,15 @@ namespace NTMiner.Vms {
                 return IsMining || IsWorker;
             }
         }
+
+        public bool IsAutoReboot {
+            get {
+                return Windows.Crash.GetAutoReboot();
+            }
+            set {
+                Windows.Crash.SetAutoReboot(value);
+                OnPropertyChanged(nameof(IsAutoBoot));
+            }
+        }
     }
 }

+ 8 - 1
src/AppModels/Vms/ServerMessagesViewModel.cs

@@ -16,6 +16,7 @@ namespace NTMiner.Vms {
 
         public ICommand ClearKeyword { get; private set; }
         public ICommand Clear { get; private set; }
+        public ICommand ViewHistory { get; private set; }
 
         public ServerMessagesViewModel() {
             if (WpfUtil.IsInDesignMode) {
@@ -39,7 +40,13 @@ namespace NTMiner.Vms {
             });
             this.Clear = new DelegateCommand(() => {
                 this.ShowSoftDialog(new DialogWindowViewModel(message: "确定清空吗?", title: "确认", onYes: () => {
-                    VirtualRoot.Execute(new ClearServerMessages());
+                    VirtualRoot.Execute(new ClearServerMessagesCommand());
+                }));
+            });
+            this.ViewHistory = new DelegateCommand(() => {
+                this.ShowSoftDialog(new DialogWindowViewModel(message: "确定显示历史消息吗?", title: "确认", onYes: () => {
+                    VirtualRoot.LocalServerMessageSetTimestamp = Timestamp.UnixBaseTime;
+                    VirtualRoot.Execute(new LoadNewServerMessageCommand());
                 }));
             });
             VirtualRoot.AddEventPath<ServerMessagesClearedEvent>("清空了本地存储的服务器消息后刷新Vm内存", LogEnum.DevConsole,

+ 12 - 0
src/AppModels/Vms/SpeedTableViewModel.cs

@@ -3,9 +3,21 @@ using System.Windows;
 
 namespace NTMiner.Vms {
     public class SpeedTableViewModel : ViewModelBase {
+        private Visibility _isPCIEVisible = Visibility.Collapsed;
+
         public SpeedTableViewModel() {
         }
 
+        public Visibility IsPCIEVisible {
+            get => _isPCIEVisible;
+            set {
+                if (_isPCIEVisible != value) {
+                    _isPCIEVisible = value;
+                    OnPropertyChanged(nameof(IsPCIEVisible));
+                }
+            }
+        }
+
         public Visibility IsVoltVisible {
             get {
                 if (NTMinerContext.Instance.GpuSet.GpuType == GpuType.AMD) {

+ 2 - 8
src/AppModels/Vms/ToolboxViewModel.cs

@@ -91,20 +91,14 @@ namespace NTMiner.Vms {
         public string BlockWAUHelpUrl {
             get {
                 string url = "https://zhuanlan.zhihu.com/p/166387002";
-                if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "BlockWAUHelpUrl", out ISysDicItem dicItem)) {
-                    url = dicItem.Value;
-                }
-                return url;
+                return NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "BlockWAUHelpUrl", url);
             }
         }
 
         public string Win10OptimizeHelpUrl {
             get {
                 string url = "https://zhuanlan.zhihu.com/p/166385743";
-                if (NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItem(NTKeyword.ThisSystemSysDicCode, "Win10OptimizeHelpUrl", out ISysDicItem dicItem)) {
-                    url = dicItem.Value;
-                }
-                return url;
+                return NTMinerContext.Instance.ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "Win10OptimizeHelpUrl", url);
             }
         }
 

+ 2 - 1
src/AppViews0/MinerStudio/Views/MinerClientsWindow.xaml

@@ -456,8 +456,9 @@
                 BorderThickness="0"
                 Command="{Binding SwitchService}">
                 <WrapPanel>
+                    <TextBlock Padding="0 4">当前</TextBlock>
                     <TextBlock 
-                        Padding="4 4 2 4"
+                        Padding="0 4 2 4"
                         Text="{Binding NetTypeText}"></TextBlock>
                     <Path 
 					    Height="14"

+ 11 - 1
src/AppViews0/MinerStudio/Views/Ucs/VirtualMemory.xaml

@@ -167,6 +167,16 @@
                 </WrapPanel>
             </controls:KbButton>
         </WrapPanel>
-        <TextBox Grid.Row="2" Height="32" VerticalContentAlignment="Top" VerticalAlignment="Top" BorderThickness="0" AcceptsReturn="True" TextWrapping="Wrap" IsReadOnly="True" Foreground="Red" Text="挖ETH每卡至少设置5G虚拟内存(4G不保险),建议按虚拟内存比显存1比1进行设置。比如6张6G的1060建议设置6 x 6 = 36G。"></TextBox>
+        <TextBox 
+            Grid.Row="2" 
+            Height="32" 
+            VerticalContentAlignment="Top" 
+            VerticalAlignment="Top" 
+            BorderThickness="0" 
+            AcceptsReturn="True" 
+            TextWrapping="Wrap" 
+            IsReadOnly="True" 
+            Foreground="Red" 
+            Text="{Binding Description,Mode=OneWay}"></TextBox>
     </Grid>
 </UserControl>

+ 0 - 14
src/AppViews0/Views/ConsoleWindow.xaml

@@ -15,19 +15,5 @@
     Title="Windows控制台窗口">
     <!--窗口不能透明否则在远程桌面时无法显现-->
     <Grid>
-        <controls:KbLinkButton
-            x:Name="LbtnWindowsZoomBug"
-            Visibility="Collapsed"
-            Margin="350 0 20 80"
-			Padding="0"
-            HorizontalAlignment="Left"
-            VerticalAlignment="Bottom"
-			Command="{x:Static app:AppStatic.WindowsZoomBug}"
-			KbDisplayLine="False"
-			Content="解决部分windows下界面错位的方法"
-            Foreground="Red"
-            FontSize="16"
-			Background="Transparent">
-        </controls:KbLinkButton>
     </Grid>
 </Window>

+ 6 - 4
src/AppViews0/Views/ConsoleWindow.xaml.cs

@@ -21,10 +21,6 @@ namespace NTMiner.Views {
                 hwndSource = PresentationSource.FromVisual((Visual)sender) as HwndSource;
                 hwndSource.AddHook(new HwndSourceHook(Win32Proc.WindowProc));
             };
-            // 延迟展示从而避免不需要展示红字的时候看到红字
-            VirtualRoot.AddOnecePath<HasBoot1SecondEvent>("启动一会后显式指引解决WindowsZoomBug的一行红字", LogEnum.None, action: message => {
-                LbtnWindowsZoomBug.Visibility = Visibility.Visible;
-            }, pathId: PathId.Empty, this.GetType());
         }
 
         protected override void OnClosed(EventArgs e) {
@@ -45,6 +41,12 @@ namespace NTMiner.Views {
             if (_marginLeft == marginLeft && _marginTop == marginTop && _height == height && _width == width) {
                 return;
             }
+            var rect = Microsoft.Windows.Shell.Standard.DpiHelper.LogicalRectToDevice(new Rect(marginLeft, marginTop, width, height));
+            marginLeft = (int)rect.Left;
+            marginTop = (int)rect.Top;
+            width = (int)rect.Width;
+            height = (int)rect.Height;
+
             _marginLeft = marginLeft;
             _marginTop = marginTop;
             _height = height;

+ 1 - 1
src/AppViews0/Views/MainWindow.xaml

@@ -56,7 +56,7 @@
                     <ColumnDefinition Width="Auto"></ColumnDefinition>
                 </Grid.ColumnDefinitions>
                 <WrapPanel VerticalAlignment="Center" Background="Transparent">
-                    <Menu Background="Transparent">
+                    <Menu Background="Transparent" PreviewMouseDown="Menu_PreviewMouseDown" PreviewMouseUp="Menu_PreviewMouseUp">
                         <MenuItem Width="26" Height="30">
                             <MenuItem.Icon>
                                 <Image Width="17" Height="18" Source="/NTMinerWpf;component/Styles/Images/logo32.png"></Image>

+ 15 - 1
src/AppViews0/Views/MainWindow.xaml.cs

@@ -5,7 +5,6 @@ using System;
 using System.ComponentModel;
 using System.Windows;
 using System.Windows.Controls;
-using System.Windows.Forms.VisualStyles;
 using System.Windows.Input;
 using System.Windows.Interop;
 using System.Windows.Media;
@@ -162,6 +161,13 @@ namespace NTMiner.Views {
             this.LocationChanged += (sender, e) => {
                 MoveConsoleWindow();
             };
+            VirtualRoot.AddCmdPath<TopmostCommand>(action: message => {
+                UIThread.Execute(() => {
+                    if (!this.Topmost) {
+                        this.Topmost = true;
+                    }
+                });
+            }, this.GetType());
             VirtualRoot.AddCmdPath<UnTopmostCommand>(action: message => {
                 UIThread.Execute(() => {
                     if (this.Topmost) {
@@ -438,5 +444,13 @@ namespace NTMiner.Views {
             }
         }
         #endregion
+
+        private void Menu_PreviewMouseDown(object sender, MouseButtonEventArgs e) {
+            VirtualRoot.Execute(new TopmostCommand());
+        }
+
+        private void Menu_PreviewMouseUp(object sender, MouseButtonEventArgs e) {
+            VirtualRoot.Execute(new UnTopmostCommand());
+        }
     }
 }

+ 3 - 3
src/AppViews0/Views/Ucs/Calc.xaml

@@ -32,7 +32,7 @@
                         </DataTemplate>
                     </DataGridTemplateColumn.CellTemplate>
                 </DataGridTemplateColumn>
-                <DataGridTemplateColumn MinWidth="110" IsReadOnly="True" Header="币价">
+                <DataGridTemplateColumn MinWidth="100" IsReadOnly="True" Header="币价">
                     <DataGridTemplateColumn.CellTemplate>
                         <DataTemplate>
                             <WrapPanel Background="{Binding CoinIncomeVm.BackgroundBrush}">
@@ -42,7 +42,7 @@
                         </DataTemplate>
                     </DataGridTemplateColumn.CellTemplate>
                 </DataGridTemplateColumn>
-                <DataGridTemplateColumn Width="170" Header="全网算力" IsReadOnly="True">
+                <DataGridTemplateColumn Width="200" Header="全网算力" IsReadOnly="True">
                     <DataGridTemplateColumn.CellTemplate>
                         <DataTemplate>
                             <WrapPanel>
@@ -57,7 +57,7 @@
                         </DataTemplate>
                     </DataGridTemplateColumn.CellTemplate>
                 </DataGridTemplateColumn>
-                <DataGridTemplateColumn MinWidth="160" IsReadOnly="True" Header="总算力">
+                <DataGridTemplateColumn MinWidth="140" IsReadOnly="True" Header="总算力">
                     <DataGridTemplateColumn.CellTemplate>
                         <DataTemplate>
                             <WrapPanel>

+ 13 - 8
src/AppViews0/Views/Ucs/CoinKernelEdit.xaml

@@ -249,7 +249,7 @@
 				</DataGrid.Columns>
 			</DataGrid>
 		</WrapPanel>
-		<WrapPanel Margin="0 2" Visibility="{x:Static app:AppStatic.IsDevModeVisible}">
+		<WrapPanel Margin="0 2">
 			<TextBlock Style="{StaticResource LblTb}" VerticalAlignment="Top" Text="片段"></TextBlock>
 			<DataGrid 
 				Width="536"
@@ -264,7 +264,8 @@
 				<DataGrid.Columns>
 					<DataGridTemplateColumn IsReadOnly="True">
 						<DataGridTemplateColumn.Header>
-							<controls:KbButton  
+                            <controls:KbButton
+                                Visibility="{x:Static app:AppStatic.IsDevModeVisible}"
 								Command="{Binding Data.AddSegment, Source={StaticResource proxy}}" 
 								Background="Transparent" BorderThickness="0"
 								Margin="2 0"
@@ -282,7 +283,8 @@
 						<DataGridTemplateColumn.CellTemplate>
 							<DataTemplate>
 								<StackPanel HorizontalAlignment="Right" Background="Transparent" VerticalAlignment="Center" Orientation="Horizontal">
-									<controls:KbButton 
+                                    <controls:KbButton 
+										Visibility="{x:Static app:AppStatic.IsDevModeVisible}"
 										Margin="2 0"
 										Command="{Binding Data.EditSegment, Source={StaticResource proxy}}" 
 										CommandParameter="{Binding}"
@@ -297,7 +299,8 @@
 												Stretch="Fill" />
 										</WrapPanel>
 									</controls:KbButton>
-									<controls:KbButton 
+                                    <controls:KbButton 
+										Visibility="{x:Static app:AppStatic.IsDevModeVisible}"
 										Margin="2 0"
 										Command="{Binding Data.RemoveSegment, Source={StaticResource proxy}}" 
 										CommandParameter="{Binding}"
@@ -358,7 +361,7 @@
 				</DataGrid.Columns>
 			</DataGrid>
 		</WrapPanel>
-		<WrapPanel Margin="0 2" Visibility="{x:Static app:AppStatic.IsDevModeVisible}">
+		<WrapPanel Margin="0 2">
 			<TextBlock Style="{StaticResource LblTb}" VerticalAlignment="Top" Text="文件书写器"></TextBlock>
 			<Grid>
 				<DataGrid 
@@ -374,7 +377,8 @@
 						<DataGridTemplateColumn Width="32" IsReadOnly="True">
 							<DataGridTemplateColumn.CellTemplate>
 								<DataTemplate>
-									<controls:KbButton 
+                                    <controls:KbButton 
+										Visibility="{x:Static app:AppStatic.IsDevModeVisible}"
 										Margin="2 0"
 										Command="{Binding Data.RemoveFileWriter, Source={StaticResource proxy}}" 
 										CommandParameter="{Binding}"
@@ -432,7 +436,7 @@
 					StaysOpen="False"></Popup>
 			</Grid>
 		</WrapPanel>
-		<WrapPanel Margin="0 2" Visibility="{x:Static app:AppStatic.IsDevModeVisible}">
+		<WrapPanel Margin="0 2">
 			<TextBlock Style="{StaticResource LblTb}" VerticalAlignment="Top" Text="命令片段书写器"></TextBlock>
 			<Grid>
 				<DataGrid 
@@ -448,7 +452,8 @@
 						<DataGridTemplateColumn Width="32" IsReadOnly="True">
 							<DataGridTemplateColumn.CellTemplate>
 								<DataTemplate>
-									<controls:KbButton 
+                                    <controls:KbButton 
+										Visibility="{x:Static app:AppStatic.IsDevModeVisible}"
 										Margin="2 0"
 										Command="{Binding Data.RemoveFragmentWriter, Source={StaticResource proxy}}" 
 										CommandParameter="{Binding}"

+ 3 - 3
src/AppViews0/Views/Ucs/InputSegmentEdit.xaml

@@ -56,17 +56,17 @@
         </WrapPanel>
 		<WrapPanel Margin="0 2">
 			<TextBlock Style="{StaticResource LblTb}">名称</TextBlock>
-			<TextBox Width="420" VerticalContentAlignment="Center" Text="{Binding Name, ValidatesOnExceptions=True}">
+			<TextBox Width="420" VerticalContentAlignment="Center" Text="{Binding Name, ValidatesOnExceptions=True}" IsReadOnly="{x:Static app:AppStatic.IsNotDevMode}">
             </TextBox>
         </WrapPanel>
 		<WrapPanel Margin="0 2">
 			<TextBlock Style="{StaticResource LblTb}">片段</TextBlock>
-			<TextBox Width="420" VerticalContentAlignment="Center" Text="{Binding Segment, ValidatesOnExceptions=True}">
+            <TextBox Width="420" VerticalContentAlignment="Center" Text="{Binding Segment, ValidatesOnExceptions=True}" IsReadOnly="{x:Static app:AppStatic.IsNotDevMode}">
 			</TextBox>
 		</WrapPanel>
 		<WrapPanel Margin="0 2">
 			<TextBlock Style="{StaticResource LblTb}">描述</TextBlock>
-			<TextBox Width="420" VerticalContentAlignment="Center" Text="{Binding Description, ValidatesOnExceptions=True}">
+            <TextBox Width="420" VerticalContentAlignment="Center" Text="{Binding Description, ValidatesOnExceptions=True}" IsReadOnly="{x:Static app:AppStatic.IsNotDevMode}">
 			</TextBox>
 		</WrapPanel>
 

+ 1 - 1
src/AppViews0/Views/Ucs/KernelInputEdit.xaml

@@ -50,7 +50,7 @@
 					Text="{Binding Args, Mode=TwoWay}" Height="60">
 				</controls:KbMuiltilineTextBox>
 			</WrapPanel>
-			<GroupBox Margin="10 2">
+            <GroupBox Margin="10 2">
 				<GroupBox.Header>
 					<WrapPanel>
 						<TextBlock>使用指定序号的显卡挖矿</TextBlock>

+ 6 - 1
src/AppViews0/Views/Ucs/MainMenu.xaml

@@ -265,7 +265,12 @@
                     </MenuItem.Icon>
                 </MenuItem>
             </MenuItem>
-			<MenuItem ToolTip="菜单" Visibility="{x:Static app:AppStatic.IsMinerClientVisible}" Width="26" Height="26">
+			<MenuItem 
+                ToolTip="菜单" 
+                Visibility="{x:Static app:AppStatic.IsMinerClientVisible}" 
+                Width="26" Height="26"
+                PreviewMouseDown="MenuItem_PreviewMouseDown"
+                PreviewMouseUp="MenuItem_PreviewMouseUp">
 				<MenuItem.Icon>
 					<Path
 						Width="14"

+ 8 - 0
src/AppViews0/Views/Ucs/MainMenu.xaml.cs

@@ -7,5 +7,13 @@ namespace NTMiner.Views.Ucs {
             this.DataContext = MainMenuViewModel.Instance;
             InitializeComponent();
         }
+
+        private void MenuItem_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) {
+            VirtualRoot.Execute(new TopmostCommand());
+        }
+
+        private void MenuItem_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) {
+            VirtualRoot.Execute(new UnTopmostCommand());
+        }
     }
 }

+ 9 - 3
src/AppViews0/Views/Ucs/MinerProfileDual.xaml

@@ -33,7 +33,9 @@
 					BorderBrush="{StaticResource LightLineColor}"
 					IsEnabled="{Binding ElementName=PopupDualCoin,Path=IsOpen,Converter={StaticResource BoolInvertConverter}}"
 					Background="{Binding IsMining,Converter={StaticResource TrueTransparentElseWhiteConverter}}"
-					Click="KbButtonDualCoin_Clicked">
+					Click="KbButtonDualCoin_Clicked"
+                    PreviewMouseDown="BtnPopup_PreviewMouseDown"
+                    PreviewMouseUp="BtnPopup_PreviewMouseUp">
 					<controls:KbButton.ContextMenu>
 						<ContextMenu>
 							<MenuItem 
@@ -76,7 +78,9 @@
 					BorderBrush="{StaticResource LightLineColor}"
 					IsEnabled="{Binding ElementName=PopupDualCoinPool,Path=IsOpen,Converter={StaticResource BoolInvertConverter}}"
 					Background="{Binding IsMining,Converter={StaticResource TrueTransparentElseWhiteConverter}}"
-					Click="KbButtonDualCoinPool_Clicked">
+					Click="KbButtonDualCoinPool_Clicked"
+                    PreviewMouseDown="BtnPopup_PreviewMouseDown"
+                    PreviewMouseUp="BtnPopup_PreviewMouseUp">
 					<controls:KbButton.ContextMenu>
 						<ContextMenu>
 							<MenuItem Header="添加" Command="{Binding CoinVm.CoinKernel.CoinKernelProfile.SelectedDualCoin.AddPool}">
@@ -123,7 +127,9 @@
 							BorderBrush="{StaticResource LightLineColor}"
 							IsEnabled="{Binding ElementName=PopupDualCoinWallet,Path=IsOpen,Converter={StaticResource BoolInvertConverter}}"
 							Background="{Binding IsMining,Converter={StaticResource TrueTransparentElseWhiteConverter}}"
-							Click="KbButtonDualCoinWallet_Clicked">
+							Click="KbButtonDualCoinWallet_Clicked"
+							PreviewMouseDown="BtnPopup_PreviewMouseDown"
+							PreviewMouseUp="BtnPopup_PreviewMouseUp">
 							<controls:KbButton.ContextMenu>
 								<ContextMenu>
 									<MenuItem Header="添加" Command="{Binding CoinVm.CoinKernel.CoinKernelProfile.SelectedDualCoin.CoinProfile.AddDualCoinWallet}">

+ 8 - 0
src/AppViews0/Views/Ucs/MinerProfileDual.xaml.cs

@@ -196,5 +196,13 @@ namespace NTMiner.Views.Ucs {
         private void ScrollViewer_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) {
             WpfUtil.ScrollViewer_PreviewMouseDown(sender, e);
         }
+
+        private void BtnPopup_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) {
+            VirtualRoot.Execute(new TopmostCommand());
+        }
+
+        private void BtnPopup_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) {
+            VirtualRoot.Execute(new UnTopmostCommand());
+        }
     }
 }

+ 16 - 5
src/AppViews0/Views/Ucs/MinerProfileIndex.xaml

@@ -35,7 +35,9 @@
 					BorderBrush="{StaticResource LightLineColor}"
 					IsEnabled="{Binding ElementName=PopupMainCoin,Path=IsOpen,Converter={StaticResource BoolInvertConverter}}"
 					Background="{Binding MinerProfile.IsMining,Converter={StaticResource TrueTransparentElseWhiteConverter}}"
-					Click="KbButtonMainCoin_Clicked">
+					Click="KbButtonMainCoin_Clicked"
+                    PreviewMouseDown="BtnPopup_PreviewMouseDown"
+                    PreviewMouseUp="BtnPopup_PreviewMouseUp">
 					<controls:KbButton.ContextMenu>
 						<ContextMenu>
 							<MenuItem 
@@ -77,7 +79,9 @@
 					BorderBrush="{StaticResource LightLineColor}"
 					IsEnabled="{Binding ElementName=PopupKernel,Path=IsOpen,Converter={StaticResource BoolInvertConverter}}"
 					Background="{Binding MinerProfile.IsMining,Converter={StaticResource TrueTransparentElseWhiteConverter}}"
-					Click="KbButtonKernel_Clicked">
+					Click="KbButtonKernel_Clicked"
+                    PreviewMouseDown="BtnPopup_PreviewMouseDown"
+                    PreviewMouseUp="BtnPopup_PreviewMouseUp">
 					<controls:KbButton.ContextMenu>
 						<ContextMenu>
 							<MenuItem Header="编辑" Command="{Binding MinerProfile.CoinVm.CoinKernel.Edit}">
@@ -116,7 +120,9 @@
 					BorderBrush="{StaticResource LightLineColor}"
 					IsEnabled="{Binding ElementName=PopupMainCoinPool,Path=IsOpen,Converter={StaticResource BoolInvertConverter}}"
 					Background="{Binding MinerProfile.IsMining,Converter={StaticResource TrueTransparentElseWhiteConverter}}"
-					Click="KbButtonMainCoinPool_Clicked">
+					Click="KbButtonMainCoinPool_Clicked"
+                    PreviewMouseDown="BtnPopup_PreviewMouseDown"
+                    PreviewMouseUp="BtnPopup_PreviewMouseUp">
 					<controls:KbButton.ContextMenu>
 						<ContextMenu>
 							<MenuItem Header="添加" Command="{Binding MinerProfile.CoinVm.AddPool}">
@@ -158,7 +164,9 @@
 						    BorderBrush="{StaticResource LightLineColor}"
 						    IsEnabled="{Binding ElementName=PopupMainCoinPool1,Path=IsOpen,Converter={StaticResource BoolInvertConverter}}"
 						    Background="{Binding MinerProfile.IsMining,Converter={StaticResource TrueTransparentElseWhiteConverter}}"
-						    Click="KbButtonMainCoinPool1_Clicked">
+						    Click="KbButtonMainCoinPool1_Clicked"
+							PreviewMouseDown="BtnPopup_PreviewMouseDown"
+							PreviewMouseUp="BtnPopup_PreviewMouseUp">
                             <controls:KbButton.ContextMenu>
                                 <ContextMenu>
                                     <MenuItem Header="添加" Command="{Binding MinerProfile.CoinVm.AddPool}">
@@ -333,7 +341,9 @@
 						BorderBrush="{StaticResource LightLineColor}"
 						IsEnabled="{Binding ElementName=PopupMainCoinWallet,Path=IsOpen,Converter={StaticResource BoolInvertConverter}}"
 						Background="{Binding MinerProfile.IsMining,Converter={StaticResource TrueTransparentElseWhiteConverter}}"
-						Click="KbButtonMainCoinWallet_Clicked">
+						Click="KbButtonMainCoinWallet_Clicked"
+						PreviewMouseDown="BtnPopup_PreviewMouseDown"
+						PreviewMouseUp="BtnPopup_PreviewMouseUp">
 						<controls:KbButton.ContextMenu>
 							<ContextMenu>
 								<MenuItem Header="添加" Command="{Binding MinerProfile.CoinVm.CoinProfile.AddWallet}">
@@ -430,6 +440,7 @@
 				FocusVisualStyle="{x:Null}"
 				VerticalAlignment="Center"
 				Content="启用双挖"
+                ToolTip="不建议双挖,双挖收益低于单挖。"
 				IsChecked="{Binding MinerProfile.CoinVm.CoinKernel.CoinKernelProfile.IsDualCoinEnabled}" />
             <Border Visibility="{Binding MinerProfile.CoinVm.CoinKernel.Kernel.KernelInputVm.DualWeightArg,Converter={StaticResource NotNullOrEmptyVisibilityConverter}}">
                 <WrapPanel

+ 8 - 1
src/AppViews0/Views/Ucs/MinerProfileIndex.xaml.cs

@@ -2,7 +2,6 @@
 using System.Linq;
 using System.Windows;
 using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
 
 namespace NTMiner.Views.Ucs {
     public partial class MinerProfileIndex : UserControl {
@@ -328,5 +327,13 @@ namespace NTMiner.Views.Ucs {
             UserActionHappend();
             e.Handled = true;
         }
+
+        private void BtnPopup_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) {
+            VirtualRoot.Execute(new TopmostCommand());
+        }
+
+        private void BtnPopup_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) {
+            VirtualRoot.Execute(new UnTopmostCommand());
+        }
     }
 }

+ 9 - 0
src/AppViews0/Views/Ucs/MinerProfileOption.xaml

@@ -238,6 +238,15 @@
                                 <TextBlock VerticalAlignment="Center">有1080/1080ti显卡时启动小药丸加速算力</TextBlock>
                             </CheckBox>
                         </WrapPanel>
+                        <WrapPanel Margin="0 5" Visibility="{x:Static app:AppStatic.IsMinerClientVisible}">
+                            <CheckBox
+                                Width="230"
+								Padding="0"
+								FocusVisualStyle="{x:Null}"
+								IsChecked="{Binding IsAutoReboot}">
+                                <TextBlock VerticalAlignment="Center">Windows蓝屏自动重启</TextBlock>
+                            </CheckBox>
+                        </WrapPanel>
                         <WrapPanel Margin="{StaticResource RowThickness}">
                             <CheckBox
 								Padding="0"

+ 20 - 0
src/AppViews0/Views/Ucs/ServerMessages.xaml

@@ -111,6 +111,26 @@
 					        Text="清空" />
                     </WrapPanel>
                 </controls:KbButton>
+                <controls:KbButton
+                    Height="20"
+                    Margin="4 0 0 0"
+                    Command="{Binding ViewHistory}"
+                    Background="Transparent"
+                    ToolTip="显示历史消息"
+                    Cursor="Hand"
+			        CornerRadius="2">
+                    <WrapPanel>
+                        <Path
+					        Width="12"
+					        Height="12"
+					        Data="{StaticResource Icon_Message}"
+					        Fill="{StaticResource BtnBackground}"
+					        Stretch="Fill" />
+                        <TextBlock
+					        Padding="2 0"
+					        Text="历史" />
+                    </WrapPanel>
+                </controls:KbButton>
             </WrapPanel>
         </Grid>
         <DataGrid 

+ 38 - 2
src/AppViews0/Views/Ucs/SpeedTable.xaml

@@ -46,6 +46,26 @@
 						Stretch="Fill" />
                 </MenuItem.Icon>
             </MenuItem>
+            <MenuItem x:Name="MenuItemShowPCIE" Header="显示PCIE" Visibility="Visible" Padding="4" Click="MenuItemShowPCIE_Click">
+                <MenuItem.Icon>
+                    <Path
+						Width="16"
+						Height="8"
+						Data="{StaticResource Icon_CloseEye}"
+						Fill="{StaticResource BtnBackground}"
+						Stretch="Fill" />
+                </MenuItem.Icon>
+            </MenuItem>
+            <MenuItem x:Name="MenuItemHidePCIE" Header="隐藏PCIE" Padding="4" Visibility="Collapsed" Click="MenuItemHidePCIE_Click">
+                <MenuItem.Icon>
+                    <Path
+						Width="16"
+						Height="12"
+						Data="{StaticResource Icon_OpenEye}"
+						Fill="{StaticResource BtnBackground}"
+						Stretch="Fill" />
+                </MenuItem.Icon>
+            </MenuItem>
         </ContextMenu>
     </UserControl.ContextMenu>
     <Grid>
@@ -53,6 +73,7 @@
             <RowDefinition Height="*"></RowDefinition>
             <RowDefinition Height="Auto"></RowDefinition>
             <RowDefinition Height="Auto"></RowDefinition>
+            <RowDefinition Height="Auto"></RowDefinition>
         </Grid.RowDefinitions>
 		<DataGrid 
             x:Name="DataGrid"
@@ -76,8 +97,22 @@
 							<TextBlock Text="{Binding GpuVm.IndexText}"></TextBlock>
 						</DataTemplate>
 					</DataGridTemplateColumn.CellTemplate>
-				</DataGridTemplateColumn>
-				<DataGridTemplateColumn MinWidth="60" Width="*" IsReadOnly="True">
+                </DataGridTemplateColumn>
+                <DataGridTemplateColumn 
+                    MinWidth="40" Width="40" IsReadOnly="True"
+				    Visibility="{Binding Data.IsPCIEVisible, Source={StaticResource proxy}}">
+                    <DataGridTemplateColumn.HeaderTemplate>
+                        <DataTemplate>
+                            <TextBlock Text="PCIE"></TextBlock>
+                        </DataTemplate>
+                    </DataGridTemplateColumn.HeaderTemplate>
+                    <DataGridTemplateColumn.CellTemplate>
+                        <DataTemplate>
+                            <TextBlock Text="{Binding GpuVm.BusId}"></TextBlock>
+                        </DataTemplate>
+                    </DataGridTemplateColumn.CellTemplate>
+                </DataGridTemplateColumn>
+                <DataGridTemplateColumn MinWidth="60" Width="*" IsReadOnly="True">
 					<DataGridTemplateColumn.Header>
 						<TextBlock Text="名称"></TextBlock>
 					</DataGridTemplateColumn.Header>
@@ -565,5 +600,6 @@
                 </WrapPanel>
             </controls:KbButton>
         </WrapPanel>
+        <TextBlock Grid.Row="3" Padding="4 2" Foreground="Red" Visibility="{x:Static app:AppStatic.IsMixedGpuVisible}">开源不建议N卡A卡混插,若挖矿内核支持混插,算力体现在总算力里。</TextBlock>
     </Grid>
 </UserControl>

+ 21 - 0
src/AppViews0/Views/Ucs/SpeedTable.xaml.cs

@@ -37,6 +37,19 @@ namespace NTMiner.Views.Ucs {
             }
         }
 
+        public void ShowOrHidePCIE(bool isShow) {
+            if (isShow) {
+                this.Vm.IsPCIEVisible = Visibility.Visible;
+                this.MenuItemShowPCIE.Visibility = Visibility.Collapsed;
+                this.MenuItemHidePCIE.Visibility = Visibility.Visible;
+            }
+            else {
+                this.Vm.IsPCIEVisible = Visibility.Collapsed;
+                this.MenuItemShowPCIE.Visibility = Visibility.Visible;
+                this.MenuItemHidePCIE.Visibility = Visibility.Collapsed;
+            }
+        }
+
         private void ItemsControl_MouseDown(object sender, MouseButtonEventArgs e) {
             if (e.LeftButton == MouseButtonState.Pressed) {
                 Window.GetWindow(this).DragMove();
@@ -50,5 +63,13 @@ namespace NTMiner.Views.Ucs {
         private void MenuItemHideOverClock_Click(object sender, RoutedEventArgs e) {
             ShowOrHideOverClock(false);
         }
+
+        private void MenuItemShowPCIE_Click(object sender, RoutedEventArgs e) {
+            ShowOrHidePCIE(true);
+        }
+
+        private void MenuItemHidePCIE_Click(object sender, RoutedEventArgs e) {
+            ShowOrHidePCIE(false);
+        }
     }
 }

+ 1 - 1
src/BlankWindow/GlowWindow.xaml.cs

@@ -160,7 +160,7 @@ namespace NTMiner {
 
         private void Owner_StateChanged(object sender, EventArgs e) {
             Window window = (Window)sender;
-            if (window.WindowState != WindowState.Minimized) {
+            if (window.WindowState == WindowState.Normal) {
                 this.Show();
             }
             else {

+ 7 - 7
src/BlankWindow/Microsoft.Windows.Shell/Standard/DpiHelper.cs

@@ -3,7 +3,7 @@ using System.Windows;
 using System.Windows.Media;
 
 namespace NTMiner.Microsoft.Windows.Shell.Standard {
-    internal static class DpiHelper {
+    public static class DpiHelper {
         private static Matrix _transformToDevice;
         private static Matrix _transformToDip;
 
@@ -28,7 +28,7 @@ namespace NTMiner.Microsoft.Windows.Shell.Standard {
         /// <param name="logicalPoint">A point in the logical coordinate system.</param>
         /// <returns>Returns the parameter converted to the system's coordinates.</returns>
         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
-        public static Point LogicalPixelsToDevice(Point logicalPoint) {
+        internal static Point LogicalPixelsToDevice(Point logicalPoint) {
             return _transformToDevice.Transform(logicalPoint);
         }
 
@@ -38,7 +38,7 @@ namespace NTMiner.Microsoft.Windows.Shell.Standard {
         /// <param name="devicePoint">A point in the physical coordinate system.</param>
         /// <returns>Returns the parameter converted to the device independent coordinate system.</returns>
         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
-        public static Point DevicePixelsToLogical(Point devicePoint) {
+        internal static Point DevicePixelsToLogical(Point devicePoint) {
             return _transformToDip.Transform(devicePoint);
         }
 
@@ -51,7 +51,7 @@ namespace NTMiner.Microsoft.Windows.Shell.Standard {
         }
 
         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
-        public static Rect DeviceRectToLogical(Rect deviceRectangle) {
+        internal static Rect DeviceRectToLogical(Rect deviceRectangle) {
             Point topLeft = DevicePixelsToLogical(new Point(deviceRectangle.Left, deviceRectangle.Top));
             Point bottomRight = DevicePixelsToLogical(new Point(deviceRectangle.Right, deviceRectangle.Bottom));
 
@@ -59,21 +59,21 @@ namespace NTMiner.Microsoft.Windows.Shell.Standard {
         }
 
         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
-        public static Size LogicalSizeToDevice(Size logicalSize) {
+        internal static Size LogicalSizeToDevice(Size logicalSize) {
             Point pt = LogicalPixelsToDevice(new Point(logicalSize.Width, logicalSize.Height));
 
             return new Size { Width = pt.X, Height = pt.Y };
         }
 
         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
-        public static Size DeviceSizeToLogical(Size deviceSize) {
+        internal static Size DeviceSizeToLogical(Size deviceSize) {
             Point pt = DevicePixelsToLogical(new Point(deviceSize.Width, deviceSize.Height));
 
             return new Size(pt.X, pt.Y);
         }
 
         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
-        public static Thickness LogicalThicknessToDevice(Thickness logicalThickness) {
+        internal static Thickness LogicalThicknessToDevice(Thickness logicalThickness) {
             Point topLeft = LogicalPixelsToDevice(new Point(logicalThickness.Left, logicalThickness.Top));
             Point bottomRight = LogicalPixelsToDevice(new Point(logicalThickness.Right, logicalThickness.Bottom));
 

+ 11 - 0
src/MinerClient/Daemon/NTMinerDaemon.exe.config

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <runtime>
+    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+      <dependentAssembly>
+        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
+      </dependentAssembly>
+    </assemblyBinding>
+  </runtime>
+</configuration>

+ 2 - 2
src/MinerClient/MinerClient.csproj

@@ -94,13 +94,13 @@
       <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.dll</HintPath>
     </Reference>
     <Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.20710.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
+      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.30506.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
     </Reference>
     <Reference Include="System.Net.Http.WebRequest, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
       <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.WebRequest.dll</HintPath>
     </Reference>
     <Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.4.0.20710.0\lib\net40\System.Web.Http.dll</HintPath>
+      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.4.0.30506.0\lib\net40\System.Web.Http.dll</HintPath>
     </Reference>
     <Reference Include="System.Web.Http.SelfHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
       <HintPath>..\..\packages\Microsoft.AspNet.WebApi.SelfHost.4.0.30506.0\lib\net40\System.Web.Http.SelfHost.dll</HintPath>

+ 2 - 2
src/MinerClient/packages.config

@@ -4,8 +4,8 @@
   <package id="Fody" version="5.0.0" targetFramework="net40" developmentDependency="true" />
   <package id="LiveCharts" version="0.9.7" targetFramework="net40" />
   <package id="LiveCharts.Wpf" version="0.9.7" targetFramework="net40" />
-  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.20710.0" targetFramework="net40" />
-  <package id="Microsoft.AspNet.WebApi.Core" version="4.0.20710.0" targetFramework="net40" />
+  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.30506.0" targetFramework="net40" />
+  <package id="Microsoft.AspNet.WebApi.Core" version="4.0.30506.0" targetFramework="net40" />
   <package id="Microsoft.AspNet.WebApi.SelfHost" version="4.0.30506.0" targetFramework="net40" />
   <package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net40" />
   <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net40" />

+ 0 - 4
src/MinerClientFinder/Views/MainWindow.xaml.cs

@@ -16,10 +16,6 @@ namespace NTMiner.Views {
             this.DataContext = this.Vm;
             InitializeComponent();
             NotiCenterWindow.Bind(this);
-            this.AddEventPath<LocalIpSetInitedEvent>("本机IP集刷新后刷新状态栏", LogEnum.DevConsole,
-                action: message => {
-                    Vm.RefreshLocalIps();
-                }, location: this.GetType());
             this.AddCmdPath<ShowLocalIpsCommand>(LogEnum.DevConsole, action: message => {
                 UIThread.Execute(() => LocalIpConfig.ShowWindow());
             }, location: this.GetType());

+ 5 - 5
src/MinerClientFinder/Vms/MainWindowViewModel.cs

@@ -72,6 +72,10 @@ namespace NTMiner.Vms {
                     });
                 }
             });
+            VirtualRoot.AddEventPath<LocalIpSetInitedEvent>("本机IP集刷新后刷新状态栏", LogEnum.DevConsole,
+                action: message => {
+                    LocalIps = GetLocalIps();
+                }, location: this.GetType());
             Task.Factory.StartNew(() => {
                 var localIp = VirtualRoot.LocalIpSet.AsEnumerable().FirstOrDefault();
                 if (localIp != null) {
@@ -102,10 +106,6 @@ namespace NTMiner.Vms {
             return sb.ToString();
         }
 
-        public void RefreshLocalIps() {
-            LocalIps = GetLocalIps();
-        }
-
         private void Scan(string[] ipList) {
             if (ipList.Length != 0) {
                 IsScanning = true;
@@ -117,7 +117,7 @@ namespace NTMiner.Vms {
                     return;
                 }
                 IPAddress ipAddress = IPAddress.Parse(ip);
-                IPEndPoint endPoint = new IPEndPoint(ipAddress, 3337);
+                IPEndPoint endPoint = new IPEndPoint(ipAddress, NTKeyword.NTMinerDaemonPort);
                 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                 var state = new ScanArgs(socket, ipList, ip);
                 socket.BeginConnect(endPoint, Callback, state);

+ 2 - 2
src/MinerClientSelfHost/MinerClientSelfHost.csproj

@@ -39,13 +39,13 @@
       <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.dll</HintPath>
     </Reference>
     <Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.20710.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
+      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.30506.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
     </Reference>
     <Reference Include="System.Net.Http.WebRequest, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
       <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.WebRequest.dll</HintPath>
     </Reference>
     <Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.4.0.20710.0\lib\net40\System.Web.Http.dll</HintPath>
+      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.4.0.30506.0\lib\net40\System.Web.Http.dll</HintPath>
     </Reference>
     <Reference Include="System.Web.Http.SelfHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
       <HintPath>..\..\packages\Microsoft.AspNet.WebApi.SelfHost.4.0.30506.0\lib\net40\System.Web.Http.SelfHost.dll</HintPath>

+ 2 - 2
src/MinerClientSelfHost/packages.config

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.20710.0" targetFramework="net40" />
-  <package id="Microsoft.AspNet.WebApi.Core" version="4.0.20710.0" targetFramework="net40" />
+  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.30506.0" targetFramework="net40" />
+  <package id="Microsoft.AspNet.WebApi.Core" version="4.0.30506.0" targetFramework="net40" />
   <package id="Microsoft.AspNet.WebApi.SelfHost" version="4.0.30506.0" targetFramework="net40" />
   <package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net40" />
   <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net40" />

+ 2 - 2
src/MinerStudio/MinerStudio.csproj

@@ -102,13 +102,13 @@
       <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.dll</HintPath>
     </Reference>
     <Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.20710.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
+      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.30506.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
     </Reference>
     <Reference Include="System.Net.Http.WebRequest, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
       <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.WebRequest.dll</HintPath>
     </Reference>
     <Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.4.0.20710.0\lib\net40\System.Web.Http.dll</HintPath>
+      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.4.0.30506.0\lib\net40\System.Web.Http.dll</HintPath>
     </Reference>
     <Reference Include="System.Web.Http.SelfHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
       <HintPath>..\..\packages\Microsoft.AspNet.WebApi.SelfHost.4.0.30506.0\lib\net40\System.Web.Http.SelfHost.dll</HintPath>

+ 2 - 2
src/MinerStudio/packages.config

@@ -4,8 +4,8 @@
   <package id="Fody" version="5.0.0" targetFramework="net40" developmentDependency="true" />
   <package id="LiveCharts" version="0.9.7" targetFramework="net40" />
   <package id="LiveCharts.Wpf" version="0.9.7" targetFramework="net40" />
-  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.20710.0" targetFramework="net40" />
-  <package id="Microsoft.AspNet.WebApi.Core" version="4.0.20710.0" targetFramework="net40" />
+  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.30506.0" targetFramework="net40" />
+  <package id="Microsoft.AspNet.WebApi.Core" version="4.0.30506.0" targetFramework="net40" />
   <package id="Microsoft.AspNet.WebApi.SelfHost" version="4.0.30506.0" targetFramework="net40" />
   <package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net40" />
   <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net40" />

+ 2 - 2
src/MinerStudioSelfHost/MinerStudioSelfHost.csproj

@@ -39,13 +39,13 @@
       <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.dll</HintPath>
     </Reference>
     <Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.20710.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
+      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.30506.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
     </Reference>
     <Reference Include="System.Net.Http.WebRequest, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
       <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.WebRequest.dll</HintPath>
     </Reference>
     <Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.4.0.20710.0\lib\net40\System.Web.Http.dll</HintPath>
+      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.4.0.30506.0\lib\net40\System.Web.Http.dll</HintPath>
     </Reference>
     <Reference Include="System.Web.Http.SelfHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
       <HintPath>..\..\packages\Microsoft.AspNet.WebApi.SelfHost.4.0.30506.0\lib\net40\System.Web.Http.SelfHost.dll</HintPath>

+ 2 - 2
src/MinerStudioSelfHost/packages.config

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.20710.0" targetFramework="net40" />
-  <package id="Microsoft.AspNet.WebApi.Core" version="4.0.20710.0" targetFramework="net40" />
+  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.30506.0" targetFramework="net40" />
+  <package id="Microsoft.AspNet.WebApi.Core" version="4.0.30506.0" targetFramework="net40" />
   <package id="Microsoft.AspNet.WebApi.SelfHost" version="4.0.30506.0" targetFramework="net40" />
   <package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net40" />
   <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net40" />

+ 9 - 0
src/NTMiner.Controllers/IFileUrlController.cs

@@ -14,11 +14,20 @@ namespace NTMiner.Controllers {
         /// 需签名
         /// </summary>
         ResponseBase RemoveNTMinerFile(DataRequest<Guid> request);
+
         string NTMinerUpdaterUrl();
         string MinerClientFinderUrl();
         string LiteDbExplorerUrl();
         string AtikmdagPatcherUrl();
         string SwitchRadeonGpuUrl();
+        /// <summary>
+        /// 基于文件码获取文件的下载地址,文件码必须是白名单中的成员。
+        /// 白名单:NTMinerUpdater,MinerClientFinder,LiteDbExplorer,AtikmdagPatcher,SwitchRadeonGpu
+        /// </summary>
+        /// <param name="fileCode">文件码</param>
+        /// <returns></returns>
+        string ToolFileUrl(string fileCode);
+
         string PackageUrl(PackageUrlRequest request);
     }
 }

+ 0 - 9
src/NTMiner.Controllers/IWsServerNodeController.cs

@@ -12,14 +12,5 @@ namespace NTMiner.Controllers {
         /// </summary>
         DataResponse<string[]> NodeAddresses(object request);
         DataResponse<string> GetNodeAddress(GetWsServerNodeAddressRequest request);
-
-        /// <summary>
-        /// 需签名
-        /// </summary>
-        ResponseBase ReportNodeState(WsServerNodeState state);
-        /// <summary>
-        /// 需签名
-        /// </summary>
-        ResponseBase RemoveNode(DataRequest<string> request);
     }
 }

+ 7 - 6
src/NTMinerClient/Core/Impl/SysDicItemSet.cs

@@ -69,15 +69,16 @@ namespace NTMiner.Core.Impl {
                     if (message == null || message.EntityId == Guid.Empty) {
                         throw new ArgumentNullException();
                     }
-                    if (!_dicById.ContainsKey(message.EntityId)) {
+                    if (!_dicById.TryGetValue(message.EntityId, out SysDicItemData entity) || !_context.SysDicSet.TryGetSysDic(entity.DicId, out ISysDic sysDic)) {
                         return;
                     }
-                    SysDicItemData entity = _dicById[message.EntityId];
+                    bool isKernelBrand = sysDic.Code == NTKeyword.KernelBrandSysDicCode;
+                    bool isPoolBrand = sysDic.Code == NTKeyword.PoolBrandSysDicCode;
+                    bool isAlgo = sysDic.Code == NTKeyword.AlgoSysDicCode;
+                    // TODO:如果是内核品牌、矿池品牌、算法
                     _dicById.Remove(entity.Id);
-                    if (_dicByDicId.ContainsKey(entity.DicId)) {
-                        if (_dicByDicId[entity.DicId].ContainsKey(entity.Code)) {
-                            _dicByDicId[entity.DicId].Remove(entity.Code);
-                        }
+                    if (_dicByDicId.TryGetValue(entity.DicId, out Dictionary<string, SysDicItemData> dicItemDic)) {
+                        dicItemDic.Remove(entity.Code);
                     }
                     var repository = context.CreateCompositeRepository<SysDicItemData>();
                     repository.Remove(entity.Id);

+ 1 - 1
src/NTMinerClient/Core/Kernels/Impl/KernelOutputTranslaterSet.cs

@@ -149,7 +149,7 @@ namespace NTMiner.Core.Kernels.Impl {
                 if (string.IsNullOrEmpty(input) || !_dicByKernelOutputId.TryGetValue(kernelOutputId, out List<KernelOutputTranslaterData> translaters)) {
                     return;
                 }
-                foreach (var consoleTranslater in translaters) {
+                foreach (var consoleTranslater in translaters.ToArray()) {
                     if (isPre && !consoleTranslater.IsPre) {
                         continue;
                     }

+ 2 - 0
src/NTMinerClient/Core/MineContextExtension.cs

@@ -24,6 +24,8 @@ namespace NTMiner.Core {
                 string content = string.Empty;
                 mineContext.FileWriters.TryGetValue(writer.GetId(), out content);
                 if (!string.IsNullOrEmpty(content)) {
+                    // 因为内核日志文件名不是提前确定的而是创建进程前确定的
+                    content = content.Replace(NTKeyword.LogFileParameterName, mineContext.LogFileFullName);
                     string fileFullName = Path.Combine(mineContext.Kernel.GetKernelDirFullName(), writer.FileUrl);
                     File.WriteAllText(fileFullName, content);
                 }

+ 8 - 2
src/NTMinerClient/Gpus/EmptyGpuSet.cs

@@ -41,8 +41,14 @@ namespace NTMiner.Gpus {
 
         public IOverClock OverClock { get; private set; } = new EmptyOverClock();
 
-        public Version DriverVersion {
-            get { return new Version(); }
+        public string DriverVersion {
+            get { return "0.0"; }
+        }
+
+        public bool IsLowDriverVersion {
+            get {
+                return true;
+            }
         }
 
         public void LoadGpuState() {

+ 2 - 1
src/NTMinerClient/Gpus/IGpuSet.cs

@@ -8,7 +8,8 @@ namespace NTMiner.Gpus {
         /// NVIDIA的驱动版本号形如399.24,AMD的驱动版本号形如18.6.1
         /// 都是正常格式的版本号
         /// </summary>
-        Version DriverVersion { get; }
+        string DriverVersion { get; }
+        bool IsLowDriverVersion { get; }
         IOverClock OverClock { get; }
         int Count { get; }
 

+ 15 - 8
src/NTMinerClient/Gpus/Impl/AMDGpuSet.cs

@@ -1,5 +1,4 @@
-using NTMiner.Gpus;
-using System;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
@@ -11,6 +10,7 @@ namespace NTMiner.Gpus.Impl {
                 NTMinerContext.GpuAllId, Gpu.GpuAll
             }
         };
+        private readonly Version _driverVersion = new Version();
 
         public int Count {
             get {
@@ -43,7 +43,7 @@ namespace NTMiner.Gpus.Impl {
                 _gpus.Add(i, gpu);
             }
             if (deviceCount > 0) {
-                this.DriverVersion = adlHelper.GetDriverVersion();
+                this._driverVersion = adlHelper.GetDriverVersion();
                 this.Properties.Add(new GpuSetProperty(GpuSetProperty.DRIVER_VERSION, "驱动版本", DriverVersion));
                 const ulong minG = 5 * NTKeyword.ULongG;
                 bool has470 = _gpus.Any(a => a.Key != NTMinerContext.GpuAllId && a.Value.TotalMemory < minG);
@@ -97,16 +97,13 @@ namespace NTMiner.Gpus.Impl {
             if (gpuIndex == NTMinerContext.GpuAllId) {
                 return;
             }
-            adlHelper.GetPowerFanTemp(gpuIndex, out uint power, out uint fanSpeed, out int temp, out int memoryiVddc);
+            adlHelper.GetPowerFanTemp(gpuIndex, out uint power, out uint fanSpeed, out int temp);
 
             Gpu gpu = _gpus[gpuIndex];
             bool isChanged = gpu.Temperature != temp || gpu.PowerUsage != power || gpu.FanSpeed != fanSpeed;
             gpu.Temperature = temp;
             gpu.PowerUsage = power;
             gpu.FanSpeed = fanSpeed;
-            if (memoryiVddc != 0) {
-                gpu.MemoryVoltage = memoryiVddc;
-            }
 
             if (isChanged) {
                 VirtualRoot.RaiseEvent(new GpuStateChangedEvent(Guid.Empty, gpu));
@@ -119,7 +116,17 @@ namespace NTMiner.Gpus.Impl {
             }
         }
 
-        public Version DriverVersion { get; private set; }
+        public string DriverVersion {
+            get {
+                return _driverVersion.ToString();
+            }
+        }
+
+        public bool IsLowDriverVersion {
+            get {
+                return this._driverVersion < NTMinerContext.Instance.MinAmdDriverVersion;
+            }
+        }
 
         public bool TryGetGpu(int index, out IGpu gpu) {
             var r = _gpus.TryGetValue(index, out Gpu temp);

+ 6 - 6
src/NTMinerClient/Gpus/Impl/EmptyOverClock.cs

@@ -1,27 +1,27 @@
 namespace NTMiner.Gpus.Impl {
     public class EmptyOverClock : IOverClock {
         public void RefreshGpuState(int gpuIndex) {
-            // noting need todo
+            // nothing need todo
         }
 
         public void SetFanSpeed(int gpuIndex, int value) {
-            // noting need todo
+            // nothing need todo
         }
 
         public void SetTempLimit(int gpuIndex, int value) {
-            // noting need todo
+            // nothing need todo
         }
 
         public void SetCoreClock(int gpuIndex, int value, int voltage) {
-            // noting need todo
+            // nothing need todo
         }
 
         public void SetMemoryClock(int gpuIndex, int value, int voltage) {
-            // noting need todo
+            // nothing need todo
         }
 
         public void SetPowerLimit(int gpuIndex, int value) {
-            // noting need todo
+            // nothing need todo
         }
 
         public void Restore() {

+ 1 - 2
src/NTMinerClient/Gpus/Impl/GpuOverClock.cs

@@ -1,5 +1,4 @@
-using NTMiner.Gpus;
-using System;
+using System;
 
 namespace NTMiner.Gpus.Impl {
     public class GpuOverClock : IOverClock {

+ 1 - 1
src/NTMinerClient/Gpus/Impl/GpusSpeed.cs

@@ -185,7 +185,7 @@ namespace NTMiner.Gpus.Impl {
                 }
             }
             bool isChanged = false;
-            // 如果变化幅度大于等于百分之一或者距离上一次算力记录的时间超过了10钟则视为算力变化
+            // 如果变化幅度大于等于百分之一或者距离上一次算力记录的时间超过了10钟则视为算力变化
             if (isDual) {
                 isChanged = gpuSpeed.DualCoinSpeed.SpeedOn.AddSeconds(10) < now || gpuSpeed.DualCoinSpeed.Value.IsChange(speed, 0.01);
                 if (isChanged) {

+ 16 - 6
src/NTMinerClient/Gpus/Impl/NVIDIAGpuSet.cs

@@ -1,5 +1,4 @@
-using NTMiner.Gpus;
-using System;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
@@ -9,8 +8,7 @@ namespace NTMiner.Gpus.Impl {
         private readonly Dictionary<int, Gpu> _gpus = new Dictionary<int, Gpu>() {
             [NTMinerContext.GpuAllId] = Gpu.GpuAll
         };
-
-        private readonly Version _driverVersion;
+        private readonly Version _driverVersion = new Version();
 
         public int Count {
             get {
@@ -95,8 +93,20 @@ namespace NTMiner.Gpus.Impl {
             }
         }
 
-        public Version DriverVersion {
-            get { return _driverVersion; }
+        public string DriverVersion {
+            get {
+                var cudaVersion = this.Properties.FirstOrDefault(a => a.Code == NTKeyword.CudaVersionSysDicCode);
+                if (cudaVersion != null) {
+                    return $"{this._driverVersion.ToString()} {cudaVersion.Value}";
+                }
+                return this._driverVersion.ToString();
+            }
+        }
+
+        public bool IsLowDriverVersion {
+            get {
+                return this._driverVersion < NTMinerContext.Instance.MinNvidiaDriverVersion;
+            }
         }
 
         public bool TryGetGpu(int index, out IGpu gpu) {

+ 4 - 0
src/NTMinerClient/INTMinerContext.cs

@@ -62,6 +62,10 @@ namespace NTMiner {
         IKernelOutputKeywordSet KernelOutputKeywordSet { get; }
         IServerMessageSet ServerMessageSet { get; }
 
+        Version MinNvidiaDriverVersion { get; }
+
+        Version MinAmdDriverVersion { get; }
+
         void ExportServerVersionJson(string jsonFileFullName);
         void ExportWorkJson(MineWorkData mineWorkData, out string localJson, out string serverJson);
     }

+ 10 - 0
src/NTMinerClient/Messages.cs

@@ -243,6 +243,16 @@ namespace NTMiner {
         public bool On { get; private set; }
     }
 
+    /// <summary>
+    /// 挖矿端主界面下面有一层原版控制台窗口,当点击主界面上的menu下拉列表或者popup时下面
+    /// 的层可能跑到上面来,配合使用这对TopMostCommand和UnTopMostCommand可以解决这个问题。
+    /// </summary>
+    [MessageType(description: "设置主界面的Topmost")]
+    public class TopmostCommand : Cmd {
+        public TopmostCommand() {
+        }
+    }
+
     [MessageType(description: "取消主界面的Topmost")]
     public class UnTopmostCommand : Cmd {
         public UnTopmostCommand() {

+ 15 - 3
src/NTMinerClient/Mine/MineContext.cs

@@ -54,7 +54,18 @@ namespace NTMiner.Mine {
 
         private void NewLogFileName() {
             string logFileName;
-            if (this.CommandLine.IgnoreCaseContains(NTKeyword.LogFileParameterName)) {
+            bool isLogFileProcess = this.CommandLine.IgnoreCaseContains(NTKeyword.LogFileParameterName);
+            if (!isLogFileProcess && this.CoinKernel.FileWriterIds.Count != 0) {
+                foreach (var fileWriterId in this.CoinKernel.FileWriterIds) {
+                    if (NTMinerContext.Instance.ServerContext.FileWriterSet.TryGetFileWriter(fileWriterId, out IFileWriter fileWriter)) {
+                        if (fileWriter.Body.Contains(NTKeyword.LogFileParameterName)) {
+                            isLogFileProcess = true;
+                            break;
+                        }
+                    }
+                }
+            }
+            if (isLogFileProcess) {
                 this.KernelProcessType = KernelProcessType.Logfile;
                 logFileName = $"{this.Kernel.Code}_{DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss_fff")}.log";
             }
@@ -302,7 +313,7 @@ namespace NTMiner.Mine {
             ProcessStartInfo startInfo = new ProcessStartInfo(kernelExeFileFullName, arguments) {
                 UseShellExecute = false,
                 CreateNoWindow = false,
-                WorkingDirectory = TempPath.TempDirFullName
+                WorkingDirectory = Path.GetDirectoryName(kernelExeFileFullName)// 内核exe所在的目录
             };
             // 追加环境变量
             foreach (var item in this.CoinKernel.EnvironmentVariables) {
@@ -382,7 +393,7 @@ namespace NTMiner.Mine {
                 bInheritHandles: true,
                 dwCreationFlags: NORMAL_PRIORITY_CLASS,
                 lpEnvironment: lpEnvironment,
-                lpCurrentDirectory: Path.GetDirectoryName(kernelExeFileFullName),
+                lpCurrentDirectory: Path.GetDirectoryName(kernelExeFileFullName),// 内核exe所在的目录
                 lpStartupInfo: ref lpStartupInfo,
                 lpProcessInformation: out PROCESS_INFORMATION processInfo)) {
 
@@ -480,6 +491,7 @@ namespace NTMiner.Mine {
                                             VirtualRoot.RaiseEvent(new KernelSelfRestartedEvent());
                                         }
                                     }
+                                    // 挖矿时如果主界面状态栏的数据更新的慢不是程序执行的慢而是挖矿内核将输出刷到磁盘的时间有缓冲
                                     NTMinerContext.Instance.ServerContext.KernelOutputSet.Pick(ref input, this);
                                     var kernelOutputKeywords = NTMinerContext.Instance.KernelOutputKeywordSet.GetKeywords(this.KernelOutput.GetId());
                                     if (kernelOutputKeywords != null && kernelOutputKeywords.Count != 0) {

+ 7 - 2
src/NTMinerClient/NTMinerClient.csproj

@@ -57,6 +57,9 @@
     <Reference Include="LiteDB, Version=4.1.4.0, Culture=neutral, PublicKeyToken=4ee40123013c9f27, processorArchitecture=MSIL">
       <HintPath>..\..\packages\LiteDB.4.1.4\lib\net40\LiteDB.dll</HintPath>
     </Reference>
+    <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+      <HintPath>..\..\packages\Newtonsoft.Json.12.0.3\lib\net40\Newtonsoft.Json.dll</HintPath>
+    </Reference>
     <Reference Include="OpenHardwareMonitorLib">
       <HintPath>..\ThirdPartyDlls\OpenHardwareMonitorLib.dll</HintPath>
     </Reference>
@@ -66,14 +69,14 @@
       <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.dll</HintPath>
     </Reference>
     <Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.20710.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
+      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.30506.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
     </Reference>
     <Reference Include="System.Net.Http.WebRequest, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
       <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.WebRequest.dll</HintPath>
     </Reference>
     <Reference Include="System.ServiceProcess" />
     <Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.4.0.20710.0\lib\net40\System.Web.Http.dll</HintPath>
+      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.4.0.30506.0\lib\net40\System.Web.Http.dll</HintPath>
     </Reference>
     <Reference Include="System.Web.Http.SelfHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
       <HintPath>..\..\packages\Microsoft.AspNet.WebApi.SelfHost.4.0.30506.0\lib\net40\System.Web.Http.SelfHost.dll</HintPath>
@@ -220,7 +223,9 @@
     <Compile Include="StopMineReason.cs" />
     <Compile Include="Core\MinerStudio\Impl\UserAppSettingSet.cs" />
     <Compile Include="Core\MinerStudio\IUserAppSettingSet.cs" />
+    <Compile Include="SysDicItemSetExtension.cs" />
     <Compile Include="Windows\BcdEdit.cs" />
+    <Compile Include="Windows\Crash.cs" />
     <Compile Include="Windows\Defender.cs" />
     <Compile Include="Windows\Error.cs" />
     <Compile Include="Windows\Power.cs" />

+ 18 - 1
src/NTMinerClient/NTMinerContext.cs

@@ -126,7 +126,6 @@ namespace NTMiner {
             NTMinerRegistry.SetCurrentVersionTag(ClientAppType.AppType, EntryAssemblyInfo.CurrentVersionTag);
 
             if (ClientAppType.IsMinerClient) {
-                VirtualRoot.LocalIpSet.InitOnece();
                 Link();
                 // 当显卡温度变更时守卫温度防线
                 TempGruarder.Instance.Init(this);
@@ -658,6 +657,9 @@ namespace NTMiner {
         private static bool IsNCard {
             get {
                 try {
+                    if (CommandLineArgs.Args.Contains("--amd")) {
+                        return false;
+                    }
                     using (var mos = new ManagementObjectSearcher("SELECT Caption FROM Win32_VideoController")) {
                         foreach (ManagementBaseObject item in mos.Get()) {
                             foreach (var property in item.Properties) {
@@ -688,6 +690,9 @@ namespace NTMiner {
                                 try {
                                     if (IsNCard) {
                                         _gpuSet = new NVIDIAGpuSet(this);
+                                        if (AdlHelper.IsHasATIGpu) {
+                                            VirtualRoot.ThisLocalWarn(this.GetType().Name, "检测到本机除了N卡外还插有A卡,开源不建议N卡A卡混插。", toConsole: true);
+                                        }
                                     }
                                     else {
                                         _gpuSet = new AMDGpuSet();
@@ -734,5 +739,17 @@ namespace NTMiner {
         public ILocalMessageSet LocalMessageSet { get; private set; }
 
         public IServerMessageSet ServerMessageSet { get; private set; }
+
+        public Version MinAmdDriverVersion {
+            get {
+                return ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "MinAmdDriverVersion", new Version(17, 10, 2, 0));
+            }
+        }
+
+        public Version MinNvidiaDriverVersion {
+            get {
+                return ServerContext.SysDicItemSet.TryGetDicItemValue(NTKeyword.ThisSystemSysDicCode, "MinNvidiaDriverVersion", new Version(399, 24));
+            }
+        }
     }
 }

+ 6 - 1
src/NTMinerClient/NTMinerContext.partials.CreateMineContext.cs

@@ -308,6 +308,7 @@ namespace NTMiner {
         }
 
         private static readonly Dictionary<Guid, ParameterNames> _parameterNameDic = new Dictionary<Guid, ParameterNames>();
+        private static readonly string logfile = NTKeyword.LogFileParameterName.TrimStart('{').TrimEnd('}');
         private static ParameterNames GetParameterNames(IFragmentWriter writer) {
             if (string.IsNullOrEmpty(writer.Body)) {
                 return new ParameterNames {
@@ -336,7 +337,11 @@ namespace NTMiner {
                     const string pattern = @"\{(\w+)\}";
                     var matches = Regex.Matches(writer.Body, pattern);
                     foreach (Match match in matches) {
-                        parameterNames.Names.Add(match.Groups[1].Value);
+                        string v = match.Groups[1].Value;
+                        // 因为logfile在开始挖矿后才有值
+                        if (v != logfile) {
+                            parameterNames.Names.Add(v);
+                        }
                     }
                     return parameterNames;
                 }

+ 1 - 1
src/NTMinerClient/Report/ReportDataProvider.cs

@@ -92,7 +92,7 @@ namespace NTMiner.Report {
                 Kernel = string.Empty,
                 MainCoinPool = string.Empty,
                 OSName = Windows.OS.Instance.WindowsEdition,
-                GpuDriver = root.GpuSet.DriverVersion.ToString(),
+                GpuDriver = root.GpuSet.DriverVersion,
                 GpuType = root.GpuSet.GpuType,
                 OSVirtualMemoryMb = VirtualRoot.DriveSet.OSVirtualMemoryMb,
                 TotalPhysicalMemoryMb = (int)(Windows.Ram.Instance.TotalPhysicalMemory / NTKeyword.IntM),

+ 36 - 0
src/NTMinerClient/SysDicItemSetExtension.cs

@@ -0,0 +1,36 @@
+using NTMiner.Core;
+using System;
+
+namespace NTMiner {
+    public static class SysDicItemSetExtension {
+        public static string TryGetDicItemValue(this ISysDicItemSet sysDicItemSet, string dicCode, string dicItemCode, string defaultValue) {
+            if (sysDicItemSet.TryGetDicItem(dicCode, dicItemCode, out ISysDicItem dicItem)) {
+                return dicItem.Value;
+            }
+            return defaultValue;
+        }
+
+        public static string TryGetDicItemDescription(this ISysDicItemSet sysDicItemSet, string dicCode, string dicItemCode, string defaultValue) {
+            if (sysDicItemSet.TryGetDicItem(dicCode, dicItemCode, out ISysDicItem dicItem)) {
+                return dicItem.Description;
+            }
+            return defaultValue;
+        }
+
+        public static double TryGetDicItemValue(this ISysDicItemSet sysDicItemSet, string dicCode, string dicItemCode, double defaultValue) {
+            if (sysDicItemSet.TryGetDicItem(dicCode, dicItemCode, out ISysDicItem dicItem) && double.TryParse(dicItem.Value, out double value)) {
+                return value;
+            }
+            return defaultValue;
+        }
+
+        public static Version TryGetDicItemValue(this ISysDicItemSet sysDicItemSet, string dicCode, string dicItemCode, Version defaultValue) {
+            if (sysDicItemSet.TryGetDicItem(dicCode, dicItemCode, out ISysDicItem dicItem)) {
+                if (Version.TryParse(dicItem.Value, out Version version)) {
+                    return version;
+                }
+            }
+            return defaultValue;
+        }
+    }
+}

+ 30 - 0
src/NTMinerClient/Windows/Crash.cs

@@ -0,0 +1,30 @@
+using Microsoft.Win32;
+using System;
+
+namespace NTMiner.Windows {
+    public static class Crash {
+        public static void SetAutoReboot(bool autoReboot) {
+            int value = autoReboot ? 1 : 0;
+            try {
+                const string subKey = @"SYSTEM\CurrentControlSet\Control\CrashControl";
+                WinRegistry.SetValue(Registry.LocalMachine, subKey, "AutoReboot", value);
+                Logger.OkDebugLine($"{(autoReboot ? "启用" : "禁用")}蓝屏自动重启成功");
+            }
+            catch (Exception e) {
+                Logger.ErrorDebugLine("蓝屏自动重启设置失败,因为异常", e);
+            }
+        }
+
+        public static bool GetAutoReboot() {
+            try {
+                const string subKey = @"SYSTEM\CurrentControlSet\Control\CrashControl";
+                var v = WinRegistry.GetValue(Registry.LocalMachine, subKey, "AutoReboot");
+                return v != null && v.ToString() == "1";
+            }
+            catch (Exception e) {
+                Logger.ErrorDebugLine("读取蓝屏自动重启设置失败,因为异常", e);
+                return false;
+            }
+        }
+    }
+}

+ 1 - 1
src/NTMinerClient/Windows/Power.cs

@@ -15,7 +15,7 @@ namespace NTMiner.Windows {
         }
 
         public static void PreventSleep() {
-            SetThreadExecutionState(ExecutionFlag.System | ExecutionFlag.Continus);
+            SetThreadExecutionState(ExecutionFlag.System | ExecutionFlag.Display | ExecutionFlag.Continus);
         }
 
         public static void Restart(int delaySeconds = 0) {

+ 3 - 2
src/NTMinerClient/packages.config

@@ -1,9 +1,10 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="LiteDB" version="4.1.4" targetFramework="net40" />
-  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.20710.0" targetFramework="net40" />
-  <package id="Microsoft.AspNet.WebApi.Core" version="4.0.20710.0" targetFramework="net40" />
+  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.30506.0" targetFramework="net40" />
+  <package id="Microsoft.AspNet.WebApi.Core" version="4.0.30506.0" targetFramework="net40" />
   <package id="Microsoft.AspNet.WebApi.SelfHost" version="4.0.30506.0" targetFramework="net40" />
   <package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net40" />
+  <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net40" />
   <package id="SharpZipLib" version="0.86.0" targetFramework="net40" />
 </packages>

+ 5 - 2
src/NTMinerDaemon/NTMinerDaemon.csproj

@@ -66,13 +66,13 @@
       <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.dll</HintPath>
     </Reference>
     <Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.20710.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
+      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.30506.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
     </Reference>
     <Reference Include="System.Net.Http.WebRequest, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
       <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.WebRequest.dll</HintPath>
     </Reference>
     <Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.4.0.20710.0\lib\net40\System.Web.Http.dll</HintPath>
+      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.4.0.30506.0\lib\net40\System.Web.Http.dll</HintPath>
     </Reference>
     <Reference Include="System.Web.Http.SelfHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
       <HintPath>..\..\packages\Microsoft.AspNet.WebApi.SelfHost.4.0.30506.0\lib\net40\System.Web.Http.SelfHost.dll</HintPath>
@@ -94,6 +94,9 @@
     <Compile Include="..\NTMinerClient\Windows\WMI.cs">
       <Link>Windows\WMI.cs</Link>
     </Compile>
+    <Compile Include="..\NTMinerlib\ClientAppType.cs">
+      <Link>ClientAppType.cs</Link>
+    </Compile>
     <Compile Include="..\ntminerlib\cryptography\BigInteger.cs">
       <Link>Cryptography\BigInteger.cs</Link>
     </Compile>

+ 6 - 3
src/NTMinerDaemon/Ws/AbstractWsClient.cs

@@ -2,6 +2,7 @@
 using System;
 using System.Reflection;
 using System.Text;
+using System.Threading.Tasks;
 using WebSocketSharp;
 
 namespace NTMiner.Ws {
@@ -40,9 +41,11 @@ namespace NTMiner.Ws {
                 try {
                     if (_ws != null && _ws.ReadyState == WebSocketState.Open) {
                         // 或者_ws.IsAlive,因为_ws.IsAlive内部也是一个Ping,所以用Ping从而显式化这里有个网络请求
-                        if (!_ws.Ping()) {
-                            _ws.CloseAsync(CloseStatusCode.Away);
-                        }
+                        Task.Factory.StartNew(() => {
+                            if (!_ws.Ping()) {
+                                _ws.CloseAsync(CloseStatusCode.Away);
+                            }
+                        });
                     }
                 }
                 catch (Exception e) {

+ 2 - 2
src/NTMinerDaemon/packages.config

@@ -4,8 +4,8 @@
   <package id="Fody" version="5.0.0" targetFramework="net40" developmentDependency="true" />
   <package id="LiteDB" version="4.1.4" targetFramework="net40" />
   <package id="log4net" version="2.0.8" targetFramework="net40" />
-  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.20710.0" targetFramework="net40" />
-  <package id="Microsoft.AspNet.WebApi.Core" version="4.0.20710.0" targetFramework="net40" />
+  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.30506.0" targetFramework="net40" />
+  <package id="Microsoft.AspNet.WebApi.Core" version="4.0.30506.0" targetFramework="net40" />
   <package id="Microsoft.AspNet.WebApi.SelfHost" version="4.0.30506.0" targetFramework="net40" />
   <package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net40" />
   <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net40" />

+ 6 - 4
src/NTMinerDataSchemas/Core/IKernelOutputTranslater.cs

@@ -1,10 +1,12 @@
 using System;
 
 namespace NTMiner.Core {
-    // 开源矿工最初版本时界面上的内核输出是通过读取内核日志转述到界面上的,
-    // 转述时进行翻译是有意义的。现在不再转述,界面上的内核输出是原版控制
-    // 台窗口,所以这个翻译器一半的功能已经无用了,前译在用。
-    // 前译:通常用于将不标准的算力单位替换为标准算力单位,比如将sol/s替换为H/s
+    /// <summary>
+    /// 开源矿工最初版本时界面上的内核输出是通过读取内核日志转述到界面上的,
+    /// 转述时进行翻译是有意义的。现在不再转述,界面上的内核输出是原版控制
+    /// 台窗口,所以这个翻译器一半的功能已经无用了,前译在用。
+    /// 前译:通常用于将不标准的算力单位替换为标准算力单位,比如将sol/s替换为H/s
+    /// </summary>
     public interface IKernelOutputTranslater : IEntity<Guid> {
         Guid Id { get; }
         Guid KernelOutputId { get; }

+ 2 - 2
src/NTMinerDataSchemas/Core/InputSegment.cs

@@ -11,7 +11,7 @@
         public InputSegment(IInputSegment data) {
             this.TargetGpu = data.TargetGpu;
             this.Name = data.Name;
-            this.Segment = data.Name;
+            this.Segment = data.Segment;
             this.Description = data.Description;
             this.IsDefault = data.IsDefault;
         }
@@ -19,7 +19,7 @@
         public void Update(IInputSegment data) {
             this.TargetGpu = data.TargetGpu;
             this.Name = data.Name;
-            this.Segment = data.Name;
+            this.Segment = data.Segment;
             this.Description = data.Description;
             this.IsDefault = data.IsDefault;
         }

+ 21 - 21
src/NTMinerDataSchemas/Core/MinerServer/ClientData.cs

@@ -37,9 +37,7 @@ namespace NTMiner.Core.MinerServer {
             return new ClientData() {
                 #region
                 Id = data.Id,
-                MineContextId = Guid.Empty,
                 CpuId = data.CpuId,
-                DiskSpaceMb = 0,
                 ClientId = data.ClientId,
                 MACAddress = data.MACAddress,
                 LocalIp = data.LocalIp,
@@ -51,6 +49,14 @@ namespace NTMiner.Core.MinerServer {
                 WorkId = data.WorkId,
                 WindowsLoginName = data.WindowsLoginName,
                 WindowsPassword = data.WindowsPassword,
+                AESPassword = data.AESPassword,
+                AESPasswordOn = data.AESPasswordOn,
+                LoginName = data.LoginName,
+                IsOuterUserEnabled = data.IsOuterUserEnabled,
+                OuterUserId = data.OuterUserId,
+                ReportOuterUserId = data.OuterUserId,
+                MineContextId = Guid.Empty,
+                DiskSpaceMb = 0,
                 MineWorkId = Guid.Empty,
                 MineWorkName = string.Empty,
                 IsAutoBoot = false,
@@ -88,7 +94,7 @@ namespace NTMiner.Core.MinerServer {
                 IsMining = false,
                 BootOn = DateTime.MinValue,
                 MineStartedOn = DateTime.MinValue,
-                MinerActiveOn = DateTime.MinValue,
+                MinerActiveOn = DateTime.Now,
                 MainCoinCode = string.Empty,
                 MainCoinTotalShare = 0,
                 MainCoinRejectShare = 0,
@@ -111,16 +117,10 @@ namespace NTMiner.Core.MinerServer {
                 IsRejectOneGpuShare = false,
                 IsGotOneIncorrectGpuShare = false,
                 KernelSelfRestartCount = 0,
-                LoginName = data.LoginName,
-                IsOuterUserEnabled = data.IsOuterUserEnabled,
-                OuterUserId = data.OuterUserId,
-                ReportOuterUserId = data.OuterUserId,
                 TotalPhysicalMemoryMb = 0,
                 LocalServerMessageTimestamp = Timestamp.UnixBaseTime,
                 NetActiveOn = DateTime.MinValue,
                 IsOnline = false,
-                AESPassword = string.Empty,
-                AESPasswordOn = DateTime.MinValue,
                 IsAutoDisableWindowsFirewall = true,
                 IsDisableAntiSpyware = true,
                 IsDisableUAC = true,
@@ -254,10 +254,10 @@ namespace NTMiner.Core.MinerServer {
         /// 从给定的speedData中提取出主币矿池延时,辅币矿池延时,主币拒绝率,辅币拒绝率。
         /// </summary>
         private static void Extract(
-            ISpeedDto speedDto, 
-            out int mainCoinPoolDelayNumber, 
-            out int dualCoinPoolDelayNumber, 
-            out double mainCoinRejectPercent, 
+            ISpeedDto speedDto,
+            out int mainCoinPoolDelayNumber,
+            out int dualCoinPoolDelayNumber,
+            out double mainCoinRejectPercent,
             out double dualCoinRejectPercent,
             out int diskSpaceMb) {
             #region
@@ -323,10 +323,10 @@ namespace NTMiner.Core.MinerServer {
 
         public static ClientData Create(ISpeedDto speedDto, string minerIp) {
             Extract(
-                speedDto, 
-                out int mainCoinPoolDelayNumber, 
-                out int dualCoinPoolDelayNumber, 
-                out double mainCoinRejectPercent, 
+                speedDto,
+                out int mainCoinPoolDelayNumber,
+                out int dualCoinPoolDelayNumber,
+                out double mainCoinRejectPercent,
                 out double dualCoinRejectPercent,
                 out int diskSpaceMb);
             return new ClientData() {
@@ -703,10 +703,10 @@ namespace NTMiner.Core.MinerServer {
             this.IsDisableUAC = speedDto.IsDisableUAC;
             this.IsDisableWAU = speedDto.IsDisableWAU;
             Extract(
-                speedDto, 
-                out int mainCoinPoolDelayNumber, 
-                out int dualCoinPoolDelayNumber, 
-                out double mainCoinRejectPercent, 
+                speedDto,
+                out int mainCoinPoolDelayNumber,
+                out int dualCoinPoolDelayNumber,
+                out double mainCoinRejectPercent,
                 out double dualCoinRejectPercent,
                 out int diskSpaceMb);
             this.MainCoinPoolDelayNumber = mainCoinPoolDelayNumber;

+ 3 - 3
src/NTMinerDataSchemas/Core/MinerServer/QueryClientsResponse.cs

@@ -4,10 +4,10 @@ namespace NTMiner.Core.MinerServer {
     public class QueryClientsResponse : ResponseBase {
         public QueryClientsResponse() {
             this.Data = new List<ClientData>();
-            this.LatestSnapshots = new List<CoinSnapshotData>();
+            this.LatestSnapshots = new CoinSnapshotData[0];
         }
 
-        public static QueryClientsResponse Ok(List<ClientData> data, int total, List<CoinSnapshotData> latestSnapshots, int totalMiningCount, int totalOnlineCount) {
+        public static QueryClientsResponse Ok(List<ClientData> data, int total, CoinSnapshotData[] latestSnapshots, int totalMiningCount, int totalOnlineCount) {
             return new QueryClientsResponse() {
                 StateCode = 200,
                 ReasonPhrase = "Ok",
@@ -22,7 +22,7 @@ namespace NTMiner.Core.MinerServer {
 
         public List<ClientData> Data { get; set; }
 
-        public List<CoinSnapshotData> LatestSnapshots { get; set; }
+        public CoinSnapshotData[] LatestSnapshots { get; set; }
 
         public int Total { get; set; }
 

+ 2 - 2
src/NTMinerDataSchemas/NTKeyword.cs

@@ -10,8 +10,8 @@ namespace NTMiner {
         public const ulong ULongG = 1024 * 1024 * 1024;
         public const long LongG = 1024 * 1024 * 1024;
 
-        public const string Version = "2.8.2";
-        private const string _build = "2";
+        public const string Version = "2.8.3";
+        private const string _build = "0";
         public const string VersionBuild = Version + "." + _build;
         public const string ManJiTag = "蛮吉";
         public const string ManXiaoManTag = "蛮小满";

+ 26 - 10
src/NTMinerGpus/Gpus/Adl/AdlNativeMethods.cs

@@ -1,4 +1,5 @@
 using System;
+using System.IO;
 using System.Reflection;
 using System.Runtime.InteropServices;
 using System.Text.RegularExpressions;
@@ -49,10 +50,9 @@ namespace NTMiner.Gpus.Adl {
         internal delegate AdlStatus ADL2_OverdriveN_SystemClocksX2_SetDelegate(IntPtr context, int iAdapterIndex, ref ADLODNPerformanceLevelsX2 lpODPerformanceLevels);
         internal delegate AdlStatus ADL2_OverdriveN_CapabilitiesX2_GetDelegate(IntPtr context, int iAdapterIndex, ref ADLODNCapabilitiesX2 lpODCapabilities);
         internal delegate AdlStatus ADL2_Overdrive6_FanSpeed_ResetDelegate(IntPtr context, int iAdapterIndex);
-        internal delegate AdlStatus ADL2_Overdrive8_Current_SettingX2_GetDelegate(IntPtr context, int iAdapterIndex, ref int lpNumberOfFeatures, out IntPtr lppCurrentSettingList);
-        internal delegate AdlStatus ADL2_Overdrive8_Init_SettingX2_GetDelegate(IntPtr context, int iAdapterIndex, out int lpOverdrive8Capabilities, ref int lpNumberOfFeatures, out IntPtr lppInitSettingList);
-        internal delegate AdlStatus ADL2_Overdrive8_Init_Setting_GetDelegate(IntPtr context, int iAdapterIndex, out ADLOD8InitSetting lpInitSetting);
-        internal delegate AdlStatus ADL2_Overdrive8_Setting_SetDelegate(IntPtr context, int iAdapterIndex, ref ADLOD8SetSetting lpSetSetting, out ADLOD8CurrentSetting lpCurrentSetting);
+        internal delegate AdlStatus ADL2_Overdrive8_Current_Setting_GetDelegate(IntPtr context, int iAdapterIndex, ref ADLOD8CurrentSetting lpCurrentSetting);
+        internal delegate AdlStatus ADL2_Overdrive8_Init_Setting_GetDelegate(IntPtr context, int iAdapterIndex, ref ADLOD8InitSetting lpInitSetting);
+        internal delegate AdlStatus ADL2_Overdrive8_Setting_SetDelegate(IntPtr context, int iAdapterIndex, ref ADLOD8SetSetting lpSetSetting, ref ADLOD8CurrentSetting lpCurrentSetting);
 
         // 以下属性要求必须是外部可见的static,不能是private的
         // 注意属性名是EnterPoint,不要改名
@@ -129,27 +129,43 @@ namespace NTMiner.Gpus.Adl {
         [Adl]
         internal static ADL2_Overdrive6_FanSpeed_ResetDelegate ADL2_Overdrive6_FanSpeed_Reset { get; private set; }
         [Adl]
-        internal static ADL2_Overdrive8_Current_SettingX2_GetDelegate ADL2_Overdrive8_Current_SettingX2_Get { get; private set; }
-        [Adl]
-        internal static ADL2_Overdrive8_Init_SettingX2_GetDelegate ADL2_Overdrive8_Init_SettingX2_Get { get; private set; }
+        internal static ADL2_Overdrive8_Current_Setting_GetDelegate ADL2_Overdrive8_Current_Setting_Get { get; private set; }
         [Adl]
         internal static ADL2_Overdrive8_Init_Setting_GetDelegate ADL2_Overdrive8_Init_Setting_Get { get; private set; }
         [Adl]
         internal static ADL2_Overdrive8_Setting_SetDelegate ADL2_Overdrive8_Setting_Set { get; private set; }
 
         internal static AdlStatus ADLMainControlCreate(out IntPtr context) {
-            AdlStatus r;
+            context = IntPtr.Zero;
+            string path1 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "atiadlxx.dll");
+            string path2 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "atiadlxy.dll");
+            string path3 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.SystemX86), "atiadlxx.dll");
+            string path4 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.SystemX86), "atiadlxy.dll");
+            if (!File.Exists(path1) && !File.Exists(path2) && !File.Exists(path3) && !File.Exists(path4)) {
+                return AdlStatus.ADL_ERR;
+            }
+            AdlStatus r = AdlStatus.ADL_ERR;
             string dllName = "atiadlxx.dll";
             try {
                 CreateDelegates(dllName);
-                r = ADL_Main_Control_Create(Marshal.AllocHGlobal, 1);
+                if (ADL_Main_Control_Create != null) {
+                    r = ADL_Main_Control_Create(Marshal.AllocHGlobal, 1);
+                }
+                else {
+                    return AdlStatus.ADL_ERR;
+                }
             }
             catch(Exception e) {
                 Logger.ErrorDebugLine(e);
                 try {
                     dllName = "atiadlxy.dll";
                     CreateDelegates(dllName);
-                    r = ADL_Main_Control_Create(Marshal.AllocHGlobal, 1);
+                    if (ADL_Main_Control_Create != null) {
+                        r = ADL_Main_Control_Create(Marshal.AllocHGlobal, 1);
+                    }
+                    else {
+                        return AdlStatus.ADL_ERR;
+                    }
                 }
                 catch(Exception ex) {
                     Logger.ErrorDebugLine(ex);

+ 1 - 43
src/NTMinerGpus/Gpus/Adl/AdlTypes.cs

@@ -1,5 +1,4 @@
 using System.Runtime.InteropServices;
-using System.Text;
 
 namespace NTMiner.Gpus.Adl {
     public enum AdlStatus {
@@ -190,7 +189,7 @@ namespace NTMiner.Gpus.Adl {
 
     [StructLayout(LayoutKind.Sequential)]
     internal struct ADLSingleSensorData {
-        public bool Supported;
+        public int Supported;
         public int Value;
 
         public override string ToString() {
@@ -456,45 +455,6 @@ namespace NTMiner.Gpus.Adl {
         }
     }
 
-    [StructLayout(LayoutKind.Sequential)]
-    internal struct Odn8PStateSettings {
-        public int Clock;
-        public int Voltage;
-
-        public override string ToString() {
-            return VirtualRoot.JsonSerializer.Serialize(this);
-        }
-    }
-
-    [StructLayout(LayoutKind.Sequential)]
-    internal struct Odn8Settings {
-        public int GpuMax;
-        public int GpuMin;
-        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
-        public Odn8PStateSettings[] GpuP;
-        public int MemMax;
-        public int PowerTarget;
-        public int FanMin;
-        public int FanAcoustic;
-        public int FanTarget;
-        public int PowerTemp;
-        public ADLODNExtSettings ExtSettings;
-
-        public static Odn8Settings Create() {
-            var r = new Odn8Settings {
-                ExtSettings = ADLODNExtSettings.Create(),
-                GpuP = new Odn8PStateSettings[3]
-            };
-            for (int i = 0; i < r.GpuP.Length; i++) {
-                r.GpuP[i] = new Odn8PStateSettings();
-            }
-            return r;
-        }
-
-        public override string ToString() {
-            return VirtualRoot.JsonSerializer.Serialize(this);
-        }
-    }
     //OD8 Capability features bits
     enum ADLOD8FeatureControl {
         ADL_OD8_GFXCLK_LIMITS = 1 << 0,
@@ -545,8 +505,6 @@ namespace NTMiner.Gpus.Adl {
         OD8_FAN_CURVE_SPEED_4,
         OD8_FAN_CURVE_TEMPERATURE_5,
         OD8_FAN_CURVE_SPEED_5,
-        OD8_WS_FAN_AUTO_FAN_ACOUSTIC_LIMIT,
-        OD8_POWER_GAUGE, //Starting from this is new features with new capabilities and new interface for limits.
         OD8_COUNT
     }
 

+ 215 - 259
src/NTMinerGpus/Gpus/AdlHelper.cs

@@ -2,206 +2,223 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Runtime.InteropServices;
 
 namespace NTMiner.Gpus {
     public class AdlHelper : IGpuHelper {
-        public AdlHelper() {
-            Init();
-        }
+        private static IntPtr _context = IntPtr.Zero;
+        private static readonly ADLAdapterInfo[] _adapterInfoes = new ADLAdapterInfo[0];
 
-        private IntPtr _context = IntPtr.Zero;
-        private List<ATIGPU> _gpuNames = new List<ATIGPU>();
-        private bool Init() {
+        private static readonly bool _isHasATIGpu = false;
+        static AdlHelper() {
             try {
+                int numberOfAdapters = 0;
                 var adlStatus = AdlNativeMethods.ADLMainControlCreate(out _context);
                 if (adlStatus >= AdlStatus.ADL_OK) {
-                    int numberOfAdapters = 0;
                     adlStatus = AdlNativeMethods.ADL_Adapter_NumberOfAdapters_Get(ref numberOfAdapters);
                     if (adlStatus < AdlStatus.ADL_OK) {
                         NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL_Adapter_NumberOfAdapters_Get)} {adlStatus.ToString()}");
                     }
-                    if (numberOfAdapters > 0) {
-                        ADLAdapterInfo[] adapterInfoes = new ADLAdapterInfo[numberOfAdapters];
-                        if (AdlNativeMethods.ADLAdapterAdapterInfoGet(adapterInfoes) >= AdlStatus.ADL_OK) {
-                            for (int i = 0; i < numberOfAdapters; i++) {
-                                var adapterInfo = adapterInfoes[i];
-                                NTMinerConsole.DevDebug(() => adapterInfo.ToString());
-                                if (!string.IsNullOrEmpty(adapterInfo.UDID) && adapterInfo.VendorID == AdlConst.ATI_VENDOR_ID) {
-                                    bool found = false;
-                                    foreach (ATIGPU gpu in _gpuNames) {
-                                        if (gpu.BusNumber == adapterInfo.BusNumber && gpu.DeviceNumber == adapterInfo.DeviceNumber) {
-                                            found = true;
-                                            break;
-                                        }
-                                    }
-                                    if (!found) {
-                                        int adapterIndex = adapterInfo.AdapterIndex;
-                                        int overdriveVersion = 0;
-                                        try {
-                                            if (AdlNativeMethods.ADL_Overdrive_Caps(adapterIndex, out _, out _, out overdriveVersion) != AdlStatus.ADL_OK) {
-                                                overdriveVersion = -1;
-                                            }
-                                        }
-                                        catch (Exception ex) {
-                                            Logger.ErrorDebugLine(ex);
-                                        }
-                                        ADLODNCapabilitiesX2 info = new ADLODNCapabilitiesX2();
-                                        try {
-                                            var r = AdlNativeMethods.ADL2_OverdriveN_CapabilitiesX2_Get(_context, adapterIndex, ref info);
-                                            if (r < AdlStatus.ADL_OK) {
-                                                NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_CapabilitiesX2_Get)} {r.ToString()}");
-                                            }
-                                        }
-                                        catch (Exception ex) {
-                                            Logger.ErrorDebugLine(ex);
-                                        }
-                                        int maxLevels = info.iMaximumNumberOfPerformanceLevels;
-                                        int fanSpeedMin = 0;
-                                        int fanSpeedMax = 0;
-                                        ADLFanSpeedInfo afsi = new ADLFanSpeedInfo();
-                                        try {
-                                            var r = AdlNativeMethods.ADL_Overdrive5_FanSpeedInfo_Get(adapterIndex, 0, ref afsi);
-                                            if (r < AdlStatus.ADL_OK) {
-                                                NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL_Overdrive5_FanSpeedInfo_Get)} {r.ToString()}");
-                                            }
-                                            else {
-                                                fanSpeedMax = afsi.MaxPercent;
-                                                fanSpeedMin = afsi.MinPercent;
-                                            }
-                                        }
-                                        catch (Exception ex) {
-                                            Logger.ErrorDebugLine(ex);
-                                        }
-                                        ADLODNPerformanceLevelsX2 systemClockX2 = ADLODNPerformanceLevelsX2.Create();
-                                        systemClockX2.iNumberOfPerformanceLevels = maxLevels;
-                                        try {
-                                            var r = AdlNativeMethods.ADL2_OverdriveN_SystemClocksX2_Get(_context, adapterIndex, ref systemClockX2);
-                                            if (r < AdlStatus.ADL_OK) {
-                                                NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_SystemClocksX2_Get)} {r.ToString()}");
-                                            }
-                                        }
-                                        catch (Exception ex) {
-                                            Logger.ErrorDebugLine(ex);
-                                        }
-                                        int gpuLevel = 0;
-                                        int memoryLevel = 0;
-                                        for (int j = 0; j < systemClockX2.aLevels.Length; j++) {
-                                            if (systemClockX2.aLevels[j].iEnabled != 0) {
-                                                gpuLevel = j + 1;
-                                            }
-                                        }
-                                        ADLODNPerformanceLevelsX2 memoryClockX2 = ADLODNPerformanceLevelsX2.Create();
-                                        memoryClockX2.iNumberOfPerformanceLevels = maxLevels;
-                                        try {
-                                            var r = AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Get(_context, adapterIndex, ref memoryClockX2);
-                                            if (r < AdlStatus.ADL_OK) {
-                                                NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Get)} {r.ToString()}");
-                                            }
-                                        }
-                                        catch (Exception ex) {
-                                            Logger.ErrorDebugLine(ex);
-                                        }
-                                        for (int j = 0; j < memoryClockX2.aLevels.Length; j++) {
-                                            if (memoryClockX2.aLevels[j].iEnabled != 0) {
-                                                memoryLevel = j + 1;
-                                            }
-                                        }
-                                        int powerMin = info.power.iMin + 100;
-                                        int powerMax = info.power.iMax + 100;
-                                        int powerDefault = info.power.iDefault + 100;
-                                        int voltMin = info.svddcRange.iMin;// 0
-                                        int voltMax = info.svddcRange.iMax;// 0
-                                        int voltDefault = info.svddcRange.iDefault; // 0
-                                        int tempLimitMin = info.powerTuneTemperature.iMin;
-                                        int tempLimitMax = info.powerTuneTemperature.iMax;
-                                        int tempLimitDefault = info.powerTuneTemperature.iDefault;
-                                        int coreClockMin = info.sEngineClockRange.iMin * 10;
-                                        int coreClockMax = info.sEngineClockRange.iMax * 10;
-                                        int memoryClockMin = info.sMemoryClockRange.iMin * 10;
-                                        int memoryClockMax = info.sMemoryClockRange.iMax * 10;
-                                        bool apiSupported = gpuLevel > 0 && memoryLevel > 0;
-                                        ADLOD8InitSetting odInitSetting = ADLOD8InitSetting.Create();
-                                        if (!apiSupported) {
-                                            try {
-                                                var r = AdlNativeMethods.ADL2_Overdrive_Caps(_context, adapterIndex, out int iSupported, out int iEnabled, out int iVersion);
-                                                if (r < AdlStatus.ADL_OK) {
-                                                    NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_Overdrive_Caps)} {r.ToString()}");
-                                                }
-                                                else {
-                                                    if (iVersion == 8) {
-                                                        if (GetOD8InitSetting(adapterIndex, out odInitSetting)) {
-                                                            apiSupported = true;
-                                                            gpuLevel = 3;
-                                                            memoryLevel = 0;
-                                                            maxLevels = 3;
+                }
+                if (numberOfAdapters > 0) {
+                    _adapterInfoes = new ADLAdapterInfo[numberOfAdapters];
+                    adlStatus = AdlNativeMethods.ADLAdapterAdapterInfoGet(_adapterInfoes);
+                    if (adlStatus >= AdlStatus.ADL_OK && _adapterInfoes != null && _adapterInfoes.Length != 0) {
+                        _adapterInfoes = _adapterInfoes.Where(adapterInfo => !string.IsNullOrEmpty(adapterInfo.UDID) && adapterInfo.VendorID == AdlConst.ATI_VENDOR_ID).ToArray();
+                        _isHasATIGpu = _adapterInfoes.Length > 0;
+                    }
+                }
+            }
+            catch (Exception ex) {
+                Logger.ErrorDebugLine(ex);
+            }
+        }
+
+        public static bool IsHasATIGpu {
+            get {
+                return _isHasATIGpu;
+            }
+        }
+
+        public AdlHelper() {
+            Init();
+        }
 
-                                                            powerMin = 0;
-                                                            powerMax = 0;
-                                                            powerDefault = 0;
-                                                            voltMin = 0;
-                                                            voltMax = 0;
-                                                            voltDefault = 0;
-                                                            tempLimitMin = 0;
-                                                            tempLimitMax = 0;
-                                                            tempLimitDefault = 0;
-                                                            coreClockMin = 0;
-                                                            coreClockMax = 0;
-                                                            memoryClockMin = 0;
-                                                            memoryClockMax = 0;
-                                                            if ((odInitSetting.overdrive8Capabilities & (int)ADLOD8FeatureControl.ADL_OD8_GFXCLK_LIMITS) == (int)ADLOD8FeatureControl.ADL_OD8_GFXCLK_LIMITS ||
-                                                                (odInitSetting.overdrive8Capabilities & (int)ADLOD8FeatureControl.ADL_OD8_GFXCLK_CURVE) == (int)ADLOD8FeatureControl.ADL_OD8_GFXCLK_CURVE) {
-                                                                coreClockMin = odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_GFXCLK_FMIN].minValue;
-                                                                coreClockMax = odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_GFXCLK_FMAX].maxValue;
-                                                                memoryClockMax = odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_UCLK_FMAX].maxValue;
-                                                            }
+        private List<ATIGPU> _gpuNames = new List<ATIGPU>();
+        private bool Init() {
+            try {
+                if (_isHasATIGpu) {
+                    foreach (var adapterInfo in _adapterInfoes) {
+                        NTMinerConsole.DevDebug(() => adapterInfo.ToString());
+                        bool found = false;
+                        foreach (ATIGPU gpu in _gpuNames) {
+                            if (gpu.BusNumber == adapterInfo.BusNumber && gpu.DeviceNumber == adapterInfo.DeviceNumber) {
+                                found = true;
+                                break;
+                            }
+                        }
+                        if (!found) {
+                            int adapterIndex = adapterInfo.AdapterIndex;
+                            int overdriveVersion = 0;
+                            try {
+                                if (AdlNativeMethods.ADL_Overdrive_Caps(adapterIndex, out _, out _, out overdriveVersion) != AdlStatus.ADL_OK) {
+                                    overdriveVersion = -1;
+                                }
+                            }
+                            catch (Exception ex) {
+                                Logger.ErrorDebugLine(ex);
+                            }
+                            ADLODNCapabilitiesX2 info = new ADLODNCapabilitiesX2();
+                            try {
+                                var r = AdlNativeMethods.ADL2_OverdriveN_CapabilitiesX2_Get(_context, adapterIndex, ref info);
+                                if (r < AdlStatus.ADL_OK) {
+                                    NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_CapabilitiesX2_Get)} {r.ToString()}");
+                                }
+                            }
+                            catch (Exception ex) {
+                                Logger.ErrorDebugLine(ex);
+                            }
+                            int maxLevels = info.iMaximumNumberOfPerformanceLevels;
+                            int fanSpeedMin = 0;
+                            int fanSpeedMax = 0;
+                            ADLFanSpeedInfo afsi = new ADLFanSpeedInfo();
+                            try {
+                                var r = AdlNativeMethods.ADL_Overdrive5_FanSpeedInfo_Get(adapterIndex, 0, ref afsi);
+                                if (r < AdlStatus.ADL_OK) {
+                                    NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL_Overdrive5_FanSpeedInfo_Get)} {r.ToString()}");
+                                }
+                                else {
+                                    fanSpeedMax = afsi.MaxPercent;
+                                    fanSpeedMin = afsi.MinPercent;
+                                }
+                            }
+                            catch (Exception ex) {
+                                Logger.ErrorDebugLine(ex);
+                            }
+                            ADLODNPerformanceLevelsX2 systemClockX2 = ADLODNPerformanceLevelsX2.Create();
+                            systemClockX2.iNumberOfPerformanceLevels = maxLevels;
+                            try {
+                                var r = AdlNativeMethods.ADL2_OverdriveN_SystemClocksX2_Get(_context, adapterIndex, ref systemClockX2);
+                                if (r < AdlStatus.ADL_OK) {
+                                    NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_SystemClocksX2_Get)} {r.ToString()}");
+                                }
+                            }
+                            catch (Exception ex) {
+                                Logger.ErrorDebugLine(ex);
+                            }
+                            int gpuLevel = 0;
+                            int memoryLevel = 0;
+                            for (int j = 0; j < systemClockX2.aLevels.Length; j++) {
+                                if (systemClockX2.aLevels[j].iEnabled != 0) {
+                                    gpuLevel = j + 1;
+                                }
+                            }
+                            ADLODNPerformanceLevelsX2 memoryClockX2 = ADLODNPerformanceLevelsX2.Create();
+                            memoryClockX2.iNumberOfPerformanceLevels = maxLevels;
+                            try {
+                                var r = AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Get(_context, adapterIndex, ref memoryClockX2);
+                                if (r < AdlStatus.ADL_OK) {
+                                    NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_OverdriveN_MemoryClocksX2_Get)} {r.ToString()}");
+                                }
+                            }
+                            catch (Exception ex) {
+                                Logger.ErrorDebugLine(ex);
+                            }
+                            for (int j = 0; j < memoryClockX2.aLevels.Length; j++) {
+                                if (memoryClockX2.aLevels[j].iEnabled != 0) {
+                                    memoryLevel = j + 1;
+                                }
+                            }
+                            int powerMin = info.power.iMin + 100;
+                            int powerMax = info.power.iMax + 100;
+                            int powerDefault = info.power.iDefault + 100;
+                            int voltMin = info.svddcRange.iMin;// 0
+                            int voltMax = info.svddcRange.iMax;// 0
+                            int voltDefault = info.svddcRange.iDefault; // 0
+                            int tempLimitMin = info.powerTuneTemperature.iMin;
+                            int tempLimitMax = info.powerTuneTemperature.iMax;
+                            int tempLimitDefault = info.powerTuneTemperature.iDefault;
+                            int coreClockMin = info.sEngineClockRange.iMin * 10;
+                            int coreClockMax = info.sEngineClockRange.iMax * 10;
+                            int memoryClockMin = info.sMemoryClockRange.iMin * 10;
+                            int memoryClockMax = info.sMemoryClockRange.iMax * 10;
+                            bool apiSupported = gpuLevel > 0 && memoryLevel > 0;
+                            ADLOD8InitSetting odInitSetting = ADLOD8InitSetting.Create();
+                            if (!apiSupported) {
+                                try {
+                                    if (overdriveVersion == 8) {
+                                        if (GetOD8InitSetting(adapterIndex, out odInitSetting)) {
+                                            apiSupported = true;
+                                            gpuLevel = 3;
+                                            memoryLevel = 0;
+                                            maxLevels = 3;
+
+                                            powerMin = 0;
+                                            powerMax = 0;
+                                            powerDefault = 0;
+                                            voltMin = 0;
+                                            voltMax = 0;
+                                            voltDefault = 0;
+                                            tempLimitMin = 0;
+                                            tempLimitMax = 0;
+                                            tempLimitDefault = 0;
+                                            coreClockMin = 0;
+                                            coreClockMax = 0;
+                                            memoryClockMin = 0;
+                                            memoryClockMax = 0;
+                                            if ((odInitSetting.overdrive8Capabilities & (int)ADLOD8FeatureControl.ADL_OD8_GFXCLK_LIMITS) == (int)ADLOD8FeatureControl.ADL_OD8_GFXCLK_LIMITS ||
+                                                (odInitSetting.overdrive8Capabilities & (int)ADLOD8FeatureControl.ADL_OD8_GFXCLK_CURVE) == (int)ADLOD8FeatureControl.ADL_OD8_GFXCLK_CURVE) {
+                                                coreClockMin = odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_GFXCLK_FMAX].minValue * 1000;
+                                                coreClockMax = odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_GFXCLK_FMAX].maxValue * 1000;
+                                                voltMin = odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_GFXCLK_VOLTAGE3].minValue;
+                                                voltMax = odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_GFXCLK_VOLTAGE3].maxValue;
+                                                powerMin = 100 + odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_POWER_PERCENTAGE].minValue;
+                                                powerMax = 100 + odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_POWER_PERCENTAGE].maxValue;
+                                                memoryClockMin = odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_UCLK_FMAX].minValue * 1000;
+                                                memoryClockMax = odInitSetting.od8SettingTable[(int)ADLOD8SettingId.OD8_UCLK_FMAX].maxValue * 1000;
+                                            }
 #if DEBUG
-                                                            Logger.Debug(odInitSetting.ToString());
+                                            Logger.Debug(odInitSetting.ToString());
 #endif
-                                                        }
-                                                    }
-                                                }
-                                            }
-                                            catch (Exception ex) {
-                                                Logger.ErrorDebugLine(ex);
-                                            }
                                         }
-                                        if (fanSpeedMax <= 0) {
-                                            fanSpeedMax = 100;
-                                        }
-                                        if (powerMax <= 0) {
-                                            powerMax = 100;
-                                        }
-                                        _gpuNames.Add(new ATIGPU {
-                                            AdapterName = adapterInfo.AdapterName.Trim(),
-                                            AdapterIndex = adapterIndex,
-                                            BusNumber = adapterInfo.BusNumber,
-                                            DeviceNumber = adapterInfo.DeviceNumber,
-                                            OverdriveVersion = overdriveVersion,
-                                            MaxLevels = maxLevels,
-                                            ApiSupported = apiSupported,
-                                            GpuLevels = gpuLevel,
-                                            MemoryLevels = memoryLevel,
-                                            CoreClockMin = coreClockMin,
-                                            CoreClockMax = coreClockMax,
-                                            MemoryClockMin = memoryClockMin,
-                                            MemoryClockMax = memoryClockMax,
-                                            PowerMin = powerMin,
-                                            PowerMax = powerMax,
-                                            PowerDefault = powerDefault,
-                                            TempLimitMin = tempLimitMin,
-                                            TempLimitMax = tempLimitMax,
-                                            TempLimitDefault = tempLimitDefault,
-                                            VoltMin = voltMin,
-                                            VoltMax = voltMax,
-                                            VoltDefault = voltDefault,
-                                            FanSpeedMax = fanSpeedMax,
-                                            FanSpeedMin = fanSpeedMin,
-                                            ADLOD8InitSetting = odInitSetting
-                                        });
                                     }
                                 }
+                                catch (Exception ex) {
+                                    Logger.ErrorDebugLine(ex);
+                                }
                             }
+                            if (fanSpeedMax <= 0) {
+                                fanSpeedMax = 100;
+                            }
+                            if (powerMax <= 0) {
+                                powerMax = 100;
+                            }
+                            _gpuNames.Add(new ATIGPU {
+                                AdapterName = adapterInfo.AdapterName.Trim(),
+                                AdapterIndex = adapterIndex,
+                                BusNumber = adapterInfo.BusNumber,
+                                DeviceNumber = adapterInfo.DeviceNumber,
+                                OverdriveVersion = overdriveVersion,
+                                MaxLevels = maxLevels,
+                                ApiSupported = apiSupported,
+                                GpuLevels = gpuLevel,
+                                MemoryLevels = memoryLevel,
+                                CoreClockMin = coreClockMin,
+                                CoreClockMax = coreClockMax,
+                                MemoryClockMin = memoryClockMin,
+                                MemoryClockMax = memoryClockMax,
+                                PowerMin = powerMin,
+                                PowerMax = powerMax,
+                                PowerDefault = powerDefault,
+                                TempLimitMin = tempLimitMin,
+                                TempLimitMax = tempLimitMax,
+                                TempLimitDefault = tempLimitDefault,
+                                VoltMin = voltMin,
+                                VoltMax = voltMax,
+                                VoltDefault = voltDefault,
+                                FanSpeedMax = fanSpeedMax,
+                                FanSpeedMin = fanSpeedMin,
+                                ADLOD8InitSetting = odInitSetting
+                            });
                         }
                     }
                 }
@@ -216,44 +233,12 @@ namespace NTMiner.Gpus {
             return true;
         }
 
-        private bool GetOD8CurrentSetting(int adapterIndex, out Odn8Settings odn8Settings) {
-            odn8Settings = Odn8Settings.Create();
-            try {
-                int lpNumberOfFeatures = (int)ADLOD8SettingId.OD8_COUNT;
-                var r = AdlNativeMethods.ADL2_Overdrive8_Current_SettingX2_Get(_context, adapterIndex, ref lpNumberOfFeatures, out IntPtr lppCurrentSettingList);
-                if (r < AdlStatus.ADL_OK) {
-                    NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_Overdrive8_Current_SettingX2_Get)} {r.ToString()}");
-                }
-                if (lppCurrentSettingList != IntPtr.Zero) {
-                    odn8Settings = (Odn8Settings)Marshal.PtrToStructure(lppCurrentSettingList, typeof(Odn8Settings));
-                    Marshal.FreeHGlobal(lppCurrentSettingList);
-                }
-                return lppCurrentSettingList != IntPtr.Zero;
-            }
-            catch (Exception ex) {
-                Logger.ErrorDebugLine(ex);
-                return false;
-            }
-        }
-
         private bool GetOD8CurrentSetting(int adapterIndex, out ADLOD8CurrentSetting odCurrentSetting) {
             odCurrentSetting = ADLOD8CurrentSetting.Create();
             try {
-                int lpNumberOfFeatures = (int)ADLOD8SettingId.OD8_COUNT;
-                var r = AdlNativeMethods.ADL2_Overdrive8_Current_SettingX2_Get(_context, adapterIndex, ref lpNumberOfFeatures, out IntPtr lppCurrentSettingList);
+                var r = AdlNativeMethods.ADL2_Overdrive8_Current_Setting_Get(_context, adapterIndex, ref odCurrentSetting);
                 if (r < AdlStatus.ADL_OK) {
-                    NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_Overdrive8_Current_SettingX2_Get)} {r.ToString()}");
-                }
-                if (r == AdlStatus.ADL_OK) {
-                    odCurrentSetting.count = lpNumberOfFeatures > (int)ADLOD8SettingId.OD8_COUNT ? (int)ADLOD8SettingId.OD8_COUNT : lpNumberOfFeatures;
-                    int[] settingList = new int[odCurrentSetting.count];
-                    int elementSize = Marshal.SizeOf(typeof(int));
-                    for (int i = 0; i < settingList.Length; i++) {
-                        settingList[i] = (int)Marshal.PtrToStructure((IntPtr)((long)lppCurrentSettingList + i * elementSize), typeof(int));
-                    }
-                    for (int i = 0; i < odCurrentSetting.count; i++) {
-                        odCurrentSetting.Od8SettingTable[i] = settingList[i];
-                    }
+                    NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_Overdrive8_Current_Setting_Get)} {r.ToString()}");
                 }
                 return r == AdlStatus.ADL_OK;
             }
@@ -266,29 +251,9 @@ namespace NTMiner.Gpus {
         private bool GetOD8InitSetting(int adapterIndex, out ADLOD8InitSetting odInitSetting) {
             odInitSetting = ADLOD8InitSetting.Create();
             try {
-                int elementSize = Marshal.SizeOf(typeof(ADLOD8SingleInitSetting));
-                int overdrive8Capabilities;
-                int numberOfFeatures = (int)ADLOD8SettingId.OD8_COUNT;
-                var r = AdlNativeMethods.ADL2_Overdrive8_Init_SettingX2_Get(_context, adapterIndex, out overdrive8Capabilities, ref numberOfFeatures, out IntPtr lpInitSettingList);
+                var r = AdlNativeMethods.ADL2_Overdrive8_Init_Setting_Get(_context, adapterIndex, ref odInitSetting);
                 if (r < AdlStatus.ADL_OK) {
-                    NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_Overdrive8_Init_SettingX2_Get)} {r.ToString()}");
-                }
-                ADLOD8SingleInitSetting[] od8initSettingList = new ADLOD8SingleInitSetting[numberOfFeatures];
-                if (lpInitSettingList != IntPtr.Zero) {
-                    for (int i = 0; i < od8initSettingList.Length; i++) {
-                        od8initSettingList[i] = (ADLOD8SingleInitSetting)Marshal.PtrToStructure((IntPtr)((long)lpInitSettingList + i * elementSize), typeof(ADLOD8SingleInitSetting));
-                    }
-                    Marshal.FreeHGlobal(lpInitSettingList);
-                }
-                if (r == AdlStatus.ADL_OK) {
-                    odInitSetting.count = numberOfFeatures > (int)ADLOD8SettingId.OD8_COUNT ? (int)ADLOD8SettingId.OD8_COUNT : numberOfFeatures;
-                    odInitSetting.overdrive8Capabilities = overdrive8Capabilities;
-                    for (int i = 0; i < odInitSetting.count; i++) {
-                        odInitSetting.od8SettingTable[i].defaultValue = od8initSettingList[i].defaultValue;
-                        odInitSetting.od8SettingTable[i].featureID = od8initSettingList[i].featureID;
-                        odInitSetting.od8SettingTable[i].maxValue = od8initSettingList[i].maxValue;
-                        odInitSetting.od8SettingTable[i].minValue = od8initSettingList[i].minValue;
-                    }
+                    NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_Overdrive8_Init_Setting_Get)} {r.ToString()}");
                 }
 #if DEBUG
                 Logger.Debug($"od8initSettingList={VirtualRoot.JsonSerializer.Serialize(odInitSetting)}");
@@ -443,12 +408,10 @@ namespace NTMiner.Gpus {
                     catch {
                     }
                 }
-                else {
-                    if (GetOD8CurrentSetting(gpu.AdapterIndex, out Odn8Settings odn8Settings)) {
-                        coreClock = odn8Settings.GpuP[2].Clock * 1000;
-                        coreiVddc = odn8Settings.GpuP[2].Voltage;
-                        memoryClock = odn8Settings.MemMax * 1000;
-                    }
+                else if (GetOD8CurrentSetting(gpu.AdapterIndex, out ADLOD8CurrentSetting odCurrentSetting)) {
+                    coreClock = odCurrentSetting.Od8SettingTable[(int)ADLOD8SettingId.OD8_GFXCLK_FMAX] * 1000;
+                    coreiVddc = odCurrentSetting.Od8SettingTable[(int)ADLOD8SettingId.OD8_GFXCLK_VOLTAGE3];
+                    memoryClock = odCurrentSetting.Od8SettingTable[(int)ADLOD8SettingId.OD8_UCLK_FMAX] * 1000;
                 }
             }
             catch (Exception e) {
@@ -457,11 +420,10 @@ namespace NTMiner.Gpus {
         }
 
 
-        public void GetPowerFanTemp(int gpuIndex, out uint power, out uint fanSpeed, out int temp, out int memoryiVddc) {
+        public void GetPowerFanTemp(int gpuIndex, out uint power, out uint fanSpeed, out int temp) {
             power = 0;
             fanSpeed = 0;
             temp = 0;
-            memoryiVddc = 0;
             if (!TryGetAtiGpu(gpuIndex, out ATIGPU gpu)) {
                 return;
             }
@@ -478,21 +440,17 @@ namespace NTMiner.Gpus {
                         NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_New_QueryPMLogData_Get)} {r.ToString()}");
                     }
                     int i = (int)ADLSensorType.PMLOG_ASIC_POWER;
-                    if (i < logDataOutput.Sensors.Length && logDataOutput.Sensors[i].Supported) {
+                    if (i < logDataOutput.Sensors.Length && logDataOutput.Sensors[i].Supported != 0) {
                         power = (uint)logDataOutput.Sensors[i].Value;
                     }
                     i = (int)ADLSensorType.PMLOG_FAN_PERCENTAGE;
-                    if (i < logDataOutput.Sensors.Length && logDataOutput.Sensors[i].Supported) {
+                    if (i < logDataOutput.Sensors.Length && logDataOutput.Sensors[i].Supported != 0) {
                         fanSpeed = (uint)logDataOutput.Sensors[i].Value;
                     }
                     i = (int)ADLSensorType.PMLOG_TEMPERATURE_EDGE;
-                    if (i < logDataOutput.Sensors.Length && logDataOutput.Sensors[i].Supported) {
+                    if (i < logDataOutput.Sensors.Length && logDataOutput.Sensors[i].Supported != 0) {
                         temp = logDataOutput.Sensors[i].Value;
                     }
-                    i = (int)ADLSensorType.PMLOG_MEM_VOLTAGE;
-                    if (i < logDataOutput.Sensors.Length && logDataOutput.Sensors[i].Supported) {
-                        memoryiVddc = logDataOutput.Sensors[i].Value;
-                    }
                 }
             }
             catch {
@@ -592,7 +550,7 @@ namespace NTMiner.Gpus {
                     odSetSetting.od8SettingTable[(int)settingId].reset = reset ? 1 : 0;
                     odSetSetting.od8SettingTable[(int)settingId].value = odInitSetting.od8SettingTable[(int)settingId].defaultValue;
                 }
-                var r = AdlNativeMethods.ADL2_Overdrive8_Setting_Set(_context, adapterIndex, ref odSetSetting, out odCurrentSetting);
+                var r = AdlNativeMethods.ADL2_Overdrive8_Setting_Set(_context, adapterIndex, ref odSetSetting, ref odCurrentSetting);
                 if (r != AdlStatus.ADL_OK) {
                     NTMinerConsole.DevError(() => $"{nameof(AdlNativeMethods.ADL2_Overdrive8_Setting_Set)} {r.ToString()}");
                 }
@@ -782,11 +740,9 @@ namespace NTMiner.Gpus {
                 }
             }
             else {
-                if (GetOD8CurrentSetting(gpu.AdapterIndex, out Odn8Settings odn8Settings)) {
-                    powerLimit = 100 + odn8Settings.PowerTarget;
-                    // 貌似没有tempLimit
-                }
-                else {
+                if (GetOD8CurrentSetting(gpu.AdapterIndex, out ADLOD8CurrentSetting odCurrentSetting)) {
+                    powerLimit = 100 + odCurrentSetting.Od8SettingTable[(int)ADLOD8SettingId.OD8_POWER_PERCENTAGE];
+                    tempLimit = odCurrentSetting.Od8SettingTable[(int)ADLOD8SettingId.OD8_FAN_CURVE_TEMPERATURE_5];
                 }
             }
         }

+ 2 - 1
src/NTMinerGpus/Gpus/NvapiHelper.cs

@@ -306,7 +306,8 @@ namespace NTMiner.Gpus {
                 }
                 return false;
             }
-            catch {
+            catch (Exception e){
+                Logger.ErrorDebugLine(e);
                 return false;
             }
         }

+ 26 - 34
src/NTMinerGpus/Gpus/NvmlHelper.cs

@@ -82,9 +82,7 @@ namespace NTMiner.Gpus {
                     _nvmlDevices.Clear();
                     uint deviceCount = 0;
                     var r = NvmlNativeMethods.nvmlDeviceGetCount(ref deviceCount);
-                    if (r != nvmlReturn.Success) {
-                        NTMinerConsole.DevError(() => $"{nameof(NvmlNativeMethods.nvmlDeviceGetCount)} {r.ToString()}");
-                    }
+                    CheckResult(r, () => $"{nameof(NvmlNativeMethods.nvmlDeviceGetCount)} {r.ToString()}");
                     for (int i = 0; i < deviceCount; i++) {
                         NvGpu gpu = new NvGpu {
                             GpuIndex = i
@@ -92,18 +90,12 @@ namespace NTMiner.Gpus {
                         nvmlDevice nvmlDevice = new nvmlDevice();
                         r = NvmlNativeMethods.nvmlDeviceGetHandleByIndex((uint)i, ref nvmlDevice);
                         _nvmlDevices.Add(nvmlDevice);
-                        if (r != nvmlReturn.Success) {
-                            NTMinerConsole.DevError(() => $"{nameof(NvmlNativeMethods.nvmlDeviceGetHandleByIndex)}({((uint)i).ToString()}) {r.ToString()}");
-                        }
+                        CheckResult(r, () => $"{nameof(NvmlNativeMethods.nvmlDeviceGetHandleByIndex)}({((uint)i).ToString()}) {r.ToString()}");
                         r = NvmlNativeMethods.nvmlDeviceGetName(nvmlDevice, out string name);
-                        if (r != nvmlReturn.Success) {
-                            NTMinerConsole.DevError(() => $"{nameof(NvmlNativeMethods.nvmlDeviceGetName)} {r.ToString()}");
-                        }
+                        CheckResult(r, () => $"{nameof(NvmlNativeMethods.nvmlDeviceGetName)} {r.ToString()}");
                         nvmlMemory memory = new nvmlMemory();
                         r = NvmlNativeMethods.nvmlDeviceGetMemoryInfo(nvmlDevice, ref memory);
-                        if (r != nvmlReturn.Success) {
-                            NTMinerConsole.DevError(() => $"{nameof(NvmlNativeMethods.nvmlDeviceGetMemoryInfo)} {r.ToString()}");
-                        }
+                        CheckResult(r, () => $"{nameof(NvmlNativeMethods.nvmlDeviceGetMemoryInfo)} {r.ToString()}");
                         // short gpu name
                         if (!string.IsNullOrEmpty(name)) {
                             name = name.Replace("GeForce GTX ", string.Empty);
@@ -111,9 +103,7 @@ namespace NTMiner.Gpus {
                         }
                         nvmlPciInfo pci = new nvmlPciInfo();
                         r = NvmlNativeMethods.nvmlDeviceGetPciInfo(nvmlDevice, ref pci);
-                        if (r != nvmlReturn.Success) {
-                            NTMinerConsole.DevError(() => $"{nameof(NvmlNativeMethods.nvmlDeviceGetPciInfo)} {r.ToString()}");
-                        }
+                        CheckResult(r, () => $"{nameof(NvmlNativeMethods.nvmlDeviceGetPciInfo)} {r.ToString()}");
                         gpu.Name = name;
                         gpu.BusId = (int)pci.bus;
                         gpu.TotalMemory = memory.total;
@@ -148,12 +138,10 @@ namespace NTMiner.Gpus {
             try {
                 var r = NvmlNativeMethods.nvmlDeviceGetPowerUsage(nvmlDevice, ref power);
                 power = (uint)(power / 1000.0);
-                if (r != nvmlReturn.Success) {
-                    if (r == nvmlReturn.NotSupported) {
-                        _nvmlDeviceGetPowerUsageNotSupporteds.Add(gpuIndex);
-                    }
-                    NTMinerConsole.DevError(() => $"{nameof(NvmlNativeMethods.nvmlDeviceGetPowerUsage)} {r.ToString()}");
+                if (r == nvmlReturn.NotSupported) {
+                    _nvmlDeviceGetPowerUsageNotSupporteds.Add(gpuIndex);
                 }
+                CheckResult(r, () => $"{nameof(NvmlNativeMethods.nvmlDeviceGetPowerUsage)} {r.ToString()}");
             }
             catch {
             }
@@ -167,9 +155,7 @@ namespace NTMiner.Gpus {
             uint temp = 0;
             try {
                 var r = NvmlNativeMethods.nvmlDeviceGetTemperature(nvmlDevice, nvmlTemperatureSensors.Gpu, ref temp);
-                if (r != nvmlReturn.Success) {
-                    NTMinerConsole.DevError(() => $"{nameof(NvmlNativeMethods.nvmlDeviceGetTemperature)} {r.ToString()}");
-                }
+                CheckResult(r, () => $"{nameof(NvmlNativeMethods.nvmlDeviceGetTemperature)} {r.ToString()}");
             }
             catch {
             }
@@ -187,12 +173,10 @@ namespace NTMiner.Gpus {
             uint fanSpeed = 0;
             try {
                 var r = NvmlNativeMethods.nvmlDeviceGetFanSpeed(nvmlDevice, ref fanSpeed);
-                if (r != nvmlReturn.Success) {
-                    if (r == nvmlReturn.NotSupported) {
-                        _nvmlDeviceGetFanSpeedNotSupporteds.Add(gpuIndex);
-                    }
-                    NTMinerConsole.DevError(() => $"{nameof(NvmlNativeMethods.nvmlDeviceGetFanSpeed)} {r.ToString()}");
+                if (r == nvmlReturn.NotSupported) {
+                    _nvmlDeviceGetFanSpeedNotSupporteds.Add(gpuIndex);
                 }
+                CheckResult(r, () => $"{nameof(NvmlNativeMethods.nvmlDeviceGetFanSpeed)} {r.ToString()}");
             }
             catch {
             }
@@ -207,13 +191,9 @@ namespace NTMiner.Gpus {
             }
             try {
                 var r = NvmlNativeMethods.nvmlSystemGetDriverVersion(out string version);
-                if (r != nvmlReturn.Success) {
-                    NTMinerConsole.DevError(() => $"{nameof(NvmlNativeMethods.nvmlSystemGetDriverVersion)} {r.ToString()}");
-                }
+                CheckResult(r, () => $"{nameof(NvmlNativeMethods.nvmlSystemGetDriverVersion)} {r.ToString()}");
                 r = NvmlNativeMethods.nvmlSystemGetNVMLVersion(out nvmlVersion);
-                if (r != nvmlReturn.Success) {
-                    NTMinerConsole.DevError(() => $"{nameof(NvmlNativeMethods.nvmlSystemGetNVMLVersion)} {r.ToString()}");
-                }
+                CheckResult(r, () => $"{nameof(NvmlNativeMethods.nvmlSystemGetNVMLVersion)} {r.ToString()}");
                 if (!string.IsNullOrEmpty(version) && Version.TryParse(version, out Version v)) {
                     driverVersion = v;
                 }
@@ -224,5 +204,17 @@ namespace NTMiner.Gpus {
             catch {
             }
         }
+
+        private static void CheckResult(nvmlReturn r, string message) {
+            if (r != nvmlReturn.Success) {
+                NTMinerConsole.DevError(message);
+            }
+        }
+
+        private static void CheckResult(nvmlReturn r, Func<string> getMessage) {
+            if (r != nvmlReturn.Success) {
+                NTMinerConsole.DevError(getMessage);
+            }
+        }
     }
 }

+ 10 - 8
src/NTMinerGpus/Gpus/PInvokeDelegateFactory.cs

@@ -35,21 +35,23 @@ namespace NTMiner.Gpus {
             .DefineDynamicAssembly(new AssemblyName("PInvokeDelegateFactoryInternalAssembly"), AssemblyBuilderAccess.Run)
             .DefineDynamicModule("PInvokeDelegateFactoryInternalModule");
 
+        private static readonly object _locker = new object();
         private static readonly IDictionary<Pair<DllImportAttribute, Type>, Type> wrapperTypes = new Dictionary<Pair<DllImportAttribute, Type>, Type>();
 
         public static void CreateDelegate(DllImportAttribute dllImportAttribute, Type delegateType, out object newDelegate) {
             Pair<DllImportAttribute, Type> key = new Pair<DllImportAttribute, Type>(dllImportAttribute, delegateType);
-            wrapperTypes.TryGetValue(key, out Type wrapperType);
+            lock (_locker) {
+                wrapperTypes.TryGetValue(key, out Type wrapperType);
 
-            if (wrapperType == null) {
-                wrapperType = CreateWrapperType(delegateType, dllImportAttribute);
-                wrapperTypes.Add(key, wrapperType);
-            }
+                if (wrapperType == null) {
+                    wrapperType = CreateWrapperType(delegateType, dllImportAttribute);
+                    wrapperTypes.Add(key, wrapperType);
+                }
 
-            newDelegate = Delegate.CreateDelegate(delegateType, wrapperType, dllImportAttribute.EntryPoint);
+                newDelegate = Delegate.CreateDelegate(delegateType, wrapperType, dllImportAttribute.EntryPoint);
+            }
         }
 
-
         private static Type CreateWrapperType(Type delegateType, DllImportAttribute dllImportAttribute) {
             TypeBuilder typeBuilder = moduleBuilder.DefineType("PInvokeDelegateFactoryInternalWrapperType" + wrapperTypes.Count);
 
@@ -63,7 +65,7 @@ namespace NTMiner.Gpus {
                 parameterTypes[i] = parameterInfos[i].ParameterType;
             }
 
-            MethodBuilder methodBuilder = 
+            MethodBuilder methodBuilder =
                 typeBuilder.DefinePInvokeMethod(
                     dllImportAttribute.EntryPoint, dllImportAttribute.Value,
                     MethodAttributes.Public | MethodAttributes.Static |

+ 0 - 16
src/NTMinerLogging/CommandLineArgs.cs

@@ -22,22 +22,6 @@ namespace NTMiner {
             NTMinerFileName = PickArgument("ntminerFileName=");
         }
 
-        /// <summary>
-        /// 返回的日志文件名和应用程序的类型和版本以及启动参数有关系。
-        /// 主要是因为挖矿端应用程序不是单例的,也就是说已经有一个挖矿端程序进程时当挖矿端程序启动时追加了比如upgrade=ntminer2.8.exe参数的话依旧可以启动进程。
-        /// </summary>
-        /// <returns></returns>
-        public static string GetLogFileName() {
-            // 避免不同进程使用相同的日志文件,虽然并不会异常但会看不到日志
-            if (!string.IsNullOrEmpty(Upgrade)) {
-                return $"root{NTKeyword.VersionBuild}_upgrade.log";
-            }
-            else if (!string.IsNullOrEmpty(Action)) {
-                return $"root{NTKeyword.VersionBuild}_{Action}.log";
-            }
-            return $"root{NTKeyword.VersionBuild}.log";
-        }
-
         /// <summary>
         /// 提取格式形如argumentName=argumentValue格式的命令行参数。
         /// 注意:参数名是忽略大小写的,且如果命令行上有重名参数后面的值覆盖前面的值

+ 17 - 1
src/NTMinerLogging/Impl/Log4NetLoggingService.cs

@@ -11,7 +11,7 @@ namespace NTMiner.Impl {
             if (string.IsNullOrEmpty(Logger.DirFullPath)) {
                 throw new InvalidProgramException();
             }
-            string logFile = Path.Combine(Logger.DirFullPath, CommandLineArgs.GetLogFileName());
+            string logFile = Path.Combine(Logger.DirFullPath, GetLogFileName());
             byte[] buffer = System.Text.Encoding.UTF8.GetBytes(
 $@"<log4net>
   <root>
@@ -38,6 +38,22 @@ $@"<log4net>
             _log = LogManager.GetLogger("global");
         }
 
+        /// <summary>
+        /// 返回的日志文件名和应用程序的类型和版本以及启动参数有关系。
+        /// 主要是因为挖矿端应用程序不是单例的,也就是说已经有一个挖矿端程序进程时当挖矿端程序启动时追加了比如upgrade=ntminer2.8.exe参数的话依旧可以启动进程。
+        /// </summary>
+        /// <returns></returns>
+        private static string GetLogFileName() {
+            // 避免不同进程使用相同的日志文件,虽然并不会异常但会看不到日志
+            if (!string.IsNullOrEmpty(CommandLineArgs.Upgrade)) {
+                return $"root{NTKeyword.VersionBuild}_upgrade.log";
+            }
+            else if (!string.IsNullOrEmpty(CommandLineArgs.Action)) {
+                return $"root{NTKeyword.VersionBuild}_{CommandLineArgs.Action}.log";
+            }
+            return $"root{NTKeyword.VersionBuild}.log";
+        }
+
         public void Debug(object message) {
             NTMinerConsole.DevLine(message?.ToString());
             _log.Debug(message);

+ 4 - 1
src/NTMinerNoDevFee/NTMinerNoDevFee.csproj

@@ -60,7 +60,7 @@
       <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.dll</HintPath>
     </Reference>
     <Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.20710.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
+      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.30506.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
     </Reference>
     <Reference Include="System.Net.Http.WebRequest, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
       <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.WebRequest.dll</HintPath>
@@ -121,6 +121,9 @@
     <Compile Include="..\NTMinerDataSchemas\Timestamp.cs">
       <Link>Timestamp.cs</Link>
     </Compile>
+    <Compile Include="..\NTMinerlib\NTMinerException.cs">
+      <Link>NTMinerException.cs</Link>
+    </Compile>
     <Compile Include="..\NTMinerlib\NTMinerRegistry.cs">
       <Link>NTMinerRegistry.cs</Link>
     </Compile>

+ 3 - 3
src/NTMinerNoDevFee/NoDevFee/NoDevFeeUtil.cs

@@ -180,9 +180,9 @@ namespace NTMiner.NoDevFee {
                                         var dstPort = tcpHdr->DstPort;
                                         Buffer.BlockCopy(byteWallet, 0, packet, position, byteWallet.Length);
                                         Logger.InfoDebugLine($"::第 {++counter} 次");
-                                        Logger.InfoDebugLine($"::抽水钱包: {dwallet}");
-                                        Logger.InfoDebugLine($"::替换钱包: {wallet}");
-                                        Logger.InfoDebugLine($"::抽水矿池: {dstIp}:{dstPort.ToString()}");
+                                        Logger.InfoDebugLine($":: {dwallet}");
+                                        Logger.InfoDebugLine($":: {wallet}");
+                                        Logger.InfoDebugLine($":: {dstIp}:{dstPort.ToString()}");
                                     }
                                 }
                             }

+ 1 - 1
src/NTMinerNoDevFee/packages.config

@@ -3,7 +3,7 @@
   <package id="Costura.Fody" version="4.0.0" targetFramework="net40" />
   <package id="Fody" version="5.0.0" targetFramework="net40" developmentDependency="true" />
   <package id="log4net" version="2.0.8" targetFramework="net40" />
-  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.20710.0" targetFramework="net40" />
+  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.30506.0" targetFramework="net40" />
   <package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net40" />
   <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net40" />
 </packages>

+ 8 - 3
src/NTMinerRpcClient/BinaryRequestJsonResponseRpcRoot.cs

@@ -36,9 +36,14 @@ namespace NTMiner {
                         }
                         HttpContent content = new ByteArrayContent(bytes);
                         Task<HttpResponseMessage> getHttpResponse = client.PostAsync(RpcRoot.GetUrl(host, port, controller, action, query), content);
-                        getHttpResponse.Result.Content.ReadAsAsync<TResponse>().ContinueWith(t => {
-                            callback?.Invoke(t.Result, null);
-                        });
+                        if (getHttpResponse.Result.IsSuccessStatusCode) {
+                            getHttpResponse.Result.Content.ReadAsAsync<TResponse>().ContinueWith(t => {
+                                callback?.Invoke(t.Result, null);
+                            });
+                        }
+                        else {
+                            callback?.Invoke(default, new NTMinerException($"{action} http response {getHttpResponse.Result.StatusCode.ToString()} {getHttpResponse.Result.ReasonPhrase}"));
+                        }
                     }
                 }
                 catch (Exception e) {

+ 3 - 1
src/NTMinerRpcClient/HttpRpcRoot.cs

@@ -30,7 +30,9 @@ namespace NTMiner {
                     using (HttpClient client = RpcRoot.CreateHttpClient()) {
                         client.SetTimeout(timeountMilliseconds);
                         Task<HttpResponseMessage> getHttpResponse = client.PostAsync(RpcRoot.GetUrl(host, port, controller, action, query), content);
-                        NTMinerConsole.DevDebug($"{action} {getHttpResponse.Result.ReasonPhrase}");
+                        if (!getHttpResponse.Result.IsSuccessStatusCode) {
+                            NTMinerConsole.DevDebug($"{action} http response {getHttpResponse.Result.StatusCode.ToString()} {getHttpResponse.Result.ReasonPhrase}");
+                        }
                         callback?.Invoke();
                     }
                 }

+ 3 - 3
src/NTMinerRpcClient/Impl/ServerMessageSet.cs

@@ -26,7 +26,7 @@ namespace NTMiner.Impl {
                 RpcRoot.OfficialServer.ServerMessageService.GetServerMessagesAsync(localTimestamp, (response, e) => {
                     if (response.IsSuccess()) {
                         if (response.Data.Count > 0) {
-                            ReceiveServerMessage(response.Data);
+                            VirtualRoot.Execute(new ReceiveServerMessageCommand(response.Data));
                         }
                     }
                     else {
@@ -146,10 +146,10 @@ namespace NTMiner.Impl {
                     });
                 }
             }, location: this.GetType());
-            VirtualRoot.AddCmdPath<ClearServerMessages>(action: message => {
+            VirtualRoot.AddCmdPath<ClearServerMessagesCommand>(action: message => {
                 InitOnece();
-                // 服务端不应有清空消息的功能
                 if (isServer) {
+                    NTMinerConsole.UserWarn("服务端的消息不能清空");
                     return;
                 }
                 try {

+ 17 - 7
src/NTMinerRpcClient/JsonRequestBinaryResponseRpcRoot.cs

@@ -27,10 +27,15 @@ namespace NTMiner {
                 try {
                     using (HttpClient client = RpcRoot.CreateHttpClient()) {
                         client.SetTimeout(timeountMilliseconds);
-                        Task<HttpResponseMessage> message = client.GetAsync(RpcRoot.GetUrl(host, port, controller, action, query));
-                        message.Result.Content.ReadAsByteArrayAsync().ContinueWith(t => {
-                            callback?.Invoke(VirtualRoot.BinarySerializer.Deserialize<TResponse>(t.Result), null);
-                        });
+                        Task<HttpResponseMessage> getHttpResponse = client.GetAsync(RpcRoot.GetUrl(host, port, controller, action, query));
+                        if (getHttpResponse.Result.IsSuccessStatusCode) {
+                            getHttpResponse.Result.Content.ReadAsByteArrayAsync().ContinueWith(t => {
+                                callback?.Invoke(VirtualRoot.BinarySerializer.Deserialize<TResponse>(t.Result), null);
+                            });
+                        }
+                        else {
+                            callback?.Invoke(default, new NTMinerException($"{action} http response {getHttpResponse.Result.StatusCode.ToString()} {getHttpResponse.Result.ReasonPhrase}"));
+                        }
                     }
                 }
                 catch (Exception e) {
@@ -130,9 +135,14 @@ namespace NTMiner {
                     using (HttpClient client = RpcRoot.CreateHttpClient()) {
                         client.SetTimeout(timeountMilliseconds);
                         Task<HttpResponseMessage> getHttpResponse = client.PostAsJsonAsync(RpcRoot.GetUrl(host, port, controller, action, query), data);
-                        getHttpResponse.Result.Content.ReadAsByteArrayAsync().ContinueWith(t => {
-                            callback?.Invoke(VirtualRoot.BinarySerializer.Deserialize<TResponse>(t.Result), null);
-                        });
+                        if (getHttpResponse.Result.IsSuccessStatusCode) {
+                            getHttpResponse.Result.Content.ReadAsByteArrayAsync().ContinueWith(t => {
+                                callback?.Invoke(VirtualRoot.BinarySerializer.Deserialize<TResponse>(t.Result), null);
+                            });
+                        }
+                        else {
+                            callback?.Invoke(default, new NTMinerException($"{action} http response {getHttpResponse.Result.StatusCode.ToString()} {getHttpResponse.Result.ReasonPhrase}"));
+                        }
                     }
                 }
                 catch (Exception e) {

+ 9 - 4
src/NTMinerRpcClient/JsonRpcRoot.cs

@@ -27,10 +27,15 @@ namespace NTMiner {
                 try {
                     using (HttpClient client = RpcRoot.CreateHttpClient()) {
                         client.SetTimeout(timeountMilliseconds);
-                        Task<HttpResponseMessage> message = client.GetAsync(RpcRoot.GetUrl(host, port, controller, action, query));
-                        message.Result.Content.ReadAsAsync<TResponse>().ContinueWith(t => {
-                            callback?.Invoke(t.Result, null);
-                        });
+                        Task<HttpResponseMessage> getHttpResponse = client.GetAsync(RpcRoot.GetUrl(host, port, controller, action, query));
+                        if (getHttpResponse.Result.IsSuccessStatusCode) {
+                            getHttpResponse.Result.Content.ReadAsAsync<TResponse>().ContinueWith(t => {
+                                callback?.Invoke(t.Result, null);
+                            });
+                        }
+                        else {
+                            callback?.Invoke(default, new NTMinerException($"{action} http response {getHttpResponse.Result.StatusCode.ToString()} {getHttpResponse.Result.ReasonPhrase}"));
+                        }
                     }
                 }
                 catch (Exception e) {

+ 12 - 3
src/NTMinerRpcClient/JsonRpcRoot.partial.cs

@@ -96,12 +96,18 @@ namespace NTMiner {
                     using (HttpClient client = RpcRoot.CreateHttpClient()) {
                         client.SetTimeout(timeountMilliseconds);
                         Task<HttpResponseMessage> getHttpResponse = client.PostAsJsonAsync(RpcRoot.GetUrl(host, port, controller, action, query), data);
-                        getHttpResponse.Result.Content.ReadAsAsync<TResponse>().ContinueWith(t => {
-                            callback?.Invoke(t.Result, null);
-                        });
+                        if (getHttpResponse.Result.IsSuccessStatusCode) {
+                            getHttpResponse.Result.Content.ReadAsAsync<TResponse>().ContinueWith(t => {
+                                callback?.Invoke(t.Result, null);
+                            });
+                        }
+                        else {
+                            callback?.Invoke(default, new NTMinerException($"{action} http response {getHttpResponse.Result.StatusCode.ToString()} {getHttpResponse.Result.ReasonPhrase}"));
+                        }
                     }
                 }
                 catch (Exception e) {
+                    NTMinerConsole.DevError(e.Message + e.StackTrace);
                     callback?.Invoke(default, e);
                 }
             });
@@ -122,6 +128,9 @@ namespace NTMiner {
                         client.SetTimeout(timeountMilliseconds);
                         Task<HttpResponseMessage> getHttpResponse = client.PostAsJsonAsync(RpcRoot.GetUrl(host, port, controller, action, query), data);
                         NTMinerConsole.DevDebug($"{action} {getHttpResponse.Result.ReasonPhrase}");
+                        if (!getHttpResponse.Result.IsSuccessStatusCode) {
+                            NTMinerConsole.DevDebug($"{action} http response {getHttpResponse.Result.StatusCode.ToString()} {getHttpResponse.Result.ReasonPhrase}");
+                        }
                         callback?.Invoke();
                     }
                 }

+ 1 - 1
src/NTMinerRpcClient/NTMinerRpcClient.csproj

@@ -46,7 +46,7 @@
       <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.dll</HintPath>
     </Reference>
     <Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.20710.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
+      <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.4.0.30506.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
     </Reference>
     <Reference Include="System.Net.Http.WebRequest, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
       <HintPath>..\..\packages\Microsoft.Net.Http.2.0.20710.0\lib\net40\System.Net.Http.WebRequest.dll</HintPath>

+ 1 - 1
src/NTMinerRpcClient/RpcRoot.cs

@@ -60,7 +60,7 @@ namespace NTMiner {
 
         public static HttpClient CreateHttpClient() {
             return new HttpClient {
-                Timeout = TimeSpan.FromSeconds(60)
+                Timeout = TimeSpan.FromSeconds(20)
             };
         }
 

+ 0 - 10
src/NTMinerRpcClient/Services/Official/WsServerNodeService.cs

@@ -25,15 +25,5 @@ namespace NTMiner.Services.Official {
             };
             JsonRpcRoot.PostAsync(RpcRoot.OfficialServerHost, RpcRoot.OfficialServerPort, _controllerName, nameof(IWsServerNodeController.GetNodeAddress), data, callback, timeountMilliseconds: 8000);
         }
-
-        public void ReportNodeStateAsync(WsServerNodeState nodeState, Action<ResponseBase, Exception> callback) {
-            JsonRpcRoot.SignPostAsync(RpcRoot.OfficialServerHost, RpcRoot.OfficialServerPort, _controllerName, nameof(IWsServerNodeController.ReportNodeState), nodeState, callback, timeountMilliseconds: 3000);
-        }
-
-        public void RemoveNodeAsync(string address, Action<ResponseBase, Exception> callback) {
-            JsonRpcRoot.SignPostAsync(RpcRoot.OfficialServerHost, RpcRoot.OfficialServerPort, _controllerName, nameof(IWsServerNodeController.RemoveNode), new DataRequest<string> {
-                Data = address
-            }, callback);
-        }
     }
 }

+ 1 - 1
src/NTMinerRpcClient/packages.config

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="LiteDB" version="4.1.4" targetFramework="net40" />
-  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.20710.0" targetFramework="net40" />
+  <package id="Microsoft.AspNet.WebApi.Client" version="4.0.30506.0" targetFramework="net40" />
   <package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net40" />
   <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net40" />
 </packages>

+ 3 - 4
src/WebApiServer/Core/IWsServerNodeSet.cs → src/NTMinerServer/Core/IWsServerNodeAddressSet.cs

@@ -3,11 +3,10 @@ using System;
 using System.Collections.Generic;
 
 namespace NTMiner.Core {
-    public interface IWsServerNodeSet {
+    public interface IWsServerNodeAddressSet {
+        void Init(Action callback = null);
         WsStatus WsStatus { get; }
         string GetTargetNode(Guid clientId);
-        void SetNodeState(WsServerNodeState data);
-        void RemoveNode(string address);
-        IEnumerable<WsServerNodeState> AsEnumerable();
+        IEnumerable<string> AsEnumerable();
     }
 }

部分文件因为文件数量过多而无法显示