pinte
TRANSCRIPT
![Page 1: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/1.jpg)
In Touch with Things: Programming NFC on Android with MORENA
Kevin PinteAndoni Lombide CarretonWolfgang De Meuter
DroidconApril 10, 2013Berlin, Germany
![Page 2: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/2.jpg)
• NFC (touch range).
• Callback on activities to detect RFID tags with subscribed MIME-type in memory.
• File access abstraction
RFID in Android
NdefMessage: { , , }
NdefRecord byte array
read write
![Page 3: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/3.jpg)
Drawbacks of the Android NFC API
• Manual failure handlingfailures are the rule rather than the exception:NFC causes A LOT of failures because of its hardware characteristics
• Blocking communicationAndroid documentation recommends to use a separate thread for many NFC operations
• Manual data conversion
• Tight coupling with activity-based architecture
![Page 4: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/4.jpg)
Lessons Learnt from Previous Ambient-Oriented Programming Research
• Using objects as first class software representations for RFID-tagged “things” is a nice abstraction.
• These objects can be directly stored in the RFID tags’ memory to minimize data conversion.
• Event-driven discovery (fortunately built-in into Android).
• Asynchronous, fault tolerant reads and writes.experimental scripting
language for mobile apps in ad hoc networks
RFID tags as “mobile devices” and I/O as
network communication
![Page 5: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/5.jpg)
Application
MORENA Middleware Architecture
Android
Tag level
Thing level One middlewarefor Android 4.0 or higher (API 14)
![Page 6: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/6.jpg)
Evaluation: Wi-Fi Sharing Application
![Page 7: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/7.jpg)
Evaluation: Wi-Fi Sharing Application
![Page 8: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/8.jpg)
Things
public class WifiConfig extends Thing {
public String ssid_; public String key_;
public WifiConfig(ThingActivity<WifiConfig> activity, String ssid, String key) { super(activity); ssid_ = ssid; key_ = key; } public boolean connect(WifiManager wm) {
// Connect to ssid_ with password key_ };}
From now on, we don’t have to worry about the
activity anymore.
Supported serialization: - JSON-serializable fields. - Skipping transient fields. - Deep serialization, no cycles.
![Page 9: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/9.jpg)
Initializing Things
@Overridepublic void whenDiscovered(EmptyRecord empty) { empty.initialize( myWifiThing, new ThingSavedListener<WifiConfig>() { @Override public void signal(WifiConfig thing) { toast("WiFi joiner created!"); } }, new ThingSaveFailedListener() { @Override public void signal() { toast("Creating WiFi joiner failed, try again."); } },
5000);}
As soon as an empty tag is detected
![Page 10: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/10.jpg)
Discovering and Reading Things
@Overridepublic void whenDiscovered(WifiConfig wc) { toast("Joining Wifi network " + wc.ssid_); wc.connect();}
As soon as a WifiConfig tag is detected
Contains cached fields for synchronous access.
Physical reads must be asynchronous.
![Page 11: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/11.jpg)
Saving Modified ThingsmyWifiConfig.ssid_ = "MyNewWifiName";myWifiConfig.key_ = "MyNewWifiPassword";
myWifiConfig.saveAsync( new ThingSavedListener<WifiConfig>() { @Override public void signal(WifiConfig wc) { toast("WiFi joiner saved!"); } }, new ThingSaveFailedListener() { @Override public void signal() { toast("Saving WiFi joiner failed, try again."); } }, 5000);
![Page 12: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/12.jpg)
Broadcasting Things to Other Phones
myWifiConfig.broadcast( new ThingBroadcastSuccessListener<WifiConfig>() { @Override public void signal(WifiConfig wc) { toast("WiFi joiner shared!"); } }, new ThingBroadcastFailedListener<WifiConfig>() { @Override public void signal(WifiConfig wc) { toast("Failed to share WiFi joiner, try again."); } }, 5000);
Will trigger whenDiscovered on the receiving phone with the broadcasted thing
![Page 13: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/13.jpg)
Evaluation: WiFi Sharing Application
![Page 14: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/14.jpg)
MORENA Middleware Architecture
Android
Tag level
Thing level
Application
One middlewarefor Android 4.0 or higher (API 14)
![Page 15: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/15.jpg)
Detecting RFID Tags
new TextTagDiscoverer(currentActivity, TEXT_TYPE, new NdefMessageToStringConverter(), new StringToNdefMessageConverter());
private class TextTagDiscoverer extends TagDiscoverer { @Override public void onTagDetected(TagReference tagReference) { readTagAndUpdateUI(tagReference); } @Override public void onTagRedetected(TagReference tagReference) { readTagAndUpdateUI(tagReference); }}
![Page 16: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/16.jpg)
The Tag Reference Abstraction
![Page 17: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/17.jpg)
Reading RFID Tags
tagReference.read( new TagReadListener() { @Override public void signal(TagReference tagReference) { // tagReference.getCachedData() } }, new TagReadFailedListener() { @Override public void signal(TagReference tagReference) { // Deal with failure } });
![Page 18: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/18.jpg)
Writing RFID Tags
tagReference.write( toWrite, new TagWrittenListener() { @Override public void signal(TagReference tagReference) { // Handle write success } }, new TagWriteFailedListener() { @Override public void signal(TagReference tagReference) { // Deal with failure } });
![Page 19: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/19.jpg)
Fine-grained Filtering
private class TextTagDiscoverer extends TagDiscoverer { @Override public void onTagDetected(TagReference tagReference) { readTagAndUpdateUI(tagReference); } @Override public void onTagRedetected(TagReference tagReference) { readTagAndUpdateUI(tagReference); }
@Override public boolean checkCondition(TagReference tagReference) { // Can be used to apply a predicate // on tagReference.getCachedData() }}
![Page 20: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/20.jpg)
MORENA Conclusion
• Event-driven discovery.
• Non-blocking communication:
• Things: cached copy, asynchronous saving of cached data.
• TagReferences: first class references to RFID tags offering asynchronous reads and writes.
• Automatic data conversion
• Looser coupling from activity-based architecture
![Page 21: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/21.jpg)
Current Research: Volatile Database
• Data structures over many tags?
• Querying collections of things?
• Stronger consistency guarantees?
• Transactions?
• Validations?
• ... Active Record (RoR) for RFID
![Page 22: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/22.jpg)
Thing Associations
defmodel: Shelf properties: { number: Number} associations: { hasMany: `books};
defmodel: Book properties: { title: Text; authors: Text; isbn: Text;} proto: { def isMisplaced(currentShelf) { shelf != currentShelf; };} associations: {
belongsTo: `shelf};
a shelf contains many books
a book belongs to exactly one shelf in the library
![Page 23: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/23.jpg)
Instantiating a Model and Saving to Tag
def newBook := Book.create: {title := “Agile Web Development with Rails”;authors := “Dave Thomas, ...”;isbn := “978-0-9776-1663-3”;
};def saveReq := newBook.saveAsync(10.seconds);when: saveReq succeeded: {
// the book was saved to a tag} catch: { |exc|
// book could not be saved within 10 sec};
newBook.shelf := shelf42;
shelf42.books << newBook; associate a book with a shelf:foreign key in book thing
![Page 24: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/24.jpg)
Working with Many Things: Reactive Queries
def shelf42 := Shelf.all.first: { |s| s.number == 42 };def currentShelf := Shelf.all.last;
def misplacedBooks := Book.all.where: { |b|b.isMisplaced(currentShelf)
};
misplacedBooks.each: { |b|b.shelf := currentShelf;b.saveAsync(5.seconds)
};
most recently scanned shelf
synchronize misplaced books with current shelf
finding misplaced books in a library
all books not matching the last scanned shelf
![Page 25: Pinte](https://reader033.vdocuments.net/reader033/viewer/2022060205/55a134e01a28abff6a8b456e/html5/thumbnails/25.jpg)
In Touch with Things: Programming NFC on Android with MORENA
Droidcon, April 10, 2013, Berlin, Germany
@ambienttalk
soft.vub.ac.be/amopcode.google.com/p/ambienttalk
tinyurl.com/morena-android
@bommasaurus
tinyurl.com/kevinpinte