Skip to content

Commit

Permalink
quick and dirty changes to get interleaved matching working
Browse files Browse the repository at this point in the history
  • Loading branch information
davidgyoung committed Mar 20, 2015
1 parent 0e5330e commit 4dd1d97
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 40 deletions.
13 changes: 13 additions & 0 deletions src/main/java/org/altbeacon/beacon/Beacon.java
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ protected Beacon(Parcel in) {
mDataFields.add(in.readLong());
}
int extraDataSize = in.readInt();
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "reading "+extraDataSize+" extra data fields from parcel");
}
this.mExtraDataFields = new ArrayList<Long>(extraDataSize);
for (int i = 0; i < extraDataSize; i++) {
mExtraDataFields.add(in.readLong());
Expand All @@ -208,9 +211,16 @@ protected Beacon(Beacon otherBeacon) {
super();
mIdentifiers = new ArrayList<Identifier>(otherBeacon.mIdentifiers.size());
mDataFields = new ArrayList<Long>(otherBeacon.mDataFields.size());
mExtraDataFields = new ArrayList<Long>(otherBeacon.mExtraDataFields.size());
for (int i = 0; i < otherBeacon.mIdentifiers.size(); i++) {
mIdentifiers.add(otherBeacon.mIdentifiers.get(i));
}
for (int i = 0; i < otherBeacon.mDataFields.size(); i++) {
mDataFields.add(otherBeacon.mDataFields.get(i));
}
for (int i = 0; i < otherBeacon.mExtraDataFields.size(); i++) {
mExtraDataFields.add(otherBeacon.mExtraDataFields.get(i));
}
this.mDistance = otherBeacon.mDistance;
this.mRunningAverageRssi = otherBeacon.mRunningAverageRssi;
this.mRssi = otherBeacon.mRssi;
Expand Down Expand Up @@ -476,6 +486,9 @@ public void writeToParcel(Parcel out, int flags) {
for (Long dataField: mDataFields) {
out.writeLong(dataField);
}
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "writing "+mExtraDataFields.size()+" extra data fields to parcel");
}
out.writeInt(mExtraDataFields.size());
for (Long dataField: mExtraDataFields) {
out.writeLong(dataField);
Expand Down
169 changes: 130 additions & 39 deletions src/main/java/org/altbeacon/beacon/service/BeaconService.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public class BeaconService extends Service {

private Map<Region, RangeState> rangedRegionState = new HashMap<Region, RangeState>();
private Map<Region, MonitorState> monitoredRegionState = new HashMap<Region, MonitorState>();
private HashSet<Beacon> trackedBeacons;
private HashMap<String,Beacon> mTrackedBeacons;
int trackedBeaconsPacketCount;
private Handler handler = new Handler();
private int bindCount = 0;
Expand Down Expand Up @@ -364,66 +364,157 @@ private void processExpiredMonitors() {
}

private void processBeaconFromScan(Beacon beacon) {
if (trackedBeacons == null){
trackedBeacons = new HashSet<>();
if (mTrackedBeacons == null){
mTrackedBeacons = new HashMap<String,Beacon>();
}
if (Stats.getInstance().isEnabled()) {
Stats.getInstance().log(beacon);
}

/*
// Check to see if this is an extra beacon frame that needs to be folded in to an existing beacon
// TODO: add a flag to beacon... don't use the size of the identifiers to determine this
if (beacon.getIdentifiers().size() == 0) {
// TODO: make a more efficient way of finding tracked beacons by mac address
for (Beacon trackedBeacon: trackedBeacons) {
for (Beacon trackedBeacon: mTrackedBeacons.values()) {
if (trackedBeacon.getBluetoothAddress().equals(beacon.getBluetoothAddress())) {
// the data fields from this beacon need to be moved to the other beacon.
Beacon.Builder builder = new Beacon.Builder();
builder.copyBeaconFields(trackedBeacon);
builder.setExtraDataFields(beacon.getDataFields());
Beacon mergedBeacon = builder.build();
Log.d(TAG, "Adding extra data fields: "+mergedBeacon.getExtraDataFields().size()+" from beacon with "+beacon.getDataFields()+" data fields ");
trackedBeacons.add(mergedBeacon);
Beacon mergedBeacon = mergeBeacon(trackedBeacon, beacon);
mTrackedBeacons.put(mergedBeacon.toString(),mergedBeacon);
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "Adding extra data fields: "+mergedBeacon.getExtraDataFields().size()+" from beacon with "+beacon.getDataFields()+" data fields ");
LogManager.d(TAG, "Adding extra data fields, keying by "+mergedBeacon.toString()+" and "+trackedBeacon.toString());
LogManager.d(TAG, "stored value has extra data field count"+mTrackedBeacons.get(mergedBeacon.toString()).getExtraDataFields().size());
}
}
}
// TODO: don't return in middle of method
return;
}
*/
synchronized(mTrackedBeacons) {
trackedBeaconsPacketCount++;
Beacon newMergedBeacon = beacon;
if (mTrackedBeacons.get(beacon) != null) {
LogManager.d(TAG,
"BEM: beacon detected multiple times in scan cycle : %s", beacon.toString());
newMergedBeacon = mergeBeacon(mTrackedBeacons.get(beacon.toString()), beacon);
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM: after merge extra data field size is " + newMergedBeacon.getExtraDataFields().size());
}

} else {
if (beacon.getIdentifiers().size() == 0) {
boolean match = false;
// TODO: make a more efficient way of finding tracked beacons by mac address

for (Beacon trackedBeacon : mTrackedBeacons.values()) {
if (trackedBeacon.getServiceUuid() != 0 &&
trackedBeacon.getServiceUuid() == beacon.getServiceUuid() &&
trackedBeacon.getBluetoothAddress().equals(beacon.getBluetoothAddress())) {
LogManager.d(TAG, "BEM: merging beacon with matching mac and zero identifiers");
newMergedBeacon = mergeBeacon(trackedBeacon, beacon);
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM: after merge extra data field size is " + newMergedBeacon.getExtraDataFields().size());
}
match = true;
}
}
if (!match) {
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM: ignoring beacon object with no identifiers");
}
return;
}
}
}
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM: past short cirucuit return " + newMergedBeacon.getExtraDataFields().size());
}

trackedBeaconsPacketCount++;
if (trackedBeacons.contains(beacon)) {

mTrackedBeacons.put(beacon.toString(), newMergedBeacon);
LogManager.d(TAG,
"beacon detected multiple times in scan cycle : %s", beacon.toString());
"beacon detected : %s", beacon.toString());

List<Region> matchedRegions = null;
synchronized (monitoredRegionState) {
matchedRegions = matchingRegions(newMergedBeacon,
monitoredRegionState.keySet());
}
Iterator<Region> matchedRegionIterator = matchedRegions.iterator();
while (matchedRegionIterator.hasNext()) {
Region region = matchedRegionIterator.next();
MonitorState state = monitoredRegionState.get(region);
if (state.markInside()) {
state.getCallback().call(BeaconService.this, "monitoringData",
new MonitoringData(state.isInside(), region));
}
}


LogManager.d(TAG, "looking for ranging region matches for this beacon");
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM: about to do ranging matches extraData size " + newMergedBeacon.getExtraDataFields().size());
LogManager.d(TAG, "BEM: about to do ranging matches identifiers size " + newMergedBeacon.getIdentifiers().size());
}
synchronized (rangedRegionState) {
matchedRegions = matchingRegions(newMergedBeacon, rangedRegionState.keySet());
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM: about to do ranging matches 2 " + newMergedBeacon.getExtraDataFields().size());
LogManager.d(TAG, "BEM: matched ranging regions " + matchedRegions.size());
}


matchedRegionIterator = matchedRegions.iterator();
while (matchedRegionIterator.hasNext()) {
Region region = matchedRegionIterator.next();
LogManager.d(TAG, "matches ranging region: %s", region);
RangeState rangeState = rangedRegionState.get(region);
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM: adding beacon to rangeState with extra data fields " + newMergedBeacon.getExtraDataFields().size());
}
rangeState.addBeacon(newMergedBeacon);
}
}
}
trackedBeacons.add(beacon);
LogManager.d(TAG,
"beacon detected : %s", beacon.toString());

List<Region> matchedRegions = null;
synchronized(monitoredRegionState) {
matchedRegions = matchingRegions(beacon,
monitoredRegionState.keySet());

}

private Beacon mergeBeacon(Beacon oldBeacon, Beacon newBeacon) {
// the data fields from this beacon need to be moved to the other beacon.
// TODO: key this off something else besides identifier size
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM: merging extra fields if needed");
}
Iterator<Region> matchedRegionIterator = matchedRegions.iterator();
while (matchedRegionIterator.hasNext()) {
Region region = matchedRegionIterator.next();
MonitorState state = monitoredRegionState.get(region);
if (state.markInside()) {
state.getCallback().call(BeaconService.this, "monitoringData",
new MonitoringData(state.isInside(), region));

Beacon.Builder builder = new Beacon.Builder();
if (newBeacon.getIdentifiers().size() == 0) {
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM: we have a beacon detected with zero identifiers");
}
}

LogManager.d(TAG, "looking for ranging region matches for this beacon");
synchronized (rangedRegionState) {
matchedRegions = matchingRegions(beacon, rangedRegionState.keySet());
matchedRegionIterator = matchedRegions.iterator();
while (matchedRegionIterator.hasNext()) {
Region region = matchedRegionIterator.next();
LogManager.d(TAG, "matches ranging region: %s", region);
RangeState rangeState = rangedRegionState.get(region);
rangeState.addBeacon(beacon);
builder.copyBeaconFields(oldBeacon);
if (newBeacon.getDataFields().size() != 0) {
builder.setExtraDataFields(newBeacon.getDataFields());
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM: Adding extra data fields: " + newBeacon.getDataFields().size() + " from beacon with " + newBeacon.getDataFields() + " data fields ");
}
}

}
else {
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM: we have a beacon detected with identifiers");
}
builder.copyBeaconFields(newBeacon);
if (oldBeacon.getExtraDataFields().size() != 0) {
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM: Copying extra data fields from oldBeacon");
}
builder.setExtraDataFields(oldBeacon.getDataFields());
}
}
return builder.build();
}


Expand Down
27 changes: 26 additions & 1 deletion src/main/java/org/altbeacon/beacon/service/RangeState.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,28 @@ public void addBeacon(Beacon beacon) {
if (mRangedBeacons.containsKey(beacon)) {
RangedBeacon rangedBeacon = mRangedBeacons.get(beacon);
LogManager.d(TAG, "adding %s to existing range for: %s", beacon, rangedBeacon);
rangedBeacon.updateBeacon(beacon);

if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM updated 1 ranged beacon, extraDataField count changing to : "+beacon.getExtraDataFields().size()+" from: "+rangedBeacon.getBeacon().getExtraDataFields().size());
}
if (beacon.getExtraDataFields().size() == 0 && rangedBeacon.getBeacon().getExtraDataFields().size() > 0) {
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM refusing to downgrade extra data fields");
}
}
else {
rangedBeacon.updateBeacon(beacon);
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM updated 2 ranged beacon, extraDataField count: "+rangedBeacon.getBeacon().getExtraDataFields().size());
}
}
}
else {
LogManager.d(TAG, "adding %s to new rangedBeacon", beacon);
mRangedBeacons.put(beacon, new RangedBeacon(beacon));
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM creating ranged beacon, extraDataField count: "+beacon.getExtraDataFields().size());
}
}
}

Expand All @@ -68,11 +85,19 @@ public synchronized Collection<Beacon> finalizeBeacons() {
synchronized (mRangedBeacons) {
for (Beacon beacon : mRangedBeacons.keySet()) {
RangedBeacon rangedBeacon = mRangedBeacons.get(beacon);
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM committing ranged beacons 1, extraDataField count: "+rangedBeacon.getBeacon().getExtraDataFields().size());
}

if (rangedBeacon.isTracked()) {
rangedBeacon.commitMeasurements(); // calculates accuracy
if (!rangedBeacon.noMeasurementsAvailable()) {
finalizedBeacons.add(rangedBeacon.getBeacon());
}
if (LogManager.isVerboseLoggingEnabled()) {
LogManager.d(TAG, "BEM committing ranged beacons 2, extraDataField count: "+rangedBeacon.getBeacon().getExtraDataFields().size());
}

}
// If we still have useful measurements, keep it around but mark it as not
// tracked anymore so we don't pass it on as visible unless it is seen again
Expand Down

0 comments on commit 4dd1d97

Please sign in to comment.