Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
D
donkey
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
genofire
donkey
Commits
0e74fac5
Commit
0e74fac5
authored
Aug 10, 2019
by
Anon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add basic file transfer implementation
parent
5c94d18f
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
647 additions
and
185 deletions
+647
-185
app/src/main/java/com/github/antweb/donkey/ConnectionService.kt
...c/main/java/com/github/antweb/donkey/ConnectionService.kt
+115
-1
app/src/main/java/com/github/antweb/donkey/Debug.kt
app/src/main/java/com/github/antweb/donkey/Debug.kt
+9
-0
app/src/main/java/com/github/antweb/donkey/DeviceListAdapter.kt
...c/main/java/com/github/antweb/donkey/DeviceListAdapter.kt
+0
-1
app/src/main/java/com/github/antweb/donkey/FileTransfer.kt
app/src/main/java/com/github/antweb/donkey/FileTransfer.kt
+0
-72
app/src/main/java/com/github/antweb/donkey/GattListener.kt
app/src/main/java/com/github/antweb/donkey/GattListener.kt
+9
-0
app/src/main/java/com/github/antweb/donkey/ScanActivity.kt
app/src/main/java/com/github/antweb/donkey/ScanActivity.kt
+1
-5
app/src/main/java/com/github/antweb/donkey/SendActivity.kt
app/src/main/java/com/github/antweb/donkey/SendActivity.kt
+83
-93
app/src/main/java/com/github/antweb/donkey/file/ChunkedReader.kt
.../main/java/com/github/antweb/donkey/file/ChunkedReader.kt
+78
-0
app/src/main/java/com/github/antweb/donkey/file/FileTransfer.kt
...c/main/java/com/github/antweb/donkey/file/FileTransfer.kt
+129
-0
app/src/main/java/com/github/antweb/donkey/file/FileTransferListener.kt
...ava/com/github/antweb/donkey/file/FileTransferListener.kt
+6
-0
app/src/main/java/com/github/antweb/donkey/file/LowEffortService.kt
...in/java/com/github/antweb/donkey/file/LowEffortService.kt
+87
-0
app/src/main/java/com/github/antweb/donkey/file/OnPacketReceivedListener.kt
...com/github/antweb/donkey/file/OnPacketReceivedListener.kt
+7
-0
app/src/main/java/com/github/antweb/donkey/file/protocol/InvalidPacketException.kt
...hub/antweb/donkey/file/protocol/InvalidPacketException.kt
+3
-0
app/src/main/java/com/github/antweb/donkey/file/protocol/Packet.kt
...ain/java/com/github/antweb/donkey/file/protocol/Packet.kt
+45
-0
app/src/main/java/com/github/antweb/donkey/file/protocol/PacketType.kt
...java/com/github/antweb/donkey/file/protocol/PacketType.kt
+12
-0
app/src/main/java/com/github/antweb/donkey/file/protocol/TransferState.kt
...a/com/github/antweb/donkey/file/protocol/TransferState.kt
+9
-0
app/src/main/res/layout/activity_send.xml
app/src/main/res/layout/activity_send.xml
+54
-13
No files found.
app/src/main/java/com/github/antweb/donkey/ConnectionService.kt
View file @
0e74fac5
package
com.github.antweb.donkey
import
android.bluetooth.BluetoothDevice
import
android.bluetooth.*
import
android.content.Context
import
android.util.Log
import
com.github.antweb.donkey.file.LowEffortService
import
java.lang.IllegalStateException
import
java.lang.NullPointerException
import
java.util.*
private
const
val
TAG
=
"ConnectionService"
object
ConnectionService
{
var
device
:
BluetoothDevice
?
=
null
var
leService
:
LowEffortService
?
=
null
var
mtu
=
100
private
var
connection
:
BluetoothGatt
?
=
null
private
var
connectionState
=
BluetoothGatt
.
STATE_DISCONNECTED
private
var
gattListeners
=
mutableListOf
<
GattListener
>()
private
const
val
serviceUuid
=
"00422342-2342-2342-2342-234223422342"
val
deviceName
:
String
?
get
()
=
device
?.
name
...
...
@@ -14,4 +31,101 @@ object ConnectionService {
fun
hasDevice
():
Boolean
{
return
device
!=
null
}
fun
isConnected
()
=
connectionState
==
BluetoothGatt
.
STATE_CONNECTED
fun
addGattListener
(
listener
:
GattListener
)
{
gattListeners
.
add
(
listener
)
}
fun
connect
(
context
:
Context
)
{
if
(
device
==
null
)
{
throw
IllegalStateException
()
}
// 1. Connect
// 2. Discover services
// 3. Change MTU
// 4. ???
// 5. Profit
connection
=
device
?.
connectGatt
(
context
,
true
,
gattCallback
,
BluetoothDevice
.
TRANSPORT_LE
)
}
private
val
gattCallback
=
object
:
BluetoothGattCallback
()
{
override
fun
onServicesDiscovered
(
gatt
:
BluetoothGatt
?,
status
:
Int
)
{
if
(
gatt
==
null
)
{
throw
NullPointerException
()
}
connection
=
gatt
for
(
service
in
gatt
.
services
)
{
Log
.
d
(
TAG
,
"Found service: ${service.uuid}"
)
if
(
service
.
uuid
.
toString
()
==
serviceUuid
)
{
leService
=
LowEffortService
(
service
)
}
}
if
(
leService
==
null
)
{
Log
.
e
(
TAG
,
"Could not find file transfer service"
)
return
}
gatt
.
requestMtu
(
mtu
)
// leService?.enableNotify(gatt)
}
override
fun
onConnectionStateChange
(
gatt
:
BluetoothGatt
?,
status
:
Int
,
newState
:
Int
)
{
connectionState
=
newState
connection
=
gatt
gattListeners
.
map
{
it
.
onConnectionStateChange
(
newState
)
}
when
(
newState
)
{
BluetoothGatt
.
STATE_CONNECTED
->
{
gatt
?.
discoverServices
()
}
}
}
override
fun
onMtuChanged
(
gatt
:
BluetoothGatt
?,
mtu
:
Int
,
status
:
Int
)
{
Log
.
d
(
TAG
,
"MTU changed to: $mtu"
)
if
(
gatt
==
null
)
{
throw
IllegalStateException
()
}
leService
?.
enableNotify
(
gatt
)
}
override
fun
onCharacteristicWrite
(
gatt
:
BluetoothGatt
?,
characteristic
:
BluetoothGattCharacteristic
?,
status
:
Int
)
{
if
(
gatt
==
null
||
characteristic
==
null
)
{
throw
IllegalStateException
()
}
connection
=
gatt
gattListeners
.
map
{
it
.
onCharacteristicWrite
(
characteristic
,
status
)
}
}
override
fun
onCharacteristicChanged
(
gatt
:
BluetoothGatt
?,
characteristic
:
BluetoothGattCharacteristic
?)
{
connection
=
gatt
if
(
gatt
==
null
||
characteristic
==
null
)
{
throw
IllegalStateException
()
}
gattListeners
.
map
{
it
.
onCharacteristicChanged
(
characteristic
)
}
}
}
fun
writeCharacteristic
(
characteristic
:
BluetoothGattCharacteristic
):
Boolean
{
return
connection
?.
writeCharacteristic
(
characteristic
)
?:
false
}
}
\ No newline at end of file
app/src/main/java/com/github/antweb/donkey/Debug.kt
0 → 100644
View file @
0e74fac5
package
com.github.antweb.donkey
fun
toHex
(
bytes
:
ByteArray
):
String
{
val
sb
=
StringBuilder
()
for
(
b
in
bytes
)
{
sb
.
append
(
String
.
format
(
"%02X "
,
b
))
}
return
sb
.
toString
()
}
\ No newline at end of file
app/src/main/java/com/github/antweb/donkey/DeviceListAdapter.kt
View file @
0e74fac5
...
...
@@ -7,7 +7,6 @@ import android.view.View
import
android.view.ViewGroup
import
android.widget.ArrayAdapter
import
android.widget.TextView
import
kotlinx.android.synthetic.main.activity_main.view.*
class
DeviceListAdapter
(
context
:
Context
,
private
val
list
:
ArrayList
<
BluetoothDevice
>
=
ArrayList
())
:
ArrayAdapter
<
BluetoothDevice
>(
context
,
android
.
R
.
layout
.
simple_list_item_1
,
list
)
{
...
...
app/src/main/java/com/github/antweb/donkey/FileTransfer.kt
deleted
100644 → 0
View file @
5c94d18f
package
com.github.antweb.donkey
import
android.bluetooth.BluetoothGatt
import
android.bluetooth.BluetoothGattCharacteristic
import
android.os.Environment
import
java.io.BufferedInputStream
import
java.io.File
import
java.io.FileInputStream
import
java.nio.ByteBuffer
class
FileTransfer
(
private
val
gatt
:
BluetoothGatt
,
private
val
dataCharacteristic
:
BluetoothGattCharacteristic
,
private
val
mtu
:
Int
)
{
private
val
filePath
=
"/Download/SEND.txt"
private
val
iterator
=
openFile
().
iterator
()
private
var
offset
:
Int
=
0
private
fun
openFile
():
ByteArray
{
// TODO: Don't listen to Android Docs, use stuff that is not deprecated
val
file
=
File
(
Environment
.
getExternalStorageDirectory
()
.
absolutePath
,
filePath
)
val
size
=
file
.
length
()
val
bytes
=
ByteArray
(
size
.
toInt
())
val
buf
=
BufferedInputStream
(
FileInputStream
(
file
))
buf
.
read
(
bytes
,
0
,
bytes
.
size
)
buf
.
close
()
return
bytes
}
fun
sendFile
()
{
// Send first chunk
sendNext
()
}
fun
sendNext
()
{
if
(!
iterator
.
hasNext
())
{
return
}
gatt
?.
beginReliableWrite
()
val
chunk
=
mutableListOf
<
Byte
>()
for
(
i
in
0
until
(
mtu
-
5
))
{
chunk
.
add
(
iterator
.
next
())
}
// Our packet:
// 4 byte header + chunk
val
header
=
offset
offset
+=
chunk
.
size
val
sendBuffer
=
ByteBuffer
.
allocate
(
chunk
.
size
+
4
)
sendBuffer
.
putInt
(
header
)
sendBuffer
.
put
(
chunk
.
toByteArray
())
dataCharacteristic
?.
value
=
sendBuffer
.
array
()
gatt
?.
writeCharacteristic
(
dataCharacteristic
)
// This will trigger the onCharacteristicWrite callback once the other side ACKs
// In there, we can call the actual gatt?.executeReliableWrite()
}
}
\ No newline at end of file
app/src/main/java/com/github/antweb/donkey/GattListener.kt
0 → 100644
View file @
0e74fac5
package
com.github.antweb.donkey
import
android.bluetooth.BluetoothGattCharacteristic
interface
GattListener
{
fun
onCharacteristicWrite
(
characteristic
:
BluetoothGattCharacteristic
,
status
:
Int
)
{}
fun
onCharacteristicChanged
(
characteristic
:
BluetoothGattCharacteristic
)
{}
fun
onConnectionStateChange
(
state
:
Int
)
{}
}
\ No newline at end of file
app/src/main/java/com/github/antweb/donkey/ScanActivity.kt
View file @
0e74fac5
...
...
@@ -14,11 +14,6 @@ private const val TAG = "ScanActivity"
class
ScanActivity
:
AppCompatActivity
()
{
// TODO: Figure out how to transfer this later
companion
object
{
var
selectedDevice
:
BluetoothDevice
?
=
null
}
private
lateinit
var
listView
:
ListView
private
lateinit
var
listAdapter
:
DeviceListAdapter
...
...
@@ -42,6 +37,7 @@ class ScanActivity : AppCompatActivity() {
if
(
item
!=
null
)
{
ConnectionService
.
device
=
item
ConnectionService
.
connect
(
this
)
val
intent
=
Intent
(
this
,
MainActivity
::
class
.
java
)
startActivity
(
intent
)
}
...
...
app/src/main/java/com/github/antweb/donkey/SendActivity.kt
View file @
0e74fac5
package
com.github.antweb.donkey
import
android.bluetooth.*
import
android.content.Intent
import
android.net.Uri
import
android.os.Bundle
import
android.util.Log
import
android.view.View
import
android.widget.Button
import
android.widget.ProgressBar
import
android.widget.TextView
import
androidx.appcompat.app.AppCompatActivity
import
com.github.antweb.donkey.file.ChunkedReader
import
com.github.antweb.donkey.file.FileTransfer
import
java.lang.NullPointerException
import
java.util.*
import
com.github.antweb.donkey.file.FileTransferListener
import
java.lang.Exception
import
java.lang.IllegalStateException
private
const
val
TAG
=
"SendActivity"
private
const
val
INTENT_RESULT_CODE
=
1
class
SendActivity
:
AppCompatActivity
()
{
private
val
mtu
=
128
private
val
serviceUuid
=
"00422342-2342-2342-2342-234223422342"
class
SendActivity
:
AppCompatActivity
(),
GattListener
,
FileTransferListener
{
private
va
l
centralTxCharacteristicUuid
=
UUID
.
fromString
(
"01422342-2342-2342-2342-234223422342"
)
private
va
l
centralRxCharacteristicUuid
=
UUID
.
fromString
(
"02422342-2342-2342-2342-234223422342"
)
private
va
r
isSending
=
false
private
va
r
transfer
:
FileTransfer
?
=
null
private
var
bluetoothGatt
:
BluetoothGatt
?
=
null
private
var
fileService
:
BluetoothGattService
?
=
null
private
var
mGatt
:
BluetoothGatt
?
=
null
private
var
fileTransferService
:
FileTransfer
?
=
null
private
lateinit
var
tvConnection
:
TextView
private
lateinit
var
tvValue
:
TextView
private
lateinit
var
buttonPickFile
:
Button
private
lateinit
var
buttonStartStop
:
Button
private
lateinit
var
tvSelected
:
TextView
private
lateinit
var
tvStatus
:
TextView
private
lateinit
var
progressBar
:
ProgressBar
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
setContentView
(
R
.
layout
.
activity_send
)
tv
Value
=
findViewById
(
R
.
id
.
text_value
)
tv
Connection
=
findViewById
(
R
.
id
.
text_connection
_status
)
tvConnection
.
text
=
"STATE_DISCONNECTED"
tv
Selected
=
findViewById
(
R
.
id
.
label_selected
)
tv
Status
=
findViewById
(
R
.
id
.
label
_status
)
progressBar
=
findViewById
(
R
.
id
.
progress
)
val
device
=
ScanActivity
.
selectedDevice
if
(
device
!=
null
)
{
connect
(
device
)
}
else
{
Log
.
e
(
TAG
,
"Device is NULL!"
)
buttonPickFile
=
findViewById
(
R
.
id
.
button_pick_file
)
buttonPickFile
.
setOnClickListener
{
val
intent
=
Intent
(
Intent
.
ACTION_GET_CONTENT
)
intent
.
addCategory
(
Intent
.
CATEGORY_OPENABLE
)
intent
.
type
=
"*/*"
startActivityForResult
(
intent
,
INTENT_RESULT_CODE
)
}
}
fun
connect
(
device
:
BluetoothDevice
)
{
val
gattCallback
=
object
:
BluetoothGattCallback
()
{
override
fun
onServicesDiscovered
(
gatt
:
BluetoothGatt
?,
status
:
Int
)
{
if
(
gatt
==
null
)
{
throw
NullPointerException
()
}
buttonStartStop
=
findViewById
(
R
.
id
.
button_start_stop_transfer
)
for
(
service
in
gatt
.
services
)
{
Log
.
d
(
TAG
,
"Found service: ${service.uuid}"
)
toggleControls
()
}
if
(
service
.
uuid
.
toString
()
==
serviceUuid
)
{
fileService
=
service
}
}
override
fun
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
?
)
{
if
(
requestCode
!=
INTENT_RESULT_CODE
)
{
return
}
if
(
fileService
==
null
)
{
Log
.
e
(
TAG
,
"Could not find file transfer service"
)
return
}
val
uri
=
data
?.
data
?:
return
gatt
.
requestMtu
(
mtu
)
}
try
{
val
reader
=
ChunkedReader
(
this
,
uri
,
ConnectionService
.
mtu
)
val
service
=
ConnectionService
.
leService
?:
throw
IllegalStateException
()
override
fun
onConnectionStateChange
(
gatt
:
BluetoothGatt
?,
status
:
Int
,
newState
:
Int
)
{
when
(
newState
)
{
BluetoothGatt
.
STATE_CONNECTED
->
{
runOnUiThread
{
tvConnection
.
text
=
"STATE_CONNECTED"
}
mGatt
=
gatt
gatt
?.
discoverServices
()
}
BluetoothGatt
.
STATE_DISCONNECTED
->
tvConnection
.
text
=
"STATE_DISCONNECTED"
BluetoothGatt
.
STATE_CONNECTING
->
tvConnection
.
text
=
"STATE_CONNECTING"
BluetoothGatt
.
STATE_DISCONNECTING
->
tvConnection
.
text
=
"STATE_DISCONNECTING"
}
}
transfer
=
FileTransfer
(
service
,
reader
,
this
)
}
catch
(
e
:
Exception
)
{
Log
.
e
(
TAG
,
"Failed to initialize transfer"
)
return
}
override
fun
onCharacteristicChanged
(
gatt
:
BluetoothGatt
?,
characteristic
:
BluetoothGattCharacteristic
?)
{
super
.
onCharacteristicChanged
(
gatt
,
characteristic
)
}
buttonStartStop
.
isEnabled
=
true
tvSelected
.
text
=
uri
.
path
}
override
fun
onCharacteristicRead
(
gatt
:
BluetoothGatt
?,
characteristic
:
BluetoothGattCharacteristic
?,
status
:
Int
)
{
super
.
onCharacteristicRead
(
gatt
,
characteristic
,
status
)
}
private
fun
toggleControls
()
{
if
(
isSending
)
{
progressBar
.
visibility
=
View
.
VISIBLE
buttonPickFile
.
isEnabled
=
false
buttonStartStop
.
text
=
getString
(
R
.
string
.
send_button_stop_transfer
)
override
fun
onMtuChanged
(
gatt
:
BluetoothGatt
?,
mtu
:
Int
,
status
:
Int
)
{
Log
.
d
(
TAG
,
"MTU changed to: $mtu"
)
buttonStartStop
.
setOnClickListener
{
transfer
?.
abort
()
transfer
=
null
isSending
=
false
runOnUiThread
{
t
vValue
.
text
=
"MTU: $mtu"
t
oggleControls
()
}
}
}
else
{
progressBar
.
visibility
=
View
.
INVISIBLE
buttonPickFile
.
isEnabled
=
true
buttonStartStop
.
text
=
getString
(
R
.
string
.
send_button_start_transfer
)
val
tx
=
fileService
?.
getCharacteristic
(
centralTxCharacteristicUuid
)
val
rx
=
fileService
?.
getCharacteristic
(
centralRxCharacteristicUuid
)
if
(
gatt
!=
null
&&
tx
!=
null
&&
rx
!=
null
)
{
val
notifySuccess
=
gatt
.
setCharacteristicNotification
(
rx
,
true
)
if
(!
notifySuccess
)
{
Log
.
e
(
TAG
,
"Notify enable failed"
)
}
buttonStartStop
.
setOnClickListener
{
transfer
?.
start
()
isSending
=
true
// fileTransferService = FileTransfer("/Download/SEND.txt", mtu)
// fileTransferService?.sendFile()
runOnUiThread
{
tvStatus
.
text
=
"STARTED"
toggleControls
()
}
}
}
override
fun
onCharacteristicWrite
(
gatt
:
BluetoothGatt
?,
characteristic
:
BluetoothGattCharacteristic
?,
status
:
Int
)
{
// Thread.sleep(3000)
// fileTransferService?.sendNext()
// return
}
buttonStartStop
.
isEnabled
=
transfer
!=
null
}
override
fun
onError
()
{
runOnUiThread
{
tvStatus
.
text
=
"ERROR"
}
}
override
fun
onFinish
()
{
isSending
=
false
transfer
=
null
bluetoothGatt
=
device
.
connectGatt
(
this
,
true
,
gattCallback
,
BluetoothDevice
.
TRANSPORT_LE
)
runOnUiThread
{
tvStatus
.
text
=
"FINISHED"
toggleControls
()
}
}
}
\ No newline at end of file
app/src/main/java/com/github/antweb/donkey/file/ChunkedReader.kt
0 → 100644
View file @
0e74fac5
package
com.github.antweb.donkey.file
import
android.content.Context
import
android.net.Uri
import
android.util.Log
import
com.github.antweb.donkey.file.protocol.Packet
import
com.github.antweb.donkey.file.protocol.PacketType
import
java.lang.IllegalStateException
import
java.nio.ByteBuffer
import
java.nio.charset.Charset
private
const
val
TAG
=
"ChunkedReader"
class
ChunkedReader
(
context
:
Context
,
uri
:
Uri
,
private
val
mtu
:
Int
)
{
private
val
iterator
:
Iterator
<
Byte
>
private
var
lastPacket
:
Packet
?
=
null
init
{
val
inputStream
=
context
.
getContentResolver
().
openInputStream
(
uri
)
?:
throw
IllegalStateException
()
val
bytes
=
inputStream
.
readBytes
()
iterator
=
bytes
.
iterator
()
}
private
var
offset
:
Int
=
0
private
var
lastCrc
:
Long
=
0
fun
verifyCrc
(
crc
:
Long
):
Boolean
=
(
lastCrc
==
crc
)
fun
isDone
()
=
!
iterator
.
hasNext
()
fun
getLast
():
Packet
{
return
lastPacket
?:
throw
IllegalStateException
()
}
fun
getNext
():
Packet
{
Log
.
d
(
TAG
,
"Next chunk: $offset"
)
if
(!
iterator
.
hasNext
())
{
throw
IndexOutOfBoundsException
()
}
// Our packet:
// 1 byte header + 4 byte offset + chunk
val
maxChunkSize
=
mtu
-
5
-
10
val
buffer
=
ByteBuffer
.
allocate
(
mtu
-
11
)
buffer
.
putInt
(
offset
)
// TODO: Make less hacky
var
n
=
0
for
(
i
in
0
until
maxChunkSize
)
{
if
(!
iterator
.
hasNext
())
{
break
}
buffer
.
put
(
iterator
.
next
())
n
++
}
var
byteArray
=
buffer
.
array
().
sliceArray
(
0
..
n
)
offset
+=
n
val
packet
=
Packet
(
PacketType
.
CHUNK
,
byteArray
)
lastCrc
=
packet
.
getCrc
()
lastPacket
=
packet
return
packet
}
}
\ No newline at end of file
app/src/main/java/com/github/antweb/donkey/file/FileTransfer.kt
0 → 100644
View file @
0e74fac5
package
com.github.antweb.donkey.file
import
android.util.Log
import
com.github.antweb.donkey.file.protocol.Packet
import
com.github.antweb.donkey.file.protocol.PacketType
import
com.github.antweb.donkey.file.protocol.TransferState
import
com.github.antweb.donkey.toHex
import
java.nio.Buffer
import
java.nio.charset.Charset
private
const
val
TAG
=
"FileTransfer"
class
FileTransfer
(
private
val
service
:
LowEffortService
,
private
val
reader
:
ChunkedReader
,
private
var
listener
:
FileTransferListener
)
:
OnPacketReceivedListener
{
private
var
currentState
=
TransferState
.
IDLE
init
{
service
.
addOnPacketReceivedListener
(
this
)
}
override
fun
onPacketReceived
(
packet
:
Packet
)
{
Log
.
d
(
TAG
,
"Received packet ${packet.type.prefix} ${toHex(packet.payload)}"
)
Log
.
d
(
TAG
,
"Received packet ${packet.type.prefix} ${String(packet.payload, Charset.defaultCharset())}"
)
when
(
packet
.
type
)
{
PacketType
.
START_ACK
->
{
if
(
currentState
!=
TransferState
.
START_SENT
)
{
abort
()
}
else
{
currentState
=
TransferState
.
READY_TO_SEND