BABIL_PROJECT/BLE

BLE_SCAN 액션 수정 (babilScan.js)

ForteQook 2022. 4. 10. 19:35

 위 메인 페이지에서 "연결된" 오토바이를 터치하면, 제어 페이지로 넘어가야 하는데, 이 과정에서 BLE 디바이스가 연결된다. 반대로 뒤로가기를 누르면 연결이 해제 되어야 한다. 그런데 보다보니 중요한 사실이 하나 떠오른다. 바로 scan 액션이 찾으려는 기기를 하나만 찾아도 바로 스캔을 종료시킨다는 것이다.

 우리가 필요한 조건은, 인자로 넘겨주는 uuidList에 있는 요소들을 모두 찾았을 때 스캔을 종료하는 것이다.

 

 몇시간 삽질 끝에 결국 전부 원래대로 되돌렸다. 생각을 해보자.

 

1. startScan 액션은, startDeviceScan 만 해줄 것.

2. startScan 액션은, 단 한번만 호출될것. 즉 렌더링 될 때마다 호출 되면 안된다.

3. startDeviceScan은 startScan 안에서 호출되고, 스캔할 때마다 인자로 넣어준 배열안의 요소 개수만큼 전부 스캔 됐는지 검사해서, 전부 다 스캔 됐으면 stopDeviceScan을 한다.

 

 대충 해결을 봤다.

1. startDeviceScan을 컴포넌트가 올라갈 때 단 한번만 하기 위해 componentDidMount 에서 호출했다.

2. props 업데이트에 따라 화면전환을 하는것이 아닌, 따로 componentDidMount 에서 시한폭탄 함수를 (시간제한..?) 호출하여 setState를 통해 isLoading 과 isDeviceFound 상태를 업데이트 하는 방식으로 했다. componentDidUpdate 를 통해 navigate 한다.

 

이렇게 하면 그동안 한 고민이 무색해질 정도로 간단히 굴러간다. 아참, 이 시한폭탄 함수는, setInterval 에서 내가 찾으려는 device가 있는지 확인 될때까지, 혹은 5바퀴 이상 돌려봤는데 안나올 때까지 state에 변화를 주면 안되므로, Promise 객체로 선언한다. 그 외에도 액션 부분 역시 이전과 비슷하게 좀 더 간단한 형태로 바꿔줬다.

 

ble_actions.js

export const _scan = (uuidList) => (dispatch, getState, DeviceManager) => {
  return DeviceManager.startDeviceScan(uuidList, null, (error, device) => {
    dispatch(changeStatus('Scanning'));
    if (error) {
      console.log(error)
    }
    if (device !== null) {
      dispatch(addBLE(device))
    }
  })
}

export const _startScan = (uuidList) => (dispatch, getState, DeviceManager) => {
  const subscription = DeviceManager.onStateChange((state) => {
    console.log("start Scanning");
    if (state === 'PoweredOn') {
        console.log("powered on");
        subscription.remove();
    }
    }, true);

    checkPermission()
    .then(() => dispatch(_scan(uuidList)))
}

 

 

보다시피, scan 액션은 그저 startDeviceScan을 하고 찾아낸 device가 있으면 add 하는것으로 바뀌었다.

또, startScan도 promise를 반환하지 않는다.

 

babilScan.js

class BabilScan extends Component {
    constructor() {
        super()
        this.state = {
            isLoading: true,
            isDeviceFound: false
        }
    }

    componentDidMount() {
        this.props._startScan(['FFE0'])
        this.timeBomb
        .then(() => this.setState({
            isLoading: false,
            isDeviceFound: true
        }))
        .catch(() => this.setState({
            isLoading: false,
            isDeviceFound: false
        }))
    }

    componentDidUpdate(prevProps, prevState) {
        if (this.state !== prevState) {
            if (!this.state.isLoading) {
                if (this.state.isDeviceFound) {
                    this.props.navigation.navigate('BikeNickName')
                } else {
                    this.props.navigation.navigate('ScanFail')
                }
            }
        }
    }

    timeBomb = new Promise((resolve, reject) => {
        var cnt = 1
        const checker = setInterval(() => {
            console.log('checking!!!', cnt)
            if (this.props.BLEList?.find((item) => {
                item.name == 'BABIL'
                return true
            })) {
                this.props.terminateScan()
                clearInterval(checker)
                resolve()
            }
            if (cnt > 5) {
                this.props.terminateScan()
                clearInterval(checker)
                reject()
            }
            cnt += 1
        }, 500)
    })

이렇게 간단한 로직을 왜 이리 오래 끌었는지 모르겠다... 이제 바뀐 액션을 기반으로 메인 페이지 역시 수정해야한다.

'BABIL_PROJECT > BLE' 카테고리의 다른 글

BLE  (0) 2022.06.18
BLE_WRITE  (0) 2022.04.26
BLE_SCAN 액션 수정 (main/index.js)  (0) 2022.04.11
React 와 Redux 불변성 (Immutability in React and Redux)  (0) 2022.03.31
BLE-PLX  (0) 2022.01.29