Individual Sensor Requests (#1504)

* added /Sensor endpoints

* fix intel sensor order

* Update HttpServer.cs

---------

Co-authored-by: PhyxionNL <7643972+PhyxionNL@users.noreply.github.com>
This commit is contained in:
blakekrpec
2024-11-24 11:04:46 +01:00
committed by GitHub
co-authored by PhyxionNL
parent e6e2b23ce4
commit 06ed4744b1
2 changed files with 124 additions and 101 deletions
+106 -84
View File
@@ -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();
}
@@ -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<Sensor>();
//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++)