-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* release/0.1.0: Update readme & abstract local file creation (GH-6) Add xml documentation to public members * fixes #6 (GH-3) Add Set/Get Date, Take picture sets date * fixes #3 (GH-4) Reduce external dependencies * fixes #4 Add TakePicture support for local uri Inital PoC
- Loading branch information
Showing
37 changed files
with
5,075 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,79 @@ | ||
# OSC.Net | ||
.NET Standard Library for Open Spherical Camera API | ||
.NET Standard Library for Open Spherical Camera API 2.0 | ||
|
||
## Example | ||
```csharp | ||
var cameraClient = new CameraClient(); | ||
cameraClient.TakePicture("test.jpg"); | ||
``` | ||
|
||
## Client | ||
|
||
The library exposes `CameraClient` class which implements an `ICameraClient` interface, which has a set of extension methods on it i.e. `TakePicture()`. | ||
|
||
### Create client default IP (192.168.42.1) and Port (80) | ||
```csharp | ||
var cameraClient = new CameraClient(); | ||
``` | ||
|
||
### Create client supply IP and Port | ||
```csharp | ||
var cameraClient = new CameraClient(new IPEndPoint(IPAddress.Parse("192.168.42.1"), 80)); | ||
``` | ||
|
||
### Create client supply Uri | ||
```csharp | ||
var cameraClient = new CameraClient(new Uri("http://192.168.42.1")); | ||
``` | ||
|
||
### HttpClientFactoryHandler | ||
|
||
All `CameraClient` constructors takes an optional `HttpClientFactoryHandler` `createClient`parameter which allows you to override how the internally used HttpClient is created. | ||
|
||
Example usage with `System.Net` `IHttpClientFactory` | ||
```csharp | ||
var serviceProvider = new ServiceCollection().AddHttpClient().BuildServiceProvider(); | ||
var httpClientFactory = serviceProvider.GetService<IHttpClientFactory>(); | ||
|
||
var httpClientFactory = serviceProvider.GetService<IHttpClientFactory>(); | ||
|
||
var cameraClient = new CameraClient(createClient: httpClientFactory.CreateClient); | ||
``` | ||
|
||
### CreateFileHandler | ||
|
||
All `CameraClient` constructors takes an optional `CreateFileHandler` `createFile`parameter which allows you to override how local files are created. | ||
|
||
```csharp | ||
var cameraClient = new CameraClient( | ||
createFile: path => File.Open(path, FileMode.Create, FileAccess.Write, FileShare.None)); | ||
``` | ||
|
||
## Take Picture | ||
|
||
### Take picture and get uri to image | ||
|
||
```csharp | ||
var pictureUri = await client.TakePicture(); | ||
``` | ||
|
||
### Take picture and download image to supplied stream | ||
|
||
```csharp | ||
var imageStream = new MemoryStream(); | ||
await client.TakePicture(imageStream); | ||
``` | ||
|
||
### Take picture and save to supplied local path | ||
```csharp | ||
await client.TakePicture("test.jpg"); | ||
``` | ||
|
||
### useLocalFileUri | ||
|
||
All `TakePicture` methods takes an optional `useLocalFileUri` bool parameter, by default it's false. If set to true it'll use `ICameraClient.EndPoint` for construction an absolute uri to images. This is useful if using camera through proxy or firewall. | ||
|
||
## Supported cameras | ||
|
||
This library has been tested with | ||
* [Insta360 One X](https://www.insta360.com/product/insta360-onex/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>netcoreapp3.0</TargetFramework> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.0" /> | ||
<PackageReference Include="Microsoft.Extensions.Http" Version="3.0.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\OSC.Net\OSC.Net.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
using System; | ||
using System.IO; | ||
using System.Net.Http; | ||
using static System.Console; | ||
using System.Threading.Tasks; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using OSC.Net.Model; | ||
|
||
namespace OSC.Net.Console | ||
{ | ||
public static class Program | ||
{ | ||
public static async Task Main(string[] args) | ||
{ | ||
var serviceProvider = new ServiceCollection().AddHttpClient().BuildServiceProvider(); | ||
var httpClientFactory = serviceProvider.GetService<IHttpClientFactory>(); | ||
|
||
|
||
var client = Uri.TryCreate( | ||
Environment.GetEnvironmentVariable("OSC.Net.Console.EndPoint"), | ||
UriKind.Absolute, | ||
out var endpoint) | ||
? new CameraClient(endpoint, createClient: httpClientFactory.CreateClient) | ||
: new CameraClient(createClient: httpClientFactory.CreateClient); | ||
|
||
|
||
var currentDateTime = await client.GetDateTime(); | ||
WriteLine(currentDateTime); | ||
|
||
await client.SetDateTime(DateTimeOffset.Now); | ||
|
||
currentDateTime = await client.GetDateTime(); | ||
WriteLine(currentDateTime); | ||
|
||
var pictureUri = await client.TakePicture(true); | ||
WriteLine("PictureUri: {0}", pictureUri); | ||
|
||
var imageStream = new MemoryStream(); | ||
await client.TakePicture(imageStream, true); | ||
WriteLine("Downloaded {0} bytes.", imageStream.Length); | ||
|
||
await client.TakePicture("test.jpg", true); | ||
WriteLine("test.jpg {0}.", File.Exists("test.jpg") ? "exists" : "missing"); | ||
|
||
var captureMode = await client.GetCaptureMode(); | ||
WriteLine("CaptureMode: {0}", captureMode); | ||
|
||
await client.SetCaptureMode(CaptureMode.image); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 16 | ||
VisualStudioVersion = 16.0.29318.209 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OSC.Net", "OSC.Net\OSC.Net.csproj", "{ADCC92AF-67AA-460C-B3D5-A20931C0A3E6}" | ||
EndProject | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OSC.Net.Console", "OSC.Net.Console\OSC.Net.Console.csproj", "{B9E66C20-2458-45E4-B811-40D9EAAD4F99}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{ADCC92AF-67AA-460C-B3D5-A20931C0A3E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{ADCC92AF-67AA-460C-B3D5-A20931C0A3E6}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{ADCC92AF-67AA-460C-B3D5-A20931C0A3E6}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{ADCC92AF-67AA-460C-B3D5-A20931C0A3E6}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{B9E66C20-2458-45E4-B811-40D9EAAD4F99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{B9E66C20-2458-45E4-B811-40D9EAAD4F99}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{B9E66C20-2458-45E4-B811-40D9EAAD4F99}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{B9E66C20-2458-45E4-B811-40D9EAAD4F99}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(ExtensibilityGlobals) = postSolution | ||
SolutionGuid = {98743999-18AB-4A71-AFE8-E57844A2F6EB} | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
using System; | ||
using System.IO; | ||
using System.Net; | ||
using System.Net.Http; | ||
using OSC.Net.Http; | ||
using OSC.Net.IO; | ||
|
||
namespace OSC.Net | ||
{ | ||
/// <summary> | ||
/// Standard implementation of <see cref="ICameraClient"/>. | ||
/// </summary> | ||
public class CameraClient : ICameraClient | ||
{ | ||
private static Stream DefaultCreateFile(string path) | ||
=> File.Open(path, FileMode.Create, FileAccess.Write, FileShare.None); | ||
|
||
private static HttpClient DefaultCreateClient(string name) => new HttpClient(); | ||
|
||
/// <summary> | ||
/// The Default Camera Ip Address. | ||
/// </summary> | ||
/// <value>192.168.42.1</value> | ||
public const string DefaultIp = "192.168.42.1"; | ||
|
||
/// <summary> | ||
/// The Default Camera Port. | ||
/// </summary> | ||
/// <value>80</value> | ||
public const int DefaultPort = 80; | ||
|
||
/// <summary> | ||
/// The Default Camera ip end point. | ||
/// </summary> | ||
/// <value>192.168.42.1:80</value> | ||
public static readonly IPEndPoint DefaultIpEndPoint = new IPEndPoint(IPAddress.Parse(DefaultIp), DefaultPort); | ||
|
||
private HttpClientFactoryHandler CreateClient { get; } | ||
private CreateFileHandler CreateFile { get; } | ||
|
||
/// <inheritdoc /> | ||
public Uri EndPoint { get; } | ||
|
||
/// <inheritdoc /> | ||
HttpClient ICameraClient.GetHttpClient() | ||
{ | ||
var client = CreateClient(nameof(CameraClient)); | ||
client.BaseAddress = EndPoint; | ||
return client; | ||
} | ||
|
||
/// <inheritdoc /> | ||
Stream ICameraClient.CreateFile(string path) => CreateFile(path); | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="CameraClient"/> class using <see cref="DefaultIpEndPoint"/>. | ||
/// </summary> | ||
/// <param name="createFile">Optional handler to override local file creation.</param> | ||
/// <param name="createClient">Optional handler to override http client creation.</param> | ||
public CameraClient(CreateFileHandler createFile = null, HttpClientFactoryHandler createClient = null) : this(DefaultIpEndPoint, createFile, createClient) | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="CameraClient"/> class. | ||
/// </summary> | ||
/// <param name="ipEndPoint">The camera ip address and port.</param> | ||
/// <param name="createFile">Optional handler to override local file creation.</param> | ||
/// <param name="createClient">Optional handler to override http client creation.</param> | ||
public CameraClient(IPEndPoint ipEndPoint, CreateFileHandler createFile = null, HttpClientFactoryHandler createClient = null) : this(new Uri($"http://{ipEndPoint}"), createFile, createClient) | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="CameraClient"/> class. | ||
/// </summary> | ||
/// <param name="endPoint">The camera http end point.</param> | ||
/// <param name="createFile">Optional handler to override local file creation.</param> | ||
/// <param name="createClient">Optional handler to override http client creation.</param> | ||
public CameraClient(Uri endPoint, CreateFileHandler createFile = null, HttpClientFactoryHandler createClient = null) | ||
{ | ||
EndPoint = endPoint; | ||
CreateFile = createFile ?? DefaultCreateFile; | ||
CreateClient = createClient ?? DefaultCreateClient; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
using System; | ||
using System.Threading.Tasks; | ||
using OSC.Net.Model; | ||
using OSC.Net.Model.SetOptions; | ||
|
||
namespace OSC.Net | ||
{ | ||
public static partial class Commands | ||
{ | ||
/// <summary> | ||
/// Gets camera current capture mode. | ||
/// </summary> | ||
/// <param name="client">The <see cref="ICameraClient"/> method extends.</param> | ||
/// <returns>Current <see cref="CaptureMode"/>.</returns> | ||
public static async Task<CaptureMode> GetCaptureMode(this ICameraClient client) | ||
{ | ||
var result = await client.PostAsJson<Model.GetOptions.Result<Model.GetCaptureMode.Options>>(new | ||
{ | ||
name = "camera.getOptions", | ||
parameters = new | ||
{ | ||
optionNames = new[] | ||
{ | ||
"captureMode" | ||
} | ||
} | ||
}); | ||
|
||
return Enum.TryParse(result?.results?.options?.captureMode, true, out CaptureMode mode) | ||
? mode | ||
: CaptureMode.unknown; | ||
} | ||
|
||
/// <summary> | ||
/// Sets camera capture mode. | ||
/// </summary> | ||
/// <param name="client">The <see cref="ICameraClient"/> method extends.</param> | ||
/// <param name="captureMode">Supported capture modes <see cref="CaptureMode.image"/> and <see cref="CaptureMode.video"/>.</param> | ||
/// <returns></returns> | ||
public static async Task SetCaptureMode(this ICameraClient client, CaptureMode captureMode) | ||
{ | ||
switch (captureMode) | ||
{ | ||
case CaptureMode.image: | ||
case CaptureMode.video: | ||
break; | ||
|
||
// ReSharper disable once RedundantCaseLabel | ||
case CaptureMode._other: | ||
// ReSharper disable once RedundantCaseLabel | ||
case CaptureMode.unknown: | ||
default: | ||
throw new ArgumentOutOfRangeException(nameof(captureMode), captureMode, null); | ||
} | ||
|
||
var result = await client.PostAsJson<Result>(new | ||
{ | ||
name = "camera.setOptions", | ||
parameters = new | ||
{ | ||
options = new | ||
{ | ||
captureMode = captureMode.ToString("F") | ||
} | ||
} | ||
}); | ||
|
||
if (result?.error != null) | ||
{ | ||
throw new Exception($"Failed to set options (code: {result.error.code}, message: {result.error.message})."); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.