mirror of
https://github.com/SlimeVR/SlimeVR-Server.git
synced 2026-04-06 02:01:58 +02:00
ProvisioningHandler,ProvisioningListener: Convert to Kotlin
This commit is contained in:
@@ -25,7 +25,7 @@ class RPCProvisioningHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) :
|
||||
val req = messageHeader
|
||||
.message(StartWifiProvisioningRequest()) as StartWifiProvisioningRequest?
|
||||
if (req == null) return
|
||||
this.api.server.provisioningHandler.start(req.ssid(), req.password(), req.port())
|
||||
this.api.server.provisioningHandler.start(req.ssid() ?: error("expected ssid"), req.password() ?: error("expected password"), req.port())
|
||||
conn.context.useProvisioning = true
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ class RPCSerialHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) : Seria
|
||||
)
|
||||
}
|
||||
|
||||
override fun onSerialLog(str: String, server: Boolean) {
|
||||
override fun onSerialLog(str: String, fromServer: Boolean) {
|
||||
val fbb = FlatBufferBuilder(32)
|
||||
|
||||
val logOffset = fbb.createString(str)
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
package dev.slimevr.serial;
|
||||
|
||||
import dev.slimevr.VRServer;
|
||||
import io.eiren.util.logging.LogManager;
|
||||
import kotlin.text.Regex;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
|
||||
public class ProvisioningHandler implements SerialListener {
|
||||
|
||||
private ProvisioningStatus provisioningStatus = ProvisioningStatus.NONE;
|
||||
|
||||
private boolean isRunning = false;
|
||||
private final List<ProvisioningListener> listeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
private String ssid;
|
||||
private String password;
|
||||
|
||||
private String preferredPort;
|
||||
|
||||
private final Timer provisioningTickTimer = new Timer("ProvisioningTickTimer");
|
||||
private long lastStatusChange = -1;
|
||||
private byte connectRetries = 0;
|
||||
private boolean hasLogs = false;
|
||||
private final byte MAX_CONNECTION_RETRIES = 1;
|
||||
private final VRServer vrServer;
|
||||
|
||||
public ProvisioningHandler(VRServer vrServer) {
|
||||
this.vrServer = vrServer;
|
||||
vrServer.serialHandler.addListener(this);
|
||||
this.provisioningTickTimer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isRunning || provisioningStatus == ProvisioningStatus.DONE)
|
||||
return;
|
||||
provisioningTick();
|
||||
}
|
||||
}, 0, 1000);
|
||||
}
|
||||
|
||||
|
||||
public void start(String ssid, String password, String port) {
|
||||
this.isRunning = true;
|
||||
this.hasLogs = false;
|
||||
this.ssid = ssid;
|
||||
this.password = password;
|
||||
this.preferredPort = port;
|
||||
this.provisioningStatus = ProvisioningStatus.NONE;
|
||||
this.connectRetries = 0;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
this.isRunning = false;
|
||||
this.hasLogs = false;
|
||||
this.ssid = null;
|
||||
this.password = null;
|
||||
this.connectRetries = 0;
|
||||
this.changeStatus(ProvisioningStatus.NONE);
|
||||
this.vrServer.serialHandler.closeSerial();
|
||||
}
|
||||
|
||||
public void initSerial(String port) {
|
||||
this.provisioningStatus = ProvisioningStatus.SERIAL_INIT;
|
||||
this.hasLogs = false;
|
||||
|
||||
try {
|
||||
boolean openResult = false;
|
||||
if (port != null)
|
||||
openResult = vrServer.serialHandler.openSerial(port, false);
|
||||
else
|
||||
openResult = vrServer.serialHandler.openSerial(null, true);
|
||||
if (!openResult)
|
||||
LogManager.info("[SerialHandler] Serial port wasn't open...");
|
||||
} catch (Exception e) {
|
||||
LogManager.severe("[SerialHandler] Unable to open serial port", e);
|
||||
} catch (Throwable e) {
|
||||
LogManager
|
||||
.severe("[SerialHandler] Using serial ports is not supported on this platform", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void tryObtainMacAddress() {
|
||||
this.changeStatus(ProvisioningStatus.OBTAINING_MAC_ADDRESS);
|
||||
vrServer.serialHandler.infoRequest();
|
||||
}
|
||||
|
||||
public void tryProvisioning() {
|
||||
this.changeStatus(ProvisioningStatus.PROVISIONING);
|
||||
vrServer.serialHandler.setWifi(this.ssid, this.password);
|
||||
}
|
||||
|
||||
|
||||
public void provisioningTick() {
|
||||
if (this.provisioningStatus == ProvisioningStatus.OBTAINING_MAC_ADDRESS)
|
||||
this.tryObtainMacAddress();
|
||||
|
||||
if (
|
||||
!hasLogs
|
||||
&& this.provisioningStatus == ProvisioningStatus.OBTAINING_MAC_ADDRESS
|
||||
&& System.currentTimeMillis() - this.lastStatusChange > 1_000
|
||||
) {
|
||||
this.changeStatus(ProvisioningStatus.NO_SERIAL_LOGS_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
this.provisioningStatus == ProvisioningStatus.SERIAL_INIT
|
||||
&& vrServer.serialHandler.getKnownPorts().findAny().isEmpty()
|
||||
&& System.currentTimeMillis() - this.lastStatusChange > 15_000
|
||||
) {
|
||||
this.changeStatus(ProvisioningStatus.NO_SERIAL_DEVICE_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
System.currentTimeMillis() - this.lastStatusChange
|
||||
> this.provisioningStatus.getTimeout()
|
||||
) {
|
||||
if (
|
||||
this.provisioningStatus == ProvisioningStatus.NONE
|
||||
|| this.provisioningStatus == ProvisioningStatus.SERIAL_INIT
|
||||
)
|
||||
this.initSerial(this.preferredPort);
|
||||
else if (this.provisioningStatus == ProvisioningStatus.CONNECTING)
|
||||
this.changeStatus(ProvisioningStatus.CONNECTION_ERROR);
|
||||
else if (this.provisioningStatus == ProvisioningStatus.LOOKING_FOR_SERVER)
|
||||
this.changeStatus(ProvisioningStatus.COULD_NOT_FIND_SERVER);
|
||||
else if (!this.provisioningStatus.isError()) {
|
||||
this.changeStatus(ProvisioningStatus.CONNECTION_ERROR); // TIMEOUT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onSerialConnected(@NotNull SerialPort port) {
|
||||
if (!isRunning)
|
||||
return;
|
||||
this.tryObtainMacAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSerialDisconnected() {
|
||||
if (!isRunning)
|
||||
return;
|
||||
this.changeStatus(ProvisioningStatus.NONE);
|
||||
this.connectRetries = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSerialLog(@NotNull String str, boolean server) {
|
||||
if (!isRunning)
|
||||
return;
|
||||
if (!server) {
|
||||
this.hasLogs = true;
|
||||
if (provisioningStatus == ProvisioningStatus.NO_SERIAL_LOGS_ERROR) {
|
||||
// Recover the onboarding process if the user turned on the
|
||||
// tracker afterward
|
||||
this.changeStatus(ProvisioningStatus.OBTAINING_MAC_ADDRESS);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
provisioningStatus == ProvisioningStatus.OBTAINING_MAC_ADDRESS && str.contains("mac:")
|
||||
) {
|
||||
var match = new Regex("mac: (?<mac>([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})), ")
|
||||
.find(str, str.indexOf("mac:"));
|
||||
|
||||
if (match != null) {
|
||||
var b = match.getGroups().get(1);
|
||||
if (b != null) {
|
||||
vrServer.configManager.getVrConfig().addKnownDevice(b.getValue());
|
||||
vrServer.configManager.saveConfig();
|
||||
this.tryProvisioning();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (
|
||||
provisioningStatus == ProvisioningStatus.PROVISIONING
|
||||
&& str.contains("New wifi credentials set")
|
||||
) {
|
||||
this.changeStatus(ProvisioningStatus.CONNECTING);
|
||||
}
|
||||
|
||||
if (
|
||||
provisioningStatus == ProvisioningStatus.CONNECTING
|
||||
&& (str.contains("Looking for the server")
|
||||
|| str.contains("Searching for the server"))
|
||||
) {
|
||||
this.changeStatus(ProvisioningStatus.LOOKING_FOR_SERVER);
|
||||
}
|
||||
|
||||
if (
|
||||
provisioningStatus == ProvisioningStatus.LOOKING_FOR_SERVER
|
||||
&& str.contains("Handshake successful")
|
||||
) {
|
||||
this.changeStatus(ProvisioningStatus.DONE);
|
||||
}
|
||||
|
||||
if (
|
||||
provisioningStatus == ProvisioningStatus.CONNECTING
|
||||
&& str.contains("Can't connect from any credentials")
|
||||
) {
|
||||
if (++connectRetries >= MAX_CONNECTION_RETRIES) {
|
||||
this.changeStatus(ProvisioningStatus.CONNECTION_ERROR);
|
||||
} else {
|
||||
this.vrServer.serialHandler.rebootRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void changeStatus(ProvisioningStatus status) {
|
||||
if (this.provisioningStatus != status) {
|
||||
this.lastStatusChange = System.currentTimeMillis();
|
||||
this.listeners
|
||||
.forEach(
|
||||
(l) -> l
|
||||
.onProvisioningStatusChange(status, vrServer.serialHandler.getCurrentPort())
|
||||
);
|
||||
this.provisioningStatus = status;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewSerialDevice(SerialPort port) {
|
||||
if (!isRunning)
|
||||
return;
|
||||
this.initSerial(this.preferredPort);
|
||||
}
|
||||
|
||||
public void addListener(ProvisioningListener channel) {
|
||||
this.listeners.add(channel);
|
||||
}
|
||||
|
||||
public void removeListener(ProvisioningListener l) {
|
||||
listeners.removeIf(listener -> l == listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSerialDeviceDeleted(@NotNull SerialPort port) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
package dev.slimevr.serial
|
||||
|
||||
import dev.slimevr.VRServer
|
||||
import io.eiren.util.logging.LogManager
|
||||
import java.util.*
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
import java.util.function.Consumer
|
||||
import kotlin.concurrent.scheduleAtFixedRate
|
||||
|
||||
class ProvisioningHandler(private val server: VRServer) : SerialListener {
|
||||
private var provisioningStatus = ProvisioningStatus.NONE
|
||||
|
||||
private var isRunning = false
|
||||
private val listeners = CopyOnWriteArrayList<ProvisioningListener>()
|
||||
|
||||
private var ssid: String? = null
|
||||
private var password: String? = null
|
||||
|
||||
private var preferredPort: String? = null
|
||||
|
||||
private val provisioningTickTimer = Timer("ProvisioningTickTimer")
|
||||
private var lastStatusChange: Long = -1
|
||||
private var connectRetries: Byte = 0
|
||||
private var hasLogs = false
|
||||
|
||||
companion object {
|
||||
const val MAX_CONNECTION_RETRIES: Byte = 1
|
||||
}
|
||||
|
||||
init {
|
||||
server.serialHandler.addListener(this)
|
||||
provisioningTickTimer.scheduleAtFixedRate(0, 1000) {
|
||||
if (isRunning && provisioningStatus != ProvisioningStatus.DONE) provisioningTick()
|
||||
}
|
||||
}
|
||||
|
||||
fun start(ssid: String, password: String, port: String?) {
|
||||
this.isRunning = true
|
||||
this.hasLogs = false
|
||||
this.ssid = ssid
|
||||
this.password = password
|
||||
this.preferredPort = port
|
||||
this.provisioningStatus = ProvisioningStatus.NONE
|
||||
this.connectRetries = 0
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
this.isRunning = false
|
||||
this.hasLogs = false
|
||||
this.ssid = null
|
||||
this.password = null
|
||||
this.connectRetries = 0
|
||||
changeStatus(ProvisioningStatus.NONE)
|
||||
server.serialHandler.closeSerial()
|
||||
}
|
||||
|
||||
fun initSerial(port: String?) {
|
||||
provisioningStatus = ProvisioningStatus.SERIAL_INIT
|
||||
hasLogs = false
|
||||
|
||||
try {
|
||||
val openResult = if (port != null) {
|
||||
server.serialHandler.openSerial(port, false)
|
||||
} else {
|
||||
server.serialHandler.openSerial(null, true)
|
||||
}
|
||||
if (!openResult) {
|
||||
LogManager.info("[SerialHandler] Serial port wasn't open...")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
LogManager.severe("[SerialHandler] Unable to open serial port", e)
|
||||
} catch (e: Throwable) {
|
||||
LogManager.severe("[SerialHandler] Using serial ports is not supported on this platform", e)
|
||||
}
|
||||
}
|
||||
|
||||
fun tryObtainMacAddress() {
|
||||
changeStatus(ProvisioningStatus.OBTAINING_MAC_ADDRESS)
|
||||
server.serialHandler.infoRequest()
|
||||
}
|
||||
|
||||
fun tryProvisioning() {
|
||||
changeStatus(ProvisioningStatus.PROVISIONING)
|
||||
server.serialHandler.setWifi(ssid!!, password!!)
|
||||
}
|
||||
|
||||
fun provisioningTick() {
|
||||
if (provisioningStatus == ProvisioningStatus.OBTAINING_MAC_ADDRESS) tryObtainMacAddress()
|
||||
|
||||
if (!hasLogs && provisioningStatus == ProvisioningStatus.OBTAINING_MAC_ADDRESS && System.currentTimeMillis() - lastStatusChange > 1000) {
|
||||
changeStatus(ProvisioningStatus.NO_SERIAL_LOGS_ERROR)
|
||||
return
|
||||
}
|
||||
|
||||
if (provisioningStatus == ProvisioningStatus.SERIAL_INIT &&
|
||||
server.serialHandler.knownPorts.findAny().isEmpty &&
|
||||
System.currentTimeMillis() - lastStatusChange > 15000
|
||||
) {
|
||||
changeStatus(ProvisioningStatus.NO_SERIAL_DEVICE_FOUND)
|
||||
return
|
||||
}
|
||||
|
||||
if (System.currentTimeMillis() - lastStatusChange
|
||||
> provisioningStatus.timeout
|
||||
) {
|
||||
if (provisioningStatus == ProvisioningStatus.NONE ||
|
||||
provisioningStatus == ProvisioningStatus.SERIAL_INIT
|
||||
) {
|
||||
initSerial(preferredPort)
|
||||
} else if (provisioningStatus == ProvisioningStatus.CONNECTING) {
|
||||
changeStatus(ProvisioningStatus.CONNECTION_ERROR)
|
||||
} else if (provisioningStatus == ProvisioningStatus.LOOKING_FOR_SERVER) {
|
||||
changeStatus(
|
||||
ProvisioningStatus.COULD_NOT_FIND_SERVER,
|
||||
)
|
||||
} else if (!provisioningStatus.isError) {
|
||||
changeStatus(ProvisioningStatus.CONNECTION_ERROR) // TIMEOUT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSerialConnected(port: SerialPort) {
|
||||
if (!isRunning) return
|
||||
tryObtainMacAddress()
|
||||
}
|
||||
|
||||
override fun onSerialDisconnected() {
|
||||
if (!isRunning) return
|
||||
changeStatus(ProvisioningStatus.NONE)
|
||||
connectRetries = 0
|
||||
}
|
||||
|
||||
override fun onSerialLog(str: String, fromServer: Boolean) {
|
||||
if (!isRunning) return
|
||||
if (!fromServer) {
|
||||
hasLogs = true
|
||||
if (provisioningStatus == ProvisioningStatus.NO_SERIAL_LOGS_ERROR) {
|
||||
// Recover the onboarding process if the user turned on the
|
||||
// tracker afterward
|
||||
changeStatus(ProvisioningStatus.OBTAINING_MAC_ADDRESS)
|
||||
}
|
||||
}
|
||||
|
||||
if (provisioningStatus == ProvisioningStatus.OBTAINING_MAC_ADDRESS && str.contains("mac:")) {
|
||||
val match = Regex("mac: (?<mac>([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})), ")
|
||||
.find(str, str.indexOf("mac:"))
|
||||
|
||||
if (match != null) {
|
||||
val b = match.groups[1]
|
||||
if (b != null) {
|
||||
server.configManager.vrConfig.addKnownDevice(b.value)
|
||||
server.configManager.saveConfig()
|
||||
tryProvisioning()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (provisioningStatus == ProvisioningStatus.PROVISIONING &&
|
||||
str.contains("New wifi credentials set")
|
||||
) {
|
||||
changeStatus(ProvisioningStatus.CONNECTING)
|
||||
}
|
||||
|
||||
if (provisioningStatus == ProvisioningStatus.CONNECTING &&
|
||||
(
|
||||
str.contains("Looking for the server") ||
|
||||
str.contains("Searching for the server")
|
||||
)
|
||||
) {
|
||||
changeStatus(ProvisioningStatus.LOOKING_FOR_SERVER)
|
||||
}
|
||||
|
||||
if (provisioningStatus == ProvisioningStatus.LOOKING_FOR_SERVER &&
|
||||
str.contains("Handshake successful")
|
||||
) {
|
||||
changeStatus(ProvisioningStatus.DONE)
|
||||
}
|
||||
|
||||
if (provisioningStatus == ProvisioningStatus.CONNECTING &&
|
||||
str.contains("Can't connect from any credentials")
|
||||
) {
|
||||
if (++connectRetries >= MAX_CONNECTION_RETRIES) {
|
||||
changeStatus(ProvisioningStatus.CONNECTION_ERROR)
|
||||
} else {
|
||||
server.serialHandler.rebootRequest()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun changeStatus(status: ProvisioningStatus) {
|
||||
if (provisioningStatus != status) {
|
||||
lastStatusChange = System.currentTimeMillis()
|
||||
listeners
|
||||
.forEach { l ->
|
||||
l.onProvisioningStatusChange(status, server.serialHandler.getCurrentPort())
|
||||
}
|
||||
provisioningStatus = status
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNewSerialDevice(port: SerialPort) {
|
||||
if (!isRunning) return
|
||||
initSerial(preferredPort)
|
||||
}
|
||||
|
||||
fun addListener(channel: ProvisioningListener) {
|
||||
listeners.add(channel)
|
||||
}
|
||||
|
||||
fun removeListener(l: ProvisioningListener) {
|
||||
listeners.removeIf { listener: ProvisioningListener? -> l === listener }
|
||||
}
|
||||
|
||||
override fun onSerialDeviceDeleted(port: SerialPort) {
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package dev.slimevr.serial;
|
||||
|
||||
public interface ProvisioningListener {
|
||||
|
||||
void onProvisioningStatusChange(ProvisioningStatus status, SerialPort port);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package dev.slimevr.serial
|
||||
|
||||
interface ProvisioningListener {
|
||||
fun onProvisioningStatusChange(status: ProvisioningStatus, port: SerialPort?)
|
||||
}
|
||||
@@ -24,8 +24,8 @@ interface SerialListener {
|
||||
fun onSerialConnected(port: SerialPort)
|
||||
fun onSerialDisconnected()
|
||||
|
||||
// var server indicates if the log is injected by the server (not an actual serial log)
|
||||
fun onSerialLog(str: String, server: Boolean)
|
||||
// fromServer indicates if the log is injected by the server (not an actual serial log)
|
||||
fun onSerialLog(str: String, fromServer: Boolean)
|
||||
fun onNewSerialDevice(port: SerialPort)
|
||||
|
||||
// This is called when the serial diver does not see the device anymore
|
||||
|
||||
@@ -208,9 +208,9 @@ class DesktopSerialHandler :
|
||||
}
|
||||
}
|
||||
|
||||
fun addLog(str: String, server: Boolean = true) {
|
||||
fun addLog(str: String, fromServer: Boolean = true) {
|
||||
LogManager.info("[Serial] $str")
|
||||
listeners.forEach { it.onSerialLog(str, server) }
|
||||
listeners.forEach { it.onSerialLog(str, fromServer) }
|
||||
}
|
||||
|
||||
override fun getListeningEvents(): Int = (
|
||||
|
||||
Reference in New Issue
Block a user