Git Product home page Git Product logo

Comments (20)

otaviojr avatar otaviojr commented on August 19, 2024 2

@jhartzell42 done

from bluer.

otaviojr avatar otaviojr commented on August 19, 2024 1

You are right, and you made me see things from a different perspective.

Looking at the API documentation, we must register the root endpoint once and add the AdvertisementMonitor1 interface underneath it multiple times.

Instead, we are adding the root endpoint for every monitor we register.

And this is also the problem with the crossroad. Every time we add the same path again, it replaces the old one and loses the previous child structure. In the end, it will have only the last monitor as a child, and the previous ones will stop working.

With that in mind, I made another proposal, one where we register the monitor once and then add as many rules as we want.

I created a new branch for it:
https://github.com/otaviojr/bluer/tree/monitor1

And here is the code I used to try it out.

if let Ok(mut monitor_handle) = adapter.register_monitor().await {
    monitor_handle.add_monitor(Monitor {
        activate: Some(Box::new(move || {
            Box::pin(async {
                println!("Monitor 1: Activate funcion called");
                Ok(())
            })
        })),
        release: Some(Box::new(move || {
            Box::pin(async {
                println!("Monitor 1: Release funcion called");
                Ok(())
            })
        })),
        device_found: Some(Box::new(move |device| {
            Box::pin(async move {
                println!("Monitor 1: DeviceFound funcion called: {}",device.addr);
                Ok(())
            })
        })),
        patterns: Some(vec!(Pattern {
            start_position: 2,
            ad_data_type: 0xff,
            content_of_pattern: vec!(190, 172, 57, 237, 152, 255, 41, 0, 68, 26, 128, 47, 156, 57, 143, 193, 153, 210, 0, 1, 0, 100, 197, 100)
        })),
        rssi_low_threshold: Some(127),
        rssi_high_threshold: Some(127),
        rssi_low_timeout: Some(0),
        rssi_high_timeout: Some(0),
        ..Default::default()
    }).await;
    monitor_handle.add_monitor(Monitor {
        activate: Some(Box::new( move || {
            Box::pin(async {
                println!("Monitor 2: Activate funcion called");
                Ok(())
            })
        })),
        release: Some(Box::new( move || {
            Box::pin(async {
                println!("Monitor 2: Release funcion called");
                Ok(())
            })
        })),
        device_found: Some(Box::new(move |device| {
            Box::pin(async move {
                println!("Monitor 2: DeviceFound funcion called: {}",device.addr);
                Ok(())
            })
        })),
        patterns: Some(vec!(Pattern {
            start_position: 2,
            ad_data_type: 0xff,
            content_of_pattern: vec!(190, 172, 57, 237, 152, 255, 41, 0, 68, 26, 128, 47, 156, 57, 143, 193, 153, 210, 0, 1, 0, 100, 197, 100)
        })),
        rssi_low_threshold: Some(127),
        rssi_high_threshold: Some(127),
        rssi_low_timeout: Some(0),
        rssi_high_timeout: Some(0),
        ..Default::default()
    }).await;
}

With this code, I have been able to receive events for both monitors.

Monitor 1: DeviceFound funcion called: 60:68:4E:15:18:25
Monitor 2: DeviceFound funcion called: 60:68:4E:15:18:25

And the dbus objects's paths are now following what has been suggested in the API documentation.

PS: I borrowed some pieces of your code, especially the one that handles the or_patterns, which are much better than mine. Thanks for that.

regards,
Otávio Ribeiro

from bluer.

surban avatar surban commented on August 19, 2024

This would probably be provided by the advertisement monitoring api which is indeed not yet implemented in BlueR.

from bluer.

otaviojr avatar otaviojr commented on August 19, 2024

I'm working on this for a few days now, it's not working yet. It should, but bluez is not calling the callback functions.

Maybe something with bluez?

I compiled the latest version manually since monitoring API is something new.

I forked bluer:
https://github.com/otaviojr/bluer/tree/monitor

The code is simple:

callbacks:

    pub fn activate_fn() -> Pin<Box<dyn Future<Output = bluer::monitor::ReqResult<()>> + Send>> {
        println!("Activate funcion called(1)");
        Box::pin(async {
            println!("Activate funcion called(2)");
            Ok(())
        })
    }

    pub fn release_fn() -> Pin<Box<dyn Future<Output = bluer::monitor::ReqResult<()>> + Send>> {
        println!("Release funcion called(1)");
        Box::pin(async {
            println!("Release funcion called(2)");
            Ok(())
        })
    }

    pub fn device_found_fn(device: DeviceFound) -> Pin<Box<dyn Future<Output = bluer::monitor::ReqResult<()>> + Send>> {
        println!("DeviceFound funcion called(1)");
        Box::pin(async {
            println!("DeviceFound funcion called(2)");
            Ok(())
        })
    }

code:

if let Ok(monitor_handle) = adapter.register_monitor(Monitor {
                        activate: Some(Box::new(BlueZ::activate_fn)),
                        release: Some(Box::new(BlueZ::release_fn)),
                        device_found: Some(Box::new(BlueZ::device_found_fn)),
                        patterns: Some((0x00, 0xff,vec![0xbe,0xac])),
                        ..Default::default()
                    }).await { ...

Now, a few things on bluer may complicate things further.

BlueR changes some filters on discover_devices on the user's behalf, it doesn't allow duplicates, which could be a problem with beacons, and it does not allow us to choose a LE scan only.

I think discover_devices is not necessary with passive scan, but if they work simultaneously, it could be a problem with beacons. I don't know.

And sorry if my Rust code is not state of the art. I'm relatively new to Rust.. just trying to do my best here.

regards,
Otávio Ribeiro

from bluer.

otaviojr avatar otaviojr commented on August 19, 2024

Oh, and I'm having a hard time with those or_patterns as well... but I will figure them out eventually.

from bluer.

lopsided98 avatar lopsided98 commented on August 19, 2024

I also started a prototype a while ago, but forgot to post it here: lopsided98/bluer@master...adv-mon

It works, but currently only supports one monitor at a time. The monitor root can only contain a single monitor right now because dbus-crossroads seems to only support sending added/removed signals for the root ObjectManager, so I can't tell BlueZ when a new monitor was added.

I also found that adjusting any of the RSSI settings broke the monitor (I forget the exact details, but most of the time I would just get no notifications), and I was never able to get the DeviceLost callback to work reliably. These both appear to be BlueZ issues.

Despite these issues, I was to get it working well for my application. To reliably get notifications when a device starts reappears after disappearing for a while, I have to re-register the monitor. My application code can be found here: https://github.com/lopsided98/WaterLevelMonitor/blob/54e8bc2219d0ef33d84bb9c4fb57ed287cb848a3/base_station/src/sensor.rs#L185

from bluer.

otaviojr avatar otaviojr commented on August 19, 2024

I managed to make it to work. At least receiving the Activate/Release callbacks.

It was the object manager indeed. Once I implemented it on the monitor interface things started to work.

I managed to implement object manager at the monitor path, so, in my version, you can have more than one monitor, as many as bluez allows. At least, in theory, I will make more tests on it. If you want to get a look at it, maybe you could allow more than one monitor on your version as well.

Now, I need to finish the DeviceFound and DeviceLost endpoints and I think it will be good to go.

regards,
Otávio Ribeiro

from bluer.

lopsided98 avatar lopsided98 commented on August 19, 2024

It looks like you are still calling RegisterMonitor and UnregisterMonitor for each monitor, right? If the object manager signals are working, you should be able to register the root once (with RegisterMonitor) and then just add monitors under that root through the object manager.

from bluer.

otaviojr avatar otaviojr commented on August 19, 2024

I made the last commit with those changes....

I'm implementing the object manager at the root level, but my root level is the uuid. The AdvertisementMonitor1 interface is one level above the uuid...

that allows you to have multiple monitors.

object manager -> /org/bluez/bluer/monitor/4e7adc5601864010bf393486740bbe92
AdvertisementMonitor1 -> /org/bluez/bluer/monitor/4e7adc5601864010bf393486740bbe92/app

    pub(crate) async fn register(self, inner: Arc<SessionInner>, adapter_name: &str) -> Result<MonitorHandle> {
        let manager_path = dbus::Path::new(format!("{}/{}", MANAGER_PATH, adapter_name)).unwrap();
        let uuid = Uuid::new_v4().as_simple().to_string();
        let root = dbus::Path::new(format!("{}/{}",MONITOR_PREFIX,uuid)).unwrap();
        let name = dbus::Path::new(format!("{}/{}/app",MONITOR_PREFIX,uuid)).unwrap();

        log::trace!("Publishing monitor at {}", &name);

        {
            let mut cr = inner.crossroads.lock().await;
            let object_manager_token = cr.object_manager();
            let introspectable_token = cr.introspectable();
            let properties_token = cr.properties();
            cr.insert(root.clone(), [&object_manager_token, &introspectable_token, &properties_token], {});
            cr.insert(name.clone(), [&inner.monitor_token], Arc::new(self));
        }

        log::trace!("Registering monitor at {}", &name);
        let proxy = Proxy::new(SERVICE_NAME, manager_path, TIMEOUT, inner.connection.clone());
        proxy.method_call(MANAGER_INTERFACE, "RegisterMonitor", (root.clone(),)).await?;

        let (drop_tx, drop_rx) = oneshot::channel();
        let unreg_name = root.clone();
        tokio::spawn(async move {
            let _ = drop_rx.await;

            log::trace!("Unregistering monitor at {}", &unreg_name);
            let _: std::result::Result<(), dbus::Error> =
                proxy.method_call(MANAGER_INTERFACE, "UnregisterMonitor", (unreg_name.clone(),)).await;

            log::trace!("Unpublishing monitor at {}", &unreg_name);
            let mut cr = inner.crossroads.lock().await;
            let _: Option<Self> = cr.remove(&unreg_name);
        });

        Ok(MonitorHandle { name, _drop_tx: drop_tx })
    }

regards,
Otávio Ribeiro

from bluer.

lopsided98 avatar lopsided98 commented on August 19, 2024

Yeah, I guess that works, but it doesn't seem to be the how the advertisement monitor API is intended to be used. The documentation implies that you are supposed to create a single root object manager per application and then create multiple monitors underneath that, using the object manager signals to tell BlueZ that they were added/removed.

from bluer.

hpux735 avatar hpux735 commented on August 19, 2024

Is this issue still open? I'm hoping to use this lib for essentially beacon advertisements, so it seems like this issue might be impactful for me?

from bluer.

otaviojr avatar otaviojr commented on August 19, 2024

I believe it is still open.

I am still waiting for feedback.

You could get my branch, update it and use it.

I've been using it for a while now, and it works well.

Regards

from bluer.

jhartzell42 avatar jhartzell42 commented on August 19, 2024

@otaviojr I got feedback pretty quickly for my (unrelated) change once I actually made a MR. Would you be willing to make a MR of your branch? If not, I can make an MR from a copy of your branch on my fork, so I can handle the feedback and make appropriate updates.

from bluer.

surban avatar surban commented on August 19, 2024

Could you please send a PR if you would like a review? This makes it easier for everyone.

from bluer.

jhartzell42 avatar jhartzell42 commented on August 19, 2024

OK, I made an MR on @otaviojr 's behalf...

from bluer.

jhartzell42 avatar jhartzell42 commented on August 19, 2024

If @surban would be interested, I can move this MR to my own fork and clean up the commit log as well :-)

from bluer.

otaviojr avatar otaviojr commented on August 19, 2024

OK, I made an MR on @otaviojr 's behalf...

Sorry for the delay, but thanks. If you need something, let me know...

About the commit logs, I developed them on a remote host and used git to sync code... :-(

Can be cleaned

from bluer.

otaviojr avatar otaviojr commented on August 19, 2024

@jhartzell42 I've cleaned all commit logs at https://github.com/otaviojr/bluer/tree/monitor1 branch

Can you change your pull request?

from bluer.

jhartzell42 avatar jhartzell42 commented on August 19, 2024

I can't retarget it to a different branch, and I can't modify the branch I'm using, as it's a pull request literally from your fork. Could you possibly make your own pull request from monitor1?? If not, I'll delete the one I have, make my own fork, migrate your new branch over, and make a new pull request.

from bluer.

surban avatar surban commented on August 19, 2024

PR merged.

from bluer.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.