From f1972a758057c5d8562760ddcd0648d2332beca4 Mon Sep 17 00:00:00 2001 From: Maksym Slobodianiuk Date: Wed, 27 Sep 2023 20:15:50 +0300 Subject: [PATCH 1/4] Add to support toughfan --- ...ontroller.Plugin.ToughfanController.csproj | 13 ++ .../ToughfanControllerDefinition.cs | 18 +++ .../ToughfanControllerProxy.cs | 113 ++++++++++++++++++ Plugins/Devices/Toughfan.json | 5 + Source/TTController.Common/Enums.cs | 3 +- TTController.sln | 8 ++ 6 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 Plugins/Controllers/TTController.Plugin.ToughfanController/TTController.Plugin.ToughfanController.csproj create mode 100644 Plugins/Controllers/TTController.Plugin.ToughfanController/ToughfanControllerDefinition.cs create mode 100644 Plugins/Controllers/TTController.Plugin.ToughfanController/ToughfanControllerProxy.cs create mode 100644 Plugins/Devices/Toughfan.json diff --git a/Plugins/Controllers/TTController.Plugin.ToughfanController/TTController.Plugin.ToughfanController.csproj b/Plugins/Controllers/TTController.Plugin.ToughfanController/TTController.Plugin.ToughfanController.csproj new file mode 100644 index 0000000..8a7a211 --- /dev/null +++ b/Plugins/Controllers/TTController.Plugin.ToughfanController/TTController.Plugin.ToughfanController.csproj @@ -0,0 +1,13 @@ + + + net48 + TTController.Plugin.ToughfanController + TTController.Plugin.ToughfanController + Copyright © 2023 + false + false + + + + + \ No newline at end of file diff --git a/Plugins/Controllers/TTController.Plugin.ToughfanController/ToughfanControllerDefinition.cs b/Plugins/Controllers/TTController.Plugin.ToughfanController/ToughfanControllerDefinition.cs new file mode 100644 index 0000000..af19370 --- /dev/null +++ b/Plugins/Controllers/TTController.Plugin.ToughfanController/ToughfanControllerDefinition.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using TTController.Common.Plugin; + +namespace TTController.Plugin.ToughfanController +{ + public class ToughfanControllerDefinition : IControllerDefinition + { + public string Name => "Toughfan"; + + public int VendorId => 0x264a; + + public IEnumerable ProductIds => Enumerable.Range(0, 16).Select(x => 0x232b + x); + public int PortCount => 5; + public Type ControllerProxyType => typeof(ToughfanControllerProxy); + } +} \ No newline at end of file diff --git a/Plugins/Controllers/TTController.Plugin.ToughfanController/ToughfanControllerProxy.cs b/Plugins/Controllers/TTController.Plugin.ToughfanController/ToughfanControllerProxy.cs new file mode 100644 index 0000000..03b3cf0 --- /dev/null +++ b/Plugins/Controllers/TTController.Plugin.ToughfanController/ToughfanControllerProxy.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using TTController.Common; +using TTController.Common.Plugin; + +namespace TTController.Plugin.ToughfanController +{ + public class ToughfanControllerProxy : AbstractControllerProxy + { + private readonly IReadOnlyDictionary _availableEffects; + + public ToughfanControllerProxy(IHidDeviceProxy device, IControllerDefinition definition) + : base(device, definition) + { + var effectModes = new Dictionary() + { + ["Flow"] = 0x00, + ["Spectrum"] = 0x04, + ["Ripple"] = 0x08, + ["Blink"] = 0x0c, + ["Pulse"] = 0x10, + ["Wave"] = 0x14, + }; + + var effectSpeeds = new Dictionary() + { + ["Extreme"] = 0x00, + ["Fast"] = 0x01, + ["Normal"] = 0x02, + ["Slow"] = 0x03 + }; + + var result = new Dictionary(); + foreach (var mkv in effectModes) + foreach (var skv in effectSpeeds) + result.Add($"{mkv.Key}_{skv.Key}", (byte)(mkv.Value + skv.Value)); + + result.Add("PerLed", 0x18); + result.Add("Full", 0x19); + + _availableEffects = result; + } + + public override Version Version + { + get + { + var bytes = Device.WriteReadBytes(0x33, 0x50); + if (bytes == null) + return new Version(); + + return new Version(bytes[3], bytes[4], bytes[5]); + } + } + + public override IEnumerable Ports => Enumerable.Range(1, Definition.PortCount) + .Select(x => new PortIdentifier(Device.VendorId, Device.ProductId, (byte)x)); + + public override IEnumerable EffectTypes => _availableEffects.Keys; + + public override bool SetRgb(byte port, string effectType, IEnumerable colors) + { + if (!_availableEffects.TryGetValue(effectType, out var mode)) + return false; + + var bytes = new List { 0x32, 0x52, port, mode }; + foreach (var color in colors) + { + bytes.Add(color.G); + bytes.Add(color.R); + bytes.Add(color.B); + } + + return Device.WriteReadBytes(bytes)?[3] == 0xfc; + } + + public override bool SetSpeed(byte port, byte speed) => + Device.WriteReadBytes(0x32, 0x51, port, 0x01, speed)?[3] == 0xfc; + + public override PortData GetPortData(byte port) + { + var result = Device.WriteReadBytes(0x33, 0x51, port); + if (result == null) + return null; + + if (result[3] == 0xfe) + return null; + + var data = new PortData + { + PortId = result[3], + Speed = result[5], + Rpm = (result[7] << 8) + result[6], + ["Unknown"] = result[4] + }; + + return data; + } + + public override void SaveProfile() => + Device.WriteReadBytes(0x32, 0x53); + + public override bool Init() => + Device.WriteReadBytes(0xfe, 0x33)?[3] == 0xfc; + + public override bool IsValidPort(PortIdentifier port) => + port.ControllerProductId == Device.ProductId + && port.ControllerVendorId == Device.VendorId + && port.Id >= 1 + && port.Id <= Definition.PortCount; + } +} diff --git a/Plugins/Devices/Toughfan.json b/Plugins/Devices/Toughfan.json new file mode 100644 index 0000000..a142688 --- /dev/null +++ b/Plugins/Devices/Toughfan.json @@ -0,0 +1,5 @@ +{ + "Name": "Toughfan", + "LedCount": 24, + "Zones": [ 24 ] +} \ No newline at end of file diff --git a/Source/TTController.Common/Enums.cs b/Source/TTController.Common/Enums.cs index e395fa9..66d9e4c 100644 --- a/Source/TTController.Common/Enums.cs +++ b/Source/TTController.Common/Enums.cs @@ -19,6 +19,7 @@ public enum DeviceType RiingTrio, RiingDuo, FloeRiing, - PurePlus + PurePlus, + Toughfan, } } diff --git a/TTController.sln b/TTController.sln index 45f871d..ab3e0bb 100644 --- a/TTController.sln +++ b/TTController.sln @@ -82,6 +82,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Devices", "Devices", "{A1AD Plugins\Devices\RiingDuo.json = Plugins\Devices\RiingDuo.json Plugins\Devices\RiingQuad.json = Plugins\Devices\RiingQuad.json Plugins\Devices\RiingTrio.json = Plugins\Devices\RiingTrio.json + Plugins\Devices\Toughfan.json = Plugins\Devices\Toughfan.json EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TTController.Plugin.CopyColorEffect", "Plugins\Effects\TTController.Plugin.CopyColorEffect\TTController.Plugin.CopyColorEffect.csproj", "{7CD00102-32DA-4664-83EB-7FDDCE5B9129}" @@ -118,6 +119,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TTController.Plugin.RotateL EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TTController.Plugin.ReverseLedColorModifier", "Plugins\Modifiers\TTController.Plugin.ReverseLedColorModifier\TTController.Plugin.ReverseLedColorModifier.csproj", "{BEA975C9-DADC-4EE3-9B38-D4AD3A72D4C0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TTController.Plugin.ToughfanController", "Plugins\Controllers\TTController.Plugin.ToughfanController\TTController.Plugin.ToughfanController.csproj", "{6B41EC5A-23B0-4705-937E-345B2812B408}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -298,6 +301,10 @@ Global {BEA975C9-DADC-4EE3-9B38-D4AD3A72D4C0}.Debug|Any CPU.Build.0 = Debug|Any CPU {BEA975C9-DADC-4EE3-9B38-D4AD3A72D4C0}.Release|Any CPU.ActiveCfg = Release|Any CPU {BEA975C9-DADC-4EE3-9B38-D4AD3A72D4C0}.Release|Any CPU.Build.0 = Release|Any CPU + {6B41EC5A-23B0-4705-937E-345B2812B408}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6B41EC5A-23B0-4705-937E-345B2812B408}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B41EC5A-23B0-4705-937E-345B2812B408}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6B41EC5A-23B0-4705-937E-345B2812B408}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -353,6 +360,7 @@ Global {194E027F-FD95-449F-9D17-729036DD9CE6} = {EA09CF17-E583-4C9C-B68A-05764654BCE3} {42E8E8E9-E4BB-4D8F-81DC-63880A84A970} = {EA09CF17-E583-4C9C-B68A-05764654BCE3} {BEA975C9-DADC-4EE3-9B38-D4AD3A72D4C0} = {EA09CF17-E583-4C9C-B68A-05764654BCE3} + {6B41EC5A-23B0-4705-937E-345B2812B408} = {72415EA8-F57C-4F2C-9B6C-167BF94FE3F8} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {9B8A6C39-77D8-476B-B89B-C39D2AF3D3B9} From 6b2604ccc6cd5992f8305f56cd22d3268d1ca8c3 Mon Sep 17 00:00:00 2001 From: Maksym Slobodianiuk Date: Thu, 28 Sep 2023 00:54:24 +0300 Subject: [PATCH 2/4] static color effect2? --- Build/Build.csproj.DotSettings | 3 +- .../PingPongEffect.cs | 5 ++ .../CurvePoint.cs | 22 +++++ .../CurvePointConverter.cs | 21 +++++ .../StaticColorEffect2.cs | 84 +++++++++++++++++++ ...ontroller.Plugin.StaticColorEffect2.csproj | 16 ++++ TTController.Plugin.StaticColorEffect2.csproj | 13 +++ TTController.sln | 7 ++ 8 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 Plugins/Effects/TTController.Plugin.StaticColorEffect2/CurvePoint.cs create mode 100644 Plugins/Effects/TTController.Plugin.StaticColorEffect2/CurvePointConverter.cs create mode 100644 Plugins/Effects/TTController.Plugin.StaticColorEffect2/StaticColorEffect2.cs create mode 100644 Plugins/Effects/TTController.Plugin.StaticColorEffect2/TTController.Plugin.StaticColorEffect2.csproj create mode 100644 TTController.Plugin.StaticColorEffect2.csproj diff --git a/Build/Build.csproj.DotSettings b/Build/Build.csproj.DotSettings index c8947fc..7bc2848 100644 --- a/Build/Build.csproj.DotSettings +++ b/Build/Build.csproj.DotSettings @@ -1,4 +1,4 @@ - + DO_NOT_SHOW DO_NOT_SHOW DO_NOT_SHOW @@ -20,6 +20,7 @@ True True True + True True True True diff --git a/Plugins/Effects/TTController.Plugin.PingPongEffect/PingPongEffect.cs b/Plugins/Effects/TTController.Plugin.PingPongEffect/PingPongEffect.cs index 80a078c..7ba484d 100644 --- a/Plugins/Effects/TTController.Plugin.PingPongEffect/PingPongEffect.cs +++ b/Plugins/Effects/TTController.Plugin.PingPongEffect/PingPongEffect.cs @@ -67,6 +67,11 @@ public override IDictionary> GenerateColors(List< colors.AddRange(GenerateColors(12, portStart, portEnd)); colors.AddRange(GenerateColors(6, portStart, portEnd, radius: 0.33, oddDivide: false)); break; + case "Toughfan": + colors.AddRange(GenerateColors(12, portStart, portEnd)); + colors.AddRange(colors.ToList()); + colors.AddRange(GenerateColors(6, portStart, portEnd, radius: 0.33, oddDivide: false)); + break; case "PurePlus": colors.AddRange(GenerateColors(9, portStart, portEnd, radius: 0.33)); break; diff --git a/Plugins/Effects/TTController.Plugin.StaticColorEffect2/CurvePoint.cs b/Plugins/Effects/TTController.Plugin.StaticColorEffect2/CurvePoint.cs new file mode 100644 index 0000000..9088a03 --- /dev/null +++ b/Plugins/Effects/TTController.Plugin.StaticColorEffect2/CurvePoint.cs @@ -0,0 +1,22 @@ +using System.Drawing; + +namespace TTController.Plugin.StaticColorEffect2 +{ + public struct CurvePoint + { + public int Value { get; } + public byte Red { get; } + public byte Green { get; } + public byte Blue { get; } + + public CurvePoint(int value, byte red, byte green, byte blue) + { + Value = value; + Red = red; + Green = green; + Blue = blue; + } + + public override string ToString() => $"[Value: {Value}, Color: ({Red}, {Green}, {Blue})]"; + } +} \ No newline at end of file diff --git a/Plugins/Effects/TTController.Plugin.StaticColorEffect2/CurvePointConverter.cs b/Plugins/Effects/TTController.Plugin.StaticColorEffect2/CurvePointConverter.cs new file mode 100644 index 0000000..5f59cfc --- /dev/null +++ b/Plugins/Effects/TTController.Plugin.StaticColorEffect2/CurvePointConverter.cs @@ -0,0 +1,21 @@ +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace TTController.Plugin.StaticColorEffect2 +{ + public class CurvePointConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, CurvePoint value, JsonSerializer serializer) + { + var array = new JArray { value.Value, value.Red, value.Green, value.Blue }; + writer.WriteRawValue(JsonConvert.SerializeObject(array, Formatting.None)); + } + + public override CurvePoint ReadJson(JsonReader reader, Type objectType, CurvePoint existingValue, bool hasExistingValue, JsonSerializer serializer) + { + var array = JArray.Load(reader); + return new CurvePoint(array[0].Value(), array[1].Value(), array[2].Value(), array[3].Value()); + } + } +} \ No newline at end of file diff --git a/Plugins/Effects/TTController.Plugin.StaticColorEffect2/StaticColorEffect2.cs b/Plugins/Effects/TTController.Plugin.StaticColorEffect2/StaticColorEffect2.cs new file mode 100644 index 0000000..6f16bb9 --- /dev/null +++ b/Plugins/Effects/TTController.Plugin.StaticColorEffect2/StaticColorEffect2.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Linq; +using LibreHardwareMonitor.Hardware; +using TTController.Common; +using TTController.Common.Plugin; + +namespace TTController.Plugin.StaticColorEffect2 +{ + public class StaticColorEffect2Config : EffectConfigBase + { + public List CurvePoints { get; internal set; } = new List(); + public List Sensors { get; internal set; } = new List(); + + [DefaultValue(SensorMixFunction.Maximum)] + public SensorMixFunction SensorMixFunction { get; internal set; } = SensorMixFunction.Maximum; + + [DefaultValue(4)] public int MinimumChange { get; internal set; } = 4; + [DefaultValue(8)] public int MaximumChange { get; internal set; } = 8; + } + + public class StaticColorEffect2 : EffectBase + { + public StaticColorEffect2(StaticColorEffect2Config config) : base(config) + { + } + + public override string EffectType => "PerLed"; + + public override IDictionary> GenerateColors(List ports, + ICacheProvider cache) + { + var values = Config.Sensors.Select(cache.GetSensorValue); + var value = float.NaN; + if (Config.SensorMixFunction == SensorMixFunction.Average) + value = values.Average(); + else if (Config.SensorMixFunction == SensorMixFunction.Minimum) + value = values.Min(); + else if (Config.SensorMixFunction == SensorMixFunction.Maximum) + value = values.Max(); + + if (float.IsNaN(value)) + return ports.ToDictionary(p => p, _ => new List { new LedColor(255, 255, 255) }); + + var curveTargetColor = Color.FromArgb(255, 255, 255, 255); // Default color (e.g., gray) + + for (var i = 0; i <= Config.CurvePoints.Count; i++) + { + var current = i == Config.CurvePoints.Count + ? new CurvePoint(100, Config.CurvePoints[i - 1].Red, Config.CurvePoints[i - 1].Green, + Config.CurvePoints[i - 1].Blue) + : Config.CurvePoints[i]; + + if (value >= current.Value) + continue; + + var last = i == 0 + ? new CurvePoint(0, current.Red, current.Green, current.Blue) + : Config.CurvePoints[i - 1]; + + var t = (value - last.Value) / (current.Value - last.Value); + var red = (byte)Math.Round(last.Red * (1 - t) + current.Red * t); + var green = (byte)Math.Round(last.Green * (1 - t) + current.Green * t); + var blue = (byte)Math.Round(last.Blue * (1 - t) + current.Blue * t); + + curveTargetColor = Color.FromArgb(255, red, green, blue); + + break; + } + + return ports.ToDictionary(p => p, _ => new List + { new LedColor(curveTargetColor.R, curveTargetColor.G, curveTargetColor.B) } + ); + } + + + public override List GenerateColors(int count, ICacheProvider cache) + { + return null; + } + } +} \ No newline at end of file diff --git a/Plugins/Effects/TTController.Plugin.StaticColorEffect2/TTController.Plugin.StaticColorEffect2.csproj b/Plugins/Effects/TTController.Plugin.StaticColorEffect2/TTController.Plugin.StaticColorEffect2.csproj new file mode 100644 index 0000000..c6f7ce9 --- /dev/null +++ b/Plugins/Effects/TTController.Plugin.StaticColorEffect2/TTController.Plugin.StaticColorEffect2.csproj @@ -0,0 +1,16 @@ + + + net48 + TTController.Plugin.StaticColorEffect + TTController.Plugin.StaticColorEffect + Copyright © 2020 + false + false + + + + + + + + \ No newline at end of file diff --git a/TTController.Plugin.StaticColorEffect2.csproj b/TTController.Plugin.StaticColorEffect2.csproj new file mode 100644 index 0000000..c42f9d6 --- /dev/null +++ b/TTController.Plugin.StaticColorEffect2.csproj @@ -0,0 +1,13 @@ + + + net48 + TTController.Plugin.StaticColorEffect2 + TTController.Plugin.StaticColorEffect2 + Copyright © 2020 + false + false + + + + + \ No newline at end of file diff --git a/TTController.sln b/TTController.sln index ab3e0bb..a07e038 100644 --- a/TTController.sln +++ b/TTController.sln @@ -121,6 +121,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TTController.Plugin.Reverse EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TTController.Plugin.ToughfanController", "Plugins\Controllers\TTController.Plugin.ToughfanController\TTController.Plugin.ToughfanController.csproj", "{6B41EC5A-23B0-4705-937E-345B2812B408}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TTController.Plugin.StaticColorEffect2", "Plugins\Effects\TTController.Plugin.StaticColorEffect2\TTController.Plugin.StaticColorEffect2.csproj", "{4912FE98-A9D3-4947-842B-9B5330FEAF1A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -305,6 +307,10 @@ Global {6B41EC5A-23B0-4705-937E-345B2812B408}.Debug|Any CPU.Build.0 = Debug|Any CPU {6B41EC5A-23B0-4705-937E-345B2812B408}.Release|Any CPU.ActiveCfg = Release|Any CPU {6B41EC5A-23B0-4705-937E-345B2812B408}.Release|Any CPU.Build.0 = Release|Any CPU + {4912FE98-A9D3-4947-842B-9B5330FEAF1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4912FE98-A9D3-4947-842B-9B5330FEAF1A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4912FE98-A9D3-4947-842B-9B5330FEAF1A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4912FE98-A9D3-4947-842B-9B5330FEAF1A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -361,6 +367,7 @@ Global {42E8E8E9-E4BB-4D8F-81DC-63880A84A970} = {EA09CF17-E583-4C9C-B68A-05764654BCE3} {BEA975C9-DADC-4EE3-9B38-D4AD3A72D4C0} = {EA09CF17-E583-4C9C-B68A-05764654BCE3} {6B41EC5A-23B0-4705-937E-345B2812B408} = {72415EA8-F57C-4F2C-9B6C-167BF94FE3F8} + {4912FE98-A9D3-4947-842B-9B5330FEAF1A} = {521264D1-73FB-44B3-8243-CB3C95AFB179} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {9B8A6C39-77D8-476B-B89B-C39D2AF3D3B9} From 7facca3a40e4a0b9c8afeebe84bd78d30dbda97a Mon Sep 17 00:00:00 2001 From: Maksym Slobodianiuk Date: Sat, 30 Sep 2023 21:06:21 +0300 Subject: [PATCH 3/4] fix with working state for toughfan --- .../ToughfanControllerProxy.cs | 52 ++++++++++++++-- .../StaticColorEffect2.cs | 59 +++++++++++-------- 2 files changed, 79 insertions(+), 32 deletions(-) diff --git a/Plugins/Controllers/TTController.Plugin.ToughfanController/ToughfanControllerProxy.cs b/Plugins/Controllers/TTController.Plugin.ToughfanController/ToughfanControllerProxy.cs index 03b3cf0..20180b0 100644 --- a/Plugins/Controllers/TTController.Plugin.ToughfanController/ToughfanControllerProxy.cs +++ b/Plugins/Controllers/TTController.Plugin.ToughfanController/ToughfanControllerProxy.cs @@ -33,8 +33,8 @@ public ToughfanControllerProxy(IHidDeviceProxy device, IControllerDefinition def var result = new Dictionary(); foreach (var mkv in effectModes) - foreach (var skv in effectSpeeds) - result.Add($"{mkv.Key}_{skv.Key}", (byte)(mkv.Value + skv.Value)); + foreach (var skv in effectSpeeds) + result.Add($"{mkv.Key}_{skv.Key}", (byte)(mkv.Value + skv.Value)); result.Add("PerLed", 0x18); result.Add("Full", 0x19); @@ -64,15 +64,55 @@ public override bool SetRgb(byte port, string effectType, IEnumerable if (!_availableEffects.TryGetValue(effectType, out var mode)) return false; - var bytes = new List { 0x32, 0x52, port, mode }; - foreach (var color in colors) + var bytes = new List { 0x32, 0x52, port, 0x24 }; + var color = colors.First(); + for (int i = 0; i < 24; i++) { bytes.Add(color.G); bytes.Add(color.R); bytes.Add(color.B); } - return Device.WriteReadBytes(bytes)?[3] == 0xfc; + // var bytes = new byte[] + // { + // 0x32, 0x52, port, 0x24, + // 0x00, 0x00, 0xff, // 1 + // 0x00, 0x00, 0xff, // 2 + // 0x00, 0x00, 0xff, // 3 + // 0x00, 0x00, 0xff, // 4 + // 0x00, 0x00, 0xff, // 5 + // 0x00, 0x00, 0xff, // 6 + // 0x00, 0x00, 0xff, // 7 + // 0x00, 0x00, 0xff, // 8 + // 0x00, 0x00, 0xff, // 9 + // 0x00, 0x00, 0xff, // 10 + // 0x00, 0x00, 0xff, // 11 + // 0x00, 0x00, 0xff, // 12 + // 0x00, 0x00, 0xff, // 13 + // 0x00, 0x00, 0xff, // 14 + // 0x00, 0x00, 0xff, // 15 + // 0x00, 0x00, 0xff, // 16 + // 0x00, 0x00, 0xff, // 17 + // 0x00, 0x00, 0xff, // 18 + // 0x00, 0x00, 0xff, // 19 + // 0x00, 0x00, 0xff, // 20 + // 0x00, 0x00, 0xff, // 21 + // 0x00, 0x00, 0xff, // 22 + // 0x00, 0x00, 0xff, // 23 + // 0x00, 0x00, 0xff, // 24 + var endBytes = new byte[] + { + 0x7f, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x7f, 0xff, 0x00, 0x00, 0xff, 0x7f, 0x00, 0xff, 0xff, + 0x00, 0x7f, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x7f, 0x00, 0xff, 0xff, 0x00, 0x7f, 0xff, 0x00, + 0x00, 0xff, 0x7f, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x7f, 0xff, 0x00, 0x00, 0xff, 0x7f, 0x00, + 0xff, 0xff, 0x00, 0x7f, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x7f, 0x00, 0xff, 0xff, 0x00, 0x7f, + 0xff, 0x00, 0x00, 0xff, 0x7f, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x7f, 0xff, 0x00, 0x00, 0xff, + 0x7f, 0x00, 0xff, 0xff, 0x00, 0x7f, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x7f, 0x00, 0xff, 0xff, + 0x00, 0x7f, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + bytes.AddRange(endBytes); + var result = Device.WriteReadBytes(bytes); + return result?[3] == 0xfc; } public override bool SetSpeed(byte port, byte speed) => @@ -110,4 +150,4 @@ public override bool IsValidPort(PortIdentifier port) => && port.Id >= 1 && port.Id <= Definition.PortCount; } -} +} \ No newline at end of file diff --git a/Plugins/Effects/TTController.Plugin.StaticColorEffect2/StaticColorEffect2.cs b/Plugins/Effects/TTController.Plugin.StaticColorEffect2/StaticColorEffect2.cs index 6f16bb9..20f5edb 100644 --- a/Plugins/Effects/TTController.Plugin.StaticColorEffect2/StaticColorEffect2.cs +++ b/Plugins/Effects/TTController.Plugin.StaticColorEffect2/StaticColorEffect2.cs @@ -29,6 +29,37 @@ public StaticColorEffect2(StaticColorEffect2Config config) : base(config) public override string EffectType => "PerLed"; + private Color InterpolateColor(double temperature) + { + var minTemperature = Config.CurvePoints.Min(x => x.Value); + var maxTemperature = Config.CurvePoints.Max(x => x.Value); + var minConfig = Config.CurvePoints.First(x => x.Value == minTemperature); + var maxConfig = Config.CurvePoints.First(x => x.Value == maxTemperature); + var lowerPoint = Color.FromArgb(minConfig.Red, minConfig.Green, minConfig.Blue); + var upperPoint = Color.FromArgb(maxConfig.Red, maxConfig.Green, maxConfig.Blue); + + for (int i = 0; i < Config.CurvePoints.Count - 1; i++) + { + if (Config.CurvePoints[i].Value <= temperature && temperature <= Config.CurvePoints[i + 1].Value) + { + lowerPoint = Color.FromArgb(Config.CurvePoints[i].Red, Config.CurvePoints[i].Green, + Config.CurvePoints[i].Blue); + upperPoint = Color.FromArgb(Config.CurvePoints[i + 1].Red, Config.CurvePoints[i + 1].Green, + Config.CurvePoints[i + 1].Blue); + break; + } + } + + var t = (temperature - minTemperature) / (maxTemperature - minTemperature); + + var r = (int)(lowerPoint.R + t * (upperPoint.R - lowerPoint.R)); + var g = (int)(lowerPoint.G + t * (upperPoint.G - lowerPoint.G)); + var b = (int)(lowerPoint.B + t * (upperPoint.B - lowerPoint.B)); + + return Color.FromArgb(r, g, b); + } + + public override IDictionary> GenerateColors(List ports, ICacheProvider cache) { @@ -44,32 +75,8 @@ public override IDictionary> GenerateColors(List< if (float.IsNaN(value)) return ports.ToDictionary(p => p, _ => new List { new LedColor(255, 255, 255) }); - var curveTargetColor = Color.FromArgb(255, 255, 255, 255); // Default color (e.g., gray) - - for (var i = 0; i <= Config.CurvePoints.Count; i++) - { - var current = i == Config.CurvePoints.Count - ? new CurvePoint(100, Config.CurvePoints[i - 1].Red, Config.CurvePoints[i - 1].Green, - Config.CurvePoints[i - 1].Blue) - : Config.CurvePoints[i]; - - if (value >= current.Value) - continue; - - var last = i == 0 - ? new CurvePoint(0, current.Red, current.Green, current.Blue) - : Config.CurvePoints[i - 1]; - - var t = (value - last.Value) / (current.Value - last.Value); - var red = (byte)Math.Round(last.Red * (1 - t) + current.Red * t); - var green = (byte)Math.Round(last.Green * (1 - t) + current.Green * t); - var blue = (byte)Math.Round(last.Blue * (1 - t) + current.Blue * t); - - curveTargetColor = Color.FromArgb(255, red, green, blue); - - break; - } - + var curveTargetColor = InterpolateColor(value); + return ports.ToDictionary(p => p, _ => new List { new LedColor(curveTargetColor.R, curveTargetColor.G, curveTargetColor.B) } ); From 56e28e0d4445cb726940789440c36e43554fb173 Mon Sep 17 00:00:00 2001 From: Maksym Slobodianiuk Date: Sun, 22 Oct 2023 12:07:18 +0300 Subject: [PATCH 4/4] Refactor static color effect --- .../StaticColorEffect2.cs | 76 ++++++++++++++----- 1 file changed, 56 insertions(+), 20 deletions(-) diff --git a/Plugins/Effects/TTController.Plugin.StaticColorEffect2/StaticColorEffect2.cs b/Plugins/Effects/TTController.Plugin.StaticColorEffect2/StaticColorEffect2.cs index 20f5edb..4477156 100644 --- a/Plugins/Effects/TTController.Plugin.StaticColorEffect2/StaticColorEffect2.cs +++ b/Plugins/Effects/TTController.Plugin.StaticColorEffect2/StaticColorEffect2.cs @@ -31,34 +31,70 @@ public StaticColorEffect2(StaticColorEffect2Config config) : base(config) private Color InterpolateColor(double temperature) { - var minTemperature = Config.CurvePoints.Min(x => x.Value); - var maxTemperature = Config.CurvePoints.Max(x => x.Value); - var minConfig = Config.CurvePoints.First(x => x.Value == minTemperature); - var maxConfig = Config.CurvePoints.First(x => x.Value == maxTemperature); - var lowerPoint = Color.FromArgb(minConfig.Red, minConfig.Green, minConfig.Blue); - var upperPoint = Color.FromArgb(maxConfig.Red, maxConfig.Green, maxConfig.Blue); - - for (int i = 0; i < Config.CurvePoints.Count - 1; i++) + var curvePoints = Config.CurvePoints.OrderBy(p => p.Value).ToArray(); + var n = curvePoints.Length; + + if (temperature <= curvePoints[0].Value) + { + return CreateColorFromCurvePoint(curvePoints[0]); + } + + if (temperature >= curvePoints[n - 1].Value) + { + return CreateColorFromCurvePoint(curvePoints[n - 1]); + } + + for (var i = 0; i < n - 1; i++) { - if (Config.CurvePoints[i].Value <= temperature && temperature <= Config.CurvePoints[i + 1].Value) + if (IsInRange(temperature, curvePoints[i].Value, curvePoints[i + 1].Value)) { - lowerPoint = Color.FromArgb(Config.CurvePoints[i].Red, Config.CurvePoints[i].Green, - Config.CurvePoints[i].Blue); - upperPoint = Color.FromArgb(Config.CurvePoints[i + 1].Red, Config.CurvePoints[i + 1].Green, - Config.CurvePoints[i + 1].Blue); - break; + var t = CalculateInterpolationParameter(temperature, curvePoints[i].Value, + curvePoints[i + 1].Value); + + var r = InterpolateLinear(curvePoints[i].Red, curvePoints[i + 1].Red, t); + var g = InterpolateLinear(curvePoints[i].Green, curvePoints[i + 1].Green, t); + var b = InterpolateLinear(curvePoints[i].Blue, curvePoints[i + 1].Blue, t); + + return CreateColorFromRgbValues(r, g, b); } } - var t = (temperature - minTemperature) / (maxTemperature - minTemperature); + return Color.White; // Handle cases outside the defined range + } - var r = (int)(lowerPoint.R + t * (upperPoint.R - lowerPoint.R)); - var g = (int)(lowerPoint.G + t * (upperPoint.G - lowerPoint.G)); - var b = (int)(lowerPoint.B + t * (upperPoint.B - lowerPoint.B)); + private Color CreateColorFromCurvePoint(CurvePoint curvePoint) + { + return Color.FromArgb(curvePoint.Red, curvePoint.Green, curvePoint.Blue); + } - return Color.FromArgb(r, g, b); + private bool IsInRange(double value, int minValue, int maxValue) + { + return value >= minValue && value <= maxValue; } + private double CalculateInterpolationParameter(double value, int minValue, int maxValue) + { + return (double)(value - minValue) / (maxValue - minValue); + } + + private double InterpolateLinear(int startValue, int endValue, double t) + { + return startValue + t * (endValue - startValue); + } + + private Color CreateColorFromRgbValues(double r, double g, double b) + { + return Color.FromArgb(Clamp((int)r, 0, 255), Clamp((int)g, 0, 255), Clamp((int)b, 0, 255)); + } + + private int Clamp(int value, int min, int max) + { + if (value < min) + return min; + if (value > max) + return max; + return value; + } public override IDictionary> GenerateColors(List ports, ICacheProvider cache) @@ -76,7 +112,7 @@ public override IDictionary> GenerateColors(List< return ports.ToDictionary(p => p, _ => new List { new LedColor(255, 255, 255) }); var curveTargetColor = InterpolateColor(value); - + return ports.ToDictionary(p => p, _ => new List { new LedColor(curveTargetColor.R, curveTargetColor.G, curveTargetColor.B) } );