diff --git a/.gitignore b/.gitignore
index b4cd389..6e0b222 100644
--- a/.gitignore
+++ b/.gitignore
@@ -189,3 +189,5 @@ GeneratedArtifacts/
_Pvt_Extensions/
ModelManifest.xml
*.nupkg
+
+LifxHttpSample/TestProgram.cs
diff --git a/LifxHttp/ApiResult.cs b/LifxHttp/ApiResult.cs
index ac7cd62..d162f1b 100644
--- a/LifxHttp/ApiResult.cs
+++ b/LifxHttp/ApiResult.cs
@@ -6,7 +6,17 @@
using System.Threading.Tasks;
namespace LifxHttp
-{
+{
+ ///
+ /// Operation returned from setting multiple states. Contains selector and state properties.
+ ///
+ [JsonObject(MemberSerialization.OptIn)]
+ public sealed class ApiOperation : LightState
+ {
+ [JsonProperty("selector")]
+ string Selector;
+ }
+
///
/// Returned from API actions
///
@@ -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; }
+
+ ///
+ /// When setting multiple states, each result contains operation(s) and the results of each operation.
+ ///
+ [JsonProperty("results")]
+ public List Results { get; set; }
[JsonProperty("id")]
public string Id { get; private set; }
diff --git a/LifxHttp/ApiResults.cs b/LifxHttp/ApiResults.cs
new file mode 100644
index 0000000..1d85fc6
--- /dev/null
+++ b/LifxHttp/ApiResults.cs
@@ -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 Results { get; set; }
+ }
+}
diff --git a/LifxHttp/Enums/Direction.cs b/LifxHttp/Enums/Direction.cs
new file mode 100644
index 0000000..0b59d64
--- /dev/null
+++ b/LifxHttp/Enums/Direction.cs
@@ -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
+ }
+}
diff --git a/LifxHttp/PowerState.cs b/LifxHttp/Enums/PowerState.cs
similarity index 94%
rename from LifxHttp/PowerState.cs
rename to LifxHttp/Enums/PowerState.cs
index 2811ecf..07f6db5 100644
--- a/LifxHttp/PowerState.cs
+++ b/LifxHttp/Enums/PowerState.cs
@@ -7,7 +7,7 @@
using System.Text;
using System.Threading.Tasks;
-namespace LifxHttp
+namespace LifxHttp.Enums
{
[JsonConverter(typeof(StringEnumConverter))]
public enum PowerState
diff --git a/LifxHttp/Extensions.cs b/LifxHttp/Extensions.cs
index 34c5459..b2196e3 100644
--- a/LifxHttp/Extensions.cs
+++ b/LifxHttp/Extensions.cs
@@ -16,15 +16,15 @@ public static List AsGroups(this IEnumerable lights)
new Dictionary>();
foreach (Light light in lights)
{
- if (!groups.ContainsKey(light.group))
+ if (!groups.ContainsKey(light.Group))
{
- groups[light.group] = new List();
+ groups[light.Group] = new List();
}
- 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 AsLocations(this IEnumerable lights)
{
@@ -32,15 +32,15 @@ public static List AsLocations(this IEnumerable lights)
new Dictionary>();
foreach (Light light in lights)
{
- if (!groups.ContainsKey(light.location))
+ if (!groups.ContainsKey(light.Location))
{
- groups[light.location] = new List();
+ groups[light.Location] = new List();
}
- 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 results, MatchMode matchMode = MatchMode.Any)
diff --git a/LifxHttp/Helpers/LifxColorConverter.cs b/LifxHttp/Helpers/LifxColorConverter.cs
new file mode 100644
index 0000000..f43090d
--- /dev/null
+++ b/LifxHttp/Helpers/LifxColorConverter.cs
@@ -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(reader);
+ }
+ }
+
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ //Write to string to get correct color formatting.
+ writer.WriteValue(value.ToString());
+ }
+ }
+}
diff --git a/LifxHttp/ILifxApi.cs b/LifxHttp/ILifxApi.cs
index 7cb1083..00490da 100644
--- a/LifxHttp/ILifxApi.cs
+++ b/LifxHttp/ILifxApi.cs
@@ -10,30 +10,40 @@ namespace LifxHttp
internal interface ILifxApi
{
[Get("/lights/{selector}")]
- Task GetLight([Header("Authorization")] string auth, string selector);
+ Task> ListLights([Header("Authorization")] string auth, string selector);
+
+ [Get("/scenes")]
+ Task> ListScenes([Header("Authorization")] string auth);
+
+ [Get("/color?string={colorName}")]
+ Task ValidateColor([Header("Authorization")] string auth, string colorName);
- [Get("/lights/{selector}")]
- Task> ListLights([Header("Authorization")] string auth, string selector);
-
- [Post("/lights/{selector}/toggle")]
- Task> TogglePower([Header("Authorization")] string auth, string selector);
-
- [Post("/lights/{selector}/toggle")]
- Task TogglePowerSingle([Header("Authorization")] string auth, string selector);
-
- [Put("/lights/{selector}/power")]
+ [Put("/lights/{selector}/state")]
[Headers("Content-Type: application/x-www-form-urlencoded")]
- Task> SetPower([Header("Authorization")] string auth, string selector, [Body] string args);
-
- [Put("/lights/{selector}/power")]
- [Headers("Content-Type: application/x-www-form-urlencoded")]
- Task SetPowerSingle([Header("Authorization")] string auth, string selector, [Body] string args);
-
- [Put("/lights/{selector}/color")]
+ Task SetState([Header("Authorization")] string auth, string selector, [Body] string args);
+
+ [Put("/lights/states")]
+ [Headers("Content-Type: application/json")]
+ Task SetStates([Header("Authorization")] string auth, [Body] LifxClient.SetStatesSpec args);
+
+ [Put("/scenes/scene_id:{sceneUUID}/activate")]
[Headers("Content-Type: application/x-www-form-urlencoded")]
- Task> SetColor([Header("Authorization")] string auth, string selector, [Body] string args);
- [Put("/lights/{selector}/color")]
+ Task ActivateScene([Header("Authorization")] string auth, string sceneUUID, [Body] string args);
+
+ [Post("/lights/{selector}/toggle")]
[Headers("Content-Type: application/x-www-form-urlencoded")]
- Task SetColorSingle([Header("Authorization")] string auth, string selector, [Body] string args);
+ Task TogglePower([Header("Authorization")] string auth, string selector, [Body] string args);
+
+ [Post("/lights/{selector}/effects/pulse")]
+ [Headers("Content-Type: application/x-www-form-urlencoded")]
+ Task PulseEffect([Header("Authorization")] string auth, string selector, [Body] string args);
+
+ [Post("/lights/{selector}/effects/breathe")]
+ [Headers("Content-Type: application/x-www-form-urlencoded")]
+ Task BreatheEffect([Header("Authorization")] string auth, string selector, [Body] string args);
+
+ [Post("/lights/{selector}/cycle")]
+ [Headers("Content-Type: application/json")]
+ Task Cycle([Header("Authorization")] string auth, string selector, [Body] LifxClient.SetStateSpec args);
}
}
diff --git a/LifxHttp/ILightTarget.cs b/LifxHttp/ILightTarget.cs
index 4f6ac68..796e204 100644
--- a/LifxHttp/ILightTarget.cs
+++ b/LifxHttp/ILightTarget.cs
@@ -1,4 +1,5 @@
-using System;
+using LifxHttp.Enums;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -13,8 +14,12 @@ public interface ILightTarget
bool IsOn { get; }
- Task TogglePower();
- Task SetPower(bool powerState, float duration = LifxClient.DEFAULT_DURATION);
- Task SetColor(LifxColor color, float duration = LifxClient.DEFAULT_DURATION, bool powerOn = LifxClient.DEFAULT_POWER_ON);
+ Task TogglePower(double duration = LifxClient.DEFAULT_DURATION);
+ Task SetPower(PowerState powerState, double duration = LifxClient.DEFAULT_DURATION);
+ Task SetColor(LifxColor color, double duration = LifxClient.DEFAULT_DURATION, bool powerOn = LifxClient.DEFAULT_POWER_ON);
+ Task SetState(PowerState powerState, LifxColor color, double brightness, double duration = LifxClient.DEFAULT_DURATION, double infrared = LifxClient.DEFAULT_INFRARED);
+ Task 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 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 Cycle(List states, LightState defaults, Direction direction = LifxClient.DEFAULT_DIRECTION);
}
}
diff --git a/LifxHttp/LifxClient.cs b/LifxHttp/LifxClient.cs
index d5f508e..78da604 100644
--- a/LifxHttp/LifxClient.cs
+++ b/LifxHttp/LifxClient.cs
@@ -3,6 +3,8 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using LifxHttp.Enums;
+using Newtonsoft.Json;
namespace LifxHttp
{
@@ -11,8 +13,20 @@ namespace LifxHttp
///
public class LifxClient
{
- internal const float DEFAULT_DURATION = 1f;
+ internal const double DEFAULT_DURATION = 1.0d;
internal const bool DEFAULT_POWER_ON = true;
+ internal const double DEFAULT_INFRARED = 0.0d;
+ internal const LifxColor DEFAULT_FROM_COLOR = null;
+ internal const double DEFAULT_PEAK = 0.5d;
+ internal const bool DEFAULT_PERSIST = false;
+ internal const Enums.Direction DEFAULT_DIRECTION = Direction.Forward;
+ internal const double MIN_BRIGHTNESS = 0.0d;
+ internal const double MAX_BRIGHTNESS = 1.0d;
+ internal const double MIN_DURATION = 0.0d;
+ internal const double MAX_DURATION = 3155760000.0d;
+ internal const double MIN_PEAK = 0.0d;
+ internal const double MAX_PEAK = 1.0d;
+
private ILifxApi lifxApi;
protected readonly string auth;
@@ -23,8 +37,38 @@ public class LifxClient
public LifxClient(string token)
{
auth = "Bearer " + token;
- lifxApi = Refit.RestService.For("https://api.lifx.com/v1beta1");
-
+ lifxApi = Refit.RestService.For("https://api.lifx.com/v1");
+ }
+
+ [JsonObject(MemberSerialization.OptIn)]
+ public class SetStateSpec
+ {
+ [JsonProperty("states")]
+ public List States { get; set; }
+ [JsonProperty("defaults")]
+ public LightState Defaults { get; set; }
+ [JsonProperty("direction")]
+ public Direction Direction { get; set; }
+ public SetStateSpec(List states, LightState defaults, Direction direction)
+ {
+ States = states;
+ Defaults = defaults;
+ Direction = direction;
+ }
+ }
+
+ [JsonObject(MemberSerialization.OptIn)]
+ public class SetStatesSpec
+ {
+ [JsonProperty("states")]
+ public List States { get; set; }
+ [JsonProperty("defaults")]
+ public LightState Defaults { get; set; }
+ public SetStatesSpec(List states, LightState defaults)
+ {
+ States = states;
+ Defaults = defaults;
+ }
}
///
@@ -36,26 +80,15 @@ public async Task> ListLights(Selector selector = null)
{
if (selector == null) { selector = Selector.All; }
List lights;
- if (selector.IsSingle)
- {
- Light light = await lifxApi.GetLight(auth, selector.ToString());
- lights = new List();
- if (light != null)
- {
- lights.Add(light);
- }
- }
- else
- {
- lights = await lifxApi.ListLights(auth, selector.ToString());
- }
- foreach (var l in lights)
+ lights = await lifxApi.ListLights(auth, selector.ToString());
+ foreach (var light in lights)
{
// Attach this client to lights
- l.Client = this;
+ light.Client = this;
}
return lights;
}
+
///
/// Gets light groups belonging to the authenticated account
///
@@ -65,6 +98,7 @@ public async Task> ListGroups(Selector selector = null)
{
return (await ListLights(selector)).AsGroups();
}
+
///
/// Gets locations belonging to the authenticated account
///
@@ -73,118 +107,225 @@ public async Task> ListGroups(Selector selector = null)
public async Task> ListLocations(Selector selector = null)
{
return (await ListLights(selector)).AsLocations();
- }
+ }
+
///
- /// Turn off lights if they are on, or turn them on if they are off.
- /// Physically powered off lights are ignored.
+ /// Lists all the scenes available in the user's account. Scenes listed here can be activated with the ActivateScene. As documented here: https://api.developer.lifx.com/docs/list-scenes.
///
- /// Filter for which lights are targetted
- /// Result indicating success of operation
- public async Task> TogglePower(Selector selector)
+ /// All scenes available.
+ public async Task> ListScenes()
{
- if (selector == null) { selector = Selector.All; }
- if (selector.IsSingle)
- {
- ApiResult result;
- try
- {
- result = await lifxApi.TogglePowerSingle(auth, selector.ToString());
- }
- catch (Refit.ApiException e)
- {
- result = e.GetContentAs();
- }
- return new List() { result };
- }
- else
- {
- try
- {
- return await lifxApi.TogglePower(auth, selector.ToString());
- }
- catch (Refit.ApiException e)
- {
- return e.GetContentAs>();
- }
- }
+ return await lifxApi.ListScenes(auth);
}
- ///
- /// Turn lights on, or turn lights off.
- ///
- /// True for on, false for off
- /// Optionally set a duration which will fade on (or off) over the given duration in seconds.
+
+ ///
+ /// Toggles light power state. As documented here: https://api.developer.lifx.com/docs/toggle-power.
+ ///
/// Filter for which lights are targetted
- /// Result indicating success of operation
- public async Task> SetPower(Selector selector, bool powerState, float duration = DEFAULT_DURATION)
+ /// How long in seconds you want the power action to take. Range: 0.0 – 3155760000.0 (100 years).
+ ///
+ public async Task TogglePower(Selector selector, double duration = DEFAULT_DURATION)
{
- return await SetPower(selector, powerState ? PowerState.On : PowerState.Off, duration);
+ if (selector == null) { selector = Selector.All; }
+ duration = duration < MIN_DURATION ? MIN_DURATION : duration > MAX_DURATION ? MAX_DURATION : duration;
+ string args = string.Format("duration={0}", duration);
+ try
+ {
+ return await lifxApi.TogglePower(auth, selector.ToString(), args);
+ }
+ catch (Refit.ApiException e)
+ {
+ return e.GetContentAs();
+ }
}
- ///
- /// Turn lights on, or turn lights off.
- ///
- /// Desired power state for lights
- /// Optionally set a duration which will fade on (or off) over the given duration in seconds.
- /// Filter for which lights are targetted
- /// Result indicating success of operation
- public async Task> SetPower(Selector selector, PowerState powerState, float duration = DEFAULT_DURATION)
+
+ ///
+ /// Set power to an explicit state (on/off).
+ ///
+ /// Filter for which lights are targetted
+ /// On or off.
+ /// How long in seconds you want the power action to take. Range: 0.0 – 3155760000.0 (100 years).
+ ///
+ public async Task SetPower(Selector selector, PowerState powerState, double duration = DEFAULT_DURATION)
+ {
+ if (selector == null) { selector = Selector.All; }
+ string args = string.Format("power={0}&duration={1}", powerState.ToString().ToLowerInvariant(), duration);
+ try
+ {
+ return await lifxApi.SetState(auth, selector.ToString(), args);
+ }
+ catch (Refit.ApiException e)
+ {
+ return e.GetContentAs();
+ }
+ }
+
+ ///
+ /// Set the light to a specific color.
+ ///
+ /// Filter for which lights are targetted
+ /// The color to set the light to.
+ /// How long in seconds you want the power action to take. Range: 0.0 – 3155760000.0 (100 years).
+ /// If true, turn the bulb on if it is not already on.
+ ///
+ public async Task SetColor(Selector selector, LifxColor color, double duration = DEFAULT_DURATION, bool powerOn = DEFAULT_POWER_ON)
{
if (selector == null) { selector = Selector.All; }
- string args = string.Format("state={0}&duration={1}", powerState.ToString().ToLowerInvariant(), duration);
- if (selector.IsSingle)
- {
- ApiResult result;
- try
- {
- result = await lifxApi.SetPowerSingle(auth, selector.ToString(), args);
- }
- catch (Refit.ApiException e)
- {
- result = e.GetContentAs();
- }
- return new List() { result };
- }
- else
- {
- try
- {
- return await lifxApi.SetPower(auth, selector.ToString(), args);
- }
- catch (Refit.ApiException e)
- {
- return e.GetContentAs>();
- }
+ string args = string.Format("color={0}&duration={1}", color, duration);
+ if (powerOn) { args = args + "&power=" + PowerState.On.ToString().ToLowerInvariant(); }
+ try
+ {
+ return await lifxApi.SetState(auth, selector.ToString(), args);
}
- }
-
- public async Task> SetColor(Selector selector, LifxColor color, float duration = DEFAULT_DURATION, bool powerOn = DEFAULT_POWER_ON)
+ catch (Refit.ApiException e)
+ {
+ return e.GetContentAs();
+ }
+ }
+
+ ///
+ /// Set an explicit state. As documented here: https://api.developer.lifx.com/docs/set-state.
+ ///
+ /// Filter for which lights are targetted
+ /// On or off.
+ /// The color to set the light to.
+ /// The brightness level from 0.0 to 1.0. Overrides any brightness set in color (if any).
+ /// How long in seconds you want the power action to take. Range: 0.0 – 3155760000.0 (100 years).
+ /// The maximum brightness of the infrared channel.
+ ///
+ public async Task SetState(Selector selector, PowerState powerState, LifxColor color, double brightness, double duration = LifxClient.DEFAULT_DURATION, double infrared = LifxClient.DEFAULT_INFRARED)
+ {
+ if (selector == null) { selector = Selector.All; }
+ string args = string.Format("power={0}&color={1}&brightness={2}&duration={3}&infrared={4}", powerState.ToString().ToLowerInvariant(), color, brightness, duration, infrared);
+ try
+ {
+ return await lifxApi.SetState(auth, selector.ToString(), args);
+ }
+ catch (Refit.ApiException e)
+ {
+ return e.GetContentAs();
+ }
+ }
+
+ ///
+ /// Set multiple states across multiple selectors. As documented here: https://api.developer.lifx.com/docs/set-states.
+ ///
+ /// A list of states (each which may have a unique selector to chose the light(s) which will be set to said state).
+ /// A state which contains default properties that are inherited by states that don't explicitely set them.
+ ///
+ public async Task SetStates(List states, LightState defaults)
+ {
+ SetStatesSpec args = new SetStatesSpec(states, defaults);
+ try
+ {
+ return await lifxApi.SetStates(auth, args);
+ }
+ catch (Refit.ApiException e)
+ {
+ return e.GetContentAs();
+ }
+ }
+
+ ///
+ /// Activates a scene from the users account. As documented here: https://api.developer.lifx.com/docs/activate-scene.
+ ///
+ /// The UUID for the scene you wish to activate.
+ /// The time in seconds to spend performing the scene transition.
+ ///
+ public async Task ActivateScene(string sceneUUID, double duration = DEFAULT_DURATION)
+ {
+ string args = string.Format("duration={0}", duration);
+ try
+ {
+ return await lifxApi.ActivateScene(auth, sceneUUID, args);
+ }
+ catch (Refit.ApiException e)
+ {
+ return e.GetContentAs();
+ }
+ }
+
+ ///
+ /// Triggers a pulsing ("strobe") effect on the light. During each cycle the light switches between two colors ("fromColor" and "color"). As documented here: https://api.developer.lifx.com/docs/pulse-effect.
+ ///
+ /// Filter for which lights are targetted
+ /// Color which the light changes to. Light alternates between this and fromColor.
+ /// The time (in seconds) to complete one cycle of the effect.
+ /// The number of times to repeat the effect.
+ /// Color which the light begins on and changes back to at the start of the next cycle. If omitted, this will be the current color of the light. Set to LifxColor.OffState to toggle between an off state and your chosen color (which must have a brightness level set above 0... default named colors will result in the light staying off).
+ /// If false, this sets the light back to its previous state when the effect ends. If true the light remains on the last color of the effect.
+ /// If true, turn the bulb on if it is not already on.
+ ///
+ public async Task PulseEffect(Selector selector, LifxColor color, double period, double cycles, LifxColor fromColor = null, bool persist = false, bool powerOn = DEFAULT_POWER_ON)
{
if (selector == null) { selector = Selector.All; }
- string args = string.Format("color={0}&duration={1}&power_on={2}", color, duration, powerOn);
- if (selector.IsSingle)
- {
- ApiResult result;
- try
- {
- result = await lifxApi.SetColorSingle(auth, selector.ToString(), args);
- }
- catch (Refit.ApiException e)
- {
- result = e.GetContentAs();
- }
- return new List() { result };
- }
- else
- {
- try
- {
- return await lifxApi.SetColor(auth, selector.ToString(), args);
- }
- catch (Refit.ApiException e)
- {
- return e.GetContentAs>();
- }
+ string args = string.Format("color={0}&from_color={1}&period={2}&cycles={3}&persist={4}&power_on={5}", color, fromColor, period, cycles, persist, powerOn);
+ try
+ {
+ return await lifxApi.PulseEffect(auth, selector.ToString(), args);
}
- }
-
+ catch (Refit.ApiException e)
+ {
+ return e.GetContentAs();
+ }
+ }
+
+ ///
+ /// Triggers a breathing ("fade") effect on the light. During each cycle the light fades between two colors ("fromColor" and "color"). As documented here: https://api.developer.lifx.com/docs/breathe-effect.
+ ///
+ /// Filter for which lights are targetted
+ /// Color which the light fades to. Light alternates between this and fromColor.
+ /// The time (in seconds) to complete one cycle of the effect.
+ /// The number of times to repeat the effect.
+ /// Color which the light begins on and changes back to at the start of the next cycle. If omitted, this will be the current color of the light. Set to LifxColor.OffState to toggle between an off state and your chosen color (which must have a brightness level set above 0... default named colors will result in the light staying "off").
+ /// If false, this sets the light back to its previous state when the effect ends. If true the light remains on the last color of the effect.
+ /// If true, turn the bulb on if it is not already on.
+ /// Defines where in a period the target color is at its maximum. Minimum 0.0, maximum 1.0.
+ ///
+ public async Task BreatheEffect(Selector selector, LifxColor color, double period, double cycles, LifxColor fromColor = null, bool persist = false, bool powerOn = DEFAULT_POWER_ON, double peak = DEFAULT_PEAK)
+ {
+ if (selector == null) { selector = Selector.All; }
+ string args = string.Format("color={0}&from_color={1}&period={2}&cycles={3}&persist={4}&power_on={5}&peak={6}", color, fromColor, period, cycles, persist, powerOn, peak);
+ try
+ {
+ return await lifxApi.BreatheEffect(auth, selector.ToString(), args);
+ }
+ catch (Refit.ApiException e)
+ {
+ return e.GetContentAs();
+ }
+ }
+
+ /// Triggers a state cycle effect on the light. During each cycle the light transitions between 2 - 5 predefined states that will inherit properties from the default state. As documented here: https://api.developer.lifx.com/docs/cycle.
+ /// A list of states. Within each you can set power, color, brightness, power action duration, and infrared channel value. Must have 2 to 5 entries.
+ /// A state which contains default properties that are inherited by states that don't explicitely set them.
+ /// Direction in which to cycle through the list of states.
+ ///
+ public async Task Cycle(Selector selector, List states, LightState defaults, Direction direction = DEFAULT_DIRECTION)
+ {
+ if (selector == null) { selector = Selector.All; }
+ SetStateSpec args = new SetStateSpec(states, defaults, direction);
+ try
+ {
+ return await lifxApi.Cycle(auth, selector.ToString(), args);
+ }
+ catch (Refit.ApiException e)
+ {
+ return e.GetContentAs();
+ }
+ }
+
+ public async Task> ValidateColor(string colorName)
+ {
+ try
+ {
+ var color = await lifxApi.ValidateColor(auth, colorName);
+ return new Tuple(true, color);
+ }
+ catch (Refit.ApiException e)
+ {
+ return new Tuple(false, new LifxColor.HSBK());
+ }
+ }
}
}
diff --git a/LifxHttp/LifxColor.cs b/LifxHttp/LifxColor.cs
index 025d0a7..ab8be20 100644
--- a/LifxHttp/LifxColor.cs
+++ b/LifxHttp/LifxColor.cs
@@ -1,4 +1,5 @@
-using Newtonsoft.Json;
+using LifxHttp.Helpers;
+using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -12,6 +13,7 @@ namespace LifxHttp
/// kelvin, and brightness components. However, other means of expressing
/// colors are available
///
+ [JsonConverter(typeof(LifxColorConverter))]
public abstract class LifxColor
{
///
@@ -62,6 +64,10 @@ public abstract class LifxColor
/// Sets hue to 325
///
public static readonly LifxColor Pink = new Named("pink");
+ ///
+ /// A pseudo "off" state color with no brightness - used for effects
+ ///
+ public static readonly LifxColor OffState = new White(0);
public static readonly IEnumerable NamedColors = new List()
{
DefaultWhite, Red, Orange, Yellow, Cyan, Green, Blue, Purple, Pink
@@ -99,20 +105,20 @@ public override string ToString()
public class HSBK : LifxColor
{
[JsonProperty]
- private float? hue;
+ private double? hue;
[JsonProperty]
- private float? saturation;
+ private double? saturation;
[JsonProperty]
- private float? brightness;
+ private double? brightness;
[JsonProperty]
private int? kelvin;
- public float Hue { get { return hue ?? float.NaN; } }
- public float Saturation { get { return saturation ?? float.NaN; } }
- public float Brightness { get { return brightness ?? float.NaN; } }
+ public double Hue { get { return hue ?? double.NaN; } }
+ public double Saturation { get { return saturation ?? double.NaN; } }
+ public double Brightness { get { return brightness ?? double.NaN; } }
public int Kelvin { get { return kelvin ?? TemperatureDefault; } }
internal HSBK() { }
- public HSBK(float? hue = null, float? saturation = null, float? brightness = null, int? kelvin = null)
+ public HSBK(double? hue = null, double? saturation = null, double? brightness = null, int? kelvin = null)
{
if (hue == null && saturation == null && brightness == null && kelvin == null)
{
@@ -147,7 +153,7 @@ public override string ToString()
return sb.ToString();
}
- internal HSBK WithBrightness(float brightness)
+ internal HSBK WithBrightness(double brightness)
{
return new HSBK(this.hue, this.saturation, brightness, this.kelvin);
}
@@ -158,7 +164,7 @@ internal HSBK WithBrightness(float brightness)
///
public sealed class HSB : HSBK
{
- public HSB(float hue, float saturation = 1f, float brightness = 1f) : base(hue, saturation, brightness) { }
+ public HSB(double hue, double saturation = 1f, double brightness = 1f) : base(hue, saturation, brightness) { }
}
///
@@ -166,7 +172,7 @@ public HSB(float hue, float saturation = 1f, float brightness = 1f) : base(hue,
///
public sealed class White : HSBK
{
- public White(float brightness = 1f, int kelvin = TemperatureDefault) : base(null, null, brightness, kelvin) { }
+ public White(double brightness = 1f, int kelvin = TemperatureDefault) : base(null, null, brightness, kelvin) { }
}
///
diff --git a/LifxHttp/LifxHttp.csproj b/LifxHttp/LifxHttp.csproj
index a447b14..763fdfd 100644
--- a/LifxHttp/LifxHttp.csproj
+++ b/LifxHttp/LifxHttp.csproj
@@ -1,82 +1,87 @@
-
-
-
-
- 10.0
- Debug
- AnyCPU
- {1E9E789F-2750-4E8C-8F0D-D5A41322C953}
- Library
- Properties
- LifxHttp
- LifxHttp
- en-US
- 512
- {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- Profile111
- v4.5
-
-
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(SolutionDir)\packages\Newtonsoft.Json.6.0.5\lib\portable-net45+wp80+win8+wpa81\Newtonsoft.Json.dll
- True
-
-
- $(SolutionDir)\packages\refit.2.3.0\lib\Portable-Net45+WinRT45+WP8+WPA81\Refit.dll
- False
-
-
-
-
-
-
-
-
-
- This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
+
+
+
+
+ 10.0
+ Debug
+ AnyCPU
+ {1E9E789F-2750-4E8C-8F0D-D5A41322C953}
+ Library
+ Properties
+ LifxHttp
+ LifxHttp
+ en-US
+ 512
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Profile111
+ v4.5
+
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(SolutionDir)\packages\Newtonsoft.Json.6.0.5\lib\portable-net45+wp80+win8+wpa81\Newtonsoft.Json.dll
+ True
+
+
+ $(SolutionDir)\packages\refit.2.3.0\lib\Portable-Net45+WinRT45+WP8+WPA81\Refit.dll
+ False
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+ -->
\ No newline at end of file
diff --git a/LifxHttp/Light.cs b/LifxHttp/Light.cs
index a2351f0..4fc1233 100644
--- a/LifxHttp/Light.cs
+++ b/LifxHttp/Light.cs
@@ -5,6 +5,7 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using LifxHttp.Enums;
namespace LifxHttp
{
@@ -15,26 +16,44 @@ namespace LifxHttp
public sealed class Light : ILightTarget
{
public const string ColorCapability = "has_color";
- public const string ColorTemperatureCapability = "has_variable_color_temp";
-
- [JsonObject(MemberSerialization.Fields)]
+ public const string ColorTemperatureCapability = "has_variable_color_temp";
+ public const string IRCapability = "has_ir";
+ public const string MultizoneCapability = "has_multizone";
+
+ [JsonObject(MemberSerialization.OptIn)]
internal class CollectionSpec
{
- public string id;
- public string name;
+ [JsonProperty("id")]
+ public string Id { get; set; }
+ [JsonProperty("name")]
+ public string Name { get; set; }
public override bool Equals(object obj)
{
CollectionSpec spec = obj as CollectionSpec;
- return spec != null && spec.id == id && spec.name == name;
+ return spec != null && spec.Id == Id && spec.Name == Name;
}
public override int GetHashCode()
{
- return (id.GetHashCode() * 77) + name.GetHashCode();
+ return (Id.GetHashCode() * 77) + Name.GetHashCode();
}
- }
-
+ }
+
+ [JsonObject(MemberSerialization.OptIn)]
+ internal class ProductSpec
+ {
+ [JsonProperty("name")]
+ public string ProductName { get; set; }
+ [JsonProperty("company")]
+ public string Company { get; set; }
+ [JsonProperty("identifier")]
+ public string ProductId { get; set; }
+ [JsonProperty("capabilities")]
+ public Dictionary Capabilities { get; set; }
+ }
+
internal LifxClient Client { get; set; }
+
///
/// Serial number of the light
///
@@ -51,6 +70,7 @@ public override int GetHashCode()
public bool IsConnected { get; private set; }
public bool IsOn { get { return PowerState == PowerState.On; } }
+
[JsonProperty("power")]
public PowerState PowerState { get; private set; }
@@ -59,34 +79,37 @@ public LifxColor.HSBK Color
{
get { return color == null ? null : color.WithBrightness(Brightness); }
set { color = value; }
- }
+ }
+
+ [JsonProperty("infrared")]
+ public double? Infrared { get; private set; }
[JsonProperty("brightness")]
- public float Brightness { get; private set; }
+ public double Brightness { get; private set; }
[JsonProperty("group")]
- internal CollectionSpec group = new CollectionSpec();
- public string GroupId { get { return group.id; } }
- public string GroupName { get { return group.name; } }
+ internal CollectionSpec Group = new CollectionSpec();
+ public string GroupId { get { return Group.Id; } }
+ public string GroupName { get { return Group.Name; } }
[JsonProperty("location")]
- internal CollectionSpec location = new CollectionSpec();
- public string LocationId { get { return location.id; } }
- public string LocationName { get { return location.name; } }
+ internal CollectionSpec Location = new CollectionSpec();
+ public string LocationId { get { return Location.Id; } }
+ public string LocationName { get { return Location.Name; } }
[JsonProperty("last_seen")]
[JsonConverter(typeof(IsoDateTimeConverter))]
public DateTime LastSeen { get; private set; }
[JsonProperty("seconds_since_seen")]
- public float SecondsSinceSeen { get; private set; }
-
- [JsonProperty("product_name")]
- public string ProductName { get; private set; }
-
- [JsonProperty("capabilities")]
- private Dictionary capabilities;
- private LifxColor.HSBK color;
+ public double SecondsSinceSeen { get; private set; }
+
+ [JsonProperty("product")]
+ internal ProductSpec Product = new ProductSpec();
+ public string ProductName { get { return Product.ProductName; } private set { ProductName = value; } }
+ public string Company { get { return Product.Company; } private set { Company = value; } }
+ public string ProductId { get { return Product.ProductId; } private set { ProductId = value; } }
+ public Dictionary capabilities { get { return Product.Capabilities; } }
public IEnumerable Capabilities
{
@@ -108,21 +131,96 @@ public IEnumerable Capabilities
public bool HasCapability(string capabilitity)
{
return capabilities != null && capabilities.ContainsKey(capabilitity) && capabilities[capabilitity];
+ }
+
+ private LifxColor.HSBK color;
+
+ ///
+ /// Toggles light power state. As documented here: https://api.developer.lifx.com/docs/toggle-power.
+ ///
+ /// How long in seconds you want the power action to take. Range: 0.0 – 3155760000.0 (100 years).
+ ///
+ public async Task TogglePower(double duration = LifxClient.DEFAULT_DURATION)
+ {
+ return (await Client.TogglePower(this)).Results.First();
}
- public async Task TogglePower()
+ ///
+ /// Set power to an explicit state (on/off).
+ ///
+ /// On or off.
+ /// How long in seconds you want the power action to take. Range: 0.0 – 3155760000.0 (100 years).
+ ///
+ public async Task SetPower(PowerState powerState, double duration = LifxClient.DEFAULT_DURATION)
{
- return (await Client.TogglePower(this)).First();
+ return (await Client.SetPower(this, powerState, duration)).Results.First();
}
- public async Task SetPower(bool powerState, float duration = LifxClient.DEFAULT_DURATION)
+ ///
+ /// Set the light to a specific color.
+ ///
+ /// The color to set the light to.
+ /// How long in seconds you want the power action to take. Range: 0.0 – 3155760000.0 (100 years).
+ /// If true, turn the bulb on if it is not already on.
+ ///
+ public async Task SetColor(LifxColor color, double duration = LifxClient.DEFAULT_DURATION, bool powerOn = LifxClient.DEFAULT_POWER_ON)
+ {
+ return (await Client.SetColor(this, color, duration, powerOn)).Results.First();
+ }
+
+ ///
+ /// Set an explicit state. As documented here: https://api.developer.lifx.com/docs/set-state.
+ ///
+ /// On or off.
+ /// The color to set the light to.
+ /// The brightness level from 0.0 to 1.0. Overrides any brightness set in color (if any).
+ /// How long in seconds you want the power action to take. Range: 0.0 – 3155760000.0 (100 years).
+ /// The maximum brightness of the infrared channel.
+ ///
+ public async Task SetState(PowerState powerState, LifxColor color, double brightness, double duration = LifxClient.DEFAULT_DURATION, double infrared = LifxClient.DEFAULT_INFRARED)
+ {
+ return (await Client.SetState(this, powerState, color, brightness, duration, infrared)).Results.First();
+ }
+
+ ///
+ /// Triggers a pulsing ("strobe") effect on the light. During each cycle the light switches between two colors ("fromColor" and "color"). As documented here: https://api.developer.lifx.com/docs/pulse-effect.
+ ///
+ /// Color which the light changes to. Light alternates between this and fromColor.
+ /// The time (in seconds) to complete one cycle of the effect.
+ /// The number of times to repeat the effect.
+ /// Color which the light begins on and changes back to at the start of the next cycle. If omitted, this will be the current color of the light. Set to LifxColor.OffState to toggle between an off state and your chosen color (which must have a brightness level set above 0... default named colors will result in the light staying off).
+ /// If false, this sets the light back to its previous state when the effect ends. If true the light remains on the last color of the effect.
+ /// If true, turn the bulb on if it is not already on.
+ ///
+ public async Task PulseEffect(LifxColor color, double period, double cycles, LifxColor fromColor = LifxClient.DEFAULT_FROM_COLOR, bool persist = LifxClient.DEFAULT_PERSIST, bool powerOn = LifxClient.DEFAULT_POWER_ON)
{
- return (await Client.SetPower(this, powerState, duration)).First();
+ return (await Client.PulseEffect(this, color, period, cycles, fromColor, persist, powerOn)).Results.First();
+ }
+
+ ///
+ /// Triggers a breathing ("fade") effect on the light. During each cycle the light fades between two colors ("fromColor" and "color"). As documented here: https://api.developer.lifx.com/docs/breathe-effect.
+ ///
+ /// Color which the light fades to. Light alternates between this and fromColor.
+ /// The time (in seconds) to complete one cycle of the effect.
+ /// The number of times to repeat the effect.
+ /// Color which the light begins on and changes back to at the start of the next cycle. If omitted, this will be the current color of the light. Set to LifxColor.OffState to toggle between an off state and your chosen color (which must have a brightness level set above 0... default named colors will result in the light staying "off").
+ /// If false, this sets the light back to its previous state when the effect ends. If true the light remains on the last color of the effect.
+ /// If true, turn the bulb on if it is not already on.
+ /// Defines where in a period the target color is at its maximum. Minimum 0.0, maximum 1.0.
+ ///
+ public async Task 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)
+ {
+ return (await Client.BreatheEffect(this, color, period, cycles, fromColor, persist, powerOn, peak)).Results.First();
}
- public async Task SetColor(LifxColor color, float duration = LifxClient.DEFAULT_DURATION, bool powerOn = LifxClient.DEFAULT_POWER_ON)
- {
- return (await Client.SetColor(this, color, duration, powerOn)).First();
+ /// Triggers a state cycle effect on the light. During each cycle the light transitions between 2 - 5 predefined states that will inherit properties from the default state. As documented here: https://api.developer.lifx.com/docs/cycle.
+ /// A list of states. Within each you can set power, color, brightness, power action duration, and infrared channel value. Must have 2 to 5 entries.
+ /// A state which contains default properties that are inherited by states that don't explicitely set them.
+ /// Direction in which to cycle through the list of states.
+ ///
+ public async Task Cycle(List states, LightState defaults, Direction direction = LifxClient.DEFAULT_DIRECTION)
+ {
+ return (await Client.Cycle(this, states, defaults, direction)).Results.First();
}
///
@@ -147,18 +245,18 @@ public async Task Refresh()
PowerState = light.PowerState;
Color = light.Color;
Brightness = light.Brightness;
- group = light.group;
- location = light.location;
+ Group = light.Group;
+ Location = light.Location;
LastSeen = light.LastSeen;
SecondsSinceSeen = light.SecondsSinceSeen;
- ProductName = light.ProductName;
+ Product = light.Product;
}
public override string ToString()
{
return Label;
- }
-
+ }
+
public static implicit operator Selector(Light light)
{
return new Selector.LightId(light.Id);
diff --git a/LifxHttp/LightCollection.cs b/LifxHttp/LightCollection.cs
index b81aafc..e6d717a 100644
--- a/LifxHttp/LightCollection.cs
+++ b/LifxHttp/LightCollection.cs
@@ -1,75 +1,150 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace LifxHttp
-{
- public abstract class LightCollection : IEnumerable, ILightTarget>
- {
- public string Id { get; private set; }
- public string Label { get; private set; }
-
- public bool IsOn { get { return lights.Any(l => l.IsOn); } }
-
- private List lights;
- private LifxClient client;
-
- internal LightCollection(LifxClient client, string id, string label, List lights)
- {
- this.client = client;
- Id = id;
- Label = label;
- this.lights = lights;
- }
-
- public IEnumerator GetEnumerator()
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using LifxHttp.Enums;
+
+namespace LifxHttp
+{
+ public abstract class LightCollection : IEnumerable, ILightTarget
+ {
+ public string Id { get; private set; }
+ public string Label { get; private set; }
+
+ public bool IsOn { get { return lights.Any(l => l.IsOn); } }
+
+ private List lights;
+ private LifxClient client;
+
+ internal LightCollection(LifxClient client, string id, string label, List lights)
+ {
+ this.client = client;
+ Id = id;
+ Label = label;
+ this.lights = lights;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return lights.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return lights.GetEnumerator();
+ }
+
+ ///
+ /// Toggles light power state. As documented here: https://api.developer.lifx.com/docs/toggle-power.
+ ///
+ /// How long in seconds you want the power action to take. Range: 0.0 – 3155760000.0 (100 years).
+ ///
+ public async Task TogglePower(double duration = LifxClient.DEFAULT_DURATION)
+ {
+ if (client == null) { return new ApiResults(); }
+ return await client.TogglePower(this, duration);
+ }
+
+ ///
+ /// Set power to an explicit state (on/off).
+ ///
+ /// On or off.
+ /// How long in seconds you want the power action to take. Range: 0.0 – 3155760000.0 (100 years).
+ ///
+ public async Task SetPower(PowerState powerState, double duration = LifxClient.DEFAULT_DURATION)
{
- return lights.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return lights.GetEnumerator();
- }
- public async Task> TogglePower()
- {
- if (client == null) { return new List(); }
- return await client.TogglePower(this);
- }
-
- public async Task> SetPower(bool powerState, float duration = LifxClient.DEFAULT_DURATION)
- {
- if (client == null) { return new List(); }
return await client.SetPower(this, powerState, duration);
}
- public async Task> SetColor(LifxColor color, float duration = LifxClient.DEFAULT_DURATION, bool powerOn = LifxClient.DEFAULT_POWER_ON)
+ ///
+ /// Set the light to a specific color.
+ ///
+ /// The color to set the light to.
+ /// How long in seconds you want the power action to take. Range: 0.0 – 3155760000.0 (100 years).
+ /// If true, turn the bulb on if it is not already on.
+ ///
+ public async Task SetColor(LifxColor color, double duration = LifxClient.DEFAULT_DURATION, bool powerOn = LifxClient.DEFAULT_POWER_ON)
{
- if (client == null) { return new List(); }
return await client.SetColor(this, color, duration, powerOn);
- }
-
- public async Task Refresh()
- {
- if (client != null)
- {
- lights = await client.ListLights(this);
- }
- }
-
- public abstract Selector ToSelector();
-
- public override string ToString()
- {
- return Label;
- }
-
- public static implicit operator Selector(LightCollection lightCollection)
+ }
+
+ ///
+ /// Set an explicit state. As documented here: https://api.developer.lifx.com/docs/set-state.
+ ///
+ /// On or off.
+ /// The color to set the light to.
+ /// The brightness level from 0.0 to 1.0. Overrides any brightness set in color (if any).
+ /// How long in seconds you want the power action to take. Range: 0.0 – 3155760000.0 (100 years).
+ /// The maximum brightness of the infrared channel.
+ ///
+ public async Task SetState(PowerState powerState, LifxColor color, double brightness, double duration = LifxClient.DEFAULT_DURATION, double infrared = LifxClient.DEFAULT_INFRARED)
{
- return lightCollection.ToSelector();
- }
- }
-}
+ return await client.SetState(this, powerState, color, brightness, duration, infrared);
+ }
+
+ ///
+ /// Triggers a pulsing ("strobe") effect on the light. During each cycle the light switches between two colors ("fromColor" and "color"). As documented here: https://api.developer.lifx.com/docs/pulse-effect.
+ ///
+ /// Color which the light changes to. Light alternates between this and fromColor.
+ /// The time (in seconds) to complete one cycle of the effect.
+ /// The number of times to repeat the effect.
+ /// Color which the light begins on and changes back to at the start of the next cycle. If omitted, this will be the current color of the light. Set to LifxColor.OffState to toggle between an off state and your chosen color (which must have a brightness level set above 0... default named colors will result in the light staying off).
+ /// If false, this sets the light back to its previous state when the effect ends. If true the light remains on the last color of the effect.
+ /// If true, turn the bulb on if it is not already on.
+ ///
+ public async Task PulseEffect(LifxColor color, double period, double cycles, LifxColor fromColor = LifxClient.DEFAULT_FROM_COLOR, bool persist = LifxClient.DEFAULT_PERSIST, bool powerOn = LifxClient.DEFAULT_POWER_ON)
+ {
+ if (client == null) { return new ApiResults(); }
+ return await client.PulseEffect(this, color, period, cycles, fromColor, persist, powerOn);
+ }
+
+ ///
+ /// Triggers a breathing ("fade") effect on the light. During each cycle the light fades between two colors ("fromColor" and "color"). As documented here: https://api.developer.lifx.com/docs/breathe-effect.
+ ///
+ /// Color which the light fades to. Light alternates between this and fromColor.
+ /// The time (in seconds) to complete one cycle of the effect.
+ /// The number of times to repeat the effect.
+ /// Color which the light begins on and changes back to at the start of the next cycle. If omitted, this will be the current color of the light. Set to LifxColor.OffState to toggle between an off state and your chosen color (which must have a brightness level set above 0... default named colors will result in the light staying "off").
+ /// If false, this sets the light back to its previous state when the effect ends. If true the light remains on the last color of the effect.
+ /// If true, turn the bulb on if it is not already on.
+ /// Defines where in a period the target color is at its maximum. Minimum 0.0, maximum 1.0.
+ ///
+ public async Task 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)
+ {
+ if (client == null) { return new ApiResults(); }
+ return await client.BreatheEffect(this, color, period, cycles, fromColor, persist, powerOn, peak);
+ }
+
+ /// Triggers a state cycle effect on the light. During each cycle the light transitions between 2 - 5 predefined states that will inherit properties from the default state. As documented here: https://api.developer.lifx.com/docs/cycle.
+ /// A list of states. Within each you can set power, color, brightness, power action duration, and infrared channel value. Must have 2 to 5 entries.
+ /// A state which contains default properties that are inherited by states that don't explicitely set them.
+ /// Direction in which to cycle through the list of states.
+ ///
+ public async Task Cycle(List states, LightState defaults, Direction direction = LifxClient.DEFAULT_DIRECTION)
+ {
+ return await client.Cycle(this, states, defaults, direction);
+ }
+
+ public async Task Refresh()
+ {
+ if (client != null)
+ {
+ lights = await client.ListLights(this);
+ }
+ }
+
+ public abstract Selector ToSelector();
+
+ public override string ToString()
+ {
+ return Label;
+ }
+
+ public static implicit operator Selector(LightCollection lightCollection)
+ {
+ return lightCollection.ToSelector();
+ }
+ }
+}
diff --git a/LifxHttp/LightState.cs b/LifxHttp/LightState.cs
new file mode 100644
index 0000000..0941701
--- /dev/null
+++ b/LifxHttp/LightState.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using LifxHttp.Enums;
+using LifxHttp.Helpers;
+
+namespace LifxHttp
+{
+ [JsonObject(MemberSerialization.OptIn)]
+ public class LightState
+ {
+ ///
+ /// Selector used for Set States.
+ ///
+ [JsonProperty("selector", NullValueHandling = NullValueHandling.Ignore)]
+ public Selector Selector { get; set; }
+ [JsonProperty("power", NullValueHandling = NullValueHandling.Ignore)]
+ public PowerState PowerState { get; set; }
+ [JsonProperty("color", NullValueHandling = NullValueHandling.Ignore)]
+ public LifxColor Color { get; set; }
+ private double? _brightness;
+ [JsonProperty("brightness", NullValueHandling = NullValueHandling.Ignore)]
+ public double? Brightness { get { return _brightness; }
+ set {
+ if (value.HasValue)
+ _brightness = value < LifxClient.MIN_BRIGHTNESS ? LifxClient.MIN_BRIGHTNESS : value > LifxClient.MAX_BRIGHTNESS ? LifxClient.MAX_BRIGHTNESS : value;
+ else _brightness = value;
+ }
+ }
+ private double? _duration;
+ [JsonProperty("duration", NullValueHandling = NullValueHandling.Ignore)]
+ public double? Duration { get { return _duration; }
+ set {
+ if (value.HasValue)
+ _duration = value < LifxClient.MIN_DURATION ? LifxClient.MIN_DURATION : value > LifxClient.MAX_DURATION ? LifxClient.MAX_DURATION : value;
+ else _duration = value;
+ }
+ }
+ [JsonProperty("infrared", NullValueHandling = NullValueHandling.Ignore)]
+ public double? Infrared { get; set; }
+
+ public LightState(PowerState powerState, LifxColor color, double? brightness = null, double? duration = null, double? infrared = null)
+ {
+ PowerState = powerState;
+ Color = color;
+ Brightness = brightness;
+ Duration = duration;
+ Infrared = infrared;
+ }
+
+ public LightState(Selector selector, PowerState powerState, LifxColor color, double? brightness = null, double? duration = null, double? infrared = null)
+ {
+ Selector = selector;
+ PowerState = powerState;
+ Color = color;
+ Brightness = brightness;
+ Duration = duration;
+ Infrared = infrared;
+ }
+
+ public LightState() { }
+
+ public override string ToString()
+ {
+ StringBuilder result = new StringBuilder();
+ if(Selector != null)
+ {
+ result.Append(string.Format("Selector: {0} ", Selector));
+ }
+ result.Append(string.Format("Power State: {0} ", PowerState));
+ if (Color != null)
+ {
+ result.Append(string.Format("Color: {0} ", Color));
+ }
+ if (Brightness != null)
+ {
+ result.Append(string.Format("Brightness: {0} ", Brightness));
+ }
+ if (Duration != null)
+ {
+ result.Append(string.Format("Duration: {0} ", Duration));
+ }
+ if (Infrared != null)
+ {
+ result.Append(string.Format("Infrared: {0} ", Infrared));
+ }
+ return result.ToString();
+ }
+ }
+}
diff --git a/LifxHttp/Package.nuspec b/LifxHttp/Package.nuspec
index c5a209a..749c1a5 100644
--- a/LifxHttp/Package.nuspec
+++ b/LifxHttp/Package.nuspec
@@ -1,17 +1,17 @@
-
+
$id$
$version$
- Michael Ensly
+ Michael Ensly, Jason Kowaleski
$author$
https://raw.githubusercontent.com/mensly/LifxHttpNet/master/COPYING
https://github.com/mensly/LifxHttpNet
false
$description$
- Initial release with most simple remote tasks available
- Copyright 2015
- lifx http iot cloud lighting remote
+ Updated release which is up to date with V1.0 of LIFX API.
+ Copyright 2017
+ lifx http iot cloud lighting remote smart lighting
diff --git a/LifxHttp/RefitStubs.cs b/LifxHttp/RefitStubs.cs
index 5c64afc..1ea36f7 100644
--- a/LifxHttp/RefitStubs.cs
+++ b/LifxHttp/RefitStubs.cs
@@ -44,52 +44,64 @@ public AutoGeneratedILifxApi(HttpClient client, IRequestBuilder requestBuilder)
Client = client;
}
- public virtual Task GetLight(string auth,string selector)
+ public virtual Task> ListLights(string auth,string selector)
{
var arguments = new object[] { auth,selector };
- return (Task) methodImpls["GetLight"](Client, arguments);
+ return (Task>) methodImpls["ListLights"](Client, arguments);
}
- public virtual Task> ListLights(string auth,string selector)
+ public virtual Task> ListScenes(string auth)
{
- var arguments = new object[] { auth,selector };
- return (Task>) methodImpls["ListLights"](Client, arguments);
+ var arguments = new object[] { auth };
+ return (Task>) methodImpls["ListScenes"](Client, arguments);
}
- public virtual Task> TogglePower(string auth,string selector)
+ public virtual Task ValidateColor(string auth,string colorName)
{
- var arguments = new object[] { auth,selector };
- return (Task>) methodImpls["TogglePower"](Client, arguments);
+ var arguments = new object[] { auth,colorName };
+ return (Task) methodImpls["ValidateColor"](Client, arguments);
}
- public virtual Task TogglePowerSingle(string auth,string selector)
+ public virtual Task SetState(string auth,string selector,string args)
{
- var arguments = new object[] { auth,selector };
- return (Task) methodImpls["TogglePowerSingle"](Client, arguments);
+ var arguments = new object[] { auth,selector,args };
+ return (Task) methodImpls["SetState"](Client, arguments);
+ }
+
+ public virtual Task SetStates(string auth,LifxClient.SetStatesSpec args)
+ {
+ var arguments = new object[] { auth,args };
+ return (Task) methodImpls["SetStates"](Client, arguments);
+ }
+
+ public virtual Task ActivateScene(string auth,string sceneUUID,string args)
+ {
+ var arguments = new object[] { auth,sceneUUID,args };
+ return (Task) methodImpls["ActivateScene"](Client, arguments);
}
- public virtual Task> SetPower(string auth,string selector,string args)
+ public virtual Task TogglePower(string auth,string selector,string args)
{
var arguments = new object[] { auth,selector,args };
- return (Task>) methodImpls["SetPower"](Client, arguments);
+ return (Task) methodImpls["TogglePower"](Client, arguments);
}
- public virtual Task SetPowerSingle(string auth,string selector,string args)
+ public virtual Task PulseEffect(string auth,string selector,string args)
{
var arguments = new object[] { auth,selector,args };
- return (Task) methodImpls["SetPowerSingle"](Client, arguments);
+ return (Task) methodImpls["PulseEffect"](Client, arguments);
}
- public virtual Task> SetColor(string auth,string selector,string args)
+ public virtual Task BreatheEffect(string auth,string selector,string args)
{
var arguments = new object[] { auth,selector,args };
- return (Task>) methodImpls["SetColor"](Client, arguments);
+ return (Task) methodImpls["BreatheEffect"](Client, arguments);
}
- public virtual Task SetColorSingle(string auth,string selector,string args)
+ public virtual Task Cycle(string auth,string selector,LifxClient.SetStateSpec args)
{
var arguments = new object[] { auth,selector,args };
- return (Task) methodImpls["SetColorSingle"](Client, arguments);
+ return (Task) methodImpls["Cycle"](Client, arguments);
}
}
diff --git a/LifxHttp/Scene.cs b/LifxHttp/Scene.cs
new file mode 100644
index 0000000..6fc88a0
--- /dev/null
+++ b/LifxHttp/Scene.cs
@@ -0,0 +1,47 @@
+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 struct AccountSpec
+ {
+ [JsonProperty("uuid")]
+ public string UUID { get; private set; }
+ }
+
+ [JsonObject(MemberSerialization.OptIn)]
+ public class Scene
+ {
+ [JsonProperty("uuid")]
+ public string UUID { get; private set; }
+ [JsonProperty("name")]
+ public string Name { get; private set; }
+ [JsonProperty("account")]
+ public AccountSpec Account { get; private set; }
+ [JsonProperty("states")]
+ public List States { get; set; }
+ [JsonProperty("created_at")]
+ public string CreatedAt { get; set; }
+ [JsonProperty("updated_at")]
+ public string UpdatedAt { get; set; }
+
+ public override string ToString()
+ {
+ StringBuilder result = new StringBuilder(string.Format("UUID: {0} Name:{1} Account:{2} Created At:{3} Updated At:{4}", UUID, Name, Account.UUID, CreatedAt, UpdatedAt));
+ result.AppendLine();
+ result.AppendLine("States: ");
+ foreach (var state in States)
+ {
+ result.AppendLine(state.ToString());
+ }
+ return result.ToString();
+ }
+ }
+
+
+}
diff --git a/LifxHttp/Selector.cs b/LifxHttp/Selector.cs
index c2e6358..1085d34 100644
--- a/LifxHttp/Selector.cs
+++ b/LifxHttp/Selector.cs
@@ -12,12 +12,14 @@ namespace LifxHttp
public class Selector
{
private const string TYPE_ALL = "all";
- private const string TYPE_RANDOM = "random";
private const string TYPE_LIGHT_ID = "id";
+ private const string TYPE_LIGHT_LABEL = "label";
private const string TYPE_GROUP_ID = "group_id";
private const string TYPE_GROUP_LABEL = "group";
private const string TYPE_LOCATION_ID = "location_id";
- private const string TYPE_LOCATION_LABEL = "location";
+ private const string TYPE_LOCATION_LABEL = "location";
+ private const string TYPE_SCENE_ID = "scene_id";
+ private const string TYPE_RANDOM = "random"; // Unsure if this is still supported.
///
/// All lights belonging to the authenticated account.
@@ -53,7 +55,7 @@ public class LightId : Selector
///
public class LightLabel : Selector
{
- public LightLabel(string label) : base(label) { IsSingle = true; }
+ public LightLabel(string label) : base(TYPE_LIGHT_LABEL, label) { IsSingle = true; }
}
///
@@ -72,9 +74,8 @@ public class GroupLabel : Selector
public GroupLabel(string label) : base(TYPE_GROUP_LABEL, label) { }
}
-
///
- /// OOnly the lights belonging to the location matching the given ID.
+ /// Only the lights belonging to the location matching the given ID.
///
public class LocationId : Selector
{
@@ -87,6 +88,14 @@ public LocationId(string id) : base(TYPE_LOCATION_ID, id) { }
public class LocationLabel : Selector
{
public LocationLabel(string label) : base(TYPE_LOCATION_LABEL, label) { }
+ }
+
+ ///
+ /// The lights that are referenced in the scene ID.
+ ///
+ public class SceneId : Selector
+ {
+ public SceneId(string id) : base(TYPE_SCENE_ID, id) { }
}
public static explicit operator Selector(string selector)
@@ -103,10 +112,12 @@ public static explicit operator Selector(string selector)
switch (selector.Substring(0, criteria))
{
case TYPE_LIGHT_ID: return new LightId(remainder);
+ case TYPE_LIGHT_LABEL: return new LightLabel(remainder);
case TYPE_GROUP_ID: return new GroupId(remainder);
case TYPE_GROUP_LABEL: return new GroupLabel(remainder);
case TYPE_LOCATION_ID: return new LocationId(remainder);
case TYPE_LOCATION_LABEL: return new LocationLabel(remainder);
+ case TYPE_SCENE_ID: return new SceneId(remainder);
default: return new LightLabel(selector);
}
}
diff --git a/LifxHttpSample/LifxHttpSample.csproj b/LifxHttpSample/LifxHttpSample.csproj
index 0127525..2d89916 100644
--- a/LifxHttpSample/LifxHttpSample.csproj
+++ b/LifxHttpSample/LifxHttpSample.csproj
@@ -1,83 +1,84 @@
-
-
-
-
- Debug
- AnyCPU
- {0F13DC78-BB39-4D5F-98E5-71FB4DCC110A}
- Exe
- Properties
- LifxHttpSample
- LifxHttpSample
- v4.5.2
- 512
- true
-
-
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
- ..\packages\Newtonsoft.Json.6.0.5\lib\net45\Newtonsoft.Json.dll
- True
-
-
- ..\packages\refit.2.3.0\lib\Net45\Refit.dll
- True
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {1e9e789f-2750-4e8c-8f0d-d5a41322c953}
- LifxHttp
-
-
-
-
-
-
- This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
+
+
+
+
+ Debug
+ AnyCPU
+ {0F13DC78-BB39-4D5F-98E5-71FB4DCC110A}
+ Exe
+ Properties
+ LifxHttpSample
+ LifxHttpSample
+ v4.5.2
+ 512
+ true
+
+
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Newtonsoft.Json.6.0.5\lib\net45\Newtonsoft.Json.dll
+ True
+
+
+ ..\packages\refit.2.3.0\lib\Net45\Refit.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {1e9e789f-2750-4e8c-8f0d-d5a41322c953}
+ LifxHttp
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+ -->
\ No newline at end of file
diff --git a/LifxHttpSample/Program.cs b/LifxHttpSample/Program.cs
index 4fd9d24..8d16dd3 100644
--- a/LifxHttpSample/Program.cs
+++ b/LifxHttpSample/Program.cs
@@ -4,13 +4,15 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using LifxHttp.Enums;
namespace LifxHttpSample
{
class Program
{
private const string TOKEN = "REDACTED - Generate from https://cloud.lifx.com/settings";
- private const int DELAY = 2000;
+ private const int DELAY = 2000;
+ private const int EFFECT_DELAY = 10000;
static void Main(string[] args)
{
@@ -27,13 +29,17 @@ static void Main(string[] args)
private static async Task RunDemos(LifxClient client)
{
- await DemoListing(client);
+ await DemoListing(client);
+ await DemoScenes(client);
await DemoModifyLight(client);
await DemoModifyCollections(client);
+ await DemoEffects(client);
+ await DemoValidateColor(client);
}
private static async Task DemoListing(LifxClient client)
- {
+ {
+ Console.WriteLine();
Console.WriteLine("Lights:");
foreach (var light in await client.ListLights())
{
@@ -53,12 +59,30 @@ private static async Task DemoListing(LifxClient client)
{
Console.WriteLine("{0} - {1} lights", group, group.Count());
}
- Console.WriteLine();
+ }
+
+ private static async Task DemoScenes(LifxClient client)
+ {
+ Console.WriteLine();
+ Console.WriteLine("Scenes:");
+ List scenes = await client.ListScenes();
+ if (scenes.Count() > 0)
+ {
+ foreach (var scene in scenes)
+ {
+ Console.WriteLine(scene.ToString());
+ }
+ Console.WriteLine(string.Format("Activating Scene: {0}", scenes.First().Name));
+ await client.ActivateScene(scenes.First().UUID);
+ await Task.Delay(EFFECT_DELAY);
+ }
+ else Console.WriteLine("No scenes on account.");
}
private static async Task DemoModifyLight(LifxClient client)
- {
- Light light = (await client.ListLights(new Selector.GroupLabel("Living Room"))).FirstOrDefault();
+ {
+ Console.WriteLine();
+ Light light = (await client.ListLights(new Selector.GroupLabel("Room 1"))).FirstOrDefault();
if (light == null)
{
// Find a connected light
@@ -108,7 +132,9 @@ private static async Task DemoModifyLight(LifxClient client)
}
private static async Task DemoModifyCollections(LifxClient client)
- {
+ {
+ Console.WriteLine();
+ List lights = (await client.ListLights(new Selector.LightLabel("LIFX 027d98")));
Group group = (await client.ListGroups()).FirstOrDefault();
if (group == null)
{
@@ -117,24 +143,119 @@ private static async Task DemoModifyCollections(LifxClient client)
else
{
Console.WriteLine("Using group: {0}", group);
- Console.WriteLine("Toggling group");
- await group.TogglePower();
+ Console.WriteLine("Toggling group, 3 second duration.");
+ await group.TogglePower(3);
+ await Task.Delay(DELAY + 3000);
+
Console.WriteLine("Turning group green");
- await group.SetColor(LifxColor.Green);
+ await group.SetColor(LifxColor.Green, 0);
+ await Task.Delay(DELAY);
}
Location location = (await client.ListLocations()).FirstOrDefault();
+ await Task.Delay(DELAY);
if (location == null)
{
Console.WriteLine("No locations");
}
else
+ {
+ Console.WriteLine("Using location: {0}", location);
+
+ Console.WriteLine("Turning off location");
+ await location.SetPower(PowerState.Off);
+ await Task.Delay(DELAY);
+
+ Console.WriteLine("Setting color to white with 5 second duration.");
+ await location.SetColor(new LifxColor.White(1), 5);
+ await Task.Delay(DELAY + 5000);
+
+ Console.WriteLine("Set light to a blue color, using 90% brightness override. Uses SetState explicitely.");
+ await location.SetState(PowerState.On, new LifxColor.HSBK(180, 1, 1, 2000), 0.9, 2);
+ await Task.Delay(DELAY);
+ }
+ }
+
+ private static async Task DemoEffects(LifxClient client)
+ {
+ Console.WriteLine();
+ Light light = (await client.ListLights(new Selector.GroupLabel("Room 1"))).FirstOrDefault();
+ if (light == null)
{
- Console.WriteLine("Using location: {0}", location);
- Console.WriteLine("Turning off location");
- await location.SetPower(false);
- Console.WriteLine("Turning location pink");
- await location.SetColor(LifxColor.Pink);
+ // Find a connected light
+ foreach (var l in await client.ListLights())
+ {
+ if (l.IsConnected)
+ {
+ light = l;
+ break;
+ }
+ }
+ if (!light.IsConnected)
+ {
+ Console.WriteLine("No connected lights");
+ return;
+ }
}
+ Console.WriteLine("Using light: {0}", light);
+
+ Console.WriteLine("Pulsing slowly between previously set color and green");
+ await light.PulseEffect(LifxColor.Green, 1, 10);
+ await Task.Delay(EFFECT_DELAY);
+
+ /* If strobing with a single color (therefore the light alternates between the "color" parameter and "fromColor"
+ parameter which should be set to LifxColor.OffState (zero brightness) you must set the "color" parameter to a custom color
+ with a brightness value explicitly set. The default named parameters appear to leave the light in a fixed zero brightness state
+ until the end of the effect. */
+ Console.WriteLine("Pulsing quickly in white");
+ await light.PulseEffect(new LifxColor.White(1, 3500), 0.1, 50, fromColor: LifxColor.OffState);
+ await Task.Delay(EFFECT_DELAY);
+
+ Console.WriteLine("Breathing red alert light.");
+ await light.BreatheEffect(new LifxColor.RGB(120, 0, 0), 2.5, 4, LifxColor.OffState, peak: 0.4d);
+ await Task.Delay(EFFECT_DELAY);
+
+ Console.WriteLine("\"Party breathe\", will pass through intermediate colors.");
+ await light.BreatheEffect(LifxColor.Cyan, 5, 4, LifxColor.Orange, peak: 0.5d);
+ await Task.Delay(EFFECT_DELAY);
+
+ List stateList = new List();
+ stateList.Add(new LightState(PowerState.On, LifxColor.Pink, 0.5d));
+ stateList.Add(new LightState(PowerState.On, LifxColor.Pink, 1.0d));
+ stateList.Add(new LightState(PowerState.On, LifxColor.DefaultWhite, 1.0d));
+ stateList.Add(new LightState(PowerState.On, LifxColor.Green));
+ stateList.Add(new LightState(PowerState.On, LifxColor.Blue, 1.0d));
+ stateList.Add(new LightState(PowerState.On, LifxColor.Blue, 0.5d));
+ LightState defaults = new LightState();
+ defaults.Duration = 3.0d;
+ defaults.Brightness = 1.0d;
+
+ // Cycle forward
+ Console.WriteLine("Cycling forward through set of 6 light states.");
+ for (int i = 0; i < stateList.Count(); i++)
+ {
+ await light.Cycle(stateList, defaults);
+ await Task.Delay(4000);
+ }
+
+ await Task.Delay(1000);
+
+ // Cycle backward
+ Console.WriteLine("Cycling backward through set of 6 light states.");
+ for (int i = 0; i < stateList.Count(); i++)
+ {
+ await light.Cycle(stateList, defaults, Direction.Backward);
+ await Task.Delay(4000);
+ }
+ }
+
+ private static async Task DemoValidateColor(LifxClient client)
+ {
+ string colorName = "Pink";
+ Console.WriteLine();
+ Console.WriteLine(string.Format("Validating color: {0}", colorName));
+ var color = await client.ValidateColor(colorName);
+ if (color.Item1) { Console.WriteLine(string.Format("{0} is a valid color name. Values are {1}.", colorName, color.Item2)); }
+ else Console.WriteLine(string.Format("{0} is not a valid color name.", colorName));
}
}
}
diff --git a/README.md b/README.md
index b7578ef..941629f 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,29 @@
# LifxHttpNet
-.Net wrapper around the Lifx cloud HTTP API
+### .Net wrapper around the LIFX cloud HTTP API:
-* This library acts as a thin wrapper around the public Lifx HTTP API as described
+* This library acts as a thin wrapper around the public LIFX HTTP API as described
at http://developer.lifx.com
* All operations make use of the async Task APIs via
[Refit](http://paulcbetts.github.io/refit/) for REST calls
* This library does not perform any caching or management of model objects other than to
simplify accessing the API
-* I hope that this library helps enthusiasts tinker with their Lifx lights, though much
+* I hope that this library helps enthusiasts tinker with their LIFX lights, though much
more backend code would be required for a full-featured Lifx client
* Use of this library requires a Personal Access token acquired from:
https://cloud.lifx.com/settings
* Use of this library should only be in accordance to the terms at:
- http://developer.lifx.com/terms.html
\ No newline at end of file
+ http://developer.lifx.com/terms.html
+
+### Supports the following operations:
+* List Lights
+* Toggle Power
+* Set Power State
+* Set Color
+* Set State
+* Set States
+* Breathe Effect
+* Pulse Effect
+* Cycle
+* List Scenes
+* Activate Scene
+* Validate Color
\ No newline at end of file