Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,5 @@ GeneratedArtifacts/
_Pvt_Extensions/
ModelManifest.xml
*.nupkg

LifxHttpSample/TestProgram.cs
23 changes: 21 additions & 2 deletions LifxHttp/ApiResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,17 @@
using System.Threading.Tasks;

namespace LifxHttp
{
{
/// <summary>
/// Operation returned from setting multiple states. Contains selector and state properties.
/// </summary>
[JsonObject(MemberSerialization.OptIn)]
public sealed class ApiOperation : LightState
{
[JsonProperty("selector")]
string Selector;
}

/// <summary>
/// Returned from API actions
/// </summary>
Expand All @@ -16,7 +26,16 @@ public sealed class ApiResult
internal static bool Successful(ApiResult result)
{
return result.IsSuccessful;
}
}

[JsonProperty("operation")]
public ApiOperation Operation { get; private set; }

/// <summary>
/// When setting multiple states, each result contains operation(s) and the results of each operation.
/// </summary>
[JsonProperty("results")]
public List<ApiResult> Results { get; set; }

[JsonProperty("id")]
public string Id { get; private set; }
Expand Down
16 changes: 16 additions & 0 deletions LifxHttp/ApiResults.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LifxHttp
{
[JsonObject(MemberSerialization.OptIn)]
public sealed class ApiResults
{
[JsonProperty("results")]
public List<ApiResult> Results { get; set; }
}
}
20 changes: 20 additions & 0 deletions LifxHttp/Enums/Direction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace LifxHttp.Enums
{
[JsonConverter(typeof(StringEnumConverter))]
public enum Direction
{
[EnumMember(Value = "forward")]
Forward,
[EnumMember(Value = "backward")]
Backward
}
}
2 changes: 1 addition & 1 deletion LifxHttp/PowerState.cs → LifxHttp/Enums/PowerState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using System.Text;
using System.Threading.Tasks;

namespace LifxHttp
namespace LifxHttp.Enums
{
[JsonConverter(typeof(StringEnumConverter))]
public enum PowerState
Expand Down
16 changes: 8 additions & 8 deletions LifxHttp/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,31 @@ public static List<Group> AsGroups(this IEnumerable<Light> lights)
new Dictionary<Light.CollectionSpec, List<Light>>();
foreach (Light light in lights)
{
if (!groups.ContainsKey(light.group))
if (!groups.ContainsKey(light.Group))
{
groups[light.group] = new List<Light>();
groups[light.Group] = new List<Light>();
}
groups[light.group].Add(light);
groups[light.Group].Add(light);
}
// Grab client from a light
LifxClient client = (groups.Count > 0) ? groups.First().Value.First().Client : null;
return groups.Select(entry => new Group(client, entry.Key.id, entry.Key.name, entry.Value)).ToList();
return groups.Select(entry => new Group(client, entry.Key.Id, entry.Key.Name, entry.Value)).ToList();
}
public static List<Location> AsLocations(this IEnumerable<Light> lights)
{
Dictionary<Light.CollectionSpec, List<Light>> groups =
new Dictionary<Light.CollectionSpec, List<Light>>();
foreach (Light light in lights)
{
if (!groups.ContainsKey(light.location))
if (!groups.ContainsKey(light.Location))
{
groups[light.location] = new List<Light>();
groups[light.Location] = new List<Light>();
}
groups[light.location].Add(light);
groups[light.Location].Add(light);
}
// Grab client from a light
LifxClient client = (groups.Count > 0) ? groups.First().Value.First().Client : null;
return groups.Select(entry => new Location(client, entry.Key.id, entry.Key.name, entry.Value)).ToList();
return groups.Select(entry => new Location(client, entry.Key.Id, entry.Key.Name, entry.Value)).ToList();
}

public static bool IsSuccessful(this IEnumerable<ApiResult> results, MatchMode matchMode = MatchMode.Any)
Expand Down
63 changes: 63 additions & 0 deletions LifxHttp/Helpers/LifxColorConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LifxHttp.Helpers
{
public static class JsonExtensions
{
public static bool IsNullOrEmpty(this JToken token)
{
return (token == null) ||
(token.Type == JTokenType.Array && !token.HasValues) ||
(token.Type == JTokenType.Object && !token.HasValues) ||
(token.Type == JTokenType.String && token.ToString() == String.Empty) ||
(token.Type == JTokenType.Null);
}
}

public class LifxColorConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
//Assume we can convert to anything for now.
return true;
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value is null)
{
var token = JToken.Load(reader);
double? hue = null;
double? saturation = null;
double? brightness = null;
int? kelvin = null;

if (!token["hue"].IsNullOrEmpty())
hue = (double)token["hue"];
if (!token["saturation"].IsNullOrEmpty())
saturation = (double)token["saturation"];
if (!token["brightness"].IsNullOrEmpty())
brightness = (double)token["brightness"];
if (!token["kelvin"].IsNullOrEmpty())
kelvin = (int)token["kelvin"];
return new LifxColor.HSBK(hue, saturation, brightness, kelvin);
}
else
{
return serializer.Deserialize<LifxColor.HSBK>(reader);
}
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
//Write to string to get correct color formatting.
writer.WriteValue(value.ToString());
}
}
}
52 changes: 31 additions & 21 deletions LifxHttp/ILifxApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,40 @@ namespace LifxHttp
internal interface ILifxApi
{
[Get("/lights/{selector}")]
Task<Light> GetLight([Header("Authorization")] string auth, string selector);
Task<List<Light>> ListLights([Header("Authorization")] string auth, string selector);

[Get("/scenes")]
Task<List<Scene>> ListScenes([Header("Authorization")] string auth);

[Get("/color?string={colorName}")]
Task<LifxColor.HSBK> ValidateColor([Header("Authorization")] string auth, string colorName);

[Get("/lights/{selector}")]
Task<List<Light>> ListLights([Header("Authorization")] string auth, string selector);

[Post("/lights/{selector}/toggle")]
Task<List<ApiResult>> TogglePower([Header("Authorization")] string auth, string selector);

[Post("/lights/{selector}/toggle")]
Task<ApiResult> TogglePowerSingle([Header("Authorization")] string auth, string selector);

[Put("/lights/{selector}/power")]
[Put("/lights/{selector}/state")]
[Headers("Content-Type: application/x-www-form-urlencoded")]
Task<List<ApiResult>> SetPower([Header("Authorization")] string auth, string selector, [Body] string args);

[Put("/lights/{selector}/power")]
[Headers("Content-Type: application/x-www-form-urlencoded")]
Task<ApiResult> SetPowerSingle([Header("Authorization")] string auth, string selector, [Body] string args);

[Put("/lights/{selector}/color")]
Task<ApiResults> SetState([Header("Authorization")] string auth, string selector, [Body] string args);
[Put("/lights/states")]
[Headers("Content-Type: application/json")]
Task<ApiResults> SetStates([Header("Authorization")] string auth, [Body] LifxClient.SetStatesSpec args);
[Put("/scenes/scene_id:{sceneUUID}/activate")]
[Headers("Content-Type: application/x-www-form-urlencoded")]
Task<List<ApiResult>> SetColor([Header("Authorization")] string auth, string selector, [Body] string args);
[Put("/lights/{selector}/color")]
Task<ApiResults> ActivateScene([Header("Authorization")] string auth, string sceneUUID, [Body] string args);

[Post("/lights/{selector}/toggle")]
[Headers("Content-Type: application/x-www-form-urlencoded")]
Task<ApiResult> SetColorSingle([Header("Authorization")] string auth, string selector, [Body] string args);
Task<ApiResults> TogglePower([Header("Authorization")] string auth, string selector, [Body] string args);

[Post("/lights/{selector}/effects/pulse")]
[Headers("Content-Type: application/x-www-form-urlencoded")]
Task<ApiResults> PulseEffect([Header("Authorization")] string auth, string selector, [Body] string args);

[Post("/lights/{selector}/effects/breathe")]
[Headers("Content-Type: application/x-www-form-urlencoded")]
Task<ApiResults> BreatheEffect([Header("Authorization")] string auth, string selector, [Body] string args);

[Post("/lights/{selector}/cycle")]
[Headers("Content-Type: application/json")]
Task<ApiResults> Cycle([Header("Authorization")] string auth, string selector, [Body] LifxClient.SetStateSpec args);
}
}
13 changes: 9 additions & 4 deletions LifxHttp/ILightTarget.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using LifxHttp.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
Expand All @@ -13,8 +14,12 @@ public interface ILightTarget<ResponseType>

bool IsOn { get; }

Task<ResponseType> TogglePower();
Task<ResponseType> SetPower(bool powerState, float duration = LifxClient.DEFAULT_DURATION);
Task<ResponseType> SetColor(LifxColor color, float duration = LifxClient.DEFAULT_DURATION, bool powerOn = LifxClient.DEFAULT_POWER_ON);
Task<ResponseType> TogglePower(double duration = LifxClient.DEFAULT_DURATION);
Task<ResponseType> SetPower(PowerState powerState, double duration = LifxClient.DEFAULT_DURATION);
Task<ResponseType> SetColor(LifxColor color, double duration = LifxClient.DEFAULT_DURATION, bool powerOn = LifxClient.DEFAULT_POWER_ON);
Task<ResponseType> SetState(PowerState powerState, LifxColor color, double brightness, double duration = LifxClient.DEFAULT_DURATION, double infrared = LifxClient.DEFAULT_INFRARED);
Task<ResponseType> PulseEffect(LifxColor color, double period, double cycles, LifxColor fromColor = LifxClient.DEFAULT_FROM_COLOR, bool persist = LifxClient.DEFAULT_PERSIST, bool powerOn = LifxClient.DEFAULT_POWER_ON);
Task<ResponseType> BreatheEffect(LifxColor color, double period, double cycles, LifxColor fromColor = LifxClient.DEFAULT_FROM_COLOR, bool persist = LifxClient.DEFAULT_PERSIST, bool powerOn = LifxClient.DEFAULT_POWER_ON, double peak = LifxClient.DEFAULT_PEAK);
Task<ResponseType> Cycle(List<LightState> states, LightState defaults, Direction direction = LifxClient.DEFAULT_DIRECTION);
}
}
Loading