using System; using System.Text; using System.Text.Json; using System.Threading; namespace Barsik { /// /// Parses output of "sensors" command and puts CPU core temperatures into /// registers /// 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]\" ", name, i)); config.Append(" {channel=\""); config.AppendFormat("modbus:data:{0}:{1}:Core{2}Temp:number", name, unitName, i); config.Append("\"}\n"); } } } }