using SkiaSharp; using System.Threading.Tasks; public class MatrixRenderer { private readonly WledDdpClient _wled; private readonly int _width = 64; private readonly int _height = 64; public MatrixRenderer(string wledIp) { _wled = new WledDdpClient(wledIp); } // public async Task DrawAndSendFrameAsync(float currentTemp, int currentWater, DateTime currentTime) //public async Task DrawAndSendFrameAsync(string currentTemp) { using SKBitmap bitmap = new SKBitmap(_width, _height, SKColorType.Rgba8888, SKAlphaType.Premul); using SKCanvas canvas = new SKCanvas(bitmap); canvas.Clear(SKColors.Black); // --- DRAW CLOCK --- using SKPaint clockPaint = new SKPaint { Color = SKColors.Cyan, IsAntialias = false }; using SKTypeface typeface = SKTypeface.FromFamilyName("monospace"); using SKFont clockFont = new SKFont(typeface, 16); string timeFormat = (currentTime.Second % 2 == 0) ? "HH:mm" : "HH mm"; string timeString = currentTime.ToString(timeFormat); canvas.DrawText(timeString, 4, 16, SKTextAlign.Left, clockFont, clockPaint); // --- DRAW TEMPERATURE --- using SKPaint textPaint = new SKPaint { Color = SKColors.Orange, IsAntialias = false }; using SKFont textFont = new SKFont { Size = 16 }; canvas.DrawText($"{currentTemp:F1}c", 4, 30, SKTextAlign.Left, textFont, textPaint); canvas.DrawText($"{currentWater:F1}%", 4, 50, SKTextAlign.Left, textFont, textPaint); // 4. Convert 32-bit RGBA to 24-bit RGB for WLED byte[] rgbaBytes = bitmap.Bytes; byte[] rgbBytes = new byte[_width * _height * 3]; int rgbIndex = 0; for (int i = 0; i < rgbaBytes.Length; i += 4) { rgbBytes[rgbIndex++] = rgbaBytes[i]; // R rgbBytes[rgbIndex++] = rgbaBytes[i + 1]; // G rgbBytes[rgbIndex++] = rgbaBytes[i + 2]; // B // We ignore rgbaBytes[i + 3] (Alpha channel) } // 5. Fire it over UDP! await _wled.SendFrameAsync(rgbBytes); } }