Commit aec0ac31 authored by Anon's avatar Anon
Browse files

Merge branch 'transfer-fix' into 'master'

File transfer and Hatchery fixes

See merge request card10/companion-app-android!16
parents bea887cb 44ed195c
...@@ -42,7 +42,7 @@ object ConnectionService { ...@@ -42,7 +42,7 @@ object ConnectionService {
private var connection: BluetoothGatt? = null private var connection: BluetoothGatt? = null
private var connectionState = BluetoothGatt.STATE_DISCONNECTED private var connectionState = BluetoothGatt.STATE_DISCONNECTED
private var gattListeners = mutableListOf<GattListener>() private var gattListeners = mutableMapOf<String, GattListener>()
private val fileServiceUuid = UUID.fromString("42230100-2342-2342-2342-234223422342") private val fileServiceUuid = UUID.fromString("42230100-2342-2342-2342-234223422342")
...@@ -58,8 +58,8 @@ object ConnectionService { ...@@ -58,8 +58,8 @@ object ConnectionService {
fun isConnected() = connectionState == BluetoothGatt.STATE_CONNECTED fun isConnected() = connectionState == BluetoothGatt.STATE_CONNECTED
fun addGattListener(listener: GattListener) { fun addGattListener(tag: String, listener: GattListener) {
gattListeners.add(listener) gattListeners[tag] = listener
} }
fun connect(context: Context) { fun connect(context: Context) {
...@@ -113,8 +113,6 @@ object ConnectionService { ...@@ -113,8 +113,6 @@ object ConnectionService {
connectionState = newState connectionState = newState
connection = gatt connection = gatt
gattListeners.map { it.onConnectionStateChange(newState) }
when (newState) { when (newState) {
BluetoothGatt.STATE_CONNECTED -> { BluetoothGatt.STATE_CONNECTED -> {
gatt?.discoverServices() gatt?.discoverServices()
...@@ -132,6 +130,8 @@ object ConnectionService { ...@@ -132,6 +130,8 @@ object ConnectionService {
mtu = newMtu - 3 // Very precise science mtu = newMtu - 3 // Very precise science
leService?.enableNotify(gatt) leService?.enableNotify(gatt)
gattListeners.values.map { it.onConnectionReady() }
} }
override fun onCharacteristicWrite( override fun onCharacteristicWrite(
...@@ -145,7 +145,7 @@ object ConnectionService { ...@@ -145,7 +145,7 @@ object ConnectionService {
connection = gatt connection = gatt
gattListeners.map { it.onCharacteristicWrite(characteristic, status) } gattListeners.values.map { it.onCharacteristicWrite(characteristic, status) }
} }
override fun onCharacteristicChanged(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?) { override fun onCharacteristicChanged(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?) {
...@@ -155,7 +155,7 @@ object ConnectionService { ...@@ -155,7 +155,7 @@ object ConnectionService {
throw IllegalStateException() throw IllegalStateException()
} }
gattListeners.map { it.onCharacteristicChanged(characteristic) } gattListeners.values.map { it.onCharacteristicChanged(characteristic) }
} }
} }
......
...@@ -27,5 +27,5 @@ import android.bluetooth.BluetoothGattCharacteristic ...@@ -27,5 +27,5 @@ import android.bluetooth.BluetoothGattCharacteristic
interface GattListener { interface GattListener {
fun onCharacteristicWrite(characteristic: BluetoothGattCharacteristic, status: Int) {} fun onCharacteristicWrite(characteristic: BluetoothGattCharacteristic, status: Int) {}
fun onCharacteristicChanged(characteristic: BluetoothGattCharacteristic) {} fun onCharacteristicChanged(characteristic: BluetoothGattCharacteristic) {}
fun onConnectionStateChange(state: Int) {} fun onConnectionReady() {}
} }
\ No newline at end of file
...@@ -61,8 +61,7 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener { ...@@ -61,8 +61,7 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener {
progress.max = 5 progress.max = 5
button_cancel.setOnClickListener { button_cancel.setOnClickListener {
// isCancelled = true isCancelled = true
startTransfer()
} }
button_done.setOnClickListener { button_done.setOnClickListener {
...@@ -78,6 +77,7 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener { ...@@ -78,6 +77,7 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener {
private fun initConnection() { private fun initConnection() {
val ctx = context ?: throw IllegalStateException() val ctx = context ?: throw IllegalStateException()
ConnectionService.addGattListener("batchfiletransfer", this)
ConnectionService.connect(ctx) ConnectionService.connect(ctx)
} }
...@@ -91,6 +91,7 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener { ...@@ -91,6 +91,7 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener {
} }
private fun transferNext() { private fun transferNext() {
Thread.sleep(1000)
val item = queue.dequeue() val item = queue.dequeue()
if (item == null || isCancelled) { if (item == null || isCancelled) {
...@@ -115,16 +116,15 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener { ...@@ -115,16 +116,15 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener {
val reader = ChunkedReader(ctx, transferJob.sourceUri, ConnectionService.mtu) val reader = ChunkedReader(ctx, transferJob.sourceUri, ConnectionService.mtu)
val service = ConnectionService.leService ?: throw IllegalStateException() val service = ConnectionService.leService ?: throw IllegalStateException()
transfer = FileTransfer(service, reader,this, transferJob.destPath) transfer = FileTransfer(service, reader,this, transferJob.destPath)
transfer?.start()
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Failed to initialize transfer") Log.e(TAG, "Failed to initialize transfer")
return return
} }
} }
override fun onConnectionStateChange(state: Int) { override fun onConnectionReady() {
if (state == BluetoothGatt.STATE_CONNECTED) { startTransfer()
startTransfer()
}
} }
override fun onError() { override fun onError() {
......
...@@ -41,7 +41,7 @@ class FileTransfer( ...@@ -41,7 +41,7 @@ class FileTransfer(
private var currentState = TransferState.IDLE private var currentState = TransferState.IDLE
init { init {
service.addOnPacketReceivedListener(this) service.setOnPacketReceivedListener(this)
} }
override fun onPacketReceived(packet: Packet) { override fun onPacketReceived(packet: Packet) {
...@@ -98,13 +98,13 @@ class FileTransfer( ...@@ -98,13 +98,13 @@ class FileTransfer(
throw IllegalStateException() throw IllegalStateException()
} }
currentState = TransferState.START_SENT
service.sendPacket( service.sendPacket(
Packet( Packet(
PacketType.START, PacketType.START,
destinationPath.toByteArray(Charset.forName("ASCII")) destinationPath.toByteArray(Charset.forName("ASCII"))
) )
) )
currentState = TransferState.START_SENT
} }
private fun sendNext() { private fun sendNext() {
......
...@@ -34,11 +34,14 @@ import android.widget.EditText ...@@ -34,11 +34,14 @@ import android.widget.EditText
import android.widget.ProgressBar import android.widget.ProgressBar
import android.widget.TextView import android.widget.TextView
import androidx.annotation.UiThread import androidx.annotation.UiThread
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import de.ccc.events.badge.card10.CARD10_BLUETOOTH_MAC_PREFIX import de.ccc.events.badge.card10.CARD10_BLUETOOTH_MAC_PREFIX
import de.ccc.events.badge.card10.R import de.ccc.events.badge.card10.R
import de.ccc.events.badge.card10.common.ConnectionException
import de.ccc.events.badge.card10.common.ConnectionService import de.ccc.events.badge.card10.common.ConnectionService
import de.ccc.events.badge.card10.common.GattListener import de.ccc.events.badge.card10.common.GattListener
import de.ccc.events.badge.card10.main.MainFragment
import java.lang.Exception import java.lang.Exception
import java.lang.IllegalStateException import java.lang.IllegalStateException
...@@ -76,8 +79,15 @@ class FileTransferFragment : Fragment(), GattListener, FileTransferListener{ ...@@ -76,8 +79,15 @@ class FileTransferFragment : Fragment(), GattListener, FileTransferListener{
buttonStartStop = view.findViewById(R.id.button_start_stop_transfer) buttonStartStop = view.findViewById(R.id.button_start_stop_transfer)
initConnection() try {
toggleControls() initConnection()
toggleControls()
} catch (e: ConnectionException) {
showError(e.message)
} catch (e: Exception) {
showError(getString(R.string.connection_error_generic))
}
} }
private fun initConnection() { private fun initConnection() {
...@@ -160,4 +170,21 @@ class FileTransferFragment : Fragment(), GattListener, FileTransferListener{ ...@@ -160,4 +170,21 @@ class FileTransferFragment : Fragment(), GattListener, FileTransferListener{
} }
toggleControls() toggleControls()
} }
private fun showError(message: String?) {
val ctx = context ?: throw IllegalStateException()
val fm = fragmentManager ?: throw IllegalStateException()
val errorDialog =
AlertDialog.Builder(ctx)
.setMessage(message ?: getString(R.string.connection_error_generic))
.setPositiveButton(R.string.dialog_action_ok) {
dialog, _ -> dialog.dismiss()
fm.beginTransaction()
.replace(R.id.fragment_container, MainFragment())
.addToBackStack(null)
.commit()
}
.show()
}
} }
\ No newline at end of file
...@@ -43,7 +43,7 @@ class LowEffortService( ...@@ -43,7 +43,7 @@ class LowEffortService(
private val centralRxCharacteristicUuid = UUID.fromString("42230102-2342-2342-2342-234223422342") private val centralRxCharacteristicUuid = UUID.fromString("42230102-2342-2342-2342-234223422342")
private var notifyEnabled = false private var notifyEnabled = false
private val listeners = mutableListOf<OnPacketReceivedListener>() private var listener: OnPacketReceivedListener? = null
init { init {
val tx = service.getCharacteristic(centralTxCharacteristicUuid) val tx = service.getCharacteristic(centralTxCharacteristicUuid)
...@@ -58,7 +58,7 @@ class LowEffortService( ...@@ -58,7 +58,7 @@ class LowEffortService(
centralTx = tx centralTx = tx
centralRx = rx centralRx = rx
ConnectionService.addGattListener(this) ConnectionService.addGattListener("filetransfer",this)
} }
fun enableNotify(gatt: BluetoothGatt) { fun enableNotify(gatt: BluetoothGatt) {
...@@ -89,8 +89,8 @@ class LowEffortService( ...@@ -89,8 +89,8 @@ class LowEffortService(
return status return status
} }
fun addOnPacketReceivedListener(listener: OnPacketReceivedListener) { fun setOnPacketReceivedListener(packetListener: OnPacketReceivedListener) {
listeners.add(listener) listener = packetListener
} }
// GattListener methods // GattListener methods
...@@ -99,6 +99,6 @@ class LowEffortService( ...@@ -99,6 +99,6 @@ class LowEffortService(
} }
override fun onCharacteristicChanged(characteristic: BluetoothGattCharacteristic) { override fun onCharacteristicChanged(characteristic: BluetoothGattCharacteristic) {
listeners.map { it.onPacketReceived(Packet.fromBytes(characteristic.value)) } listener?.onPacketReceived(Packet.fromBytes(characteristic.value))
} }
} }
\ No newline at end of file
...@@ -117,7 +117,7 @@ class AppDetailFragment : Fragment() { ...@@ -117,7 +117,7 @@ class AppDetailFragment : Fragment() {
targetFile.createNewFile() targetFile.createNewFile()
Log.d(TAG, "Extracting ${entry.name} to ${targetFile.absolutePath}") Log.d(TAG, "Extracting ${entry.name} to ${targetFile.absolutePath}")
tarStream.copyTo(targetFile.outputStream()) tarStream.copyTo(targetFile.outputStream())
appFiles.add(TransferJob(targetFile.toUri(), "apps/${entry.name}")) appFiles.add(TransferJob(targetFile.toUri(), "/apps/${entry.name}"))
} }
val launcher = createLauncher(app.slug, cacheDir) val launcher = createLauncher(app.slug, cacheDir)
...@@ -157,12 +157,12 @@ class AppDetailFragment : Fragment() { ...@@ -157,12 +157,12 @@ class AppDetailFragment : Fragment() {
val src = """ val src = """
# Launcher script for $slug # Launcher script for $slug
import os import os
os.exec("apps/$slug/__init__.py") os.exec("/apps/$slug/__init__.py")
""".trimIndent() """.trimIndent()
file.writeText(src) file.writeText(src)
return TransferJob(file.toUri(), fileName) return TransferJob(file.toUri(), "/$fileName")
} }
} }
} }
...@@ -52,8 +52,7 @@ ...@@ -52,8 +52,7 @@
android:text="@string/main_button_browse_apps" android:text="@string/main_button_browse_apps"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"/>
android:enabled="false"/>
<Button android:layout_width="wrap_content" <Button android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment