Browse Source

scan scan scan scan

main 2.2.0
Stian Fredrik Aune 2 years ago
parent
commit
724108d9d5
  1. 270
      ykonsole-iconsole/src/main/kotlin/net/aiterp/git/ykonsole2/infrastructure/IConsole.kt

270
ykonsole-iconsole/src/main/kotlin/net/aiterp/git/ykonsole2/infrastructure/IConsole.kt

@ -71,160 +71,162 @@ class IConsole : ActiveDriver() {
current?.cancelConnection()
tryingSince = Instant.now()
val cbPeripheral = object : BluetoothPeripheralCallback() {
override fun onServicesDiscovered(peripheral: BluetoothPeripheral, services: MutableList<BluetoothGattService>) {
logger.info("Checking device...")
val service1 = services.firstOrNull { it.uuid == S1_SERVICE }
val service2 = services.firstOrNull { it.uuid == S2_SERVICE }
if (service1 != null && service2 != null) {
btCommandInput = service1.getCharacteristic(S1_CHAR_COMMAND_INPUT)
val s1out = service1.getCharacteristic(S1_CHAR_DATA_OUTPUT)
val s1mys = service1.getCharacteristic(S1_CHAR_MYSTERY_OUTPUT)
val s2mys = service2.getCharacteristic(S2_CHAR_MYSTERY_OUTPUT)
if (btCommandInput == null || s1out == null || s1mys == null || s2mys == null) {
logger.warn("Something is off about this i-CONSOLE device")
output.emitBlocking(ErrorOccurred("(Maybe) a malfunctioning i-CONSOLE device"))
peripheral.cancelConnection()
return
}
peripheral.setNotify(btCommandInput!!, true)
peripheral.setNotify(s1out, true)
peripheral.setNotify(s1mys, true)
peripheral.setNotify(s2mys, true)
logger.info("Device setup successfully; sending first request...")
runBlocking {
peripheral.writeCharacteristic(
btCommandInput!!,
AckRequest.toBytes(),
WITHOUT_RESPONSE,
)
}
current = peripheral
} else {
logger.warn("This is maybe not an i-CONSOLE device, since it lacks the required services")
output.emitBlocking(ErrorOccurred("(Maybe) not an i-CONSOLE device"))
peripheral.cancelConnection()
}
}
override fun onCharacteristicUpdate(
peripheral: BluetoothPeripheral,
value: ByteArray?,
characteristic: BluetoothGattCharacteristic,
status: BluetoothCommandStatus,
) {
val res = value?.let { Response.fromBytes(it) }
if (!connected && res is AckResponse) {
logger.info("Device is now ready")
connected = true
output.emitBlocking(Connected)
}
if (res is MaxLevelResponse) {
maxLevel = res.level
if (central == null) {
val cbScan = object : BluetoothCentralManagerCallback() {
override fun onScanStarted() {
logger.info("Scanning for $connectionString...")
}
if (res is ControlStateResponse) {
if (res.value == 1) {
running = true
output.emitBlocking(Started)
} else {
running = false
output.emitBlocking(Stopped)
override fun onScanStopped() {
logger.info("Scan stopped")
tryingSince?.let { ts ->
if (ts.isBefore(Instant.now().minusSeconds(20))) {
central?.stopScan()
tryingSince = null
runBlocking {
output.emit(ErrorOccurred("Connection timeout after 20 seconds"))
output.emit(Disconnected)
}
}
}
}
if (res is WorkoutStatusResponse) {
val currentTime = (res.minutes * 60) + res.seconds
if (currentTime > lastTime) {
lastTime = currentTime
lastCals = maxOf(res.calories, lastCals)
lastMeters = maxOf((res.distance * 1000).toInt(), lastMeters)
output.emitBlocking(
ValuesReceived(
listOf(
Time(lastTime + bonusTime),
Calories(lastCals + bonusCals),
Distance(lastMeters + bonusMeters),
Level(res.level),
)
)
)
override fun onDiscoveredPeripheral(peripheral: BluetoothPeripheral, scanResult: ScanResult) {
logger.info("Connecting to ${peripheral.name} (${peripheral.address})...")
if (tryingSince != null) {
val cbPeripheral = object : BluetoothPeripheralCallback() {
override fun onServicesDiscovered(peripheral: BluetoothPeripheral, services: MutableList<BluetoothGattService>) {
logger.info("Checking device...")
val service1 = services.firstOrNull { it.uuid == S1_SERVICE }
val service2 = services.firstOrNull { it.uuid == S2_SERVICE }
if (service1 != null && service2 != null) {
btCommandInput = service1.getCharacteristic(S1_CHAR_COMMAND_INPUT)
val s1out = service1.getCharacteristic(S1_CHAR_DATA_OUTPUT)
val s1mys = service1.getCharacteristic(S1_CHAR_MYSTERY_OUTPUT)
val s2mys = service2.getCharacteristic(S2_CHAR_MYSTERY_OUTPUT)
if (btCommandInput == null || s1out == null || s1mys == null || s2mys == null) {
logger.warn("Something is off about this i-CONSOLE device")
output.emitBlocking(ErrorOccurred("(Maybe) a malfunctioning i-CONSOLE device"))
peripheral.cancelConnection()
return
}
peripheral.setNotify(btCommandInput!!, true)
peripheral.setNotify(s1out, true)
peripheral.setNotify(s1mys, true)
peripheral.setNotify(s2mys, true)
logger.info("Device setup successfully; sending first request...")
runBlocking {
peripheral.writeCharacteristic(
btCommandInput!!,
AckRequest.toBytes(),
WITHOUT_RESPONSE,
)
}
current = peripheral
} else {
logger.warn("This is maybe not an i-CONSOLE device, since it lacks the required services")
output.emitBlocking(ErrorOccurred("(Maybe) not an i-CONSOLE device"))
peripheral.cancelConnection()
}
}
override fun onCharacteristicUpdate(
peripheral: BluetoothPeripheral,
value: ByteArray?,
characteristic: BluetoothGattCharacteristic,
status: BluetoothCommandStatus,
) {
val res = value?.let { Response.fromBytes(it) }
if (!connected && res is AckResponse) {
logger.info("Device is now ready")
connected = true
output.emitBlocking(Connected)
}
if (res is MaxLevelResponse) {
maxLevel = res.level
}
if (res is ControlStateResponse) {
if (res.value == 1) {
running = true
output.emitBlocking(Started)
} else {
running = false
output.emitBlocking(Stopped)
}
}
if (res is WorkoutStatusResponse) {
val currentTime = (res.minutes * 60) + res.seconds
if (currentTime > lastTime) {
lastTime = currentTime
lastCals = maxOf(res.calories, lastCals)
lastMeters = maxOf((res.distance * 1000).toInt(), lastMeters)
output.emitBlocking(
ValuesReceived(
listOf(
Time(lastTime + bonusTime),
Calories(lastCals + bonusCals),
Distance(lastMeters + bonusMeters),
Level(res.level),
)
)
)
}
}
}
}
tryingSince = null
central?.connectPeripheral(peripheral, cbPeripheral)
central?.stopScan()
}
}
}
}
val cbScan = object : BluetoothCentralManagerCallback() {
override fun onScanStarted() {
logger.info("Scanning for $connectionString...")
}
override fun onScanStopped() {
logger.info("Scan stopped")
tryingSince?.let { ts ->
if (ts.isBefore(Instant.now().minusSeconds(20))) {
central?.stopScan()
tryingSince = null
runBlocking {
output.emit(ErrorOccurred("Connection timeout after 20 seconds"))
output.emit(Disconnected)
override fun onDisconnectedPeripheral(peripheral: BluetoothPeripheral, status: BluetoothCommandStatus) {
if (peripheral.address == current?.address) {
if (wantsConnection) {
logger.warn("Will try restarting in 10 seconds (disconnection)")
prepareReconnect(connectionString, output)
} else {
current = null
output.emitBlocking(Disconnected)
}
}
}
}
override fun onDiscoveredPeripheral(peripheral: BluetoothPeripheral, scanResult: ScanResult) {
logger.info("Connecting to ${peripheral.name} (${peripheral.address})...")
if (tryingSince != null) {
tryingSince = null
central?.connectPeripheral(peripheral, cbPeripheral)
override fun onConnectionFailed(peripheral: BluetoothPeripheral, status: BluetoothCommandStatus) {
central?.stopScan()
}
}
override fun onDisconnectedPeripheral(peripheral: BluetoothPeripheral, status: BluetoothCommandStatus) {
if (peripheral.address == current?.address) {
if (wantsConnection) {
logger.warn("Will try restarting in 10 seconds (disconnection)")
prepareReconnect(connectionString, output)
} else {
current = null
output.emitBlocking(Disconnected)
runBlocking {
if (health > 1) {
logger.warn("Will try restarting in 10 seconds (connection error)")
prepareReconnect(connectionString, output)
} else {
output.emit(ErrorOccurred("Failure: $status"))
output.emit(Disconnected)
}
}
}
}
override fun onConnectionFailed(peripheral: BluetoothPeripheral, status: BluetoothCommandStatus) {
central?.stopScan()
runBlocking {
if (health > 1) {
logger.warn("Will try restarting in 10 seconds (connection error)")
prepareReconnect(connectionString, output)
} else {
output.emit(ErrorOccurred("Failure: $status"))
output.emit(Disconnected)
}
}
}
central = BluetoothCentralManager(cbScan)
}
central = BluetoothCentralManager(cbScan).apply {
scanForPeripheralsWithAddresses(arrayOf(connectionString))
}
central?.scanForPeripheralsWithAddresses(arrayOf(connectionString))
}
private fun onDisconnect() {

Loading…
Cancel
Save