Rewrite Hierachy that shockers now contain the api they use.
This commit is contained in:
@ -7,13 +7,13 @@ using CShocker.Shockers;
|
||||
using CShocker.Shockers.Abstract;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CShocker.Devices;
|
||||
namespace CShocker.Devices.APIs;
|
||||
|
||||
public class OpenShockHttp : OpenShockDevice
|
||||
public class OpenShockHttp : OpenShockApi
|
||||
{
|
||||
|
||||
|
||||
protected override void ControlInternal(ControlAction action, IShocker shocker, int intensity, int duration)
|
||||
protected override void ControlInternal(ControlAction action, Shocker shocker, int intensity, int duration)
|
||||
{
|
||||
if (shocker is not OpenShockShocker openShockShocker)
|
||||
{
|
@ -6,9 +6,9 @@ using CShocker.Shockers;
|
||||
using CShocker.Shockers.Abstract;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CShocker.Devices;
|
||||
namespace CShocker.Devices.APIs;
|
||||
|
||||
public class OpenShockSerial : OpenShockDevice
|
||||
public class OpenShockSerial : OpenShockApi
|
||||
{
|
||||
private const int BaudRate = 115200;
|
||||
public SerialPortInfo SerialPortI;
|
||||
@ -18,10 +18,18 @@ public class OpenShockSerial : OpenShockDevice
|
||||
{
|
||||
this.SerialPortI = serialPortI;
|
||||
this._serialPort = new SerialPort(serialPortI.PortName, BaudRate);
|
||||
this._serialPort.Open();
|
||||
try
|
||||
{
|
||||
this._serialPort.Open();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.Logger?.Log(LogLevel.Error, e.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ControlInternal(ControlAction action, IShocker shocker, int intensity, int duration)
|
||||
protected override void ControlInternal(ControlAction action, Shocker shocker, int intensity, int duration)
|
||||
{
|
||||
if (shocker is not OpenShockShocker openShockShocker)
|
||||
{
|
@ -7,9 +7,9 @@ using CShocker.Shockers;
|
||||
using CShocker.Shockers.Abstract;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CShocker.Devices;
|
||||
namespace CShocker.Devices.APIs;
|
||||
|
||||
public class PiShockHttp : PiShockDevice
|
||||
public class PiShockHttp : PiShockApi
|
||||
{
|
||||
// ReSharper disable twice MemberCanBePrivate.Global external usage
|
||||
public string Username, Endpoint, ApiKey;
|
||||
@ -22,7 +22,7 @@ public class PiShockHttp : PiShockDevice
|
||||
this.ApiKey = apiKey;
|
||||
}
|
||||
|
||||
protected override void ControlInternal(ControlAction action, IShocker shocker, int intensity, int duration)
|
||||
protected override void ControlInternal(ControlAction action, Shocker shocker, int intensity, int duration)
|
||||
{
|
||||
if (shocker is not PiShockShocker piShockShocker)
|
||||
{
|
@ -5,9 +5,9 @@ using CShocker.Ranges;
|
||||
using CShocker.Shockers.Abstract;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CShocker.Devices;
|
||||
namespace CShocker.Devices.APIs;
|
||||
|
||||
public class PiShockSerial : PiShockDevice
|
||||
public class PiShockSerial : PiShockApi
|
||||
{
|
||||
private const int BaudRate = 115200;
|
||||
public SerialPortInfo SerialPortI;
|
||||
@ -20,7 +20,7 @@ public class PiShockSerial : PiShockDevice
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override void ControlInternal(ControlAction action, IShocker shocker, int intensity, int duration)
|
||||
protected override void ControlInternal(ControlAction action, Shocker shocker, int intensity, int duration)
|
||||
{
|
||||
string json = "{" +
|
||||
"\"cmd\": \"operate\"," +
|
@ -5,20 +5,20 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CShocker.Devices.Abstract;
|
||||
|
||||
public abstract class Device : IDisposable
|
||||
public abstract class Api : IDisposable
|
||||
{
|
||||
// ReSharper disable 4 times MemberCanBePrivate.Global external use
|
||||
public readonly IntensityRange IntensityRange;
|
||||
public readonly DurationRange DurationRange;
|
||||
protected ILogger? Logger;
|
||||
public readonly DeviceApi ApiType;
|
||||
private readonly Queue<ValueTuple<ControlAction, IShocker, int, int>> _queue = new();
|
||||
private readonly Queue<ValueTuple<ControlAction, Shocker, int, int>> _queue = new();
|
||||
private bool _workQueue = true;
|
||||
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
|
||||
private readonly Thread _workQueueThread;
|
||||
private const short CommandDelay = 50;
|
||||
|
||||
public void Control(ControlAction action, int? intensity = null, int? duration = null, params IShocker[] shockers)
|
||||
internal void Control(ControlAction action, int? intensity = null, int? duration = null, params Shocker[] shockers)
|
||||
{
|
||||
int i = intensity ?? IntensityRange.GetRandomRangeValue();
|
||||
int d = duration ?? DurationRange.GetRandomRangeValue();
|
||||
@ -27,16 +27,16 @@ public abstract class Device : IDisposable
|
||||
this.Logger?.Log(LogLevel.Information, "Doing nothing");
|
||||
return;
|
||||
}
|
||||
foreach (IShocker shocker in shockers)
|
||||
foreach (Shocker shocker in shockers)
|
||||
{
|
||||
this.Logger?.Log(LogLevel.Debug, $"Enqueueing {action} {(intensity is not null ? $"Overwrite {i}" : $"{i}")} {(duration is not null ? $"Overwrite {d}" : $"{d}")}");
|
||||
_queue.Enqueue(new(action, shocker, i ,d));
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void ControlInternal(ControlAction action, IShocker shocker, int intensity, int duration);
|
||||
protected abstract void ControlInternal(ControlAction action, Shocker shocker, int intensity, int duration);
|
||||
|
||||
protected Device(IntensityRange intensityRange, DurationRange durationRange, DeviceApi apiType, ILogger? logger = null)
|
||||
protected Api(IntensityRange intensityRange, DurationRange durationRange, DeviceApi apiType, ILogger? logger = null)
|
||||
{
|
||||
this.IntensityRange = intensityRange;
|
||||
this.DurationRange = durationRange;
|
||||
@ -71,10 +71,10 @@ public abstract class Device : IDisposable
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is Device d && Equals(d);
|
||||
return obj is Api d && Equals(d);
|
||||
}
|
||||
|
||||
protected bool Equals(Device other)
|
||||
protected bool Equals(Api other)
|
||||
{
|
||||
return IntensityRange.Equals(other.IntensityRange) && DurationRange.Equals(other.DurationRange) && ApiType == other.ApiType;
|
||||
}
|
@ -7,13 +7,14 @@ using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace CShocker.Devices.Abstract;
|
||||
|
||||
public abstract class OpenShockDevice : Device
|
||||
public abstract class OpenShockApi : Api
|
||||
{
|
||||
protected readonly HttpClient HttpClient = new();
|
||||
public string Endpoint { get; init; }
|
||||
public string ApiKey { get; init; }
|
||||
private const string DefaultEndpoint = "https://api.shocklink.net";
|
||||
|
||||
public OpenShockDevice(IntensityRange intensityRange, DurationRange durationRange, DeviceApi apiType, string apiKey, string endpoint = "https://api.shocklink.net", ILogger? logger = null) : base(intensityRange, durationRange, apiType, logger)
|
||||
public OpenShockApi(IntensityRange intensityRange, DurationRange durationRange, DeviceApi apiType, string apiKey, string endpoint = DefaultEndpoint, ILogger? logger = null) : base(intensityRange, durationRange, apiType, logger)
|
||||
{
|
||||
this.Endpoint = endpoint;
|
||||
this.ApiKey = apiKey;
|
||||
@ -21,10 +22,10 @@ public abstract class OpenShockDevice : Device
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is OpenShockDevice osd && Equals(osd);
|
||||
return obj is OpenShockApi osd && Equals(osd);
|
||||
}
|
||||
|
||||
private bool Equals(OpenShockDevice other)
|
||||
private bool Equals(OpenShockApi other)
|
||||
{
|
||||
return base.Equals(other) && Endpoint == other.Endpoint && ApiKey == other.ApiKey;
|
||||
}
|
||||
@ -34,12 +35,18 @@ public abstract class OpenShockDevice : Device
|
||||
return HashCode.Combine(Endpoint, ApiKey);
|
||||
}
|
||||
|
||||
public List<OpenShockShocker> GetShockers()
|
||||
public List<OpenShockShocker> GetShockers(string apiKey, string apiEndpoint = DefaultEndpoint,
|
||||
ILogger? logger = null)
|
||||
{
|
||||
return GetShockers(apiKey, this, apiEndpoint, logger);
|
||||
}
|
||||
|
||||
public static List<OpenShockShocker> GetShockers(string apiKey, OpenShockApi api, string apiEndpoint = DefaultEndpoint, ILogger? logger = null)
|
||||
{
|
||||
List<OpenShockShocker> shockers = new();
|
||||
|
||||
HttpClient httpClient = new();
|
||||
HttpRequestMessage requestOwnShockers = new (HttpMethod.Get, $"{Endpoint}/1/shockers/own")
|
||||
HttpRequestMessage requestOwnShockers = new (HttpMethod.Get, $"{apiEndpoint}/1/shockers/own")
|
||||
{
|
||||
Headers =
|
||||
{
|
||||
@ -47,21 +54,24 @@ public abstract class OpenShockDevice : Device
|
||||
Accept = { new MediaTypeWithQualityHeaderValue("application/json") }
|
||||
}
|
||||
};
|
||||
requestOwnShockers.Headers.Add("OpenShockToken", ApiKey);
|
||||
this.Logger?.Log(LogLevel.Debug, $"Requesting {requestOwnShockers.RequestUri}");
|
||||
requestOwnShockers.Headers.Add("OpenShockToken", apiKey);
|
||||
logger?.Log(LogLevel.Debug, $"Requesting {requestOwnShockers.RequestUri}");
|
||||
HttpResponseMessage ownResponse = httpClient.Send(requestOwnShockers);
|
||||
this.Logger?.Log(!ownResponse.IsSuccessStatusCode ? LogLevel.Error : LogLevel.Debug,
|
||||
logger?.Log(!ownResponse.IsSuccessStatusCode ? LogLevel.Error : LogLevel.Debug,
|
||||
$"{requestOwnShockers.RequestUri} response: {ownResponse.StatusCode}");
|
||||
if (!ownResponse.IsSuccessStatusCode)
|
||||
return shockers;
|
||||
|
||||
StreamReader ownShockerStreamReader = new(ownResponse.Content.ReadAsStream());
|
||||
string ownShockerJson = ownShockerStreamReader.ReadToEnd();
|
||||
this.Logger?.Log(LogLevel.Debug,ownShockerJson);
|
||||
logger?.Log(LogLevel.Debug,ownShockerJson);
|
||||
JObject ownShockerListJObj = JObject.Parse(ownShockerJson);
|
||||
shockers.AddRange(ownShockerListJObj.SelectTokens("$.data..shockers[*]").Select(t => t.ToObject<OpenShockShocker>()));
|
||||
shockers.AddRange(ownShockerListJObj.SelectTokens("$.data..shockers[*]").Select(t =>
|
||||
{
|
||||
return new OpenShockShocker(api, t["name"]!.Value<string>()!, t["id"]!.Value<string>()!, t["rfId"]!.Value<short>(), Enum.Parse<OpenShockShocker.OpenShockModel>(t["model"]!.Value<string>()!), t["createdOn"]!.ToObject<DateTime>(), t["isPaused"]!.Value<bool>());
|
||||
}));
|
||||
|
||||
HttpRequestMessage requestSharedShockers = new (HttpMethod.Get, $"{Endpoint}/1/shockers/shared")
|
||||
HttpRequestMessage requestSharedShockers = new (HttpMethod.Get, $"{apiEndpoint}/1/shockers/shared")
|
||||
{
|
||||
Headers =
|
||||
{
|
||||
@ -69,19 +79,22 @@ public abstract class OpenShockDevice : Device
|
||||
Accept = { new MediaTypeWithQualityHeaderValue("application/json") }
|
||||
}
|
||||
};
|
||||
requestSharedShockers.Headers.Add("OpenShockToken", ApiKey);
|
||||
this.Logger?.Log(LogLevel.Debug, $"Requesting {requestSharedShockers.RequestUri}");
|
||||
requestSharedShockers.Headers.Add("OpenShockToken", apiKey);
|
||||
logger?.Log(LogLevel.Debug, $"Requesting {requestSharedShockers.RequestUri}");
|
||||
HttpResponseMessage sharedResponse = httpClient.Send(requestSharedShockers);
|
||||
this.Logger?.Log(!sharedResponse.IsSuccessStatusCode ? LogLevel.Error : LogLevel.Debug,
|
||||
logger?.Log(!sharedResponse.IsSuccessStatusCode ? LogLevel.Error : LogLevel.Debug,
|
||||
$"{requestSharedShockers.RequestUri} response: {sharedResponse.StatusCode}");
|
||||
if (!sharedResponse.IsSuccessStatusCode)
|
||||
return shockers;
|
||||
|
||||
StreamReader sharedShockerStreamReader = new(sharedResponse.Content.ReadAsStream());
|
||||
string sharedShockerJson = sharedShockerStreamReader.ReadToEnd();
|
||||
this.Logger?.Log(LogLevel.Debug, sharedShockerJson);
|
||||
logger?.Log(LogLevel.Debug, sharedShockerJson);
|
||||
JObject sharedShockerListJObj = JObject.Parse(sharedShockerJson);
|
||||
shockers.AddRange(sharedShockerListJObj.SelectTokens("$.data..shockers[*]").Select(t => t.ToObject<OpenShockShocker>()));
|
||||
shockers.AddRange(sharedShockerListJObj.SelectTokens("$.data..shockers[*]").Select(t =>
|
||||
{
|
||||
return new OpenShockShocker(api, t["name"]!.Value<string>()!, t["id"]!.Value<string>()!, t["rfId"]!.Value<short>(),Enum.Parse<OpenShockShocker.OpenShockModel>(t["model"]!.Value<string>()!), t["createdOn"]!.ToObject<DateTime>(), t["isPaused"]!.Value<bool>());
|
||||
}));
|
||||
return shockers;
|
||||
}
|
||||
}
|
12
CShocker/Devices/Abstract/PiShockApi.cs
Normal file
12
CShocker/Devices/Abstract/PiShockApi.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using CShocker.Devices.Additional;
|
||||
using CShocker.Ranges;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CShocker.Devices.Abstract;
|
||||
|
||||
public abstract class PiShockApi : Api
|
||||
{
|
||||
protected PiShockApi(IntensityRange intensityRange, DurationRange durationRange, DeviceApi apiType, ILogger? logger = null) : base(intensityRange, durationRange, apiType, logger)
|
||||
{
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
using CShocker.Devices.Additional;
|
||||
using CShocker.Ranges;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CShocker.Devices.Abstract;
|
||||
|
||||
public abstract class PiShockDevice : Device
|
||||
{
|
||||
protected PiShockDevice(IntensityRange intensityRange, DurationRange durationRange, DeviceApi apiType, ILogger? logger = null) : base(intensityRange, durationRange, apiType, logger)
|
||||
{
|
||||
}
|
||||
}
|
@ -1,15 +1,16 @@
|
||||
using CShocker.Devices.Abstract;
|
||||
using CShocker.Devices.APIs;
|
||||
using CShocker.Ranges;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace CShocker.Devices.Additional;
|
||||
|
||||
public class DeviceJsonConverter : JsonConverter
|
||||
public class ApiJsonConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return (objectType == typeof(Device));
|
||||
return (objectType == typeof(Api));
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
|
Reference in New Issue
Block a user