Skip to content

Commit

Permalink
Add pause example
Browse files Browse the repository at this point in the history
  • Loading branch information
LucHeart committed Feb 24, 2025
1 parent cff2cf6 commit cbefe0b
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 68 deletions.
9 changes: 9 additions & 0 deletions SDK.CSharp.Example/ExampleConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace SDK.CSharp.Example;

public sealed class ExampleConfig
{
public Uri ApiUrl { get; set; } = new("https://api.openshock.app");
public required string ApiToken { get; set; }
public Guid? Hub { get; set; }
public IReadOnlyCollection<Guid> Shockers { get; set; } = Array.Empty<Guid>();
}
41 changes: 41 additions & 0 deletions SDK.CSharp.Example/Http/PauseShocker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using OpenShock.SDK.CSharp;

namespace SDK.CSharp.Example.Http;

public sealed class PauseShocker : IExample
{
private readonly ExampleConfig _config;

public PauseShocker(ExampleConfig config)
{
_config = config;
}


public async Task Start()
{
var apiClient = new OpenShockApiClient(new ApiClientOptions
{
Token = _config.ApiToken
});

var firstShocker = _config.Shockers.First();

var response = await apiClient.PauseShocker(firstShocker, true);

response.Switch(
success => Console.WriteLine("Shocker paused: " + success.Value),
error => Console.WriteLine("Shocker not found")
);

Console.WriteLine("Press enter to unpause again");
Console.ReadLine();

response = await apiClient.PauseShocker(firstShocker, false);

response.Switch(
success => Console.WriteLine("Shocker paused: " + success.Value),
error => Console.WriteLine("Shocker not found")
);
}
}
6 changes: 6 additions & 0 deletions SDK.CSharp.Example/IExample.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace SDK.CSharp.Example;

public interface IExample
{
public Task Start();
}
60 changes: 60 additions & 0 deletions SDK.CSharp.Example/LiveControl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using Microsoft.Extensions.Logging;
using OpenShock.SDK.CSharp;
using OpenShock.SDK.CSharp.Live;
using OpenShock.SDK.CSharp.Models;

namespace SDK.CSharp.Example;

public sealed class LiveControl
{
private readonly ILoggerFactory _loggerFactory;
private readonly ILogger<LiveControl> _logger;

public LiveControl(ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
_logger = loggerFactory.CreateLogger<LiveControl>();
}

public async Task ControlExample(string apiToken, Guid hubId, Guid shockerId)
{
var apiClient = new OpenShockApiClient(new ApiClientOptions
{
Token = apiToken
});

var gatewayRequest = await apiClient.GetDeviceGateway(hubId);

if (gatewayRequest.IsT1)
{
_logger.LogError("Failed to get gateway, make sure you used a valid device id");
return;
}

if (gatewayRequest.IsT2)
{
_logger.LogError("Device is offline");
return;
}

if (gatewayRequest.IsT3)
{
_logger.LogError("Device is not connected to a gateway");
return;
}

var gateway = gatewayRequest.AsT0.Value;

_logger.LogInformation("Device is connected to gateway {GatewayId} in region {Region}", gateway.Gateway, gateway.Country);

OpenShockLiveControlClient controlClient = new(gateway.Gateway, hubId, apiToken, _loggerFactory.CreateLogger<OpenShockLiveControlClient>());
await controlClient.InitializeAsync();

while (true)
{
Console.ReadLine();
controlClient.IntakeFrame(shockerId, ControlType.Vibrate, 100);
Console.WriteLine("Sent frame");
}
}
}
111 changes: 46 additions & 65 deletions SDK.CSharp.Example/Program.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Immutable;
using System.Text.Json;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using OpenShock.SDK.CSharp;
using OpenShock.SDK.CSharp.Hub;
using OpenShock.SDK.CSharp.Live;
using OpenShock.SDK.CSharp.Models;
using SDK.CSharp.Example;
using Serilog;
using Control = OpenShock.SDK.CSharp.Hub.Models.Control;

const string apiToken = "";
var deviceId = Guid.Parse("bc849182-89e0-43ff-817b-32400be3f97d");

var hostBuilder = Host.CreateDefaultBuilder();
var hostBuilder = Host.CreateApplicationBuilder();

var loggerConfiguration = new LoggerConfiguration()
.MinimumLevel.Verbose()
Expand All @@ -21,74 +19,57 @@

Log.Logger = loggerConfiguration.CreateLogger();

hostBuilder.UseSerilog(Log.Logger);
hostBuilder.Logging.ClearProviders();
hostBuilder.Logging.AddSerilog();

var host = hostBuilder.Build();

var logger = host.Services.GetRequiredService<ILogger<Program>>();

var apiClient = new OpenShockApiClient(new ApiClientOptions
var exampleType = typeof(IExample);
typeof(Program).Assembly.GetTypes().Where(x => x.IsClass && x.IsAssignableTo(exampleType)).ToList().ForEach(x =>
{
Token = apiToken
hostBuilder.Services.TryAddEnumerable(new ServiceDescriptor(exampleType, x, ServiceLifetime.Singleton));
});

var shockers = await apiClient.GetOwnShockers();
var config = hostBuilder.Configuration.Get<ExampleConfig>()!;
hostBuilder.Services.AddSingleton<ExampleConfig>(config);
Console.WriteLine(JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true }));

if (!shockers.IsT0)
{
logger.LogError("Failed to get own shockers, make sure you used a valid api token");
return;
}
var host = hostBuilder.Build();

var apiSignalRHubClient = new OpenShockHubClient(new HubClientOptions
var console = new Thread(async () =>
{
Token = apiToken,
ConfigureLogging = builder => builder.AddSerilog(Log.Logger)
});

await apiSignalRHubClient.StartAsync();
Console.WriteLine("OpenShock Example Program...");

var examples = host.Services.GetServices<IExample>().ToImmutableArray();
Console.WriteLine($"Available Examples:");

await apiSignalRHubClient.Control([
new Control
for (int i = 0; i < examples.Length; i++)
{
Id = Guid.Parse("d9267ca6-d69b-4b7a-b482-c455f75a4408"),
Type = ControlType.Shock,
Intensity = 10,
Duration = 1000,
Exclusive = true
var example = examples[i];
Console.WriteLine($"[{i}] {example.GetType().Name}");
}
]);

var gatewayRequest = await apiClient.GetDeviceGateway(deviceId);

if (gatewayRequest.IsT1)
{
logger.LogError("Failed to get gateway, make sure you used a valid device id");
return;
}

if (gatewayRequest.IsT2)
{
logger.LogError("Device is offline");
return;
}

if (gatewayRequest.IsT3)
{
logger.LogError("Device is not connected to a gateway");
return;
}
while (true)
{
var input = Console.ReadLine();
if (!int.TryParse(input, out var choice))
{
Console.WriteLine("Invalid choice");
continue;
}

var example = examples[choice];

if (examples == null) Console.WriteLine("Invalid choice, example doesnt exist");

Console.WriteLine($"Starting example {example.GetType().Name}");

example.Start().Wait();
}

var gateway = gatewayRequest.AsT0.Value;
});

logger.LogInformation("Device is connected to gateway {GatewayId} in region {Region}", gateway.Gateway, gateway.Country);
console.IsBackground = true;

OpenShockLiveControlClient controlClient = new(gateway.Gateway, deviceId, apiToken, host.Services.GetRequiredService<ILogger<OpenShockLiveControlClient>>());
await controlClient.InitializeAsync();
console.Start();

while (true)
{
Console.ReadLine();
controlClient.IntakeFrame(Guid.Parse("d9267ca6-d69b-4b7a-b482-c455f75a4408"), ControlType.Vibrate, 100);
Console.WriteLine("Sent frame");
}
await host.RunAsync();
40 changes: 40 additions & 0 deletions SDK.CSharp.Example/SignalrHub.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using OpenShock.SDK.CSharp.Hub;
using OpenShock.SDK.CSharp.Models;
using Serilog;

namespace SDK.CSharp.Example;

public sealed class SignalrHub : IExample
{
private readonly ExampleConfig _config;

public SignalrHub(ExampleConfig config)
{
_config = config;
}

public async Task Start()
{
var apiSignalRHubClient = new OpenShockHubClient(new HubClientOptions
{
Server = _config.ApiUrl,
Token = _config.ApiToken,
ConfigureLogging = builder => builder.AddSerilog(Log.Logger)
});

await apiSignalRHubClient.StartAsync();



await apiSignalRHubClient.Control(_config.Shockers.Select(x => new OpenShock.SDK.CSharp.Hub.Models.Control
{
Id = x,
Type = ControlType.Shock,
Intensity = 10,
Duration = 1000,
Exclusive = true
}));


}
}
3 changes: 2 additions & 1 deletion SDK.CSharp/IOpenShockApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ public Task<OneOf<Success<LcgResponse>, NotFound, DeviceOffline, DeviceNotConnec
/// <param name="paused">True when the shocker needs to be paused</param>
/// <param name="cancellationToken"></param>
/// <returns>bool that indicates the current state of the shocker pause</returns>
public Task<OneOf<Success<bool>, NotFound>> PauseShocker(Guid shockerId, bool paused, CancellationToken cancellationToken = default);
public Task<OneOf<Success<bool>, NotFound>> PauseShocker(Guid shockerId, bool paused,
CancellationToken cancellationToken = default);
}

public struct DeviceOffline;
Expand Down
2 changes: 1 addition & 1 deletion SDK.CSharp/OpenShockApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ await pauseResponse.Content.ReadBaseResponseAsJsonAsync<bool>(cancellationToken,
var problem = await pauseResponse.Content.ReadAsJsonAsync<ProblemDetails>(cancellationToken, JsonSerializerOptions);
if (problem.Type == "Shocker.NotFound") return new NotFound();

throw new OpenShockApiError("Failed to pause shocker", pauseResponse.StatusCode);
throw new OpenShockApiError("Failed to pause shocker", problem);
}

private string GetUserAgent()
Expand Down
11 changes: 10 additions & 1 deletion SDK.CSharp/OpenShockApiError.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
using System.Net;
using OpenShock.SDK.CSharp.Problems;

namespace OpenShock.SDK.CSharp;

public sealed class OpenShockApiError : Exception
{
public OpenShockApiError(string message, HttpStatusCode statusCode) : base(message)
public OpenShockApiError(string message, HttpStatusCode statusCode) : base($"{message} (HTTP {(int)statusCode})")
{
}

public OpenShockApiError(string message, ProblemDetails problemDetails) : base(
$"{message} (HTTP {problemDetails.Status}; {problemDetails.Title}; {problemDetails.Detail})")
{
ProblemDetails = problemDetails;
}

public ProblemDetails? ProblemDetails { get; }
}

0 comments on commit cbefe0b

Please sign in to comment.