beacons, raspberry pi & node.js

31
Beacons RaspberryPi Nodejs Uniting technologies to Giving a URL to All Objects Jeff Prestes

Upload: jeff-prestes

Post on 13-Apr-2017

10.664 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Beacons, Raspberry Pi & Node.js

BeaconsRaspberryPiNodejs

Uniting technologies to Giving a URL to All Objects

Jeff Prestes

Page 2: Beacons, Raspberry Pi & Node.js

About me…

@jeffprestesgithub.com/jeffprestesslideshare.net/jeffprestes

Developer & EntrepreneurJava, PHP, JavaScript, Mobile Developer

Football (Soccer?) fan,father and IoT Researcher

Page 3: Beacons, Raspberry Pi & Node.js

BeaconsRaspberryPiNodejs

Uniting technologies to Giving a URL to All Objects

Jeff Prestes

Page 4: Beacons, Raspberry Pi & Node.js

To be more fun…first install

Physical Web clients

@jeffprestes#physicalweb

iOS – Physical Webhttps://itunes.apple.com/ca/app/physical-web/id927653608?mt=8

Android – Physical Webhttps://play.google.com/store/apps/details?id=physical_web.org.physicalweb

Page 5: Beacons, Raspberry Pi & Node.js

InstallingNodejs

on a Raspberry Pi

@jeffprestes#physicalweb

Page 6: Beacons, Raspberry Pi & Node.js

$ curl -sLS https://apt.adafruit.com/add | sudo bash

$ sudo apt-get install node

$ sudo apt-get autoremove

@jeffprestes#physicalweb

Source: https://learn.adafruit.com/node-embedded-development/installing-node-dot-js

Page 7: Beacons, Raspberry Pi & Node.js

Demo

@jeffprestes#physicalweb

Page 8: Beacons, Raspberry Pi & Node.js

Advertising a URL

https://github.com/jeffprestes/node-eddystone-url

@jeffprestes#physicalweb

Page 9: Beacons, Raspberry Pi & Node.js

$ sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev

$ git clone https://github.com/jeffprestes/node-eddystone-url

$ cd node-eddystone-url

$ npm install eddystone-beacon –-save

@jeffprestes#physicalweb

Page 10: Beacons, Raspberry Pi & Node.js

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};

var myPayPalMe = 'http://bit.ly/1Q3Iani';var myLinkedIn = 'http://bit.ly/1SLiO3n';var myGitHub = 'http://bit.ly/1Ld89Mg';

beacon.advertiseUrl(myGitHub, [options]);

@jeffprestes#physicalweb

Page 11: Beacons, Raspberry Pi & Node.js

$ sudo node index.js

@jeffprestes#physicalweb

Page 12: Beacons, Raspberry Pi & Node.js

Demo

@jeffprestes#physicalweb

Page 13: Beacons, Raspberry Pi & Node.js

EddystoneProtocol

@jeffprestes#physicalweb

Page 14: Beacons, Raspberry Pi & Node.js

eddystone-tlmeddystone-uideddystone-url

@jeffprestes#physicalweb

Page 15: Beacons, Raspberry Pi & Node.js

eddystone-tlmeddystone-uideddystone-url

@jeffprestes#physicalweb

Page 16: Beacons, Raspberry Pi & Node.js

eddystone-tlmeddystone-uideddystone-url

@jeffprestes#physicalweb

Page 17: Beacons, Raspberry Pi & Node.js

eddystone-tlmeddystone-uideddystone-url

@jeffprestes#physicalweb

Page 18: Beacons, Raspberry Pi & Node.js

https://github.com/google/eddystone/tree/master/eddystone-url

@jeffprestes#physicalweb

Page 19: Beacons, Raspberry Pi & Node.js

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};

var myPayPalMe = 'http://bit.ly/1Q3Iani';var myLinkedIn = 'http://bit.ly/1SLiO3n';var myGitHub = 'http://bit.ly/1Ld89Mg';

beacon.advertiseUrl(myGitHub, [options]);

@jeffprestes#physicalweb

Page 20: Beacons, Raspberry Pi & Node.js

@jeffprestes

Physical WebExpand the internet

#physicalweb

http://physical-web.org

Page 21: Beacons, Raspberry Pi & Node.js

I’d love to hearyour questions.

Thanks.

Jeff [email protected]/jeffprestesGithub.com/jeffprestes

Page 22: Beacons, Raspberry Pi & Node.js

@jeffprestes

AppendixCreate your own client

#physicalweb

How to detect a Beacon using Eddystone formatand how to parse his data

Code for Android

Page 23: Beacons, Raspberry Pi & Node.js

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); }}

@jeffprestes#physicalweb

Page 24: Beacons, Raspberry Pi & Node.js

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);}

@jeffprestes#physicalweb

Page 25: Beacons, Raspberry Pi & Node.js

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 Serviceprivate void initialize() { mNotificationManager = NotificationManagerCompat.from(this); mPwoDiscoverers = new ArrayList<>(); mPwoDiscoverers.add(new BlePwoDiscoverer(this)); for (PwoDiscoverer pwoDiscoverer : mPwoDiscoverers) { pwoDiscoverer.setCallback(this); } ...}

@jeffprestes#physicalweb

Page 26: Beacons, Raspberry Pi & Node.js

BlePwoDiscoverer.java

public class BlePwoDiscoverer extends PwoDiscoverer implements BluetoothAdapter.LeScanCallback {

mBluetoothAdapter.startLeScan(this);

@jeffprestes#physicalweb

Page 27: Beacons, Raspberry Pi & Node.js

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

@jeffprestes#physicalweb

Page 28: Beacons, Raspberry Pi & Node.js

/** * 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

@jeffprestes#physicalweb

Page 29: Beacons, Raspberry Pi & Node.js

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

@jeffprestes#physicalweb

Page 30: Beacons, Raspberry Pi & Node.js

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

@jeffprestes#physicalweb

Page 31: Beacons, Raspberry Pi & Node.js

@jeffprestes

#physicalweb

/** * 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