From 1c942a10b3387bc25152205dc7c73d71d18f6abc Mon Sep 17 00:00:00 2001 From: geeksville Date: Tue, 21 Jan 2020 12:07:03 -0800 Subject: [PATCH] first test --- TODO.md | 2 + .../com/geeksville/meshutil/MainActivity.kt | 2 + .../meshutil/SoftwareUpdateService.kt | 48 ++++++++++++++++--- app/src/main/res/values/firmwareversion.xml | 3 ++ 4 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 app/src/main/res/values/firmwareversion.xml diff --git a/TODO.md b/TODO.md index a695a98c1..e7369c7e1 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,8 @@ # Medium priority +* require user auth to pair with the device (i.e. press button on device to allow a new phone to pair with it). +Don't leave device discoverable. Don't let unpaired users do thing with device * add crash reporting * remove example code boilerplate from the service * add analytics (make them optional) diff --git a/app/src/main/java/com/geeksville/meshutil/MainActivity.kt b/app/src/main/java/com/geeksville/meshutil/MainActivity.kt index efa1f97c3..1db701ae8 100644 --- a/app/src/main/java/com/geeksville/meshutil/MainActivity.kt +++ b/app/src/main/java/com/geeksville/meshutil/MainActivity.kt @@ -42,6 +42,8 @@ class MainActivity : AppCompatActivity() { val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT) } + + SoftwareUpdateService.enqueueWork(this, SoftwareUpdateService.scanDevicesIntent) } override fun onCreateOptionsMenu(menu: Menu): Boolean { diff --git a/app/src/main/java/com/geeksville/meshutil/SoftwareUpdateService.kt b/app/src/main/java/com/geeksville/meshutil/SoftwareUpdateService.kt index 69a609466..d48e602df 100644 --- a/app/src/main/java/com/geeksville/meshutil/SoftwareUpdateService.kt +++ b/app/src/main/java/com/geeksville/meshutil/SoftwareUpdateService.kt @@ -9,6 +9,7 @@ import android.util.Log import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.core.app.JobIntentService +import java.io.InputStream import java.util.* @@ -36,13 +37,17 @@ class SoftwareUpdateService : JobIntentService() { lateinit var updateGatt: BluetoothGatt // the gatt api used to talk to our device lateinit var updateService: BluetoothGattService // The service we are currently talking to to do the update lateinit var totalSizeDesc: BluetoothGattCharacteristic + lateinit var dataDesc: BluetoothGattCharacteristic + lateinit var firmwareStream: InputStream fun startUpdate() { if (updateService != null) { totalSizeDesc = updateService.getCharacteristic(SW_UPDATE_TOTALSIZE_CHARACTER)!! + firmwareStream = assets.open("firmware.bin")!! + // Start the update by writing the # of bytes in the image - val numBytes = 45 + val numBytes = firmwareStream.available() assert(totalSizeDesc.setValue(numBytes, BluetoothGattCharacteristic.FORMAT_UINT32, 0)) assert(updateGatt.writeCharacteristic(totalSizeDesc)) assert(updateGatt.readCharacteristic(totalSizeDesc)) @@ -51,7 +56,24 @@ class SoftwareUpdateService : JobIntentService() { // Send the next block of our file to the device fun sendNextBlock() { + if(firmwareStream.available() > 0) { + var blockSize = 512 + if (blockSize > firmwareStream.available()) + blockSize = firmwareStream.available() + val buffer = ByteArray(blockSize) + + // slightly expensive to keep reallocing this buffer, but whatever + assert(firmwareStream.read(buffer) == blockSize) + + dataDesc = updateService.getCharacteristic(SW_UPDATE_DATA_CHARACTER)!! + // updateGatt.beginReliableWrite() + dataDesc.value = buffer + assert(updateGatt.writeCharacteristic(dataDesc)) + } + else { + assert(false) // fixme + } } // For each device that appears in our scan, ask for its GATT, when the gatt arrives, @@ -75,16 +97,11 @@ class SoftwareUpdateService : JobIntentService() { //intentAction = ACTION_GATT_CONNECTED //connectionState = STATE_CONNECTED // broadcastUpdate(intentAction) - Log.i(AppCompatActivity.TAG, "Connected to GATT server.") - Log.i( - AppCompatActivity.TAG, "Attempting to start service discovery: " - ) assert(bluetoothGatt.discoverServices()) } BluetoothProfile.STATE_DISCONNECTED -> { //intentAction = ACTION_GATT_DISCONNECTED //connectionState = STATE_DISCONNECTED - Log.i(AppCompatActivity.TAG, "Disconnected from GATT server.") // broadcastUpdate(intentAction) } } @@ -127,6 +144,18 @@ class SoftwareUpdateService : JobIntentService() { // broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic) } + + override fun onCharacteristicWrite( + gatt: BluetoothGatt?, + characteristic: BluetoothGattCharacteristic?, + status: Int + ) { + assert(status == BluetoothGatt.GATT_SUCCESS) + + if (characteristic == dataDesc) { + enqueueWork(this@SoftwareUpdateService, sendNextBlockIntent) + } + } } bluetoothGatt = device.connectGatt(this, false, gattCallback)!! } @@ -158,6 +187,13 @@ class SoftwareUpdateService : JobIntentService() { } toast("Executing: $label") + when(intent.action) { + scanDevicesIntent.action -> scanLeDevice(true) + startUpdateIntent.action -> startUpdate() + sendNextBlockIntent.action -> sendNextBlock() + else -> assert(false) + } + Log.i( "SimpleJobIntentService", "Completed service @ " + SystemClock.elapsedRealtime() diff --git a/app/src/main/res/values/firmwareversion.xml b/app/src/main/res/values/firmwareversion.xml new file mode 100644 index 000000000..b4bc9818d --- /dev/null +++ b/app/src/main/res/values/firmwareversion.xml @@ -0,0 +1,3 @@ + + 0.1.01 + \ No newline at end of file