SensorCollector.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. using System.Collections.Concurrent;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using NLog;
  5. using LibreHardwareMonitor.Hardware;
  6. using LibreHardwareMonitor.Hardware.Storage;
  7. using System;
  8. namespace OhmGraphite
  9. {
  10. public class SensorCollector : IGiveSensors
  11. {
  12. private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
  13. private readonly Computer _computer;
  14. private readonly MetricConfig _config;
  15. private readonly IVisitor _updateVisitor = new UpdateVisitor();
  16. private readonly ConcurrentDictionary<Identifier, object> _ids =
  17. new ConcurrentDictionary<Identifier, object>();
  18. private readonly ConcurrentDictionary<Identifier, OhmNvme> _nvmes =
  19. new ConcurrentDictionary<Identifier, OhmNvme>();
  20. public SensorCollector(Computer computer, MetricConfig config)
  21. {
  22. _computer = computer;
  23. _config = config;
  24. }
  25. public void Open()
  26. {
  27. foreach (var hardware in _computer.Hardware)
  28. {
  29. HardwareAdded(hardware);
  30. }
  31. _computer.HardwareAdded += HardwareAdded;
  32. _computer.HardwareRemoved += HardwareRemoved;
  33. _computer.Open();
  34. }
  35. public void Close()
  36. {
  37. _computer.HardwareRemoved -= HardwareRemoved;
  38. _computer.HardwareAdded -= HardwareAdded;
  39. foreach (var hardware in _computer.Hardware)
  40. {
  41. HardwareRemoved(hardware);
  42. }
  43. _computer.Close();
  44. }
  45. public void Start() => Open();
  46. public void Dispose() => Close();
  47. private void HardwareAdded(IHardware hardware)
  48. {
  49. if (!_ids.TryAdd(hardware.Identifier, hardware))
  50. {
  51. Logger.Debug("Hardware previously added: {0}", hardware.Identifier);
  52. return;
  53. }
  54. Logger.Debug("Hardware added: {0}", hardware.Identifier);
  55. hardware.SensorAdded += SensorAdded;
  56. hardware.SensorRemoved += SensorRemoved;
  57. foreach (var sensor in hardware.Sensors)
  58. {
  59. SensorAdded(sensor);
  60. }
  61. if (hardware is NVMeGeneric nvme)
  62. {
  63. var ohmNvme = new OhmNvme(nvme);
  64. _nvmes.TryAdd(hardware.Identifier, ohmNvme);
  65. SensorAdded(ohmNvme.MediaErrors);
  66. SensorAdded(ohmNvme.PowerCycles);
  67. SensorAdded(ohmNvme.ErrorInfoLogEntryCount);
  68. SensorAdded(ohmNvme.UnsafeShutdowns);
  69. }
  70. foreach (var sub in hardware.SubHardware)
  71. {
  72. HardwareAdded(sub);
  73. }
  74. }
  75. private void HardwareRemoved(IHardware hardware)
  76. {
  77. _ids.TryRemove(hardware.Identifier, out _);
  78. Logger.Debug("Hardware removed: {0}", hardware.Identifier);
  79. hardware.SensorAdded -= SensorAdded;
  80. hardware.SensorRemoved -= SensorRemoved;
  81. foreach (var sensor in hardware.Sensors)
  82. {
  83. SensorRemoved(sensor);
  84. }
  85. if (_nvmes.TryRemove(hardware.Identifier, out OhmNvme ohmNvme))
  86. {
  87. SensorRemoved(ohmNvme.MediaErrors);
  88. SensorRemoved(ohmNvme.PowerCycles);
  89. SensorRemoved(ohmNvme.ErrorInfoLogEntryCount);
  90. SensorRemoved(ohmNvme.UnsafeShutdowns);
  91. }
  92. foreach (var sub in hardware.SubHardware)
  93. {
  94. HardwareRemoved(sub);
  95. }
  96. }
  97. private void SensorAdded(ISensor sensor)
  98. {
  99. sensor.ValuesTimeWindow = TimeSpan.Zero;
  100. var added = _ids.TryAdd(sensor.Identifier, sensor);
  101. var msg = added ? "Sensor added: {0} \"{1}\"" : "Sensor previously added: {0} \"{1}\"";
  102. Logger.Info(msg, sensor.Identifier, SensorName(sensor));
  103. }
  104. private void SensorRemoved(ISensor sensor)
  105. {
  106. Logger.Debug("Sensor removed: {0}", sensor.Identifier);
  107. _ids.TryRemove(sensor.Identifier, out _);
  108. }
  109. public IEnumerable<ReportedValue> ReadAllSensors()
  110. {
  111. _computer.Accept(_updateVisitor);
  112. foreach (var nvme in _nvmes.Values)
  113. {
  114. nvme.Update();
  115. }
  116. return _ids.Values.OfType<ISensor>().SelectMany(ReportedValues);
  117. }
  118. private string SensorName(ISensor sensor)
  119. {
  120. // Remove hardware index indentifier for motherboards to preserve
  121. // librehardwaremonitor pre-0.9.3 behavior
  122. // https://github.com/nickbabcock/OhmGraphite/pull/433
  123. return sensor.Hardware.HardwareType == LibreHardwareMonitor.Hardware.HardwareType.Motherboard
  124. ? string.Join("/", sensor.Name.Split('/').Where((x, i) => i != 2))
  125. : sensor.Name;
  126. }
  127. private IEnumerable<ReportedValue> ReportedValues(ISensor sensor)
  128. {
  129. string sensorName = SensorName(sensor);
  130. string id = sensor.Identifier.ToString();
  131. // Only report a value if the sensor was able to get a value
  132. // as 0 is different than "didn't read". For example, are the
  133. // fans really spinning at 0 RPM or was the value not read.
  134. if (!sensor.Value.HasValue)
  135. {
  136. Logger.Debug($"{id} did not have a value");
  137. }
  138. else if (float.IsNaN(sensor.Value.Value))
  139. {
  140. Logger.Debug($"{id} had a NaN value");
  141. }
  142. else if (float.IsInfinity(sensor.Value.Value))
  143. {
  144. Logger.Debug($"{id} had an infinite value");
  145. }
  146. else if (!_config.IsHidden(sensor.Identifier.ToString()) && !_config.IsHidden(sensorName))
  147. {
  148. var hwInstance = ExtractHardwareInstance(sensor.Hardware.Identifier.ToString());
  149. var name = _config.TryGetAlias(sensor.Identifier.ToString(), out string alias) ? alias : sensorName;
  150. var result = new ReportedValue(id,
  151. name,
  152. sensor.Value.Value,
  153. sensor.SensorType.ToOwnSensor(),
  154. sensor.Hardware.Name,
  155. sensor.Hardware.HardwareType.ToOwnHardware(),
  156. hwInstance,
  157. sensor.Index);
  158. Logger.Trace(
  159. "Value: ID {id}, sensor: {sensor}, value: {value}, sensor type: {sensorType}, hardware: {hardware}, hardware type: {hardwareType}, sensor index: {sensorIndex}, hardware instance: {hardwareInstance}",
  160. result.Identifier,
  161. result.Sensor,
  162. result.Value,
  163. result.SensorType,
  164. result.Hardware,
  165. result.HardwareType,
  166. result.SensorIndex,
  167. result.HardwareInstance
  168. );
  169. yield return result;
  170. }
  171. }
  172. public static string ExtractHardwareInstance(string hwInstance)
  173. {
  174. var ind = hwInstance.LastIndexOf('/');
  175. hwInstance = hwInstance.Substring(ind + 1);
  176. hwInstance = hwInstance.Replace("%7B", "").Replace("%7D", "");
  177. return hwInstance;
  178. }
  179. }
  180. }