Eddystone beacons demo

Post on 19-Jan-2017

873 views 4 download

Transcript of Eddystone beacons demo

Eddystone Beacons DemoLecture on Eddystone, an open Bluetooth Smart Beacon format from Google

+Angelo Rüggeberg@s3xy4ngyc

agenda- Introductions to Beacons

- Introduction to Eddystone

- Coding Session

Introduction to Beacons

Image: Google

Context orexact Location

Location, Accuracy, Range, and alike

Image: Google…

Use Cases

Image: Estimote

Opportunities

Presence (e.g. sights)

Image: Google

Opportunities

Tracking and Securing

Image: Google

Opportunities

• Contextual fencing(aka Geo-fence)

• Contextual content(e.g. reader circle)

• …

Image: Bundesarchiv

Landscape

• AltBeacon• Apple‘s property: iBeacon™• Estimote• Gimbal™ • PayPal™ Beacon• yoints• …

• Bluetooth® SIG(Special Interest Group)

• Bluetooth® Smart Beacon • Eddystone™

• https://github.com/google/eddystone/tree/master/branding

Introduction to Eddystone

Eddystone™, what’s so special?Openness

• It is an open Bluetooth 4.0 protocol• While iBeacon™ is officially

supported by iOS devices only, Eddystone™ has official support for both iOS and Android

Packet types / frames

• Eddystone-UID (identifier)• Namespace as UUID• Instance (6 bytes), much like Major

and Minor

• Eddystone-URL• Eddystone-TLM (telemetry)

• battery voltage• temperature• number of packets since last reboot• beacon uptime since last reboot

HardwarePhones can become Smart Beacons themselves• TxEddystone-UID (Android Lollipop 5.0)

Almost all devices with BLE can become Smart Beacons themselves• BlueGiga BLED112 Dongle• Cambridge Silicon Radio CSR1010 (Beacon

Development Board)• Rfduino

• Linux (bluez)

• ARM mbed (Nordic nRF51-dongle, nRF51-DK)

• Node.js (node-eddystone-beacon using bleno)

• Arduino (BLEPeripheral), using Nordic Semiconductor's nRF8001 or nR51822

https://github.com/google/eddystone/tree/master/eddystone-uid/tools/txeddystone-uid

Some Bluetooth® Facts

• Bluetooth / BLEis a wireless protocol

• Bluetooth uses UHF radio waves in the ISM band from 2.4 to 2.485 GHz divided into channels with frequency hopping

• Signal strength is an indicator for proximity (RSSI, received signal strength indicator)

• BLE has reduced power consumption

• Bluetooth SIG predicts more than 90% of Bluetooth-enabled smartphones will support the low energy standard by 2018.

Coding a Simple BLE Scanner

BLE Permissions for an App

<!– Allow any Bluetooth communication --><uses-permission android:name="android.permission.BLUETOOTH"/>

<!– Allow device discovery --><uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

<uses-feature android:name="android.hardware.bluetooth_le" android:required="true“

/>

public class MainActivity extends AppCompatActivity {

// Declare Bluetooth adapter private BluetoothManager bluetoothManager; private BluetoothAdapter bluetoothAdapter;

public class MainActivity extends AppCompatActivity {

// Declare Bluetooth adapter private BluetoothManager bluetoothManager; private BluetoothAdapter bluetoothAdapter;

@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);

// Initialize Bluetooth adapter bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); bluetoothAdapter = bluetoothManager.getAdapter(); …

@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);

// Initialize Bluetooth adapter bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); bluetoothAdapter = bluetoothManager.getAdapter(); …

@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);

// Initialize Bluetooth adapter bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); bluetoothAdapter = bluetoothManager.getAdapter(); …

bluetoothAdapter.startLeScan(new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { Log.d(TAG, "Device-Adress: " + device.getAddress()); Log.d(TAG, "RSSI: " + rssi); }});

bluetoothAdapter.startLeScan(new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { Log.d(TAG, "Device-Adress: " + device.getAddress()); Log.d(TAG, "RSSI: " + rssi); }});

bluetoothAdapter.startLeScan(new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { Log.d(TAG, "Device-Adress: " + device.getAddress()); Log.d(TAG, "RSSI: " + rssi); }});

bluetoothAdapter.startLeScan(new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { Log.d(TAG, "Device-Adress: " + device.getAddress()); Log.d(TAG, "RSSI: " + rssi); }});

bluetoothAdapter.startLeScan(new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { if(device.getAddress().equals("C1:4F:F1:FF:9B:90")) { Log.d(TAG, "Device-Adress: " + device.getAddress()); Log.d(TAG, "RSSI: " + rssi); } }});

bluetoothAdapter.startLeScan(new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { if(device.getAddress().equals("C1:4F:F1:FF:9B:90")) { Log.d(TAG, "Device-Adress: " + device.getAddress()); Log.d(TAG, "RSSI: " + rssi); } }});

Move away from deprecated Methods

bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();

bluetoothLeScanner.startScan(new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); }

@Override public void onBatchScanResults(List<ScanResult> results) { super.onBatchScanResults(results); }});

bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();

bluetoothLeScanner.startScan(new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); }

@Override public void onBatchScanResults(List<ScanResult> results) { super.onBatchScanResults(results); }});

bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();

bluetoothLeScanner.startScan(new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); }

@Override public void onBatchScanResults(List<ScanResult> results) { super.onBatchScanResults(results); }});

bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();

bluetoothLeScanner.startScan(new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); }

@Override public void onBatchScanResults(List<ScanResult> results) { super.onBatchScanResults(results); }});

bluetoothLeScanner.startScan(filters, settings, new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); }});

bluetoothLeScanner.startScan(filters, settings, new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); }});

ScanSettings settings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .build();

List<ScanFilter> filters = new ArrayList<>();

ScanFilter filter = new ScanFilter.Builder() .setDeviceAddress("C1:4F:F1:FF:9B:90") .build();

filters.add(filter);

ScanSettings settings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .build();

List<ScanFilter> filters = new ArrayList<>();

ScanFilter filter = new ScanFilter.Builder() .setDeviceAddress("C1:4F:F1:FF:9B:90") .build();

filters.add(filter);

ScanSettings settings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .build();

List<ScanFilter> filters = new ArrayList<>();

ScanFilter filter = new ScanFilter.Builder() .setDeviceAddress("C1:4F:F1:FF:9B:90") .build();

filters.add(filter);

ScanSettings settings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .build();

List<ScanFilter> filters = new ArrayList<>();

ScanFilter filter = new ScanFilter.Builder() .setDeviceAddress("C1:4F:F1:FF:9B:90") .build();

filters.add(filter);

ScanSettings settings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .build();

List<ScanFilter> filters = new ArrayList<>();

ScanFilter filter = new ScanFilter.Builder() .setDeviceAddress("C1:4F:F1:FF:9B:90") .build();

filters.add(filter);

Coding Proximity and Presence

There is only one packet format for BLE which

Payload consists of 2 Bytes Header, 6 Bytes Mac Address and up to 31 Bytes data.

Image: Google

Fixed: 02 01 06 03 03 aa fe

Length: 15

Fixed: 16 aa fe

Frame Type: 00

TX Power: ed

Namespace: ed d1 eb ea c0 4e 5d ef a0 17

Instance: c5 61 2a 8c c2 53

... 04 09

... 45 53 54 03 03

Bat. Service: 0f 18 0e

... 16 0a 18

Mac: 53 c2 8c 2a 61 c5

... 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Fixed: 02 01 06 03 03 aa fe

Length: 11

Fixed: 16 aa fe

Frame Type: 20

Version: 00

Volt: 0c 06

Temo: 13 00

Adv. Count: 00 0f 70 77

Sec. Count: 00 14 4e 70

... 04 09

... 45 53 54 03 03

Bat. Service: 0f 18 0e

... 16 0a 18

Mac: 53 c2 8c 2a 61 c5

... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

// The Eddystone Service UUID, 0xFEAA. private static final ParcelUuid EDDYSTONE_SERVICE_UUID = ParcelUuid.fromString("0000FEAA-0000-1000-8000-00805F9B34FB");

// Eddystone frame types private static final byte TYPE_UID = 0x00; private static final byte TYPE_URL = 0x10; private static final byte TYPE_TLM = 0x20;

// The Eddystone Service UUID, 0xFEAA. private static final ParcelUuid EDDYSTONE_SERVICE_UUID = ParcelUuid.fromString("0000FEAA-0000-1000-8000-00805F9B34FB");

// Eddystone frame types private static final byte TYPE_UID = 0x00; private static final byte TYPE_URL = 0x10; private static final byte TYPE_TLM = 0x20;

// The Eddystone Service UUID, 0xFEAA. private static final ParcelUuid EDDYSTONE_SERVICE_UUID = ParcelUuid.fromString("0000FEAA-0000-1000-8000-00805F9B34FB");

// Eddystone frame types private static final byte TYPE_UID = 0x00; private static final byte TYPE_URL = 0x10; private static final byte TYPE_TLM = 0x20;

// The Eddystone Service UUID, 0xFEAA. private static final ParcelUuid EDDYSTONE_SERVICE_UUID = ParcelUuid.fromString("0000FEAA-0000-1000-8000-00805F9B34FB");

// Eddystone frame types private static final byte TYPE_UID = 0x00; private static final byte TYPE_URL = 0x10; private static final byte TYPE_TLM = 0x20;

// The Eddystone Service UUID, 0xFEAA. private static final ParcelUuid EDDYSTONE_SERVICE_UUID = ParcelUuid.fromString("0000FEAA-0000-1000-8000-00805F9B34FB");

// Eddystone frame types private static final byte TYPE_UID = 0x00; private static final byte TYPE_URL = 0x10; private static final byte TYPE_TLM = 0x20;

••

Image: Estimote

bluetoothLeScanner.startScan(filters, settings, new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); byte[] data = result.getScanRecord().getServiceData(EDDYSTONE_SERVICE_UUID);

byte frameType = data[0]; if (frameType != TYPE_TLM) { return; } // Beacon temperature

double temp = new BigInteger(Arrays.copyOfRange(data, 4, 6)).intValue() / 256.0;

Log.d(TAG, String.format("%.2f°C", temp)); }});

bluetoothLeScanner.startScan(filters, settings, new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); byte[] data = result.getScanRecord().getServiceData(EDDYSTONE_SERVICE_UUID);

byte frameType = data[0]; if (frameType != TYPE_TLM) { return; } // Beacon temperature

double temp = new BigInteger(Arrays.copyOfRange(data, 4, 6)).intValue() / 256.0;

Log.d(TAG, String.format("%.2f°C", temp)); }});

bluetoothLeScanner.startScan(filters, settings, new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); byte[] data = result.getScanRecord().getServiceData(EDDYSTONE_SERVICE_UUID);

byte frameType = data[0]; if (frameType != TYPE_TLM) { return; } // Beacon temperature

double temp = new BigInteger(Arrays.copyOfRange(data, 4, 6)).intValue() / 256.0;

Log.d(TAG, String.format("%.2f°C", temp)); }});

bluetoothLeScanner.startScan(filters, settings, new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); byte[] data = result.getScanRecord().getServiceData(EDDYSTONE_SERVICE_UUID);

byte frameType = data[0]; if (frameType != TYPE_TLM) { return; } // Beacon temperature

double temp = new BigInteger(Arrays.copyOfRange(data, 4, 6)).intValue() / 256.0;

Log.d(TAG, String.format("%.2f°C", temp)); }});

Fixed: 02 01 06 03 03 aa fe

Length: 11

Fixed: 16 aa fe

Frame Type: 20

Version: 00

Volt: 0c 06

Temo: 13 00

Adv. Count: 00 0f 70 77

Sec. Count: 00 14 4e 70

... 04 09

... 45 53 54 03 03

Bat. Service: 0f 18 0e

... 16 0a 18

Mac: 53 c2 8c 2a 61 c5

... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

bluetoothLeScanner.startScan(filters, settings, new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); byte[] data = result.getScanRecord().getServiceData(EDDYSTONE_SERVICE_UUID);

byte frameType = data[0]; if (frameType != TYPE_TLM) { return; } // Beacon temperature

double temp = new BigInteger(Arrays.copyOfRange(data, 4, 6)).intValue() / 256.0;

Log.d(TAG, String.format("%.2f°C", temp)); }});

bluetoothLeScanner.startScan(filters, settings, new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); byte[] data = result.getScanRecord().getServiceData(EDDYSTONE_SERVICE_UUID);

byte frameType = data[0]; if (frameType != TYPE_TLM) { return; } // Beacon temperature

double temp = new BigInteger(Arrays.copyOfRange(data, 4, 6)).intValue() / 256.0;

Log.d(TAG, String.format("%.2f°C", temp)); }});

bluetoothLeScanner.startScan(filters, settings, new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); byte[] data = result.getScanRecord().getServiceData(EDDYSTONE_SERVICE_UUID);

byte frameType = data[0]; if (frameType != TYPE_TLM) { return; } // Beacon temperature

double temp = new BigInteger(Arrays.copyOfRange(data, 4, 6)).intValue() / 256.0;

Log.d(TAG, String.format("%.2f°C", temp)); }});

Outlook and helpers

, etc.http://on.google.com/hub/

Image: https://commons.wikimedia.org/wiki/File:Zinkh%C3%BCtter_Hof_Messing_Werkzeuge.jpg