I am trying to write an android application to interface with iBeacons, but I need to find the start of the UUID / major / minor characteristics in the byte array. Through look at a couple of resources including this question, it seems like ALL iBeacons transmit some pattern in the byte array that is the same that identifies them as iBeacons.
I asked another question recently and got a useful answer, link here but 1) I haven't been able to test it's functionality (waiting on my device) and 2) I want to know how it is working.
So my questions: What is that pattern? Can I find it just by searching that array for the pattern? And is the UUID / Major / Minor always a predefined number of spots in the array from that identifying pattern?
Thanks!
So after looking around on a few different sites, I have found that 3 people list their patterns as
02 01 06 1A FF 4C 00 02 15
or
02 01 1A 1A FF 4C 00 02 15
which isn't super helpful, since the 4C 00 appears to just be the Apple identifier, which I'm assuming could switch based on the manufacturer (Estimote, GE, Apple, whatever). However, it appears that the
02 15
is static, so I'm using that. My solution for finding it basically is just searching the byte array that I get for the first occurrence of that sequence of 2 bytes, and starting right after that I grab the next 16 as the UUID, the next 2 after that as the Major, and the next 2 after that as the Minor. So to clarify with code:
//adPacket is an array I created to represent an iBeacon ad for testing
byte[] adPacket = {(byte) 0xd6, (byte) 0xbe, (byte) 0x89, (byte) 0x8e, 0x40, 0x24, 0x05, (byte) 0xa2,
0x17, 0x6e, 0x3d, 0x71, 0x02, 0x01, 0x06, 0x1A, (byte) 0xFF, 0x4C, 0x00, 0x02, 0x15, (byte) 0xe2,
(byte) 0xc5, 0x6d, (byte) 0xb5, (byte) 0xdf, (byte) 0xfb, 0x48, (byte) 0xd2, (byte) 0xb0, 0x60, (byte) 0xd0,
(byte) 0xf5, (byte) 0xa7, 0x10, (byte) 0x96, (byte) 0xe0, 0x00, 0x00, 0x00, 0x00, (byte) 0xc5, 0x52, (byte) 0xab, (byte) 0x8d, 0x38, (byte) 0xa5};
byte[] pattern = {0x02, 0x15};
int startIndex = findAdPacketEnd(adPacket, pattern) + 1;
if(startIndex == 0){ System.out.println("Pattern not found"); return;}
int endIndex = startIndex + 21;
ArrayList<Byte> tempArray = new ArrayList<Byte>();
for(int i = startIndex; i<endIndex; i++){
tempArray.add(adPacket[i]);
}
byte[] proxUUID = new byte[16];
for(int i = 0; i<16; i++){
proxUUID[i] = tempArray.get(i);
}
byte[] major = new byte[2];
major[0] = tempArray.get(16);
major[1] = tempArray.get(17);
byte[] minor = new byte[2];
minor[0] = tempArray.get(18);
minor[1] = tempArray.get(19);
...
where my findAdPacketEnd function is (not the most efficient but it works):
private static int findAdPacketEnd(byte[] adPacket, byte[] pattern){
//return -1 if pattern is too long
if(adPacket.length < pattern.length)
return -1;
//iterate over adPacket
for(int i = 0; i<adPacket.length - pattern.length; i++){
System.out.println("Searching Ad Packet");
//iterate over pattern
for(int j = 0; j<pattern.length; j++){
//compare wherever you are in the adpacket to the pattern, break if it doesn't match
if(adPacket[i+j] != pattern[j])
break;
// if you get to the end of the pattern and there wasn't a mismatch, return the index
if(j == pattern.length-1)
return i+pattern.length-1;
}
}
//pattern not found
return -1;
}