public static void PopulateFrom(this MiningStatistics miningStatistics, DeviceInformation deviceInformation) { miningStatistics.AcceptedShares = deviceInformation.AcceptedShares; miningStatistics.AverageHashrate = deviceInformation.AverageHashrate; miningStatistics.CurrentHashrate = deviceInformation.CurrentHashrate; miningStatistics.Enabled = deviceInformation.Enabled; miningStatistics.FanPercent = deviceInformation.FanPercent; miningStatistics.FanSpeed = deviceInformation.FanSpeed; miningStatistics.GpuActivity = deviceInformation.GpuActivity; miningStatistics.GpuClock = deviceInformation.GpuClock; miningStatistics.GpuVoltage = deviceInformation.GpuVoltage; miningStatistics.HardwareErrors = deviceInformation.HardwareErrors; miningStatistics.Index = deviceInformation.Index; miningStatistics.Intensity = deviceInformation.Intensity; miningStatistics.Kind = deviceInformation.Kind; miningStatistics.MemoryClock = deviceInformation.MemoryClock; miningStatistics.PowerTune = deviceInformation.PowerTune; miningStatistics.RejectedShares = deviceInformation.RejectedShares; miningStatistics.Status = deviceInformation.Status; miningStatistics.Temperature = deviceInformation.Temperature; miningStatistics.Utility = deviceInformation.Utility; //new properties from bfgminer miningStatistics.Name = deviceInformation.Name; miningStatistics.DeviceID = deviceInformation.ID; miningStatistics.PoolIndex = deviceInformation.PoolIndex; //miningStatistics.PoolName = deviceInformation.PoolName; miningStatistics.RejectedSharesPercent = deviceInformation.RejectedSharesPercent; miningStatistics.HardwareErrorsPercent = deviceInformation.HardwareErrorsPercent; }
private void PopulateMobileMinerStatistics(MultiMiner.MobileMiner.Data.MiningStatistics miningStatistics, DeviceInformation deviceInformation, string coinName) { miningStatistics.MinerName = "MultiMiner"; miningStatistics.CoinName = coinName; Engine.Data.Configuration.Coin coinConfiguration = engineConfiguration.CoinConfigurations.Single(c => c.CryptoCoin.Name.Equals(coinName)); CryptoCoin coin = coinConfiguration.CryptoCoin; miningStatistics.CoinSymbol = coin.Symbol; //MobileMiner currently only supports SHA and Scrypt //attempt to treat them as "Families" for now if ((coin.Algorithm == CoinAlgorithm.SHA256) || (coin.Algorithm == CoinAlgorithm.Keccak) || (coin.Algorithm == CoinAlgorithm.Groestl)) //SHA family algorithms grouped together miningStatistics.Algorithm = AlgorithmNames.SHA256; else //assume Scrypt for rest until MobileMiner supports more miningStatistics.Algorithm = AlgorithmNames.Scrypt; miningStatistics.PopulateFrom(deviceInformation); }
private void FlagSuspiciousMiner(MinerProcess minerProcess, DeviceInformation deviceInformation) { if (deviceInformation.Status.ToLower().Contains("sick")) minerProcess.HasSickDevice = true; if (deviceInformation.Status.ToLower().Contains("dead")) minerProcess.HasDeadDevice = true; if (deviceInformation.CurrentHashrate == 0) minerProcess.HasZeroHashrateDevice = true; //only check GPUs for subpar hashrate //ASICs spike too much for this to be reliable there //don't check average hashrate if using dynamic intensity if (deviceInformation.Kind.Equals("GPU", StringComparison.OrdinalIgnoreCase) && !engineConfiguration.XgminerConfiguration.DesktopMode) { //avoid div by 0 if (deviceInformation.AverageHashrate > 0) { double performanceRatio = deviceInformation.CurrentHashrate / deviceInformation.AverageHashrate; if (performanceRatio <= 0.50) minerProcess.HasPoorPerformingDevice = true; } } if (miningCoinConfigurations == null) //started mining but haven't yet assigned mining members //cannot check the following yet return; //Work Utility not returned by legacy API miners if (!minerProcess.Miner.LegacyApi) { double effectiveHashrate = WorkUtilityToHashrate(deviceInformation.WorkUtility); //avoid div by 0 if (deviceInformation.AverageHashrate > 0) { double performanceRatio = effectiveHashrate / deviceInformation.AverageHashrate; if (performanceRatio <= 0.25) minerProcess.StoppedAcceptingShares = true; } } }
public DeviceViewModel ApplyDeviceInformationResponseModel(DeviceDescriptor deviceModel, DeviceInformation deviceInformationResponseModel) { string[] excludedProperties = { "Name", //don't overwrite our "nice" name "Kind", //we have our own enum Kind "Enabled" //don't overwrite our own Enabled flag }; DeviceViewModel deviceViewModel = Devices.SingleOrDefault(d => d.Equals(deviceModel)); if (deviceViewModel != null) { if ((deviceModel.Kind == DeviceKind.PXY) || (deviceModel.Kind == DeviceKind.NET)) { deviceViewModel.PoolIndex = deviceInformationResponseModel.PoolIndex; //we will get multiple deviceInformationResponseModels for the same deviceModel in the case of a Stratum Proxy //bfgminer will report back for each Proxy Worker, but we only show a single entry in the ViewModel that rolls //up the stats for individual Proxy Workers deviceViewModel.AverageHashrate += deviceInformationResponseModel.AverageHashrate; deviceViewModel.CurrentHashrate += deviceInformationResponseModel.CurrentHashrate; deviceViewModel.AcceptedShares += deviceInformationResponseModel.AcceptedShares; deviceViewModel.RejectedShares += deviceInformationResponseModel.RejectedShares; deviceViewModel.HardwareErrors += deviceInformationResponseModel.HardwareErrors; deviceViewModel.Utility += deviceInformationResponseModel.Utility; deviceViewModel.WorkUtility += deviceInformationResponseModel.WorkUtility; //now add as a worker DeviceViewModel workerViewModel = new DeviceViewModel(); ObjectCopier.CopyObject(deviceInformationResponseModel, workerViewModel, excludedProperties); workerViewModel.WorkerName = deviceInformationResponseModel.Name; //set a default until (if) we get details deviceViewModel.Workers.Add(workerViewModel); //recalculate hardware and rejected share percentages - need to be weighted with worker hashrates UpdatePercentagesBasedOnWorkers(deviceViewModel); } else { ObjectCopier.CopyObject(deviceInformationResponseModel, deviceViewModel, excludedProperties); } } return deviceViewModel; }
private void PopulateMiningStatistics(MultiMiner.MobileMiner.Data.MiningStatistics miningStatistics, DeviceInformation deviceInformation, string coinName) { miningStatistics.MinerName = "MultiMiner"; miningStatistics.CoinName = coinName; Engine.Data.Configuration.Coin coinConfiguration = engineConfiguration.CoinConfigurations.Single(c => c.CryptoCoin.Name.Equals(coinName)); CryptoCoin coin = coinConfiguration.CryptoCoin; miningStatistics.CoinSymbol = coin.Symbol; if (coin.Algorithm == CoinAlgorithm.Scrypt) miningStatistics.Algorithm = AlgorithmNames.Scrypt; else if (coin.Algorithm == CoinAlgorithm.SHA256) miningStatistics.Algorithm = AlgorithmNames.SHA256; miningStatistics.PopulateFrom(deviceInformation); }
private void FlagSuspiciousMiner(MinerProcess minerProcess, DeviceInformation deviceInformation) { if (deviceInformation.Status.ToLower().Contains("sick")) minerProcess.HasSickDevice = true; if (deviceInformation.Status.ToLower().Contains("dead")) minerProcess.HasDeadDevice = true; if (deviceInformation.CurrentHashrate == 0) minerProcess.HasZeroHashrateDevice = true; //only check GPUs for subpar hashrate //ASICs spike too much for this to be reliable there //don't check average hashrate if using dynamic intensity if (deviceInformation.Kind.Equals("GPU", StringComparison.OrdinalIgnoreCase) && !engineConfiguration.XgminerConfiguration.DesktopMode) { //avoid div by 0 if (deviceInformation.AverageHashrate > 0) { double performanceRatio = deviceInformation.CurrentHashrate / deviceInformation.AverageHashrate; if (performanceRatio <= 0.50) minerProcess.HasPoorPerformingDevice = true; } } double effectiveHashrate = WorkUtilityToHashrate(deviceInformation.WorkUtility); //avoid div by 0 if (deviceInformation.AverageHashrate > 0) { double performanceRatio = effectiveHashrate / deviceInformation.AverageHashrate; if (performanceRatio <= 0.25) minerProcess.StoppedAcceptingShares = true; } }
public static void ParseTextForDeviceInformation(string text, List<DeviceInformation> deviceInformation, int logInterval) { List<string> deviceBlob = text.Split('|').ToList(); deviceBlob.RemoveAt(0); foreach (string deviceText in deviceBlob) { if (deviceText == "\0") continue; //bfgminer may have multiple entries for the same key, e.g. Hardware Errors //seen with customer data/hardware //remove dupes using Distinct() var deviceAttributes = deviceText.Split(',').ToList().Distinct(); Dictionary<string, string> keyValuePairs = deviceAttributes .Where(value => value.Contains('=')) .Select(value => value.Split('=')) .ToDictionary(pair => pair[0], pair => pair[1]); //seen Count == 0 with user API logs if (keyValuePairs.Count > 0) { DeviceInformation newDevice = new DeviceInformation(); newDevice.Kind = keyValuePairs.ElementAt(0).Key; newDevice.Index = TryToParseInt(keyValuePairs, newDevice.Kind, -1); if (newDevice.Index == -1) continue; if (keyValuePairs.ContainsKey("Enabled")) //seen this needed with a user newDevice.Enabled = keyValuePairs["Enabled"].Equals("Y"); if (keyValuePairs.ContainsKey("Status")) //check required for bfgminer newDevice.Status = keyValuePairs["Status"]; if (keyValuePairs.ContainsKey("Name")) newDevice.Name = keyValuePairs["Name"]; else //default to Kind for older RPC API versions newDevice.Name = newDevice.Kind; //default to Index for older RPC API versions newDevice.ID = newDevice.Index; if (keyValuePairs.ContainsKey("ID")) newDevice.ID = TryToParseInt(keyValuePairs, "ID", newDevice.Index); //parse regardless of device type = ASICs may have Temp newDevice.Temperature = TryToParseDouble(keyValuePairs, "Temperature", 0.00); newDevice.FanSpeed = TryToParseInt(keyValuePairs, "Fan Speed", 0); newDevice.FanPercent = TryToParseInt(keyValuePairs, "Fan Percent", 0); newDevice.GpuClock = TryToParseInt(keyValuePairs, "GPU Clock", 0); newDevice.MemoryClock = TryToParseInt(keyValuePairs, "Memory Clock", 0); newDevice.GpuVoltage = TryToParseDouble(keyValuePairs, "GPU Voltage", 0.00); newDevice.GpuActivity = TryToParseInt(keyValuePairs, "GPU Activity", 0); newDevice.PowerTune = TryToParseInt(keyValuePairs, "Powertune", 0); if (keyValuePairs.ContainsKey("Intensity")) //check required for bfgminer 3.3.0 newDevice.Intensity = keyValuePairs["Intensity"]; newDevice.AverageHashrate = TryToParseDouble(keyValuePairs, "MHS av", 0.00) * 1000; //seen both MHS 5s and MHS 1s //the key here is based on the value passed for --log to bfgminer newDevice.CurrentHashrate = GetCurrentHashrate(keyValuePairs, logInterval); if (newDevice.CurrentHashrate == 0.0) //check for 20s newDevice.CurrentHashrate = GetCurrentHashrate(keyValuePairs, 20); if (newDevice.CurrentHashrate == 0.0) //check for 5s newDevice.CurrentHashrate = GetCurrentHashrate(keyValuePairs, 5); newDevice.AcceptedShares = TryToParseInt(keyValuePairs, "Accepted", 0); newDevice.RejectedShares = TryToParseInt(keyValuePairs, "Rejected", 0); newDevice.HardwareErrors = TryToParseInt(keyValuePairs, "Hardware Errors", 0); newDevice.Utility = TryToParseDouble(keyValuePairs, "Utility", 0.00); newDevice.WorkUtility = TryToParseDouble(keyValuePairs, "Work Utility", 0.00); newDevice.PoolIndex = TryToParseInt(keyValuePairs, "Last Share Pool", -1); newDevice.HardwareErrorsPercent = TryToParseDouble(keyValuePairs, "Device Hardware%", 0.00); newDevice.RejectedSharesPercent = TryToParseDouble(keyValuePairs, "Device Rejected%", 0.00); newDevice.LastShareDifficulty = TryToParseDouble(keyValuePairs, "Last Share Difficulty", 0.00); newDevice.DifficultyAccepted = TryToParseDouble(keyValuePairs, "Difficulty Accepted", 0.00); newDevice.DeviceElapsed = TryToParseInt(keyValuePairs, "Device Elapsed", 0); if (newDevice.WorkUtility == 0.0) { if (newDevice.DeviceElapsed > 0) newDevice.WorkUtility = newDevice.DifficultyAccepted / newDevice.DeviceElapsed * 60; else if (newDevice.LastShareDifficulty > 0) newDevice.WorkUtility = newDevice.Utility / newDevice.LastShareDifficulty; } deviceInformation.Add(newDevice); } } }
public static void ParseTextForDeviceInformation(string text, List<DeviceInformation> deviceInformation) { List<string> responseParts = ParseResponseText(text); if (responseParts.Count == 0) return; foreach (string responsePart in responseParts) { Dictionary<string, string> keyValuePairs = ParseResponsePart(responsePart); //check for key-value pairs, seen Count == 0 with user API logs if (keyValuePairs.Count > 0) { DeviceInformation newDevice = new DeviceInformation(); newDevice.Kind = keyValuePairs.ElementAt(0).Key; newDevice.Index = TryToParseInt(keyValuePairs, newDevice.Kind, -1); if (newDevice.Index == -1) continue; if (keyValuePairs.ContainsKey("Enabled")) //seen this needed with a user newDevice.Enabled = keyValuePairs["Enabled"].Equals("Y"); if (keyValuePairs.ContainsKey("Status")) //check required for bfgminer newDevice.Status = keyValuePairs["Status"]; if (keyValuePairs.ContainsKey("Name")) newDevice.Name = keyValuePairs["Name"]; else //default to Kind for older RPC API versions newDevice.Name = newDevice.Kind; //default to Index for older RPC API versions newDevice.ID = newDevice.Index; if (keyValuePairs.ContainsKey("ID")) newDevice.ID = TryToParseInt(keyValuePairs, "ID", newDevice.Index); //parse regardless of device type = ASICs may have Temp newDevice.Temperature = TryToParseDouble(keyValuePairs, "Temperature", 0.00); newDevice.FanSpeed = TryToParseInt(keyValuePairs, "Fan Speed", 0); newDevice.FanPercent = TryToParseInt(keyValuePairs, "Fan Percent", 0); newDevice.GpuClock = TryToParseInt(keyValuePairs, "GPU Clock", 0); newDevice.MemoryClock = TryToParseInt(keyValuePairs, "Memory Clock", 0); newDevice.GpuVoltage = TryToParseDouble(keyValuePairs, "GPU Voltage", 0.00); newDevice.GpuActivity = TryToParseInt(keyValuePairs, "GPU Activity", 0); newDevice.PowerTune = TryToParseInt(keyValuePairs, "Powertune", 0); if (keyValuePairs.ContainsKey("Intensity")) //check required for bfgminer 3.3.0 newDevice.Intensity = keyValuePairs["Intensity"]; newDevice.DeviceElapsed = TryToParseInt(keyValuePairs, "Device Elapsed", 0); newDevice.AverageHashrate = TryToParseDouble(keyValuePairs, "MHS av", 0.00) * 1000; //try for a 5m reading first //some Network Devices (Spondoolies) have wildly innacurate 5s entries if ((newDevice.CurrentHashrate == 0.0) //consider DeviceElapsed for accurate R3-Box stats && (newDevice.DeviceElapsed >= (5 * 60))) //check for 5m newDevice.CurrentHashrate = GetCurrentHashrate(keyValuePairs, "5m"); if ((newDevice.CurrentHashrate == 0.0) //consider DeviceElapsed for accurate R3-Box stats && (newDevice.DeviceElapsed >= 60)) //check for 1m newDevice.CurrentHashrate = GetCurrentHashrate(keyValuePairs, "1m"); if (newDevice.CurrentHashrate == 0.0) //check for 20s newDevice.CurrentHashrate = GetCurrentHashrate(keyValuePairs, "20s"); if (newDevice.CurrentHashrate == 0.0) //check for 5s newDevice.CurrentHashrate = GetCurrentHashrate(keyValuePairs, "5s"); if (newDevice.CurrentHashrate == 0.0) //check for 1s newDevice.CurrentHashrate = GetCurrentHashrate(keyValuePairs, "1s"); newDevice.AcceptedShares = TryToParseInt(keyValuePairs, "Accepted", 0); newDevice.RejectedShares = TryToParseInt(keyValuePairs, "Rejected", 0); newDevice.HardwareErrors = TryToParseInt(keyValuePairs, "Hardware Errors", 0); newDevice.Utility = TryToParseDouble(keyValuePairs, "Utility", 0.00); newDevice.WorkUtility = TryToParseDouble(keyValuePairs, "Work Utility", 0.00); newDevice.PoolIndex = TryToParseInt(keyValuePairs, "Last Share Pool", -1); newDevice.HardwareErrorsPercent = TryToParseDouble(keyValuePairs, "Device Hardware%", 0.00); newDevice.RejectedSharesPercent = TryToParseDouble(keyValuePairs, "Device Rejected%", 0.00); newDevice.LastShareDifficulty = TryToParseDouble(keyValuePairs, "Last Share Difficulty", 0.00); newDevice.DifficultyAccepted = TryToParseDouble(keyValuePairs, "Difficulty Accepted", 0.00); if (newDevice.WorkUtility == 0.0) { if (newDevice.DeviceElapsed > 0) newDevice.WorkUtility = newDevice.DifficultyAccepted / newDevice.DeviceElapsed * 60; else if (newDevice.LastShareDifficulty > 0) newDevice.WorkUtility = newDevice.Utility / newDevice.LastShareDifficulty; } deviceInformation.Add(newDevice); } } }