Beacon一開始制定的封包格式如下圖:
在接收到藍芽封包後可以根據以上格是進行解析,最終得到個欄位的資料。
以下使用Java實作封包解析並將其封裝成物件,程式碼中的 package_parser 為專門解析 beacon 封包之函數。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
public class Beacon { private String prefix; private String uuid; private int major; private int minor; private int tx_power; private String macAddress; private int rssi; static { hexArray = "0123456789ABCDEF".toCharArray(); } public Beacon(String uuid,int major,int minor,int txPower,int rssi){ this.uuid = uuid; this.major = major; this.minor = minor; this.tx_power = txPower; this.rssi = rssi; } public Beacon(String uuid,int major,int minor,int txPower,int rssi,String mac){ this.uuid = uuid; this.major = major; this.minor = minor; this.tx_power = txPower; this.rssi = rssi; this.macAddress = mac; } public Beacon(byte[] package_raw, BluetoothDevice device,int rssi) throws BeaconFormateNotFoundException { this.rssi = rssi; this.macAddress = device.getAddress(); package_parser(package_raw); } private void package_parser(byte[] package_raw) throws BeaconFormateNotFoundException { int startByte = 2; boolean patternFound = false; // 尋找ibeacon // 先依序尋找第2到第8陣列的元素 while (startByte <= 5) { // Identifies an iBeacon if (((int) package_raw[startByte + 2] & 0xff) == 0x02 && // Identifies correct data length ((int) package_raw[startByte + 3] & 0xff) == 0x15) { patternFound = true; break; } startByte++; } if (patternFound) { byte[] uuidBytes = new byte[16]; // 來源、起始位置 System.arraycopy(package_raw, startByte + 4, uuidBytes, 0, 16); String hexString = Beacon.bytesToHex(uuidBytes); // UUID this.uuid = hexString.substring(0, 8) + "-" + hexString.substring(8, 12) + "-" + hexString.substring(12, 16) + "-" + hexString.substring(16, 20) + "-" + hexString.substring(20, 32); // Major this.major = (package_raw[startByte + 20] & 0xff) * 0x100 + (package_raw[startByte + 21] & 0xff); // Minor this.minor = (package_raw[startByte + 22] & 0xff) * 0x100 + (package_raw[startByte + 23] & 0xff); // txPower this.tx_power = (package_raw[startByte + 24]); }else { throw new BeaconFormateNotFoundException("patternFound"); } } private final static char[] hexArray; private static String bytesToHex(byte[] bytes) { char[] hexChars = new char[bytes.length * 2]; for (int j = 0; j < bytes.length; j++) { int v = bytes[j] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); } private static double calculateAccuracy(int txPower, double rssi) { if (rssi == 0) return -1.0; double ratio = rssi * 1.0 / txPower; if (ratio < 1.0) return Math.pow(ratio, 10); else { double accuracy = (0.89976) * Math.pow(ratio, 7.7095) + 0.111; return accuracy; } } public double distance(){ return calculateAccuracy(this.tx_power,this.rssi); } public String getUuid() { return uuid; } public int getMajor() { return major; } public int getMinor() { return minor; } public String getMacAddress() { return macAddress; } public int getRssi(){ return rssi; } public int getTxPower(){ return tx_power; } public int getX() { return this.major; } public int getY() { return this.minor; } public static List<Beacon> getSamples(){ List<Beacon> list = new ArrayList<>(); Beacon b1 = new Beacon("00910-412f-4124-1245",5,2,-35,12); list.add(b1); Beacon b2 = new Beacon("00910-412f-4124-1245",1,5,-45,12); list.add(b2); Beacon b3 = new Beacon("00910-412f-4124-1245",8,6,-25,12); list.add(b3); return list; } } |
關於如何使用,可以參考 Android Ble - 掃描beacon裝置 該文章有接收藍芽封包並進行解析完整說明,而範例專案則可點此 連結 參考
文章標籤
全站熱搜