feat: api integration
This commit is contained in:
@@ -7,91 +7,27 @@ import android.bluetooth.BluetoothGatt
|
||||
import android.bluetooth.BluetoothGattCharacteristic
|
||||
import android.bluetooth.BluetoothGattDescriptor
|
||||
import android.bluetooth.le.ScanResult
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.android.volley.Request
|
||||
import com.android.volley.RequestQueue
|
||||
import com.android.volley.toolbox.JsonObjectRequest
|
||||
import com.android.volley.toolbox.Volley
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.Base64
|
||||
import java.util.EnumSet
|
||||
import java.util.UUID
|
||||
import java.util.stream.Collectors
|
||||
|
||||
|
||||
private val DEMO_SERVICE_UUID = UUID.fromString("00000000-0001-11E1-9AB4-0002A5D5C51B")
|
||||
private val DEMO_CHAR_UUID = UUID.fromString("00140000-0001-11E1-AC36-0002A5D5C51B")
|
||||
|
||||
data class DemoPayload(
|
||||
val ts: Int,
|
||||
val pressure: Float,
|
||||
val temperature: Float,
|
||||
val sysTs: String = LocalDateTime.now()
|
||||
.format(DateTimeFormatter.ofPattern("HH:mm:ss"))
|
||||
)
|
||||
|
||||
|
||||
fun bytesToUInt16(arr: ByteArray, start: Int): Int {
|
||||
return ByteBuffer.wrap(arr, start, 2)
|
||||
.order(ByteOrder.LITTLE_ENDIAN).short.toInt() and 0xFFFF
|
||||
}
|
||||
|
||||
fun bytesToInt16(arr: ByteArray, start: Int): Short {
|
||||
return ByteBuffer.wrap(arr, start, 2)
|
||||
.order(ByteOrder.LITTLE_ENDIAN).short
|
||||
}
|
||||
|
||||
fun bytesToInt32(arr: ByteArray, start: Int): Int {
|
||||
return ByteBuffer.wrap(arr, start, 4)
|
||||
.order(ByteOrder.LITTLE_ENDIAN).int
|
||||
}
|
||||
|
||||
|
||||
fun decodeDemoPayload(bytes: ByteArray): DemoPayload {
|
||||
val ts = bytesToUInt16(bytes, 0)
|
||||
val pressure = bytesToInt32(bytes, 2) / 100.0f
|
||||
val temp = bytesToInt16(bytes, 6) / 10.0f;
|
||||
return DemoPayload(ts, pressure, temp)
|
||||
}
|
||||
|
||||
private fun demoPayloadToMeasurements(payload: DemoPayload): List<Measurement> {
|
||||
return listOf(object : Measurement {
|
||||
override fun getLabel(): String {
|
||||
return "TS"
|
||||
}
|
||||
|
||||
override fun getFormattedValue(): String {
|
||||
return "${payload.sysTs} (${payload.ts})"
|
||||
}
|
||||
|
||||
override fun getIcon(): Int? {
|
||||
return R.drawable.baseline_access_time_24
|
||||
}
|
||||
}, object : Measurement {
|
||||
override fun getLabel(): String {
|
||||
return "Temperature"
|
||||
}
|
||||
|
||||
override fun getFormattedValue(): String {
|
||||
return "${payload.temperature} °C"
|
||||
}
|
||||
|
||||
override fun getIcon(): Int? {
|
||||
return R.drawable.baseline_device_thermostat_24
|
||||
}
|
||||
|
||||
}, object : Measurement {
|
||||
override fun getLabel(): String {
|
||||
return "Pressure"
|
||||
}
|
||||
|
||||
override fun getFormattedValue(): String {
|
||||
return "${payload.pressure} hPa"
|
||||
}
|
||||
|
||||
override fun getIcon(): Int? {
|
||||
return R.drawable.baseline_compress_24
|
||||
}
|
||||
})
|
||||
}
|
||||
// Kirby service uuid: 6e400001-b5a3-f393-e1a9-e50e24dcac9e
|
||||
private val DEMO_SERVICE_UUID = UUID.fromString("6e400001-b5a3-f393-e1a9-e50e24dcac9e")
|
||||
private val DEMO_CHAR_UUID = UUID.fromString("6e400005-b5a3-f393-e1a9-e50e24dcac9e")
|
||||
|
||||
enum class DeviceStatus {
|
||||
CONNECTED, BONDED, SUBSCRIBED, MISSING
|
||||
@@ -99,11 +35,13 @@ enum class DeviceStatus {
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
class KirbyDevice(
|
||||
private val context: Context,
|
||||
private val connectionManager: ConnectionManager,
|
||||
private val bleDevice: BluetoothDevice,
|
||||
private val onStateChange: (device: KirbyDevice) -> Unit
|
||||
) : BleListener(bleDevice.address), DeviceListEntry {
|
||||
private val onStateChange: (device: KirbyDevice) -> Unit,
|
||||
|
||||
) : BleListener(bleDevice.address), DeviceListEntry {
|
||||
private val queue : RequestQueue = Volley.newRequestQueue(context)
|
||||
|
||||
override fun onScanResult(callbackType: Int, result: ScanResult) {
|
||||
rssi = result.rssi
|
||||
@@ -179,13 +117,42 @@ class KirbyDevice(
|
||||
|
||||
private fun addMeasurement(characteristic: BluetoothGattCharacteristic) {
|
||||
if (characteristic.service.uuid == DEMO_SERVICE_UUID && characteristic.uuid == DEMO_CHAR_UUID) {
|
||||
val payload = decodeDemoPayload(characteristic.value)
|
||||
|
||||
val hexPayload = characteristic.value.toHexString()
|
||||
val payload = Payload(hexPayload)
|
||||
val base64Payload = Base64.getEncoder().encodeToString(characteristic.value)
|
||||
Log.i("BleListener", "Demo char received: $payload")
|
||||
measurements.add(payload)
|
||||
publishMeasurement(base64Payload)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private val measurements = ArrayList<DemoPayload>()
|
||||
private fun publishMeasurement(payload: String) {
|
||||
val accessKey = BuildConfig.API_BASE_URL
|
||||
val url = BuildConfig.API_KEY
|
||||
val eui = "0000${bleDevice.address}"
|
||||
|
||||
val postData = JSONObject()
|
||||
try {
|
||||
postData.put("accessKey", accessKey)
|
||||
postData.put("metricPayload", payload)
|
||||
postData.put("eui", eui)
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
val request = JsonObjectRequest(
|
||||
Request.Method.POST, url, postData,
|
||||
{ response ->
|
||||
Log.i("sendDataResponse","Response is: $response")
|
||||
}
|
||||
) { error -> error.printStackTrace() }
|
||||
|
||||
queue.add(request)
|
||||
}
|
||||
|
||||
private val measurements = ArrayList<Payload>()
|
||||
|
||||
private val statuses = EnumSet.noneOf(DeviceStatus::class.java)
|
||||
|
||||
@@ -223,7 +190,7 @@ class KirbyDevice(
|
||||
return measurements.size.toString()
|
||||
}
|
||||
})
|
||||
result.addAll(demoPayloadToMeasurements(latest))
|
||||
result.addAll(payloadToMeasurements(latest))
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -365,4 +332,60 @@ class KirbyDevice(
|
||||
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
|
||||
data class Payload(
|
||||
val payload: String,
|
||||
val ts: String = LocalDateTime.now()
|
||||
.format(DateTimeFormatter.ofPattern("HH:mm:ss"))
|
||||
)
|
||||
|
||||
|
||||
|
||||
fun bytesToUInt16(arr: ByteArray, start: Int): Int {
|
||||
return ByteBuffer.wrap(arr, start, 2)
|
||||
.order(ByteOrder.LITTLE_ENDIAN).short.toInt() and 0xFFFF
|
||||
}
|
||||
|
||||
fun bytesToInt16(arr: ByteArray, start: Int): Short {
|
||||
return ByteBuffer.wrap(arr, start, 2)
|
||||
.order(ByteOrder.LITTLE_ENDIAN).short
|
||||
}
|
||||
|
||||
fun bytesToInt32(arr: ByteArray, start: Int): Int {
|
||||
return ByteBuffer.wrap(arr, start, 4)
|
||||
.order(ByteOrder.LITTLE_ENDIAN).int
|
||||
}
|
||||
|
||||
|
||||
private fun payloadToMeasurements(payload: Payload): List<Measurement> {
|
||||
return listOf(object : Measurement {
|
||||
override fun getLabel(): String {
|
||||
return "TS"
|
||||
}
|
||||
|
||||
override fun getFormattedValue(): String {
|
||||
return "${payload.ts}"
|
||||
}
|
||||
|
||||
override fun getIcon(): Int? {
|
||||
return R.drawable.baseline_access_time_24
|
||||
}
|
||||
},
|
||||
object : Measurement {
|
||||
override fun getLabel(): String {
|
||||
return "Payload"
|
||||
}
|
||||
|
||||
override fun getFormattedValue(): String {
|
||||
return payload.payload
|
||||
}
|
||||
|
||||
override fun getIcon(): Int? {
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
)
|
||||
}
|
||||
@@ -103,6 +103,7 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun isKirbyDevice(device: BluetoothDevice): Boolean {
|
||||
Log.i("kby", "found device ${device.name}")
|
||||
return (device.name ?: "").lowercase().contains("kirby")
|
||||
}
|
||||
|
||||
@@ -177,7 +178,8 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun newKirbyDevice(bleDevice: BluetoothDevice): KirbyDevice {
|
||||
val device = KirbyDevice(connectionManager, bleDevice) {
|
||||
|
||||
val device = KirbyDevice( this.applicationContext, connectionManager, bleDevice) {
|
||||
val i = kirbyDevices.indexOfFirst { d -> d === it }
|
||||
runOnUiThread {
|
||||
deviceListAdapter.notifyItemChanged(i)
|
||||
|
||||
Reference in New Issue
Block a user