google / google/bumble

Unable to trigger notifications from two virtual devices connected to the same bumble controller

Open
#136 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
555
Forks
138
Avg merge
3d 15h
Merged PRs (30d)
9

Description

Hello, I have had good success melding the heart rate server example (```heart_rate_server.py```) with the run controller example (```run_controller.py```). I have used the vhci controller bus option and been able to observe virtual heart rate measurements on my raspberry pi from the chromium browser. Great!

But, I want to add a second virtual device, so I added another virtual heart rate server. Something like this:

C1<-VHCI->System
|
|->C2(Heart rate monitor 1)
|->C3(Heart rate monitor 2)

Now things have gone wrong. Only one of these virtual heart rate monitors, say C2, ever gets notifications from a subscriber sent to its ```HeartRateService()``` instance, although both C2 and C3 can be found and paired from ```bluetoothctl``` to the bluez stack.

I have been careful to check that I duplicated instances for all necessary classes, but I can't find what the cause for the second virtual device not firing messages might be and single stepping the code didn't provide any clues either.

I've attached my script below, which will reproduce the issue when dumped into the ```examples``` directory. But if anyone has a working example of more than one virtual device connected to the same controller that would also be ideal.

Cheers!

```
import logging
import asyncio
import os

import time
import math
import random
import struct

from bumble.gatt import (
GATT_CHARACTERISTIC_USER_DESCRIPTION_DESCRIPTOR,
GATT_DEVICE_INFORMATION_SERVICE,
GATT_MANUFACTURER_NAME_STRING_CHARACTERISTIC,
Characteristic,
Descriptor,
Service,
)
from bumble.device import Device
from bumble.host import Host
from bumble.controller import Controller
from bumble.link import LocalLink
from bumble.transport import open_transport_or_link

from bumble.core import AdvertisingData

from bumble.profiles.device_information_service import DeviceInformationService
from bumble.profiles.heart_rate_service import HeartRateService
from bumble.profiles.battery_service import BatteryService

# -----------------------------------------------------------------------------
async def main():

print('>>> connecting to HCI...')
async with await open_transport_or_link('vhci') as (hci_source, hci_sink):
print('>>> connected')

# Create a local link
link = LocalLink()

# Create a first controller using the packet source/sink as its host interface
controller1 = Controller(
'C1', host_source=hci_source, host_sink=hci_sink, link=link
)
controller1.random_address = "F0:F7:F8:F9:FA:FB"

#========================================
# Virtual Heart Rate Device #
#========================================
# Keep track of accumulated expended energy
energy_start_time_hrm = time.time()

def reset_energy_expended_hrm():
nonlocal energy_start_time_hrm
energy_start_time_hrm = time.time()

# Create a second controller using the same link
controller2 = Controller('C2', link=link)

# Create a host for the second controller
host = Host()
host.controller = controller2

# Create a device to manage the host
hrm_device = Device.from_config_file("device2.json")
hrm_device.host = host

#MB also add a heart rate service
heart_rate_service = HeartRateService(
read_heart_rate_measurement=lambda _: HeartRateService.HeartRateMeasurement(
heart_rate=100 + int(50 * math.sin(time.time() * math.pi / 60)),
sensor_contact_detected=random.choice((True, False, None)),
energy_expended=random.choice(
(int((time.time() - energy_start_time_hrm) * 100), None)
),
rr_intervals=random.choice(
(
(
random.randint(900, 1100) / 1000,
random.randint(900, 1100) / 1000,
),
None,
)
),
),
body_sensor_location=HeartRateService.BodySensorLocation.WRIST,
reset_energy_expended=lambda _: reset_energy_expended_hrm(),
)

hrm_device.add_services([heart_rate_service])

# Debug print
for attribute in hrm_device.gatt_server.attributes:
print(attribute)

#MB: set virtual device to advertize heart rate capability
# Set the advertising data
hrm_device.advertising_data = bytes(
AdvertisingData(
[
(
AdvertisingData.COMPLETE_LOCAL_NAME,
bytes('Bumble Heart', 'utf-8'),
),
(
AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
bytes(heart_rate_service.uuid),
),
(AdvertisingData.APPEARANCE, struct.pack('

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.