From 8bce655acbeeea0bc054bd71498a3d54dd86be97 Mon Sep 17 00:00:00 2001 From: Remi Date: Mon, 29 Jan 2024 11:00:44 -0500 Subject: [PATCH 1/3] Refactor + cleanup * open serial once per update cycle * send rpm command once, update every fan with with the same response * set fan speed during update, with the same serial connection * use standard identifiers * fix lifecycle of the plugin object, use Initialize + Close properly --- OpenFanManagementControlSensor.cs | 32 +++++------ OpenFanManagementFanSensor.cs | 25 ++++----- OpenFanPlugin.cs | 83 +++++++++++++++------------- OpenFan_Serial.cs | 92 ++++++++++++++----------------- 4 files changed, 110 insertions(+), 122 deletions(-) diff --git a/OpenFanManagementControlSensor.cs b/OpenFanManagementControlSensor.cs index 23f35b9..10e2329 100644 --- a/OpenFanManagementControlSensor.cs +++ b/OpenFanManagementControlSensor.cs @@ -1,48 +1,44 @@ -using FanControl.OpenFanPlugin; -using FanControl.Plugins; -using System; -using System.Net; +using FanControl.Plugins; namespace FanControl.OpenFanPlugin { public class OpenFanManagementControlSensor: IPluginControlSensor { private readonly int _fanIndex; - private float? _val; + private float? _lastSetValue; public OpenFanManagementControlSensor(int fanIndex) => _fanIndex = fanIndex; public float? Value { get; private set; } - public string Name => $"OpenFAN Fan #{(int)_fanIndex + 1}"; + public string Name => $"OpenFAN Fan #{_fanIndex + 1}"; public string Origin => $"OpenFAN"; - public string Id => "Control_" + _fanIndex.ToString(); + public string Id => "OpenFan/Control/" + _fanIndex.ToString(); public void Reset() { - //DellSmbiosBzh.EnableAutomaticFanControl(_fanIndex == BzhFanIndex.Fan1 ? false : true); + // set back the original control value, is there a command to get the current value we could use + // to get the original value at the start? } public void Set(float val) { - if (val != _val) - { - SetFanSpeed(val); - _val = val; - } + _lastSetValue = val; } - public void Update() => Value = _val; + public void Update(){ } - private void SetFanSpeed(float speed) + public void SetFanSpeed(OpenFan_Serial serial) { - OpenFan_Serial OpenFan = new OpenFan_Serial(); - OpenFan.SetPercent(_fanIndex, (int)speed); - OpenFan.Close(); + if (Value != _lastSetValue) + { + serial.SetPercent(_fanIndex, (int)_lastSetValue); + Value = _lastSetValue; + } } } } diff --git a/OpenFanManagementFanSensor.cs b/OpenFanManagementFanSensor.cs index 8692ab1..bda7bd5 100644 --- a/OpenFanManagementFanSensor.cs +++ b/OpenFanManagementFanSensor.cs @@ -1,7 +1,5 @@ using FanControl.Plugins; -using System; -using System.Net; -using FanControl.OpenFanPlugin; +using System.Collections.Generic; namespace FanControl.OpenFanPlugin { @@ -9,28 +7,27 @@ public class OpenFanManagementFanSensor : IPluginSensor { private readonly int _fanIndex; - public OpenFanManagementFanSensor(int fanIndex) => _fanIndex = fanIndex; + public OpenFanManagementFanSensor(int fanIndex) + { + _fanIndex = fanIndex; + } - public string Identifier => $"OpenFan/Fan{(int)_fanIndex}"; + public string Identifier => $"OpenFan/Fan/{_fanIndex}"; public float? Value { get; private set; } - public string Name => $"OpenFan FAN #{(int)_fanIndex + 1}"; + public string Name => $"OpenFan FAN #{_fanIndex + 1}"; public string Origin => $"OpenFan"; public string Id => "Fan_" + _fanIndex.ToString(); - public void Update() => Value = GetFanRPM(); + public void Update() { } - private int GetFanRPM() + public void UpdateFanRPM(SerialResponse response) { - int rpm = 0; - OpenFan_Serial OpenFan = new OpenFan_Serial(); - rpm = OpenFan.ReadRPM(_fanIndex); - OpenFan.Close(); - - return rpm; + int rpm = response.Data[_fanIndex]; + Value = rpm; } } } diff --git a/OpenFanPlugin.cs b/OpenFanPlugin.cs index ddc2965..851dc0d 100644 --- a/OpenFanPlugin.cs +++ b/OpenFanPlugin.cs @@ -1,14 +1,15 @@ using FanControl.Plugins; using System; -using System.Collections.Generic; using System.Linq; namespace FanControl.OpenFanPlugin { - public class OpenFanPlugin : IPlugin2, IDisposable + public class OpenFanPlugin : IPlugin2 { private bool _OpenFanInitialized; - private Boolean m_DisposedValue; + private OpenFan_Serial _serial; + private OpenFanManagementControlSensor[] _fanControls; + private OpenFanManagementFanSensor[] _fanSensors; public string Name => "OpenFAN"; private readonly IPluginLogger _logger; @@ -25,6 +26,13 @@ public void Close() if (_OpenFanInitialized) { _OpenFanInitialized = false; + lock (_serial) + { + _serial.Dispose(); + } + + _fanControls = null; + _fanSensors = null; } } @@ -32,58 +40,55 @@ public void Initialize() { _OpenFanInitialized = true; _logger.Log("OpenFAN plugin loaded."); + + lock(_serial) + { + _serial = new OpenFan_Serial(); + } } - public void Load(IPluginSensorsContainer _container) + public void Load(IPluginSensorsContainer container) { if (_OpenFanInitialized) { - IEnumerable fanControls = new[] { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 - }.Select(i => new OpenFanManagementControlSensor(i)).ToArray(); + _fanControls = Enumerable.Range(0, 10) + .Select(i => new OpenFanManagementControlSensor(i)).ToArray(); - IEnumerable fanSensors = new[] { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 - }.Select(i => new OpenFanManagementFanSensor(i)).ToArray(); + _fanSensors = Enumerable.Range(0, 10) + .Select(i => new OpenFanManagementFanSensor(i)).ToArray(); - _container.ControlSensors.AddRange(fanControls); - _container.FanSensors.AddRange(fanSensors); + container.ControlSensors.AddRange(_fanControls); + container.FanSensors.AddRange(_fanSensors); } } public void Update() { - - } - - protected virtual void Dispose(Boolean disposing) - { - if (!m_DisposedValue) + lock (_serial) { - if (disposing) + try { - // TODO: dispose managed state (managed objects) - } + _serial.Open(); - // TODO: free unmanaged resources (unmanaged objects) and override finalizer - // TODO: set large fields to null - Close(); - m_DisposedValue = true; + var rpms = _serial.ReadRPM(); + foreach(OpenFanManagementFanSensor fan in _fanSensors) + { + fan.UpdateFanRPM(rpms); + } + foreach(OpenFanManagementControlSensor control in _fanControls) + { + control.SetFanSpeed(_serial); + } + } + catch (Exception exception) + { + // do something + } + finally + { + _serial.Close(); + } } } - - // // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources - ~OpenFanPlugin() - { - // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method - Dispose(disposing: false); - } - - public void Dispose() - { - // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method - Dispose(disposing: true); - GC.SuppressFinalize(this); - } } } diff --git a/OpenFan_Serial.cs b/OpenFan_Serial.cs index 8e621c6..2268873 100644 --- a/OpenFan_Serial.cs +++ b/OpenFan_Serial.cs @@ -1,18 +1,22 @@ -using FanControl.Plugins; -using Microsoft.Win32; +using Microsoft.Win32; using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; -using System.Security.Cryptography; using System.Text.RegularExpressions; namespace FanControl.OpenFanPlugin { + public class OpenFanException: Exception + { + private OpenFanException(string message) : base(message) { } + + public static OpenFanException SerialNotOpened(string command) => new OpenFanException($"OpenFAN not opened, cannot send command {command}"); + } public class SerialResponse { - private String _res; + private string _res; private int _cmd = 0; private List _data = new List(); @@ -41,34 +45,12 @@ private void _parse() } } - public int getCMD() - { - try - { - return _cmd; - } - catch (Exception e) - { - return 0; - } - } - + public int CMD => _cmd; - public int getData(int pos) - { - try - { - return _data[pos]; - } - catch (Exception e) - { - Console.WriteLine(e); - return 0; - } - } + public IReadOnlyList Data => _data; } - public class OpenFan_Serial + public class OpenFan_Serial : IDisposable { private SerialPort _serialPort = new SerialPort(); private bool IsConnectionOpen = false; @@ -93,7 +75,7 @@ public OpenFan_Serial(string COMPort = "COM15") ~OpenFan_Serial() { - _serialPort.Close(); + Close(); } public void Close() @@ -104,36 +86,43 @@ public void Close() } } - public int ReadRPM(int index) + public SerialResponse ReadRPM() { - SerialResponse res = SendRequest(">00\r\n"); - return res.getData(index); + const string READ_RPM_CMD = ">00\r\n"; + if (!IsConnectionOpen ) + { + throw OpenFanException.SerialNotOpened(READ_RPM_CMD); + } + + SerialResponse res = SendRequest(READ_RPM_CMD); + return res; } - public void SetPercent(int index, int value) + public SerialResponse SetPercent(int index, int value) { value = (value * 255 / 100); - String request = String.Format(">02{0:X2}{1:X2}\r\n", index, value); - SendRequest(request); + string request = string.Format(">02{0:X2}{1:X2}\r\n", index, value); + return SendRequest(request); } + public void Open() + { + _serialPort.Open(); + IsConnectionOpen = true; + } private SerialResponse SendRequest(string cmd) { bool _response_found = false; - String res = ""; + string res = ""; - - _serialPort.Open(); - IsConnectionOpen = true; _serialPort.DiscardInBuffer(); _serialPort.DiscardOutBuffer(); _serialPort.Write(cmd); // Wait for response - while (_serialPort.BytesToRead == 0) ; - + while (_serialPort.BytesToRead == 0); while (_response_found == false) { @@ -141,40 +130,37 @@ private SerialResponse SendRequest(string cmd) if (res.StartsWith("<")) { _response_found = true; - break; } } - _serialPort.Close(); - return new SerialResponse(res.TrimEnd(Environment.NewLine.ToCharArray())); } - static List ComPortNames(String VID, String PID) + static List ComPortNames( string VID, string PID ) { - String pattern = String.Format("^VID_{0}.PID_{1}", VID, PID); + string pattern = string.Format("^VID_{0}.PID_{1}", VID, PID); Regex _rx = new Regex(pattern, RegexOptions.IgnoreCase); List comports = new List(); RegistryKey rk1 = Registry.LocalMachine; RegistryKey rk2 = rk1.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum"); - foreach (String s3 in rk2.GetSubKeyNames()) + foreach ( string s3 in rk2.GetSubKeyNames()) { RegistryKey rk3 = rk2.OpenSubKey(s3); - foreach (String s in rk3.GetSubKeyNames()) + foreach ( string s in rk3.GetSubKeyNames()) { if (_rx.Match(s).Success) { RegistryKey rk4 = rk3.OpenSubKey(s); - foreach (String s2 in rk4.GetSubKeyNames()) + foreach ( string s2 in rk4.GetSubKeyNames()) { RegistryKey rk5 = rk4.OpenSubKey(s2); string location = (string)rk5.GetValue("LocationInformation"); RegistryKey rk6 = rk5.OpenSubKey("Device Parameters"); string portName = (string)rk6.GetValue("PortName"); - if (!String.IsNullOrEmpty(portName) && SerialPort.GetPortNames().Contains(portName)) + if (!string.IsNullOrEmpty(portName) && SerialPort.GetPortNames().Contains(portName)) comports.Add((string)rk6.GetValue("PortName")); } } @@ -183,5 +169,9 @@ static List ComPortNames(String VID, String PID) return comports; } + public void Dispose() + { + Close(); + } } } From c4ad8adda960e7ce6da10c7ba8b040dff6e89a55 Mon Sep 17 00:00:00 2001 From: Remi Date: Mon, 29 Jan 2024 11:01:05 -0500 Subject: [PATCH 2/3] Pull FanIndexes var as static readonly --- OpenFanPlugin.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OpenFanPlugin.cs b/OpenFanPlugin.cs index 851dc0d..e6fd4f9 100644 --- a/OpenFanPlugin.cs +++ b/OpenFanPlugin.cs @@ -11,6 +11,8 @@ public class OpenFanPlugin : IPlugin2 private OpenFanManagementControlSensor[] _fanControls; private OpenFanManagementFanSensor[] _fanSensors; + private static readonly int[] _fanIndexes = Enumerable.Range(0, 10).ToArray(); + public string Name => "OpenFAN"; private readonly IPluginLogger _logger; private readonly IPluginDialog _dialog; @@ -51,10 +53,10 @@ public void Load(IPluginSensorsContainer container) { if (_OpenFanInitialized) { - _fanControls = Enumerable.Range(0, 10) + _fanControls = _fanIndexes .Select(i => new OpenFanManagementControlSensor(i)).ToArray(); - _fanSensors = Enumerable.Range(0, 10) + _fanSensors = _fanIndexes .Select(i => new OpenFanManagementFanSensor(i)).ToArray(); container.ControlSensors.AddRange(_fanControls); From ebf671df776acf3fce54cf658b1633653375a68a Mon Sep 17 00:00:00 2001 From: Rem0o Date: Mon, 29 Jan 2024 22:17:44 -0500 Subject: [PATCH 3/3] Use seperate lock object --- OpenFanPlugin.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/OpenFanPlugin.cs b/OpenFanPlugin.cs index e6fd4f9..2ff0574 100644 --- a/OpenFanPlugin.cs +++ b/OpenFanPlugin.cs @@ -7,6 +7,7 @@ namespace FanControl.OpenFanPlugin public class OpenFanPlugin : IPlugin2 { private bool _OpenFanInitialized; + private object _serialLock = new object(); private OpenFan_Serial _serial; private OpenFanManagementControlSensor[] _fanControls; private OpenFanManagementFanSensor[] _fanSensors; @@ -28,7 +29,7 @@ public void Close() if (_OpenFanInitialized) { _OpenFanInitialized = false; - lock (_serial) + lock (_serialLock) { _serial.Dispose(); } @@ -43,7 +44,7 @@ public void Initialize() _OpenFanInitialized = true; _logger.Log("OpenFAN plugin loaded."); - lock(_serial) + lock(_serialLock) { _serial = new OpenFan_Serial(); } @@ -66,7 +67,7 @@ public void Load(IPluginSensorsContainer container) public void Update() { - lock (_serial) + lock (_serialLock) { try {