[Android App BLE] #7 BLE 장치 제어

in #kr6 years ago

이전글 - [Android App BLE] #6 BLE 장치 통신 설정


출처: https://simbeez.com/


이전까지 BLE 통신을 위한 모든 준비를 마쳤습니다. 이제 데이터를 주고 받는 것만 구현하면 장치를 제어할 수 있습니다.

오늘은 간단히 장치에 명령을 려서 장치를 동작시키는 것을 구현해 보겠습니다.

제어하고자 하는 Peripheral 장치는 이겁니다.

간단히는 전기 자극기입니다. 이 장치의 API는 여기에 나와 있습니다.
https://www.foc.us/bluetooth-low-energy-api
여러 가지 명령 중에서 장치에 저장되어 있는 전기 자극 프로그램을 실행시키는 명령을 전송해 보겠습니다.

API 프로토콜 분석

명령을 전송하기 위해서는 적절한 데이터를 전송해야 합니다. 이를 위해서는 API에 적힌 내용을 잘 분석하고 정확한 데이터를 전송해야 합니다.
아래 그림을 보면 제어 명령을 내리기 위한 Characteristic의 UUID가 표시되어 있습니다. 그리고 총 6바이트의 데이터를 보내야 합니다.
image.png

  • 첫번째 전송할 바이트는 Command ID로 여기서는 manage program을 선택해야 합니다. 따라서 첫번째 바이트는 02가 됩니다.
  • 두번째 바이트는 SubCommand ID 입니다.
  • 세번째에서 여섯번째까지는 Data 바이트 입니다.

SubCommand ID와 Data

SubCommand ID와 Data를 정하기 위해서 다음 그림을 살펴봅니다.
image.png
위 그림에 나타난 프로토콜은 Data에 대한 부분입니다. 이전 그림에서 Command ID, SubCommand ID, Data 세부분으로 표시된 것중 제일 마지막에 해당하는 Data에 대한 전송 규약(프로토콜)을 나태나고 있는 것입니다.
프로토콜 바로 밑에 SubCommand ID에 대해서 설명이 나와 있습니다. 자극 프로그램을 start하기 위해서는 SubCommand ID를 7로 해야 한다고 되어 있습니다. 이 다음에 Data 프로토콜을 전송하게 되어 있습니다. Data 프로토콜로 정하는 것은 Program ID와 Program Descriptor ID입니다. 끝 두바이트는 상관없다고 되어 있고요.

Program ID는 자극 프로그램의 ID입니다. Program Descriptor ID는 Program의 정보를 읽거나 쓰기 위해 2개의 Descriptor가 있는데, 이에 대한 ID입니다.

요약해보면, 자극 프로그램 ID 1을 시작하도록 명령을 내리려면 다음과 같은 프로토콜을 전송하면 됩니다.

  • Command ID: 02
  • SubCommand ID: 07
  • Data:
    • Program ID : 1
    • Program Descriptor ID (not used): 0
    • not used: 0
    • not used: 0
      즉 전송할 프로토콜은 02 07 01 00 00 00 입니다. 위에서 설명한 것이 아래 그림에 예로 나타나 있습니다.
      image.png

구현

image.png

그럼 이제 Send Data 버튼을 눌렀을 때 위에서 살펴본 프로토콜을 전송하는 함수를 구현해 보겠습니다.

먼저 "Send Data"버튼이 눌렸을 때 이벤트를 처리하는 함수를 연결합니다.

protected void onCreate(Bundle savedInstanceState) {
(생략)
        // send data button handler
        btn_send_.setOnClickListener( (v) -> { sendData(v); });
}

다음으로 "SendData" 함수를 구현합니다.

public class MainActivity extends AppCompatActivity {
(생략)
    /*
    Send Data
     */
    private void sendData( View v ) {
        // check connection
        if( !connected_ )
        {
            Log.e( TAG, "Failed to sendData due to no connection" );
            return;
        }
        // find command characteristics from the GATT server
        BluetoothGattCharacteristic cmd_characteristic= BluetoothUtils.findCommandCharacteristic( ble_gatt_ );
        // disconnect if the characteristic is not found
        if( cmd_characteristic == null ) {
            Log.e( TAG, "Unable to find cmd characteristic" );
            disconnectGattServer();
            return;
        }
        // start stimulation
        startStimulation( cmd_characteristic, 1 );
    }
}

마지막으로 실제로 데이터를 전송하는 "startStimulation"함수를 구현합니다. 여기서는 Program ID를 입력받게 하여 다른 Program을 시작할 수 있게 했습니다.

public class MainActivity extends AppCompatActivity {
(생략)
    /*
    Start stimulation
    @param cmd_characteristic command characteristic instance
    @param program_id stimulation program id
     */
    private void startStimulation( BluetoothGattCharacteristic _cmd_characteristic, final int _program_id ) {
        // build protocol
        byte[] cmd_bytes= new byte[6];
        cmd_bytes[0]= 2;
        cmd_bytes[1]= 7;
        cmd_bytes[2]= (byte)(_program_id);
        cmd_bytes[3]= 0;
        cmd_bytes[4]= 0;
        cmd_bytes[5]= 0;

        // set values to the characteristic
        _cmd_characteristic.setValue( cmd_bytes );
        // write the characteristic
        boolean success= ble_gatt_.writeCharacteristic( _cmd_characteristic );
        // check the result
        if( success ) {
            Log.d( TAG, "Wrote: 02 07 " + _program_id + " 00 00 00" );
        }
        else
        {
            Log.e( TAG, "Failed to write command" );
        }
    }
}

결과 확인

빌드후 앱을 설치합니다. 그리고 Start Scan을 눌러서 장치를 검색하고, 연결합니다. 연결이 바로 안될 수 있습니다. 스캔 결과 한 번에 찾아지지 않는 경우가 종종 발생합니다. 연결이 되었다는 메시지가 표시되면 "Send Data" 버튼을 누릅니다. 그러면 짜잔~ 장치에서 해당 자극 프로그램이 시작됩니다. 아래 그림이 장치 동작 상태를 보여주고 있습니다. 0.1mA로 자극이 들어가고 있다는 의미입니다.
image.png

장치에 전극을 연결하고 사람 머리에 자극을 가하면 실제 파형까지도 표시가 되지만, 여기서는 실제 사람 몸에 자극을 가하지 않았기때문에 위와 같은 단순한 파형이 나타나고 있습니다.

한가지 놀라운 점은 장치 제조사에서 제공하는 공식 앱으로 장치에 연결하는게 무척 안됩니다. 수십번 연결시도해야 한 번 될까 말까 합니다. 답답하죠. 반면에 제가 만든 앱으로는 연결이 비교적 잘됩니다 ^^v 뿌듯합니다!
Screenshot_20180812-010502_focus me - EEG-tDCS-V3.jpg


이번에는 순조롭게 잘 진행되었네요. 별다른 에러도 발생하지 않았습니다.

오늘의 실습: 블루투스 장치에서 제공하는 앱 대신에 직접 연결, 제어 앱을 만들어 보세요.

Coin Marketplace

STEEM 0.16
TRX 0.17
JST 0.029
BTC 69280.52
ETH 2490.79
USDT 1.00
SBD 2.53