adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
Other
4.11k stars 1.22k forks source link

BLE_HID mouse mix message send to two separate device #6790

Open dglaude opened 2 years ago

dglaude commented 2 years ago

CircuitPython version

Adafruit CircuitPython 8.0.0-beta.0 on 2022-08-18; Adafruit Feather Bluefruit Sense with nRF52840

Code/REPL

###
# Dual BLE mouse jiggling:
#  Advertise a first mouse as "CircuitPython HID1"
#  Once we have a first connection
#  Advertise a second mouse as "CircuitPython HID2"
#
# Once the first mouse is connected the jiggling start.
# Mouse1 should do Left-Right movement
# Mouse2 (once connected) should do Up-Down movement
#
# BUG?: Mouse2 does square move, so it gets the move for Mouse1.
###

import adafruit_ble

from adafruit_ble.advertising import Advertisement
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.standard.hid import HIDService
from adafruit_ble.services.standard.device_info import DeviceInfoService
from adafruit_hid.mouse import Mouse

import time
import board

hid1 = HIDService()
device_info = DeviceInfoService(software_revision=adafruit_ble.__version__, manufacturer="Adafruit Industries")
advertisement1 = ProvideServicesAdvertisement(hid1)
advertisement1.appearance = 961
scan_response1 = Advertisement()
scan_response1.complete_name = "CircuitPython HID1"

ble = adafruit_ble.BLERadio()

if not ble.connected:
    print("advertising1")
    ble.start_advertising(advertisement1, scan_response1)
else:
    print("already connected")
    print(ble.connections)

# This is a BLE mouse
mouse1 = Mouse(hid1.devices)

hid2 = HIDService()
advertisement2 = ProvideServicesAdvertisement(hid2)
advertisement2.appearance = 961
scan_response2 = Advertisement()
scan_response2.complete_name = "CircuitPython HID2"

# If I do the following before I get a connection on the first advertisement...
#   ble.start_advertising(advertisement2, scan_response2)
# It produce the following error...
#   _bleio.BluetoothError: Already advertising.

# This is a trick to wait for a first connection before making a new advertisement
while len(ble.connections) < 1:
    pass

print("advertising2")
ble.start_advertising(advertisement2, scan_response2)

# This is a BLE mouse
mouse2 = Mouse(hid2.devices)

m=10
s=1

# This works even if mouse2 is not connected yet
while True:
    while not ble.connected:
        pass
    print("Start shaking the mouse for you.")

    while ble.connected:
        time.sleep(s);        mouse1.move(x=m);
        time.sleep(s);                              mouse2.move(y=m);
        time.sleep(s);        mouse1.move(x=-m);
        time.sleep(s);                              mouse2.move(y=-m);

# This is far from perfect, we only advertise 1 where the second is not there too.
    ble.start_advertising(advertisement1)

Behavior

Mouse 1 device is supposed to receive "up" and "down" mouse movement. Mouse 2 device is supposed to receive "left" and "right" mouse movement.

However, the first device (a host that connect to the NRF) is receiving both kind of mouvement and make square pattern. The second device only does one kind of movement.

Description

The code to demonstrate this problem is maybe not the best, and maybe that trigger some problem, but a least the observed behavior is buggy. I would love to know a better way to write this kind of code, to support more than two devices.

Additional information

This bug is not new, it is there since more than one year, so not 8.0 specific. I am not the first one to notice that, but I hope to be the first to formally report it, even if it is so long after discovery. It might be a bit niche usage and certainly not high priority.

dglaude commented 2 years ago

Usually I get one device making square and the other device doing only one kind of move (left-right or up-down, I don't remember)... However, this morning as I added a new/different PC, I had two PC doing mouse square. One possibility is that the PC does connect to both mouse1 and mouse2, and that is why they do square. PCs could be confused by two so similar BLE devices, or something is remembered.