From 06ed4744b1a15ca0b5ad977bb37f4236bc231aad Mon Sep 17 00:00:00 2001 From: blakekrpec Date: Sun, 24 Nov 2024 04:04:46 -0600 Subject: [PATCH] Individual Sensor Requests (#1504) * added /Sensor endpoints * fix intel sensor order * Update HttpServer.cs --------- Co-authored-by: PhyxionNL <7643972+PhyxionNL@users.noreply.github.com> --- LibreHardwareMonitor/Utilities/HttpServer.cs | 190 ++++++++++-------- .../Hardware/Cpu/IntelCpu.cs | 35 ++-- 2 files changed, 124 insertions(+), 101 deletions(-) diff --git a/LibreHardwareMonitor/Utilities/HttpServer.cs b/LibreHardwareMonitor/Utilities/HttpServer.cs index 14d0d19..494f6c6 100644 --- a/LibreHardwareMonitor/Utilities/HttpServer.cs +++ b/LibreHardwareMonitor/Utilities/HttpServer.cs @@ -54,7 +54,6 @@ public class HttpServer if (PlatformNotSupported) return; - StopHttpListener(); _listener.Abort(); } @@ -83,13 +82,11 @@ public class HttpServer if (PlatformNotSupported) return false; - try { if (_listener.IsListening) return true; - string prefix = "http://+:" + ListenerPort + "/"; _listener.Prefixes.Clear(); _listener.Prefixes.Add(prefix); @@ -116,7 +113,6 @@ public class HttpServer if (PlatformNotSupported) return false; - try { _listenerThread?.Abort(); @@ -232,6 +228,8 @@ public class HttpServer throw new ArgumentNullException("No value provided"); case "Get": result["value"] = sNode.Sensor.Value; + result["min"] = sNode.Sensor.Min; + result["max"] = sNode.Sensor.Max; result["format"] = sNode.Format; break; default: @@ -253,7 +251,7 @@ public class HttpServer //Currently the only supported base URL is http://localhost:8085/Sensor. private string HandlePostRequest(HttpListenerRequest request) { - JObject result = new JObject { ["result"] = "ok" }; + JObject result = new() { ["result"] = "ok" }; try { @@ -279,7 +277,7 @@ public class HttpServer #if DEBUG return result.ToString(Newtonsoft.Json.Formatting.Indented); #else - return result.ToString(Newtonsoft.Json.Formatting.None); + return result.ToString(Newtonsoft.Json.Formatting.None); #endif } @@ -289,7 +287,6 @@ public class HttpServer if (listener == null || !listener.IsListening) return; - // Call EndGetContext to complete the asynchronous operation. HttpListenerContext context; try @@ -360,6 +357,14 @@ public class HttpServer return; } + if (requestedFile.Contains("Sensor")) + { + JObject sensorResult = new(); + HandleSensorRequest(request, sensorResult); + SendJsonSensor(context.Response, sensorResult); + return; + } + // default file to be served if (string.IsNullOrEmpty(requestedFile)) requestedFile = "index.html"; @@ -412,38 +417,36 @@ public class HttpServer name = "LibreHardwareMonitor.Resources." + name.Replace("custom-theme", "custom_theme"); - string[] names = - Assembly.GetExecutingAssembly().GetManifestResourceNames(); + string[] names = Assembly.GetExecutingAssembly().GetManifestResourceNames(); for (int i = 0; i < names.Length; i++) { if (names[i].Replace('\\', '.') == name) { - using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(names[i])) + using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(names[i]); + + response.ContentType = GetContentType("." + ext); + response.ContentLength64 = stream.Length; + byte[] buffer = new byte[512 * 1024]; + try { - response.ContentType = GetContentType("." + ext); - response.ContentLength64 = stream.Length; - byte[] buffer = new byte[512 * 1024]; - try + Stream output = response.OutputStream; + int len; + while ((len = stream.Read(buffer, 0, buffer.Length)) > 0) { - Stream output = response.OutputStream; - int len; - while ((len = stream.Read(buffer, 0, buffer.Length)) > 0) - { - output.Write(buffer, 0, len); - } - - output.Flush(); - output.Close(); - response.Close(); + output.Write(buffer, 0, len); } - catch (HttpListenerException) - { } - catch (InvalidOperationException) - { } - return; + output.Flush(); + output.Close(); + response.Close(); } + catch (HttpListenerException) + { } + catch (InvalidOperationException) + { } + + return; } } @@ -461,28 +464,27 @@ public class HttpServer { if (names[i].Replace('\\', '.') == name) { - using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(names[i])) + using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(names[i]); + + Image image = Image.FromStream(stream); + response.ContentType = "image/png"; + try { - Image image = Image.FromStream(stream); - response.ContentType = "image/png"; - try + Stream output = response.OutputStream; + using (MemoryStream ms = new()) { - Stream output = response.OutputStream; - using (MemoryStream ms = new MemoryStream()) - { - image.Save(ms, ImageFormat.Png); - ms.WriteTo(output); - } - - output.Close(); + image.Save(ms, ImageFormat.Png); + ms.WriteTo(output); } - catch (HttpListenerException) - { } - image.Dispose(); - response.Close(); - return; + output.Close(); } + catch (HttpListenerException) + { } + + image.Dispose(); + response.Close(); + return; } } @@ -492,7 +494,7 @@ public class HttpServer private void SendJson(HttpListenerResponse response, HttpListenerRequest request = null) { - JObject json = new JObject(); + JObject json = new(); int nodeIndex = 0; @@ -503,12 +505,12 @@ public class HttpServer json["Max"] = "Max"; json["ImageURL"] = string.Empty; - JArray children = new JArray { GenerateJsonForNode(_root, ref nodeIndex) }; - json["Children"] = children; + json["Children"] = new JArray { GenerateJsonForNode(_root, ref nodeIndex) }; + #if DEBUG string responseContent = json.ToString(Newtonsoft.Json.Formatting.Indented); #else - string responseContent = json.ToString(Newtonsoft.Json.Formatting.None); + string responseContent = json.ToString(Newtonsoft.Json.Formatting.None); #endif byte[] buffer = Encoding.UTF8.GetBytes(responseContent); @@ -532,13 +534,11 @@ public class HttpServer { if (acceptGzip) { - using (var ms = new MemoryStream()) - { - using (var zip = new GZipStream(ms, CompressionMode.Compress, true)) - zip.Write(buffer, 0, buffer.Length); + using var ms = new MemoryStream(); + using (var zip = new GZipStream(ms, CompressionMode.Compress, true)) + zip.Write(buffer, 0, buffer.Length); - buffer = ms.ToArray(); - } + buffer = ms.ToArray(); } response.ContentLength64 = buffer.Length; @@ -552,9 +552,35 @@ public class HttpServer response.Close(); } + private void SendJsonSensor(HttpListenerResponse response, JObject sensorData) + { + // Convert the JObject to a JSON string + string responseContent = sensorData.ToString(Newtonsoft.Json.Formatting.None); + byte[] buffer = Encoding.UTF8.GetBytes(responseContent); + + // Add headers and set content type + response.AddHeader("Cache-Control", "no-cache"); + response.AddHeader("Access-Control-Allow-Origin", "*"); + response.ContentType = "application/json"; + + // Write the response content to the output stream + try + { + response.ContentLength64 = buffer.Length; + Stream output = response.OutputStream; + output.Write(buffer, 0, buffer.Length); + output.Close(); + } + catch (HttpListenerException) + { } + + // Close the response + response.Close(); + } + private JObject GenerateJsonForNode(Node n, ref int nodeIndex) { - JObject jsonNode = new JObject + JObject jsonNode = new() { ["id"] = nodeIndex++, ["Text"] = n.Text, @@ -563,29 +589,28 @@ public class HttpServer ["Max"] = string.Empty }; - if (n is SensorNode sensorNode) + switch (n) { - jsonNode["SensorId"] = sensorNode.Sensor.Identifier.ToString(); - jsonNode["Type"] = sensorNode.Sensor.SensorType.ToString(); - jsonNode["Min"] = sensorNode.Min; - jsonNode["Value"] = sensorNode.Value; - jsonNode["Max"] = sensorNode.Max; - jsonNode["ImageURL"] = "images/transparent.png"; - } - else if (n is HardwareNode hardwareNode) - { - jsonNode["ImageURL"] = "images_icon/" + GetHardwareImageFile(hardwareNode); - } - else if (n is TypeNode typeNode) - { - jsonNode["ImageURL"] = "images_icon/" + GetTypeImageFile(typeNode); - } - else - { - jsonNode["ImageURL"] = "images_icon/computer.png"; + case SensorNode sensorNode: + jsonNode["SensorId"] = sensorNode.Sensor.Identifier.ToString(); + jsonNode["Type"] = sensorNode.Sensor.SensorType.ToString(); + jsonNode["Min"] = sensorNode.Min; + jsonNode["Value"] = sensorNode.Value; + jsonNode["Max"] = sensorNode.Max; + jsonNode["ImageURL"] = "images/transparent.png"; + break; + case HardwareNode hardwareNode: + jsonNode["ImageURL"] = "images_icon/" + GetHardwareImageFile(hardwareNode); + break; + case TypeNode typeNode: + jsonNode["ImageURL"] = "images_icon/" + GetTypeImageFile(typeNode); + break; + default: + jsonNode["ImageURL"] = "images_icon/computer.png"; + break; } - JArray children = new JArray(); + JArray children = []; foreach (Node child in n.Nodes) { children.Add(GenerateJsonForNode(child, ref nodeIndex)); @@ -690,12 +715,10 @@ public class HttpServer private string ComputeSHA256(string text) { - using (SHA256 hash = SHA256.Create()) - { - return string.Concat(hash - .ComputeHash(Encoding.UTF8.GetBytes(text)) - .Select(item => item.ToString("x2"))); - } + using SHA256 hash = SHA256.Create(); + return string.Concat(hash + .ComputeHash(Encoding.UTF8.GetBytes(text)) + .Select(item => item.ToString("x2"))); } public void Quit() @@ -703,7 +726,6 @@ public class HttpServer if (PlatformNotSupported) return; - StopHttpListener(); _listener.Abort(); } diff --git a/LibreHardwareMonitorLib/Hardware/Cpu/IntelCpu.cs b/LibreHardwareMonitorLib/Hardware/Cpu/IntelCpu.cs index c8f8daf..fb1a40a 100644 --- a/LibreHardwareMonitorLib/Hardware/Cpu/IntelCpu.cs +++ b/LibreHardwareMonitorLib/Hardware/Cpu/IntelCpu.cs @@ -310,6 +310,24 @@ internal sealed class IntelCpu : GenericCpu int coreSensorId = 0; + //core temp avg and max value + //is only available when the cpu has more than 1 core + if (cpuId[0][0].Data.GetLength(0) > 6 && (cpuId[0][0].Data[6, 0] & 0x40) != 0 && _microArchitecture != MicroArchitecture.Unknown && _coreCount > 1) + { + _coreMax = new Sensor("Core Max", coreSensorId, SensorType.Temperature, this, settings); + ActivateSensor(_coreMax); + coreSensorId++; + + _coreAvg = new Sensor("Core Average", coreSensorId, SensorType.Temperature, this, settings); + ActivateSensor(_coreAvg); + coreSensorId++; + } + else + { + _coreMax = null; + _coreAvg = null; + } + // check if processor supports a digital thermal sensor at core level if (cpuId[0][0].Data.GetLength(0) > 6 && (cpuId[0][0].Data[6, 0] & 1) != 0 && _microArchitecture != MicroArchitecture.Unknown) { @@ -366,23 +384,6 @@ internal sealed class IntelCpu : GenericCpu else _distToTjMaxTemperatures = Array.Empty(); - //core temp avg and max value - //is only available when the cpu has more than 1 core - if (cpuId[0][0].Data.GetLength(0) > 6 && (cpuId[0][0].Data[6, 0] & 0x40) != 0 && _microArchitecture != MicroArchitecture.Unknown && _coreCount > 1) - { - _coreMax = new Sensor("Core Max", coreSensorId, SensorType.Temperature, this, settings); - ActivateSensor(_coreMax); - coreSensorId++; - - _coreAvg = new Sensor("Core Average", coreSensorId, SensorType.Temperature, this, settings); - ActivateSensor(_coreAvg); - } - else - { - _coreMax = null; - _coreAvg = null; - } - _busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings); _coreClocks = new Sensor[_coreCount]; for (int i = 0; i < _coreClocks.Length; i++)