I want to monitor a range of beacons using Estimote. For example lets say that ("rid", "uuid", , ) identifies a series of beacons, where all the beacons my app uses share the same "rid" and "uuid". I also hace a number of brands, where each can have more than one store.
This app would be sold to a number of brands, and I would like to use something like this:
private static final Region ALL_STORES_REGION = new Region("rid", "uuid", BRAND_ID, null);
beaconManager.startMonitoring(ALL_STORES_REGION);
Then, to receive notifications when a customer exits a certain store:
beaconManager.setMonitoringListener(new BeaconManager.MonitoringListener() {
#Override
public void onEnteredRegion(Region region, List<Beacon> beacons) {
// do nothing
}
#Override
public void onExitedRegion(Region region) {
listener.onCustomerLeaving(region.getMinor());
}
});
This is what Im using right now, and its working fine. The problem is that since I used a null as the last value in the Region (in order to capture any store of that brand), the region returned by the onEnteredRegion method returns null, and Im unable to identify the specific store.
I thought of two possible solutions:
Saving the list of beacons return on the entering, and retrieving the store's id when the customer leaves. (This could be dangerous, if there are more than one beacon in range)
Or, monitoring a number of specific Regions using the store ids. (This would involve knowing all the stores Ids, so again not an ideal solution)
I was wandering if there was any way to get the actual Beacon that triggered the onExitedRegion method, or any other better solution.
Thanks!
You have two options:
Start ranging when you receive onEnteredRegion callback. From ranging you get back beacons around you so you can identify a store/brand.
Take a look at second parameter (beacon) in onEnteredRegion. According to docs:
beacons - List of beacons that triggered onEnteredRegion event. This list may not reflect all beacons around that are matching given region.
You can use this information to identify store/brand.
Related
All the questions are related to the demo project in android for pocketsphinx, given on the official site of CMUSphinx.
I don't understand what the method switchSearch() really does. The method is using KWS_SEARCH="wakeup" attribute, what is the use of this attribute? It doesn't appear in the grammar files (.gram). What is the purpose of this attribute? The method compares the searchName with KWS_SEARCH, I don't know why. The KWS_SEARCH it's also passed as a parameter to startListening() method on the recognizer object. Why?
I dont' understand how working with a timeout of 10000ms improves the result.
This is the switchSearch() method:
private void switchSearch(String searchName) {
recognizer.stop();
// If we are not spotting, start listening with timeout (10000 ms or 10 seconds).
if (searchName.equals(KWS_SEARCH))
recognizer.startListening(searchName);
else
recognizer.startListening(searchName, 10000);
String caption = getResources().getString(captions.get(searchName));
((TextView) findViewById(R.id.caption_text)).setText(caption);
}
From Pocketsphinx tutorial:
Developer can configure several “search” objects with different
grammars and language models and switch them in runtime to provide
interactive experience for the user.
There are different possible search modes:
keyword - efficiently looks for keyphrase and ignores other speech. allows to configure detection threshold.
grammar - recognizes speech according to JSGF grammar. Unlike keyphrase grammar search doesn't ignore words which are not in grammar
but tries to recognize them.
ngram/lm - recognizes natural speech with a language model.
allphone - recognizes phonemes with a phonetic language model. Each search has a name and can be referenced by a name, names are
application-specific. The function ps_set_search allows to activate
the search previously added by a name.
To add the search one needs to point to the grammar/language model
describing the search. The location of the grammar is specific to the
application. If only a simple recognition is required it is sufficient
to add a single search or just configure the required mode with
configuration options.
The exact design of a searches depends on your application. For
example, you might want to listen for activation keyword first and
once keyword is recognized switch to ngram search to recognize actual
command. Once you recognized the command you can switch to grammar
search to recognize the confirmation and then switch back to keyword
listening mode to wait for another command.
I don't understand what the method switchSearch() really does. The method is using KWS_SEARCH="wakeup" attribute, what is the use of this attribute?
"wakeup" is the search name of the keyword spotting search. It was added when recognizer was initialized. Name can be arbitrary, it just identifies the search.
The KWS_SEARCH it's also passed as a parameter to startListening() method on the recognizer object. Why?
startListening starts listening with the named search.
I dont' understand how working with a timeout of 10000ms improves the result.
It has nothing about result, it is just a user experience. When we spot for a word continuously, we do not need a timeout. When we recognize a command we wait for 10 seconds and then return back to spotting mode.
I'm using the beacon ranging methods to discover and use iBeacons. However, I have run into problem while trying to iterate through all the beacons that were found.
The beacon service returns a collection, which I can check the size of and see there are 3 beacons. However, not matter what I try I can reliably iterate through the beacons. I seem to go in a different random order of beacons every time, and some are frequently skipped over.
I have tried while(iBeacons.iterator().hasNext()) and that just froze my app. I have tried comparing the lastBeacon which I parsed to the current beacon selected and throwing it out, but this didnt work to get through all beacons.
I think that since the collection is being update asynchronously and my parsing takes far longer than a second new beacons have been added before I ever get a chance to process the old ones, and I seems to just randomly process one from the collection each time.
How can I get and parse each beacon each time?
The code is close -- it simply needs to construct an Iterator on a separate line like this:
Iterator<IBeacon> iterator = iBeacons.iterator();
while (iterator.hasNext())
The reason your the freezes has nothing to do with asynchronous updates by the library. (The list of iBeacons passed to the ranging callback is a copy of those seen in the last scan cycle and never gets changed.) The problem has to do with the way the iterator() method works in Java.
In the code above, the while(iBeacons.iterator().hasNext()) creates a new copy of Iterator every time inside the loop, and that iterator is always pointing at the first element in the iBeacons collection. So if there is ever at least one item in that collection when the loop starts, it will never finish, and the code will freeze.
You can demonstrate this with the following example:
public class IteratorTest{
public static void main(String []args){
java.util.Collection iBeacons = java.util.Arrays.asList("1", "2", "3");
System.out.println("This loop will not freeze");
java.util.Iterator iterator = iBeacons.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("This loop will freeze");
while(iBeacons.iterator().hasNext()) {
System.out.println(iBeacons.iterator().next());
}
// We will never get to here
}
}
Which produces the following (never ending) output:
This loop will not freeze
1
2
3
This loop will freeze
1
1
1
1
1
1
1
1
1
1
1
1
1
Is it just me or is the getCreatorId() method in Room not unique for automatch games?
I have some logic in my game that is based on a unique entity deciding things, such as which player belongs on which team. Each client waits to receive this information from the 'host' (which is the room creator in this case) before launching into and setting up the game.
#Override
public void onRoomConnected(int status, Room room) {
// Game Lobby is full
if (status != GamesClient.STATUS_OK) {
return;
}
this.room = room;
// Assign the players teams
if (room.getParticipantId(activity.gameHelperManager.gameHelper.getGamesClient().getCurrentPlayerId()).equals(room.getCreatorId())) {
// Some logic here
activity.androidManager.sendMessage(Data Sent Here);
activity.game.startGame(GameType.MULTIPLAYER);
}
}
On the other side of things:
#Override
public void onRealTimeMessageReceived(RealTimeMessage message) {
// Get Message from host about game specific properties is here
if (data.contains(Message Tag Here)) {
// Parse information
activity.game.startGame(GameType.MULTIPLAYER);
}
}
However, each client views itself as the host in the onRoomConnected() method during an auto-match type game.
Is there a solution to this or am I missing something fundamental?
Admittedly, our documentation is a bit misleading (I'm requesting a fix right away), but here's the explanation of what went through our heads when we designed this :-D
What automatching really does is connect different rooms created by different people, and making them into virtually one room with everybody in it. So different people in the room may have a different idea of who was the room's creator. So using the room's creator as a way to decide who goes first is generally not a good idea.
Using the participant ID directly isn't a good idea either (because someone with a lexicographically very high participant ID would find themselves going last on every single game they play).
Please see my answer to the following question for more ideas on how to decide who goes first:
How to decide who is the first player when user plays quick game?
I need to get the current value of the proximity sensor (rather than implementing a continuous listener). On some devices, the first reported value will be a default value (e.g. "FAR") that isn't necessarily accurate, and actual values will only start appearing after the second or third reading. At the moment, I've implemented a 1-second Handler and use the last reported value (after the second has elapsed) as the "true" value, but this solution seems crude (and slow). Is there a better approach that works on all 4.0+ devices? I could simply count up until I've received 3 readings, but on some devices (e.g. GNex), the first value will be correct, and the value will only change after that if there is actually a change in the sensor.
You can do what I did:
You probably have an if statement on the listener - one logic flow for near and one for far.
Instead of waiting on the handler - do this:
if(near) {
myHandler.removeCallbacks(yourRunnableForFar);
myHandler.postDelayed(yourRunnableForNear,100);
else {
myHandler.removeCallbacks(yourRunnableForNear);
myHandler.postDelayed(yourRunnableForFar,100);
}
Notice that the inaccurate first reading(s) will immediately be followed by an accurate one, so the last one "wins".
This code works well if you didn't register sensors other than proximity. If you have a flow of readings from other sensors, than use a static flag (such as the boolean near) to trigger the handler calls only on state change.
Elaboration:
yourRunnableForFar and yourRunnableForNear - are placeholders that implement Runnable to hold your app logic on what to do when the proximity sensor returns "near" (event.values[0] == 0) or "far" (not 0).
myHandler is just any Handler you might created, or declare one just for this with Handler myHandler = new Handler(Looper.getMainLooper());
You might want to acquire a proximity lock on near, and release it and clear the listener on far. But this is app logic that might be completely different from app to app.
I just start with IBeacon. There is one is issue specified in IBeacon Android, "If two apps register ranges with the same id, they clobber eachother". I did not get perfect idea about this.
If anybody knows about this then please help me.
You don't need to worry about this. In theory, if two apps were sharing the same instance of the Android iBeacon Library, and they both passed the same unique id when defining their Region objects, the second app would overwrite the Region of the first app.
Because there is no easy way to make two apps use the same service instance, this is not a practical concern, except for very advanced users. I put this in the documentation for the library mostly as a note to myself to fix this in the future.
Example (don't do this):
// App 1
Region region1 = new Region("myUniqueId", "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0", 1, 2);
iBeaconManager.startMonitoringBeaconsInRegion(region1);
// App 2 - the startMonitoring call will actually alter the region1 definition above
// because the two Region objects have the same "myUniqueId" identifier
Region region2 = new Region("myUniqueId", "5A4BCFCE-174E-4BAC-A814-092E77F6B7E5", 3, 4);
iBeaconManager.startMonitoringBeaconsInRegion(region2);