Estimote / react-native-proximity

React Native wrapper for Estimote Proximity SDK
Apache License 2.0
61 stars 38 forks source link

onChangeAction event is not triggered when multiple beacons are nearby. #42

Closed cfmitrah closed 5 years ago

cfmitrah commented 5 years ago

onEnterAction is triggered when two beacons are nearby. but only one beacon data is passed as an event object . I went through docs and found out that onChangeAction has data about multiple beacons in the range. but it doesn't trigger at all. I have a use case where i need to display multiple beaons list. how can i achieve this? is there any other alternative to onChangeAction?

heypiotr commented 5 years ago

Are you sure that both beacons are tagged appropriately? Last time I was testing, I believe I saw the onChangeAction trigger properly. I'll re-test when I have a moment.

cfmitrah commented 5 years ago

This is affecting our release schedule. Please look into this as soon as possible . Thanks.

heypiotr commented 5 years ago

I can confirm that it works for me:

Running application "example" with appParams: {"rootTag":1}. __DEV__ === true, development-level warning are ON, performance optimizations are OFF
location permission: always
'zone1 onEnter', { tag: 'proximity-one-cet',
  attachments: 
   { 'proximity-one-lkn/title': 'blueberry',
     'proximity-one-cet/title': 'blueberry',
     'proximityone-ci2/title': 'blueberry',
     'proximity-bxf/title': 'blueberry' },
  deviceIdentifier: '7d3a2f6ce0eaeffc05f939c5a8b4943a' }
'zone1 onChange', [ { tag: 'proximity-one-cet',
    attachments: 
     { 'proximity-one-lkn/title': 'blueberry',
       'proximity-one-cet/title': 'blueberry',
       'proximityone-ci2/title': 'blueberry',
       'proximity-bxf/title': 'blueberry' },
    deviceIdentifier: '7d3a2f6ce0eaeffc05f939c5a8b4943a' } ]
'zone1 onChange', [ { tag: 'proximity-one-cet',
    attachments: 
     { 'proximity-one-lkn/title': 'blueberry',
       'proximity-one-cet/title': 'blueberry',
       'proximityone-ci2/title': 'blueberry',
       'proximity-bxf/title': 'blueberry' },
    deviceIdentifier: '7d3a2f6ce0eaeffc05f939c5a8b4943a' },
  { tag: 'proximity-one-cet',
    attachments: {},
    deviceIdentifier: 'fd10f449c05ee38c26edc723bb502e2a' } ]

You can see first both onEnter and onChange triggered for 7d3a2f6c, then followed by onChange with both 7d3a2f6c and fd10f449.

I tested with the latest example app, on Android.

Maybe double-check your onChangeAction, your zones setup (tags/range), and the Estimote Cloud tags?

cfmitrah commented 5 years ago

each beacon is detected individually on onEnter but onChangeAction never gets triggered. How can i help you to replicate the issue? how to get the logs like you did?

heypiotr commented 5 years ago

Can you show me your code, and write down your tags setup? (i.e., which beacon has what tags)

cfmitrah commented 5 years ago

This is my beacon monitoring code

const beaconList = [
            {
                bec_id: 1001,
                bec_uuid: <BEACON_IDENTIFIER>,
                str_id: 4005,
                bec_name: 'mint',
                loc_id: 2001,
                id: 25,
                tag: 'store1'
            },
            {
                bec_id: 1002,
                bec_uuid:<BEACON_IDENTIFIER>,
                str_id: 1002,
                bec_name: 'blueberry',
                loc_id: 2010,
                id: 26,
                tag: 'store11'
            },
            {
                bec_id: 1003,
                bec_uuid:<BEACON_IDENTIFIER>,
                str_id: 4006,
                bec_name: 'ice',
                loc_id: 2005,
                id: 27,
                tag: 'store3'
            },
            {
                bec_id: 1004,
                bec_uuid:<BEACON_IDENTIFIER>,
                str_id: 4006,
                bec_name: 'coconut',
                loc_id: 2004,
                id: 28,
                tag: 'store2'
            }
        ];
        if (beaconList.length) {
            RNEP.locationPermission.request().then(
                permission => {
                    if (permission !== RNEP.locationPermission.DENIED) {
                        const credentials = new RNEP.CloudCredentials(ESTIMOTE_APP_ID, ESTIMOTE_APP_TOKEN);
                        const config = {
                            notification: {
                                title: 'Exploration mode is on',
                                text: "We'll notify you when you're next to something interesting.",
                                channel: {
                                    id: 'exploration-mode',
                                    name: 'Exploration Mode'
                                }
                            }
                        };
                        var zones = [];
                        Reactotron.log({ beaconList });
                        for (var i = 0; i < beaconList.length; i++) {
                            var zone = new RNEP.ProximityZone(5, beaconList[i].tag);
                            zone.onEnterAction = this.onZoneEntered;
                            zone.onExitAction = this.onZoneExit;
                            zone.onChangeAction = this.onZoneChanged;
                            zones.push(zone);
                        }
                        RNEP.proximityObserver.initialize(credentials, config);
                        if (zones.length) {
                            RNEP.proximityObserver.startObservingZones(zones);
                        }
                    }
                },
                error => {
                    Alert.alert('Error', JSON.stringify(error));
                    console.error('Error when trying to obtain location permission', error);
                }
            );
        }

    onZoneEntered = context => {
        Alert.alert(`beacon Zone Entered`, JSON.stringify(context));
        console.log('zone onEnter', context);
    };

    onZoneExit = context => {
        console.log('zone onExit', context);
    };

    onZoneChanged = contexts => {
        console.log('zone onChange', contexts);
        Alert.alert('zoneChanged', JSON.stringify(contexts));
    };
heypiotr commented 5 years ago

Thanks! So you have one beacon per each zone, is that right? In this case, you should only ever see onEnter and onChange trigger together (when you enter range of that one beacon), and onExit and onChange trigger together too (when you exit range of that one beacon). You'll never see onChange trigger on its own, because that only makes sense for a zone with multiple beacons, whereas you have zones each with a single beacon.

Does that make sense now? Is the behavior I've described what you're seeing?

how to get the logs like you did?

Sorry, I missed that question earlier. My logs were simply output from the console, you can see that via react-native log-android or via Chrome/React Developer Tools (https://facebook.github.io/react-native/docs/debugging#chrome-developer-tools).

cfmitrah commented 5 years ago

No I do not have one beacon per zone. I placed two beacons nearby my phone. and opened the app, only onEnter is triggered.

heypiotr commented 5 years ago

Your beaconList has exactly 4 beacons, and each of them has a different tag. Are there any other beacons that are not on the beaconList, but which share tags with these 4 beacons?

In any case, this looks like a problem with your setup and/or understanding how Proximity Zones work, and the plugin itself works as intended, so I'll close this bug report. This is essentially a Proximity SDK conversation, and the react-native-proximity is just a bridge between the Proximity SDK and React Native, so it'd be better to continue this conversation on our forums (https://forums.estimote.com), in the Proximity category.

cfmitrah commented 5 years ago

I just need to know one thing. two beacons with tags store1 and store2 respectively. I place those beacons near my phone. i open the app. How am i supposed to know there are multiple beacons in range when only onEnter is triggered.?

heypiotr commented 5 years ago

You should see two onEnter events. One for the "store1" zone, and one for the "store2" zone.

cfmitrah commented 5 years ago

Ok thank you

cfmitrah commented 5 years ago

Can you suggest a better approach for my use case? if the phone is inside range of multiple beacons we need to display those list of beacon data. since onEnter has data of only one beacon. how can i achieve it?

heypiotr commented 5 years ago

Assign the same tag to all the beacons (e.g., "store", instead of "store1", "store2", etc.), and create just one Proximity Zone for that tag.

Then the onChange handler will be called every time the list of "store" beacons currently in range changes.

cfmitrah commented 5 years ago

You have said that Then the onChange handler will be called every time the list of "store" beacons currently in range changes.. onChange will be called only when beacon range changes ?. Doesn't it trigger initially with data of all beacons in range?

heypiotr commented 5 years ago

Perhaps it's best we look at the logs I posted previously to understand this better: (I've reformatted them slightly for better readability)

'zone1 onEnter', { 
  tag: 'proximity-one-cet',
  attachments: { ... },
  deviceIdentifier: '7d3a2f6ce0eaeffc05f939c5a8b4943a' }
'zone1 onChange', [ { 
    tag: 'proximity-one-cet',
    attachments: { ... },
    deviceIdentifier: '7d3a2f6ce0eaeffc05f939c5a8b4943a' } ]

'zone1 onChange', [ { 
    tag: 'proximity-one-cet',
    attachments: { ... },
    deviceIdentifier: '7d3a2f6ce0eaeffc05f939c5a8b4943a' },
  { tag: 'proximity-one-cet',
    attachments: {},
    deviceIdentifier: 'fd10f449c05ee38c26edc723bb502e2a' } ]

Here you can see I have two beacons both tagged as "proximity-one-cet".

First, I entered range of 7d3a, which triggered both onEnter, and onChange with an array with 7d3a.

Then, I entered range of fd10, which triggered onChange with array with both 7d3a and fd10.

Say, if I were now to exit range of 7d3a, but remain in range of fd10, there would be onChange with an array with fd10.

Finally, if I were now to exit range of fd10, there would be onChange with an empty array, and an onExit with fd10.

cfmitrah commented 5 years ago

I get what you are saying. But Please consider this scenario where the app starts scanning on click of a button. Your two beacons 7d3a and fd10 are placed close together and they have the same tag. you go near them and click the button to start monitoring. my question is will the onChange event get triggered with array of both beacon data?

heypiotr commented 5 years ago

Since Bluetooth scanning is sequential (radio discovers packets one by one), first you'll get an onChange event with one beacon (whichever the radio managed to scan first), and almost immediately after (specifically, after the radio scans the second beacon) you'll get onChange with both beacons. It'll look just like in the logs above (7d3a first, then both 7d3a and fd10).

cfmitrah commented 5 years ago

can you tell me approx the time taken for subsequent scans? so that i can wait for multiple beacons detection and complete my functionality. Does the distance between the beacons have an impact in time delay?

heypiotr commented 5 years ago

The way this works is, the Bluetooth stack in the smartphone will periodically start scanning, and during that time, it should detect any Bluetooth devices that broadcast nearby. Beacons in Estimote Monitoring broadcast every 200 or 300 ms, so if the smartphone is listening and processing this data, it should take < 200/300 ms between beacon detections.

In practice this is more complicated, because the Bluetooth stack in smartphones doesn't necessarily scan all the time, it also needs to share time/resources between other apps, and things like Bluetooth headphones, etc.

Distance is generally negligible, since Bluetooth radio waves travel at the speed of light. Distance however does increase the error rates, i.e., the probability that the signal/data will get corrupted.


I'll lock this issue now, but I'll be happy to continue the conversation on our forums: http://forums.estimote.com