I have 4 nearables I am testing the following code against;
I am coding in Android Studio.
I am using the Estimote android phone app for configuring the devices
Dog - my account, set as Ibeacon, my UUID
Bag - my account, set as nearable, not my UUID
Bed - not my account, set as nearable, my UUID
Car - not my account, set as nearable, my UUID
Questions
-
How do you turn a nearable in to an Ibeacon.
They appear to be mutually exclusive - ie when you listen you either receive Ibeacon data or nearable data.
I managed to turn Dog in to an Ibeacon but I have no idea how - I poked and prodded in both the Estimote Phone App and the web page facility and about an hour later it changed in to an iBeacon and was detected as a beacon, not a nearable. -
The documentation appears to imply that a nearable sends both Ibeacon packets and nearable packets. However, in code, when you detect a nearable object, the nearable class does not give UUID, major, minor - it appears that if you want to see these you have to turn the nearable in to an Ibeacon and get these values off a beacon object.
-
All the nearables turn up when scanning - whether or not they belong to my account or my UUID.
Using a secure region makes no difference - region only appears to filter beacons, not nearables.
How am I going to prevent my user’s app being bombarded with nearable hits when they walk through a shopping centre - this will impose a lot of additional traffic over our HTTP link - with foreign nearable ids having to be rejected at the far back office end. -
For beacons I can just set a single UUID in my phone app code and know that I will be filtering to just my set of beacons and can then do some fairly easy work just using major and minor numbers - these are quite small, easy to handle number that can be easily typed in to a reference table somewhere in the back end and interpreted - eg Toowoomba Office, or Vehicle 225.
It looks like for nearables I will have to type horrifically long id numbers in to the same reference table.
Or have I got the wrong end of the stick ? -
If I want to use secure UUID then this appears to have some cloud component involved. Does this mean that the phone app is going to need 3G/4G access. In lot of cases we will be tracking who has entered a vehicle using their phone and a sticker in the vehicle - these vehicles are working in remote areas without internet access - does this invalidate secure UUID ?
Here is my code - I have written it as a service that gets started from a timer with a wake lock.
So far, for the last two weeks, this have been giving me rock solid ibeacon and nearable sensing at almost exact 10 minute intervals:
public class BeaconRanging extends IntentService {
private BeaconManager beaconManager;
private Region region;
private AceLogging aceLogging;
private static final String subTAG = “BeaconRangingService”;
private static Context thisContext;
private int intCallbacksBeacons = 0;
private int intCallbacksNearables = 0;
private String scanId;
public BeaconRanging()
{
super("BeaconRanging");
aceLogging = new AceLogging();
thisContext = this;
}
@Override
protected void onHandleIntent(Intent intent)
{
intCallbacksBeacons = 0;
intCallbacksNearables = 0;
EstimoteSDK.initialize(getApplicationContext(), "<my id>", "<my hash>");
StartBeaconRanging();
}
private void StartBeaconRanging()
{
GoTrial mApplication = (GoTrial)getApplicationContext();
beaconManager = mApplication.getBeaconManager();
beaconManager.setBackgroundScanPeriod(10000, 0);
beaconManager.setForegroundScanPeriod(10000, 0);
region = new SecureRegion("ranged region", UUID.fromString("<my uuid>"), null, null);
beaconManager.setRangingListener
(
new BeaconManager.RangingListener() {
@Override
public void onBeaconsDiscovered(Region region, List<Beacon> beaconlist) {
//if (!beaconlist.isEmpty())
if (true) {
List<String> beaconInfo = formatBeaconInfo(beaconlist);
aceLogging.LogEvent(thisContext, "I", "Beacons: " + GetTimeStamp() + " " + beaconInfo.toString(), subTAG);
intCallbacksBeacons++;
if (intCallbacksBeacons >= 1) {
beaconManager.stopRanging(region);
if (intCallbacksNearables >= 1) {
beaconManager.disconnect();
return;
}
}
}
}
}
);
beaconManager.setNearableListener
(new BeaconManager.NearableListener() {
@Override
public void onNearablesDiscovered(List<Nearable> nearablelist) {
//if (!nearablelist.isEmpty())
if (true) {
List<String> nearableInfo = formatNearableInfo(nearablelist);
aceLogging.LogEvent(thisContext, "I", "Nearables: " + GetTimeStamp() + " " + nearableInfo.toString(), subTAG);
intCallbacksNearables++;
if (intCallbacksNearables >= 1)
{
beaconManager.stopNearableDiscovery(scanId);
if (intCallbacksBeacons >= 1) {
beaconManager.disconnect();
return;
}
}
}
}
}
);
beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
@Override
public void onServiceReady()
{
beaconManager.startRanging(region);
scanId = beaconManager.startNearableDiscovery();
}
});
}
private List<String> formatBeaconInfo(List<Beacon> beaconList) {
List<String> beaconInfo = new ArrayList<String>();
String strOneLine = "";
if (beaconList.isEmpty()) {
strOneLine = "no beacons found";
beaconInfo.add(0,strOneLine);
}
else
{
for (int i = 0; i < beaconList.size(); i++) {
Beacon beacon = beaconList.get(i);
strOneLine = String.format("%d:%d:%d", beacon.getMajor(), beacon.getMinor(), beacon.getRssi());
beaconInfo.add(i, strOneLine);
}
}
return beaconInfo;
}
private List<String> formatNearableInfo(List<Nearable> nearableList) {
List<String> nearableInfo = new ArrayList<String>();
String strOneLine = "";
if (nearableList.isEmpty()) {
strOneLine = "no nearables found";
nearableInfo.add(0,strOneLine);
}
else
{
for (int i = 0; i < nearableList.size(); i++) {
Nearable nearable = nearableList.get(i);
strOneLine = nearable.identifier + " " + String.format("%d", nearable.rssi);
nearableInfo.add(i, strOneLine);
}
}
return nearableInfo;
}
public String GetTimeStamp()
{
String str_time = "";
final Calendar c = Calendar.getInstance();
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);
int seconds = c.get(Calendar.SECOND);
str_time = String.format("%02d",hour) + ":" + String.format("%02d", minute)+ ":" + String.format("%02d",seconds);
return str_time;
}
}