Skip to content
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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
3 changes: 2 additions & 1 deletion Winleafs.Api.Test/Program.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using System;
using Winleafs.Api.DTOs;

namespace Winleafs.Api.Test
{
class Program
{
static void Main(string[] args)
{
var nanoLeafClient = new NanoleafClient("192.168.178.160", 16021);
var nanoLeafClient = new NanoleafClient(new ClientDto("192.168.178.160", 16021));
Console.WriteLine("Authorizing..");
nanoLeafClient.AuthorizationEndpoint.GetAuthTokenAsync().GetAwaiter().GetResult();
Console.WriteLine("Authorized!");
Expand Down
71 changes: 71 additions & 0 deletions Winleafs.Api/ClientFactory.cs
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;
}
}
}
10 changes: 10 additions & 0 deletions Winleafs.Api/DTOs/Authentication/AuthenticationDto.cs
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; }
}
}
29 changes: 29 additions & 0 deletions Winleafs.Api/DTOs/ClientDto.cs
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}/";
Copy link
Member

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?

}
}
14 changes: 14 additions & 0 deletions Winleafs.Api/DTOs/Effects/GetEffectDetailsDto.cs
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; }
}
}
12 changes: 12 additions & 0 deletions Winleafs.Api/DTOs/Effects/SelectEffectDto.cs
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; }
}
}
19 changes: 19 additions & 0 deletions Winleafs.Api/DTOs/ExternalControl/ExternalControlDto.cs
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; }
}
}
9 changes: 9 additions & 0 deletions Winleafs.Api/DTOs/Shared/WriteCommands.cs
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";
}
}
24 changes: 24 additions & 0 deletions Winleafs.Api/DTOs/Shared/WriteObjectDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace Winleafs.Api.DTOs.Shared
{
public class WriteObjectDto
Copy link
Member

Choose a reason for hiding this comment

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

Use full names for variables and parameters

Copy link
Member

Choose a reason for hiding this comment

The 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 ExtControlVersion property

{
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;
}
}
}
12 changes: 12 additions & 0 deletions Winleafs.Api/DTOs/States/SetStateDto.cs
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; }
}
}
55 changes: 55 additions & 0 deletions Winleafs.Api/DTOs/States/SetStateValuesDto.cs
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)
};
}
}
}
12 changes: 12 additions & 0 deletions Winleafs.Api/DTOs/States/SetValueDto.cs
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; }
}
}
15 changes: 15 additions & 0 deletions Winleafs.Api/DTOs/States/SetValueWithDurationDto.cs
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; }
}
}
12 changes: 12 additions & 0 deletions Winleafs.Api/DTOs/States/StateValueDto.cs
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; }
}
}
54 changes: 30 additions & 24 deletions Winleafs.Api/Endpoints/AuthorizationEndpoint.cs
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;
}
}
}
Loading