Eddystone Beacons - Physical Web - Giving a URL to All Objects
- 2. “Operating System for Digital Commerce.”
Dan Schulman – USA Today - May 21th, 2015
@braintree_dev / @jeffprestesPre-presentation slide
- 19. @braintree_dev / @jeffprestes#eddystone
var Beacon = require('./node_modules/eddystone-beacon/lib/beacon');
beacon = new Beacon();
var options = {
txPowerLevel: -22, //override TX Power Level, default value is -21
tlmCount: 2, // 2 TLM frames
tlmPeriod: 10 // every 10 advertisements
};
beacon.advertiseUrl('http://www.paypal.com', [options]);
- 21. @braintree_dev / @jeffprestes#eddystone
MainActivity.java
protected void onResume() {
super.onResume();
BluetoothManager btManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
BluetoothAdapter btAdapter = btManager != null ? btManager.getAdapter() : null;
if (btAdapter == null) {
finish();
return;
}
if (checkIfUserHasOptedIn()) {
ensureBluetoothIsEnabled(btAdapter);
showNearbyBeaconsFragment();
} else {
// Show the oob activity
// Webview to: https://google.github.io/physical-web/mobile/android/getting-started.html
Intent intent = new Intent(this, OobActivity.class);
startActivity(intent);
}
}
- 22. @braintree_dev / @jeffprestes#eddystone
NearbyBeaconsFragment.java
public void onResume() {
super.onResume();
getActivity().getActionBar().setTitle(R.string.title_nearby_beacons);
getActivity().getActionBar().setDisplayHomeAsUpEnabled(false);
getListView().setVisibility(View.INVISIBLE);
mDiscoveryServiceConnection.connect(true);
}
public synchronized void connect(boolean requestCachedPwos) {
if (mDiscoveryService != null) {
return;
}
mRequestCachedPwos = requestCachedPwos;
Intent intent = new Intent(getActivity(), PwoDiscoveryService.class);
getActivity().startService(intent);
getActivity().bindService(intent, this, Context.BIND_AUTO_CREATE);
}
- 23. @braintree_dev / @jeffprestes#eddystone
PwoDiscoveryService.java
/**
* This is a service that scans for nearby Physical Web Objects.
* It is created by MainActivity.
* It finds nearby ble beacons, and stores a count of them.
* It also listens for screen on/off events
* and start/stops the scanning accordingly.
* It also silently issues a notification informing the user of nearby beacons.
* As beacons are found and lost, the notification is updated to reflect
* the current number of nearby beacons.
*/
public class PwoDiscoveryService extends Service
private void initialize() {
mNotificationManager = NotificationManagerCompat.from(this);
mPwoDiscoverers = new ArrayList<>();
mPwoDiscoverers.add(new BlePwoDiscoverer(this));
for (PwoDiscoverer pwoDiscoverer : mPwoDiscoverers) {
pwoDiscoverer.setCallback(this);
}
...
}
- 25. @braintree_dev / @jeffprestes#eddystone
mScanFilterUuids = new ParcelUuid[]{URIBEACON_SERVICE_UUID, EDDYSTONE_URL_SERVICE_UUID};
@Override
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanBytes) {
if (!leScanMatches(ScanRecord.parseFromBytes(scanBytes))) {
return;
}
UriBeacon uriBeacon = UriBeacon.parseFromBytes(scanBytes);
if (uriBeacon == null) {
return;
}
String url = uriBeacon.getUriString();
if (!URLUtil.isNetworkUrl(url)) {
return;
}
PwoMetadata pwoMetadata = createPwoMetadata(url);
pwoMetadata.setBleMetadata(device.getAddress(), rssi, uriBeacon.getTxPowerLevel());
pwoMetadata.bleMetadata.updateRegionInfo();
reportPwo(pwoMetadata);
}
BlePwoDiscoverer.java
- 26. @braintree_dev / @jeffprestes#eddystone
/**
* Parse scan record bytes to Eddystone
* The format is defined in Eddystone specification.
*
* @param scanRecordBytes The scan record of Bluetooth LE advertisement and/or scan response.
*/
public static UriBeacon parseFromBytes(byte[] scanRecordBytes) {
byte[] serviceData = parseServiceDataFromBytes(scanRecordBytes);
...
if (serviceData != null && serviceData.length >= 2) {
int currentPos = 0;
byte txPowerLevel = serviceData[currentPos++];
byte flags = (byte) (serviceData[currentPos] >> 4);
serviceData[currentPos] = (byte) (serviceData[currentPos] & 0xFF);
String uri = decodeUri(serviceData, currentPos);
return new UriBeacon(flags, txPowerLevel, uri);
}
return null;
}
UriBeacon.java
- 27. @braintree_dev / @jeffprestes#eddystone
private static String decodeUri(byte[] serviceData, int offset) {
if (serviceData.length == offset) {
return NO_URI;
}
StringBuilder uriBuilder = new StringBuilder();
if (offset < serviceData.length) {
byte b = serviceData[offset++];
String scheme = URI_SCHEMES.get(b);
if (scheme != null) {
uriBuilder.append(scheme);
if (URLUtil.isNetworkUrl(scheme)) {
return decodeUrl(serviceData, offset, uriBuilder);
} else if ("urn:uuid:".equals(scheme)) {
return decodeUrnUuid(serviceData, offset, uriBuilder);
}
}
Log.w(TAG, "decodeUri unknown Uri scheme code=" + b);
}
return null;
}
UriBeacon.java
- 28. @braintree_dev / @jeffprestes#eddystone
private static String decodeUri(byte[] serviceData, int offset) {
if (serviceData.length == offset) {
return NO_URI;
}
StringBuilder uriBuilder = new StringBuilder();
if (offset < serviceData.length) {
byte b = serviceData[offset++];
String scheme = URI_SCHEMES.get(b);
if (scheme != null) {
uriBuilder.append(scheme);
if (URLUtil.isNetworkUrl(scheme)) {
return decodeUrl(serviceData, offset, uriBuilder);
} else if ("urn:uuid:".equals(scheme)) {
return decodeUrnUuid(serviceData, offset, uriBuilder);
}
}
Log.w(TAG, "decodeUri unknown Uri scheme code=" + b);
}
return null;
}
UriBeacon.java
- 29. @braintree_dev / @jeffprestes#eddystone
/**
* URI Scheme maps a byte code into the scheme and an optional scheme specific prefix.
*/
private static final SparseArray<String> URI_SCHEMES = new SparseArray<String>() {{
put((byte) 0, "http://www."); put((byte) 1, "https://www.");
put((byte) 2, "http://"); put((byte) 3, "https://");
put((byte) 4, "urn:uuid:"); // RFC 2141 and RFC 4122};
}};
/**
* Expansion strings for "http" and "https" schemes. These contain strings appearing anywhere in a
* URL. Restricted to Generic TLDs. <p/> Note: this is a scheme specific encoding.
*/
private static final SparseArray<String> URL_CODES = new SparseArray<String>() {{
put((byte) 0, ".com/"); put((byte) 1, ".org/");
put((byte) 2, ".edu/"); put((byte) 3, ".net/");
put((byte) 4, ".info/"); put((byte) 5, ".biz/");
put((byte) 6, ".gov/"); put((byte) 7, ".com");
put((byte) 8, ".org"); put((byte) 9, ".edu");
put((byte) 10, ".net"); put((byte) 11, ".info");
put((byte) 12, ".biz"); put((byte) 13, ".gov");
}};
UriBeacon.java
- 31. I’d love to hear
your questions.
Thanks.
Jeff Prestes
@jeffprestes
Slideshare.com/jeffprestes
Github.com/jeffprestes
@paypaldev
@braintree_dev
developer.paypal.com
developers.braintreepayments.com
Editor's Notes
- Open Protocol Designed by Google
You can have a specific device like Estimote Beacons, or you can use a Rfduino, or BLE module for Arduino, or a Bluetooth 4.0 dongle on a Raspberry Pi, or use a computer that has Bluetooth 4.0 module to advertise data. You can create your own implementation in Node, Python, Java, etc…
What data should I advertise?
- It has 3 data format specification.
Like the Eddystone-UID and Eddystone-URL frame types, Eddystone-TLM is broadcast in the clear, without message integrity validation. You should design your application to be tolerant of the open nature of such a broadcast.
- Eddystone beacons may transmit data about their own operation to clients. This data is called telemetry and is useful for monitoring the health and operation of a fleet of beacons.
- Most known format: give an ID to your device to your mobile application be able to have a context inside of buildings where GPS signal isn’t available.
- You can advertise an URL that contains data about related to something (a device, a place, or a person)
Max 17 caracters
- It’s open!
It’s easy and very straightforward
- The main reason
Old UriBeacon
Secure: the important information is in your website not into the device
It’s a backbone for Physical Web
- The main reason
Old UriBeacon
Secure: the important information is in your website not into the device
It’s a backbone for Physical Web
- An effort to enable frictionless discovery of web content relating to one’s surroundings.
- https://ppd.io/jb
https://ppd.io/jy
- https://ppd.io/jb
https://ppd.io/jy
https://github.com/don/node-eddystone-beacon
https://github.com/sandeepmistry/bleno#running-on-linux
It supports inform his temperature
It supports inform a counter that informs the number of time it has emitted data frames. Useful to control performance.
- The main reason
Old UriBeacon
Secure: the important information is in your website not into the device
It’s a backbone for Physical Web
- An effort to enable frictionless discovery of web content relating to one’s surroundings.
- The main reason
Old UriBeacon
Secure: the important information is in your website not into the device
It’s a backbone for Physical Web
- The main reason
Old UriBeacon
Secure: the important information is in your website not into the device
It’s a backbone for Physical Web
- The main reason
Old UriBeacon
Secure: the important information is in your website not into the device
It’s a backbone for Physical Web
- The main reason
Old UriBeacon
Secure: the important information is in your website not into the device
It’s a backbone for Physical Web
- The main reason
Old UriBeacon
Secure: the important information is in your website not into the device
It’s a backbone for Physical Web
- The main reason
Old UriBeacon
Secure: the important information is in your website not into the device
It’s a backbone for Physical Web
- The main reason
Old UriBeacon
Secure: the important information is in your website not into the device
It’s a backbone for Physical Web
- The main reason
Old UriBeacon
Secure: the important information is in your website not into the device
It’s a backbone for Physical Web
- The main reason
Old UriBeacon
Secure: the important information is in your website not into the device
It’s a backbone for Physical Web
- An effort to enable frictionless discovery of web content relating to one’s surroundings.