Skip to content

Commit 06ed474

Browse files
Individual Sensor Requests (#1504)
* added /Sensor endpoints * fix intel sensor order * Update HttpServer.cs --------- Co-authored-by: PhyxionNL <7643972+PhyxionNL@users.noreply.github.com>
1 parent e6e2b23 commit 06ed474

2 files changed

Lines changed: 125 additions & 102 deletions

File tree

LibreHardwareMonitor/Utilities/HttpServer.cs

Lines changed: 107 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ public HttpServer(Node node, int port, bool authEnabled = false, string userName
5454
if (PlatformNotSupported)
5555
return;
5656

57-
5857
StopHttpListener();
5958
_listener.Abort();
6059
}
@@ -83,13 +82,11 @@ public bool StartHttpListener()
8382
if (PlatformNotSupported)
8483
return false;
8584

86-
8785
try
8886
{
8987
if (_listener.IsListening)
9088
return true;
9189

92-
9390
string prefix = "http://+:" + ListenerPort + "/";
9491
_listener.Prefixes.Clear();
9592
_listener.Prefixes.Add(prefix);
@@ -116,7 +113,6 @@ public bool StopHttpListener()
116113
if (PlatformNotSupported)
117114
return false;
118115

119-
120116
try
121117
{
122118
_listenerThread?.Abort();
@@ -232,6 +228,8 @@ private void HandleSensorRequest(HttpListenerRequest request, JObject result)
232228
throw new ArgumentNullException("No value provided");
233229
case "Get":
234230
result["value"] = sNode.Sensor.Value;
231+
result["min"] = sNode.Sensor.Min;
232+
result["max"] = sNode.Sensor.Max;
235233
result["format"] = sNode.Format;
236234
break;
237235
default:
@@ -253,7 +251,7 @@ private void HandleSensorRequest(HttpListenerRequest request, JObject result)
253251
//Currently the only supported base URL is http://localhost:8085/Sensor.
254252
private string HandlePostRequest(HttpListenerRequest request)
255253
{
256-
JObject result = new JObject { ["result"] = "ok" };
254+
JObject result = new() { ["result"] = "ok" };
257255

258256
try
259257
{
@@ -279,7 +277,7 @@ private string HandlePostRequest(HttpListenerRequest request)
279277
#if DEBUG
280278
return result.ToString(Newtonsoft.Json.Formatting.Indented);
281279
#else
282-
return result.ToString(Newtonsoft.Json.Formatting.None);
280+
return result.ToString(Newtonsoft.Json.Formatting.None);
283281
#endif
284282
}
285283

@@ -289,7 +287,6 @@ private void ListenerCallback(IAsyncResult result)
289287
if (listener == null || !listener.IsListening)
290288
return;
291289

292-
293290
// Call EndGetContext to complete the asynchronous operation.
294291
HttpListenerContext context;
295292
try
@@ -360,6 +357,14 @@ private void ListenerCallback(IAsyncResult result)
360357
return;
361358
}
362359

360+
if (requestedFile.Contains("Sensor"))
361+
{
362+
JObject sensorResult = new();
363+
HandleSensorRequest(request, sensorResult);
364+
SendJsonSensor(context.Response, sensorResult);
365+
return;
366+
}
367+
363368
// default file to be served
364369
if (string.IsNullOrEmpty(requestedFile))
365370
requestedFile = "index.html";
@@ -412,38 +417,36 @@ private void ServeResourceFile(HttpListenerResponse response, string name, strin
412417
name = "LibreHardwareMonitor.Resources." +
413418
name.Replace("custom-theme", "custom_theme");
414419

415-
string[] names =
416-
Assembly.GetExecutingAssembly().GetManifestResourceNames();
420+
string[] names = Assembly.GetExecutingAssembly().GetManifestResourceNames();
417421

418422
for (int i = 0; i < names.Length; i++)
419423
{
420424
if (names[i].Replace('\\', '.') == name)
421425
{
422-
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(names[i]))
426+
using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(names[i]);
427+
428+
response.ContentType = GetContentType("." + ext);
429+
response.ContentLength64 = stream.Length;
430+
byte[] buffer = new byte[512 * 1024];
431+
try
423432
{
424-
response.ContentType = GetContentType("." + ext);
425-
response.ContentLength64 = stream.Length;
426-
byte[] buffer = new byte[512 * 1024];
427-
try
433+
Stream output = response.OutputStream;
434+
int len;
435+
while ((len = stream.Read(buffer, 0, buffer.Length)) > 0)
428436
{
429-
Stream output = response.OutputStream;
430-
int len;
431-
while ((len = stream.Read(buffer, 0, buffer.Length)) > 0)
432-
{
433-
output.Write(buffer, 0, len);
434-
}
435-
436-
output.Flush();
437-
output.Close();
438-
response.Close();
437+
output.Write(buffer, 0, len);
439438
}
440-
catch (HttpListenerException)
441-
{ }
442-
catch (InvalidOperationException)
443-
{ }
444439

445-
return;
440+
output.Flush();
441+
output.Close();
442+
response.Close();
446443
}
444+
catch (HttpListenerException)
445+
{ }
446+
catch (InvalidOperationException)
447+
{ }
448+
449+
return;
447450
}
448451
}
449452

@@ -461,28 +464,27 @@ private void ServeResourceImage(HttpListenerResponse response, string name)
461464
{
462465
if (names[i].Replace('\\', '.') == name)
463466
{
464-
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(names[i]))
467+
using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(names[i]);
468+
469+
Image image = Image.FromStream(stream);
470+
response.ContentType = "image/png";
471+
try
465472
{
466-
Image image = Image.FromStream(stream);
467-
response.ContentType = "image/png";
468-
try
473+
Stream output = response.OutputStream;
474+
using (MemoryStream ms = new())
469475
{
470-
Stream output = response.OutputStream;
471-
using (MemoryStream ms = new MemoryStream())
472-
{
473-
image.Save(ms, ImageFormat.Png);
474-
ms.WriteTo(output);
475-
}
476-
477-
output.Close();
476+
image.Save(ms, ImageFormat.Png);
477+
ms.WriteTo(output);
478478
}
479-
catch (HttpListenerException)
480-
{ }
481479

482-
image.Dispose();
483-
response.Close();
484-
return;
480+
output.Close();
485481
}
482+
catch (HttpListenerException)
483+
{ }
484+
485+
image.Dispose();
486+
response.Close();
487+
return;
486488
}
487489
}
488490

@@ -492,7 +494,7 @@ private void ServeResourceImage(HttpListenerResponse response, string name)
492494

493495
private void SendJson(HttpListenerResponse response, HttpListenerRequest request = null)
494496
{
495-
JObject json = new JObject();
497+
JObject json = new();
496498

497499
int nodeIndex = 0;
498500

@@ -503,12 +505,12 @@ private void SendJson(HttpListenerResponse response, HttpListenerRequest request
503505
json["Max"] = "Max";
504506
json["ImageURL"] = string.Empty;
505507

506-
JArray children = new JArray { GenerateJsonForNode(_root, ref nodeIndex) };
507-
json["Children"] = children;
508+
json["Children"] = new JArray { GenerateJsonForNode(_root, ref nodeIndex) };
509+
508510
#if DEBUG
509511
string responseContent = json.ToString(Newtonsoft.Json.Formatting.Indented);
510512
#else
511-
string responseContent = json.ToString(Newtonsoft.Json.Formatting.None);
513+
string responseContent = json.ToString(Newtonsoft.Json.Formatting.None);
512514
#endif
513515
byte[] buffer = Encoding.UTF8.GetBytes(responseContent);
514516

@@ -532,13 +534,11 @@ private void SendJson(HttpListenerResponse response, HttpListenerRequest request
532534
{
533535
if (acceptGzip)
534536
{
535-
using (var ms = new MemoryStream())
536-
{
537-
using (var zip = new GZipStream(ms, CompressionMode.Compress, true))
538-
zip.Write(buffer, 0, buffer.Length);
537+
using var ms = new MemoryStream();
538+
using (var zip = new GZipStream(ms, CompressionMode.Compress, true))
539+
zip.Write(buffer, 0, buffer.Length);
539540

540-
buffer = ms.ToArray();
541-
}
541+
buffer = ms.ToArray();
542542
}
543543

544544
response.ContentLength64 = buffer.Length;
@@ -552,9 +552,35 @@ private void SendJson(HttpListenerResponse response, HttpListenerRequest request
552552
response.Close();
553553
}
554554

555+
private void SendJsonSensor(HttpListenerResponse response, JObject sensorData)
556+
{
557+
// Convert the JObject to a JSON string
558+
string responseContent = sensorData.ToString(Newtonsoft.Json.Formatting.None);
559+
byte[] buffer = Encoding.UTF8.GetBytes(responseContent);
560+
561+
// Add headers and set content type
562+
response.AddHeader("Cache-Control", "no-cache");
563+
response.AddHeader("Access-Control-Allow-Origin", "*");
564+
response.ContentType = "application/json";
565+
566+
// Write the response content to the output stream
567+
try
568+
{
569+
response.ContentLength64 = buffer.Length;
570+
Stream output = response.OutputStream;
571+
output.Write(buffer, 0, buffer.Length);
572+
output.Close();
573+
}
574+
catch (HttpListenerException)
575+
{ }
576+
577+
// Close the response
578+
response.Close();
579+
}
580+
555581
private JObject GenerateJsonForNode(Node n, ref int nodeIndex)
556582
{
557-
JObject jsonNode = new JObject
583+
JObject jsonNode = new()
558584
{
559585
["id"] = nodeIndex++,
560586
["Text"] = n.Text,
@@ -563,29 +589,28 @@ private JObject GenerateJsonForNode(Node n, ref int nodeIndex)
563589
["Max"] = string.Empty
564590
};
565591

566-
if (n is SensorNode sensorNode)
567-
{
568-
jsonNode["SensorId"] = sensorNode.Sensor.Identifier.ToString();
569-
jsonNode["Type"] = sensorNode.Sensor.SensorType.ToString();
570-
jsonNode["Min"] = sensorNode.Min;
571-
jsonNode["Value"] = sensorNode.Value;
572-
jsonNode["Max"] = sensorNode.Max;
573-
jsonNode["ImageURL"] = "images/transparent.png";
574-
}
575-
else if (n is HardwareNode hardwareNode)
576-
{
577-
jsonNode["ImageURL"] = "images_icon/" + GetHardwareImageFile(hardwareNode);
578-
}
579-
else if (n is TypeNode typeNode)
580-
{
581-
jsonNode["ImageURL"] = "images_icon/" + GetTypeImageFile(typeNode);
582-
}
583-
else
584-
{
585-
jsonNode["ImageURL"] = "images_icon/computer.png";
592+
switch (n)
593+
{
594+
case SensorNode sensorNode:
595+
jsonNode["SensorId"] = sensorNode.Sensor.Identifier.ToString();
596+
jsonNode["Type"] = sensorNode.Sensor.SensorType.ToString();
597+
jsonNode["Min"] = sensorNode.Min;
598+
jsonNode["Value"] = sensorNode.Value;
599+
jsonNode["Max"] = sensorNode.Max;
600+
jsonNode["ImageURL"] = "images/transparent.png";
601+
break;
602+
case HardwareNode hardwareNode:
603+
jsonNode["ImageURL"] = "images_icon/" + GetHardwareImageFile(hardwareNode);
604+
break;
605+
case TypeNode typeNode:
606+
jsonNode["ImageURL"] = "images_icon/" + GetTypeImageFile(typeNode);
607+
break;
608+
default:
609+
jsonNode["ImageURL"] = "images_icon/computer.png";
610+
break;
586611
}
587612

588-
JArray children = new JArray();
613+
JArray children = [];
589614
foreach (Node child in n.Nodes)
590615
{
591616
children.Add(GenerateJsonForNode(child, ref nodeIndex));
@@ -690,20 +715,17 @@ private static string GetTypeImageFile(TypeNode tn)
690715

691716
private string ComputeSHA256(string text)
692717
{
693-
using (SHA256 hash = SHA256.Create())
694-
{
695-
return string.Concat(hash
696-
.ComputeHash(Encoding.UTF8.GetBytes(text))
697-
.Select(item => item.ToString("x2")));
698-
}
718+
using SHA256 hash = SHA256.Create();
719+
return string.Concat(hash
720+
.ComputeHash(Encoding.UTF8.GetBytes(text))
721+
.Select(item => item.ToString("x2")));
699722
}
700723

701724
public void Quit()
702725
{
703726
if (PlatformNotSupported)
704727
return;
705728

706-
707729
StopHttpListener();
708730
_listener.Abort();
709731
}

LibreHardwareMonitorLib/Hardware/Cpu/IntelCpu.cs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,24 @@ public IntelCpu(int processorIndex, CpuId[][] cpuId, ISettings settings) : base(
310310

311311
int coreSensorId = 0;
312312

313+
//core temp avg and max value
314+
//is only available when the cpu has more than 1 core
315+
if (cpuId[0][0].Data.GetLength(0) > 6 && (cpuId[0][0].Data[6, 0] & 0x40) != 0 && _microArchitecture != MicroArchitecture.Unknown && _coreCount > 1)
316+
{
317+
_coreMax = new Sensor("Core Max", coreSensorId, SensorType.Temperature, this, settings);
318+
ActivateSensor(_coreMax);
319+
coreSensorId++;
320+
321+
_coreAvg = new Sensor("Core Average", coreSensorId, SensorType.Temperature, this, settings);
322+
ActivateSensor(_coreAvg);
323+
coreSensorId++;
324+
}
325+
else
326+
{
327+
_coreMax = null;
328+
_coreAvg = null;
329+
}
330+
313331
// check if processor supports a digital thermal sensor at core level
314332
if (cpuId[0][0].Data.GetLength(0) > 6 && (cpuId[0][0].Data[6, 0] & 1) != 0 && _microArchitecture != MicroArchitecture.Unknown)
315333
{
@@ -366,23 +384,6 @@ public IntelCpu(int processorIndex, CpuId[][] cpuId, ISettings settings) : base(
366384
else
367385
_distToTjMaxTemperatures = Array.Empty<Sensor>();
368386

369-
//core temp avg and max value
370-
//is only available when the cpu has more than 1 core
371-
if (cpuId[0][0].Data.GetLength(0) > 6 && (cpuId[0][0].Data[6, 0] & 0x40) != 0 && _microArchitecture != MicroArchitecture.Unknown && _coreCount > 1)
372-
{
373-
_coreMax = new Sensor("Core Max", coreSensorId, SensorType.Temperature, this, settings);
374-
ActivateSensor(_coreMax);
375-
coreSensorId++;
376-
377-
_coreAvg = new Sensor("Core Average", coreSensorId, SensorType.Temperature, this, settings);
378-
ActivateSensor(_coreAvg);
379-
}
380-
else
381-
{
382-
_coreMax = null;
383-
_coreAvg = null;
384-
}
385-
386387
_busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
387388
_coreClocks = new Sensor[_coreCount];
388389
for (int i = 0; i < _coreClocks.Length; i++)

0 commit comments

Comments
 (0)