| 
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -20,6 +20,8 @@ class IConsole : ActiveDriver() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  private var lastLevel = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  private var running = false | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  private var connected = false | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  private var wantsConnection = false | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  private var health = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  private var tryingSince: Instant? = null | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -27,6 +29,11 @@ class IConsole : ActiveDriver() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  private var lastCals = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  private var lastMeters = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  private var bonusLevel = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  private var bonusTime = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  private var bonusCals = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  private var bonusMeters = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  private val queue = Collections.synchronizedSet<Request?>(LinkedHashSet()) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  private var central: BluetoothCentralManager? = null | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -41,6 +48,25 @@ class IConsole : ActiveDriver() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    val connectionString = device.connectionString.substring("iconsole:".length) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    health = 3 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    bonusTime = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    bonusCals = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    bonusMeters = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    wantsConnection = true | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    connect(connectionString, output) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  private fun connect(connectionString: String, output: FlowBus<Event>) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    health-- | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    if (health == 0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      runBlocking { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        output.emit(ErrorOccurred("Disconnected thrice during exercise")) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        output.emit(Disconnected) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      return | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    central?.stopScan() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    current?.cancelConnection() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    tryingSince = Instant.now() | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -124,12 +150,16 @@ class IConsole : ActiveDriver() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            lastCals = maxOf(res.calories, lastCals) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            lastMeters = maxOf((res.distance * 1000).toInt(), lastMeters) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            output.emitBlocking(ValuesReceived(listOf( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					              Time(lastTime), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					              Calories(lastCals), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					              Distance(lastMeters), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            output.emitBlocking( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					              ValuesReceived( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                listOf( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                  Time(lastTime + bonusTime), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                  Calories(lastCals + bonusCals), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                  Distance(lastMeters + bonusMeters), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                  Level(res.level), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            ))) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					              ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            ) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      } | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -167,20 +197,38 @@ class IConsole : ActiveDriver() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      override fun onDisconnectedPeripheral(peripheral: BluetoothPeripheral, status: BluetoothCommandStatus) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        if (peripheral.address == current?.address) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          if (wantsConnection) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            logger.info("Will try restarting in 10 seconds (disconnection)") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            runBlocking { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					              updateBonus() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					              delay(timeMillis = 10_000) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					              connect(connectionString, output) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          } else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            current = null | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            output.emitBlocking(Disconnected) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      override fun onConnectionFailed(peripheral: BluetoothPeripheral, status: BluetoothCommandStatus) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        central?.stopScan() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        runBlocking { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          if (health > 1) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            logger.info("Will try restarting in 10 seconds (connection failed)") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            runBlocking { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					              updateBonus() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					              delay(timeMillis = 10_000) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					              connect(connectionString, output) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          } else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            output.emit(ErrorOccurred("Failure: $status")) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            output.emit(Disconnected) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					          } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    central = BluetoothCentralManager(cbScan).apply { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      scanForPeripheralsWithAddresses(arrayOf(connectionString)) | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -193,6 +241,7 @@ class IConsole : ActiveDriver() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    lastMeters = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    running = false | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    connected = false | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    wantsConnection = false | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    current?.cancelConnection() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  } | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -215,6 +264,11 @@ class IConsole : ActiveDriver() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      queue += SetWorkoutModeRequest(0) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      queue += SetWorkoutParamsRequest() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      queue += SetWorkoutControlStateRequest(1) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      if (bonusLevel > 0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        onSetValue(Level(bonusLevel)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        bonusLevel = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      logger.info("RESUMED") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      queue += SetWorkoutControlStateRequest(1) | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -234,7 +288,7 @@ class IConsole : ActiveDriver() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      is SetValueCommand -> onSetValue(command.value) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      StartCommand -> onStart() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      StopCommand -> onStop() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      SkipCommand -> Unit | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					      SkipCommand -> {} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -280,6 +334,13 @@ class IConsole : ActiveDriver() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    delay(pollDuration) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  private fun updateBonus() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    bonusLevel = lastLevel | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    bonusTime += lastTime | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    bonusCals += lastCals | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    bonusMeters += bonusMeters | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					  companion object { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    private val S1_SERVICE = UUID.fromString("49535343-fe7d-4ae5-8fa9-9fafd205e455") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    private val S1_CHAR_COMMAND_INPUT = UUID.fromString("49535343-8841-43f4-a8d4-ecbe34729bb3") | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
				 | 
				
					
  |