안드로이드 BLE Beacon 신호 전송 문제 질문드립니다

조회수 2684회

안녕하세요 안드로이드를 이용해 ble beacon 리모콘을 만드려고 하는데요 아래 코드는

PowerOn, PowerOff 버튼을 누르면 Service uuid가 5105 이고 데이터는 각각 0x01, 0x02 인 비콘 신호를 만들어 전송합니다.

전송 방식은 아래와 같습니다.

  1. 앱을 이용해 ON,OFF 버튼을 누르면 sendCommand 메서드를 실행한다. on = 0x01 , off = 0x02 값을 보냅니다.

  2. 넘겨받은 데이터를 가지고 AdvertisData 객체를 생성하고 startAdvertising 메서드를 이용해 비콘신호를 송신한다.

  3. onStartSuccess 콜백 이벤트 함수가 호출되면 곧바로 advertising 을 stop 한다.

전송은 잘 됩니다.

하지만 아래와 같이 테스트를 진행하면

  1. on 버튼을 눌러 0x01 Beacon 신호를 전송한다.

  2. off 버튼을 눌러 0x02 beacon 신호를 전송한다.

  3. on 버튼을 눌러 0x01 beacon 신호를 전송한다.

이와 같이 결과가 나옵니다.

1에서 0x01 beacon 신호를 전송하면 data 패킷에 아무런 데이터도 표시되지 않습니다. (Bluetooth LE Scanner 앱을 통해 확인)

2에서 off 버튼을 눌렀음에도 불구하고 이전 on 버튼을 눌렀을 때의 데이터인 0x01이 표시됨

3에서 on 버튼을 눌렀음에도 이전 off 버튼을 눌렀을 때의 데이터닌 0x02이 표시됨

결론

  • 처음데이터가 flush 되지 않고 queue?? 등에 남아 있어 새로운 데이터가 송신되지 않고 이전에 송신되지 못한 데이터를 송신하는것 같습니다. (그래서 데이터가 밀리는 것같아요)

원인이 무엇을까요??

문제원인예상

  • onStartSuccess 호출되고 바로 stop을 해서 문제가되는건지..

  • 어딘가 딜레이를 줘야하는건지..

  • 블루투스에 쌓여있는 데이터를 clear 해주어야하는지.. <= 관련함수는 찾아봤는데 나오지 않음..

public class DeviceControlActivity extends AppCompatActivity implements Constants {

public final static String TAG = DeviceControlActivity.class.getName();
public BluetoothManager mBluetoothManager;
public BluetoothLeAdvertiser mBluetoothLeAdvertiser;
public BluetoothAdapter bluetoothAdapter;
public AdvertiseSettings settings;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    advertisingInit();
}

public void mOnClick(View v){
    switch (v.getId()){
        case R.id.powerOn :
            sendCommand(new byte[]{0x01});
            break;
        case R.id.powerOff:
            sendCommand(new byte[]{0x02});
            break;

    }
}

public void advertisingInit(){
    mBluetoothManager = (BluetoothManager)getSystemService(BLUETOOTH_SERVICE);
    bluetoothAdapter = mBluetoothManager.getAdapter();

    mBluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
    if (mBluetoothLeAdvertiser == null) {
        Log.e(TAG, "Failed to create advertiser");
        return;
    }

    bluetoothAdapter.getDefaultAdapter().setName("SANGIL");
    settings = new AdvertiseSettings.Builder()
            .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
            .setConnectable(false)
            .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
            .setTimeout(0)
            .build();
}
public ParcelUuid shortUUID(String s) {
    return ParcelUuid.fromString("0000" + s + "-0000-1000-8000-00805F9B34FB");
}


private void sendCommand(byte[] sendData) {

    StringBuilder sb= new StringBuilder();
    for(byte c : sendData){
        sb.append(String.format("%02X",c));
    }
    Log.e("BEACON SENT1","DATA : "+ sb.toString());

    AdvertiseData data = new AdvertiseData.Builder()
            .addServiceData(shortUUID("5105"),sendData)
            .setIncludeDeviceName(true)
            .build();
    Log.e("BEACON SENT2",data.toString());

    mBluetoothLeAdvertiser
            .startAdvertising(settings, data, mAdvertiseCallback);


}

private AdvertiseCallback mAdvertiseCallback = new AdvertiseCallback() {
    @Override
    public void onStartSuccess(AdvertiseSettings settingsInEffect) {
        Log.e(TAG, "LE Advertise Started.");
        mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);
    }

    @Override
    public void onStartFailure(int errorCode) {
        Log.e(TAG, "LE Advertise Failed: " + errorCode);
    }
};

@Override
protected void onDestroy() {
    super.onDestroy();
    if(mBluetoothLeAdvertiser!=null){
        mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);
    }
}

}

  • (•́ ✖ •̀)
    알 수 없는 사용자

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)