- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我对 Android Things 和蓝牙 LE Gatt 还很陌生。我试过 Bluetooth LE GATT server sample由谷歌提供。我在 Raspberry Pi 3 和 Android BluetoothLeGatt client sample 上运行蓝牙 LE GATT 服务器示例在我的手机上。我在 SampleGattAttributes.java 中编辑了一些代码并且BluetoothLeService.java。
示例GattAttributes.java
public class SampleGattAttributes {
private static HashMap<String, String> attributes = new HashMap();
public static String CURRENT_TIME = "00002a2b-0000-1000-8000-00805f9b34fb";
public static String CLIENT_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
static {
// Sample Services.
attributes.put("00001805-0000-1000-8000-00805f9b34fb", "TIME SERVICE");
// Sample Characteristics.
attributes.put(CURRENT_TIME, "CURRENT TIME");}
蓝牙服务.java
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.bluetoothlegatt;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import java.util.List;
import java.util.UUID;
/**
* Service for managing connection and data communication with a GATT server hosted on a
* given Bluetooth LE device.
*/
public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName();
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
private BluetoothGatt mBluetoothGatt;
private int mConnectionState = STATE_DISCONNECTED;
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;
public final static String ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE = "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA = "com.example.bluetooth.le.EXTRA_DATA";
public final static UUID UUID_CURRENT_TIME = UUID.fromString(SampleGattAttributes.CURRENT_TIME);
// Implements callback methods for GATT events that the app cares about. For example,
// connection change and services discovered.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
// This is special handling for the Heart Rate Measurement profile. Data parsing is
// carried out as per profile specifications:
// http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
if (UUID_CURRENT_TIME.equals(characteristic.getUuid())) {
int flag = characteristic.getProperties();
int format = -1;
if ((flag & 0x01) != 0) {
format = BluetoothGattCharacteristic.FORMAT_UINT16;
Log.d(TAG, "Heart rate format UINT16.");
} else {
format = BluetoothGattCharacteristic.FORMAT_UINT8;
Log.d(TAG, "Heart rate format UINT8.");
}
final int heartRate = characteristic.getIntValue(format, 1);
Log.d(TAG, String.format("Received heart rate: %d", heartRate));
intent.putExtra(EXTRA_DATA, String.valueOf(heartRate));
} else {
// For all other profiles, writes the data formatted in HEX.
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data)
stringBuilder.append(String.format("%02X ", byteChar));
intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
}
}
sendBroadcast(intent);
}
public class LocalBinder extends Binder {
BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
// After using a given device, you should make sure that BluetoothGatt.close() is called
// such that resources are cleaned up properly. In this particular example, close() is
// invoked when the UI is disconnected from the Service.
close();
return super.onUnbind(intent);
}
private final IBinder mBinder = new LocalBinder();
/**
* Initializes a reference to the local Bluetooth adapter.
*
* @return Return true if the initialization is successful.
*/
public boolean initialize() {
// For API level 18 and above, get a reference to BluetoothAdapter through
// BluetoothManager.
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
/**
* Connects to the GATT server hosted on the Bluetooth LE device.
*
* @param address The device address of the destination device.
*
* @return Return true if the connection is initiated successfully. The connection result
* is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
// We want to directly connect to the device, so we are setting the autoConnect parameter to false.
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
/**
* Disconnects an existing connection or cancel a pending connection. The disconnection result
* is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.disconnect();
}
/**
* After using a given BLE device, the app must call this method to ensure resources are
* released properly.
*/
public void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
}
/**
* Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported
* asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}
* callback.
*
* @param characteristic The characteristic to read from.
*/
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.readCharacteristic(characteristic);
}
/**
* Enables or disables notification on a give characteristic.
*
* @param characteristic Characteristic to act on.
* @param enabled If true, enable notification. False otherwise.
*/
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
// This is specific to Heart Rate Measurement.
if (UUID_CURRENT_TIME.equals(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(SampleGattAttributes.CLIENT_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}
/**
* Retrieves a list of supported GATT services on the connected device. This should be
* invoked only after {@code BluetoothGatt#discoverServices()} completes successfully.
*
* @return A {@code List} of supported services.
*/
public List<BluetoothGattService> getSupportedGattServices() {
if (mBluetoothGatt == null) return null;
return mBluetoothGatt.getServices();
}
}
当我单击“当前时间”时,它会在数据字段中显示 7。请问7这个数字是从哪里来的,为什么改时间没有提示。
最佳答案
您从 Android 蓝牙 LE 客户端示例中修改的代码可能会映射到正确的当前时间 UUID,但它仍在尝试解析数据,就好像它是 broadcastUpdate()< 中的单个心率测量值一样
.
该方法中的代码根据 heart rate measurement 解析数据字段规范,但来自服务器的数据是 current time值(value)。您的客户端代码需要根据当前时间的蓝牙规范定义的特征来解析各个字节。
关于onCharacteristicChanged()
没有被调用,需要验证服务端是否真的收到了订阅请求。您可以将日志记录添加到 the server callback如果你希望看到注册过程,服务器也会 log a message每次收到更新事件时都会触发给订阅者的通知。
关于android - 蓝牙 LE GATT 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43362896/
我正在尝试在 gatt 连接并成功发现服务后立即读取特征。但在 onCharacteristicRead gatt 回调中收到错误 15(0x0f,GATT_INSUFFICIENT_ENCRYPTI
我有代码连接到广告自定义服务的自定义 BLE 服务器设备,然后尝试发现它提供的所有服务。 代码适用于 Android 5.1 的 Nexus 5 三星 SM-T320 Android 4.4.2 ZT
我尝试通过蓝牙低功耗 GATT 模式将 android 连接到 linux。 Bluez 中有一个示例代码:btgatt-server.c ,我用它作为服务器。 Android 端为 Android
我的问题很简短 - 在 Zephyr 文档中,我找不到我的问题的答案(这让我感到惊讶)。 一个 GATT 客户端是否可以连接到多个 GATT 服务器? 现在我正在使用两块板来计算一些东西(一个作为服务
我的目标是在 Ubuntu 14.04 上使用 BlueZ 4.101(不是 BlueZ 5.X)通过 USB BLE Dongle(Cambridge Silicon Radio CSR8510 A
我编写了一个连接到心率模型的程序,但我不知道如何解释数据。以下是从第一个输出开始的示例: heart rate is : 16-40-15-04-6D-02-8C-01-0C-04-24-04-AB-
我开发了两个实现 GATT 角色的应用程序:服务器和客户端。就我而言,GATT 服务器也是 GAP 外围设备,GATT 客户端是 GAP 中心。 我可以将客户端连接到服务器/从服务器断开连接,但是当我
BLE 设备(脉搏计)的特性值始终相同。信号转到onCharacteristicChanged,但值没有改变,尝试通过不同的方式获取该值。 @Override public void onServic
我正在尝试编写一个应用程序来通过低功耗蓝牙发送消息,然后通过我的外围设备中的 UART 传递这些消息。我已经按照步骤 here应用程序扫描并成功找到设备。但是,使用 BluetoothGatt = B
我一直在研究 BT 4.x (LE) 规范,试图弄清楚这是否可能(没有配对/预兆的事件)。 如果可能的话,有没有人有洞察力(最好链接到规范)? 最佳答案 正如 Mike Petrichenko 评论的
我在这里有一个更广泛的问题,所以如果有人可以向我指出可以解释这一点的文档或文章,那就足够了。不用说,一天的谷歌搜索让我无处可去,我可以伸出援助之手。 我正在连接到 BeagleBoard使用 Blue
我正在为 Android 手机和 Android watch (wearOS) 编写应用程序。这些应用程序将通过蓝牙相互通信。基本上,Android 手机上的应用程序将与 WearOS 设备绑定(bi
我正在研究与 GATT 相关的低功耗蓝牙 (BLE) 中可用的安全类型。更具体地说,使用指定不同安全级别(低、中、高)的 gatttool 时会执行哪些操作?我的理解是BLE中的安全管理器支持4种不同
我正在为 Android 手机和 Android watch (wearOS) 编写应用程序。这些应用程序将通过蓝牙相互通信。基本上,Android 手机上的应用程序将与 WearOS 设备绑定(bi
我正在尝试在树莓派上使用 go 来查询蓝牙低功耗设备。它是功能性的,我可以连接到我想要的设备并迭代连接设备的服务和特性。现在我只是想简化事情,只是读/写我感兴趣的值。它不起作用。 代码: func o
我正在尝试构建一个使用 BluetoothLE 的 Android 应用程序。在教程中,他们使用 128 位 UUID,但我只有 16 位 UUID。我必须使用服务 UUID 和蓝牙基地创建一个新的
我正在开发一个带有 GATT 服务器的 Android Things 应用程序(Dev Preview 6.1,Raspberry Pi)。当连接的客户端应用程序断开连接时,我的设备已停止广告。但是,
我一直在尝试使用 Glucose service 从 BLE 设备读取葡萄糖测量记录.我能够成功连接到设备并在获取新记录时读取它们,但是当我请求以前记录的列表时,我收到状态为 129 的回调(“GAT
我正在开发一个与自定义蓝牙设备通信的 Android 应用程序。调用 BluetoothGatt.Disconnect() 后,我看到调用了 OnConnectionStateChange 回调,新状
我已经创建了一个 BLE GATT 服务器的 android 应用程序,但我找不到在哪里写 GATT 服务器的名称,我的意思是搜索中出现的设备名称。 我都试过了 https://github.com/
我是一名优秀的程序员,十分优秀!