[BLE--GAP]GAP Service及其使用

简述

GAP本身是一个Profile,并不是Protocol,其作用是定义了如何来使用蓝牙的Host的各层的Protocol。GAP中有一个GAP Service,是用来表明设备的基本信息的,只要作为GATT Server,就需要实现这个GAP Service。

GAP Service

先看一张图,对GAP Service有个整体了解:
这里写图片描述
从此图可看到,BR/EDR可以选择实现GAP Service的Device Name和Appearance属性。对于BLE而言,是分角色进行对待的,Broadcaster和Observer不需要GAP Service。对于Peripheral和Central角色,则可能会需要实现其中部分或全部实现:

Peripheral

Device Name和Appearance必须要实现,Peripheral Preferred Connection Parameters是可选的,而Central Address Resolution则要看Link Layer Privacy是否支持。

Central

Device Name和Appearance必须要实现,Peripheral Preferred Connection Parameters不需要,因为是针对peripheral的,而Central Address Resolution则要看Link Layer Privacy是否支持。

多GAP Role模式下

对于支持多GAP Role的:GAP Service必须支持所有Role的需求,即为所有Role需求的总和。而当操作于不支持某些Characteristic的Role下时,设备也必须继续暴露出其所支持的所有GAP Service的Characteristics。

Characteristic介绍

GAP Service的4个Characteristic的介绍。

Device Name

这里写图片描述
虽然这里规定Device Name长度可以到248字节,但一般不会需要那么长的名字,一般会建议最长到达40字节就好了。

Appearance

这里写图片描述
Appearance即表明这是个什么设备,如鼠标?键盘?等等,用2个字节可以表示很多种类的,某个代码对应某个具体的Appearance表示,这个需要参考SIG的Assigned Numbers,上面有列表的。另外,Device Name和Appearance都是表示本地设备属性的,因此只会有一份实例。对于多GAP Role的状况,应当还是只会维护一份Device Name和Appearance,不然一个设备有多个名字和多个Appearance,就不好表示了。

Peripheral Preferred Connection Parameters(PPCP)

这里写图片描述
主要是表明Peripheral设备这边比较偏好的一个连接参数,包括:
- Minimum connection interval
- Maximum connection interval
- Slave Latency
- Connection Supervision timeout multiplier
关于连接参数的介绍涉及的地方很多了,这里不再赘述。其实最关注的还是在哪使用这个参数?如何使用呢?我的想法是,这个是供Central来获知的。不过有点略为奇怪,Central在链路建立时是通过CONN_REQ来设置好连接参数的,而此时两者并未建立连接,因此Central此时并不同通过ATT_Read来获取Peripheral上的这个PPCP,难道是建立连接后Central有需要知道这个PPCP的必要?因为Peripheral也有直接更新连接参数的过程的啊,这样看来具体应用估计也不是必要吧。

Central Address Resolution

这个看来是BT 4.2添加的新特性了。因为在BT 4.2中,为了提高BT的安全性(原来SMP的方式是可以破解的),加入了Random Address的内容。这里的Central Address Resolution就是用来表明暴露GAP Service的这个Central设备,是否支持Resolvable Private Address(RPA)的。
Peripheral设备通过读对方Central设备的GAP Service的Central Address Resolution,就能知道其是否支持RPA了,如果其支持,那Peripheral就可以在自己的Directed Advertisement中使用RPA了。如果不支持,那还是只能使用public地址了。
关于蓝牙的public地址,private地址,请参考设备蓝牙地址这篇文章。
来看下Central Address Resolution的内容:
这里写图片描述

一份实例

最后补充下,上面的GAP Service,对于一个设备而言,应当是只有一份实例的,即不管是多GAP Role设备还是就只支持一个GAP Role,都只需要维护一份GAP Service,而该Service中的Characteristics都只有一份实例的。

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,以下是示例代码: ```python from machine import Pin from time import ticks_ms from ubluetooth import BLE, UUID, FLAG_NOTIFY, FLAG_READ, FLAG_WRITE, FLAG_WRITE_NO_RESPONSE, BLEException # 设定UUID MY_SERVICE_UUID = UUID(0x1811) MY_CHARACTERISTIC_UUID = UUID(0x2A46) MY_DESCRIPTOR_UUID = UUID(0x2901) # 初始化BLE ble = BLE() # 设定广告数据 adv_data = bytearray(b'\x02\x01\x06\x03\x02\x11\x15') + ble.config('mac')[::-1] + bytearray(b'\x0f\x09Micropython ESP32') adv_data += bytearray(b'\x03\x03\x11\x15\xE0\xFF') # 设定扫描响应数据 scan_resp_data = bytearray(b'\x04\x09ESP32\x02\x0a\x00\x02\x0a\x06\xDE\xAD\xBE\xEF') # 设定GATT服务、特征值和描述符 my_service = ble.gatts_service( uuid=MY_SERVICE_UUID, isprimary=True ) my_characteristic = my_service.add_characteristic( uuid=MY_CHARACTERISTIC_UUID, properties=FLAG_READ | FLAG_WRITE, value=b'Initial value', permissions=0x0A, ) my_descriptor = my_characteristic.add_descriptor( uuid=MY_DESCRIPTOR_UUID, value=b'ESP32', ) # 扫描结果处理函数 def scan_result(adt, addrType, addr): print('Scanned device:', addr, 'type:', addrType, 'advertising data:', adt) # 广告事件处理函数 def adv_event(adv): print('Advertising:', adv) # 设定扫描回调函数 ble.gap_scan(2000, 30000, interval_us=128000, window_us=112500, callback=scan_result) # 设定广告事件回调函数 ble.irq(ble.IRQ_ADVERTISING_START, adv_event) # 循环处理BLE事件 while True: try: events = ble.events() for event, data in events: if event == BLE.EVENT_SCAN_TIMEOUT: print('Scan timeout') elif event == BLE.EVENT_SCAN_RESULT: # 处理扫描结果 addr, addrType, advtype, rssi, advdata = data if addrType == 0: # 仅处理公共地址设备 print('Scanned device with public address:', addr) if b'Micropython ESP32' in advdata: print('Device', addr, 'is an ESP32') # 连接设备 try: dev = ble.gap_connect(addr) print('Connected to device:', addr) # 发现服务 services = dev.list_services() for service in services: if service.uuid() == MY_SERVICE_UUID: # 发现特征值 characteristics = service.list_characteristics() for characteristic in characteristics: if characteristic.uuid() == MY_CHARACTERISTIC_UUID: print('Found characteristic:', characteristic.uuid()) # 读取特征值 value = characteristic.read() print('Current value:', value) # 写入特征值 characteristic.write(b'New value') print('Value written') break # 断开连接 dev.disconnect() print('Disconnected from device:', addr) except BLEException as e: print('Could not connect to device:', addr) print(str(e)) elif event == BLE.EVENT_GATTS_WRITE: # 处理特征值写入事件 conn_handle, attr_handle = data value = my_characteristic.read() print('Characteristic value written:', value) except Exception as e: print(str(e)) # 等待100ms wait_ms = ticks_ms() + 100 while ticks_ms() < wait_ms: pass ``` 希望我的回答对你有所帮助,如有其他问题,不要犹豫地继续提问哦!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技塑未来-苏导

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值