diff --git a/SDK.CSharp/Errors/Shockers.cs b/SDK.CSharp/Errors/Shockers.cs new file mode 100644 index 0000000..d485e69 --- /dev/null +++ b/SDK.CSharp/Errors/Shockers.cs @@ -0,0 +1,16 @@ +namespace OpenShock.SDK.CSharp.Errors; + +public struct ShockerNotFoundOrNoAccess(Guid value) +{ + public Guid Value { get; } = value; +} + +public struct ShockerPaused(Guid value) +{ + public Guid Value { get; } = value; +} + +public struct ShockerNoPermission(Guid value) +{ + public Guid Value { get; } = value; +} \ No newline at end of file diff --git a/SDK.CSharp/IOpenShockApiClient.cs b/SDK.CSharp/IOpenShockApiClient.cs index 5f0608c..1a7958a 100644 --- a/SDK.CSharp/IOpenShockApiClient.cs +++ b/SDK.CSharp/IOpenShockApiClient.cs @@ -1,5 +1,6 @@ using OneOf; using OneOf.Types; +using OpenShock.SDK.CSharp.Errors; using OpenShock.SDK.CSharp.Models; namespace OpenShock.SDK.CSharp; @@ -37,7 +38,14 @@ public Task, NotFound, DeviceOffline, DeviceNotConnec /// public Task, UnauthenticatedError>> GetSelf(CancellationToken cancellationToken = default); + /// + /// Control a shocker + /// + /// + /// + public Task> ControlShocker(ControlRequest controlRequest); } public struct DeviceOffline; -public struct DeviceNotConnectedToGateway; \ No newline at end of file +public struct DeviceNotConnectedToGateway; + diff --git a/SDK.CSharp/Models/Control.cs b/SDK.CSharp/Models/Control.cs new file mode 100644 index 0000000..564eea7 --- /dev/null +++ b/SDK.CSharp/Models/Control.cs @@ -0,0 +1,16 @@ +using System.ComponentModel.DataAnnotations; + +namespace OpenShock.SDK.CSharp.Models; + +// ReSharper disable once ClassNeverInstantiated.Global +public class Control +{ + public required Guid Id { get; set; } + [EnumDataType(typeof(ControlType))] + public required ControlType Type { get; set; } + [Range(0, 100)] + public required byte Intensity { get; set; } + [Range(300, 30000)] + public required ushort Duration { get; set; } + public bool Exclusive { get; set; } = false; +} \ No newline at end of file diff --git a/SDK.CSharp/Models/ControlRequest.cs b/SDK.CSharp/Models/ControlRequest.cs new file mode 100644 index 0000000..0055203 --- /dev/null +++ b/SDK.CSharp/Models/ControlRequest.cs @@ -0,0 +1,7 @@ +namespace OpenShock.SDK.CSharp.Models; + +public sealed class ControlRequest +{ + public required IEnumerable Shocks { get; set; } + public required string? CustomName { get; set; } +} \ No newline at end of file diff --git a/SDK.CSharp/OpenShockApiClient.cs b/SDK.CSharp/OpenShockApiClient.cs index ce0e056..fc6217f 100644 --- a/SDK.CSharp/OpenShockApiClient.cs +++ b/SDK.CSharp/OpenShockApiClient.cs @@ -1,9 +1,11 @@ using System.Net; +using System.Net.Http.Json; using System.Reflection; using System.Runtime.InteropServices; using System.Text.Json; using OneOf; using OneOf.Types; +using OpenShock.SDK.CSharp.Errors; using OpenShock.SDK.CSharp.Models; using OpenShock.SDK.CSharp.Problems; using OpenShock.SDK.CSharp.Serialization; @@ -118,6 +120,31 @@ await selfResponse.Content.ReadBaseResponseAsJsonAsync(cancellatio JsonSerializerOptions)); } + public async Task> ControlShocker(ControlRequest controlRequest) + { + using var controlResponse = + await _httpClient.PostAsJsonAsync(OpenShockEndpoints.V2.Shockers.Control, controlRequest); + + if (controlResponse.IsSuccess()) return new Success(); + + if (controlResponse.StatusCode == HttpStatusCode.Unauthorized) return new UnauthenticatedError(); + + if (!controlResponse.IsProblem()) + throw new OpenShockApiError("Error from backend is not a problem response", controlResponse.StatusCode); + + var problem = + await controlResponse.Content.ReadAsJsonAsync(default, + JsonSerializerOptions); + + return problem.Type switch + { + "Shocker.Control.NotFound" => new ShockerNotFoundOrNoAccess(problem.ShockerId), + "Shocker.Control.Paused" => new ShockerPaused(problem.ShockerId), + "Shocker.Control.NoPermission" => new ShockerNoPermission(problem.ShockerId), + _ => throw new OpenShockApiError($"Unknown problem type [{problem.Type}]", controlResponse.StatusCode) + }; + } + private string GetUserAgent() { var liveClientAssembly = GetType().Assembly; diff --git a/SDK.CSharp/OpenShockEndpoints.cs b/SDK.CSharp/OpenShockEndpoints.cs index 7f42cde..46e7ece 100644 --- a/SDK.CSharp/OpenShockEndpoints.cs +++ b/SDK.CSharp/OpenShockEndpoints.cs @@ -23,4 +23,12 @@ public static class Users public const string Self = "1/users/self"; } } + + public static class V2 + { + public static class Shockers + { + public const string Control = "1/shockers/control"; + } + } } \ No newline at end of file diff --git a/SDK.CSharp/Problems/ShockerControlProblem.cs b/SDK.CSharp/Problems/ShockerControlProblem.cs new file mode 100644 index 0000000..8e20f37 --- /dev/null +++ b/SDK.CSharp/Problems/ShockerControlProblem.cs @@ -0,0 +1,8 @@ +using System.Net; + +namespace OpenShock.SDK.CSharp.Problems; + +public sealed class ShockerControlProblem : ProblemDetails +{ + public Guid ShockerId { get; set; } +} \ No newline at end of file diff --git a/SDK.CSharp/SDK.CSharp.csproj b/SDK.CSharp/SDK.CSharp.csproj index c823c21..4149276 100644 --- a/SDK.CSharp/SDK.CSharp.csproj +++ b/SDK.CSharp/SDK.CSharp.csproj @@ -8,8 +8,8 @@ OpenShock.SDK.CSharp OpenShock.SDK.CSharp OpenShock - 0.0.21 - 0.0.21 + 0.0.22 + 0.0.22 OpenShock.SDK.DotNet OpenShock .NET / C# SDK for developing OpenShock applications. Used to interact with a OpenShock backend. @@ -32,6 +32,8 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + +