-
-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reworked the entire API layer to use DTO classes and use the factory pattern #192
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
using System.Collections.Generic; | ||
using Winleafs.Api.DTOs; | ||
using Winleafs.Api.Exceptions; | ||
using Winleafs.Models.Models; | ||
|
||
namespace Winleafs.Api | ||
{ | ||
public class ClientFactory | ||
{ | ||
private readonly Dictionary<string, INanoleafClient> _clients = new Dictionary<string, INanoleafClient>(); | ||
|
||
public static ClientFactory Instance { get; } = new ClientFactory(); | ||
|
||
private ClientFactory() | ||
{ | ||
} | ||
|
||
public INanoleafClient Get(Device device) | ||
{ | ||
|
||
if (device == null || string.IsNullOrWhiteSpace(device.IPAddress) || device.Port == default) | ||
{ | ||
throw new InvalidDeviceException("The provided device does not have a valid IP or port."); | ||
} | ||
|
||
var key = GetIdentifier(device.IPAddress, device.Port); | ||
if (_clients.ContainsKey(key)) | ||
{ | ||
return _clients[key]; | ||
} | ||
|
||
var client = new NanoleafClient(new ClientDto(device)); | ||
_clients.Add(key, client); | ||
return client; | ||
} | ||
|
||
public INanoleafClient Get(string ip, int port, string authenticationToken = null) | ||
{ | ||
if (string.IsNullOrWhiteSpace(ip) || port == default) | ||
{ | ||
throw new InvalidDeviceException("The provided device does not have a valid IP or port."); | ||
} | ||
|
||
var key = GetIdentifier(ip, port); | ||
if (_clients.ContainsKey(key)) | ||
{ | ||
return _clients[key]; | ||
} | ||
|
||
var client = new NanoleafClient(new ClientDto(ip, port, authenticationToken)); | ||
_clients.Add(key, client); | ||
return client; | ||
} | ||
|
||
public bool Delete(Device device) | ||
{ | ||
if (device == null) | ||
{ | ||
return false; | ||
} | ||
|
||
var key = GetIdentifier(device.IPAddress, device.Port); | ||
return _clients.Remove(key); | ||
} | ||
|
||
private static string GetIdentifier(string ip, int port) | ||
{ | ||
return ip + '-' + port; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using Newtonsoft.Json; | ||
|
||
namespace Winleafs.Api.DTOs.Authentication | ||
{ | ||
public class AuthenticationDto | ||
{ | ||
[JsonProperty("auth_token")] | ||
public string AuthenticationToken { get; set; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
using Winleafs.Models.Models; | ||
|
||
namespace Winleafs.Api.DTOs | ||
{ | ||
public class ClientDto | ||
{ | ||
public ClientDto(string ip, int port, string authenticationToken = null) | ||
{ | ||
Ip = ip; | ||
Port = port; | ||
AuthenticationToken = authenticationToken; | ||
} | ||
|
||
public ClientDto(Device device) | ||
{ | ||
Ip = device.IPAddress; | ||
Port = device.Port; | ||
AuthenticationToken = device.AuthToken; | ||
} | ||
|
||
public string Ip { get; set; } | ||
|
||
public int Port { get; set; } | ||
|
||
public string AuthenticationToken { get; set; } | ||
|
||
public string BaseUrl => $"http://{Ip}:{Port}/api/v1/{AuthenticationToken}/"; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using Winleafs.Api.DTOs.Shared; | ||
|
||
namespace Winleafs.Api.DTOs.Effects | ||
{ | ||
public class GetEffectDetailsDto | ||
{ | ||
public GetEffectDetailsDto(string effectName) | ||
{ | ||
Write = new WriteObjectDto(WriteCommands.Request, effectName); | ||
} | ||
|
||
public WriteObjectDto Write { get; set; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
namespace Winleafs.Api.DTOs.Effects | ||
{ | ||
public class SelectEffectDto | ||
{ | ||
public SelectEffectDto(string select) | ||
{ | ||
Select = select; | ||
} | ||
|
||
public string Select { get; set; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using Winleafs.Api.DTOs.Shared; | ||
|
||
namespace Winleafs.Api.DTOs.ExternalControl | ||
{ | ||
public class ExternalControlDto | ||
{ | ||
public ExternalControlDto(string version) | ||
{ | ||
Write = new WriteObjectDto() | ||
{ | ||
Command = WriteCommands.Display, | ||
AnimType = "extControl", | ||
ExtControlVersion = version | ||
}; | ||
} | ||
|
||
public WriteObjectDto Write { get; set; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace Winleafs.Api.DTOs.Shared | ||
{ | ||
public static class WriteCommands | ||
{ | ||
public static string Request => "request"; | ||
|
||
public static string Display => "display"; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
namespace Winleafs.Api.DTOs.Shared | ||
{ | ||
public class WriteObjectDto | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use full names for variables and parameters There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this be more specific or is it used for all writes? Then maybe make this a base class and make one or more derived classes, which then has, for example, the |
||
{ | ||
public string Command { get; set; } | ||
|
||
public string AnimName { get; set; } | ||
|
||
public string AnimType { get; set; } | ||
|
||
public string ExtControlVersion { get; set; } | ||
|
||
public WriteObjectDto() | ||
{ | ||
} | ||
|
||
public WriteObjectDto(string command, string animName, string extControlVersion = null) | ||
{ | ||
Command = command; | ||
AnimName = animName; | ||
ExtControlVersion = extControlVersion; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
namespace Winleafs.Api.DTOs.States | ||
{ | ||
public class SetStateDto | ||
{ | ||
public SetStateDto(bool value) | ||
{ | ||
On = new StateValueDto(value); | ||
} | ||
|
||
public StateValueDto On { get; set; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
using Newtonsoft.Json; | ||
|
||
namespace Winleafs.Api.DTOs.States | ||
{ | ||
public class SetStateValuesDto | ||
{ | ||
public SetStateValuesDto() | ||
{ | ||
} | ||
|
||
public SetStateValuesDto(int hue, int saturation) | ||
{ | ||
Hue = new SetValueDto(hue); | ||
Saturation = new SetValueDto(saturation); | ||
} | ||
|
||
public SetStateValuesDto(int hue, int saturation, int brightness) | ||
{ | ||
Brightness = new SetValueWithDurationDto(brightness, null); | ||
Hue = new SetValueDto(hue); | ||
Saturation = new SetValueDto(saturation); | ||
} | ||
|
||
public SetValueDto Hue { get; set; } | ||
|
||
[JsonProperty("sat")] | ||
public SetValueDto Saturation { get; set; } | ||
|
||
public SetValueWithDurationDto Brightness { get; set; } | ||
|
||
public static SetStateValuesDto SetBrightness(int value, int? duration = null) | ||
{ | ||
return new SetStateValuesDto() | ||
{ | ||
Brightness = new SetValueWithDurationDto(value, duration) | ||
}; | ||
} | ||
|
||
public static SetStateValuesDto SetHue(int value) | ||
{ | ||
return new SetStateValuesDto() | ||
{ | ||
Hue = new SetValueDto(value) | ||
}; | ||
} | ||
|
||
public static SetStateValuesDto SetSaturation(int value) | ||
{ | ||
return new SetStateValuesDto() | ||
{ | ||
Saturation = new SetValueDto(value) | ||
}; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
namespace Winleafs.Api.DTOs.States | ||
{ | ||
public class SetValueDto | ||
{ | ||
public SetValueDto(int value) | ||
{ | ||
Value = value; | ||
} | ||
|
||
public int Value { get; set; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
namespace Winleafs.Api.DTOs.States | ||
{ | ||
public class SetValueWithDurationDto | ||
{ | ||
public SetValueWithDurationDto(int value, int? duration = null) | ||
{ | ||
Value = value; | ||
Duration = duration; | ||
} | ||
|
||
public int Value { get; set; } | ||
|
||
public int? Duration { get; set; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
namespace Winleafs.Api.DTOs.States | ||
{ | ||
public class StateValueDto | ||
{ | ||
public StateValueDto(bool value) | ||
{ | ||
Value = value; | ||
} | ||
|
||
public bool Value { get; set; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,44 @@ | ||
using System.Threading.Tasks; | ||
|
||
using Newtonsoft.Json.Linq; | ||
|
||
using Newtonsoft.Json; | ||
using RestSharp; | ||
|
||
using RestSharp.Serializers.NewtonsoftJson; | ||
using Winleafs.Api.DTOs; | ||
using Winleafs.Api.DTOs.Authentication; | ||
using Winleafs.Api.Endpoints.Interfaces; | ||
|
||
namespace Winleafs.Api.Endpoints | ||
{ | ||
public class AuthorizationEndpoint : NanoleafEndpoint, IAuthorizationEndpoint | ||
{ | ||
/// <inheritdoc /> | ||
public AuthorizationEndpoint(NanoleafClient client) | ||
{ | ||
Client = client; | ||
} | ||
public class AuthorizationEndpoint : NanoleafEndpoint, IAuthorizationEndpoint | ||
{ | ||
/// <inheritdoc /> | ||
public AuthorizationEndpoint(ClientDto client) | ||
{ | ||
Client = client; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public string GetAuthToken() | ||
/// <inheritdoc /> | ||
public string GetAuthToken() | ||
{ | ||
return GetAuthTokenAsync().ConfigureAwait(false).GetAwaiter().GetResult(); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public async Task<string> GetAuthTokenAsync() | ||
{ | ||
var client = new RestClient(Client.BaseUri); | ||
var request = new RestRequest("api/v1/new", Method.POST); | ||
var response = await client.ExecuteAsync(request).ConfigureAwait(false); | ||
/// <inheritdoc /> | ||
public async Task<string> GetAuthTokenAsync() | ||
{ | ||
var client = new RestClient($"http://{Client.Ip}:{Client.Port}"); | ||
client.UseNewtonsoftJson(); | ||
var request = new RestRequest("api/v1/new", Method.POST); | ||
var response = await client.ExecuteAsync<AuthenticationDto>(request).ConfigureAwait(false); | ||
|
||
|
||
var jObject = JObject.Parse(response.Content); | ||
Client.Token = jObject["auth_token"].ToString(); | ||
if (!response.IsSuccessful) | ||
{ | ||
return null; | ||
} | ||
|
||
return Client.Token; | ||
} | ||
} | ||
Client.AuthenticationToken = response.Data.AuthenticationToken; | ||
|
||
return Client.AuthenticationToken; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the best location or this base url? Maybe in the client class?