Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions src/Kevsoft.WLED/InformationResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public sealed class InformationResponse
/// Version name.
/// </summary>
[JsonPropertyName("ver")]
public string VersionName { get; set; } = null!;
public string? VersionName { get; set; } = null;

/// <summary>
/// Build ID (YYMMDDB, B = daily build index).
Expand All @@ -18,7 +18,7 @@ public sealed class InformationResponse
/// LEDs Information
/// </summary>
[JsonPropertyName("leds")]
public LedsResponse Leds { get; set; } = null!;
public LedsResponse? Leds { get; set; } = null;

/// <summary>
/// If true, an UI with only a single button for toggling sync should toggle receive+send, otherwise send only
Expand All @@ -30,7 +30,7 @@ public sealed class InformationResponse
/// Friendly name of the light.
/// </summary>
[JsonPropertyName("name")]
public string Name { get; set; } = null!;
public string? Name { get; set; } = null;

/// <summary>
/// The UDP port for realtime packets and WLED broadcast.
Expand Down Expand Up @@ -60,13 +60,13 @@ public sealed class InformationResponse
/// Name of the platform.
/// </summary>
[JsonPropertyName("arch")]
public string Arch { get; set; } = null!;
public string? Arch { get; set; } = null;

/// <summary>
/// Version of the underlying (Arduino core) SDK.
/// </summary>
[JsonPropertyName("core")]
public string Core { get; set; } = null!;
public string? Core { get; set; } = null;

/// <summary>
/// Bytes of heap memory (RAM) currently available. Problematic if less than 10k.
Expand All @@ -90,29 +90,29 @@ public sealed class InformationResponse
/// The producer/vendor of the light. Always WLED for standard installations.
/// </summary>
[JsonPropertyName("brand")]
public string Brand { get; set; } = null!;
public string? Brand { get; set; } = null;

/// <summary>
/// The product name. Always FOSS for standard installations.
/// </summary>
[JsonPropertyName("product")]
public string Product { get; set; } = null!;
public string? Product { get; set; } = null;

/// <summary>
/// The origin of the build. src if a release version is compiled from source, bin for an official release image, dev for a development build (regardless of src/bin origin) and exp for experimental versions. ogn if the image is flashed to hardware by the vendor.
/// </summary>
[JsonPropertyName("btype")]
public string BuildType { get; set; } = null!;
public string? BuildType { get; set; } = null;

/// <summary>
/// The hexadecimal hardware MAC address of the light, lowercase and without colons.
/// </summary>
[JsonPropertyName("mac")]
public string MacAddress { get; set; } = null!;
public string? MacAddress { get; set; } = null;

/// <summary>
/// The IP address of this instance. Empty string if not connected. (since 0.13.0)
/// </summary>
[JsonPropertyName("ip")]
public string NetworkAddress { get; set; } = null!;
public string? NetworkAddress { get; set; } = null;
}
4 changes: 2 additions & 2 deletions src/Kevsoft.WLED/Kevsoft.WLED.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="System.Net.Http.Json" Version="6.0.0" />
<PackageReference Include="System.Text.Json" Version="8.0.4" />
<PackageReference Include="System.Net.Http.Json" Version="9.0.0" />
<PackageReference Include="System.Text.Json" Version="9.0.0" />
</ItemGroup>

</Project>
12 changes: 12 additions & 0 deletions src/Kevsoft.WLED/LedsResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,16 @@ public sealed class LedsResponse
/// </summary>
[JsonPropertyName("maxseg")]
public byte MaximumSegments { get; set; }

/// <summary>
/// Preset number loaded on boot.
/// </summary>
[JsonPropertyName("bootps")]
public int BootupPreset { get; set; }

/// <summary>
/// Matrix configuration
/// </summary>
[JsonPropertyName("matrix")]
public MatrixResponse? Matrix { get; set; } = null;
}
12 changes: 12 additions & 0 deletions src/Kevsoft.WLED/MatrixResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Kevsoft.WLED;

public class MatrixResponse
{
/// <summary> The number of LEDs in the width of the matrix </summary>
[JsonPropertyName("w")]
public int Width { get; set; }

/// <summary> The number of LEDs in the Height of the matrix </summary>
[JsonPropertyName("h")]
public int Height { get; set; }
}
3 changes: 3 additions & 0 deletions src/Kevsoft.WLED/SegmentRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ public sealed class SegmentRequest
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? Mirror { get; set; }

[JsonPropertyName("i")]
public object[] IndividualLedControl { get; set; } = [];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this have a type?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a couple different things that can be in this list. Ends up being a mix of ints and strings, but there's not a pattern to how they are ordered - and Wled didn't respond to them all sent as strings im my testing. For what i set up - I'm ignoring the RGB option and going with just hex, but the hex string could be a list of 3 ints

just the Hex Values,
coordinate followed by hex color,
2 ints for start and end of a range followed by the hex color.



public static SegmentRequest From(SegmentResponse segmentResponse)
{
Expand Down
10 changes: 10 additions & 0 deletions src/Kevsoft.WLED/SingleLedRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Kevsoft.WLED;

public sealed class SingleLedRequest
{
/// <summary> The position of the LED in the segment </summary>
public int LedPosition { get; set; }

/// <summary> The color of the LED as HEX (e.g. FF0000 for red) </summary>
public string Color { get; set; } = string.Empty;
}
76 changes: 73 additions & 3 deletions src/Kevsoft.WLED/WLedClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public async Task<string[]> GetPalettes()
var message = await _client.GetAsync("json/pal");

message.EnsureSuccessStatusCode();

return (await message.Content.ReadFromJsonAsync<string[]>())!;
}

Expand All @@ -73,7 +73,7 @@ public async Task Post(WLedRootRequest request)
var result = await _client.PostAsync("/json", content);
result.EnsureSuccessStatusCode();
}

public async Task Post(StateRequest request)
{
var stateString = JsonSerializer.Serialize(request);
Expand All @@ -82,4 +82,74 @@ public async Task Post(StateRequest request)
var result = await _client.PostAsync("/json/state", content);
result.EnsureSuccessStatusCode();
}
}

public async Task Post(List<SingleLedRequest> ledList)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could do with some tests around this Post method to prove out all the logic

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll Look into this. Something in this repository keeps tripping the "warning as an error" thing for venerable nugets on my computer, even though im not seeing that flag on the projects, so may need to nudge a few of those along the way.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think i got a test added now.

{
// Eliminate duplicate positions
ledList = ledList.GroupBy(x => x.LedPosition).Select(x => x.Last()).ToList();

List<object> list = [];
int counter = 0;

//Attempt to group colors together to reduce the number of packets sent as there is a 256 color at a time limit
foreach (IGrouping<string, SingleLedRequest>? leds in ledList.GroupBy(x => x.Color))
{
if (counter >=255)
{
await Post(new StateRequest { On = true, Segments = [new() { Id = 0, IndividualLedControl = [.. list] }] });
list = [];
counter = 0;
}
// If there is only one LED in the group, add it to the list
if (leds.Count() == 1)
{
list.Add(leds.First().LedPosition);
list.Add(leds.First().Color);
counter++;
continue;
}

// If there are multiple LEDs in the group, find the sequential LED's and group them up
// to make the next step easier
List<List<int>> grouped = leds.Select(x => x.LedPosition).OrderBy(x => x)
.Aggregate(new List<List<int>> { new() },
(acc, curr) =>
{
if (!acc.Last().Any() || curr - acc.Last().Last() == 1)
acc.Last().Add(curr);
else
acc.Add([curr]);
return acc;
});

foreach (List<int> group in grouped)
{
//Another round of sending the colors if we are at the limit
if (counter >= 255)
{
await Post(new StateRequest { On = true, Segments = [new() { Id = 0, IndividualLedControl = [.. list] }] });
list = [];
counter = 0;
}

// If there is only one LED in the group, add it to the list
if (group.Count == 1)
{
list.Add(group.First());
list.Add(leds.First().Color);
counter++;
continue;
}

//And if there are multiple LED's, Add them to the list, but when displaying max
//is not displayed so add 1 to the max to get it to display properly
list.Add(group.Min());
list.Add(group.Max() + 1);
list.Add(leds.First().Color);
counter++;
}
}
//And finally send the last packet
await Post(new StateRequest { On = true, Segments = [new() { Id = 0, IndividualLedControl = [.. list] }] });
}
}