IanHarvey / bluepy

Python interface to Bluetooth LE on Linux
Other
1.59k stars 491 forks source link

How to receive every single advertising packet? #368

Open the-powl opened 5 years ago

the-powl commented 5 years ago

Hi, I'm using BLE to broadcast sensor data from a wireless node and use Bluepy on a Raspberry Pi 3 to receive the advertising packets. For a first test every second there is an advertising packet sent by the node which contains an increasing number in its data. The Rpi should now show me every single advertising packet as soon as it receives it. Unfortunately it seems that the Rpi is missing out on some of the packets every few seconds. Why is this happening? Is my code even suitable for this or are there better options? When I crank up the advertising interval to 20ms the Rpi only receives 7...10 of the packets although there should be like 50.

from datetime import datetime
from bluepy.btle import Scanner, DefaultDelegate

class ScanDelegate(DefaultDelegate):
    def __init__(self):
        DefaultDelegate.__init__(self)

    def handleDiscovery(self, dev, isNewDev, isNewData):
        print(datetime.now().time(), dev.rawData, dev.addr)
        scanner.clear()
        scanner.start()

scanner = Scanner().withDelegate(ScanDelegate())
scanner.start()

while True:
    scanner.process()
mikimer commented 5 years ago

I've also played with nodes broadcasting advertising data every second and not received every single advertising packet. A few thoughts:

  1. I characterized the problem by having two RPis side-by-side and then comparing the packets they received.
  2. It turns out that the BLE chip on the RPi is actually cheap / good but not the best.
  3. I added some BLE dongles and gathered many more advertising packets.

Hope this helps!

sterwen commented 5 years ago

Why are you restarting the scanner each time you receive an advertisement ? I don't understand how this work and based on my own experienced it cannot work or not properly best case.

the-powl commented 5 years ago

I restart the scanner each time I receive an advertisement packet because otherwise I won't get any more notifcations for receiving advertisement packets from the same station. Only using scanner.clear() doesn't work. Any better recommendations welcome! :)

the-powl commented 4 years ago

Hm, there must be something going on. When I put the scanner.process() routine in a Thread to run a GUI alongside most of the Advertising packets are missed out. This can't be an issue with the bluetooth receiver any more. Isn't there a better solution for receiving those Packets? I mean in every Beacon-Application it is important to receive every Packet. Why is this not even a thing?

lauraflu commented 3 years ago

Hi! Have there been any updates regarding this issue? I am running into the same problem. I have one Raspberry Pi which transmits advertising beacons at least once per second and another Pi which listens to them exactly like in the initial code snippet. However, the Pi receives a beacon every several of seconds or so, much less often than it should. I know that the Pi transmits more beacons because my phone can pick them up while the listening Pi cannot (at least not with this library). Does anyone have any recommendations for fixing this?

mikimer commented 3 years ago

Hi! I had this same problem. When I measured it, I found that the default BLE receiver on the RPi only caught about 40% of the transmitted BLE packets (pro tip: this decreases with distance). For my project, the easiest way to solve this problem was to buy 2 additional BLE dongles (~$10), which caught closer to 90% of the packets. I hope this helps! Happy to share more if you're curious.

lauraflu commented 3 years ago

So you say that the problem is with the RPi dongles, not necessarily with the library? Have you tried using other tools to get the packets? Unfortunately, getting more RPis is not really an option in my case because I'm interested in the RSSI of the beacons, so adding more dongles means that their positions will be different (hence also the RSSIs) and I can't compare the results side-by-side.

mikimer commented 3 years ago

Per your questions:

I hope this helps!

lauraflu commented 3 years ago

Thank you for your answer! I know that the RSSI fluctuates very heavily and that it's very difficult to infer the distance based on it, but there are some tricks to improve the results (looking at the trend instead of the value, using more RSSI measurements in a time window, filtering, etc.) Because the RSSI varies so much between devices and even with slight movements, I cannot put together measurements from more BLE receivers (be them from different dongles or RPis) and treat them like they came from the same receiver.

More importantly, I can confirm your first statement. I also think that the problem is not with the library but with the RPi or with the configuration of its BLE receiver. I tried using the same script (so the same library) on my laptop and I receive about 3-4 beacons per second from my transmitter, while the RPi receives one every 10 (!) seconds. I tried modifying my RPi's configuration but didn't manage to improve its RX rate. I think we can close this issue since the problem is not related to the library.

erikmajlath commented 3 years ago

@the-powl not really connected to Issue but if you scan in passive mode you won't need to restart scanner.

scanner.scan(seconds, passive=True)
coofercat commented 1 year ago

I'll just chime in... I have some (cheap) BLE "key finder" tags. With just one switched on, I get wildly different results with active or passive scanning (on my Raspberry Pi 4, using the built-in chip). I'm finding with Active scanning, I get very sporadic advertising, which averages about 6 per minute. If I switch to passive, I seem to get more like 62 per minute. I also find that with Active, the RSSI is usually in the range -84 to -83. With Passive, the range is -84 to -82.