2

我正在开发一个应用程序,我必须在其中连接到 Android 4.3 上的蓝牙设备。

我想通过 Android 应用程序更改 CC2541 Keyfob 的名称。

我的想法是:

1.有一个纯文本,我可以在我的 Android 应用程序中输入我想要的名称。

2. 输入姓名后,我按下按钮发送此文本。

3.如果CC2541从Android应用程序接收到这个文本,它将改变keyfobdemo.c中以下代码的deviceName[]中的文本:

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.如何在Android应用程序4.3中将文本数据发送到CC2541 keyfob ??

2.CC2541端如何接收文本数据??

3.我需要使用任何个人资料吗?

对不起我的英语和这些问题。

谢谢你的指导。


编辑

我试图使用 0x2A00 来获取设备名称服务,但是当我调用 Device_Name 函数时它发现它不起作用。

Name_Service 为空。

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 字符串。但是它写特征是假的。

4

2 回答 2

3

我不知道 Android BLE API,但我可以告诉你这应该如何与低功耗蓝牙一起工作。

设备名称存储在 GATT 服务器(cc2541 设备上的本地数据库)中。如果您连接到 BLE 设备,您应该能够进行发现以找出数据库的结构并找到设备名称的 ATT 句柄。

GATT 服务器由具有 UUID(松散定义属性类型)、属性句柄(在此 GATT 服务器实例中使用的标识符)和值的属性组成。根据 [1],设备名称的 UUID 是 0x2A00。因此,您可以按类型搜索并找到具有此 UUID 的句柄。

获得 UUID 后,只需使用 Android API 中的 GATT 客户端使用新值向该句柄发送写入请求

编辑:查看 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);
}
于 2013-11-11T18:35:31.630 回答
0

这是我的解决方案,添加到 Vegar 关于 GATT、配置文件等的背景信息。

这是基于 CC2541 SDK 中的 simpleBLEPeripheral 应用程序和 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 匹配,否则将无法正常工作。

于 2015-02-06T18:34:27.597 回答