mirror of
https://github.com/SlimeVR/SlimeVR-Server.git
synced 2026-04-06 02:01:58 +02:00
Migrate core/dev.slimevr.protocol to Kotlin (#1688)
Co-authored-by: Butterscotch! <bscotchvanilla@gmail.com>
This commit is contained in:
@@ -1,49 +0,0 @@
|
||||
package dev.slimevr.protocol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class ConnectionContext {
|
||||
|
||||
private final List<DataFeed> dataFeedList = new ArrayList<>();
|
||||
|
||||
private final List<Integer> subscribedTopics = new ArrayList<>();
|
||||
|
||||
private boolean useSerial = false;
|
||||
|
||||
private boolean useProvisioning = false;
|
||||
private boolean useAutoBone = false;
|
||||
|
||||
public List<DataFeed> getDataFeedList() {
|
||||
return dataFeedList;
|
||||
}
|
||||
|
||||
public List<Integer> getSubscribedTopics() {
|
||||
return subscribedTopics;
|
||||
}
|
||||
|
||||
public boolean useSerial() {
|
||||
return useSerial;
|
||||
}
|
||||
|
||||
public void setUseSerial(boolean useSerial) {
|
||||
this.useSerial = useSerial;
|
||||
}
|
||||
|
||||
public boolean useAutoBone() {
|
||||
return useAutoBone;
|
||||
}
|
||||
|
||||
public void setUseAutoBone(boolean useAutoBone) {
|
||||
this.useAutoBone = useAutoBone;
|
||||
}
|
||||
|
||||
public boolean useProvisioning() {
|
||||
return useProvisioning;
|
||||
}
|
||||
|
||||
public void setUseProvisioning(boolean useProvisioning) {
|
||||
this.useProvisioning = useProvisioning;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dev.slimevr.protocol
|
||||
|
||||
class ConnectionContext {
|
||||
val dataFeedList: MutableList<DataFeed> = mutableListOf()
|
||||
val subscribedTopics: MutableList<Int> = mutableListOf()
|
||||
|
||||
var useSerial: Boolean = false
|
||||
var useProvisioning: Boolean = false
|
||||
var useAutoBone: Boolean = false
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package dev.slimevr.protocol;
|
||||
|
||||
import solarxr_protocol.data_feed.DataFeedConfigT;
|
||||
|
||||
|
||||
public class DataFeed {
|
||||
private DataFeedConfigT config;
|
||||
private Long timeLastSent;
|
||||
|
||||
public DataFeed(DataFeedConfigT config) {
|
||||
this.config = config;
|
||||
this.timeLastSent = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public DataFeedConfigT getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public Long getTimeLastSent() {
|
||||
return timeLastSent;
|
||||
}
|
||||
|
||||
public void setTimeLastSent(Long timeLastSent) {
|
||||
this.timeLastSent = timeLastSent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package dev.slimevr.protocol
|
||||
|
||||
import solarxr_protocol.data_feed.DataFeedConfigT
|
||||
|
||||
class DataFeed(val config: DataFeedConfigT) {
|
||||
var timeLastSent: Long = System.currentTimeMillis()
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package dev.slimevr.protocol;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
public interface GenericConnection {
|
||||
|
||||
UUID getConnectionId();
|
||||
|
||||
ConnectionContext getContext();
|
||||
|
||||
void send(ByteBuffer bytes);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package dev.slimevr.protocol
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.UUID
|
||||
|
||||
interface GenericConnection {
|
||||
val connectionId: UUID
|
||||
|
||||
val context: ConnectionContext
|
||||
|
||||
fun send(bytes: ByteBuffer)
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package dev.slimevr.protocol;
|
||||
|
||||
import dev.slimevr.VRServer;
|
||||
import dev.slimevr.protocol.datafeed.DataFeedHandler;
|
||||
import dev.slimevr.protocol.pubsub.PubSubHandler;
|
||||
import dev.slimevr.protocol.rpc.RPCHandler;
|
||||
import solarxr_protocol.MessageBundle;
|
||||
import solarxr_protocol.data_feed.DataFeedMessageHeader;
|
||||
import solarxr_protocol.pub_sub.PubSubHeader;
|
||||
import solarxr_protocol.rpc.RpcMessageHeader;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class ProtocolAPI {
|
||||
|
||||
public final VRServer server;
|
||||
public final RPCHandler rpcHandler;
|
||||
public final DataFeedHandler dataFeedHandler;
|
||||
public final PubSubHandler pubSubHandler;
|
||||
|
||||
private final List<ProtocolAPIServer> servers = new ArrayList<>();
|
||||
|
||||
public ProtocolAPI(VRServer server) {
|
||||
this.server = server;
|
||||
this.rpcHandler = new RPCHandler(this);
|
||||
this.dataFeedHandler = new DataFeedHandler(this);
|
||||
this.pubSubHandler = new PubSubHandler(this);
|
||||
}
|
||||
|
||||
public void onMessage(GenericConnection conn, ByteBuffer message) {
|
||||
MessageBundle messageBundle = MessageBundle.getRootAsMessageBundle(message);
|
||||
|
||||
try {
|
||||
for (int index = 0; index < messageBundle.dataFeedMsgsLength(); index++) {
|
||||
DataFeedMessageHeader header = messageBundle.dataFeedMsgsVector().get(index);
|
||||
this.dataFeedHandler.onMessage(conn, header);
|
||||
}
|
||||
|
||||
for (int index = 0; index < messageBundle.rpcMsgsLength(); index++) {
|
||||
RpcMessageHeader header = messageBundle.rpcMsgsVector().get(index);
|
||||
this.rpcHandler.onMessage(conn, header);
|
||||
}
|
||||
|
||||
for (int index = 0; index < messageBundle.pubSubMsgsLength(); index++) {
|
||||
PubSubHeader header = messageBundle.pubSubMsgsVector().get(index);
|
||||
this.pubSubHandler.onMessage(conn, header);
|
||||
}
|
||||
} catch (AssertionError e) {
|
||||
// Catch flatbuffer errors
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public List<ProtocolAPIServer> getAPIServers() {
|
||||
return servers;
|
||||
}
|
||||
|
||||
public void registerAPIServer(ProtocolAPIServer server) {
|
||||
this.servers.add(server);
|
||||
}
|
||||
|
||||
public void removeAPIServer(ProtocolAPIServer server) {
|
||||
this.servers.remove(server);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package dev.slimevr.protocol
|
||||
|
||||
import dev.slimevr.VRServer
|
||||
import dev.slimevr.protocol.datafeed.DataFeedHandler
|
||||
import dev.slimevr.protocol.pubsub.PubSubHandler
|
||||
import dev.slimevr.protocol.rpc.RPCHandler
|
||||
import solarxr_protocol.MessageBundle
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
class ProtocolAPI(val server: VRServer) {
|
||||
val rpcHandler: RPCHandler = RPCHandler(this)
|
||||
val dataFeedHandler: DataFeedHandler = DataFeedHandler(this)
|
||||
val pubSubHandler: PubSubHandler = PubSubHandler(this)
|
||||
|
||||
val apiServers: MutableList<ProtocolAPIServer> = ArrayList()
|
||||
|
||||
fun onMessage(conn: GenericConnection, message: ByteBuffer) {
|
||||
val messageBundle = MessageBundle.getRootAsMessageBundle(message)
|
||||
|
||||
try {
|
||||
for (index in 0..<messageBundle.dataFeedMsgsLength()) {
|
||||
val header = messageBundle.dataFeedMsgsVector().get(index)
|
||||
this.dataFeedHandler.onMessage(conn, header)
|
||||
}
|
||||
|
||||
for (index in 0..<messageBundle.rpcMsgsLength()) {
|
||||
val header = messageBundle.rpcMsgsVector().get(index)
|
||||
this.rpcHandler.onMessage(conn, header)
|
||||
}
|
||||
|
||||
for (index in 0..<messageBundle.pubSubMsgsLength()) {
|
||||
val header = messageBundle.pubSubMsgsVector().get(index)
|
||||
this.pubSubHandler.onMessage(conn, header)
|
||||
}
|
||||
} catch (e: AssertionError) {
|
||||
// Catch flatbuffer errors
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
fun registerAPIServer(server: ProtocolAPIServer) {
|
||||
this.apiServers.add(server)
|
||||
}
|
||||
|
||||
fun removeAPIServer(server: ProtocolAPIServer) {
|
||||
this.apiServers.remove(server)
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package dev.slimevr.protocol;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
public interface ProtocolAPIServer {
|
||||
|
||||
Stream<GenericConnection> getAPIConnections();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package dev.slimevr.protocol
|
||||
|
||||
import java.util.stream.Stream
|
||||
|
||||
interface ProtocolAPIServer {
|
||||
val apiConnections: Stream<GenericConnection>
|
||||
}
|
||||
@@ -1,425 +0,0 @@
|
||||
package dev.slimevr.protocol.datafeed;
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder;
|
||||
import dev.slimevr.tracking.trackers.Device;
|
||||
import dev.slimevr.tracking.trackers.Tracker;
|
||||
import dev.slimevr.tracking.trackers.udp.MagnetometerStatus;
|
||||
import dev.slimevr.tracking.trackers.udp.UDPDevice;
|
||||
import io.github.axisangles.ktmath.Quaternion;
|
||||
import io.github.axisangles.ktmath.Vector3;
|
||||
import solarxr_protocol.data_feed.Bone;
|
||||
import solarxr_protocol.data_feed.DataFeedUpdate;
|
||||
import solarxr_protocol.data_feed.device_data.DeviceData;
|
||||
import solarxr_protocol.data_feed.device_data.DeviceDataMaskT;
|
||||
import solarxr_protocol.data_feed.tracker.TrackerData;
|
||||
import solarxr_protocol.data_feed.tracker.TrackerDataMaskT;
|
||||
import solarxr_protocol.data_feed.tracker.TrackerInfo;
|
||||
import solarxr_protocol.datatypes.DeviceId;
|
||||
import solarxr_protocol.datatypes.Ipv4Address;
|
||||
import solarxr_protocol.datatypes.Temperature;
|
||||
import solarxr_protocol.datatypes.TrackerId;
|
||||
import solarxr_protocol.datatypes.hardware_info.HardwareInfo;
|
||||
import solarxr_protocol.datatypes.hardware_info.HardwareStatus;
|
||||
import solarxr_protocol.datatypes.math.Quat;
|
||||
import solarxr_protocol.datatypes.math.Vec3f;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class DataFeedBuilder {
|
||||
|
||||
public static int createHardwareInfo(FlatBufferBuilder fbb, Device device) {
|
||||
int nameOffset = device.getFirmwareVersion() != null
|
||||
? fbb.createString(device.getFirmwareVersion())
|
||||
: 0;
|
||||
|
||||
int manufacturerOffset = device.getManufacturer() != null
|
||||
? fbb.createString(device.getManufacturer())
|
||||
: 0;
|
||||
|
||||
int firmwareDateOffset = device.getFirmwareDate() != null
|
||||
? fbb.createString(device.getFirmwareDate())
|
||||
: 0;
|
||||
|
||||
int hardwareIdentifierOffset = fbb.createString(device.getHardwareIdentifier());
|
||||
|
||||
HardwareInfo.startHardwareInfo(fbb);
|
||||
HardwareInfo.addFirmwareVersion(fbb, nameOffset);
|
||||
HardwareInfo.addManufacturer(fbb, manufacturerOffset);
|
||||
HardwareInfo.addHardwareIdentifier(fbb, hardwareIdentifierOffset);
|
||||
|
||||
HardwareInfo.addFirmwareDate(fbb, firmwareDateOffset);
|
||||
|
||||
if (device instanceof UDPDevice udpDevice) {
|
||||
var address = udpDevice.getIpAddress().getAddress();
|
||||
HardwareInfo
|
||||
.addIpAddress(
|
||||
fbb,
|
||||
Ipv4Address
|
||||
.createIpv4Address(
|
||||
fbb,
|
||||
ByteBuffer.wrap(address).getInt()
|
||||
)
|
||||
);
|
||||
|
||||
HardwareInfo.addNetworkProtocolVersion(fbb, udpDevice.protocolVersion);
|
||||
}
|
||||
|
||||
// BRUH MOMENT
|
||||
// TODO need support: HardwareInfo.addHardwareRevision(fbb,
|
||||
// hardwareRevisionOffset);
|
||||
// TODO need support: HardwareInfo.addDisplayName(fbb, de);
|
||||
|
||||
HardwareInfo.addMcuId(fbb, device.getMcuType().getSolarType());
|
||||
HardwareInfo.addOfficialBoardType(fbb, device.getBoardType().getSolarType());
|
||||
|
||||
return HardwareInfo.endHardwareInfo(fbb);
|
||||
}
|
||||
|
||||
public static int createTrackerId(FlatBufferBuilder fbb, Tracker tracker) {
|
||||
TrackerId.startTrackerId(fbb);
|
||||
|
||||
TrackerId.addTrackerNum(fbb, tracker.getTrackerNum());
|
||||
if (tracker.getDevice() != null)
|
||||
TrackerId.addDeviceId(fbb, DeviceId.createDeviceId(fbb, tracker.getDevice().getId()));
|
||||
|
||||
return TrackerId.endTrackerId(fbb);
|
||||
}
|
||||
|
||||
public static int createVec3(FlatBufferBuilder fbb, Vector3 vec) {
|
||||
return Vec3f
|
||||
.createVec3f(
|
||||
fbb,
|
||||
vec.getX(),
|
||||
vec.getY(),
|
||||
vec.getZ()
|
||||
);
|
||||
}
|
||||
|
||||
public static int createQuat(FlatBufferBuilder fbb, Quaternion quaternion) {
|
||||
return Quat
|
||||
.createQuat(
|
||||
fbb,
|
||||
quaternion.getX(),
|
||||
quaternion.getY(),
|
||||
quaternion.getZ(),
|
||||
quaternion.getW()
|
||||
);
|
||||
}
|
||||
|
||||
public static int createTrackerInfos(
|
||||
FlatBufferBuilder fbb,
|
||||
boolean infoMask,
|
||||
Tracker tracker
|
||||
) {
|
||||
|
||||
if (!infoMask)
|
||||
return 0;
|
||||
|
||||
int displayNameOffset = fbb.createString(tracker.getDisplayName());
|
||||
int customNameOffset = tracker.getCustomName() != null
|
||||
? fbb.createString(tracker.getCustomName())
|
||||
: 0;
|
||||
|
||||
TrackerInfo.startTrackerInfo(fbb);
|
||||
if (tracker.getTrackerPosition() != null)
|
||||
TrackerInfo.addBodyPart(fbb, tracker.getTrackerPosition().getBodyPart());
|
||||
TrackerInfo.addEditable(fbb, tracker.getUserEditable());
|
||||
TrackerInfo.addIsComputed(fbb, tracker.isComputed());
|
||||
TrackerInfo.addDisplayName(fbb, displayNameOffset);
|
||||
TrackerInfo.addCustomName(fbb, customNameOffset);
|
||||
if (tracker.getImuType() != null) {
|
||||
TrackerInfo.addImuType(fbb, tracker.getImuType().getSolarType());
|
||||
}
|
||||
|
||||
// TODO need support: TrackerInfo.addPollRate(fbb, tracker.);
|
||||
|
||||
if (tracker.isImu()) {
|
||||
TrackerInfo.addIsImu(fbb, true);
|
||||
TrackerInfo
|
||||
.addAllowDriftCompensation(
|
||||
fbb,
|
||||
tracker.getResetsHandler().getAllowDriftCompensation()
|
||||
);
|
||||
} else {
|
||||
TrackerInfo.addIsImu(fbb, false);
|
||||
TrackerInfo.addAllowDriftCompensation(fbb, false);
|
||||
}
|
||||
|
||||
if (tracker.getAllowMounting()) {
|
||||
Quaternion quaternion = tracker.getResetsHandler().getMountingOrientation();
|
||||
Quaternion mountResetFix = tracker.getResetsHandler().getMountRotFix();
|
||||
TrackerInfo.addMountingOrientation(fbb, createQuat(fbb, quaternion));
|
||||
TrackerInfo.addMountingResetOrientation(fbb, createQuat(fbb, mountResetFix));
|
||||
}
|
||||
|
||||
TrackerInfo.addMagnetometer(fbb, tracker.getMagStatus().getSolarType());
|
||||
TrackerInfo.addIsHmd(fbb, tracker.isHmd());
|
||||
|
||||
TrackerInfo.addDataSupport(fbb, tracker.getTrackerDataType().getSolarType());
|
||||
|
||||
return TrackerInfo.endTrackerInfo(fbb);
|
||||
}
|
||||
|
||||
public static int createTrackerPosition(FlatBufferBuilder fbb, Tracker tracker) {
|
||||
return createVec3(fbb, tracker.getPosition());
|
||||
}
|
||||
|
||||
public static int createTrackerRotation(FlatBufferBuilder fbb, Tracker tracker) {
|
||||
return createQuat(fbb, tracker.getRawRotation());
|
||||
}
|
||||
|
||||
public static int createTrackerAcceleration(FlatBufferBuilder fbb, Tracker tracker) {
|
||||
return createVec3(fbb, tracker.getAcceleration());
|
||||
}
|
||||
|
||||
public static int createTrackerMagneticVector(FlatBufferBuilder fbb, Tracker tracker) {
|
||||
return createVec3(fbb, tracker.getMagVector());
|
||||
}
|
||||
|
||||
public static int createTrackerTemperature(FlatBufferBuilder fbb, Tracker tracker) {
|
||||
if (tracker.getTemperature() == null)
|
||||
return 0;
|
||||
return Temperature.createTemperature(fbb, tracker.getTemperature());
|
||||
}
|
||||
|
||||
public static int createTrackerData(
|
||||
FlatBufferBuilder fbb,
|
||||
TrackerDataMaskT mask,
|
||||
Tracker tracker
|
||||
) {
|
||||
int trackerInfosOffset = DataFeedBuilder.createTrackerInfos(fbb, mask.getInfo(), tracker);
|
||||
int trackerIdOffset = DataFeedBuilder.createTrackerId(fbb, tracker);
|
||||
|
||||
int stayAlignedOffset = 0;
|
||||
if (mask.getStayAligned()) {
|
||||
stayAlignedOffset = DataFeedBuilderKotlin.INSTANCE
|
||||
.createTrackerStayAlignedTracker(fbb, tracker.getStayAligned());
|
||||
}
|
||||
|
||||
TrackerData.startTrackerData(fbb);
|
||||
|
||||
TrackerData.addTrackerId(fbb, trackerIdOffset);
|
||||
|
||||
if (trackerInfosOffset != 0)
|
||||
TrackerData.addInfo(fbb, trackerInfosOffset);
|
||||
if (mask.getStatus())
|
||||
TrackerData.addStatus(fbb, tracker.getStatus().getId() + 1);
|
||||
if (mask.getPosition() && tracker.getHasPosition())
|
||||
TrackerData.addPosition(fbb, DataFeedBuilder.createTrackerPosition(fbb, tracker));
|
||||
if (mask.getRotation() && tracker.getHasRotation())
|
||||
TrackerData.addRotation(fbb, DataFeedBuilder.createTrackerRotation(fbb, tracker));
|
||||
if (mask.getLinearAcceleration() && tracker.getHasAcceleration())
|
||||
TrackerData
|
||||
.addLinearAcceleration(
|
||||
fbb,
|
||||
DataFeedBuilder.createTrackerAcceleration(fbb, tracker)
|
||||
);
|
||||
if (mask.getTemp()) {
|
||||
int trackerTemperatureOffset = DataFeedBuilder.createTrackerTemperature(fbb, tracker);
|
||||
if (trackerTemperatureOffset != 0)
|
||||
TrackerData.addTemp(fbb, trackerTemperatureOffset);
|
||||
}
|
||||
if (tracker.getAllowMounting() && tracker.getHasRotation()) {
|
||||
if (mask.getRotationReferenceAdjusted()) {
|
||||
TrackerData
|
||||
.addRotationReferenceAdjusted(fbb, createQuat(fbb, tracker.getRotation()));
|
||||
}
|
||||
if (mask.getRotationIdentityAdjusted()) {
|
||||
TrackerData
|
||||
.addRotationIdentityAdjusted(
|
||||
fbb,
|
||||
createQuat(fbb, tracker.getIdentityAdjustedRotation())
|
||||
);
|
||||
}
|
||||
} else if (tracker.getAllowReset() && tracker.getHasRotation()) {
|
||||
if (mask.getRotationReferenceAdjusted()) {
|
||||
TrackerData
|
||||
.addRotationReferenceAdjusted(fbb, createQuat(fbb, tracker.getRotation()));
|
||||
}
|
||||
if (mask.getRotationIdentityAdjusted()) {
|
||||
TrackerData
|
||||
.addRotationIdentityAdjusted(fbb, createQuat(fbb, tracker.getRawRotation()));
|
||||
}
|
||||
}
|
||||
if (mask.getTps()) {
|
||||
TrackerData.addTps(fbb, (int) tracker.getTps());
|
||||
}
|
||||
if (mask.getRawMagneticVector() && tracker.getMagStatus() == MagnetometerStatus.ENABLED) {
|
||||
TrackerData.addRawMagneticVector(fbb, createTrackerMagneticVector(fbb, tracker));
|
||||
}
|
||||
if (mask.getStayAligned()) {
|
||||
TrackerData.addStayAligned(fbb, stayAlignedOffset);
|
||||
}
|
||||
|
||||
return TrackerData.endTrackerData(fbb);
|
||||
}
|
||||
|
||||
public static int createTrackersData(
|
||||
FlatBufferBuilder fbb,
|
||||
DeviceDataMaskT mask,
|
||||
Device device
|
||||
) {
|
||||
if (mask.getTrackerData() == null)
|
||||
return 0;
|
||||
|
||||
List<Integer> trackersOffsets = new ArrayList<>();
|
||||
|
||||
device
|
||||
.getTrackers()
|
||||
.forEach(
|
||||
(key, value) -> trackersOffsets
|
||||
.add(DataFeedBuilder.createTrackerData(fbb, mask.getTrackerData(), value))
|
||||
);
|
||||
|
||||
DeviceData.startTrackersVector(fbb, trackersOffsets.size());
|
||||
trackersOffsets.forEach(offset -> DeviceData.addTrackers(fbb, offset));
|
||||
return fbb.endVector();
|
||||
}
|
||||
|
||||
public static int createDeviceData(
|
||||
FlatBufferBuilder fbb,
|
||||
int id,
|
||||
DeviceDataMaskT mask,
|
||||
Device device
|
||||
) {
|
||||
if (!mask.getDeviceData())
|
||||
return 0;
|
||||
|
||||
if (device.getTrackers().size() <= 0)
|
||||
return 0;
|
||||
|
||||
Tracker firstTracker = device.getTrackers().get(0);
|
||||
if (firstTracker == null) {
|
||||
// Not actually the "first" tracker, but do we care?
|
||||
firstTracker = device.getTrackers().entrySet().iterator().next().getValue();
|
||||
}
|
||||
|
||||
Tracker tracker = firstTracker;
|
||||
if (tracker == null)
|
||||
return 0;
|
||||
|
||||
HardwareStatus.startHardwareStatus(fbb);
|
||||
HardwareStatus.addErrorStatus(fbb, tracker.getStatus().getId());
|
||||
|
||||
if (tracker.getBatteryVoltage() != null) {
|
||||
HardwareStatus.addBatteryVoltage(fbb, tracker.getBatteryVoltage());
|
||||
}
|
||||
if (tracker.getBatteryLevel() != null) {
|
||||
HardwareStatus.addBatteryPctEstimate(fbb, (int) tracker.getBatteryLevel().floatValue());
|
||||
}
|
||||
if (tracker.getPing() != null) {
|
||||
HardwareStatus.addPing(fbb, tracker.getPing());
|
||||
}
|
||||
if (tracker.getSignalStrength() != null) {
|
||||
HardwareStatus.addRssi(fbb, (short) tracker.getSignalStrength().floatValue());
|
||||
}
|
||||
|
||||
if (tracker.getPacketLoss() != null) {
|
||||
HardwareStatus.addPacketLoss(fbb, tracker.getPacketLoss());
|
||||
}
|
||||
|
||||
if (tracker.getPacketsLost() != null) {
|
||||
HardwareStatus.addPacketsLost(fbb, tracker.getPacketsLost());
|
||||
}
|
||||
|
||||
if (tracker.getPacketsReceived() != null) {
|
||||
HardwareStatus.addPacketsReceived(fbb, tracker.getPacketsReceived());
|
||||
}
|
||||
|
||||
if (tracker.getBatteryRemainingRuntime() != null) {
|
||||
HardwareStatus.addBatteryRuntimeEstimate(fbb, tracker.getBatteryRemainingRuntime());
|
||||
}
|
||||
|
||||
int hardwareDataOffset = HardwareStatus.endHardwareStatus(fbb);
|
||||
int hardwareInfoOffset = DataFeedBuilder.createHardwareInfo(fbb, device);
|
||||
int trackersOffset = DataFeedBuilder.createTrackersData(fbb, mask, device);
|
||||
|
||||
int nameOffset = device.getName() != null
|
||||
? fbb.createString(device.getName())
|
||||
: 0;
|
||||
|
||||
DeviceData.startDeviceData(fbb);
|
||||
DeviceData.addCustomName(fbb, nameOffset);
|
||||
DeviceData.addId(fbb, DeviceId.createDeviceId(fbb, id));
|
||||
DeviceData.addHardwareStatus(fbb, hardwareDataOffset);
|
||||
DeviceData.addHardwareInfo(fbb, hardwareInfoOffset);
|
||||
DeviceData.addTrackers(fbb, trackersOffset);
|
||||
|
||||
return DeviceData.endDeviceData(fbb);
|
||||
}
|
||||
|
||||
public static int createSyntheticTrackersData(
|
||||
FlatBufferBuilder fbb,
|
||||
TrackerDataMaskT trackerDataMaskT,
|
||||
List<Tracker> trackers
|
||||
) {
|
||||
if (trackerDataMaskT == null)
|
||||
return 0;
|
||||
|
||||
List<Integer> trackerOffsets = new ArrayList<>();
|
||||
|
||||
trackers
|
||||
.forEach(
|
||||
(tracker) -> trackerOffsets
|
||||
.add(DataFeedBuilder.createTrackerData(fbb, trackerDataMaskT, tracker))
|
||||
);
|
||||
|
||||
DataFeedUpdate.startSyntheticTrackersVector(fbb, trackerOffsets.size());
|
||||
trackerOffsets.forEach((tracker -> DataFeedUpdate.addSyntheticTrackers(fbb, tracker)));
|
||||
return fbb.endVector();
|
||||
}
|
||||
|
||||
public static int createDevicesData(
|
||||
FlatBufferBuilder fbb,
|
||||
DeviceDataMaskT deviceDataMaskT,
|
||||
List<Device> devices
|
||||
) {
|
||||
if (deviceDataMaskT == null)
|
||||
return 0;
|
||||
|
||||
int[] devicesDataOffsets = new int[devices.size()];
|
||||
for (int i = 0; i < devices.size(); i++) {
|
||||
Device device = devices.get(i);
|
||||
devicesDataOffsets[i] = DataFeedBuilder
|
||||
.createDeviceData(fbb, device.getId(), deviceDataMaskT, device);
|
||||
}
|
||||
|
||||
return DataFeedUpdate.createDevicesVector(fbb, devicesDataOffsets);
|
||||
}
|
||||
|
||||
public static int createBonesData(
|
||||
FlatBufferBuilder fbb,
|
||||
boolean shouldSend,
|
||||
List<dev.slimevr.tracking.processor.Bone> bones
|
||||
) {
|
||||
if (!shouldSend) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var boneOffsets = new int[bones.size()];
|
||||
for (var i = 0; i < bones.size(); ++i) {
|
||||
var bi = bones.get(i);
|
||||
|
||||
var headPosG = bi.getPosition();
|
||||
var rotG = bi.getGlobalRotation();
|
||||
var length = bi.getLength();
|
||||
|
||||
Bone.startBone(fbb);
|
||||
|
||||
var rotGOffset = createQuat(fbb, rotG);
|
||||
Bone.addRotationG(fbb, rotGOffset);
|
||||
var headPosGOffset = Vec3f
|
||||
.createVec3f(fbb, headPosG.getX(), headPosG.getY(), headPosG.getZ());
|
||||
Bone.addHeadPositionG(fbb, headPosGOffset);
|
||||
Bone.addBodyPart(fbb, bi.getBoneType().bodyPart);
|
||||
Bone.addBoneLength(fbb, length);
|
||||
|
||||
boneOffsets[i] = Bone.endBone(fbb);
|
||||
}
|
||||
|
||||
return DataFeedUpdate.createBonesVector(fbb, boneOffsets);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,503 @@
|
||||
package dev.slimevr.protocol.datafeed
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder
|
||||
import dev.slimevr.guards.ServerGuards
|
||||
import dev.slimevr.tracking.processor.Bone
|
||||
import dev.slimevr.tracking.processor.skeleton.HumanSkeleton
|
||||
import dev.slimevr.tracking.processor.stayaligned.poses.RelaxedPose
|
||||
import dev.slimevr.tracking.processor.stayaligned.trackers.RestDetector
|
||||
import dev.slimevr.tracking.processor.stayaligned.trackers.StayAlignedTrackerState
|
||||
import dev.slimevr.tracking.trackers.Device
|
||||
import dev.slimevr.tracking.trackers.Tracker
|
||||
import dev.slimevr.tracking.trackers.udp.MagnetometerStatus
|
||||
import dev.slimevr.tracking.trackers.udp.UDPDevice
|
||||
import io.github.axisangles.ktmath.Quaternion
|
||||
import io.github.axisangles.ktmath.Vector3
|
||||
import solarxr_protocol.data_feed.DataFeedUpdate
|
||||
import solarxr_protocol.data_feed.device_data.DeviceData
|
||||
import solarxr_protocol.data_feed.device_data.DeviceDataMaskT
|
||||
import solarxr_protocol.data_feed.stay_aligned.StayAlignedPose
|
||||
import solarxr_protocol.data_feed.stay_aligned.StayAlignedTracker
|
||||
import solarxr_protocol.data_feed.tracker.TrackerData
|
||||
import solarxr_protocol.data_feed.tracker.TrackerDataMaskT
|
||||
import solarxr_protocol.data_feed.tracker.TrackerInfo
|
||||
import solarxr_protocol.datatypes.DeviceId
|
||||
import solarxr_protocol.datatypes.Ipv4Address
|
||||
import solarxr_protocol.datatypes.Temperature
|
||||
import solarxr_protocol.datatypes.TrackerId
|
||||
import solarxr_protocol.datatypes.hardware_info.HardwareInfo
|
||||
import solarxr_protocol.datatypes.hardware_info.HardwareStatus
|
||||
import solarxr_protocol.datatypes.math.Quat
|
||||
import solarxr_protocol.datatypes.math.Vec3f
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.function.Consumer
|
||||
|
||||
fun createHardwareInfo(fbb: FlatBufferBuilder, device: Device): Int {
|
||||
val nameOffset = if (device.firmwareVersion != null) {
|
||||
fbb.createString(device.firmwareVersion)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
val manufacturerOffset = if (device.manufacturer != null) {
|
||||
fbb.createString(device.manufacturer)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
val firmwareDateOffset = if (device.firmwareDate != null) {
|
||||
fbb.createString(device.firmwareDate)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
val hardwareIdentifierOffset = fbb.createString(device.hardwareIdentifier)
|
||||
|
||||
HardwareInfo.startHardwareInfo(fbb)
|
||||
HardwareInfo.addFirmwareVersion(fbb, nameOffset)
|
||||
HardwareInfo.addFirmwareDate(fbb, firmwareDateOffset)
|
||||
HardwareInfo.addManufacturer(fbb, manufacturerOffset)
|
||||
HardwareInfo.addHardwareIdentifier(fbb, hardwareIdentifierOffset)
|
||||
|
||||
if (device is UDPDevice) {
|
||||
val address = device.ipAddress.address
|
||||
HardwareInfo
|
||||
.addIpAddress(
|
||||
fbb,
|
||||
Ipv4Address
|
||||
.createIpv4Address(
|
||||
fbb,
|
||||
ByteBuffer.wrap(address).getInt().toLong(),
|
||||
),
|
||||
)
|
||||
|
||||
HardwareInfo.addNetworkProtocolVersion(fbb, device.protocolVersion)
|
||||
}
|
||||
|
||||
// BRUH MOMENT
|
||||
// TODO need support: HardwareInfo.addHardwareRevision(fbb,
|
||||
// hardwareRevisionOffset);
|
||||
// TODO need support: HardwareInfo.addDisplayName(fbb, de);
|
||||
HardwareInfo.addMcuId(fbb, device.mcuType.getSolarType())
|
||||
HardwareInfo.addOfficialBoardType(fbb, device.boardType.getSolarType())
|
||||
return HardwareInfo.endHardwareInfo(fbb)
|
||||
}
|
||||
|
||||
fun createTrackerId(fbb: FlatBufferBuilder, tracker: Tracker): Int {
|
||||
TrackerId.startTrackerId(fbb)
|
||||
|
||||
TrackerId.addTrackerNum(fbb, tracker.trackerNum)
|
||||
if (tracker.device != null) {
|
||||
TrackerId.addDeviceId(
|
||||
fbb,
|
||||
DeviceId.createDeviceId(fbb, tracker.device.id),
|
||||
)
|
||||
}
|
||||
|
||||
return TrackerId.endTrackerId(fbb)
|
||||
}
|
||||
|
||||
fun createVec3(fbb: FlatBufferBuilder, vec: Vector3): Int = Vec3f
|
||||
.createVec3f(
|
||||
fbb,
|
||||
vec.x,
|
||||
vec.y,
|
||||
vec.z,
|
||||
)
|
||||
|
||||
fun createQuat(fbb: FlatBufferBuilder, quaternion: Quaternion): Int = Quat
|
||||
.createQuat(
|
||||
fbb,
|
||||
quaternion.x,
|
||||
quaternion.y,
|
||||
quaternion.z,
|
||||
quaternion.w,
|
||||
)
|
||||
|
||||
fun createTrackerInfos(
|
||||
fbb: FlatBufferBuilder,
|
||||
infoMask: Boolean,
|
||||
tracker: Tracker,
|
||||
): Int {
|
||||
if (!infoMask) return 0
|
||||
|
||||
val displayNameOffset = fbb.createString(tracker.displayName)
|
||||
val customNameOffset = if (tracker.customName != null) {
|
||||
fbb.createString(tracker.customName)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
TrackerInfo.startTrackerInfo(fbb)
|
||||
if (tracker.trackerPosition != null) {
|
||||
TrackerInfo.addBodyPart(
|
||||
fbb,
|
||||
tracker.trackerPosition!!.bodyPart,
|
||||
)
|
||||
}
|
||||
TrackerInfo.addEditable(fbb, tracker.userEditable)
|
||||
TrackerInfo.addIsComputed(fbb, tracker.isComputed)
|
||||
TrackerInfo.addDisplayName(fbb, displayNameOffset)
|
||||
TrackerInfo.addCustomName(fbb, customNameOffset)
|
||||
if (tracker.imuType != null) {
|
||||
TrackerInfo.addImuType(fbb, tracker.imuType.getSolarType())
|
||||
}
|
||||
|
||||
// TODO need support: TrackerInfo.addPollRate(fbb, tracker.);
|
||||
if (tracker.isImu()) {
|
||||
TrackerInfo.addIsImu(fbb, true)
|
||||
TrackerInfo
|
||||
.addAllowDriftCompensation(
|
||||
fbb,
|
||||
tracker.resetsHandler.allowDriftCompensation,
|
||||
)
|
||||
} else {
|
||||
TrackerInfo.addIsImu(fbb, false)
|
||||
TrackerInfo.addAllowDriftCompensation(fbb, false)
|
||||
}
|
||||
|
||||
if (tracker.allowMounting) {
|
||||
val quaternion = tracker.resetsHandler.mountingOrientation
|
||||
val mountResetFix = tracker.resetsHandler.mountRotFix
|
||||
TrackerInfo.addMountingOrientation(fbb, createQuat(fbb, quaternion))
|
||||
TrackerInfo.addMountingResetOrientation(fbb, createQuat(fbb, mountResetFix))
|
||||
}
|
||||
|
||||
TrackerInfo.addMagnetometer(fbb, tracker.magStatus.getSolarType())
|
||||
TrackerInfo.addIsHmd(fbb, tracker.isHmd)
|
||||
|
||||
TrackerInfo.addDataSupport(fbb, tracker.trackerDataType.getSolarType())
|
||||
|
||||
return TrackerInfo.endTrackerInfo(fbb)
|
||||
}
|
||||
|
||||
fun createTrackerPosition(fbb: FlatBufferBuilder, tracker: Tracker): Int = createVec3(fbb, tracker.position)
|
||||
|
||||
fun createTrackerRotation(fbb: FlatBufferBuilder, tracker: Tracker): Int = createQuat(fbb, tracker.getRawRotation())
|
||||
|
||||
fun createTrackerAcceleration(fbb: FlatBufferBuilder, tracker: Tracker): Int = createVec3(fbb, tracker.getAcceleration())
|
||||
|
||||
fun createTrackerMagneticVector(fbb: FlatBufferBuilder, tracker: Tracker): Int = createVec3(fbb, tracker.getMagVector())
|
||||
|
||||
fun createTrackerTemperature(fbb: FlatBufferBuilder, tracker: Tracker): Int {
|
||||
if (tracker.temperature == null) return 0
|
||||
return Temperature.createTemperature(fbb, tracker.temperature!!)
|
||||
}
|
||||
|
||||
fun createTrackerData(
|
||||
fbb: FlatBufferBuilder,
|
||||
mask: TrackerDataMaskT,
|
||||
tracker: Tracker,
|
||||
): Int {
|
||||
val trackerInfosOffset = createTrackerInfos(fbb, mask.info, tracker)
|
||||
val trackerIdOffset = createTrackerId(fbb, tracker)
|
||||
|
||||
var stayAlignedOffset = 0
|
||||
if (mask.stayAligned) {
|
||||
stayAlignedOffset =
|
||||
createTrackerStayAlignedTracker(fbb, tracker.stayAligned)
|
||||
}
|
||||
|
||||
TrackerData.startTrackerData(fbb)
|
||||
|
||||
TrackerData.addTrackerId(fbb, trackerIdOffset)
|
||||
|
||||
if (trackerInfosOffset != 0) TrackerData.addInfo(fbb, trackerInfosOffset)
|
||||
if (mask.status) TrackerData.addStatus(fbb, tracker.status.id + 1)
|
||||
if (mask.position && tracker.hasPosition) {
|
||||
TrackerData.addPosition(
|
||||
fbb,
|
||||
createTrackerPosition(fbb, tracker),
|
||||
)
|
||||
}
|
||||
if (mask.rotation && tracker.hasRotation) {
|
||||
TrackerData.addRotation(
|
||||
fbb,
|
||||
createTrackerRotation(fbb, tracker),
|
||||
)
|
||||
}
|
||||
if (mask.linearAcceleration && tracker.hasAcceleration) {
|
||||
TrackerData
|
||||
.addLinearAcceleration(
|
||||
fbb,
|
||||
createTrackerAcceleration(fbb, tracker),
|
||||
)
|
||||
}
|
||||
if (mask.temp) {
|
||||
val trackerTemperatureOffset = createTrackerTemperature(fbb, tracker)
|
||||
if (trackerTemperatureOffset != 0) {
|
||||
TrackerData.addTemp(
|
||||
fbb,
|
||||
trackerTemperatureOffset,
|
||||
)
|
||||
}
|
||||
}
|
||||
if (tracker.allowMounting && tracker.hasRotation) {
|
||||
if (mask.rotationReferenceAdjusted) {
|
||||
TrackerData
|
||||
.addRotationReferenceAdjusted(
|
||||
fbb,
|
||||
createQuat(fbb, tracker.getRotation()),
|
||||
)
|
||||
}
|
||||
if (mask.rotationIdentityAdjusted) {
|
||||
TrackerData
|
||||
.addRotationIdentityAdjusted(
|
||||
fbb,
|
||||
createQuat(fbb, tracker.getIdentityAdjustedRotation()),
|
||||
)
|
||||
}
|
||||
} else if (tracker.allowReset && tracker.hasRotation) {
|
||||
if (mask.rotationReferenceAdjusted) {
|
||||
TrackerData
|
||||
.addRotationReferenceAdjusted(
|
||||
fbb,
|
||||
createQuat(fbb, tracker.getRotation()),
|
||||
)
|
||||
}
|
||||
if (mask.rotationIdentityAdjusted) {
|
||||
TrackerData
|
||||
.addRotationIdentityAdjusted(
|
||||
fbb,
|
||||
createQuat(fbb, tracker.getRawRotation()),
|
||||
)
|
||||
}
|
||||
}
|
||||
if (mask.tps) {
|
||||
TrackerData.addTps(fbb, tracker.tps.toInt())
|
||||
}
|
||||
if (mask.rawMagneticVector && tracker.magStatus == MagnetometerStatus.ENABLED) {
|
||||
TrackerData.addRawMagneticVector(
|
||||
fbb,
|
||||
createTrackerMagneticVector(fbb, tracker),
|
||||
)
|
||||
}
|
||||
if (mask.stayAligned) {
|
||||
TrackerData.addStayAligned(fbb, stayAlignedOffset)
|
||||
}
|
||||
|
||||
return TrackerData.endTrackerData(fbb)
|
||||
}
|
||||
|
||||
fun createTrackersData(
|
||||
fbb: FlatBufferBuilder,
|
||||
mask: DeviceDataMaskT,
|
||||
device: Device,
|
||||
): Int {
|
||||
if (mask.trackerData == null) return 0
|
||||
|
||||
val trackersOffsets: MutableList<Int> = ArrayList()
|
||||
|
||||
device
|
||||
.trackers
|
||||
.forEach { (_: Int, value: Tracker) ->
|
||||
trackersOffsets
|
||||
.add(createTrackerData(fbb, mask.trackerData, value))
|
||||
}
|
||||
|
||||
DeviceData.startTrackersVector(fbb, trackersOffsets.size)
|
||||
trackersOffsets.forEach(
|
||||
Consumer { offset: Int ->
|
||||
DeviceData.addTrackers(
|
||||
fbb,
|
||||
offset,
|
||||
)
|
||||
},
|
||||
)
|
||||
return fbb.endVector()
|
||||
}
|
||||
|
||||
fun createDeviceData(
|
||||
fbb: FlatBufferBuilder,
|
||||
id: Int,
|
||||
mask: DeviceDataMaskT,
|
||||
device: Device,
|
||||
): Int {
|
||||
if (!mask.deviceData) return 0
|
||||
|
||||
if (device.trackers.isEmpty()) return 0
|
||||
|
||||
var firstTracker = device.trackers[0]
|
||||
if (firstTracker == null) {
|
||||
// Not actually the "first" tracker, but do we care?
|
||||
firstTracker = device.trackers.entries.iterator().next().value
|
||||
}
|
||||
|
||||
val tracker: Tracker = firstTracker
|
||||
|
||||
HardwareStatus.startHardwareStatus(fbb)
|
||||
HardwareStatus.addErrorStatus(fbb, tracker.status.id)
|
||||
|
||||
if (tracker.batteryVoltage != null) {
|
||||
HardwareStatus.addBatteryVoltage(fbb, tracker.batteryVoltage!!)
|
||||
}
|
||||
if (tracker.batteryLevel != null) {
|
||||
HardwareStatus.addBatteryPctEstimate(fbb, tracker.batteryLevel!!.toInt())
|
||||
}
|
||||
if (tracker.ping != null) {
|
||||
HardwareStatus.addPing(fbb, tracker.ping!!)
|
||||
}
|
||||
if (tracker.signalStrength != null) {
|
||||
HardwareStatus.addRssi(fbb, tracker.signalStrength!!.toShort())
|
||||
}
|
||||
if (tracker.packetLoss != null) {
|
||||
HardwareStatus.addPacketLoss(fbb, tracker.packetLoss!!)
|
||||
}
|
||||
if (tracker.packetsLost != null) {
|
||||
HardwareStatus.addPacketsLost(fbb, tracker.packetsLost!!)
|
||||
}
|
||||
if (tracker.packetsReceived != null) {
|
||||
HardwareStatus.addPacketsReceived(fbb, tracker.packetsReceived!!)
|
||||
}
|
||||
|
||||
val hardwareDataOffset = HardwareStatus.endHardwareStatus(fbb)
|
||||
val hardwareInfoOffset = createHardwareInfo(fbb, device)
|
||||
val trackersOffset = createTrackersData(fbb, mask, device)
|
||||
|
||||
val nameOffset = if (device.name != null) {
|
||||
fbb.createString(device.name)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
DeviceData.startDeviceData(fbb)
|
||||
DeviceData.addCustomName(fbb, nameOffset)
|
||||
DeviceData.addId(fbb, DeviceId.createDeviceId(fbb, id))
|
||||
DeviceData.addHardwareStatus(fbb, hardwareDataOffset)
|
||||
DeviceData.addHardwareInfo(fbb, hardwareInfoOffset)
|
||||
DeviceData.addTrackers(fbb, trackersOffset)
|
||||
|
||||
return DeviceData.endDeviceData(fbb)
|
||||
}
|
||||
|
||||
fun createSyntheticTrackersData(
|
||||
fbb: FlatBufferBuilder,
|
||||
trackerDataMaskT: TrackerDataMaskT?,
|
||||
trackers: MutableList<Tracker>,
|
||||
): Int {
|
||||
if (trackerDataMaskT == null) return 0
|
||||
|
||||
val trackerOffsets: MutableList<Int> = ArrayList()
|
||||
|
||||
trackers
|
||||
.forEach(
|
||||
Consumer { tracker: Tracker ->
|
||||
trackerOffsets
|
||||
.add(createTrackerData(fbb, trackerDataMaskT, tracker))
|
||||
},
|
||||
)
|
||||
|
||||
DataFeedUpdate.startSyntheticTrackersVector(fbb, trackerOffsets.size)
|
||||
trackerOffsets.forEach(
|
||||
(
|
||||
Consumer { tracker: Int ->
|
||||
DataFeedUpdate.addSyntheticTrackers(
|
||||
fbb,
|
||||
tracker,
|
||||
)
|
||||
}
|
||||
),
|
||||
)
|
||||
return fbb.endVector()
|
||||
}
|
||||
|
||||
fun createDevicesData(
|
||||
fbb: FlatBufferBuilder,
|
||||
deviceDataMaskT: DeviceDataMaskT?,
|
||||
devices: MutableList<Device>,
|
||||
): Int {
|
||||
if (deviceDataMaskT == null) return 0
|
||||
|
||||
val devicesDataOffsets = IntArray(devices.size)
|
||||
for (i in devices.indices) {
|
||||
val device = devices[i]
|
||||
devicesDataOffsets[i] =
|
||||
createDeviceData(fbb, device.id, deviceDataMaskT, device)
|
||||
}
|
||||
|
||||
return DataFeedUpdate.createDevicesVector(fbb, devicesDataOffsets)
|
||||
}
|
||||
|
||||
fun createBonesData(
|
||||
fbb: FlatBufferBuilder,
|
||||
shouldSend: Boolean,
|
||||
bones: MutableList<Bone>,
|
||||
): Int {
|
||||
if (!shouldSend) {
|
||||
return 0
|
||||
}
|
||||
|
||||
val boneOffsets = IntArray(bones.size)
|
||||
for (i in bones.indices) {
|
||||
val bi = bones[i]
|
||||
|
||||
val headPosG =
|
||||
bi.getPosition()
|
||||
val rotG =
|
||||
bi.getGlobalRotation()
|
||||
val length = bi.length
|
||||
|
||||
solarxr_protocol.data_feed.Bone.startBone(fbb)
|
||||
|
||||
val rotGOffset = createQuat(fbb, rotG)
|
||||
solarxr_protocol.data_feed.Bone.addRotationG(fbb, rotGOffset)
|
||||
val headPosGOffset = Vec3f
|
||||
.createVec3f(fbb, headPosG.x, headPosG.y, headPosG.z)
|
||||
solarxr_protocol.data_feed.Bone.addHeadPositionG(fbb, headPosGOffset)
|
||||
solarxr_protocol.data_feed.Bone.addBodyPart(fbb, bi.boneType.bodyPart)
|
||||
solarxr_protocol.data_feed.Bone.addBoneLength(fbb, length)
|
||||
|
||||
boneOffsets[i] = solarxr_protocol.data_feed.Bone.endBone(fbb)
|
||||
}
|
||||
|
||||
return DataFeedUpdate.createBonesVector(fbb, boneOffsets)
|
||||
}
|
||||
|
||||
fun createStayAlignedPose(
|
||||
fbb: FlatBufferBuilder,
|
||||
humanSkeleton: HumanSkeleton,
|
||||
): Int {
|
||||
val relaxedPose = RelaxedPose.fromTrackers(humanSkeleton)
|
||||
|
||||
StayAlignedPose.startStayAlignedPose(fbb)
|
||||
|
||||
StayAlignedPose.addUpperLegAngleInDeg(fbb, relaxedPose.upperLeg.toDeg())
|
||||
StayAlignedPose.addLowerLegAngleInDeg(fbb, relaxedPose.lowerLeg.toDeg())
|
||||
StayAlignedPose.addFootAngleInDeg(fbb, relaxedPose.foot.toDeg())
|
||||
|
||||
return StayAlignedPose.endStayAlignedPose(fbb)
|
||||
}
|
||||
|
||||
fun createTrackerStayAlignedTracker(
|
||||
fbb: FlatBufferBuilder,
|
||||
state: StayAlignedTrackerState,
|
||||
): Int {
|
||||
StayAlignedTracker.startStayAlignedTracker(fbb)
|
||||
|
||||
StayAlignedTracker.addYawCorrectionInDeg(fbb, state.yawCorrection.toDeg())
|
||||
StayAlignedTracker.addLockedErrorInDeg(
|
||||
fbb,
|
||||
state.yawErrors.lockedError.toL2Norm().toDeg(),
|
||||
)
|
||||
StayAlignedTracker.addCenterErrorInDeg(
|
||||
fbb,
|
||||
state.yawErrors.centerError.toL2Norm().toDeg(),
|
||||
)
|
||||
StayAlignedTracker.addNeighborErrorInDeg(
|
||||
fbb,
|
||||
state.yawErrors.neighborError.toL2Norm().toDeg(),
|
||||
)
|
||||
StayAlignedTracker.addLocked(
|
||||
fbb,
|
||||
state.restDetector.state == RestDetector.State.AT_REST,
|
||||
)
|
||||
|
||||
return StayAlignedTracker.endStayAlignedTracker(fbb)
|
||||
}
|
||||
|
||||
fun createServerGuard(fbb: FlatBufferBuilder, serverGuards: ServerGuards): Int = solarxr_protocol.data_feed.server.ServerGuards.createServerGuards(
|
||||
fbb,
|
||||
serverGuards.canDoMounting,
|
||||
serverGuards.canDoYawReset,
|
||||
serverGuards.canDoUserHeightCalibration,
|
||||
)
|
||||
@@ -1,50 +0,0 @@
|
||||
package dev.slimevr.protocol.datafeed
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder
|
||||
import dev.slimevr.guards.ServerGuards
|
||||
import dev.slimevr.tracking.processor.skeleton.HumanSkeleton
|
||||
import dev.slimevr.tracking.processor.stayaligned.poses.RelaxedPose
|
||||
import dev.slimevr.tracking.processor.stayaligned.trackers.RestDetector
|
||||
import dev.slimevr.tracking.processor.stayaligned.trackers.StayAlignedTrackerState
|
||||
import solarxr_protocol.data_feed.stay_aligned.StayAlignedPose
|
||||
import solarxr_protocol.data_feed.stay_aligned.StayAlignedTracker
|
||||
|
||||
object DataFeedBuilderKotlin {
|
||||
|
||||
fun createStayAlignedPose(
|
||||
fbb: FlatBufferBuilder,
|
||||
humanSkeleton: HumanSkeleton,
|
||||
): Int {
|
||||
val relaxedPose = RelaxedPose.fromTrackers(humanSkeleton)
|
||||
|
||||
StayAlignedPose.startStayAlignedPose(fbb)
|
||||
|
||||
StayAlignedPose.addUpperLegAngleInDeg(fbb, relaxedPose.upperLeg.toDeg())
|
||||
StayAlignedPose.addLowerLegAngleInDeg(fbb, relaxedPose.lowerLeg.toDeg())
|
||||
StayAlignedPose.addFootAngleInDeg(fbb, relaxedPose.foot.toDeg())
|
||||
|
||||
return StayAlignedPose.endStayAlignedPose(fbb)
|
||||
}
|
||||
|
||||
fun createTrackerStayAlignedTracker(
|
||||
fbb: FlatBufferBuilder,
|
||||
state: StayAlignedTrackerState,
|
||||
): Int {
|
||||
StayAlignedTracker.startStayAlignedTracker(fbb)
|
||||
|
||||
StayAlignedTracker.addYawCorrectionInDeg(fbb, state.yawCorrection.toDeg())
|
||||
StayAlignedTracker.addLockedErrorInDeg(fbb, state.yawErrors.lockedError.toL2Norm().toDeg())
|
||||
StayAlignedTracker.addCenterErrorInDeg(fbb, state.yawErrors.centerError.toL2Norm().toDeg())
|
||||
StayAlignedTracker.addNeighborErrorInDeg(fbb, state.yawErrors.neighborError.toL2Norm().toDeg())
|
||||
StayAlignedTracker.addLocked(fbb, state.restDetector.state == RestDetector.State.AT_REST)
|
||||
|
||||
return StayAlignedTracker.endStayAlignedTracker(fbb)
|
||||
}
|
||||
|
||||
fun createServerGuard(fbb: FlatBufferBuilder, serverGuards: ServerGuards): Int = solarxr_protocol.data_feed.server.ServerGuards.createServerGuards(
|
||||
fbb,
|
||||
serverGuards.canDoMounting,
|
||||
serverGuards.canDoYawReset,
|
||||
serverGuards.canDoUserHeightCalibration,
|
||||
)
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
package dev.slimevr.protocol.datafeed;
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder;
|
||||
import dev.slimevr.protocol.DataFeed;
|
||||
import dev.slimevr.protocol.GenericConnection;
|
||||
import dev.slimevr.protocol.ProtocolAPI;
|
||||
import dev.slimevr.protocol.ProtocolHandler;
|
||||
import dev.slimevr.tracking.trackers.Tracker;
|
||||
import io.eiren.util.logging.LogManager;
|
||||
import solarxr_protocol.MessageBundle;
|
||||
import solarxr_protocol.data_feed.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
public class DataFeedHandler extends ProtocolHandler<DataFeedMessageHeader> {
|
||||
private final ProtocolAPI api;
|
||||
|
||||
public DataFeedHandler(ProtocolAPI api) {
|
||||
this.api = api;
|
||||
|
||||
registerPacketListener(DataFeedMessage.StartDataFeed, this::onStartDataFeed);
|
||||
registerPacketListener(DataFeedMessage.PollDataFeed, this::onPollDataFeedRequest);
|
||||
|
||||
this.api.server.addOnTick(this::sendDataFeedUpdate);
|
||||
}
|
||||
|
||||
private void onStartDataFeed(GenericConnection conn, DataFeedMessageHeader header) {
|
||||
StartDataFeed req = (StartDataFeed) header.message(new StartDataFeed());
|
||||
if (req == null)
|
||||
return;
|
||||
int dataFeeds = req.dataFeedsLength();
|
||||
|
||||
List<DataFeed> feedList = conn.getContext().getDataFeedList();
|
||||
synchronized (feedList) {
|
||||
feedList.clear();
|
||||
for (int i = 0; i < dataFeeds; i++) {
|
||||
// Using the object api here because we
|
||||
// need to copy from the buffer, anyway let's
|
||||
// do it from here and send the reference to an arraylist
|
||||
DataFeedConfigT config = req.dataFeeds(i).unpack();
|
||||
feedList.add(new DataFeed(config));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onPollDataFeedRequest(
|
||||
GenericConnection conn,
|
||||
DataFeedMessageHeader messageHeader
|
||||
) {
|
||||
|
||||
PollDataFeed req = (PollDataFeed) messageHeader.message(new PollDataFeed());
|
||||
if (req == null)
|
||||
return;
|
||||
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(300);
|
||||
|
||||
int messageOffset = this.buildDatafeed(fbb, req.config().unpack(), 0);
|
||||
|
||||
DataFeedMessageHeader.startDataFeedMessageHeader(fbb);
|
||||
DataFeedMessageHeader.addMessage(fbb, messageOffset);
|
||||
DataFeedMessageHeader.addMessageType(fbb, DataFeedMessage.DataFeedUpdate);
|
||||
int headerOffset = DataFeedMessageHeader.endDataFeedMessageHeader(fbb);
|
||||
|
||||
MessageBundle.startDataFeedMsgsVector(fbb, 1);
|
||||
MessageBundle.addDataFeedMsgs(fbb, headerOffset);
|
||||
int datafeedMessagesOffset = fbb.endVector();
|
||||
|
||||
int packet = createMessage(fbb, datafeedMessagesOffset);
|
||||
fbb.finish(packet);
|
||||
conn.send(fbb.dataBuffer());
|
||||
}
|
||||
|
||||
public int buildDatafeed(FlatBufferBuilder fbb, DataFeedConfigT config, int index) {
|
||||
int devicesOffset = DataFeedBuilder
|
||||
.createDevicesData(
|
||||
fbb,
|
||||
config.getDataMask(),
|
||||
this.api.server.deviceManager
|
||||
.getDevices()
|
||||
);
|
||||
// Synthetic tracker is computed tracker apparently
|
||||
int trackersOffset = DataFeedBuilder
|
||||
.createSyntheticTrackersData(
|
||||
fbb,
|
||||
config.getSyntheticTrackersMask(),
|
||||
this.api.server
|
||||
.getAllTrackers()
|
||||
.stream()
|
||||
.filter(Tracker::isComputed)
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
|
||||
var h = this.api.server.humanPoseManager;
|
||||
int bonesOffset = DataFeedBuilder
|
||||
.createBonesData(
|
||||
fbb,
|
||||
config.getBoneMask(),
|
||||
h.getAllBones()
|
||||
);
|
||||
|
||||
int stayAlignedPoseOffset = 0;
|
||||
if (config.getStayAlignedPoseMask()) {
|
||||
stayAlignedPoseOffset = DataFeedBuilderKotlin.INSTANCE
|
||||
.createStayAlignedPose(fbb, this.api.server.humanPoseManager.skeleton);
|
||||
}
|
||||
|
||||
int serverGuardsOffset = 0;
|
||||
if (config.getServerGuardsMask()) {
|
||||
serverGuardsOffset = DataFeedBuilderKotlin.INSTANCE
|
||||
.createServerGuard(fbb, this.api.server.getServerGuards());
|
||||
}
|
||||
|
||||
return DataFeedUpdate
|
||||
.createDataFeedUpdate(
|
||||
fbb,
|
||||
devicesOffset,
|
||||
trackersOffset,
|
||||
bonesOffset,
|
||||
stayAlignedPoseOffset,
|
||||
index,
|
||||
serverGuardsOffset
|
||||
);
|
||||
}
|
||||
|
||||
public void sendDataFeedUpdate() {
|
||||
long currTime = System.currentTimeMillis();
|
||||
|
||||
this.api.getAPIServers().forEach((server) -> server.getAPIConnections().forEach((conn) -> {
|
||||
FlatBufferBuilder fbb = null;
|
||||
|
||||
List<DataFeed> feedList = conn.getContext().getDataFeedList();
|
||||
synchronized (feedList) {
|
||||
int configsCount = feedList.size();
|
||||
|
||||
int[] data = new int[configsCount];
|
||||
|
||||
for (int index = 0; index < configsCount; index++) {
|
||||
DataFeed feed = feedList.get(index);
|
||||
Long lastTimeSent = feed.getTimeLastSent();
|
||||
DataFeedConfigT configT = feed.getConfig();
|
||||
if (currTime - lastTimeSent > configT.getMinimumTimeSinceLast()) {
|
||||
if (fbb == null) {
|
||||
// That way we create a buffer only when needed
|
||||
fbb = new FlatBufferBuilder(300);
|
||||
}
|
||||
|
||||
int messageOffset = this.buildDatafeed(fbb, configT, index);
|
||||
|
||||
DataFeedMessageHeader.startDataFeedMessageHeader(fbb);
|
||||
DataFeedMessageHeader.addMessage(fbb, messageOffset);
|
||||
DataFeedMessageHeader.addMessageType(fbb, DataFeedMessage.DataFeedUpdate);
|
||||
data[index] = DataFeedMessageHeader.endDataFeedMessageHeader(fbb);
|
||||
|
||||
feed.setTimeLastSent(currTime);
|
||||
int messages = MessageBundle.createDataFeedMsgsVector(fbb, data);
|
||||
int packet = createMessage(fbb, messages);
|
||||
fbb.finish(packet);
|
||||
conn.send(fbb.dataBuffer());
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(GenericConnection conn, DataFeedMessageHeader message) {
|
||||
BiConsumer<GenericConnection, DataFeedMessageHeader> consumer = this.handlers[message
|
||||
.messageType()];
|
||||
if (consumer != null)
|
||||
consumer.accept(conn, message);
|
||||
else
|
||||
LogManager
|
||||
.info(
|
||||
"[ProtocolAPI] Unhandled Datafeed packet received id: " + message.messageType()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int messagesCount() {
|
||||
return DataFeedMessage.names.length;
|
||||
}
|
||||
|
||||
public int createMessage(FlatBufferBuilder fbb, int datafeedMessagesOffset) {
|
||||
MessageBundle.startMessageBundle(fbb);
|
||||
if (datafeedMessagesOffset > -1)
|
||||
MessageBundle.addDataFeedMsgs(fbb, datafeedMessagesOffset);
|
||||
return MessageBundle.endMessageBundle(fbb);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
package dev.slimevr.protocol.datafeed
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder
|
||||
import dev.slimevr.protocol.DataFeed
|
||||
import dev.slimevr.protocol.GenericConnection
|
||||
import dev.slimevr.protocol.ProtocolAPI
|
||||
import dev.slimevr.protocol.ProtocolAPIServer
|
||||
import dev.slimevr.protocol.ProtocolHandler
|
||||
import dev.slimevr.tracking.trackers.Tracker
|
||||
import io.eiren.util.logging.LogManager
|
||||
import solarxr_protocol.MessageBundle
|
||||
import solarxr_protocol.data_feed.DataFeedConfigT
|
||||
import solarxr_protocol.data_feed.DataFeedMessage
|
||||
import solarxr_protocol.data_feed.DataFeedMessageHeader
|
||||
import solarxr_protocol.data_feed.DataFeedUpdate
|
||||
import solarxr_protocol.data_feed.PollDataFeed
|
||||
import solarxr_protocol.data_feed.StartDataFeed
|
||||
import java.util.function.Consumer
|
||||
import java.util.stream.Collectors
|
||||
|
||||
class DataFeedHandler(private val api: ProtocolAPI) : ProtocolHandler<DataFeedMessageHeader>() {
|
||||
init {
|
||||
registerPacketListener(DataFeedMessage.StartDataFeed, ::onStartDataFeed)
|
||||
registerPacketListener(DataFeedMessage.PollDataFeed, ::onPollDataFeedRequest)
|
||||
this.api.server.addOnTick { this.sendDataFeedUpdate() }
|
||||
}
|
||||
|
||||
private fun onStartDataFeed(conn: GenericConnection, header: DataFeedMessageHeader) {
|
||||
val req = header.message(StartDataFeed()) as StartDataFeed? ?: return
|
||||
val dataFeeds = req.dataFeedsLength()
|
||||
|
||||
val feedList = conn.context.dataFeedList
|
||||
synchronized(feedList) {
|
||||
feedList.clear()
|
||||
for (i in 0..<dataFeeds) {
|
||||
// Using the object api here because we
|
||||
// need to copy from the buffer, anyway let's
|
||||
// do it from here and send the reference to an arraylist
|
||||
val config = req.dataFeeds(i).unpack()
|
||||
feedList.add(DataFeed(config))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onPollDataFeedRequest(
|
||||
conn: GenericConnection,
|
||||
messageHeader: DataFeedMessageHeader,
|
||||
) {
|
||||
val req = messageHeader.message(PollDataFeed()) as PollDataFeed? ?: return
|
||||
|
||||
val fbb = FlatBufferBuilder(300)
|
||||
|
||||
val messageOffset = this.buildDatafeed(fbb, req.config().unpack(), 0)
|
||||
|
||||
DataFeedMessageHeader.startDataFeedMessageHeader(fbb)
|
||||
DataFeedMessageHeader.addMessage(fbb, messageOffset)
|
||||
DataFeedMessageHeader.addMessageType(fbb, DataFeedMessage.DataFeedUpdate)
|
||||
val headerOffset = DataFeedMessageHeader.endDataFeedMessageHeader(fbb)
|
||||
|
||||
MessageBundle.startDataFeedMsgsVector(fbb, 1)
|
||||
MessageBundle.addDataFeedMsgs(fbb, headerOffset)
|
||||
val datafeedMessagesOffset = fbb.endVector()
|
||||
|
||||
val packet = createMessage(fbb, datafeedMessagesOffset)
|
||||
fbb.finish(packet)
|
||||
conn.send(fbb.dataBuffer())
|
||||
}
|
||||
|
||||
fun buildDatafeed(fbb: FlatBufferBuilder, config: DataFeedConfigT, index: Int): Int {
|
||||
val devicesOffset = createDevicesData(
|
||||
fbb,
|
||||
config.dataMask,
|
||||
this.api.server.deviceManager
|
||||
.devices,
|
||||
)
|
||||
// Synthetic tracker is computed tracker apparently
|
||||
val trackersOffset = createSyntheticTrackersData(
|
||||
fbb,
|
||||
config.syntheticTrackersMask,
|
||||
this.api.server
|
||||
.allTrackers
|
||||
.stream()
|
||||
.filter(Tracker::isComputed)
|
||||
.collect(Collectors.toList()),
|
||||
)
|
||||
|
||||
val h = this.api.server.humanPoseManager
|
||||
val bonesOffset =
|
||||
createBonesData(
|
||||
fbb,
|
||||
config.boneMask,
|
||||
h.allBones.toMutableList(),
|
||||
)
|
||||
|
||||
var stayAlignedPoseOffset = 0
|
||||
if (config.stayAlignedPoseMask) {
|
||||
stayAlignedPoseOffset = createStayAlignedPose(fbb, this.api.server.humanPoseManager.skeleton)
|
||||
}
|
||||
|
||||
var serverGuardsOffset = 0
|
||||
if (config.serverGuardsMask) {
|
||||
serverGuardsOffset = createServerGuard(fbb, this.api.server.serverGuards)
|
||||
}
|
||||
|
||||
return DataFeedUpdate
|
||||
.createDataFeedUpdate(
|
||||
fbb,
|
||||
devicesOffset,
|
||||
trackersOffset,
|
||||
bonesOffset,
|
||||
stayAlignedPoseOffset,
|
||||
index,
|
||||
serverGuardsOffset,
|
||||
)
|
||||
}
|
||||
|
||||
fun sendDataFeedUpdate() {
|
||||
val currTime = System.currentTimeMillis()
|
||||
|
||||
this.api.apiServers.forEach(
|
||||
Consumer { server: ProtocolAPIServer ->
|
||||
server.apiConnections.forEach { conn: GenericConnection ->
|
||||
var fbb: FlatBufferBuilder? = null
|
||||
val feedList = conn.context.dataFeedList
|
||||
synchronized(feedList) {
|
||||
val configsCount = feedList.size
|
||||
val data = IntArray(configsCount)
|
||||
for (index in 0..<configsCount) {
|
||||
val feed = feedList[index]
|
||||
val lastTimeSent = feed.timeLastSent
|
||||
val configT = feed.config
|
||||
if (currTime - lastTimeSent > configT.minimumTimeSinceLast) {
|
||||
if (fbb == null) {
|
||||
// That way we create a buffer only when needed
|
||||
fbb = FlatBufferBuilder(300)
|
||||
}
|
||||
|
||||
val messageOffset = this.buildDatafeed(fbb, configT, index)
|
||||
|
||||
DataFeedMessageHeader.startDataFeedMessageHeader(fbb)
|
||||
DataFeedMessageHeader.addMessage(fbb, messageOffset)
|
||||
DataFeedMessageHeader.addMessageType(fbb, DataFeedMessage.DataFeedUpdate)
|
||||
data[index] = DataFeedMessageHeader.endDataFeedMessageHeader(fbb)
|
||||
|
||||
feed.timeLastSent = currTime
|
||||
val messages = MessageBundle.createDataFeedMsgsVector(fbb, data)
|
||||
val packet = createMessage(fbb, messages)
|
||||
fbb.finish(packet)
|
||||
conn.send(fbb.dataBuffer())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override fun onMessage(conn: GenericConnection, message: DataFeedMessageHeader) {
|
||||
val consumer = this.handlers[message.messageType().toInt()]
|
||||
if (consumer != null) {
|
||||
consumer.accept(conn, message)
|
||||
} else {
|
||||
LogManager
|
||||
.info(
|
||||
"[ProtocolAPI] Unhandled Datafeed packet received id: " + message.messageType(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun messagesCount(): Int = DataFeedMessage.names.size
|
||||
|
||||
fun createMessage(fbb: FlatBufferBuilder, datafeedMessagesOffset: Int): Int {
|
||||
MessageBundle.startMessageBundle(fbb)
|
||||
if (datafeedMessagesOffset > -1) MessageBundle.addDataFeedMsgs(fbb, datafeedMessagesOffset)
|
||||
return MessageBundle.endMessageBundle(fbb)
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package dev.slimevr.protocol.pubsub;
|
||||
|
||||
import solarxr_protocol.pub_sub.TopicIdT;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
// This class is so the HashMap referencing the TopicId as key works
|
||||
// it needs a unique hashcode based on the topicId and also an equals function
|
||||
// because equals hashcode does not mean equals strings
|
||||
public class HashedTopicId {
|
||||
|
||||
private final TopicIdT inner;
|
||||
private final int hashcode;
|
||||
|
||||
public HashedTopicId(TopicIdT topicIdT) {
|
||||
this.inner = topicIdT;
|
||||
this.hashcode = (inner.getAppName()
|
||||
+ "."
|
||||
+ inner.getOrganization()
|
||||
+ "."
|
||||
+ inner.getTopic()).hashCode();
|
||||
}
|
||||
|
||||
public TopicIdT getInner() {
|
||||
return inner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashcode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
HashedTopicId that = (HashedTopicId) o;
|
||||
return Objects.equals(inner.getOrganization(), that.getInner().getOrganization())
|
||||
&& Objects.equals(inner.getAppName(), that.getInner().getAppName())
|
||||
&& Objects.equals(inner.getTopic(), that.getInner().getTopic());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package dev.slimevr.protocol.pubsub
|
||||
|
||||
import solarxr_protocol.pub_sub.TopicIdT
|
||||
|
||||
// This class is so the HashMap referencing the TopicId as key works
|
||||
// it needs a unique hashcode based on the topicId and also an equals function
|
||||
// because equals hashcode does not mean equals strings
|
||||
class HashedTopicId(val inner: TopicIdT) {
|
||||
private val hashcode: Int = (
|
||||
(
|
||||
inner.appName +
|
||||
"." +
|
||||
inner.organization +
|
||||
"." +
|
||||
inner.topic
|
||||
)
|
||||
).hashCode()
|
||||
|
||||
override fun hashCode(): Int = hashcode
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null || javaClass != other.javaClass) return false
|
||||
val that = other as HashedTopicId
|
||||
return inner.organization == that.inner.organization &&
|
||||
inner.appName == that.inner.appName &&
|
||||
inner.topic == that.inner.topic
|
||||
}
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
package dev.slimevr.protocol.pubsub;
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder;
|
||||
import dev.slimevr.protocol.GenericConnection;
|
||||
import dev.slimevr.protocol.ProtocolAPI;
|
||||
import dev.slimevr.protocol.ProtocolHandler;
|
||||
import io.eiren.util.logging.LogManager;
|
||||
import solarxr_protocol.MessageBundle;
|
||||
import solarxr_protocol.pub_sub.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
|
||||
public class PubSubHandler extends ProtocolHandler<PubSubHeader> {
|
||||
|
||||
private final ProtocolAPI api;
|
||||
|
||||
// Two ways maps for faster reading when handling lots of packets
|
||||
public HashMap<HashedTopicId, Integer> topicsHandle = new HashMap<>();
|
||||
public HashMap<Integer, HashedTopicId> handleTopics = new HashMap<>();
|
||||
|
||||
public AtomicInteger nextLocalHandle = new AtomicInteger();
|
||||
|
||||
public PubSubHandler(ProtocolAPI api) {
|
||||
super();
|
||||
this.api = api;
|
||||
|
||||
registerPacketListener(PubSubUnion.SubscriptionRequest, this::onSubscriptionRequest);
|
||||
registerPacketListener(PubSubUnion.TopicHandleRequest, this::onTopicHandleRequest);
|
||||
registerPacketListener(PubSubUnion.Message, this::onTopicMessage);
|
||||
}
|
||||
|
||||
private int getTopicHandle(TopicIdT topicIdT) {
|
||||
HashedTopicId hashedTopicId = new HashedTopicId(topicIdT);
|
||||
Integer handleT = topicsHandle.get(hashedTopicId);
|
||||
// if no handle exists for this topic id we create one and return it
|
||||
// anyway
|
||||
if (handleT == null) {
|
||||
handleT = nextLocalHandle.incrementAndGet();
|
||||
topicsHandle.put(hashedTopicId, handleT);
|
||||
handleTopics.put(handleT, hashedTopicId);
|
||||
}
|
||||
|
||||
return handleT;
|
||||
}
|
||||
|
||||
public void onSubscriptionRequest(GenericConnection conn, PubSubHeader messageHeader) {
|
||||
SubscriptionRequest req = (SubscriptionRequest) messageHeader.u(new SubscriptionRequest());
|
||||
|
||||
if (req == null)
|
||||
return;
|
||||
|
||||
int subHandle = -1;
|
||||
if (req.topicType() == Topic.TopicHandle) {
|
||||
TopicHandle handle = (TopicHandle) req.topic(new TopicHandle());
|
||||
if (handle != null && handleTopics.containsKey(handle.id()))
|
||||
subHandle = handle.id();
|
||||
} else if (req.topicType() == Topic.TopicId) {
|
||||
TopicId topicId = (TopicId) req.topic(new TopicId());
|
||||
if (topicId != null)
|
||||
subHandle = getTopicHandle(topicId.unpack());
|
||||
}
|
||||
|
||||
assert subHandle != -1;
|
||||
|
||||
final int finalSubHandle = subHandle;
|
||||
Optional<Integer> first = conn
|
||||
.getContext()
|
||||
.getSubscribedTopics()
|
||||
.stream()
|
||||
.filter((handle) -> handle == finalSubHandle)
|
||||
.findFirst();
|
||||
if (!first.isPresent()) {
|
||||
conn.getContext().getSubscribedTopics().add(finalSubHandle);
|
||||
}
|
||||
|
||||
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(32);
|
||||
int topicIdOffset = TopicId.pack(fbb, handleTopics.get(finalSubHandle).getInner());
|
||||
int topicHandleOffset = TopicHandle.createTopicHandle(fbb, finalSubHandle);
|
||||
|
||||
int outbound = createMessage(
|
||||
fbb,
|
||||
PubSubUnion.TopicMapping,
|
||||
TopicMapping.createTopicMapping(fbb, topicIdOffset, topicHandleOffset)
|
||||
);
|
||||
fbb.finish(outbound);
|
||||
conn.send(fbb.dataBuffer());
|
||||
}
|
||||
|
||||
public void onTopicHandleRequest(GenericConnection conn, PubSubHeader messageHeader) {
|
||||
|
||||
TopicHandleRequest req = (TopicHandleRequest) messageHeader.u(new TopicHandleRequest());
|
||||
|
||||
if (req == null)
|
||||
return;
|
||||
|
||||
TopicHandleRequestT topicRequest = req.unpack();
|
||||
int handle = getTopicHandle(topicRequest.getId());
|
||||
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(32);
|
||||
int topicIdOffset = TopicId.pack(fbb, topicRequest.getId());
|
||||
int topicHandleOffset = TopicHandle.createTopicHandle(fbb, handle);
|
||||
|
||||
int outbound = createMessage(
|
||||
fbb,
|
||||
PubSubUnion.TopicMapping,
|
||||
TopicMapping.createTopicMapping(fbb, topicIdOffset, topicHandleOffset)
|
||||
);
|
||||
fbb.finish(outbound);
|
||||
conn.send(fbb.dataBuffer());
|
||||
}
|
||||
|
||||
|
||||
public void onTopicMessage(GenericConnection c, PubSubHeader messageHeader) {
|
||||
Message req = (Message) messageHeader.u(new Message());
|
||||
|
||||
if (req == null)
|
||||
return;
|
||||
|
||||
MessageT messageT = req.unpack();
|
||||
|
||||
int subHandle = 1;
|
||||
if (messageT.getTopic().getType() == Topic.TopicHandle) {
|
||||
subHandle = messageT.getTopic().asTopicHandle().getId();
|
||||
} else if (messageT.getTopic().getType() == Topic.TopicId) {
|
||||
subHandle = getTopicHandle(messageT.getTopic().asTopicId());
|
||||
}
|
||||
|
||||
|
||||
assert subHandle != -1;
|
||||
|
||||
int finalSubHandle = subHandle;
|
||||
|
||||
this.api.getAPIServers().forEach((server) -> {
|
||||
server.getAPIConnections().forEach((conn) -> {
|
||||
// Make sure that we are not sending a message to ourselves
|
||||
// And check that the receiver has subscribed to the topic
|
||||
if (
|
||||
!conn.getConnectionId().equals(c.getConnectionId())
|
||||
&& conn.getContext().getSubscribedTopics().contains(finalSubHandle)
|
||||
) {
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(32);
|
||||
int outbound = createMessage(
|
||||
fbb,
|
||||
PubSubUnion.Message,
|
||||
Message.pack(fbb, messageT)
|
||||
);
|
||||
fbb.finish(outbound);
|
||||
conn.send(fbb.dataBuffer());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(GenericConnection conn, PubSubHeader message) {
|
||||
BiConsumer<GenericConnection, PubSubHeader> consumer = this.handlers[message.uType()];
|
||||
if (consumer != null)
|
||||
consumer.accept(conn, message);
|
||||
else
|
||||
LogManager
|
||||
.info("[ProtocolAPI] Unhandled PubSub packet received id: " + message.uType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int messagesCount() {
|
||||
return PubSubUnion.names.length;
|
||||
}
|
||||
|
||||
public int createMessage(FlatBufferBuilder fbb, byte messageType, int messageOffset) {
|
||||
int[] data = new int[1];
|
||||
|
||||
data[0] = PubSubHeader.createPubSubHeader(fbb, messageType, messageOffset);
|
||||
|
||||
int messages = MessageBundle.createPubSubMsgsVector(fbb, data);
|
||||
|
||||
MessageBundle.startMessageBundle(fbb);
|
||||
MessageBundle.addPubSubMsgs(fbb, messages);
|
||||
return MessageBundle.endMessageBundle(fbb);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package dev.slimevr.protocol.pubsub
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder
|
||||
import dev.slimevr.protocol.GenericConnection
|
||||
import dev.slimevr.protocol.ProtocolAPI
|
||||
import dev.slimevr.protocol.ProtocolAPIServer
|
||||
import dev.slimevr.protocol.ProtocolHandler
|
||||
import io.eiren.util.logging.LogManager
|
||||
import solarxr_protocol.MessageBundle
|
||||
import solarxr_protocol.pub_sub.Message
|
||||
import solarxr_protocol.pub_sub.PubSubHeader
|
||||
import solarxr_protocol.pub_sub.PubSubUnion
|
||||
import solarxr_protocol.pub_sub.SubscriptionRequest
|
||||
import solarxr_protocol.pub_sub.Topic
|
||||
import solarxr_protocol.pub_sub.TopicHandle
|
||||
import solarxr_protocol.pub_sub.TopicHandleRequest
|
||||
import solarxr_protocol.pub_sub.TopicId
|
||||
import solarxr_protocol.pub_sub.TopicIdT
|
||||
import solarxr_protocol.pub_sub.TopicMapping
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import java.util.function.Consumer
|
||||
|
||||
class PubSubHandler(private val api: ProtocolAPI) : ProtocolHandler<PubSubHeader>() {
|
||||
// Two ways maps for faster reading when handling lots of packets
|
||||
var topicsHandle: HashMap<HashedTopicId, Int> = HashMap()
|
||||
var handleTopics: HashMap<Int, HashedTopicId> = HashMap()
|
||||
|
||||
var nextLocalHandle: AtomicInteger = AtomicInteger()
|
||||
|
||||
init {
|
||||
registerPacketListener(PubSubUnion.SubscriptionRequest, ::onSubscriptionRequest)
|
||||
registerPacketListener(PubSubUnion.TopicHandleRequest, ::onTopicHandleRequest)
|
||||
registerPacketListener(PubSubUnion.Message, ::onTopicMessage)
|
||||
}
|
||||
|
||||
private fun getTopicHandle(topicIdT: TopicIdT): Int {
|
||||
val hashedTopicId = HashedTopicId(topicIdT)
|
||||
var handleT = topicsHandle.get(hashedTopicId)
|
||||
// if no handle exists for this topic id we create one and return it
|
||||
// anyway
|
||||
if (handleT == null) {
|
||||
handleT = nextLocalHandle.incrementAndGet()
|
||||
topicsHandle[hashedTopicId] = handleT
|
||||
handleTopics[handleT] = hashedTopicId
|
||||
}
|
||||
|
||||
return handleT
|
||||
}
|
||||
|
||||
fun onSubscriptionRequest(conn: GenericConnection, messageHeader: PubSubHeader) {
|
||||
val req =
|
||||
messageHeader.u(SubscriptionRequest()) as SubscriptionRequest? ?: return
|
||||
|
||||
var subHandle = -1
|
||||
if (req.topicType() == Topic.TopicHandle) {
|
||||
val handle = req.topic(TopicHandle()) as TopicHandle?
|
||||
if (handle != null && handleTopics.containsKey(handle.id())) subHandle = handle.id()
|
||||
} else if (req.topicType() == Topic.TopicId) {
|
||||
val topicId = req.topic(TopicId()) as TopicId?
|
||||
if (topicId != null) subHandle = getTopicHandle(topicId.unpack())
|
||||
}
|
||||
|
||||
assert(subHandle != -1)
|
||||
|
||||
val finalSubHandle = subHandle
|
||||
val first = conn
|
||||
.context
|
||||
.subscribedTopics
|
||||
.stream()
|
||||
.filter { handle: Int -> handle == finalSubHandle }
|
||||
.findFirst()
|
||||
if (!first.isPresent) {
|
||||
conn.context.subscribedTopics.add(finalSubHandle)
|
||||
}
|
||||
|
||||
val fbb = FlatBufferBuilder(32)
|
||||
val topicIdOffset = TopicId.pack(fbb, handleTopics.get(finalSubHandle)!!.inner)
|
||||
val topicHandleOffset = TopicHandle.createTopicHandle(fbb, finalSubHandle)
|
||||
|
||||
val outbound = createMessage(
|
||||
fbb,
|
||||
PubSubUnion.TopicMapping,
|
||||
TopicMapping.createTopicMapping(fbb, topicIdOffset, topicHandleOffset),
|
||||
)
|
||||
fbb.finish(outbound)
|
||||
conn.send(fbb.dataBuffer())
|
||||
}
|
||||
|
||||
fun onTopicHandleRequest(conn: GenericConnection, messageHeader: PubSubHeader) {
|
||||
val req = messageHeader.u(TopicHandleRequest()) as TopicHandleRequest? ?: return
|
||||
|
||||
val topicRequest = req.unpack()
|
||||
val handle = getTopicHandle(topicRequest.id)
|
||||
|
||||
val fbb = FlatBufferBuilder(32)
|
||||
val topicIdOffset = TopicId.pack(fbb, topicRequest.id)
|
||||
val topicHandleOffset = TopicHandle.createTopicHandle(fbb, handle)
|
||||
|
||||
val outbound = createMessage(
|
||||
fbb,
|
||||
PubSubUnion.TopicMapping,
|
||||
TopicMapping.createTopicMapping(fbb, topicIdOffset, topicHandleOffset),
|
||||
)
|
||||
fbb.finish(outbound)
|
||||
conn.send(fbb.dataBuffer())
|
||||
}
|
||||
|
||||
fun onTopicMessage(c: GenericConnection, messageHeader: PubSubHeader) {
|
||||
val req = messageHeader.u(Message()) as Message? ?: return
|
||||
|
||||
val messageT = req.unpack()
|
||||
|
||||
var subHandle = 1
|
||||
if (messageT.topic.type == Topic.TopicHandle) {
|
||||
subHandle = messageT.topic.asTopicHandle().id
|
||||
} else if (messageT.topic.type == Topic.TopicId) {
|
||||
subHandle = getTopicHandle(messageT.topic.asTopicId())
|
||||
}
|
||||
|
||||
assert(subHandle != -1)
|
||||
|
||||
val finalSubHandle = subHandle
|
||||
|
||||
this.api.apiServers.forEach(
|
||||
Consumer { server: ProtocolAPIServer ->
|
||||
server.apiConnections.forEach { conn: GenericConnection ->
|
||||
// Make sure that we are not sending a message to ourselves
|
||||
// And check that the receiver has subscribed to the topic
|
||||
if (conn.connectionId != c.connectionId &&
|
||||
conn.context.subscribedTopics
|
||||
.contains(finalSubHandle)
|
||||
) {
|
||||
val fbb = FlatBufferBuilder(32)
|
||||
val outbound = createMessage(
|
||||
fbb,
|
||||
PubSubUnion.Message,
|
||||
Message.pack(fbb, messageT),
|
||||
)
|
||||
fbb.finish(outbound)
|
||||
conn.send(fbb.dataBuffer())
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override fun onMessage(conn: GenericConnection, message: PubSubHeader) {
|
||||
val consumer = this.handlers[message.uType().toInt()]
|
||||
if (consumer != null) {
|
||||
consumer.accept(conn, message)
|
||||
} else {
|
||||
LogManager
|
||||
.info("[ProtocolAPI] Unhandled PubSub packet received id: " + message.uType())
|
||||
}
|
||||
}
|
||||
|
||||
override fun messagesCount(): Int = PubSubUnion.names.size
|
||||
|
||||
fun createMessage(fbb: FlatBufferBuilder, messageType: Byte, messageOffset: Int): Int {
|
||||
val data = IntArray(1)
|
||||
|
||||
data[0] = PubSubHeader.createPubSubHeader(fbb, messageType, messageOffset)
|
||||
|
||||
val messages = MessageBundle.createPubSubMsgsVector(fbb, data)
|
||||
|
||||
MessageBundle.startMessageBundle(fbb)
|
||||
MessageBundle.addPubSubMsgs(fbb, messages)
|
||||
return MessageBundle.endMessageBundle(fbb)
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package dev.slimevr.protocol.rpc;
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder;
|
||||
import dev.slimevr.tracking.processor.HumanPoseManager;
|
||||
import dev.slimevr.tracking.processor.config.SkeletonConfigOffsets;
|
||||
import solarxr_protocol.rpc.SkeletonConfigResponse;
|
||||
import solarxr_protocol.rpc.SkeletonPart;
|
||||
|
||||
|
||||
public class RPCBuilder {
|
||||
|
||||
public static int createSkeletonConfig(
|
||||
FlatBufferBuilder fbb,
|
||||
HumanPoseManager humanPoseManager
|
||||
) {
|
||||
int[] partsOffsets = new int[SkeletonConfigOffsets.values().length];
|
||||
|
||||
for (int index = 0; index < SkeletonConfigOffsets.values().length; index++) {
|
||||
SkeletonConfigOffsets val = SkeletonConfigOffsets.values[index];
|
||||
int part = SkeletonPart
|
||||
.createSkeletonPart(fbb, val.id, humanPoseManager.getOffset(val));
|
||||
partsOffsets[index] = part;
|
||||
}
|
||||
|
||||
int parts = SkeletonConfigResponse.createSkeletonPartsVector(fbb, partsOffsets);
|
||||
return SkeletonConfigResponse.createSkeletonConfigResponse(fbb, parts, 0);
|
||||
}
|
||||
}
|
||||
@@ -6,15 +6,15 @@ import dev.slimevr.config.config
|
||||
import dev.slimevr.protocol.GenericConnection
|
||||
import dev.slimevr.protocol.ProtocolAPI
|
||||
import dev.slimevr.protocol.ProtocolHandler
|
||||
import dev.slimevr.protocol.datafeed.DataFeedBuilder
|
||||
import dev.slimevr.protocol.datafeed.createTrackerId
|
||||
import dev.slimevr.protocol.rpc.autobone.RPCAutoBoneHandler
|
||||
import dev.slimevr.protocol.rpc.firmware.RPCFirmwareUpdateHandler
|
||||
import dev.slimevr.protocol.rpc.games.vrchat.RPCVRChatHandler
|
||||
import dev.slimevr.protocol.rpc.reset.RPCResetHandler
|
||||
import dev.slimevr.protocol.rpc.serial.RPCProvisioningHandler
|
||||
import dev.slimevr.protocol.rpc.serial.RPCSerialHandler
|
||||
import dev.slimevr.protocol.rpc.settings.RPCSettingsBuilder
|
||||
import dev.slimevr.protocol.rpc.settings.RPCSettingsHandler
|
||||
import dev.slimevr.protocol.rpc.settings.createSettingsResponse
|
||||
import dev.slimevr.protocol.rpc.setup.RPCHandshakeHandler
|
||||
import dev.slimevr.protocol.rpc.setup.RPCTapSetupHandler
|
||||
import dev.slimevr.protocol.rpc.setup.RPCUtil.getLocalIp
|
||||
@@ -460,7 +460,7 @@ class RPCHandler(private val api: ProtocolAPI) : ProtocolHandler<RpcMessageHeade
|
||||
}
|
||||
|
||||
val tracker = api.server.getTrackerById(req.trackerId().unpack()) ?: return
|
||||
val trackerId = DataFeedBuilder.createTrackerId(fbb, tracker)
|
||||
val trackerId = createTrackerId(fbb, tracker)
|
||||
val response = MagToggleResponse.createMagToggleResponse(
|
||||
fbb,
|
||||
trackerId,
|
||||
@@ -499,7 +499,7 @@ class RPCHandler(private val api: ProtocolAPI) : ProtocolHandler<RpcMessageHeade
|
||||
// Don't apply magnetometer setting if use magnetometer global setting is not enabled
|
||||
if (!api.server.configManager.vrConfig.server.useMagnetometerOnAllTrackers) {
|
||||
val fbb = FlatBufferBuilder(32)
|
||||
val trackerId = DataFeedBuilder.createTrackerId(fbb, tracker)
|
||||
val trackerId = createTrackerId(fbb, tracker)
|
||||
val response = MagToggleResponse.createMagToggleResponse(
|
||||
fbb,
|
||||
trackerId,
|
||||
@@ -516,7 +516,7 @@ class RPCHandler(private val api: ProtocolAPI) : ProtocolHandler<RpcMessageHeade
|
||||
}
|
||||
|
||||
val fbb = FlatBufferBuilder(32)
|
||||
val trackerId = DataFeedBuilder.createTrackerId(fbb, tracker)
|
||||
val trackerId = createTrackerId(fbb, tracker)
|
||||
val response = MagToggleResponse.createMagToggleResponse(
|
||||
fbb,
|
||||
trackerId,
|
||||
@@ -607,7 +607,7 @@ class RPCHandler(private val api: ProtocolAPI) : ProtocolHandler<RpcMessageHeade
|
||||
|
||||
fun sendSettingsChangedResponse(conn: GenericConnection, messageHeader: RpcMessageHeader?) {
|
||||
val fbb = FlatBufferBuilder(32)
|
||||
val settings = RPCSettingsBuilder.createSettingsResponse(fbb, api.server)
|
||||
val settings = createSettingsResponse(fbb, api.server)
|
||||
val outbound = createRPCMessage(fbb, RpcMessage.SettingsResponse, settings, messageHeader)
|
||||
fbb.finish(outbound)
|
||||
conn.send(fbb.dataBuffer())
|
||||
|
||||
@@ -50,8 +50,8 @@ class RPCAutoBoneHandler(
|
||||
) {
|
||||
val req = messageHeader
|
||||
.message(AutoBoneProcessRequest()) as AutoBoneProcessRequest
|
||||
if (conn.context.useAutoBone()) return
|
||||
conn.context.setUseAutoBone(true)
|
||||
if (conn.context.useAutoBone) return
|
||||
conn.context.useAutoBone = true
|
||||
api.server
|
||||
.autoBoneHandler
|
||||
.startProcessByType(getById(req.processType()))
|
||||
@@ -67,7 +67,7 @@ class RPCAutoBoneHandler(
|
||||
success: Boolean,
|
||||
) {
|
||||
forAllListeners { conn ->
|
||||
if (!conn.context.useAutoBone()) {
|
||||
if (!conn.context.useAutoBone) {
|
||||
return@forAllListeners
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ class RPCAutoBoneHandler(
|
||||
fbb.finish(outbound)
|
||||
conn.send(fbb.dataBuffer())
|
||||
if (completed) {
|
||||
conn.context.setUseAutoBone(false)
|
||||
conn.context.useAutoBone = false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,7 +106,7 @@ class RPCAutoBoneHandler(
|
||||
|
||||
override fun onAutoBoneEpoch(epoch: Epoch) {
|
||||
forAllListeners { conn ->
|
||||
if (!conn.context.useAutoBone()) {
|
||||
if (!conn.context.useAutoBone) {
|
||||
return@forAllListeners
|
||||
}
|
||||
|
||||
|
||||
@@ -108,11 +108,11 @@ class RPCResetHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) : ResetL
|
||||
|
||||
fun forAllListeners(action: Consumer<in GenericConnection?>?) {
|
||||
this.api
|
||||
.getAPIServers()
|
||||
.apiServers
|
||||
.forEach(
|
||||
Consumer { server: ProtocolAPIServer? ->
|
||||
server!!
|
||||
.getAPIConnections()
|
||||
Consumer { server: ProtocolAPIServer ->
|
||||
server
|
||||
.apiConnections
|
||||
.forEach(action)
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
package dev.slimevr.protocol.rpc.serial;
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder;
|
||||
import dev.slimevr.protocol.GenericConnection;
|
||||
import dev.slimevr.protocol.ProtocolAPI;
|
||||
import dev.slimevr.protocol.rpc.RPCHandler;
|
||||
import dev.slimevr.serial.ProvisioningListener;
|
||||
import dev.slimevr.serial.ProvisioningStatus;
|
||||
import dev.slimevr.serial.SerialPort;
|
||||
import solarxr_protocol.rpc.*;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
public class RPCProvisioningHandler implements ProvisioningListener {
|
||||
|
||||
public RPCHandler rpcHandler;
|
||||
public ProtocolAPI api;
|
||||
|
||||
public RPCProvisioningHandler(RPCHandler rpcHandler, ProtocolAPI api) {
|
||||
this.rpcHandler = rpcHandler;
|
||||
this.api = api;
|
||||
|
||||
rpcHandler
|
||||
.registerPacketListener(
|
||||
RpcMessage.StartWifiProvisioningRequest,
|
||||
this::onStartWifiProvisioningRequest
|
||||
);
|
||||
rpcHandler
|
||||
.registerPacketListener(
|
||||
RpcMessage.StopWifiProvisioningRequest,
|
||||
this::onStopWifiProvisioningRequest
|
||||
);
|
||||
|
||||
this.api.server.provisioningHandler.addListener(this);
|
||||
}
|
||||
|
||||
public void onStartWifiProvisioningRequest(
|
||||
GenericConnection conn,
|
||||
RpcMessageHeader messageHeader
|
||||
) {
|
||||
StartWifiProvisioningRequest req = (StartWifiProvisioningRequest) messageHeader
|
||||
.message(new StartWifiProvisioningRequest());
|
||||
if (req == null)
|
||||
return;
|
||||
this.api.server.provisioningHandler.start(req.ssid(), req.password(), req.port());
|
||||
conn.getContext().setUseProvisioning(true);
|
||||
}
|
||||
|
||||
public void onStopWifiProvisioningRequest(
|
||||
GenericConnection conn,
|
||||
RpcMessageHeader messageHeader
|
||||
) {
|
||||
StopWifiProvisioningRequest req = (StopWifiProvisioningRequest) messageHeader
|
||||
.message(new StopWifiProvisioningRequest());
|
||||
if (req == null)
|
||||
return;
|
||||
conn.getContext().setUseProvisioning(false);
|
||||
this.api.server.provisioningHandler.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProvisioningStatusChange(ProvisioningStatus status, SerialPort port) {
|
||||
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(32);
|
||||
|
||||
WifiProvisioningStatusResponse.startWifiProvisioningStatusResponse(fbb);
|
||||
WifiProvisioningStatusResponse.addStatus(fbb, status.id);
|
||||
int update = WifiProvisioningStatusResponse.endWifiProvisioningStatusResponse(fbb);
|
||||
int outbound = rpcHandler
|
||||
.createRPCMessage(fbb, RpcMessage.WifiProvisioningStatusResponse, update);
|
||||
fbb.finish(outbound);
|
||||
|
||||
this.forAllListeners((conn) -> conn.send(fbb.dataBuffer()));
|
||||
}
|
||||
|
||||
private void forAllListeners(Consumer<? super GenericConnection> action) {
|
||||
this.api
|
||||
.getAPIServers()
|
||||
.forEach(
|
||||
(server) -> server
|
||||
.getAPIConnections()
|
||||
.filter(conn -> conn.getContext().useProvisioning())
|
||||
.forEach(action)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package dev.slimevr.protocol.rpc.serial
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder
|
||||
import dev.slimevr.protocol.GenericConnection
|
||||
import dev.slimevr.protocol.ProtocolAPI
|
||||
import dev.slimevr.protocol.ProtocolAPIServer
|
||||
import dev.slimevr.protocol.rpc.RPCHandler
|
||||
import dev.slimevr.serial.ProvisioningListener
|
||||
import dev.slimevr.serial.ProvisioningStatus
|
||||
import dev.slimevr.serial.SerialPort
|
||||
import solarxr_protocol.rpc.*
|
||||
import java.util.function.Consumer
|
||||
|
||||
class RPCProvisioningHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) : ProvisioningListener {
|
||||
init {
|
||||
rpcHandler.registerPacketListener(RpcMessage.StartWifiProvisioningRequest, ::onStartWifiProvisioningRequest)
|
||||
rpcHandler.registerPacketListener(RpcMessage.StopWifiProvisioningRequest, ::onStopWifiProvisioningRequest)
|
||||
this.api.server.provisioningHandler.addListener(this)
|
||||
}
|
||||
|
||||
fun onStartWifiProvisioningRequest(
|
||||
conn: GenericConnection,
|
||||
messageHeader: RpcMessageHeader,
|
||||
) {
|
||||
val req = messageHeader
|
||||
.message(StartWifiProvisioningRequest()) as StartWifiProvisioningRequest?
|
||||
if (req == null) return
|
||||
this.api.server.provisioningHandler.start(req.ssid(), req.password(), req.port())
|
||||
conn.context.useProvisioning = true
|
||||
}
|
||||
|
||||
fun onStopWifiProvisioningRequest(
|
||||
conn: GenericConnection,
|
||||
messageHeader: RpcMessageHeader,
|
||||
) {
|
||||
val req = messageHeader
|
||||
.message(StopWifiProvisioningRequest()) as StopWifiProvisioningRequest?
|
||||
if (req == null) return
|
||||
conn.context.useProvisioning = false
|
||||
this.api.server.provisioningHandler.stop()
|
||||
}
|
||||
|
||||
override fun onProvisioningStatusChange(status: ProvisioningStatus, port: SerialPort?) {
|
||||
val fbb = FlatBufferBuilder(32)
|
||||
|
||||
WifiProvisioningStatusResponse.startWifiProvisioningStatusResponse(fbb)
|
||||
WifiProvisioningStatusResponse.addStatus(fbb, status.id)
|
||||
val update = WifiProvisioningStatusResponse.endWifiProvisioningStatusResponse(fbb)
|
||||
val outbound = rpcHandler
|
||||
.createRPCMessage(fbb, RpcMessage.WifiProvisioningStatusResponse, update)
|
||||
fbb.finish(outbound)
|
||||
|
||||
this.forAllListeners(Consumer { conn: GenericConnection -> conn.send(fbb.dataBuffer()) })
|
||||
}
|
||||
|
||||
private fun forAllListeners(action: Consumer<in GenericConnection?>?) {
|
||||
this.api
|
||||
.apiServers
|
||||
.forEach(
|
||||
Consumer { server: ProtocolAPIServer ->
|
||||
server
|
||||
.apiConnections
|
||||
.filter { conn: GenericConnection -> conn.context.useProvisioning }
|
||||
.forEach(action)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,303 +0,0 @@
|
||||
package dev.slimevr.protocol.rpc.serial;
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder;
|
||||
import dev.slimevr.protocol.GenericConnection;
|
||||
import dev.slimevr.protocol.ProtocolAPI;
|
||||
import dev.slimevr.protocol.rpc.RPCHandler;
|
||||
import dev.slimevr.serial.SerialListener;
|
||||
import dev.slimevr.serial.SerialPort;
|
||||
import io.eiren.util.logging.LogManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import solarxr_protocol.rpc.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
public class RPCSerialHandler implements SerialListener {
|
||||
|
||||
public RPCHandler rpcHandler;
|
||||
public ProtocolAPI api;
|
||||
|
||||
public RPCSerialHandler(RPCHandler rpcHandler, ProtocolAPI api) {
|
||||
this.rpcHandler = rpcHandler;
|
||||
this.api = api;
|
||||
|
||||
rpcHandler
|
||||
.registerPacketListener(
|
||||
RpcMessage.SerialTrackerRebootRequest,
|
||||
this::onSerialTrackerRebootRequest
|
||||
);
|
||||
rpcHandler
|
||||
.registerPacketListener(
|
||||
RpcMessage.SerialTrackerGetInfoRequest,
|
||||
this::onSerialTrackerGetInfoRequest
|
||||
);
|
||||
rpcHandler
|
||||
.registerPacketListener(
|
||||
RpcMessage.SerialTrackerFactoryResetRequest,
|
||||
this::onSerialTrackerFactoryResetRequest
|
||||
);
|
||||
rpcHandler
|
||||
.registerPacketListener(
|
||||
RpcMessage.SerialTrackerGetWifiScanRequest,
|
||||
this::onSerialTrackerGetWifiScanRequest
|
||||
);
|
||||
rpcHandler
|
||||
.registerPacketListener(
|
||||
RpcMessage.SerialTrackerCustomCommandRequest,
|
||||
this::onSerialTrackerCustomCommandRequest
|
||||
);
|
||||
rpcHandler.registerPacketListener(RpcMessage.SetWifiRequest, this::onSetWifiRequest);
|
||||
rpcHandler.registerPacketListener(RpcMessage.OpenSerialRequest, this::onOpenSerialRequest);
|
||||
rpcHandler
|
||||
.registerPacketListener(RpcMessage.CloseSerialRequest, this::onCloseSerialRequest);
|
||||
rpcHandler
|
||||
.registerPacketListener(RpcMessage.SerialDevicesRequest, this::onRequestSerialDevices);
|
||||
this.api.server.serialHandler.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSerialDisconnected() {
|
||||
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(32);
|
||||
|
||||
SerialUpdateResponse.startSerialUpdateResponse(fbb);
|
||||
SerialUpdateResponse.addClosed(fbb, true);
|
||||
int update = SerialUpdateResponse.endSerialUpdateResponse(fbb);
|
||||
int outbound = rpcHandler.createRPCMessage(fbb, RpcMessage.SerialUpdateResponse, update);
|
||||
fbb.finish(outbound);
|
||||
|
||||
this.forAllListeners((conn) -> {
|
||||
conn.send(fbb.dataBuffer());
|
||||
conn.getContext().setUseSerial(false);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSerialLog(String str, boolean server) {
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(32);
|
||||
|
||||
int logOffset = fbb.createString(str);
|
||||
|
||||
SerialUpdateResponse.startSerialUpdateResponse(fbb);
|
||||
SerialUpdateResponse.addLog(fbb, logOffset);
|
||||
int update = SerialUpdateResponse.endSerialUpdateResponse(fbb);
|
||||
int outbound = rpcHandler.createRPCMessage(fbb, RpcMessage.SerialUpdateResponse, update);
|
||||
fbb.finish(outbound);
|
||||
|
||||
this.forAllListeners((conn) -> {
|
||||
conn.send(fbb.dataBuffer());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewSerialDevice(SerialPort port) {
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(32);
|
||||
|
||||
int portOffset = fbb.createString(port.getPortLocation());
|
||||
int nameOffset = fbb.createString(port.getDescriptivePortName());
|
||||
int deviceOffset = SerialDevice.createSerialDevice(fbb, portOffset, nameOffset);
|
||||
int newSerialOffset = NewSerialDeviceResponse
|
||||
.createNewSerialDeviceResponse(fbb, deviceOffset);
|
||||
int outbound = rpcHandler
|
||||
.createRPCMessage(fbb, RpcMessage.NewSerialDeviceResponse, newSerialOffset);
|
||||
fbb.finish(outbound);
|
||||
|
||||
|
||||
this.api
|
||||
.getAPIServers()
|
||||
.forEach(
|
||||
(server) -> server
|
||||
.getAPIConnections()
|
||||
.forEach((conn) -> {
|
||||
conn.send(fbb.dataBuffer());
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSerialConnected(SerialPort port) {
|
||||
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(32);
|
||||
|
||||
SerialUpdateResponse.startSerialUpdateResponse(fbb);
|
||||
SerialUpdateResponse.addClosed(fbb, false);
|
||||
int update = SerialUpdateResponse.endSerialUpdateResponse(fbb);
|
||||
int outbound = rpcHandler.createRPCMessage(fbb, RpcMessage.SerialUpdateResponse, update);
|
||||
fbb.finish(outbound);
|
||||
|
||||
this.forAllListeners((conn) -> {
|
||||
conn.send(fbb.dataBuffer());
|
||||
});
|
||||
}
|
||||
|
||||
public void onSerialTrackerRebootRequest(
|
||||
GenericConnection conn,
|
||||
RpcMessageHeader messageHeader
|
||||
) {
|
||||
SerialTrackerRebootRequest req = (SerialTrackerRebootRequest) messageHeader
|
||||
.message(new SerialTrackerRebootRequest());
|
||||
if (req == null)
|
||||
return;
|
||||
|
||||
this.api.server.serialHandler.rebootRequest();
|
||||
}
|
||||
|
||||
public void onSerialTrackerGetInfoRequest(
|
||||
GenericConnection conn,
|
||||
RpcMessageHeader messageHeader
|
||||
) {
|
||||
SerialTrackerGetInfoRequest req = (SerialTrackerGetInfoRequest) messageHeader
|
||||
.message(new SerialTrackerGetInfoRequest());
|
||||
if (req == null)
|
||||
return;
|
||||
|
||||
this.api.server.serialHandler.infoRequest();
|
||||
}
|
||||
|
||||
public void onSerialTrackerFactoryResetRequest(
|
||||
GenericConnection conn,
|
||||
RpcMessageHeader messageHeader
|
||||
) {
|
||||
SerialTrackerFactoryResetRequest req = (SerialTrackerFactoryResetRequest) messageHeader
|
||||
.message(new SerialTrackerFactoryResetRequest());
|
||||
if (req == null)
|
||||
return;
|
||||
|
||||
this.api.server.serialHandler.factoryResetRequest();
|
||||
}
|
||||
|
||||
public void onSerialTrackerGetWifiScanRequest(
|
||||
GenericConnection conn,
|
||||
RpcMessageHeader messageHeader
|
||||
) {
|
||||
SerialTrackerGetWifiScanRequest req = (SerialTrackerGetWifiScanRequest) messageHeader
|
||||
.message(new SerialTrackerGetWifiScanRequest());
|
||||
if (req == null)
|
||||
return;
|
||||
|
||||
this.api.server.serialHandler.wifiScanRequest();
|
||||
}
|
||||
|
||||
public void onSerialTrackerCustomCommandRequest(
|
||||
GenericConnection conn,
|
||||
RpcMessageHeader messageHeader
|
||||
) {
|
||||
SerialTrackerCustomCommandRequest req = (SerialTrackerCustomCommandRequest) messageHeader
|
||||
.message(new SerialTrackerCustomCommandRequest());
|
||||
|
||||
if (req == null || req.command() == null)
|
||||
return;
|
||||
|
||||
this.api.server.serialHandler.customCommandRequest(Objects.requireNonNull(req.command()));
|
||||
}
|
||||
|
||||
private void onRequestSerialDevices(GenericConnection conn, RpcMessageHeader messageHeader) {
|
||||
SerialDevicesRequest req = (SerialDevicesRequest) messageHeader
|
||||
.message(new SerialDevicesRequest());
|
||||
if (req == null)
|
||||
return;
|
||||
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(32);
|
||||
|
||||
|
||||
List<Integer> devicesOffsets = new ArrayList<>();
|
||||
|
||||
try {
|
||||
this.api.server.serialHandler.getKnownPorts().forEach((port) -> {
|
||||
int portOffset = fbb.createString(port.getPortLocation());
|
||||
int nameOffset = fbb.createString(port.getDescriptivePortName());
|
||||
devicesOffsets.add(SerialDevice.createSerialDevice(fbb, portOffset, nameOffset));
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
LogManager.severe("Using serial ports is not supported on this platform", e);
|
||||
}
|
||||
|
||||
SerialDevicesResponse.startDevicesVector(fbb, devicesOffsets.size());
|
||||
devicesOffsets.forEach(offset -> SerialDevicesResponse.addDevices(fbb, offset));
|
||||
int devices = fbb.endVector();
|
||||
int serialDeviceOffsets = SerialDevicesResponse.createSerialDevicesResponse(fbb, devices);
|
||||
int outbound = rpcHandler
|
||||
.createRPCMessage(fbb, RpcMessage.SerialDevicesResponse, serialDeviceOffsets);
|
||||
fbb.finish(outbound);
|
||||
conn.send(fbb.dataBuffer());
|
||||
}
|
||||
|
||||
public void onSetWifiRequest(GenericConnection conn, RpcMessageHeader messageHeader) {
|
||||
SetWifiRequest req = (SetWifiRequest) messageHeader.message(new SetWifiRequest());
|
||||
if (req == null)
|
||||
return;
|
||||
|
||||
if (
|
||||
req.password() == null
|
||||
|| req.ssid() == null
|
||||
|| !this.api.server.serialHandler.isConnected()
|
||||
)
|
||||
return;
|
||||
this.api.server.serialHandler.setWifi(req.ssid(), req.password());
|
||||
}
|
||||
|
||||
public void onOpenSerialRequest(GenericConnection conn, RpcMessageHeader messageHeader) {
|
||||
OpenSerialRequest req = (OpenSerialRequest) messageHeader.message(new OpenSerialRequest());
|
||||
if (req == null)
|
||||
return;
|
||||
|
||||
conn.getContext().setUseSerial(true);
|
||||
|
||||
this.api.server.queueTask(() -> {
|
||||
try {
|
||||
this.api.server.serialHandler.openSerial(req.port(), req.auto());
|
||||
} catch (Exception e) {
|
||||
LogManager.severe("Unable to open serial port", e);
|
||||
} catch (Throwable e) {
|
||||
LogManager.severe("Using serial ports is not supported on this platform", e);
|
||||
}
|
||||
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(32);
|
||||
SerialUpdateResponse.startSerialUpdateResponse(fbb);
|
||||
SerialUpdateResponse.addClosed(fbb, !this.api.server.serialHandler.isConnected());
|
||||
int update = SerialUpdateResponse.endSerialUpdateResponse(fbb);
|
||||
int outbound = rpcHandler
|
||||
.createRPCMessage(fbb, RpcMessage.SerialUpdateResponse, update);
|
||||
fbb.finish(outbound);
|
||||
conn.send(fbb.dataBuffer());
|
||||
});
|
||||
}
|
||||
|
||||
public void onCloseSerialRequest(GenericConnection conn, RpcMessageHeader messageHeader) {
|
||||
CloseSerialRequest req = (CloseSerialRequest) messageHeader
|
||||
.message(new CloseSerialRequest());
|
||||
if (req == null)
|
||||
return;
|
||||
|
||||
conn.getContext().setUseSerial(false);
|
||||
|
||||
this.api.server.serialHandler.closeSerial();
|
||||
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(32);
|
||||
SerialUpdateResponse.startSerialUpdateResponse(fbb);
|
||||
SerialUpdateResponse.addClosed(fbb, !this.api.server.serialHandler.isConnected());
|
||||
int update = SerialUpdateResponse.endSerialUpdateResponse(fbb);
|
||||
int outbound = rpcHandler.createRPCMessage(fbb, RpcMessage.SerialUpdateResponse, update);
|
||||
fbb.finish(outbound);
|
||||
conn.send(fbb.dataBuffer());
|
||||
}
|
||||
|
||||
public void forAllListeners(Consumer<? super GenericConnection> action) {
|
||||
this.api
|
||||
.getAPIServers()
|
||||
.forEach(
|
||||
(server) -> server
|
||||
.getAPIConnections()
|
||||
.filter(conn -> conn.getContext().useSerial())
|
||||
.forEach(action)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSerialDeviceDeleted(@NotNull SerialPort port) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
package dev.slimevr.protocol.rpc.serial
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder
|
||||
import dev.slimevr.protocol.GenericConnection
|
||||
import dev.slimevr.protocol.ProtocolAPI
|
||||
import dev.slimevr.protocol.ProtocolAPIServer
|
||||
import dev.slimevr.protocol.rpc.RPCHandler
|
||||
import dev.slimevr.serial.SerialListener
|
||||
import dev.slimevr.serial.SerialPort
|
||||
import io.eiren.util.logging.LogManager
|
||||
import solarxr_protocol.rpc.*
|
||||
import java.util.*
|
||||
import java.util.function.Consumer
|
||||
|
||||
class RPCSerialHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) : SerialListener {
|
||||
init {
|
||||
rpcHandler.registerPacketListener(RpcMessage.SerialTrackerRebootRequest, ::onSerialTrackerRebootRequest)
|
||||
rpcHandler.registerPacketListener(RpcMessage.SerialTrackerGetInfoRequest, ::onSerialTrackerGetInfoRequest)
|
||||
rpcHandler.registerPacketListener(RpcMessage.SerialTrackerFactoryResetRequest, ::onSerialTrackerFactoryResetRequest)
|
||||
rpcHandler.registerPacketListener(RpcMessage.SerialTrackerGetWifiScanRequest, ::onSerialTrackerGetWifiScanRequest)
|
||||
rpcHandler.registerPacketListener(RpcMessage.SerialTrackerCustomCommandRequest, ::onSerialTrackerCustomCommandRequest)
|
||||
rpcHandler.registerPacketListener(RpcMessage.SetWifiRequest, ::onSetWifiRequest)
|
||||
rpcHandler.registerPacketListener(RpcMessage.OpenSerialRequest, ::onOpenSerialRequest)
|
||||
rpcHandler.registerPacketListener(RpcMessage.CloseSerialRequest, ::onCloseSerialRequest)
|
||||
rpcHandler.registerPacketListener(RpcMessage.SerialDevicesRequest, ::onRequestSerialDevices)
|
||||
this.api.server.serialHandler.addListener(this)
|
||||
}
|
||||
|
||||
override fun onSerialDisconnected() {
|
||||
val fbb = FlatBufferBuilder(32)
|
||||
|
||||
SerialUpdateResponse.startSerialUpdateResponse(fbb)
|
||||
SerialUpdateResponse.addClosed(fbb, true)
|
||||
val update = SerialUpdateResponse.endSerialUpdateResponse(fbb)
|
||||
val outbound = rpcHandler.createRPCMessage(fbb, RpcMessage.SerialUpdateResponse, update)
|
||||
fbb.finish(outbound)
|
||||
|
||||
this.forAllListeners(
|
||||
Consumer { conn: GenericConnection ->
|
||||
conn.send(fbb.dataBuffer())
|
||||
conn.context.useSerial = false
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override fun onSerialLog(str: String, server: Boolean) {
|
||||
val fbb = FlatBufferBuilder(32)
|
||||
|
||||
val logOffset = fbb.createString(str)
|
||||
|
||||
SerialUpdateResponse.startSerialUpdateResponse(fbb)
|
||||
SerialUpdateResponse.addLog(fbb, logOffset)
|
||||
val update = SerialUpdateResponse.endSerialUpdateResponse(fbb)
|
||||
val outbound = rpcHandler.createRPCMessage(fbb, RpcMessage.SerialUpdateResponse, update)
|
||||
fbb.finish(outbound)
|
||||
|
||||
this.forAllListeners(
|
||||
Consumer { conn: GenericConnection ->
|
||||
conn.send(fbb.dataBuffer())
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override fun onNewSerialDevice(port: SerialPort) {
|
||||
val fbb = FlatBufferBuilder(32)
|
||||
|
||||
val portOffset = fbb.createString(port.portLocation)
|
||||
val nameOffset = fbb.createString(port.descriptivePortName)
|
||||
val deviceOffset = SerialDevice.createSerialDevice(fbb, portOffset, nameOffset)
|
||||
val newSerialOffset = NewSerialDeviceResponse
|
||||
.createNewSerialDeviceResponse(fbb, deviceOffset)
|
||||
val outbound = rpcHandler
|
||||
.createRPCMessage(fbb, RpcMessage.NewSerialDeviceResponse, newSerialOffset)
|
||||
fbb.finish(outbound)
|
||||
|
||||
this.api
|
||||
.apiServers
|
||||
.forEach(
|
||||
Consumer { server: ProtocolAPIServer ->
|
||||
server
|
||||
.apiConnections
|
||||
.forEach { conn: GenericConnection ->
|
||||
conn.send(fbb.dataBuffer())
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override fun onSerialConnected(port: SerialPort) {
|
||||
val fbb = FlatBufferBuilder(32)
|
||||
|
||||
SerialUpdateResponse.startSerialUpdateResponse(fbb)
|
||||
SerialUpdateResponse.addClosed(fbb, false)
|
||||
val update = SerialUpdateResponse.endSerialUpdateResponse(fbb)
|
||||
val outbound = rpcHandler.createRPCMessage(fbb, RpcMessage.SerialUpdateResponse, update)
|
||||
fbb.finish(outbound)
|
||||
|
||||
this.forAllListeners(
|
||||
Consumer { conn: GenericConnection ->
|
||||
conn.send(fbb.dataBuffer())
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fun onSerialTrackerRebootRequest(
|
||||
conn: GenericConnection,
|
||||
messageHeader: RpcMessageHeader,
|
||||
) {
|
||||
val req = messageHeader
|
||||
.message(SerialTrackerRebootRequest()) as SerialTrackerRebootRequest?
|
||||
if (req == null) return
|
||||
|
||||
this.api.server.serialHandler.rebootRequest()
|
||||
}
|
||||
|
||||
fun onSerialTrackerGetInfoRequest(
|
||||
conn: GenericConnection,
|
||||
messageHeader: RpcMessageHeader,
|
||||
) {
|
||||
val req = messageHeader
|
||||
.message(SerialTrackerGetInfoRequest()) as SerialTrackerGetInfoRequest?
|
||||
if (req == null) return
|
||||
|
||||
this.api.server.serialHandler.infoRequest()
|
||||
}
|
||||
|
||||
fun onSerialTrackerFactoryResetRequest(
|
||||
conn: GenericConnection,
|
||||
messageHeader: RpcMessageHeader,
|
||||
) {
|
||||
val req = messageHeader
|
||||
.message(SerialTrackerFactoryResetRequest()) as SerialTrackerFactoryResetRequest?
|
||||
if (req == null) return
|
||||
|
||||
this.api.server.serialHandler.factoryResetRequest()
|
||||
}
|
||||
|
||||
fun onSerialTrackerGetWifiScanRequest(
|
||||
conn: GenericConnection,
|
||||
messageHeader: RpcMessageHeader,
|
||||
) {
|
||||
val req = messageHeader
|
||||
.message(SerialTrackerGetWifiScanRequest()) as SerialTrackerGetWifiScanRequest?
|
||||
if (req == null) return
|
||||
|
||||
this.api.server.serialHandler.wifiScanRequest()
|
||||
}
|
||||
|
||||
fun onSerialTrackerCustomCommandRequest(
|
||||
conn: GenericConnection,
|
||||
messageHeader: RpcMessageHeader,
|
||||
) {
|
||||
val req = messageHeader
|
||||
.message(SerialTrackerCustomCommandRequest()) as SerialTrackerCustomCommandRequest?
|
||||
|
||||
if (req == null || req.command() == null) return
|
||||
|
||||
this.api.server.serialHandler.customCommandRequest(Objects.requireNonNull(req.command()))
|
||||
}
|
||||
|
||||
private fun onRequestSerialDevices(conn: GenericConnection, messageHeader: RpcMessageHeader) {
|
||||
val req = messageHeader
|
||||
.message(SerialDevicesRequest()) as SerialDevicesRequest?
|
||||
if (req == null) return
|
||||
|
||||
val fbb = FlatBufferBuilder(32)
|
||||
|
||||
val devicesOffsets: MutableList<Int> = ArrayList()
|
||||
|
||||
try {
|
||||
this.api.server.serialHandler.knownPorts.forEach { port: SerialPort ->
|
||||
val portOffset = fbb.createString(port.portLocation)
|
||||
val nameOffset = fbb.createString(port.descriptivePortName)
|
||||
devicesOffsets.add(SerialDevice.createSerialDevice(fbb, portOffset, nameOffset))
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
LogManager.severe("Using serial ports is not supported on this platform", e)
|
||||
}
|
||||
|
||||
SerialDevicesResponse.startDevicesVector(fbb, devicesOffsets.size)
|
||||
devicesOffsets.forEach(Consumer { offset: Int -> SerialDevicesResponse.addDevices(fbb, offset) })
|
||||
val devices = fbb.endVector()
|
||||
val serialDeviceOffsets = SerialDevicesResponse.createSerialDevicesResponse(fbb, devices)
|
||||
val outbound = rpcHandler
|
||||
.createRPCMessage(fbb, RpcMessage.SerialDevicesResponse, serialDeviceOffsets)
|
||||
fbb.finish(outbound)
|
||||
conn.send(fbb.dataBuffer())
|
||||
}
|
||||
|
||||
fun onSetWifiRequest(conn: GenericConnection, messageHeader: RpcMessageHeader) {
|
||||
val req = messageHeader.message(SetWifiRequest()) as SetWifiRequest? ?: return
|
||||
|
||||
if (req.password() == null || req.ssid() == null || !this.api.server.serialHandler.isConnected) {
|
||||
return
|
||||
}
|
||||
this.api.server.serialHandler.setWifi(req.ssid(), req.password())
|
||||
}
|
||||
|
||||
fun onOpenSerialRequest(conn: GenericConnection, messageHeader: RpcMessageHeader) {
|
||||
val req =
|
||||
messageHeader.message(OpenSerialRequest()) as OpenSerialRequest? ?: return
|
||||
|
||||
conn.context.useSerial = true
|
||||
|
||||
this.api.server.queueTask {
|
||||
try {
|
||||
this.api.server.serialHandler.openSerial(req.port(), req.auto())
|
||||
} catch (e: Exception) {
|
||||
LogManager.severe("Unable to open serial port", e)
|
||||
} catch (e: Throwable) {
|
||||
LogManager.severe(
|
||||
"Using serial ports is not supported on this platform",
|
||||
e,
|
||||
)
|
||||
}
|
||||
val fbb = FlatBufferBuilder(32)
|
||||
SerialUpdateResponse.startSerialUpdateResponse(fbb)
|
||||
SerialUpdateResponse.addClosed(
|
||||
fbb,
|
||||
!this.api.server.serialHandler.isConnected,
|
||||
)
|
||||
val update = SerialUpdateResponse.endSerialUpdateResponse(fbb)
|
||||
val outbound = rpcHandler
|
||||
.createRPCMessage(fbb, RpcMessage.SerialUpdateResponse, update)
|
||||
fbb.finish(outbound)
|
||||
conn.send(fbb.dataBuffer())
|
||||
}
|
||||
}
|
||||
|
||||
fun onCloseSerialRequest(conn: GenericConnection, messageHeader: RpcMessageHeader) {
|
||||
val req = messageHeader
|
||||
.message(CloseSerialRequest()) as CloseSerialRequest?
|
||||
if (req == null) return
|
||||
|
||||
conn.context.useSerial = false
|
||||
|
||||
this.api.server.serialHandler.closeSerial()
|
||||
|
||||
val fbb = FlatBufferBuilder(32)
|
||||
SerialUpdateResponse.startSerialUpdateResponse(fbb)
|
||||
SerialUpdateResponse.addClosed(fbb, !this.api.server.serialHandler.isConnected)
|
||||
val update = SerialUpdateResponse.endSerialUpdateResponse(fbb)
|
||||
val outbound = rpcHandler.createRPCMessage(fbb, RpcMessage.SerialUpdateResponse, update)
|
||||
fbb.finish(outbound)
|
||||
conn.send(fbb.dataBuffer())
|
||||
}
|
||||
|
||||
fun forAllListeners(action: Consumer<in GenericConnection?>?) {
|
||||
this.api
|
||||
.apiServers
|
||||
.forEach(
|
||||
Consumer { server: ProtocolAPIServer ->
|
||||
server
|
||||
.apiConnections
|
||||
.filter { conn: GenericConnection -> conn.context.useSerial }
|
||||
.forEach(action)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override fun onSerialDeviceDeleted(port: SerialPort) {
|
||||
}
|
||||
}
|
||||
@@ -1,423 +0,0 @@
|
||||
package dev.slimevr.protocol.rpc.settings;
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder;
|
||||
import dev.slimevr.VRServer;
|
||||
import dev.slimevr.bridge.ISteamVRBridge;
|
||||
import dev.slimevr.config.*;
|
||||
import dev.slimevr.filtering.TrackerFilters;
|
||||
import dev.slimevr.tracking.processor.HumanPoseManager;
|
||||
import dev.slimevr.tracking.processor.config.SkeletonConfigToggles;
|
||||
import dev.slimevr.tracking.processor.config.SkeletonConfigValues;
|
||||
import dev.slimevr.tracking.trackers.TrackerRole;
|
||||
import solarxr_protocol.rpc.*;
|
||||
import solarxr_protocol.rpc.settings.*;
|
||||
|
||||
|
||||
public class RPCSettingsBuilder {
|
||||
|
||||
public static int createOSCRouterSettings(
|
||||
FlatBufferBuilder fbb,
|
||||
OSCConfig config
|
||||
) {
|
||||
int addressStringOffset = fbb.createString(config.getAddress());
|
||||
|
||||
int oscSettingOffset = OSCSettings
|
||||
.createOSCSettings(
|
||||
fbb,
|
||||
config.getEnabled(),
|
||||
config.getPortIn(),
|
||||
config.getPortOut(),
|
||||
addressStringOffset
|
||||
);
|
||||
|
||||
OSCRouterSettings.startOSCRouterSettings(fbb);
|
||||
OSCRouterSettings.addOscSettings(fbb, oscSettingOffset);
|
||||
|
||||
return OSCRouterSettings.endOSCRouterSettings(fbb);
|
||||
}
|
||||
|
||||
public static int createVRCOSCSettings(
|
||||
FlatBufferBuilder fbb,
|
||||
VRCOSCConfig config
|
||||
) {
|
||||
int addressStringOffset = fbb.createString(config.getAddress());
|
||||
int generalSettingOffset = OSCSettings
|
||||
.createOSCSettings(
|
||||
fbb,
|
||||
config.getEnabled(),
|
||||
config.getPortIn(),
|
||||
config.getPortOut(),
|
||||
addressStringOffset
|
||||
);
|
||||
int oscSettingOffset = OSCTrackersSetting
|
||||
.createOSCTrackersSetting(
|
||||
fbb,
|
||||
config.getOSCTrackerRole(TrackerRole.HEAD, false),
|
||||
config.getOSCTrackerRole(TrackerRole.CHEST, false),
|
||||
config.getOSCTrackerRole(TrackerRole.WAIST, false),
|
||||
config.getOSCTrackerRole(TrackerRole.LEFT_KNEE, false)
|
||||
&& config.getOSCTrackerRole(TrackerRole.RIGHT_KNEE, false),
|
||||
config.getOSCTrackerRole(TrackerRole.LEFT_FOOT, false)
|
||||
&& config.getOSCTrackerRole(TrackerRole.RIGHT_FOOT, false),
|
||||
config.getOSCTrackerRole(TrackerRole.LEFT_ELBOW, false)
|
||||
&& config.getOSCTrackerRole(TrackerRole.RIGHT_ELBOW, false),
|
||||
config.getOSCTrackerRole(TrackerRole.LEFT_HAND, false)
|
||||
&& config.getOSCTrackerRole(TrackerRole.RIGHT_HAND, false)
|
||||
);
|
||||
VRCOSCSettings.startVRCOSCSettings(fbb);
|
||||
VRCOSCSettings.addOscSettings(fbb, generalSettingOffset);
|
||||
VRCOSCSettings.addTrackers(fbb, oscSettingOffset);
|
||||
VRCOSCSettings.addOscqueryEnabled(fbb, config.getOscqueryEnabled());
|
||||
|
||||
return VRCOSCSettings.endVRCOSCSettings(fbb);
|
||||
}
|
||||
|
||||
public static int createVMCOSCSettings(
|
||||
FlatBufferBuilder fbb,
|
||||
VMCConfig config
|
||||
) {
|
||||
int addressStringOffset = fbb.createString(config.getAddress());
|
||||
int generalSettingOffset = OSCSettings
|
||||
.createOSCSettings(
|
||||
fbb,
|
||||
config.getEnabled(),
|
||||
config.getPortIn(),
|
||||
config.getPortOut(),
|
||||
addressStringOffset
|
||||
);
|
||||
|
||||
String vrmJson = config.getVrmJson();
|
||||
int vrmJsonOffset = 0;
|
||||
if (vrmJson != null)
|
||||
vrmJsonOffset = fbb.createString(vrmJson);
|
||||
|
||||
VMCOSCSettings.startVMCOSCSettings(fbb);
|
||||
VMCOSCSettings.addOscSettings(fbb, generalSettingOffset);
|
||||
if (vrmJson != null)
|
||||
VMCOSCSettings.addVrmJson(fbb, vrmJsonOffset);
|
||||
VMCOSCSettings.addAnchorHip(fbb, config.getAnchorHip());
|
||||
VMCOSCSettings.addMirrorTracking(fbb, config.getMirrorTracking());
|
||||
|
||||
return VMCOSCSettings.endVMCOSCSettings(fbb);
|
||||
}
|
||||
|
||||
public static int createFilterSettings(
|
||||
FlatBufferBuilder fbb,
|
||||
FiltersConfig filtersConfig
|
||||
) {
|
||||
return FilteringSettings
|
||||
.createFilteringSettings(
|
||||
fbb,
|
||||
TrackerFilters.getByConfigkey(filtersConfig.getType()).getId(),
|
||||
filtersConfig.getAmount()
|
||||
);
|
||||
}
|
||||
|
||||
public static int createDriftCompensationSettings(
|
||||
FlatBufferBuilder fbb,
|
||||
DriftCompensationConfig driftCompensationConfig
|
||||
) {
|
||||
return DriftCompensationSettings
|
||||
.createDriftCompensationSettings(
|
||||
fbb,
|
||||
driftCompensationConfig.getEnabled(),
|
||||
driftCompensationConfig.getPrediction(),
|
||||
driftCompensationConfig.getAmount(),
|
||||
driftCompensationConfig.getMaxResets()
|
||||
);
|
||||
}
|
||||
|
||||
public static int createTapDetectionSettings(
|
||||
FlatBufferBuilder fbb,
|
||||
TapDetectionConfig tapDetectionConfig
|
||||
) {
|
||||
return TapDetectionSettings
|
||||
.createTapDetectionSettings(
|
||||
fbb,
|
||||
tapDetectionConfig.getFullResetDelay(),
|
||||
tapDetectionConfig.getFullResetEnabled(),
|
||||
tapDetectionConfig.getFullResetTaps(),
|
||||
tapDetectionConfig.getYawResetDelay(),
|
||||
tapDetectionConfig.getYawResetEnabled(),
|
||||
tapDetectionConfig.getYawResetTaps(),
|
||||
tapDetectionConfig.getMountingResetDelay(),
|
||||
tapDetectionConfig.getMountingResetEnabled(),
|
||||
tapDetectionConfig.getMountingResetTaps(),
|
||||
tapDetectionConfig.getSetupMode(),
|
||||
tapDetectionConfig.getNumberTrackersOverThreshold()
|
||||
);
|
||||
}
|
||||
|
||||
public static int createSteamVRSettings(FlatBufferBuilder fbb, ISteamVRBridge bridge) {
|
||||
int steamvrTrackerSettings = 0;
|
||||
if (bridge != null) {
|
||||
steamvrTrackerSettings = SteamVRTrackersSetting
|
||||
.createSteamVRTrackersSetting(
|
||||
fbb,
|
||||
bridge.getShareSetting(TrackerRole.WAIST),
|
||||
bridge.getShareSetting(TrackerRole.CHEST),
|
||||
bridge.getAutomaticSharedTrackers(),
|
||||
|
||||
bridge.getShareSetting(TrackerRole.LEFT_FOOT),
|
||||
bridge.getShareSetting(TrackerRole.RIGHT_FOOT),
|
||||
bridge.getShareSetting(TrackerRole.LEFT_KNEE),
|
||||
bridge.getShareSetting(TrackerRole.RIGHT_KNEE),
|
||||
bridge.getShareSetting(TrackerRole.LEFT_ELBOW),
|
||||
bridge.getShareSetting(TrackerRole.RIGHT_ELBOW),
|
||||
bridge.getShareSetting(TrackerRole.LEFT_HAND),
|
||||
bridge.getShareSetting(TrackerRole.RIGHT_HAND)
|
||||
);
|
||||
}
|
||||
return steamvrTrackerSettings;
|
||||
}
|
||||
|
||||
public static int createModelSettings(
|
||||
FlatBufferBuilder fbb,
|
||||
HumanPoseManager humanPoseManager,
|
||||
LegTweaksConfig legTweaksConfig,
|
||||
SkeletonConfig skeletonConfig
|
||||
) {
|
||||
int togglesOffset = ModelToggles
|
||||
.createModelToggles(
|
||||
fbb,
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.EXTENDED_SPINE_MODEL),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.EXTENDED_PELVIS_MODEL),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.EXTENDED_KNEE_MODEL),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.FORCE_ARMS_FROM_HMD),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.FLOOR_CLIP),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.SKATING_CORRECTION),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.TOE_SNAP),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.FOOT_PLANT),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.SELF_LOCALIZATION),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.USE_POSITION),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.ENFORCE_CONSTRAINTS),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.CORRECT_CONSTRAINTS)
|
||||
);
|
||||
int ratiosOffset = ModelRatios
|
||||
.createModelRatios(
|
||||
fbb,
|
||||
humanPoseManager.getValue(SkeletonConfigValues.WAIST_FROM_CHEST_HIP_AVERAGING),
|
||||
humanPoseManager.getValue(SkeletonConfigValues.WAIST_FROM_CHEST_LEGS_AVERAGING),
|
||||
humanPoseManager.getValue(SkeletonConfigValues.HIP_FROM_CHEST_LEGS_AVERAGING),
|
||||
humanPoseManager.getValue(SkeletonConfigValues.HIP_FROM_WAIST_LEGS_AVERAGING),
|
||||
humanPoseManager.getValue(SkeletonConfigValues.HIP_LEGS_AVERAGING),
|
||||
humanPoseManager.getValue(SkeletonConfigValues.KNEE_TRACKER_ANKLE_AVERAGING),
|
||||
humanPoseManager.getValue(SkeletonConfigValues.KNEE_ANKLE_AVERAGING)
|
||||
);
|
||||
int legTweaksOffset = LegTweaksSettings
|
||||
.createLegTweaksSettings(
|
||||
fbb,
|
||||
legTweaksConfig.getCorrectionStrength()
|
||||
);
|
||||
int skeletonConfigOffset = SkeletonHeight
|
||||
.createSkeletonHeight(
|
||||
fbb,
|
||||
skeletonConfig.getHmdHeight(),
|
||||
skeletonConfig.getFloorHeight()
|
||||
);
|
||||
return ModelSettings
|
||||
.createModelSettings(
|
||||
fbb,
|
||||
togglesOffset,
|
||||
ratiosOffset,
|
||||
legTweaksOffset,
|
||||
skeletonConfigOffset
|
||||
);
|
||||
}
|
||||
|
||||
public static int createAutoBoneSettings(FlatBufferBuilder fbb, AutoBoneConfig autoBoneConfig) {
|
||||
return AutoBoneSettings
|
||||
.createAutoBoneSettings(
|
||||
fbb,
|
||||
autoBoneConfig.getCursorIncrement(),
|
||||
autoBoneConfig.getMinDataDistance(),
|
||||
autoBoneConfig.getMaxDataDistance(),
|
||||
autoBoneConfig.getNumEpochs(),
|
||||
autoBoneConfig.getPrintEveryNumEpochs(),
|
||||
autoBoneConfig.getInitialAdjustRate(),
|
||||
autoBoneConfig.getAdjustRateDecay(),
|
||||
autoBoneConfig.getSlideErrorFactor(),
|
||||
autoBoneConfig.getOffsetSlideErrorFactor(),
|
||||
autoBoneConfig.getFootHeightOffsetErrorFactor(),
|
||||
autoBoneConfig.getBodyProportionErrorFactor(),
|
||||
autoBoneConfig.getHeightErrorFactor(),
|
||||
autoBoneConfig.getPositionErrorFactor(),
|
||||
autoBoneConfig.getPositionOffsetErrorFactor(),
|
||||
autoBoneConfig.getCalcInitError(),
|
||||
autoBoneConfig.getRandomizeFrameOrder(),
|
||||
autoBoneConfig.getScaleEachStep(),
|
||||
autoBoneConfig.getSampleCount(),
|
||||
autoBoneConfig.getSampleRateMs(),
|
||||
autoBoneConfig.getSaveRecordings(),
|
||||
autoBoneConfig.getUseSkeletonHeight(),
|
||||
autoBoneConfig.getRandSeed()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes values from AutoBoneSettings to an AutoBoneConfig.
|
||||
*
|
||||
* @param autoBoneSettings The settings to read from.
|
||||
* @param autoBoneConfig The config to write to.
|
||||
* @return The autoBoneConfig parameter.
|
||||
*/
|
||||
public static AutoBoneConfig readAutoBoneSettings(
|
||||
AutoBoneSettings autoBoneSettings,
|
||||
AutoBoneConfig autoBoneConfig
|
||||
) {
|
||||
if (autoBoneSettings.hasCursorIncrement()) {
|
||||
autoBoneConfig.setCursorIncrement(autoBoneSettings.cursorIncrement());
|
||||
}
|
||||
if (autoBoneSettings.hasMinDataDistance()) {
|
||||
autoBoneConfig.setMinDataDistance(autoBoneSettings.minDataDistance());
|
||||
}
|
||||
if (autoBoneSettings.hasMaxDataDistance()) {
|
||||
autoBoneConfig.setMaxDataDistance(autoBoneSettings.maxDataDistance());
|
||||
}
|
||||
if (autoBoneSettings.hasNumEpochs()) {
|
||||
autoBoneConfig.setNumEpochs(autoBoneSettings.numEpochs());
|
||||
}
|
||||
if (autoBoneSettings.hasPrintEveryNumEpochs()) {
|
||||
autoBoneConfig.setPrintEveryNumEpochs(autoBoneSettings.printEveryNumEpochs());
|
||||
}
|
||||
if (autoBoneSettings.hasInitialAdjustRate()) {
|
||||
autoBoneConfig.setInitialAdjustRate(autoBoneSettings.initialAdjustRate());
|
||||
}
|
||||
if (autoBoneSettings.hasAdjustRateDecay()) {
|
||||
autoBoneConfig.setAdjustRateDecay(autoBoneSettings.adjustRateDecay());
|
||||
}
|
||||
if (autoBoneSettings.hasSlideErrorFactor()) {
|
||||
autoBoneConfig.setSlideErrorFactor(autoBoneSettings.slideErrorFactor());
|
||||
}
|
||||
if (autoBoneSettings.hasOffsetSlideErrorFactor()) {
|
||||
autoBoneConfig.setOffsetSlideErrorFactor(autoBoneSettings.offsetSlideErrorFactor());
|
||||
}
|
||||
if (autoBoneSettings.hasFootHeightOffsetErrorFactor()) {
|
||||
autoBoneConfig
|
||||
.setFootHeightOffsetErrorFactor(autoBoneSettings.footHeightOffsetErrorFactor());
|
||||
}
|
||||
if (autoBoneSettings.hasBodyProportionErrorFactor()) {
|
||||
autoBoneConfig
|
||||
.setBodyProportionErrorFactor(autoBoneSettings.bodyProportionErrorFactor());
|
||||
}
|
||||
if (autoBoneSettings.hasHeightErrorFactor()) {
|
||||
autoBoneConfig.setHeightErrorFactor(autoBoneSettings.heightErrorFactor());
|
||||
}
|
||||
if (autoBoneSettings.hasPositionErrorFactor()) {
|
||||
autoBoneConfig.setPositionErrorFactor(autoBoneSettings.positionErrorFactor());
|
||||
}
|
||||
if (autoBoneSettings.hasPositionOffsetErrorFactor()) {
|
||||
autoBoneConfig
|
||||
.setPositionOffsetErrorFactor(autoBoneSettings.positionOffsetErrorFactor());
|
||||
}
|
||||
if (autoBoneSettings.hasCalcInitError()) {
|
||||
autoBoneConfig.setCalcInitError(autoBoneSettings.calcInitError());
|
||||
}
|
||||
if (autoBoneSettings.hasRandomizeFrameOrder()) {
|
||||
autoBoneConfig.setRandomizeFrameOrder(autoBoneSettings.randomizeFrameOrder());
|
||||
}
|
||||
if (autoBoneSettings.hasScaleEachStep()) {
|
||||
autoBoneConfig.setScaleEachStep(autoBoneSettings.scaleEachStep());
|
||||
}
|
||||
if (autoBoneSettings.hasSampleCount()) {
|
||||
autoBoneConfig.setSampleCount(autoBoneSettings.sampleCount());
|
||||
}
|
||||
if (autoBoneSettings.hasSampleRateMs()) {
|
||||
autoBoneConfig.setSampleRateMs(autoBoneSettings.sampleRateMs());
|
||||
}
|
||||
if (autoBoneSettings.hasSaveRecordings()) {
|
||||
autoBoneConfig.setSaveRecordings(autoBoneSettings.saveRecordings());
|
||||
}
|
||||
if (autoBoneSettings.hasUseSkeletonHeight()) {
|
||||
autoBoneConfig.setUseSkeletonHeight(autoBoneSettings.useSkeletonHeight());
|
||||
}
|
||||
if (autoBoneSettings.hasRandSeed()) {
|
||||
autoBoneConfig.setRandSeed(autoBoneSettings.randSeed());
|
||||
}
|
||||
|
||||
return autoBoneConfig;
|
||||
}
|
||||
|
||||
public static int createArmsResetModeSettings(
|
||||
FlatBufferBuilder fbb,
|
||||
ResetsConfig resetsConfig
|
||||
) {
|
||||
return ResetsSettings
|
||||
.createResetsSettings(
|
||||
fbb,
|
||||
resetsConfig.getResetMountingFeet(),
|
||||
resetsConfig.getMode().getId(),
|
||||
resetsConfig.getYawResetSmoothTime(),
|
||||
resetsConfig.getSaveMountingReset(),
|
||||
resetsConfig.getResetHmdPitch()
|
||||
);
|
||||
}
|
||||
|
||||
public static int createSettingsResponse(FlatBufferBuilder fbb, VRServer server) {
|
||||
ISteamVRBridge bridge = server.getVRBridge(ISteamVRBridge.class);
|
||||
|
||||
return SettingsResponse
|
||||
.createSettingsResponse(
|
||||
fbb,
|
||||
RPCSettingsBuilder.createSteamVRSettings(fbb, bridge),
|
||||
RPCSettingsBuilder
|
||||
.createFilterSettings(
|
||||
fbb,
|
||||
server.configManager.getVrConfig().getFilters()
|
||||
),
|
||||
RPCSettingsBuilder
|
||||
.createDriftCompensationSettings(
|
||||
fbb,
|
||||
server.configManager.getVrConfig().getDriftCompensation()
|
||||
),
|
||||
RPCSettingsBuilder
|
||||
.createOSCRouterSettings(
|
||||
fbb,
|
||||
server.configManager.getVrConfig().getOscRouter()
|
||||
),
|
||||
RPCSettingsBuilder
|
||||
.createVRCOSCSettings(
|
||||
fbb,
|
||||
server.configManager.getVrConfig().getVrcOSC()
|
||||
),
|
||||
RPCSettingsBuilder
|
||||
.createVMCOSCSettings(
|
||||
fbb,
|
||||
server.configManager.getVrConfig().getVMC()
|
||||
),
|
||||
RPCSettingsBuilder
|
||||
.createModelSettings(
|
||||
fbb,
|
||||
server.humanPoseManager,
|
||||
server.configManager.getVrConfig().getLegTweaks(),
|
||||
server.configManager.getVrConfig().getSkeleton()
|
||||
),
|
||||
RPCSettingsBuilder
|
||||
.createTapDetectionSettings(
|
||||
fbb,
|
||||
server.configManager.getVrConfig().getTapDetection()
|
||||
),
|
||||
RPCSettingsBuilder
|
||||
.createAutoBoneSettings(
|
||||
fbb,
|
||||
server.configManager.getVrConfig().getAutoBone()
|
||||
),
|
||||
RPCSettingsBuilder
|
||||
.createArmsResetModeSettings(
|
||||
fbb,
|
||||
server.configManager.getVrConfig().getResetsConfig()
|
||||
),
|
||||
RPCSettingsBuilderKotlin.INSTANCE
|
||||
.createStayAlignedSettings(
|
||||
fbb,
|
||||
server.configManager.getVrConfig().getStayAlignedConfig()
|
||||
),
|
||||
RPCSettingsBuilderKotlin.INSTANCE
|
||||
.createHIDSettings(
|
||||
fbb,
|
||||
server.configManager.getVrConfig().getHidConfig()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,458 @@
|
||||
package dev.slimevr.protocol.rpc.settings
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder
|
||||
import dev.slimevr.VRServer
|
||||
import dev.slimevr.bridge.ISteamVRBridge
|
||||
import dev.slimevr.config.AutoBoneConfig
|
||||
import dev.slimevr.config.DriftCompensationConfig
|
||||
import dev.slimevr.config.FiltersConfig
|
||||
import dev.slimevr.config.HIDConfig
|
||||
import dev.slimevr.config.LegTweaksConfig
|
||||
import dev.slimevr.config.OSCConfig
|
||||
import dev.slimevr.config.ResetsConfig
|
||||
import dev.slimevr.config.SkeletonConfig
|
||||
import dev.slimevr.config.StayAlignedConfig
|
||||
import dev.slimevr.config.TapDetectionConfig
|
||||
import dev.slimevr.config.VMCConfig
|
||||
import dev.slimevr.config.VRCOSCConfig
|
||||
import dev.slimevr.filtering.TrackerFilters.Companion.getByConfigkey
|
||||
import dev.slimevr.tracking.processor.HumanPoseManager
|
||||
import dev.slimevr.tracking.processor.config.SkeletonConfigToggles
|
||||
import dev.slimevr.tracking.processor.config.SkeletonConfigValues
|
||||
import dev.slimevr.tracking.trackers.TrackerRole
|
||||
import solarxr_protocol.rpc.AutoBoneSettings
|
||||
import solarxr_protocol.rpc.DriftCompensationSettings
|
||||
import solarxr_protocol.rpc.FilteringSettings
|
||||
import solarxr_protocol.rpc.HIDSettings
|
||||
import solarxr_protocol.rpc.OSCRouterSettings
|
||||
import solarxr_protocol.rpc.OSCSettings
|
||||
import solarxr_protocol.rpc.OSCTrackersSetting
|
||||
import solarxr_protocol.rpc.ResetsSettings
|
||||
import solarxr_protocol.rpc.SettingsResponse
|
||||
import solarxr_protocol.rpc.StayAlignedSettings
|
||||
import solarxr_protocol.rpc.SteamVRTrackersSetting
|
||||
import solarxr_protocol.rpc.TapDetectionSettings
|
||||
import solarxr_protocol.rpc.VMCOSCSettings
|
||||
import solarxr_protocol.rpc.VRCOSCSettings
|
||||
import solarxr_protocol.rpc.settings.LegTweaksSettings
|
||||
import solarxr_protocol.rpc.settings.ModelRatios
|
||||
import solarxr_protocol.rpc.settings.ModelSettings
|
||||
import solarxr_protocol.rpc.settings.ModelToggles
|
||||
import solarxr_protocol.rpc.settings.SkeletonHeight
|
||||
|
||||
fun createOSCRouterSettings(
|
||||
fbb: FlatBufferBuilder,
|
||||
config: OSCConfig,
|
||||
): Int {
|
||||
val addressStringOffset = fbb.createString(config.address)
|
||||
|
||||
val oscSettingOffset = OSCSettings
|
||||
.createOSCSettings(
|
||||
fbb,
|
||||
config.enabled,
|
||||
config.portIn,
|
||||
config.portOut,
|
||||
addressStringOffset,
|
||||
)
|
||||
|
||||
OSCRouterSettings.startOSCRouterSettings(fbb)
|
||||
OSCRouterSettings.addOscSettings(fbb, oscSettingOffset)
|
||||
|
||||
return OSCRouterSettings.endOSCRouterSettings(fbb)
|
||||
}
|
||||
|
||||
fun createVRCOSCSettings(
|
||||
fbb: FlatBufferBuilder,
|
||||
config: VRCOSCConfig,
|
||||
): Int {
|
||||
val addressStringOffset = fbb.createString(config.address)
|
||||
val generalSettingOffset = OSCSettings
|
||||
.createOSCSettings(
|
||||
fbb,
|
||||
config.enabled,
|
||||
config.portIn,
|
||||
config.portOut,
|
||||
addressStringOffset,
|
||||
)
|
||||
val oscSettingOffset = OSCTrackersSetting
|
||||
.createOSCTrackersSetting(
|
||||
fbb,
|
||||
config.getOSCTrackerRole(TrackerRole.HEAD, false),
|
||||
config.getOSCTrackerRole(TrackerRole.CHEST, false),
|
||||
config.getOSCTrackerRole(TrackerRole.WAIST, false),
|
||||
config.getOSCTrackerRole(TrackerRole.LEFT_KNEE, false) &&
|
||||
config.getOSCTrackerRole(TrackerRole.RIGHT_KNEE, false),
|
||||
config.getOSCTrackerRole(TrackerRole.LEFT_FOOT, false) &&
|
||||
config.getOSCTrackerRole(TrackerRole.RIGHT_FOOT, false),
|
||||
config.getOSCTrackerRole(TrackerRole.LEFT_ELBOW, false) &&
|
||||
config.getOSCTrackerRole(TrackerRole.RIGHT_ELBOW, false),
|
||||
config.getOSCTrackerRole(TrackerRole.LEFT_HAND, false) &&
|
||||
config.getOSCTrackerRole(TrackerRole.RIGHT_HAND, false),
|
||||
)
|
||||
VRCOSCSettings.startVRCOSCSettings(fbb)
|
||||
VRCOSCSettings.addOscSettings(fbb, generalSettingOffset)
|
||||
VRCOSCSettings.addTrackers(fbb, oscSettingOffset)
|
||||
VRCOSCSettings.addOscqueryEnabled(fbb, config.oscqueryEnabled)
|
||||
|
||||
return VRCOSCSettings.endVRCOSCSettings(fbb)
|
||||
}
|
||||
|
||||
fun createVMCOSCSettings(
|
||||
fbb: FlatBufferBuilder,
|
||||
config: VMCConfig,
|
||||
): Int {
|
||||
val addressStringOffset = fbb.createString(config.address)
|
||||
val generalSettingOffset = OSCSettings
|
||||
.createOSCSettings(
|
||||
fbb,
|
||||
config.enabled,
|
||||
config.portIn,
|
||||
config.portOut,
|
||||
addressStringOffset,
|
||||
)
|
||||
|
||||
val vrmJson = config.vrmJson
|
||||
var vrmJsonOffset = 0
|
||||
if (vrmJson != null) vrmJsonOffset = fbb.createString(vrmJson)
|
||||
|
||||
VMCOSCSettings.startVMCOSCSettings(fbb)
|
||||
VMCOSCSettings.addOscSettings(fbb, generalSettingOffset)
|
||||
if (vrmJson != null) VMCOSCSettings.addVrmJson(fbb, vrmJsonOffset)
|
||||
VMCOSCSettings.addAnchorHip(fbb, config.anchorHip)
|
||||
VMCOSCSettings.addMirrorTracking(fbb, config.mirrorTracking)
|
||||
|
||||
return VMCOSCSettings.endVMCOSCSettings(fbb)
|
||||
}
|
||||
|
||||
fun createFilterSettings(
|
||||
fbb: FlatBufferBuilder,
|
||||
filtersConfig: FiltersConfig,
|
||||
): Int = FilteringSettings
|
||||
.createFilteringSettings(
|
||||
fbb,
|
||||
getByConfigkey(filtersConfig.type)!!.id,
|
||||
filtersConfig.amount,
|
||||
)
|
||||
|
||||
fun createDriftCompensationSettings(
|
||||
fbb: FlatBufferBuilder,
|
||||
driftCompensationConfig: DriftCompensationConfig,
|
||||
): Int = DriftCompensationSettings
|
||||
.createDriftCompensationSettings(
|
||||
fbb,
|
||||
driftCompensationConfig.enabled,
|
||||
driftCompensationConfig.prediction,
|
||||
driftCompensationConfig.amount,
|
||||
driftCompensationConfig.maxResets,
|
||||
)
|
||||
|
||||
fun createTapDetectionSettings(
|
||||
fbb: FlatBufferBuilder,
|
||||
tapDetectionConfig: TapDetectionConfig,
|
||||
): Int = TapDetectionSettings
|
||||
.createTapDetectionSettings(
|
||||
fbb,
|
||||
tapDetectionConfig.fullResetDelay,
|
||||
tapDetectionConfig.fullResetEnabled,
|
||||
tapDetectionConfig.fullResetTaps,
|
||||
tapDetectionConfig.yawResetDelay,
|
||||
tapDetectionConfig.yawResetEnabled,
|
||||
tapDetectionConfig.yawResetTaps,
|
||||
tapDetectionConfig.mountingResetDelay,
|
||||
tapDetectionConfig.mountingResetEnabled,
|
||||
tapDetectionConfig.mountingResetTaps,
|
||||
tapDetectionConfig.setupMode,
|
||||
tapDetectionConfig.numberTrackersOverThreshold,
|
||||
)
|
||||
|
||||
fun createSteamVRSettings(fbb: FlatBufferBuilder, bridge: ISteamVRBridge?): Int {
|
||||
var steamvrTrackerSettings = 0
|
||||
if (bridge != null) {
|
||||
steamvrTrackerSettings = SteamVRTrackersSetting
|
||||
.createSteamVRTrackersSetting(
|
||||
fbb,
|
||||
bridge.getShareSetting(TrackerRole.WAIST),
|
||||
bridge.getShareSetting(TrackerRole.CHEST),
|
||||
bridge.getAutomaticSharedTrackers(),
|
||||
|
||||
bridge.getShareSetting(TrackerRole.LEFT_FOOT),
|
||||
bridge.getShareSetting(TrackerRole.RIGHT_FOOT),
|
||||
bridge.getShareSetting(TrackerRole.LEFT_KNEE),
|
||||
bridge.getShareSetting(TrackerRole.RIGHT_KNEE),
|
||||
bridge.getShareSetting(TrackerRole.LEFT_ELBOW),
|
||||
bridge.getShareSetting(TrackerRole.RIGHT_ELBOW),
|
||||
bridge.getShareSetting(TrackerRole.LEFT_HAND),
|
||||
bridge.getShareSetting(TrackerRole.RIGHT_HAND),
|
||||
)
|
||||
}
|
||||
return steamvrTrackerSettings
|
||||
}
|
||||
|
||||
fun createModelSettings(
|
||||
fbb: FlatBufferBuilder,
|
||||
humanPoseManager: HumanPoseManager,
|
||||
legTweaksConfig: LegTweaksConfig,
|
||||
skeletonConfig: SkeletonConfig,
|
||||
): Int {
|
||||
val togglesOffset = ModelToggles
|
||||
.createModelToggles(
|
||||
fbb,
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.EXTENDED_SPINE_MODEL),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.EXTENDED_PELVIS_MODEL),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.EXTENDED_KNEE_MODEL),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.FORCE_ARMS_FROM_HMD),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.FLOOR_CLIP),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.SKATING_CORRECTION),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.TOE_SNAP),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.FOOT_PLANT),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.SELF_LOCALIZATION),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.USE_POSITION),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.ENFORCE_CONSTRAINTS),
|
||||
humanPoseManager.getToggle(SkeletonConfigToggles.CORRECT_CONSTRAINTS),
|
||||
)
|
||||
val ratiosOffset = ModelRatios
|
||||
.createModelRatios(
|
||||
fbb,
|
||||
humanPoseManager.getValue(SkeletonConfigValues.WAIST_FROM_CHEST_HIP_AVERAGING),
|
||||
humanPoseManager.getValue(SkeletonConfigValues.WAIST_FROM_CHEST_LEGS_AVERAGING),
|
||||
humanPoseManager.getValue(SkeletonConfigValues.HIP_FROM_CHEST_LEGS_AVERAGING),
|
||||
humanPoseManager.getValue(SkeletonConfigValues.HIP_FROM_WAIST_LEGS_AVERAGING),
|
||||
humanPoseManager.getValue(SkeletonConfigValues.HIP_LEGS_AVERAGING),
|
||||
humanPoseManager.getValue(SkeletonConfigValues.KNEE_TRACKER_ANKLE_AVERAGING),
|
||||
humanPoseManager.getValue(SkeletonConfigValues.KNEE_ANKLE_AVERAGING),
|
||||
)
|
||||
val legTweaksOffset = LegTweaksSettings
|
||||
.createLegTweaksSettings(
|
||||
fbb,
|
||||
legTweaksConfig.correctionStrength,
|
||||
)
|
||||
val skeletonConfigOffset = SkeletonHeight
|
||||
.createSkeletonHeight(
|
||||
fbb,
|
||||
skeletonConfig.hmdHeight,
|
||||
skeletonConfig.floorHeight,
|
||||
)
|
||||
return ModelSettings
|
||||
.createModelSettings(
|
||||
fbb,
|
||||
togglesOffset,
|
||||
ratiosOffset,
|
||||
legTweaksOffset,
|
||||
skeletonConfigOffset,
|
||||
)
|
||||
}
|
||||
|
||||
fun createAutoBoneSettings(
|
||||
fbb: FlatBufferBuilder,
|
||||
autoBoneConfig: AutoBoneConfig,
|
||||
): Int = AutoBoneSettings
|
||||
.createAutoBoneSettings(
|
||||
fbb,
|
||||
autoBoneConfig.cursorIncrement,
|
||||
autoBoneConfig.minDataDistance,
|
||||
autoBoneConfig.maxDataDistance,
|
||||
autoBoneConfig.numEpochs,
|
||||
autoBoneConfig.printEveryNumEpochs,
|
||||
autoBoneConfig.initialAdjustRate,
|
||||
autoBoneConfig.adjustRateDecay,
|
||||
autoBoneConfig.slideErrorFactor,
|
||||
autoBoneConfig.offsetSlideErrorFactor,
|
||||
autoBoneConfig.footHeightOffsetErrorFactor,
|
||||
autoBoneConfig.bodyProportionErrorFactor,
|
||||
autoBoneConfig.heightErrorFactor,
|
||||
autoBoneConfig.positionErrorFactor,
|
||||
autoBoneConfig.positionOffsetErrorFactor,
|
||||
autoBoneConfig.calcInitError,
|
||||
autoBoneConfig.randomizeFrameOrder,
|
||||
autoBoneConfig.scaleEachStep,
|
||||
autoBoneConfig.sampleCount,
|
||||
autoBoneConfig.sampleRateMs,
|
||||
autoBoneConfig.saveRecordings,
|
||||
autoBoneConfig.useSkeletonHeight,
|
||||
autoBoneConfig.randSeed,
|
||||
)
|
||||
|
||||
/**
|
||||
* Writes values from AutoBoneSettings to an AutoBoneConfig.
|
||||
*
|
||||
* @param autoBoneSettings The settings to read from.
|
||||
* @param autoBoneConfig The config to write to.
|
||||
* @return The autoBoneConfig parameter.
|
||||
*/
|
||||
fun readAutoBoneSettings(
|
||||
autoBoneSettings: AutoBoneSettings,
|
||||
autoBoneConfig: AutoBoneConfig,
|
||||
): AutoBoneConfig {
|
||||
if (autoBoneSettings.hasCursorIncrement()) {
|
||||
autoBoneConfig.cursorIncrement = autoBoneSettings.cursorIncrement()
|
||||
}
|
||||
if (autoBoneSettings.hasMinDataDistance()) {
|
||||
autoBoneConfig.minDataDistance = autoBoneSettings.minDataDistance()
|
||||
}
|
||||
if (autoBoneSettings.hasMaxDataDistance()) {
|
||||
autoBoneConfig.maxDataDistance = autoBoneSettings.maxDataDistance()
|
||||
}
|
||||
if (autoBoneSettings.hasNumEpochs()) {
|
||||
autoBoneConfig.numEpochs = autoBoneSettings.numEpochs()
|
||||
}
|
||||
if (autoBoneSettings.hasPrintEveryNumEpochs()) {
|
||||
autoBoneConfig.printEveryNumEpochs = autoBoneSettings.printEveryNumEpochs()
|
||||
}
|
||||
if (autoBoneSettings.hasInitialAdjustRate()) {
|
||||
autoBoneConfig.initialAdjustRate = autoBoneSettings.initialAdjustRate()
|
||||
}
|
||||
if (autoBoneSettings.hasAdjustRateDecay()) {
|
||||
autoBoneConfig.adjustRateDecay = autoBoneSettings.adjustRateDecay()
|
||||
}
|
||||
if (autoBoneSettings.hasSlideErrorFactor()) {
|
||||
autoBoneConfig.slideErrorFactor = autoBoneSettings.slideErrorFactor()
|
||||
}
|
||||
if (autoBoneSettings.hasOffsetSlideErrorFactor()) {
|
||||
autoBoneConfig.offsetSlideErrorFactor =
|
||||
autoBoneSettings.offsetSlideErrorFactor()
|
||||
}
|
||||
if (autoBoneSettings.hasFootHeightOffsetErrorFactor()) {
|
||||
autoBoneConfig
|
||||
.footHeightOffsetErrorFactor =
|
||||
autoBoneSettings.footHeightOffsetErrorFactor()
|
||||
}
|
||||
if (autoBoneSettings.hasBodyProportionErrorFactor()) {
|
||||
autoBoneConfig
|
||||
.bodyProportionErrorFactor = autoBoneSettings.bodyProportionErrorFactor()
|
||||
}
|
||||
if (autoBoneSettings.hasHeightErrorFactor()) {
|
||||
autoBoneConfig.heightErrorFactor = autoBoneSettings.heightErrorFactor()
|
||||
}
|
||||
if (autoBoneSettings.hasPositionErrorFactor()) {
|
||||
autoBoneConfig.positionErrorFactor = autoBoneSettings.positionErrorFactor()
|
||||
}
|
||||
if (autoBoneSettings.hasPositionOffsetErrorFactor()) {
|
||||
autoBoneConfig
|
||||
.positionOffsetErrorFactor = autoBoneSettings.positionOffsetErrorFactor()
|
||||
}
|
||||
if (autoBoneSettings.hasCalcInitError()) {
|
||||
autoBoneConfig.calcInitError = autoBoneSettings.calcInitError()
|
||||
}
|
||||
if (autoBoneSettings.hasRandomizeFrameOrder()) {
|
||||
autoBoneConfig.randomizeFrameOrder = autoBoneSettings.randomizeFrameOrder()
|
||||
}
|
||||
if (autoBoneSettings.hasScaleEachStep()) {
|
||||
autoBoneConfig.scaleEachStep = autoBoneSettings.scaleEachStep()
|
||||
}
|
||||
if (autoBoneSettings.hasSampleCount()) {
|
||||
autoBoneConfig.sampleCount = autoBoneSettings.sampleCount()
|
||||
}
|
||||
if (autoBoneSettings.hasSampleRateMs()) {
|
||||
autoBoneConfig.sampleRateMs = autoBoneSettings.sampleRateMs()
|
||||
}
|
||||
if (autoBoneSettings.hasSaveRecordings()) {
|
||||
autoBoneConfig.saveRecordings = autoBoneSettings.saveRecordings()
|
||||
}
|
||||
if (autoBoneSettings.hasUseSkeletonHeight()) {
|
||||
autoBoneConfig.useSkeletonHeight = autoBoneSettings.useSkeletonHeight()
|
||||
}
|
||||
if (autoBoneSettings.hasRandSeed()) {
|
||||
autoBoneConfig.randSeed = autoBoneSettings.randSeed()
|
||||
}
|
||||
|
||||
return autoBoneConfig
|
||||
}
|
||||
|
||||
fun createArmsResetModeSettings(
|
||||
fbb: FlatBufferBuilder,
|
||||
resetsConfig: ResetsConfig,
|
||||
): Int = ResetsSettings
|
||||
.createResetsSettings(
|
||||
fbb,
|
||||
resetsConfig.resetMountingFeet,
|
||||
resetsConfig.mode.id,
|
||||
resetsConfig.yawResetSmoothTime,
|
||||
resetsConfig.saveMountingReset,
|
||||
resetsConfig.resetHmdPitch,
|
||||
)
|
||||
|
||||
fun createSettingsResponse(fbb: FlatBufferBuilder, server: VRServer): Int {
|
||||
val bridge = server.getVRBridge(ISteamVRBridge::class.java)
|
||||
|
||||
return SettingsResponse
|
||||
.createSettingsResponse(
|
||||
fbb,
|
||||
createSteamVRSettings(fbb, bridge),
|
||||
createFilterSettings(
|
||||
fbb,
|
||||
server.configManager.vrConfig.filters,
|
||||
),
|
||||
createDriftCompensationSettings(
|
||||
fbb,
|
||||
server.configManager.vrConfig.driftCompensation,
|
||||
),
|
||||
createOSCRouterSettings(
|
||||
fbb,
|
||||
server.configManager.vrConfig.oscRouter,
|
||||
),
|
||||
createVRCOSCSettings(
|
||||
fbb,
|
||||
server.configManager.vrConfig.vrcOSC,
|
||||
),
|
||||
createVMCOSCSettings(
|
||||
fbb,
|
||||
server.configManager.vrConfig.vmc,
|
||||
),
|
||||
createModelSettings(
|
||||
fbb,
|
||||
server.humanPoseManager,
|
||||
server.configManager.vrConfig.legTweaks,
|
||||
server.configManager.vrConfig.skeleton,
|
||||
),
|
||||
createTapDetectionSettings(
|
||||
fbb,
|
||||
server.configManager.vrConfig.tapDetection,
|
||||
),
|
||||
createAutoBoneSettings(
|
||||
fbb,
|
||||
server.configManager.vrConfig.autoBone,
|
||||
),
|
||||
createArmsResetModeSettings(
|
||||
fbb,
|
||||
server.configManager.vrConfig.resetsConfig,
|
||||
),
|
||||
createStayAlignedSettings(
|
||||
fbb,
|
||||
server.configManager.vrConfig.stayAlignedConfig,
|
||||
),
|
||||
createHIDSettings(fbb, server.configManager.vrConfig.hidConfig),
|
||||
)
|
||||
}
|
||||
|
||||
fun createStayAlignedSettings(
|
||||
fbb: FlatBufferBuilder,
|
||||
config: StayAlignedConfig,
|
||||
): Int = StayAlignedSettings
|
||||
.createStayAlignedSettings(
|
||||
fbb,
|
||||
config.enabled,
|
||||
false, // deprecated
|
||||
config.hideYawCorrection,
|
||||
config.standingRelaxedPose.enabled,
|
||||
config.standingRelaxedPose.upperLegAngleInDeg,
|
||||
config.standingRelaxedPose.lowerLegAngleInDeg,
|
||||
config.standingRelaxedPose.footAngleInDeg,
|
||||
config.sittingRelaxedPose.enabled,
|
||||
config.sittingRelaxedPose.upperLegAngleInDeg,
|
||||
config.sittingRelaxedPose.lowerLegAngleInDeg,
|
||||
config.sittingRelaxedPose.footAngleInDeg,
|
||||
config.flatRelaxedPose.enabled,
|
||||
config.flatRelaxedPose.upperLegAngleInDeg,
|
||||
config.flatRelaxedPose.lowerLegAngleInDeg,
|
||||
config.flatRelaxedPose.footAngleInDeg,
|
||||
config.setupComplete,
|
||||
)
|
||||
|
||||
fun createHIDSettings(
|
||||
fbb: FlatBufferBuilder,
|
||||
config: HIDConfig,
|
||||
): Int = HIDSettings
|
||||
.createHIDSettings(
|
||||
fbb,
|
||||
config.trackersOverHID,
|
||||
)
|
||||
@@ -1,43 +0,0 @@
|
||||
package dev.slimevr.protocol.rpc.settings
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder
|
||||
import dev.slimevr.config.HIDConfig
|
||||
import dev.slimevr.config.StayAlignedConfig
|
||||
import solarxr_protocol.rpc.HIDSettings
|
||||
import solarxr_protocol.rpc.StayAlignedSettings
|
||||
|
||||
object RPCSettingsBuilderKotlin {
|
||||
|
||||
fun createStayAlignedSettings(
|
||||
fbb: FlatBufferBuilder,
|
||||
config: StayAlignedConfig,
|
||||
): Int = StayAlignedSettings
|
||||
.createStayAlignedSettings(
|
||||
fbb,
|
||||
config.enabled,
|
||||
false, // deprecated
|
||||
config.hideYawCorrection,
|
||||
config.standingRelaxedPose.enabled,
|
||||
config.standingRelaxedPose.upperLegAngleInDeg,
|
||||
config.standingRelaxedPose.lowerLegAngleInDeg,
|
||||
config.standingRelaxedPose.footAngleInDeg,
|
||||
config.sittingRelaxedPose.enabled,
|
||||
config.sittingRelaxedPose.upperLegAngleInDeg,
|
||||
config.sittingRelaxedPose.lowerLegAngleInDeg,
|
||||
config.sittingRelaxedPose.footAngleInDeg,
|
||||
config.flatRelaxedPose.enabled,
|
||||
config.flatRelaxedPose.upperLegAngleInDeg,
|
||||
config.flatRelaxedPose.lowerLegAngleInDeg,
|
||||
config.flatRelaxedPose.footAngleInDeg,
|
||||
config.setupComplete,
|
||||
)
|
||||
|
||||
fun createHIDSettings(
|
||||
fbb: FlatBufferBuilder,
|
||||
config: HIDConfig,
|
||||
): Int = HIDSettings
|
||||
.createHIDSettings(
|
||||
fbb,
|
||||
config.trackersOverHID,
|
||||
)
|
||||
}
|
||||
@@ -18,24 +18,9 @@ import kotlin.math.*
|
||||
|
||||
class RPCSettingsHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) {
|
||||
init {
|
||||
rpcHandler.registerPacketListener(RpcMessage.SettingsRequest) { conn: GenericConnection, messageHeader: RpcMessageHeader? ->
|
||||
this.onSettingsRequest(
|
||||
conn,
|
||||
messageHeader,
|
||||
)
|
||||
}
|
||||
rpcHandler
|
||||
.registerPacketListener(
|
||||
RpcMessage.ChangeSettingsRequest,
|
||||
) { conn: GenericConnection?, messageHeader: RpcMessageHeader ->
|
||||
this.onChangeSettingsRequest(
|
||||
conn,
|
||||
messageHeader,
|
||||
)
|
||||
}
|
||||
rpcHandler.registerPacketListener(RpcMessage.SettingsResetRequest) { conn: GenericConnection, messageHeader: RpcMessageHeader? ->
|
||||
this.onSettingsResetRequest(conn, messageHeader)
|
||||
}
|
||||
rpcHandler.registerPacketListener(RpcMessage.SettingsRequest, ::onSettingsRequest)
|
||||
rpcHandler.registerPacketListener(RpcMessage.ChangeSettingsRequest, ::onChangeSettingsRequest)
|
||||
rpcHandler.registerPacketListener(RpcMessage.SettingsResetRequest, ::onSettingsResetRequest)
|
||||
}
|
||||
|
||||
fun onSettingsRequest(conn: GenericConnection, messageHeader: RpcMessageHeader?) {
|
||||
@@ -331,7 +316,7 @@ class RPCSettingsHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) {
|
||||
.vrConfig
|
||||
.autoBone
|
||||
|
||||
RPCSettingsBuilder.readAutoBoneSettings(autoBoneSettings, autoBoneConfig)
|
||||
readAutoBoneSettings(autoBoneSettings, autoBoneConfig)
|
||||
}
|
||||
|
||||
if (req.resetsSettings() != null) {
|
||||
@@ -391,7 +376,7 @@ class RPCSettingsHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) {
|
||||
val settings = SettingsResponse
|
||||
.createSettingsResponse(
|
||||
fbb,
|
||||
RPCSettingsBuilder.createSteamVRSettings(fbb, bridge), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
createSteamVRSettings(fbb, bridge), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
)
|
||||
val outbound =
|
||||
rpcHandler.createRPCMessage(fbb, RpcMessage.SettingsResponse, settings)
|
||||
|
||||
@@ -3,7 +3,7 @@ package dev.slimevr.protocol.rpc.setup
|
||||
import com.google.flatbuffers.FlatBufferBuilder
|
||||
import dev.slimevr.protocol.GenericConnection
|
||||
import dev.slimevr.protocol.ProtocolAPI
|
||||
import dev.slimevr.protocol.datafeed.DataFeedBuilder
|
||||
import dev.slimevr.protocol.datafeed.createTrackerId
|
||||
import dev.slimevr.protocol.rpc.RPCHandler
|
||||
import dev.slimevr.setup.TapSetupListener
|
||||
import dev.slimevr.tracking.trackers.Tracker
|
||||
@@ -20,7 +20,7 @@ class RPCTapSetupHandler(
|
||||
|
||||
override fun onStarted(tracker: Tracker) {
|
||||
val fbb = FlatBufferBuilder(32)
|
||||
val idOffset = DataFeedBuilder.createTrackerId(fbb, tracker)
|
||||
val idOffset = createTrackerId(fbb, tracker)
|
||||
val update = TapDetectionSetupNotification.createTapDetectionSetupNotification(fbb, idOffset)
|
||||
val outbound =
|
||||
rpcHandler.createRPCMessage(fbb, RpcMessage.TapDetectionSetupNotification, update)
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.java_websocket.WebSocket;
|
||||
import org.java_websocket.drafts.Draft_6455;
|
||||
import org.java_websocket.handshake.ClientHandshake;
|
||||
import org.java_websocket.server.WebSocketServer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -101,7 +102,7 @@ public class WebsocketAPI extends WebSocketServer implements ProtocolAPIServer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<GenericConnection> getAPIConnections() {
|
||||
public @NotNull Stream<GenericConnection> getApiConnections() {
|
||||
return this.getConnections().stream().map(conn -> {
|
||||
var c = conn.<WebsocketConnection>getAttachment();
|
||||
return (GenericConnection) c;
|
||||
|
||||
@@ -141,7 +141,7 @@ public class UnixSocketRpcBridge implements dev.slimevr.bridge.Bridge,
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.stream.Stream<GenericConnection> getAPIConnections() {
|
||||
public java.util.stream.Stream<GenericConnection> getApiConnections() {
|
||||
return this.selector
|
||||
.keys()
|
||||
.stream()
|
||||
|
||||
Reference in New Issue
Block a user