mirror of
https://github.com/SlimeVR/SlimeVR-Server.git
synced 2026-04-06 02:01:58 +02:00
Solaxr datafeed out
This commit is contained in:
@@ -39,6 +39,5 @@ fun <S, A> createContext(
|
||||
}
|
||||
}
|
||||
val context = Context(mutableStateFlow.asStateFlow(), dispatch, dispatchAll, scope)
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ object AppLogger {
|
||||
val tracker = logger("Tracker")
|
||||
val device = logger("Device")
|
||||
val udp = logger("UDPConnection")
|
||||
val solarxr = logger("SolarXR")
|
||||
|
||||
|
||||
init {
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
package dev.slimevr.skeleton
|
||||
|
||||
enum class BodyPart(val id: UByte) {
|
||||
HEAD(solarxr_protocol.datatypes.BodyPart.HEAD),
|
||||
NECK(solarxr_protocol.datatypes.BodyPart.NECK),
|
||||
UPPER_CHEST(solarxr_protocol.datatypes.BodyPart.UPPERCHEST),
|
||||
CHEST(solarxr_protocol.datatypes.BodyPart.CHEST),
|
||||
WAIST(solarxr_protocol.datatypes.BodyPart.WAIST),
|
||||
HIP(solarxr_protocol.datatypes.BodyPart.HIP),
|
||||
LEFT_HIP(solarxr_protocol.datatypes.BodyPart.LEFTHIP),
|
||||
RIGHT_HIP(solarxr_protocol.datatypes.BodyPart.RIGHTHIP),
|
||||
LEFT_UPPER_LEG(solarxr_protocol.datatypes.BodyPart.LEFTUPPERLEG),
|
||||
RIGHT_UPPER_LEG(solarxr_protocol.datatypes.BodyPart.RIGHTUPPERLEG),
|
||||
LEFT_LOWER_LEG(solarxr_protocol.datatypes.BodyPart.LEFTLOWERLEG),
|
||||
RIGHT_LOWER_LEG(solarxr_protocol.datatypes.BodyPart.RIGHTLOWERLEG),
|
||||
LEFT_FOOT(solarxr_protocol.datatypes.BodyPart.LEFTFOOT),
|
||||
RIGHT_FOOT(solarxr_protocol.datatypes.BodyPart.RIGHTFOOT),
|
||||
LEFT_FOOT_TRACKER(solarxr_protocol.datatypes.BodyPart.LEFTFOOT),
|
||||
RIGHT_FOOT_TRACKER(solarxr_protocol.datatypes.BodyPart.RIGHTFOOT),
|
||||
LEFT_LOWER_ARM(solarxr_protocol.datatypes.BodyPart.LEFTLOWERARM),
|
||||
RIGHT_LOWER_ARM(solarxr_protocol.datatypes.BodyPart.RIGHTLOWERARM),
|
||||
LEFT_UPPER_ARM(solarxr_protocol.datatypes.BodyPart.LEFTUPPERARM),
|
||||
RIGHT_UPPER_ARM(solarxr_protocol.datatypes.BodyPart.RIGHTUPPERARM),
|
||||
LEFT_SHOULDER(solarxr_protocol.datatypes.BodyPart.LEFTSHOULDER),
|
||||
RIGHT_SHOULDER(solarxr_protocol.datatypes.BodyPart.RIGHTSHOULDER),
|
||||
LEFT_HAND(solarxr_protocol.datatypes.BodyPart.LEFTHAND),
|
||||
RIGHT_HAND(solarxr_protocol.datatypes.BodyPart.RIGHTHAND),
|
||||
LEFT_THUMB_METACARPAL(solarxr_protocol.datatypes.BodyPart.LEFTTHUMBMETACARPAL),
|
||||
LEFT_THUMB_PROXIMAL(solarxr_protocol.datatypes.BodyPart.LEFTTHUMBPROXIMAL),
|
||||
LEFT_THUMB_DISTAL(solarxr_protocol.datatypes.BodyPart.LEFTTHUMBDISTAL),
|
||||
LEFT_INDEX_PROXIMAL(solarxr_protocol.datatypes.BodyPart.LEFTINDEXPROXIMAL),
|
||||
LEFT_INDEX_INTERMEDIATE(solarxr_protocol.datatypes.BodyPart.LEFTINDEXINTERMEDIATE),
|
||||
LEFT_INDEX_DISTAL(solarxr_protocol.datatypes.BodyPart.LEFTINDEXDISTAL),
|
||||
LEFT_MIDDLE_PROXIMAL(solarxr_protocol.datatypes.BodyPart.LEFTMIDDLEPROXIMAL),
|
||||
LEFT_MIDDLE_INTERMEDIATE(solarxr_protocol.datatypes.BodyPart.LEFTMIDDLEINTERMEDIATE),
|
||||
LEFT_MIDDLE_DISTAL(solarxr_protocol.datatypes.BodyPart.LEFTMIDDLEDISTAL),
|
||||
LEFT_RING_PROXIMAL(solarxr_protocol.datatypes.BodyPart.LEFTRINGPROXIMAL),
|
||||
LEFT_RING_INTERMEDIATE(solarxr_protocol.datatypes.BodyPart.LEFTRINGINTERMEDIATE),
|
||||
LEFT_RING_DISTAL(solarxr_protocol.datatypes.BodyPart.LEFTRINGDISTAL),
|
||||
LEFT_LITTLE_PROXIMAL(solarxr_protocol.datatypes.BodyPart.LEFTLITTLEPROXIMAL),
|
||||
LEFT_LITTLE_INTERMEDIATE(solarxr_protocol.datatypes.BodyPart.LEFTLITTLEINTERMEDIATE),
|
||||
LEFT_LITTLE_DISTAL(solarxr_protocol.datatypes.BodyPart.LEFTLITTLEDISTAL),
|
||||
RIGHT_THUMB_METACARPAL(solarxr_protocol.datatypes.BodyPart.RIGHTTHUMBMETACARPAL),
|
||||
RIGHT_THUMB_PROXIMAL(solarxr_protocol.datatypes.BodyPart.RIGHTTHUMBPROXIMAL),
|
||||
RIGHT_THUMB_DISTAL(solarxr_protocol.datatypes.BodyPart.RIGHTTHUMBDISTAL),
|
||||
RIGHT_INDEX_PROXIMAL(solarxr_protocol.datatypes.BodyPart.RIGHTINDEXPROXIMAL),
|
||||
RIGHT_INDEX_INTERMEDIATE(solarxr_protocol.datatypes.BodyPart.RIGHTINDEXINTERMEDIATE),
|
||||
RIGHT_INDEX_DISTAL(solarxr_protocol.datatypes.BodyPart.RIGHTINDEXDISTAL),
|
||||
RIGHT_MIDDLE_PROXIMAL(solarxr_protocol.datatypes.BodyPart.RIGHTMIDDLEPROXIMAL),
|
||||
RIGHT_MIDDLE_INTERMEDIATE(solarxr_protocol.datatypes.BodyPart.RIGHTMIDDLEINTERMEDIATE),
|
||||
RIGHT_MIDDLE_DISTAL(solarxr_protocol.datatypes.BodyPart.RIGHTMIDDLEDISTAL),
|
||||
RIGHT_RING_PROXIMAL(solarxr_protocol.datatypes.BodyPart.RIGHTRINGPROXIMAL),
|
||||
RIGHT_RING_INTERMEDIATE(solarxr_protocol.datatypes.BodyPart.RIGHTRINGINTERMEDIATE),
|
||||
RIGHT_RING_DISTAL(solarxr_protocol.datatypes.BodyPart.RIGHTRINGDISTAL),
|
||||
RIGHT_LITTLE_PROXIMAL(solarxr_protocol.datatypes.BodyPart.RIGHTLITTLEPROXIMAL),
|
||||
RIGHT_LITTLE_INTERMEDIATE(solarxr_protocol.datatypes.BodyPart.RIGHTLITTLEINTERMEDIATE),
|
||||
RIGHT_LITTLE_DISTAL(solarxr_protocol.datatypes.BodyPart.RIGHTLITTLEDISTAL);
|
||||
|
||||
companion object {
|
||||
private val map = entries.associateBy { it.id }
|
||||
fun fromId(id: UByte) = map[id]
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package dev.slimevr.solarxr
|
||||
|
||||
import dev.slimevr.AppLogger
|
||||
import dev.slimevr.VRServer
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.engine.embeddedServer
|
||||
import io.ktor.server.netty.Netty
|
||||
@@ -7,47 +9,54 @@ import io.ktor.server.routing.routing
|
||||
import io.ktor.server.websocket.*
|
||||
import io.ktor.websocket.Frame
|
||||
import io.ktor.websocket.readBytes
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import solarxr_protocol.MessageBundle
|
||||
import java.nio.ByteBuffer
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
const val SOLARXR_PORT = 21110;
|
||||
|
||||
fun onSolarXRMessage(message: ByteBuffer) {
|
||||
val messageBundle = MessageBundle.getRootAsMessageBundle(message)
|
||||
const val SOLARXR_PORT = 21110
|
||||
|
||||
|
||||
for (index in 0..<messageBundle.dataFeedMsgsLength) {
|
||||
val header = messageBundle.dataFeedMsgs(index) ?: error("WIERD?")
|
||||
println("HEADER: ${header.message()}")
|
||||
// this.dataFeedHandler.onMessage(conn, header)
|
||||
suspend fun onSolarXRMessage(message: ByteBuffer, context: SolarXRConnection) {
|
||||
val messageBundle = MessageBundle.fromByteBuffer(message)
|
||||
|
||||
messageBundle.dataFeedMsgs?.forEach {
|
||||
val msg = it.message ?: return;
|
||||
context.dataFeedDispatcher.emit(msg)
|
||||
}
|
||||
|
||||
for (index in 0..<messageBundle.rpcMsgsLength) {
|
||||
val header = messageBundle.rpcMsgs(index)
|
||||
// this.rpcHandler.onMessage(conn, header)
|
||||
}
|
||||
|
||||
for (index in 0..<messageBundle.pubSubMsgsLength) {
|
||||
val header = messageBundle.pubSubMsgs(index)
|
||||
// this.pubSubHandler.onMessage(conn, header)
|
||||
messageBundle.rpcMsgs?.forEach {
|
||||
val msg = it.message ?: return;
|
||||
context.rpcDispatcher.emit(msg)
|
||||
}
|
||||
}
|
||||
|
||||
fun createSolarXRWebsocketServer() {
|
||||
|
||||
fun createSolarXRWebsocketServer(serverContext: VRServer) {
|
||||
embeddedServer(Netty, port = SOLARXR_PORT) {
|
||||
install(WebSockets)
|
||||
|
||||
routing {
|
||||
webSocket {
|
||||
println("Client Connected!")
|
||||
|
||||
val solarxrConnection =
|
||||
createSolarXRConnection(serverContext, scope = this, onSend = {
|
||||
send(Frame.Binary(fin = true, data = it))
|
||||
})
|
||||
|
||||
for (frame in incoming) {
|
||||
when (frame) {
|
||||
is Frame.Binary -> {
|
||||
val data = frame.readBytes()
|
||||
onSolarXRMessage(frame.buffer)
|
||||
println("Received Binary Packet: ${data.size} bytes")
|
||||
is Frame.Binary -> onSolarXRMessage(
|
||||
frame.buffer,
|
||||
solarxrConnection
|
||||
)
|
||||
|
||||
is Frame.Close -> {
|
||||
AppLogger.solarxr.info("Connection closed")
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,202 @@
|
||||
package dev.slimevr.solarxr
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder
|
||||
import dev.slimevr.VRServer
|
||||
import dev.slimevr.context.Context
|
||||
import dev.slimevr.context.createContext
|
||||
import io.ktor.util.moveToByteArray
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.cancelAndJoin
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import solarxr_protocol.MessageBundle
|
||||
import solarxr_protocol.data_feed.DataFeedConfig
|
||||
import solarxr_protocol.data_feed.DataFeedMessage
|
||||
import solarxr_protocol.data_feed.DataFeedMessageHeader
|
||||
import solarxr_protocol.data_feed.DataFeedUpdate
|
||||
import solarxr_protocol.data_feed.StartDataFeed
|
||||
import solarxr_protocol.data_feed.device_data.DeviceData
|
||||
import solarxr_protocol.data_feed.tracker.TrackerData
|
||||
import solarxr_protocol.datatypes.DeviceId
|
||||
import solarxr_protocol.datatypes.TrackerId
|
||||
import solarxr_protocol.datatypes.hardware_info.HardwareStatus
|
||||
import solarxr_protocol.rpc.RpcMessage
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.time.measureTime
|
||||
|
||||
data class SolarXRConnectionState(
|
||||
val id: Int,
|
||||
val dataFeedConfigs: List<DataFeedConfig>,
|
||||
val datafeedTimers: List<Job>,
|
||||
)
|
||||
|
||||
sealed interface SolarXRConnectionActions {
|
||||
data class SetConfig(val configs: List<DataFeedConfig>, val timers: List<Job>) :
|
||||
SolarXRConnectionActions
|
||||
}
|
||||
|
||||
typealias SolarXRConnectionContext = Context<SolarXRConnectionState, SolarXRConnectionActions>
|
||||
|
||||
class PacketDispatcher<T : Any> {
|
||||
val listeners = mutableMapOf<KClass<out T>, MutableList<suspend (T) -> Unit>>()
|
||||
val globalListeners = mutableListOf<suspend (T) -> Unit>()
|
||||
val mutex = Mutex()
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
inline fun <reified P : T> on(crossinline callback: suspend (P) -> Unit) {
|
||||
runBlocking {
|
||||
mutex.withLock {
|
||||
val list =
|
||||
listeners.getOrPut(P::class as KClass<out T>) { mutableListOf() }
|
||||
list.add { callback(it as P) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onAny(callback: suspend (T) -> Unit) {
|
||||
runBlocking {
|
||||
mutex.withLock { globalListeners.add(callback) }
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun emit(event: T) {
|
||||
val targets = mutex.withLock {
|
||||
val specific = listeners[event::class]?.toList() ?: emptyList()
|
||||
val global = globalListeners.toList()
|
||||
global + specific
|
||||
}
|
||||
targets.forEach { it(event) }
|
||||
}
|
||||
}
|
||||
|
||||
data class SolarXRConnection(
|
||||
val context: SolarXRConnectionContext,
|
||||
val serverContext: VRServer,
|
||||
val dataFeedDispatcher: PacketDispatcher<DataFeedMessage>,
|
||||
val rpcDispatcher: PacketDispatcher<RpcMessage>,
|
||||
val send: suspend (ByteArray) -> Unit
|
||||
)
|
||||
|
||||
data class SolarXRConnectionModule(
|
||||
val reducer: ((SolarXRConnectionState, SolarXRConnectionActions) -> SolarXRConnectionState)? = null,
|
||||
val observer: ((SolarXRConnection) -> Unit)? = null,
|
||||
)
|
||||
|
||||
|
||||
val DataFeedInitModule = SolarXRConnectionModule(
|
||||
observer = { context ->
|
||||
context.dataFeedDispatcher.on<StartDataFeed> { event ->
|
||||
val datafeeds = event.dataFeeds ?: return@on
|
||||
val state = context.context.state.value
|
||||
|
||||
state.datafeedTimers.forEach {
|
||||
it.cancelAndJoin()
|
||||
}
|
||||
|
||||
val timers = datafeeds.map { config ->
|
||||
val minTime = config.minimumTimeSinceLast ?: return@map null
|
||||
|
||||
return@map context.context.scope.launch {
|
||||
val fbb = FlatBufferBuilder(1024)
|
||||
while (isActive) {
|
||||
val timeTaken = measureTime {
|
||||
fbb.clear()
|
||||
|
||||
val serverState = context.serverContext.context.state.value
|
||||
val trackers =
|
||||
serverState.trackers.values.map { it.context.state.value }
|
||||
val devices =
|
||||
serverState.devices.values.map { it.context.state.value }
|
||||
.map { device ->
|
||||
DeviceData(
|
||||
id = DeviceId(device.id.toUByte()),
|
||||
hardwareStatus = HardwareStatus(
|
||||
batteryVoltage = device.batteryVoltage,
|
||||
batteryPctEstimate = device.batteryLevel.toUInt()
|
||||
.toUByte(),
|
||||
ping = device.ping?.toUShort()
|
||||
),
|
||||
trackers = trackers.filter { it.deviceId == device.id }
|
||||
.map { tracker ->
|
||||
TrackerData(
|
||||
trackerId = TrackerId(
|
||||
trackerNum = tracker.id.toUByte(),
|
||||
deviceId = DeviceId(device.id.toUByte())
|
||||
),
|
||||
status = tracker.status
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
fbb.finish(
|
||||
MessageBundle(
|
||||
dataFeedMsgs = listOf(
|
||||
DataFeedMessageHeader(
|
||||
message = DataFeedUpdate(
|
||||
devices = devices
|
||||
)
|
||||
)
|
||||
)
|
||||
).encode(fbb)
|
||||
)
|
||||
|
||||
context.send(fbb.dataBuffer().moveToByteArray())
|
||||
}
|
||||
val remainingDelay =
|
||||
(minTime.toLong() - timeTaken.inWholeMilliseconds).coerceAtLeast(
|
||||
0
|
||||
)
|
||||
delay(remainingDelay)
|
||||
}
|
||||
}
|
||||
}.filterNotNull()
|
||||
|
||||
context.context.dispatch(
|
||||
SolarXRConnectionActions.SetConfig(
|
||||
datafeeds,
|
||||
timers = timers
|
||||
)
|
||||
)
|
||||
|
||||
timers.forEach { it.start() }
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
fun createSolarXRConnection(
|
||||
serverContext: VRServer,
|
||||
onSend: suspend (ByteArray) -> Unit,
|
||||
scope: CoroutineScope
|
||||
): SolarXRConnection {
|
||||
|
||||
val state = SolarXRConnectionState(
|
||||
dataFeedConfigs = listOf(),
|
||||
datafeedTimers = listOf()
|
||||
)
|
||||
|
||||
val modules = listOf(DataFeedInitModule)
|
||||
|
||||
val context = createContext(
|
||||
initialState = state,
|
||||
reducers = modules.map { it.reducer },
|
||||
scope = scope,
|
||||
)
|
||||
|
||||
val conn = SolarXRConnection(
|
||||
context = context,
|
||||
serverContext = serverContext,
|
||||
dataFeedDispatcher = PacketDispatcher(),
|
||||
rpcDispatcher = PacketDispatcher(),
|
||||
onSend,
|
||||
)
|
||||
|
||||
modules.map { it.observer }.forEach { it?.invoke(conn) }
|
||||
|
||||
return conn
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package dev.slimevr.tracker
|
||||
|
||||
enum class IMUType(val id: UByte) {
|
||||
UNKNOWN(solarxr_protocol.datatypes.hardware_info.ImuType.Other.toUByte()),
|
||||
MPU9250(solarxr_protocol.datatypes.hardware_info.ImuType.MPU9250.toUByte()),
|
||||
MPU6500(solarxr_protocol.datatypes.hardware_info.ImuType.MPU6500.toUByte()),
|
||||
BNO080(solarxr_protocol.datatypes.hardware_info.ImuType.BNO080.toUByte()),
|
||||
BNO085(solarxr_protocol.datatypes.hardware_info.ImuType.BNO085.toUByte()),
|
||||
BNO055(solarxr_protocol.datatypes.hardware_info.ImuType.BNO055.toUByte()),
|
||||
MPU6050(solarxr_protocol.datatypes.hardware_info.ImuType.MPU6050.toUByte()),
|
||||
BNO086(solarxr_protocol.datatypes.hardware_info.ImuType.BNO086.toUByte()),
|
||||
BMI160(solarxr_protocol.datatypes.hardware_info.ImuType.BMI160.toUByte()),
|
||||
ICM20948(solarxr_protocol.datatypes.hardware_info.ImuType.ICM20948.toUByte()),
|
||||
ICM42688(solarxr_protocol.datatypes.hardware_info.ImuType.ICM42688.toUByte()),
|
||||
BMI270(solarxr_protocol.datatypes.hardware_info.ImuType.BMI270.toUByte()),
|
||||
LSM6DS3TRC(solarxr_protocol.datatypes.hardware_info.ImuType.LSM6DS3TRC.toUByte()),
|
||||
LSM6DSV(solarxr_protocol.datatypes.hardware_info.ImuType.LSM6DSV.toUByte()),
|
||||
LSM6DSO(solarxr_protocol.datatypes.hardware_info.ImuType.LSM6DSO.toUByte()),
|
||||
LSM6DSR(solarxr_protocol.datatypes.hardware_info.ImuType.LSM6DSR.toUByte()),
|
||||
ICM45686(solarxr_protocol.datatypes.hardware_info.ImuType.ICM45686.toUByte()),
|
||||
ICM45605(solarxr_protocol.datatypes.hardware_info.ImuType.ICM45605.toUByte()),
|
||||
ADC_RESISTANCE(solarxr_protocol.datatypes.hardware_info.ImuType.ADCRESISTANCE.toUByte()),
|
||||
DEV_RESERVED(solarxr_protocol.datatypes.hardware_info.ImuType.DEVRESERVED.toUByte()),
|
||||
;
|
||||
|
||||
companion object {
|
||||
private val map = entries.associateBy { it.id }
|
||||
fun fromId(id: UByte) = map[id]
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,16 @@
|
||||
package dev.slimevr.tracker
|
||||
|
||||
import dev.slimevr.AppLogger
|
||||
import dev.slimevr.VRServer
|
||||
import dev.slimevr.context.BasicModule
|
||||
import dev.slimevr.context.Context
|
||||
import dev.slimevr.context.createContext
|
||||
import dev.slimevr.skeleton.BodyPart
|
||||
import io.github.axisangles.ktmath.Quaternion
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
enum class TrackerStatus(val id: UByte) {
|
||||
DISCONNECTED(solarxr_protocol.datatypes.TrackerStatus.DISCONNECTED),
|
||||
OK(solarxr_protocol.datatypes.TrackerStatus.OK),
|
||||
BUSY(solarxr_protocol.datatypes.TrackerStatus.BUSY),
|
||||
ERROR(solarxr_protocol.datatypes.TrackerStatus.ERROR),
|
||||
OCCLUDED(solarxr_protocol.datatypes.TrackerStatus.OCCLUDED),
|
||||
TIMEDOUT(solarxr_protocol.datatypes.TrackerStatus.TIMEDOUT);
|
||||
|
||||
companion object {
|
||||
private val map = entries.associateBy { it.id }
|
||||
fun fromId(id: UByte) = map[id]
|
||||
}
|
||||
}
|
||||
import solarxr_protocol.datatypes.BodyPart
|
||||
import solarxr_protocol.datatypes.TrackerStatus
|
||||
import solarxr_protocol.datatypes.hardware_info.ImuType
|
||||
|
||||
data class TrackerIdNum(val id: Int, val trackerNum: Int)
|
||||
|
||||
@@ -31,7 +18,7 @@ data class TrackerState(
|
||||
val id: Int,
|
||||
val name: String,
|
||||
val hardwareId: String,
|
||||
val sensorType: IMUType,
|
||||
val sensorType: ImuType,
|
||||
val bodyPart: BodyPart?,
|
||||
val status: TrackerStatus,
|
||||
val customName: String?,
|
||||
@@ -65,7 +52,7 @@ fun createTracker(
|
||||
scope: CoroutineScope,
|
||||
id: Int,
|
||||
deviceId: Int,
|
||||
sensorType: IMUType,
|
||||
sensorType: ImuType,
|
||||
hardwareId: String,
|
||||
origin: DeviceOrigin,
|
||||
serverContext: VRServer
|
||||
|
||||
@@ -168,7 +168,6 @@ val HandshakeModule = UDPConnectionModule(
|
||||
didHandshake = true,
|
||||
deviceId = a.deviceId
|
||||
)
|
||||
|
||||
else -> s
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package dev.slimevr.tracker.udp
|
||||
|
||||
import dev.slimevr.tracker.IMUType
|
||||
import dev.slimevr.tracker.TrackerStatus
|
||||
import io.github.axisangles.ktmath.Quaternion
|
||||
import io.github.axisangles.ktmath.Vector3
|
||||
import io.ktor.utils.io.core.remaining
|
||||
@@ -15,6 +13,8 @@ import kotlinx.io.readFloat
|
||||
import kotlinx.io.readString
|
||||
import kotlinx.io.readUByte
|
||||
import kotlinx.io.writeUByte
|
||||
import solarxr_protocol.datatypes.TrackerStatus
|
||||
import solarxr_protocol.datatypes.hardware_info.ImuType
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
private fun Source.readU8(): Int = readByte().toInt() and 0xFF
|
||||
@@ -148,7 +148,7 @@ data class ErrorPacket(override val sensorId: Int = 0, val errorNumber: Int = 0)
|
||||
data class SensorInfo(
|
||||
override val sensorId: Int = 0,
|
||||
val status: TrackerStatus = TrackerStatus.DISCONNECTED,
|
||||
val imuType: IMUType = IMUType.UNKNOWN,
|
||||
val imuType: ImuType = ImuType.Other,
|
||||
val sensorConfig: UShort? = null,
|
||||
val hasCompletedRestCalibration: Boolean? = null,
|
||||
val trackerPosition: Int? = null,
|
||||
@@ -157,8 +157,8 @@ data class SensorInfo(
|
||||
companion object {
|
||||
fun read(src: Source) = with(src) {
|
||||
val id = readU8()
|
||||
val stat = TrackerStatus.fromId((readUByte() + 1u).toUByte()) ?: TrackerStatus.DISCONNECTED
|
||||
val imu = if (remaining > 0) IMUType.fromId(readUByte()) ?: IMUType.UNKNOWN else IMUType.UNKNOWN
|
||||
val stat = TrackerStatus.fromValue((readUByte() + 1u).toUByte()) ?: TrackerStatus.DISCONNECTED
|
||||
val imu = if (remaining > 0) ImuType.fromValue(readUByte().toUShort()) ?: ImuType.Other else ImuType.Other
|
||||
val conf = if (remaining >= 2) readShort().toUShort() else null
|
||||
val calib = if (remaining > 0) readU8() != 0 else null
|
||||
val pos = if (remaining > 0) readU8() else null
|
||||
|
||||
@@ -17,7 +17,7 @@ fun main(args: Array<String>) = runBlocking {
|
||||
createUDPTrackerServer(server, config)
|
||||
}
|
||||
launch {
|
||||
createSolarXRWebsocketServer()
|
||||
createSolarXRWebsocketServer(server)
|
||||
}
|
||||
Unit
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user