Как отправить текстовые данные на брелок CC2541 через Android 4.3?

Я разрабатываю приложение, в котором мне нужно подключиться к устройству Bluetooth на Android 4.3.

И я хочу изменить имя брелока CC2541 через приложение для Android.

Мои идеи:

1. Там есть обычный текст, который я могу ввести в свое приложение для Android.

2. После того, как я набрал имя, я нажимаю кнопку, чтобы отправить этот текст.

3. Если CC2541 получит этот текст из приложения Android, он изменит текст в deviceName[] следующего кода в keyfobdemo.c:

static uint8 deviceName[] =
{
// complete name
0x0b, // length of first data structure (11 bytes excluding length byte)
0x09, // AD Type = Complete local name
0x4b, // 'K'
0x65, // 'e'
0x79, // 'y'
0x66, // 'f'
0x6f, // 'o'
0x62, // 'b'
0x64, // 'd'
0x65, // 'e'
0x6d, // 'm'
0x6f, // 'o'
};

Вопрос примерно следующий:

1.Как отправить текстовые данные на брелок CC2541 в приложении Android 4.3??

2.Как получить текстовые данные на стороне CC2541??

3. Нужно ли мне использовать какой-либо профиль??

Извините за мой английский и эти вопросы.

Спасибо за ваше направление.


Изменить

Я пытаюсь использовать 0x2A00 для получения службы имени устройства, но она не работает, когда я вызываю функцию Device_Name.

Name_Service имеет значение null.

private static final UUID Device_Name_UUID = UUID.fromString("00002a00-0000-1000-8000-00805f9b34fb");
private static final UUID Write_UUID = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb");





    public void Device_Name(){
        BluetoothGattService Name_Service = mBluetoothGatt.getService(Write_UUID );
        if(Name_Service == null) {
            Log.d(TAG, "Name_Service service not found!");
            return;
        }

        BluetoothGattCharacteristic DeviceName = Name_Service.getCharacteristic(Device_Name_UUID);
        if(DeviceName == null) {
            Log.d(TAG, "DeviceName charateristic not found!");
            return;
        }



    }


Log.v(TAG, "readCharacteristic(DeviceName) = " + mBluetoothGatt.readCharacteristic(DeviceName));

String i = "123";       
DeviceName.setValue(i);
Log.v(TAG, "writeCharacteristic(DeviceName) = " + mBluetoothGatt.writeCharacteristic(DeviceName));

он показывает следующий журнал:

V/BluetoothLeService( 3680): readCharacteristic(DeviceName) = true
V/BluetoothLeService( 3680): writeCharacteristic(DeviceName) = false
D/audio_hw_primary( 1752): found out /dev/snd/pcmC0D0p
W/audio_hw_primary( 1752): out_write() limiting sleep time 45351 to 23219
W/audio_hw_primary( 1752): out_write() limiting sleep time 34263 to 23219
W/audio_hw_primary( 1752): out_write() limiting sleep time 33696 to 23219
D/BtGatt.btif( 2646): btif_gattc_upstreams_evt: Event 3
I/BtGatt.btif( 2646): set_read_value unformat.len = 13 
D/BtGatt.GattService( 2646): onReadCharacteristic() - address=90:59:AF:0B:8A:AB, status=0, length=13
D/BluetoothGatt( 3680): onCharacteristicRead() - Device=90:59:AF:0B:8A:AB UUID=00002a00-0000-1000-8000-00805f9b34fb Status=0

он считается успешным, и я могу получить имя устройства.

И я ссылаюсь на Bluetooth Page-Device Name , формат — строка UTF-8. Но он пишет, что характеристика ложная.


person Wun    schedule 04.11.2013    source источник
comment
Проблема с вашим кодом заключается в том, что вы не можете использовать getService с неслужебным UUID. Атрибут имени устройства всегда находится в службе общего профиля доступа (00001800-0000-1000-8000-00805f9b34fb).   -  person Vegar Westerlund    schedule 20.11.2013
comment
@VegarWesterlund: я читаю Characteristic , но пишу false с помощью writeCharacteristic. Вы предложили??   -  person Wun    schedule 22.11.2013


Ответы (2)


Я не знаю об Android BLE API, но могу рассказать вам, как это должно работать с Bluetooth Low Energy.

Имя устройства хранится на сервере GATT (локальная база данных на устройстве cc2541). Если вы подключаетесь к устройству BLE, вы сможете выполнить обнаружение, чтобы выяснить структуру базы данных и найти дескриптор ATT для имени устройства.

Сервер GATT состоит из атрибутов с UUID (приблизительно определяющим тип атрибута), дескриптора атрибута (идентификатор, используемый в этом экземпляре сервера GATT) и значения. Согласно [1] UUID имени устройства — 0x2A00. Таким образом, вы можете искать по типу и найти дескриптор с этим UUID.

Когда у вас есть UUID, достаточно использовать клиент GATT в Android API, чтобы отправить запрос на запись в этот дескриптор с новым значением.

Редактировать: Глядя на API, я думаю, вам следует использовать getService(0x18, 0x00) [2], чтобы получить основной сервис (который должен содержать имя устройства), а затем writeCharacteristic[3] для обновления имени.

Из [4] похоже, что код должен выглядеть примерно так (не тестировалось):

public void writeCharacteristic(byte[] value) {
    BluetoothGattService gap_service = mBluetoothGatt.getService(
            UUID.fromString("00001800-0000-1000-8000-00805F9B34FB"));
    if (gap_service == null) {
        System.out.println("gap_service null";);
        return;
    }
    BluetoothGattCharacteristic dev_name = gap_service.getCharacteristic(
            UUID.fromString("00002A00-0000-1000-8000-00805F9B34FB"));
    if (dev_name == null) {
        System.out.println("dev_name null";);
        return;
    }
    dev_name.setValue(value);
    boolean status = mBluetoothGatt.writeCharacteristic(dev_name);
    System.out.println("Write Status: " + status);
}
person Vegar Westerlund    schedule 11.11.2013
comment
Спасибо тебе, Вестерлунд. Но я все еще пытаюсь использовать 0X2A00 для записи имени устройства, но пока безуспешно... - person Wun; 18.11.2013
comment
@ martin-wun: вы используете 0x2a00 в качестве UUID или дескриптора? Сначала вам нужно найти дескриптор атрибута для UUID 0x2a00. Есть несколько разных способов сделать это, не уверен, что проще всего на Android. Затем, когда вы хотите выполнить запись, вам нужно указать дескриптор, а не UUID. - person Vegar Westerlund; 18.11.2013
comment
Итак, ручка — это тупик. Android API абстрагируется от этого, поэтому вам не нужно об этом думать. Кажется, я нашел здесь то, что вам нужно[1]. Я обновлю свой ответ. [1] devzone .nordicsemi.com/index.php/ - person Vegar Westerlund; 20.11.2013
comment
Я читаю Characteristic, но пишу false по writeCharacteristic. Вы предложили?? - person Wun; 22.11.2013
comment
@Wun, вам всегда нужно ждать обратного вызова, прежде чем писать/читать/устанавливать уведомления и т. д. Библиотека BLE на Android обрабатывает только одно за раз, или немедленный ответ является ложным, и ваше действие игнорируется. - person AllDayAmazing; 03.02.2015

Это мое решение, добавление в справочную информацию Vegar о GATT, профилях и т. д.

Это основано на приложении simpleBLEPeripheral в SDK CC2541 и приложении sensortag для Android. Характеристика simpleBLEPeripheral позволяет вам считывать многобайтовую характеристику, я изменил ее, чтобы разрешить запись. Методу simpleGATTprofile.c simpleProfile_WriteAttrCB() требуется дополнительный оператор case:

  case SIMPLEPROFILE_CHAR5_UUID:

    //Validate the value
    // Make sure it's not too long

    if ( len >= SIMPLEPROFILE_CHAR5_LEN )
    {
      status = ATT_ERR_INVALID_VALUE_SIZE;
    }

    //Write the value
    if ( status == SUCCESS )
    {
      uint8 *pCurValue = (uint8 *)pAttr->pValue;
      osal_memcpy(pCurValue+offset, pValue, len);

      notifyApp = SIMPLEPROFILE_CHAR5;    
    }

    break;

На стороне Android следующий код помещается в DeviceActivity.java. Пожалуйста, простите за беспорядочный код, это быстрый взлом. Он берет строку, находит шестнадцатеричное представление, которое затем отправляется как обновление характеристик в CC2541.

 void writeString() {
    UUID servUuid = SensorTagGatt.UUID_STR_SERV;
    UUID configUuid = SensorTagGatt.UUID_STR_DATA;
    BluetoothGattService serv = mBtGatt.getService(servUuid);
    BluetoothGattCharacteristic config = serv.getCharacteristic(configUuid);

    int OAD_BLOCK_SIZE = 18;
    int OAD_BUFFER_SIZE = OAD_BLOCK_SIZE + 2;
    int GATT_WRITE_TIMEOUT = 300; // Milliseconds

    String msg = new String();
    byte[] mOadBuffer = hexStringToByteArray("e04fd020ea3a6910a2d808002b30309daabbccdd");

    // Send block
    config.setValue(mOadBuffer);
    boolean success = mBtLeService.writeCharacteristic(config);

    if (success) {
        // Update stats
        if (!mBtLeService.waitIdle(GATT_WRITE_TIMEOUT)) {
            success = false;
            msg = "GATT write timeout\n";
        }
    } else {
        msg = "GATT writeCharacteristic failed\n";
    }
    if (!success) {
        Toast.makeText(this,msg,Toast.LENGTH_SHORT).show();
    }

}

public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

Ключ в том, чтобы убедиться, что ваши UUID совпадают, иначе ничего не будет работать.

person Dan Luong    schedule 06.02.2015