S K
12/23/2024, 3:56 PMloke
12/23/2024, 5:11 PMS K
12/24/2024, 4:28 AMclass BluetoothServiceIOSNew : BluetoothService {
// Central and Peripheral Managers
private val centralManager: CBCentralManager = CBCentralManager()
private var peripheralManager: CBPeripheralManager? = null
private var connectedPeripheral: CBPeripheral? = null
private var peripheral: CBPeripheral? = null
// Define properties for the callbacks
private var connectSuccessCallback: (() -> Unit)? = null
private var connectFailureCallback: ((Throwable) -> Unit)? = null
private var disconnectCallback: (() -> Unit)? = null
private var disconnectFailureCallback: ((Throwable) -> Unit)? = null
init {
println("Kotlin::: init execution")
centralManager.delegate = object : NSObject(), CBCentralManagerDelegateProtocol {
// Called when Bluetooth state changes (powered on/off)
//This method is called whenever the Bluetooth state of the CBCentralManager changes (e.g., powered on, powered off, unsupported, etc.).
override fun centralManagerDidUpdateState(manager: CBCentralManager) {
println("Kotlin::: centralManagerDidUpdateState")
when (manager.state) {
CBCentralManagerStatePoweredOn -> {
println("Kotlin::: Bluetooth is powered on.")
}
CBCentralManagerStatePoweredOff -> {
println("Kotlin::: Bluetooth is powered off.")
}
else -> {
println("Kotlin::: Bluetooth is unavailable or turned off.")
}
}
}
// Called when a peripheral is discovered during scanning
//This method is called when a peripheral device is discovered during a scan. You can use it to filter peripherals and initiate a connection.
override fun centralManager(central: CBCentralManager, didDiscoverPeripheral: CBPeripheral, advertisementData: Map<Any?, *>, RSSI: NSNumber) {
println("Kotlin:: Discovered peripheral: ${didDiscoverPeripheral.name}")
// if (didDiscoverPeripheral.name == "TargetDeviceName") {
centralManager.connectPeripheral(didDiscoverPeripheral, options = null)
connectedPeripheral = didDiscoverPeripheral
println("Kotlin:: Connecting to peripheral: ${didDiscoverPeripheral.name}")
// }
}
// Called when a peripheral has been successfully connected
//This method is called when a peripheral is successfully connected. You can use this to trigger actions upon a successful connection.
override fun centralManager(manager: CBCentralManager, didConnectPeripheral: CBPeripheral) {
println("Kotlin:: Successfully connected to peripheral: ${didConnectPeripheral.name}")
connectedPeripheral = didConnectPeripheral
connectSuccessCallback?.invoke() // Invoke the success callback
}
// Called when a connection to a peripheral fails
//This method is called when a connection attempt to a peripheral fails. It provides an error so you can handle the failure.
@ObjCSignatureOverride
override fun centralManager(manager: CBCentralManager, didFailToConnectPeripheral: CBPeripheral, error: NSError?) {
println("Kotlin:: Failed to connect to peripheral: ${didFailToConnectPeripheral.name}")
connectFailureCallback?.invoke((error ?: Exception("Unknown connection failure")) as Throwable) // Invoke failure callback
}
// Called when a peripheral is disconnected
//This method is called when a peripheral is disconnected, either intentionally or due to an error.
@ObjCSignatureOverride
override fun centralManager(manager: CBCentralManager, didDisconnectPeripheral: CBPeripheral, error: NSError?) {
println("Kotlin:: Disconnected from peripheral: ${didDisconnectPeripheral.name}")
connectedPeripheral = null
if (error != null) {
disconnectFailureCallback?.invoke(error.toThrowable()) // If there's an error on disconnect, invoke failure callback
} else {
disconnectCallback?.invoke() // Otherwise, invoke success callback
}
}
}
}
fun NSError.toThrowable(): Throwable {
return Throwable("Kotlin::: NSError code: $code, description: ${localizedDescription}")
}
override fun isBluetoothPoweredOn(): Boolean {
return when (centralManager.state) {
CBCentralManagerStatePoweredOn -> true
else -> false
}
}
override suspend fun startAdvertising(name: String, serviceUUID: String) {
println("Kotlin::: Starting advertising with name: $name and service UUID: $serviceUUID")
if (peripheralManager == null) {
println("Kotlin::: Null execution")
// Initialize the peripheral manager with the correct delegate
peripheralManager = CBPeripheralManager()
// Set the delegate after initialization
peripheralManager?.delegate = BluetoothPeripheralManagerDelegateNew(
onAdvertisingStarted = {
println("Kotlin::: Advertising started successfully!")
},
onAdvertisingFailed = { error ->
println("Kotlin::: Advertising failed with error: ${error.localizedDescription}")
}
)
}
// Wait until the peripheral manager is powered on
while (peripheralManager?.state != CBPeripheralManagerStatePoweredOn) {
delay(500) // Check every 500ms
}
val advertisementData: Map<Any?, Any?> = mapOf(
CBAdvertisementDataLocalNameKey to name,
CBAdvertisementDataServiceUUIDsKey to listOf(CBUUID.UUIDWithString(serviceUUID))
)
// peripheralManager?.startAdvertising(advertisementData)
peripheralManager?.startAdvertising(null)
println("Kotlin::: Started advertising with name: $name and service UUID: $serviceUUID")
}
override suspend fun stopAdvertising() {
peripheralManager?.stopAdvertising()
println("Kotlin:: Stopped advertising.")
}
override suspend fun startDiscovery(serviceUUID: String) {
println("Kotlin:: Starting scan for peripherals offering service UUID: $serviceUUID")
withContext(Dispatchers.Main) {
val serviceUUIDs = listOf(CBUUID.UUIDWithString(serviceUUID))
centralManager.scanForPeripheralsWithServices(serviceUUIDs, options = null)
println("Kotlin:: Started scanning for peripherals offering service UUID: $serviceUUID")
}
}
override suspend fun stopDiscovery() {
withContext(Dispatchers.Main) {
centralManager.stopScan()
println("Kotlin:: Stopped scanning for peripherals.")
}
}
@Throws(Exception::class)
override suspend fun connect(deviceId: String, onSuccess: () -> Unit, onFailure: (Throwable) -> Unit) {
println("Kotlin:: connect-1")
if (deviceId.isNullOrEmpty()) {
onFailure(IllegalArgumentException("Device ID cannot be null or empty"))
return
}
println("Kotlin:: connect-2")
val nsUUID = NSUUID(deviceId)
println("Kotlin:: connect Created NSUUID: $nsUUID")
// Retrieve peripheral by UUID
val peripheralToConnect = centralManager.retrievePeripheralsWithIdentifiers(listOf(nsUUID))
if (!peripheralToConnect.isNullOrEmpty()) {
peripheral = peripheralToConnect.firstOrNull() as? CBPeripheral
println("Kotlin:: connect-5 :: $peripheral")
if (peripheral != null) {
centralManager.connectPeripheral(peripheral!!, options = null)
println("Kotlin:: Attempting to connect to peripheral: $deviceId")
// Store the callback functions for success and failure
connectSuccessCallback = onSuccess
connectFailureCallback = onFailure
} else {
onFailure(IllegalArgumentException("Peripheral not valid"))
}
} else {
onFailure(IllegalArgumentException("Peripheral not found"))
}
}
// Implement disconnect with success and failure callbacks
override suspend fun disconnect(onSuccess: () -> Unit, onFailure: (Throwable) -> Unit) {
println("Kotlin:: disconnect-1")
if (connectedPeripheral != null) {
centralManager.cancelPeripheralConnection(connectedPeripheral!!)
println("Kotlin:: Disconnecting from peripheral: ${connectedPeripheral?.name}")
// Store the callback for disconnection success
disconnectCallback = onSuccess
disconnectFailureCallback = onFailure
} else {
println("Kotlin:: No peripheral is connected.")
onFailure(IllegalStateException("No peripheral is connected"))
}
}
}
// Bluetooth Peripheral Manager Delegate
class BluetoothPeripheralManagerDelegateNew(
private val onAdvertisingStarted: () -> Unit,
private val onAdvertisingFailed: (NSError) -> Unit
) : NSObject(), CBPeripheralManagerDelegateProtocol {
// This callback will be triggered when advertising starts
override fun peripheralManagerDidStartAdvertising(peripheral: CBPeripheralManager, error: NSError?) {
if (error == null) {
println("Kotlin::: oAdvertising-Started")
onAdvertisingStarted()
} else {
println("Kotlin::: oAdvertising-Failed")
onAdvertisingFailed(error)
}
}
// This callback is triggered when the peripheral manager's state changes (e.g., powered on/off)
override fun peripheralManagerDidUpdateState(peripheral: CBPeripheralManager) {
when (peripheral.state) {
CBPeripheralManagerStatePoweredOn -> {
println("Kotlin::: Peripheral Manager powered on.")
}
else -> {
println("Kotlin::: Peripheral Manager not ready or powered off.")
}
}
}
}
S K
12/24/2024, 4:28 AMinterface BluetoothService {
fun isBluetoothPoweredOn(): Boolean
suspend fun startAdvertising(name: String, serviceUUID: String)
suspend fun stopAdvertising()
suspend fun startDiscovery(serviceUUID: String)
suspend fun stopDiscovery()
/* @Throws(Exception::class)
suspend fun connect(deviceId: String)
suspend fun disconnect()*/
@Throws(Exception::class)
suspend fun connect(deviceId: String, onSuccess: () -> Unit, onFailure: (Throwable) -> Unit)
suspend fun disconnect(onSuccess: () -> Unit, onFailure: (Throwable) -> Unit)
}
Adrijan Rogan
12/24/2024, 7:22 AMS K
12/24/2024, 9:52 AMAdrijan Rogan
12/24/2024, 10:09 AMS K
12/24/2024, 10:18 AMAdrijan Rogan
12/24/2024, 10:31 AMS K
12/24/2024, 11:40 AM