Files
barsik/SensorsMonitoringUnit.cs
T

118 lines
3.3 KiB
C#

using System;
using System.Text;
using System.Text.Json;
using System.Threading;
namespace Barsik
{
/// <summary>
/// Parses output of "sensors" command and puts CPU core temperatures into
/// registers
/// </summary>
class SensorsMonitoringUnit : BaseMonitoringUnit
{
const string CORE_STR = "Core{0} Temp:";
const float MULTIPLIER = 100;
int cores;
public SensorsMonitoringUnit(JsonElement config, RegistersContainer registers) : base(config, registers)
{
cores = config.GetProperty("Cores").GetInt32();
}
public override void Run()
{
while (true)
{
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("sensors");
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
using (System.Diagnostics.Process proc = new System.Diagnostics.Process())
{
proc.StartInfo = procStartInfo;
proc.Start();
while (!proc.HasExited)
{
Thread.Sleep(100);
}
string result = proc.StandardOutput.ReadToEnd();
var lines = result.Split('\n');
// lines in output will be of format:
// Core0 Temp: +29.0°C
// and there could be several lines for one core
// so let's take all of them and use maximal value as core temp
float[] t = new float[cores];
for (int i = 0; i < cores; i++)
{
t[i] = 0;
}
for (int i = 0; i < lines.Length; i++)
{
for (int j = 0; j < cores; j++)
{
string toFind = string.Format(CORE_STR, j);
if (lines[i].Contains(toFind))
{
var value = ExtractValue(lines[i].Substring(toFind.Length));
t[j] = Math.Max(t[j], value);
}
}
}
// fill register data starting from baseAddress
for (int i = 0; i < cores; i++)
{
registers[baseAddress + i] = (int)(t[i] * MULTIPLIER);
}
}
Thread.Sleep(2000);
}
}
bool Good(char c)
{
if (c == '-' || c == '+' || c == '.') return true;
if (c >= '0' && c <= '9') return true;
return false;
}
private float ExtractValue(string v)
{
int pos = 0;
while (pos < v.Length && !Good(v[pos])) pos++;
int pos2 = pos;
while (pos2 < v.Length && Good(v[pos2])) pos2++;
float res;
float.TryParse(v.Substring(pos, pos2 - pos), out res);
return res;
}
public override void GenerateThingsConfig(StringBuilder config)
{
config.Append("\tBridge poller ");
config.Append(unitName);
config.AppendFormat("[start = {0}, length = {1}, type = \"holding\", refresh = 500] {{\n", baseAddress, cores);
int currentAddress = baseAddress;
for (int i = 0; i < cores; i++)
{
string name = string.Format("Core{0}Temp", i);
config.Append("\t\tThing data ");
config.Append(name);
config.AppendFormat("[readStart = \"{0}\", readValueType = \"int16\", readTransform=\"JS(divide100.js)\"]\n", currentAddress);
currentAddress++;
}
config.Append("\t}\n");
}
public override void GenerateItemsConfig(string name, StringBuilder config)
{
for (int i = 0; i < cores; i++)
{
config.Append(string.Format("Number {0}_Core{1}Temp \"{0} CPU Core{1} [%.1f °C]\" <temperature>", name, i));
config.Append(" {channel=\"");
config.AppendFormat("modbus:data:{0}:{1}:Core{2}Temp:number", name, unitName, i);
config.Append("\"}\n");
}
}
}
}