Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

is periodic on-demand scanning possible? #43

Open
jonorthwash opened this issue Jun 3, 2024 · 3 comments
Open

is periodic on-demand scanning possible? #43

jonorthwash opened this issue Jun 3, 2024 · 3 comments

Comments

@jonorthwash
Copy link

Given the issues calling asyncio more than once, is there a recommended way to on-demand scan (i.e., when some other function wants to)?

The aranet4.client.find_nearby() function, as used in the scanner_simple.py example, won't work because of the issues calling asynchio more than once.

Using aranet4.Aranet4Scanner() seems like a good alternative, but the scanner_advanced.py example is built around polling at a common interval. I need to poll periodically, triggered by some other action. If I have it .start() and .stop() every time it needs to poll, I assume I'll run into above-mentioned issues. Is there some way I can have it start, scan as requested (not with a fixed delay), and eventually stop?

@Anrijs
Copy link
Owner

Anrijs commented Jun 3, 2024

scanner_advanced.py isn't using any intervals.
It will set up scanner once with a callback function, that will be executed for every advertisement received, in the background.

If Aranet4Scanner doesn't fit you, you could also use plain BleakScanner. Just use Aranet4Advertisement to parse data:

import asyncio
from aranet4.client import Aranet4Advertisement
from aranet4.client import Aranet4
from bleak import BleakScanner


def process_advertisement(device, ad_data):
    adv = Aranet4Advertisement(device, ad_data)
    print(adv)

async def main():
    uuids = [Aranet4.AR4_SERVICE, Aranet4.AR4_OLD_SERVICE]
    scanner = BleakScanner(
        detection_callback=process_advertisement,
        service_uuids=uuids
    )
    await scanner.start()
    await asyncio.sleep(5)
    await scanner.stop()

asyncio.run(main())

@jonorthwash
Copy link
Author

will be executed for every advertisement received, in the background.

If Aranet4Scanner doesn't fit you, you could also use plain BleakScanner. Just use Aranet4Advertisement to parse data

Both of these approaches, as I see them, are "always on", and use a sleep interval to determine how often they receive data. I would like something where I turn it on, wait for an advertisement, and turn it off, and can have this happen at will (and comparatively much more infrequently). Or am I misunderstanding how this code works?

@Anrijs
Copy link
Owner

Anrijs commented Jun 3, 2024

Yes, they will be "always on", until stop() is called.

That sleep is there only to keep pogram open. It will not stop scanning and will receive and process advertisiements in background.

If you want to run scanner only at certain times, you will need to start and stop scanner yourself.

You could also use async with BleakScanner(callback) and ayncio.Event() to run in only when needed.
Something like this:

import asyncio
import time
from aranet4.client import Aranet4Advertisement
from bleak import BleakScanner

# Your Aranet mac address
aranet_addr = 'AA:BB:CC:DD:EE:FF'

async def main():
    stop_event = None

    # callback for scanner
    def callback(device, ad_data):
        # if device address matches aranet address, set stop_event, that will stop scanner.
        if device.address == aranet_addr:
            adv = Aranet4Advertisement(device, ad_data)
            print("Found my aranet.")
            if adv:
                print(adv.readings.toString())
            stop_event.set()

    while True:
        stop_event = asyncio.Event()
        async with BleakScanner(callback):
            print("Scanner started")

            # wait for correct device in callback
            await stop_event.wait()
            print("Scanner stopped.")

        # do your own stuff here. sleep is just an example
        time.sleep(5)

asyncio.run(main())

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants