모바일 앱(안드로이드)

BLE 장치와의 UART 통신을 위한 Android 앱 개발

Billcorea 2024. 10. 5. 15:23
반응형

BLE 장치와의 UART 통신을 위한 Android 앱 개발 

ble scan

소개

이번 포스트에서는 no.nordicsemi.android:ble 라이브러리를 사용하여 Android 앱에서 BLE 장치와 UART 통신을 구현하는 방법을 단계별로 설명합니다. BLE 장치와 데이터를 송수신하는 방법을 예제로 보여드리겠습니다.

1. Gradle 설정

먼저, 프로젝트의 build.gradle 파일에 필요한 의존성을 추가합니다:

dependencies {
    implementation "no.nordicsemi.android:ble:2.9.0"
    implementation "no.nordicsemi.android.support.v18:scanner:1.6.0"
}

2. GATT 서비스 및 특성 UUID 정의

BLE UART 통신을 위해 필요한 GATT 서비스와 특성의 UUID를 정의합니다:

Kotlin
 
val UART_SERVICE_UUID = UUID.fromString("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
val CHARACTERISTIC_RX_UUID = UUID.fromString("6E400002-B5A3-F393-E0A9-E50E24DCCA9E")
val CHARACTERISTIC_TX_UUID = UUID.fromString("6E400003-B5A3-F393-E0A9-E50E24DCCA9E")

 

3. BLE 장치 검색

BLE 장치를 검색하기 위해 스캐너를 초기화하고 스캔 콜백을 구현합니다:

Kotlin
 
import no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat
import no.nordicsemi.android.support.v18.scanner.ScanCallback
import no.nordicsemi.android.support.v18.scanner.ScanResult
import no.nordicsemi.android.support.v18.scanner.ScanSettings

val scanner = BluetoothLeScannerCompat.getScanner()
val settings = ScanSettings.Builder()
    .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
    .build()

val scanCallback = object : ScanCallback() {
    override fun onScanResult(callbackType: Int, result: ScanResult) {
        super.onScanResult(callbackType, result)
        val device = result.device
        val rssi = result.rssi
        println("Device found: ${device.address}, RSSI: $rssi")
    }

    override fun onBatchScanResults(results: List<ScanResult>) {
        super.onBatchScanResults(results)
        for (result in results) {
            val device = result.device
            val rssi = result.rssi
            println("Device found: ${device.address}, RSSI: $rssi")
        }
    }

    override fun onScanFailed(errorCode: Int) {
        super.onScanFailed(errorCode)
        println("Scan failed with error code: $errorCode")
    }
}

fun startScan() {
    val filters = listOf<ScanFilter>() // 필요한 경우 필터 추가
    scanner.startScan(filters, settings, scanCallback)
}

fun stopScan() {
    scanner.stopScan(scanCallback)
}

 

4. BLE 매니저 클래스 생성

BLE 매니저 클래스를 생성하여 UART 통신을 관리합니다:

Kotlin
 
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic
import android.content.Context
import no.nordicsemi.android.ble.BleManager
import no.nordicsemi.android.ble.data.Data

class UARTManager(context: Context) : BleManager(context) {

    private var txCharacteristic: BluetoothGattCharacteristic? = null
    private var rxCharacteristic: BluetoothGattCharacteristic? = null

    override fun getGattCallback(): BleManagerGattCallback {
        return object : BleManagerGattCallback() {
            override fun isRequiredServiceSupported(gatt: BluetoothGatt): Boolean {
                val service = gatt.getService(UART_SERVICE_UUID)
                txCharacteristic = service?.getCharacteristic(CHARACTERISTIC_TX_UUID)
                rxCharacteristic = service?.getCharacteristic(CHARACTERISTIC_RX_UUID)
                return txCharacteristic != null && rxCharacteristic != null
            }

            override fun initialize() {
                setNotificationCallback(rxCharacteristic).with { device, data ->
                    onDataReceived(device, data)
                }
                enableNotifications(rxCharacteristic).enqueue()
            }

            override fun onServicesInvalidated() {
                txCharacteristic = null
                rxCharacteristic = null
            }
        }
    }

    fun send(data: String) {
        if (rxCharacteristic == null) return
        GlobalScope.launch {
            val writeType = if (useLongWrite) {
                BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
            } else {
                BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
            }
            val request: WriteRequest =
                writeCharacteristic(rxCharacteristic, data.toByteArray(), writeType)
            if (!useLongWrite) {
                request.split()
            }
            request.suspend()
            Log.e("10", "\"$data\" sent")
        }
    }

    private fun onDataReceived(device: BluetoothDevice, data: Data) {
        val receivedData = data.getStringValue(0)
        println("Received: $receivedData")
    }
}

* rxCharacteristic : BLE 기기 입장에서는 수신 이라서 ?

 

5. Activity에서 BLE 매니저 사용

Activity에서 BLE 매니저를 사용하여 장치에 연결하고 데이터를 송수신합니다:

Kotlin
 
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import no.nordicsemi.android.ble.ktx.state.ConnectionState
import no.nordicsemi.android.ble.ktx.state.stateAsFlow

class MainActivity : AppCompatActivity() {

    private lateinit var uartManager: UARTManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        uartManager = UARTManager(this)

        // 장치 검색 시작
        startScan()

        // 장치에 연결
        val device: BluetoothDevice = // 연결할 BLE 장치
        uartManager.connect(device)
            .useAutoConnect(false)
            .timeout(10000)
            .retry(3, 100)
            .enqueue()

        // 연결 상태 관찰
        lifecycleScope.launch {
            uartManager.stateAsFlow().collect { state ->
                when (state) {
                    is ConnectionState.Ready -> {
                        // 연결 성공
                        uartManager.send("Hello, UART!")
                    }
                    is ConnectionState.Disconnected -> {
                        // 연결 해제
                    }
                }
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        uartManager.disconnect().enqueue()
        stopScan()
    }
}
 

결론

이 포스트에서는 no.nordicsemi.android:ble 라이브러리를 사용하여 BLE 장치와 UART 통신을 설정하고 데이터를 송수신하는 방법을 설명했습니다. 또한, BLE 장치를 검색하는 방법도 포함했습니다. BLE 장치와의 통신을 통해 다양한 IoT 애플리케이션을 개발할 수 있습니다. 추가적인 질문이 있거나 더 자세한 설명이 필요하시면 언제든지 댓글로 남겨주세요!

 

 

반응형