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