From c2a68d3022f49f72103997c098dac9e531ac9c20 Mon Sep 17 00:00:00 2001 From: Luca Date: Tue, 4 Jun 2024 13:29:14 -0700 Subject: [PATCH] Battery Percentage Pattern for Slash Lighting (#2685) * quicksave / testing * implemented battery charge pattern * changed defaults * immediately refresh pattern * cleaned up comments --- app/AnimeMatrix/AniMatrixControl.cs | 59 +++++++++++++++++++++++++++-- app/AnimeMatrix/SlashDevice.cs | 50 +++++++++++++++++++++++- 2 files changed, 104 insertions(+), 5 deletions(-) diff --git a/app/AnimeMatrix/AniMatrixControl.cs b/app/AnimeMatrix/AniMatrixControl.cs index 212125619..bea9cd6b1 100644 --- a/app/AnimeMatrix/AniMatrixControl.cs +++ b/app/AnimeMatrix/AniMatrixControl.cs @@ -14,6 +14,7 @@ public class AniMatrixControl : NAudio.CoreAudioApi.Interfaces.IMMNotificationCl SettingsForm settings; System.Timers.Timer matrixTimer = default!; + System.Timers.Timer slashTimer = default!; public AnimeMatrixDevice? deviceMatrix; public SlashDevice? deviceSlash; @@ -45,6 +46,7 @@ public AniMatrixControl(SettingsForm settingsForm) matrixTimer = new System.Timers.Timer(100); matrixTimer.Elapsed += MatrixTimer_Elapsed; + } catch (Exception ex) { @@ -101,7 +103,7 @@ public void SetSlash(bool wakeUp = false) deviceSlash.SetEnabled(true); deviceSlash.Init(); - + switch ((SlashMode)running) { case SlashMode.Static: @@ -114,12 +116,18 @@ public void SetSlash(bool wakeUp = false) deviceSlash.SetStatic(brightness); } break; + case SlashMode.BatteryLevel: + // call tick to immediately update the pattern + SlashTimer_start(); + SlashTimer_tick(); + break; default: deviceSlash.SetMode((SlashMode)running); deviceSlash.SetOptions(true, brightness, inteval); deviceSlash.Save(); break; } + // kill the timer if we are not displaying battery pattern deviceSlash.SetSleepActive(true); } @@ -237,7 +245,6 @@ private void StopMatrixTimer() matrixTimer.Stop(); } - private void MatrixTimer_Elapsed(object? sender, ElapsedEventArgs e) { @@ -255,13 +262,58 @@ private void MatrixTimer_Elapsed(object? sender, ElapsedEventArgs e) } - public void SetMatrixClock() { deviceMatrix.SetBuiltInAnimation(false); StartMatrixTimer(1000); Logger.WriteLine("Matrix Clock"); } + + + private void SlashTimer_start(int interval = 60000) + { + // 100% to 0% in 1hr = 1% every 36 seconds + // 1 bracket every 14.2857 * 36s = 514s ~ 8m 30s + // only ~5 actually distinguishable levels, so refresh every <= 514/5 ~ 100s + // default is 60s + + // create the timer if first call + // this way, the timer only spawns if user tries to use battery pattern + if(slashTimer == default(System.Timers.Timer)) + { + slashTimer = new System.Timers.Timer(interval); + slashTimer.Elapsed += SlashTimer_elapsed; + slashTimer.AutoReset = true; + } + // only write if interval changed + if(slashTimer.Interval != interval) + { + slashTimer.Interval = interval; + } + + slashTimer.Start(); + } + + private void SlashTimer_elapsed(object? sender, ElapsedEventArgs e) + { + SlashTimer_tick(); + } + + private void SlashTimer_tick() + { + if (deviceSlash is null) return; + + //kill timer if called but not in battery pattern mode + if((SlashMode)AppConfig.Get("matrix_running", 0) != SlashMode.BatteryLevel) + { + slashTimer.Stop(); + slashTimer.Dispose(); + return; + } + + deviceSlash.SetBatteryPattern(AppConfig.Get("matrix_brightness", 0)); + } + public void Dispose() { @@ -397,7 +449,6 @@ void PresentAudio(double[] audio) deviceMatrix.Present(); } - public void OpenMatrixPicture() { string fileName = null; diff --git a/app/AnimeMatrix/SlashDevice.cs b/app/AnimeMatrix/SlashDevice.cs index 5e86f0618..13053a3eb 100644 --- a/app/AnimeMatrix/SlashDevice.cs +++ b/app/AnimeMatrix/SlashDevice.cs @@ -1,5 +1,7 @@ using GHelper.AnimeMatrix.Communication; +using System.Management; using System.Text; +using System.Timers; namespace GHelper.AnimeMatrix { @@ -20,7 +22,8 @@ public enum SlashMode GameOver, Start, Buzzer, - Static + Static, + BatteryLevel, } internal class SlashPacket : Packet @@ -54,7 +57,9 @@ public class SlashDevice : Device { SlashMode.GameOver, "Game Over"}, { SlashMode.Start, "Start"}, { SlashMode.Buzzer, "Buzzer"}, + { SlashMode.Static, "Static"}, + { SlashMode.BatteryLevel, "Battery Level"} }; private static Dictionary modeCodes = new Dictionary @@ -127,7 +132,50 @@ public void SetMode(SlashMode mode) public void SetStatic(int brightness = 0) { SetCustom(Enumerable.Repeat((byte)(brightness * 85.333), 7).ToArray()); + } + + public static double GetBatteryChargePercentage() + { + double batteryCharge = 0; + try + { + ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Battery"); + foreach (ManagementObject battery in searcher.Get()) + { + batteryCharge = Convert.ToDouble(battery["EstimatedChargeRemaining"]); + break; // Assuming only one battery + } + } + catch (ManagementException e) + { + Console.WriteLine("An error occurred while querying for WMI data: " + e.Message); + } + return batteryCharge; + } + + private byte[] GetBatteryPattern(int brightness, double percentage) + { + // because 7 segments, within each led segment represents a percentage bracket of (100/7 = 14.2857%) + // set brightness to reflect battery's percentage within that range + int bracket = (int)Math.Floor(percentage / 14.2857); + if(bracket >= 7) return Enumerable.Repeat((byte)(brightness * 85.333), 7).ToArray(); + + byte[] batteryPattern = Enumerable.Repeat((byte)(0x00), 7).ToArray(); + for (int i = 6; i > 6-bracket; i--) + { + batteryPattern[i] = (byte)(brightness * 85.333); + } + + //set the "selected" bracket to the percentage of that bracket filled from 0 to 255 as a hex + batteryPattern[6-bracket] = (byte)(((percentage % 14.2857) * brightness * 85.333) / 14.2857); + + return batteryPattern; + } + + public void SetBatteryPattern(int brightness) + { + SetCustom(GetBatteryPattern(brightness, 100*(GetBatteryChargePercentage()/AppConfig.Get("charge_limit",100)))); } public void SetCustom(byte[] data)