Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
* develop:
  core and ble updates. Cleanup
  updated core
  updated gradle,core dependencies
  update core and add power level
  updated sdk-ble-android
  Added spota and FW update functionality to XyoSentinelX
  update core
  update core
  remove special uuid
  build correct service
  use le trqansport
  updated sdk-ble sdk
  updated sdk-ble sdk
  updated sdk-ble sdk
  fix getPublicKey
  Update README.md
  • Loading branch information
Bob Nies committed Apr 23, 2019
2 parents dc4e71b + 43ace7a commit e7e2d1b
Show file tree
Hide file tree
Showing 19 changed files with 241 additions and 194 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

# mod-ble-android

[![](https://jitpack.io/v/XYOracleNetwork/mod-ble-android.svg)](https://jitpack.io/#XYOracleNetwork/mod-ble-android) [![](https://img.shields.io/gitter/room/XYOracleNetwork/Stardust.svg)](https://gitter.im/XYOracleNetwork/Dev)
[![](https://jitpack.io/v/XYOracleNetwork/mod-ble-android.svg)](https://jitpack.io/#XYOracleNetwork/mod-ble-android) [![](https://img.shields.io/gitter/room/XYOracleNetwork/Stardust.svg)](https://gitter.im/XYOracleNetwork/Dev) [![DepShield Badge](https://depshield.sonatype.org/badges/XYOracleNetwork/mod-ble-android/depshield.svg)](https://depshield.github.io)

| Branches | Status |
| ------------- |:-------------:|
Expand Down
10 changes: 5 additions & 5 deletions ble-xyo-module/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])

implementation 'com.github.XYOracleNetwork:sdk-core-kotlin:ef4a3e8591'
implementation 'com.github.XYOracleNetwork:sdk-core-android:1.2.5'
implementation 'com.github.XYOracleNetwork:sdk-ble-android:2791225f1e'
implementation 'com.github.XYOracleNetwork:sdk-core-kotlin:0.1.4-beta.2'
implementation 'com.github.XYOracleNetwork:sdk-core-android:1.2.6'
implementation 'com.github.XYOracleNetwork:sdk-ble-android:1.2.3'

testImplementation 'junit:junit:4.12'
testImplementation 'junit:junit:4.13-beta-2'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
}
repositories {
mavenCentral()
Expand Down
3 changes: 1 addition & 2 deletions ble-xyo-module/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="network.xyo.modbluetoothkotlin"/>
<manifest package="network.xyo.modbluetoothkotlin" />
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,22 @@ import java.util.*
* All the XYO Bluetooth UUIDs.
*/
object XyoUuids {
/**
* The primary GATT service that will be advertised.
*/
// The descriptor to use when to manage subscribing to notifications.
val NOTIFY_DESCRIPTOR = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")!!

// The primary GATT service that will be advertised.
var XYO_SERVICE = UUID.fromString("d684352e-df36-484e-bc98-2d5398c5593e")!!

/**
* The GATT characteristic to be written to when creating pipes. This will be in the XYO_SERVICE.
*/
// The GATT characteristic to be written to when creating pipes. This will be in the XYO_SERVICE.
val XYO_PIPE = UUID.fromString("727a3639-0eb4-4525-b1bc-7fa456490b2d")!!

/**
* The password GATT characteristic to write to when changing the password.
*/
// The password GATT characteristic to write to when changing the password.
val XYO_PASSWORD = UUID.fromString("727a3639-0eb4-4525-b1bc-7fa4564A0b2d")!!

/**
* The password bound witness data characteristic characteristic to be written to.
*/
// The password bound witness data characteristic characteristic to be written to.
val XYO_CHANGE_BW_DATA = UUID.fromString("727a3639-0eb4-4525-b1bc-7fa4564B0b2d")!!

val XYO_RESET_DEVICE = UUID.fromString("727a3639-0eb4-4525-b1bc-7fa4564C0b2d")!!

val XYO_PUBLIC_KEY = UUID.fromString("727a3639-0eb4-4525-b1bc-7fa4564D0b2d")

/**
* The descriptor to use when to manage subscribing to notifications.
*/
val NOTIFY_DESCRIPTOR = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")!!
val XYO_PUBLIC_KEY = UUID.fromString("727a3639-0eb4-4525-b1bc-7fa4564D0b2d")!!
}

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ import java.nio.ByteBuffer
* @property minor The device minor to advertise
* @param advertiser The XY advertiser to advertise with.
*/
class XyoBluetoothAdvertiser (private val major : Short, private val minor : Short, private val advertiser: XYBluetoothAdvertiser) {
class XyoBluetoothAdvertiser(
private val major: Short,
private val minor: Short,
private val advertiser: XYBluetoothAdvertiser
) {

/**
* Start a advertisement cycle
*/
Expand All @@ -29,10 +34,18 @@ class XyoBluetoothAdvertiser (private val major : Short, private val minor : Sho
configureAdvertiserSingle()
}

private fun configureAdverserMulti () {
// private fun getAdvertiseUuid (uuid: UUID, major: ByteArray, minor: ByteArray): UUID {
// val uuidString = uuid.toString().dropLast(8)
// val majorString = major.toHexString().drop(2)
// val minorString = minor.toHexString().drop(2)
//
// return UUID.fromString( minorString + majorString + uuidString)
// }

private fun configureAdverserMulti() {
val encodeMajor = ByteBuffer.allocate(2).putShort(major).array()
val encodedMinor = ByteBuffer.allocate(2).putShort(minor).array()
val advertiseData = XYIBeaconAdvertiseDataCreator.create(
val advertiseData = XYIBeaconAdvertiseDataCreator.create(
encodeMajor,
encodedMinor,
XyoUuids.XYO_SERVICE,
Expand All @@ -42,7 +55,9 @@ class XyoBluetoothAdvertiser (private val major : Short, private val minor : Sho

val responseData = AdvertiseData.Builder()
.setIncludeDeviceName(false)
.addServiceUuid(ParcelUuid(XyoUuids.XYO_SERVICE))
.addServiceUuid(ParcelUuid(
XyoUuids.XYO_SERVICE
))
.build()

advertiser.advertisingData = advertiseData
Expand All @@ -52,7 +67,7 @@ class XyoBluetoothAdvertiser (private val major : Short, private val minor : Sho
advertiser.changeAdvertisingTxLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM)
}

private fun configureAdvertiserSingle () {
private fun configureAdvertiserSingle() {
val advertiseData = AdvertiseData.Builder()
.addServiceUuid(ParcelUuid(XyoUuids.XYO_SERVICE))
.setIncludeDeviceName(true)
Expand All @@ -71,7 +86,7 @@ class XyoBluetoothAdvertiser (private val major : Short, private val minor : Sho
advertiser.stopAdvertising()
}

fun startAdvertiser () = GlobalScope.async {
fun startAdvertiser() = GlobalScope.async {
return@async advertiser.startAdvertising()
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
package network.xyo.modbluetoothkotlin.client

import android.annotation.SuppressLint
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic
import android.content.Context
import android.os.Build
import kotlinx.coroutines.*
import network.xyo.ble.devices.XYBluetoothDevice
import network.xyo.ble.devices.XYCreator
import network.xyo.ble.devices.XYIBeaconBluetoothDevice
import network.xyo.ble.gatt.peripheral.XYBluetoothError
import network.xyo.ble.gatt.peripheral.XYBluetoothGattCallback
import network.xyo.ble.gatt.peripheral.XYBluetoothResult
import network.xyo.ble.scanner.XYScanResult
import network.xyo.modbluetoothkotlin.XyoUuids
import network.xyo.modbluetoothkotlin.packet.XyoBluetoothIncomingPacket
import network.xyo.modbluetoothkotlin.packet.XyoBluetoothOutgoingPacket
import network.xyo.sdkcorekotlin.network.XyoAdvertisePacket
import network.xyo.sdkcorekotlin.network.XyoNetworkPipe
import network.xyo.sdkcorekotlin.network.XyoNetworkProcedureCatalogueInterface
import network.xyo.sdkcorekotlin.schemas.XyoSchemas
import network.xyo.sdkobjectmodelkotlin.buffer.XyoBuff
import network.xyo.sdkobjectmodelkotlin.objects.toHexString
import java.nio.ByteBuffer
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
Expand All @@ -37,15 +38,19 @@ import kotlin.experimental.and
* @property device The android bluetooth device
* @property hash The unique hash of the device
*/
open class XyoBluetoothClient(context: Context, scanResult: XYScanResult, hash : Int) : XYIBeaconBluetoothDevice(context, scanResult, hash.toString()) {
open class XyoBluetoothClient : XYIBeaconBluetoothDevice {

constructor(context: Context, scanResult: XYScanResult, hash: Int) : super(context, scanResult, hash.toString())

constructor(context: Context, scanResult: XYScanResult, hash: Int, transport: Int) : super(context, scanResult, hash.toString(), transport)

/**
* The standard size of the MTU of the connection. This value is used when chunking large amounts of data.
*/
private var mtu = DEFAULT_MTU

/**
* creates a XyoNetworkPipe with THIS bluetooth device.
*
* @return A Deferred XyoNetworkPipe if successful, null if not.
*/
fun createPipe(): Deferred<XyoNetworkPipe?> = GlobalScope.async {
Expand All @@ -68,7 +73,7 @@ open class XyoBluetoothClient(context: Context, scanResult: XYScanResult, hash :
* @property initiationData The data that the other party sent after connecting (if any).
* @property rssi The RSSI of the connection. This is used for the RSSI heuristic (if any).
*/
inner class XyoBluetoothClientPipe(val rssi : Int?) : XyoNetworkPipe {
inner class XyoBluetoothClientPipe(val rssi: Int?) : XyoNetworkPipe {

override val initiationData: XyoAdvertisePacket? = null

Expand All @@ -82,12 +87,17 @@ open class XyoBluetoothClient(context: Context, scanResult: XYScanResult, hash :
}

override fun getNetworkHeretics(): Array<XyoBuff> {
val toReturn = ArrayList<XyoBuff>()

if (rssi != null) {
val encodedRssi = XyoBuff.newInstance(XyoSchemas.RSSI, byteArrayOf(rssi.toByte()))
return arrayOf(encodedRssi)
toReturn.add(encodedRssi)
}

return arrayOf()
val pwr = XyoBuff.newInstance(XyoSchemas.BLE_POWER_LVL, byteArrayOf(power))
toReturn.add(pwr)

return toReturn.toTypedArray()
}

/**
Expand All @@ -106,7 +116,7 @@ open class XyoBluetoothClient(context: Context, scanResult: XYScanResult, hash :

val sendAndReceive = GlobalScope.async {

val readJob = readIncommoding()
val readJob = readIncoming()
val packetError = chunkSend(data, XyoUuids.XYO_PIPE, XyoUuids.XYO_SERVICE, 4).await()

log.info("Sent entire packet to the server.")
Expand Down Expand Up @@ -169,10 +179,11 @@ open class XyoBluetoothClient(context: Context, scanResult: XYScanResult, hash :
protected fun chunkSend(outgoingPacket: ByteArray, characteristic: UUID, service: UUID, sizeOfSize: Int): Deferred<XYBluetoothError?> = GlobalScope.async {
return@async suspendCoroutine<XYBluetoothError?> { cont ->
GlobalScope.launch {
val chunknedOutgoingPacket = XyoBluetoothOutgoingPacket(mtu, outgoingPacket, sizeOfSize)
val chunkedOutgoingPacket = XyoBluetoothOutgoingPacket(mtu, outgoingPacket, sizeOfSize)

while (chunknedOutgoingPacket.canSendNext) {
val error = findAndWriteCharacteristic(service, characteristic, chunknedOutgoingPacket.getNext()).await().error
while (chunkedOutgoingPacket.canSendNext) {
val error = findAndWriteCharacteristic(service, characteristic, chunkedOutgoingPacket.getNext()).await().error
delay(500)
if (error != null) {
cont.resume(error)
return@launch
Expand All @@ -185,42 +196,39 @@ open class XyoBluetoothClient(context: Context, scanResult: XYScanResult, hash :
}



/**
* Reads an incoming packet by listening for notifications. This function must be invoked before any notifications
* are sent or else will return null. Timeout of the first notification is defined with FIRST_NOTIFY_TIMEOUT, in
* milliseconds and notification delta timeout is defined as NOTIFY_TIMEOUT in milliseconds.
*
* @return A deferred ByteArray of the value read. If there was an error or timeout, will return null.
*/
private fun readIncommoding() : Deferred<ByteArray?> = GlobalScope.async {
private fun readIncoming(): Deferred<ByteArray?> = GlobalScope.async {
return@async suspendCoroutine<ByteArray?> { cont ->
val key = this.toString() + Math.random().toString()

println("HERE")
centralCallback.addListener(key, object : XYBluetoothGattCallback() {
var numberOfPackets = 0
var hasResumed = false

var timeoutJob : Job = GlobalScope.launch {
var timeoutJob: Job = GlobalScope.launch {
delay(FIRST_NOTIFY_TIMEOUT.toLong())
hasResumed = true
centralCallback.removeListener(key)
cont.resume(null)
}

var incomingPacket : XyoBluetoothIncomingPacket? = null
var incomingPacket: XyoBluetoothIncomingPacket? = null

override fun onCharacteristicChanged(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?) {
super.onCharacteristicChanged(gatt, characteristic)
println("onCharacteristicChanged")
val value = characteristic?.value

if (characteristic?.uuid == XyoUuids.XYO_PIPE && !hasResumed) {

if (numberOfPackets == 0 && value != null) {
incomingPacket = XyoBluetoothIncomingPacket(value)
} else if (value != null ){
} else if (value != null) {
incomingPacket?.addPacket(value)
}

Expand Down Expand Up @@ -251,9 +259,10 @@ open class XyoBluetoothClient(context: Context, scanResult: XYScanResult, hash :
const val FIRST_NOTIFY_TIMEOUT = 12_000
const val NOTIFY_TIMEOUT = 10_000
const val MAX_MTU = 512
const val DEFAULT_MTU = 23
const val DEFAULT_MTU = 22

val xyoManufactorIdToCreator = HashMap<Byte, XYCreator>()
@SuppressLint("UseSparseArrays") //SparseArrays cannot use Byte as key
val xyoManufactureIdToCreator = HashMap<Byte, XYCreator>()

/**
* Enable this device to be created on scan.
Expand All @@ -274,7 +283,13 @@ open class XyoBluetoothClient(context: Context, scanResult: XYScanResult, hash :
}
}

override fun getDevicesFromScanResult(context: Context, scanResult: XYScanResult, globalDevices: ConcurrentHashMap<String, XYBluetoothDevice>, foundDevices: HashMap<String, XYBluetoothDevice>) {
override fun getDevicesFromScanResult(
context: Context,
scanResult: XYScanResult,
globalDevices: ConcurrentHashMap<String, XYBluetoothDevice>,
foundDevices: HashMap<String,
XYBluetoothDevice>
) {
val hash = scanResult.device?.address.hashCode()

if ((!foundDevices.containsKey(hash.toString())) && (!globalDevices.containsKey(hash.toString()))) {
Expand All @@ -284,13 +299,18 @@ open class XyoBluetoothClient(context: Context, scanResult: XYScanResult, hash :
val id = ad[19]

// masks the byte with 00111111
if (xyoManufactorIdToCreator.containsKey(id and 0x3f)) {
xyoManufactorIdToCreator[id and 0x3f]?.getDevicesFromScanResult(context, scanResult, globalDevices, foundDevices)
if (xyoManufactureIdToCreator.containsKey(id and 0x3f)) {
xyoManufactureIdToCreator[id and 0x3f]?.getDevicesFromScanResult(context, scanResult, globalDevices, foundDevices)
return
}
}

val createdDevice = XyoBluetoothClient(context, scanResult, hash)
val createdDevice = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
XyoBluetoothClient(context, scanResult, hash, BluetoothDevice.TRANSPORT_LE)
} else {
XyoBluetoothClient(context, scanResult, hash)
}

foundDevices[hash.toString()] = createdDevice
globalDevices[hash.toString()] = createdDevice
}
Expand Down
Loading

0 comments on commit e7e2d1b

Please sign in to comment.