반응형
안드로이드 블루투스(Bluetooth) Gatt 개발 순서
1.oncreate에서 ACTION_BOND_STATE_CHANGED, ACTION_STATE_CHANGED
Broadcast리시버 등록
2. 권한 체크
3. bluetooth scan
4. bluetooth connect
-기존 연결 되어있으면 끊고 연결
BleManager.getInstance.apply{
connect
}
uuid는
Service, notify, write UUID
성공:
(1)연결된 device 저장
(2)Service
(3)characteristics
(4)Notify연결
(5)write연결
gatt?.run{
this.service
.filter{
it.uuid.toString() == serviceUuid
}
.map{
it.characteristics
}
.map{
//Notify연결
it
.filter{(it.properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY)>0}
.filter{it.uuid.toString() == notifyUuid}
.map{
BlaManager.getInstance().apply{
notify(..., callback{
onNotifySuccess()
onNotifyFailure()
onCharacteristicChanged(){
}
}
}
}
}
.map{
//Write 연결
it
.filter{
(it.properties and BluetoothGattCharacteristic.PROPERTY_WRITE_NORESPONSE)>0
}
.filter{
it.uuid.toString() == writeUuid
}
.map{ writeGattCharacteristic = it}
}
}
it.onConnectSuccess
5. Bluetooth disconnect
bleDevice?.let{
BleManager.getInstance().apply{
if(isConnected(it)){
disconnect(it)
connectedBleDevice = null
ioCallback = null
}
}
}
6. Bluetooth Gatt Read
notifyPublishSource
.timeout(7, TimeUnit.SECONDS)
.map{
HexUtils.bytesToHexString(it)
}
.scan{ t1: String, t2: String ->
t1 + t2
}
.map{
HexUtils.fromHex(it)
}
.subscribe(
{it ->
var isTail = false
if(it.size % 20 == 0){
for( it in 0 until it.size step 20){
//Tail인지 확인 || ACK인지 확인 || 16frame이상인지 확인
if(it[i] and 0x10.toByte() == x0x10.toByte() ||
it[i] and 0x80.toByte() == 0x80.toByte() ||
it.[i+1] and 0xF0.toByte() == it[i+1]){
isTail = true
break
}
}
}
if(isTail){
readDisposable.clear()
callback.onReadFromNotify(it)
}
},
{
if(it is TimeoutException){
if(retryTimeOutCnt < 1){
retyTimeOutCnt++
writeDataFrame?.let{
readDisposable.clear()
writeToBle(true)
}
}else{
callback.onReadFailure(TimeoutException())
}
}
},
{
log.d(complete)
}
)
.also{
readDisposable.add(it)
}
7. Bluetooth Gatt Write
Observable.fromIterable(writeDataFrame)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.map{
if(!isConnected()){
readDisposable.clear()
throw BleConnectionException()
}
it
}
.map{ t->
writeGattCharacteristic?.let{
BleManager.getInstance().apply{
write(
connectedBleDevice!!,
it.service.uuid.toString(),
it.uuid.toString(),
t,
object: BleWriteCallback(){
override fun onWriteSuccess(...){
retryWriteCnt = 0
ioCallback?.let{
//write call 사이에 카드에서 다른 응답이 오면
//readDisposable이 clear되어 ui단으로
//response 값을 줄 수 없다.
//하여 readDisposable에 값이 없는 경우는 다른 req에 대한 response 처리 했다고 판단하고 재 생성 한다.
if(readDisposable.size() <= 0){
readFromBle()
}
it.onWriteSuccess(...)
}
}
override fun onWriteFailure(..){
}
}
)
}
}
}
.retry{ _, e ->
//retryCnt: 재시도 욋수, e: Exception type
//write()에서 실패 난 경우 진입. 만약 성공하면 subscribe로 바로 이동한다.
//실패 후 3초 지연 시간 후 재시도 하기 위함
Thread.sleep(3000)
//재시도 횟수는 2회로 정한다. true이면 subscribe가 재 호출 된다. false이면 onErrorReturn이 호출된다.
retyWriteCnt++
return@rety retryWriteCnt < 2
}
.onErrorReturn{ e ->
//retry 에서 false로 리턴 되면 실행됨.
return@onErrorReturn -1
}
.subscribe(
{ t ->
if(t<0){
ioCallback?.let{
if(retryWriteCnt >= 2){ //write 2회 실패하면 read쪽에 대해 종료처리
readDisposable.clear()
}
it.onWriteFailure()
}
}
},
{t->
ioCallback?.let{
it.onWriteFailure()
}
},
{
log.d("complete")
}
)
.also{ compositeDisposable.add(it)}
반응형
'안드로이드' 카테고리의 다른 글
[Android] Architecture, Framework, Platform에 대해 알아보자 (0) | 2022.10.24 |
---|---|
[Android] 블루투스(Bluetooth) 개발에 대해 알아보자 (0) | 2022.10.24 |
[Android] ViewPager2, tabLayout 사용 방법 (0) | 2022.10.24 |
[Android] viewpager setUserVisibleHint, swipe, transition, 양쪽 마진 (0) | 2022.10.24 |
[Android] 데이터 바인딩(DataBinding) (0) | 2022.10.24 |