Skip to content

Commit 883f4e3

Browse files
committed
New transport layer
1 parent 09af79c commit 883f4e3

File tree

11 files changed

+315
-190
lines changed

11 files changed

+315
-190
lines changed

.editorconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[*.cs]
2+
3+
# MA0003: Add parameter name to improve readability
4+
dotnet_diagnostic.MA0003.severity = none

external/manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"version": "1.0.0.1",
2+
"version": "1.0.0.2",
33
"display_name": "Amethyst Tracking Relay",
44
"download": "plugin_Relay.zip",
5-
"changelog": "Initial release.",
5+
"changelog": "New transport layer.",
66
"guid": "K2VRTEAM-AME2-APII-DVCE-TRACKINGRELAY"
77
}

plugin_Relay.sln

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ VisualStudioVersion = 17.5.33103.201
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "plugin_Relay", "plugin_Relay\plugin_Relay.csproj", "{3C5DB9DE-D479-4160-815D-7B664F6AC8EF}"
77
EndProject
8+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{08D1A2A1-5642-4C23-82D4-24C5E63D4522}"
9+
ProjectSection(SolutionItems) = preProject
10+
.editorconfig = .editorconfig
11+
EndProjectSection
12+
EndProject
813
Global
914
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1015
Debug|x64 = Debug|x64

plugin_Relay/AmethystLogger.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System;
2+
using System.Collections.Concurrent;
3+
using Amethyst.Plugins.Contract;
4+
using Microsoft.Extensions.Logging;
5+
6+
namespace plugin_Relay;
7+
8+
public sealed class AmethystHostLogger(string name, IAmethystHost host) : ILogger
9+
{
10+
public IDisposable BeginScope<TState>(TState state) where TState : notnull
11+
{
12+
return default!;
13+
}
14+
15+
public bool IsEnabled(LogLevel logLevel)
16+
{
17+
return true;
18+
}
19+
20+
public void Log<TState>(
21+
LogLevel logLevel,
22+
EventId eventId,
23+
TState state,
24+
Exception exception,
25+
Func<TState, Exception, string> formatter)
26+
{
27+
if (logLevel < LogLevel.Information || host is null) return;
28+
host.Log($"[{eventId.Id}: {logLevel}] {name} - {formatter(state, exception)}");
29+
}
30+
}
31+
32+
[ProviderAlias("AmethystHost")]
33+
public sealed class AmethystHostLoggerProvider(IAmethystHost host) : ILoggerProvider
34+
{
35+
private readonly ConcurrentDictionary<string, AmethystHostLogger> _loggers =
36+
new(StringComparer.OrdinalIgnoreCase);
37+
38+
public ILogger CreateLogger(string categoryName)
39+
{
40+
return _loggers.GetOrAdd(categoryName, name => new AmethystHostLogger(name, host));
41+
}
42+
43+
public void Dispose()
44+
{
45+
_loggers.Clear();
46+
}
47+
}

plugin_Relay/Models/Contract.cs

Lines changed: 57 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,144 +1,92 @@
11
using System;
2+
using System.Collections.Concurrent;
23
using System.Collections.Generic;
3-
using System.Collections.ObjectModel;
4-
using System.Linq;
5-
using System.Numerics;
4+
using System.Threading;
65
using System.Threading.Tasks;
76
using Amethyst.Plugins.Contract;
8-
using MagicOnion;
9-
using MessagePack;
10-
using MessagePack.Formatters;
11-
using MessagePack.Resolvers;
7+
using MemoryPack;
8+
using Microsoft.Extensions.Logging;
9+
using Stl.Rpc;
1210

1311
namespace plugin_Relay.Models;
1412

1513
#nullable enable
1614

17-
public interface IRelayClient
15+
public interface IRelayClient : IRpcService
1816
{
19-
void OnRequestShutdown(string reason = "", bool fatal = false); // Push to the client
20-
void OnRefreshInterface(string reason = "", bool fatal = false); // Push to the client
17+
Task OnRequestShutdown(string reason = "", bool fatal = false, CancellationToken cancellationToken = default); // Push to the client
18+
Task OnRefreshInterface(CancellationToken cancellationToken = default); // Push to the client
2119
}
2220

23-
public interface IRelayService : IStreamingHub<IRelayService, IRelayClient>
21+
public interface IRelayService : IRpcService
2422
{
25-
Task<long> PingService(); // Test service connection -> receive time
26-
Task<bool> RequestShutdown(string reason = "", bool fatal = false);
23+
Task<long> PingService(CancellationToken cancellationToken = default); // Test service connection -> receive time
24+
Task<bool> RequestShutdown(string reason = "", bool fatal = false, CancellationToken cancellationToken = default);
2725

28-
public Task<string> GetRemoteHostname(); // Check remote host's name
29-
public Task<List<TrackingDevice>> ListTrackingDevices(); // List available devices
30-
public Task<TrackingDevice?> GetTrackingDevice(string guid); // Null for not found
31-
public Task<List<TrackedJoint>?> GetTrackedJoints(string guid); // Null if invalid
26+
Task<string> GetRemoteHostname(CancellationToken cancellationToken = default); // Check remote host's name
27+
Task<List<TrackingDevice>> ListTrackingDevices(CancellationToken cancellationToken = default); // List available devices
28+
Task<TrackingDevice?> GetTrackingDevice(string guid, CancellationToken cancellationToken = default); // Null for not found
29+
Task<List<TrackedJoint>?> GetTrackedJoints(string guid, CancellationToken cancellationToken = default); // Null if invalid
3230

33-
public Task<TrackingDevice?> DeviceInitialize(string guid); // Init remote device
34-
public Task<TrackingDevice?> DeviceShutdown(string guid); // Shutdown remote device
35-
public Task<TrackingDevice?> DeviceSignalJoint(string guid, int jointId); // Joints
31+
Task<TrackingDevice?> DeviceInitialize(string guid, CancellationToken cancellationToken = default); // Init remote device
32+
Task<TrackingDevice?> DeviceShutdown(string guid, CancellationToken cancellationToken = default); // Shutdown remote device
33+
Task<TrackingDevice?> DeviceSignalJoint(string guid, int jointId, CancellationToken cancellationToken = default); // Joints
3634
}
3735

38-
public class CustomResolver : IFormatterResolver
39-
{
40-
public static readonly IFormatterResolver Instance = new CustomResolver();
41-
42-
// Resolve the formatter for the ImportedClass
43-
public IMessagePackFormatter<T> GetFormatter<T>()
44-
{
45-
if (typeof(T) == typeof(TrackedJoint)) return (IMessagePackFormatter<T>)new TrackedJointFormatter();
46-
if (typeof(T) == typeof(TrackingDevice)) return (IMessagePackFormatter<T>)new TrackingDeviceFormatter();
47-
48-
// Fallback to other resolvers
49-
return StandardResolver.Instance.GetFormatter<T>();
50-
}
51-
}
36+
#nullable disable
5237

53-
public class TrackedJointFormatter : IMessagePackFormatter<TrackedJoint>
38+
public class TrackedJointFormatter : MemoryPackFormatter<TrackedJoint>
5439
{
55-
public void Serialize(ref MessagePackWriter writer, TrackedJoint value, MessagePackSerializerOptions options)
40+
// Unity does not support scoped and TBufferWriter so change signature to `Serialize(ref MemoryPackWriter writer, ref AnimationCurve value)`
41+
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref TrackedJoint value)
5642
{
57-
writer.WriteArrayHeader(22);
58-
59-
writer.Write(value.Name);
60-
writer.Write((int)value.Role);
61-
writer.Write(value.Position.X);
62-
writer.Write(value.Position.Y);
63-
writer.Write(value.Position.Z);
64-
writer.Write(value.Orientation.X);
65-
writer.Write(value.Orientation.Y);
66-
writer.Write(value.Orientation.Z);
67-
writer.Write(value.Orientation.W);
68-
writer.Write(value.Velocity.X);
69-
writer.Write(value.Velocity.Y);
70-
writer.Write(value.Velocity.Z);
71-
writer.Write(value.Acceleration.X);
72-
writer.Write(value.Acceleration.Y);
73-
writer.Write(value.Acceleration.Z);
74-
writer.Write(value.AngularVelocity.X);
75-
writer.Write(value.AngularVelocity.Y);
76-
writer.Write(value.AngularVelocity.Z);
77-
writer.Write(value.AngularAcceleration.X);
78-
writer.Write(value.AngularAcceleration.Y);
79-
writer.Write(value.AngularAcceleration.Z);
80-
writer.Write((int)value.TrackingState);
43+
if (value == null)
44+
{
45+
writer.WriteNullObjectHeader();
46+
return;
47+
}
48+
49+
writer.WritePackable(new SerializableTrackedJoint(value));
8150
}
8251

83-
public TrackedJoint Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
52+
public override void Deserialize(ref MemoryPackReader reader, scoped ref TrackedJoint value)
8453
{
85-
reader.ReadArrayHeader();
86-
return new TrackedJoint
54+
if (reader.PeekIsNull())
8755
{
88-
Name = reader.ReadString(),
89-
Role = (TrackedJointType)reader.ReadInt32(),
90-
Position = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()),
91-
Orientation = new Quaternion(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()),
92-
Velocity = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()),
93-
Acceleration = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()),
94-
AngularVelocity = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()),
95-
AngularAcceleration = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()),
96-
TrackingState = (TrackedJointState)reader.ReadInt32()
97-
};
56+
reader.Advance(1); // Skip null block
57+
value = null;
58+
return;
59+
}
60+
61+
var wrapped = reader.ReadPackable<SerializableTrackedJoint>();
62+
value = wrapped.TrackedJoint;
9863
}
9964
}
10065

101-
public class TrackingDeviceFormatter : IMessagePackFormatter<TrackingDevice>
66+
public class TrackingDeviceFormatter : MemoryPackFormatter<TrackingDevice>
10267
{
103-
public void Serialize(ref MessagePackWriter writer, TrackingDevice value, MessagePackSerializerOptions options)
68+
// Unity does not support scoped and TBufferWriter so change signature to `Serialize(ref MemoryPackWriter writer, ref AnimationCurve value)`
69+
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref TrackingDevice value)
10470
{
105-
writer.WriteArrayHeader(12);
71+
if (value == null)
72+
{
73+
writer.WriteNullObjectHeader();
74+
return;
75+
}
10676

107-
writer.Write(value.DeviceGuid);
108-
//writer.Write(value.SessionGuid.ToString());
109-
writer.Write(value.DeviceName);
110-
writer.Write(value.RemoteDeviceStatusString);
111-
writer.Write(value.RemoteDeviceStatus);
112-
writer.Write(value.IsInitialized);
113-
writer.Write(value.IsSkeletonTracked);
114-
writer.Write(value.IsPositionFilterBlockingEnabled);
115-
writer.Write(value.IsPhysicsOverrideEnabled);
116-
writer.Write(value.IsFlipSupported);
117-
writer.Write(value.IsAppOrientationSupported);
118-
writer.Write(value.IsSettingsDaemonSupported);
119-
// ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract
120-
writer.Write(value.ErrorDocsUri?.ToString());
77+
writer.WritePackable(new SerializableTrackingDevice(value));
12178
}
12279

123-
public TrackingDevice Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
80+
public override void Deserialize(ref MemoryPackReader reader, scoped ref TrackingDevice value)
12481
{
125-
reader.ReadArrayHeader();
126-
return new TrackingDevice
82+
if (reader.PeekIsNull())
12783
{
128-
DeviceGuid = reader.ReadString(),
129-
//SessionGuid = Guid.TryParse(reader.ReadString(), out var guid) ? guid : Guid.NewGuid(),
130-
DeviceName = reader.ReadString(),
131-
RemoteDeviceStatusString = reader.ReadString(),
132-
RemoteDeviceStatus = reader.ReadInt32(),
133-
IsInitialized = reader.ReadBoolean(),
134-
IsSkeletonTracked = reader.ReadBoolean(),
135-
IsPositionFilterBlockingEnabled = reader.ReadBoolean(),
136-
IsPhysicsOverrideEnabled = reader.ReadBoolean(),
137-
IsFlipSupported = reader.ReadBoolean(),
138-
IsAppOrientationSupported = reader.ReadBoolean(),
139-
IsSettingsDaemonSupported = reader.ReadBoolean(),
140-
// ReSharper disable once AssignNullToNotNullAttribute
141-
ErrorDocsUri = Uri.TryCreate(reader.ReadString(), UriKind.RelativeOrAbsolute, out var uri) ? uri : null
142-
};
84+
reader.Advance(1); // Skip null block
85+
value = null;
86+
return;
87+
}
88+
89+
var wrapped = reader.ReadPackable<SerializableTrackingDevice>();
90+
value = wrapped.TrackingDevice;
14391
}
144-
}
92+
}

0 commit comments

Comments
 (0)