Skip to content

Commit

Permalink
Minor whitespace updates
Browse files Browse the repository at this point in the history
  • Loading branch information
s10wen committed Oct 3, 2014
1 parent a78ba89 commit 1119af2
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 60 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
##The Physical Web
The Physical Web is an approach to unleash the core super power of the web: interaction on demand. People should be able to walk up to any smart device: e.g. a vending machine, a poster, a toy, a bus stop, a rental car, and not have to download an app first in order to use it. The user experience of using smart devices should be much like we use links on web, just tap and use.

The Physical Web is, at its base, a discovery service where URLs are broadcast and any nearby device can receive them. This takes the web we know and love and unlocks exciting new ways to interact.
The Physical Web is, at its base, a discovery service where URLs are broadcast and any nearby device can receive them. This takes the web we know and love and unlocks exciting new ways to interact.

The URL is the fundamental building block of the web, giving remarkable flexibility of expression. It can be:

* a web page with just a tiny paragraph of info
* a fully interactive web page
* a deep link into a native application.
* a deep link into a native application.

##Why We're Doing This
The number of smart devices is going to explode, both in our homes and in public spaces. Much like the web, there is going to be a 'long tail' of interactivity for smart devices. But the overhead of installing an app for each one just doesn't scale. We need a system that lets someone walk up and use a device with just a tap. The Physical web isn't about replacing native apps, it's about allowing interaction for the times when native apps just aren't practical.
Expand Down
4 changes: 2 additions & 2 deletions documentation/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ With any system, there will be people that try to exploit it. There will likely
##5. Why URLs?
The value of a URL is that it is a known part of the web, very flexible, and most importantly, decentralized. URLs allow anyone to play and no central server to be the bottleneck. This is one of the core principles of the web and critical to keep alive.

That being said, we completely expect others to experiment with a url+ID model that goes through their server (e.g. safeurls.com/?id=12345). That is perfectly acceptable and to be encouraged. Systems like that are likely to provide much better security and vetting of sites. But that is the beauty of URLs, there can be as many of these as you'd like and the system still works seamlessly.
That being said, we completely expect others to experiment with a url+ID model that goes through their server (e.g. safeurls.com/?id=12345). That is perfectly acceptable and to be encouraged. Systems like that are likely to provide much better security and vetting of sites. But that is the beauty of URLs, there can be as many of these as you'd like and the system still works seamlessly.

##6. Which platforms will you support?
This is meant to be an extension of the web so it should work on every platform. We expect that each platform will experiment with a different UX to show the nearby devices. For example, the current Android app uses notifications while the iOS app will use lock screen notifications. We hope to see lots of experimentation here on how various platforms choose to show and rank this information.

At this point, we have both an Android and iOS app that is open source. We hope this will be used and ported to other platforms.

##7. Can't the user be tracked?
Our current URL broadcast method involves a bluetooth broadcast from each beacon. The user's phone gathers this info without connecting to the beacon. This ensures the user is invisible to all beacons, meaning a user can't be tracked simply by walking past a broadcasting beacon. This was very much by design to keep users silent passage untrackable. However, once the user does click on a URL, they are then known to that website.
Our current URL broadcast method involves a bluetooth broadcast from each beacon. The user's phone gathers this info without connecting to the beacon. This ensures the user is invisible to all beacons, meaning a user can't be tracked simply by walking past a broadcasting beacon. This was very much by design to keep users silent passage untrackable. However, once the user does click on a URL, they are then known to that website.

The search agent on the phone may keep track of which devices the user taps on so they can improve the ranking in the future. Of course, this too needs to be discussed and then possibly offered to the user as an option so they are in control of how this information is stored.

Expand Down
14 changes: 7 additions & 7 deletions documentation/technical_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
This is a prototype system being used to understand and explore the issues involved in building the Physical Web.

###Broadcast
The current design uses Bluetooth Low Energy (BLE) devices that broadcast the URL in the advertising packet. In this broadcast mode, it doesn't do anything else such as respond to requests. The sole job of the device is to broadcast the URL to the surrounding area.
The current design uses Bluetooth Low Energy (BLE) devices that broadcast the URL in the advertising packet. In this broadcast mode, it doesn't do anything else such as respond to requests. The sole job of the device is to broadcast the URL to the surrounding area.

The reason is to accommodate potentially the worst case scenario of a large numbers of devices in an area with a large amount of people. A broadcast only approach avoids an n-squared problem of every user connecting to every device. By making each device constantly broadcast, any number of devices can just pick up the information passively with little conflict.

This has another advantage in that it means that a user can walk through a space and leave no trace: the broadcasting devices have no idea who is listening.
This has another advantage in that it means that a user can walk through a space and leave no trace: the broadcasting devices have no idea who is listening.

The current prototype broadcasts once every second, striking a balance between user response time and battery life. There is nothing stopping a device from broadcasting faster if they wish.

Expand All @@ -17,14 +17,14 @@ The URL is stored in the advertising packet of a BLE device. The packet identifi

The specific fields for this packet are as follows:

| FieldName | Offset | Size | Format | Description |
|--------------|----------|--------|-------------|-----------------------------------------------------------------|
| FieldName | Offset | Size | Format | Description |
|----------------|----------|--------|-------------|-----------------------------------------------------------------|
| **AD Length** | 0 | 1 | 8-bit value | 5..23 |
| **AD Type** | 1 | 1 | 8-bit value | Service Data = 0x16 |
| **Service ID** | 2 | 2 | 16-bit UUID | URI = 0xFED8 |
| **Flags** | 4 | 1 | 8-bit value | See spec |
| **TX Power** | 5 | 1 | 8-bit value | See spec |
| **URI field** | 6 | 1..18 | octets | The US-ASCII text of the URI with embedded Text Expansion Codes |
| **URI field** | 6 | 1..18 | octets | The US-ASCII text of the URI with embedded Text Expansion Codes |

This does not, however, leave a lot of room for the text of the URL. This is one of tradeoffs that comes from avoiding any connections to the beacon (to ensure no user tracking can occur) URLs are encoded so common patterns like 'http://www.' and '.com' can be compressed into a single character. This is very similar to what QRCodes use to encode their URLs. In addition, we expect initial testers will either use short domains or a URL shortener. Both the android and iOS apps do this automatically when a URL is typed in that is too long to fit.

Expand All @@ -33,7 +33,7 @@ A GATT service that would allow the URL to be of any arbitrary length, is under
This is just a quick description to show the structure of the ad packet. It is documented in a related GitHub project, the URIBecon specification. This repo will go live shortly.

###Client
The current client is an application to prove out the technology. If you open the app, it lists the nearby beacons that it can see, sorted by signal strength. Note the signal strength is a very iffy metric as it there many reasons why it can vary. However, if you are standing in front of device and the next device is >5 feet away, it tends to work out well in practice. This is the primary reason we include a TX_POWER byte in the ad packet so it's possible to calculate signal loss and rank different strength beacons.
The current client is an application to prove out the technology. If you open the app, it lists the nearby beacons that it can see, sorted by signal strength. Note the signal strength is a very iffy metric as it there many reasons why it can vary. However, if you are standing in front of device and the next device is >5 feet away, it tends to work out well in practice. This is the primary reason we include a TX_POWER byte in the ad packet so it's possible to calculate signal loss and rank different strength beacons.

The client lists the meta information from the URL: TITLE, DESCRIPTION, URL, and FAVICON. These could be pulled at run time but there is a simple proxy server that acts as a cache to speed up this process.

Expand All @@ -44,7 +44,7 @@ The server receives a request from the client with all of the URLs found and ret
In order to use URLs, the system expects those URLs to point to a web page, which offers up the meta information described above. This somewhat limits the URLs as they much then always point to a valid HTML page. This is likely a big limitation to URLs that want to link to native applications. This is an imporant use case and needs to be discussed. Is there an alternative way to offer this meta data but not point to a web page?

###Ranking
As more devices are found, the importance of ranking the devices becomes more valuable. Sorting only be signal strength is a good start but the server could do a much better job in two ways. The first would be to track which URLs are clicked as that implies value, so higher used URLs could be ranked higher. In addition, the server could track personal use so if you tend to pick the same device at work, it would be sure to rank the device higher as well.
As more devices are found, the importance of ranking the devices becomes more valuable. Sorting only be signal strength is a good start but the server could do a much better job in two ways. The first would be to track which URLs are clicked as that implies value, so higher used URLs could be ranked higher. In addition, the server could track personal use so if you tend to pick the same device at work, it would be sure to rank the device higher as well.

### Security
At this point, the URL is broadcast as plain text so it is not really viable for personal use (as neighbors could know what devices you have in your home) However, the advantage of URLs is that there several potential solutions that would help this. There is nothing stopping a beacon from delivering an obfuscated URL or even a URL that requires login in order to see the information.
6 changes: 3 additions & 3 deletions firmware/BLE113/physical-web.bgproj
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8" ?>
<project>
<gatt in="gatt.xml" />
<hardware in="hardware.xml" />
<hardware in="hardware.xml" />
<script in="physical-web.bgs" />
<image out="physical-web.hex" />
<device type="ble113" />
<boot fw="bootuart" />
</project>
<boot fw="bootuart" />
</project>
4 changes: 2 additions & 2 deletions firmware/BLE113/physical-web.bgs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ procedure enable_advertisement()
end

# System boot event listener
event system_boot(major, minor, patch, build, ll_version, protocol_version, hw)
event system_boot(major, minor, patch, build, ll_version, protocol_version, hw)
# Initialize Advertisement data
adv_data(0:1) = $02 # AD field length = 2 bytes
adv_data(1:1) = $01 # AD field type = «Flags»
Expand All @@ -22,7 +22,7 @@ event system_boot(major, minor, patch, build, ll_version, protocol_version, hw)
adv_data(4:1) = $03 # AD field type = «Complete List of 16-bit Service Class UUIDs»
adv_data(5:1) = $D8 # URI Beacon ID
adv_data(6:1) = $FE

adv_data(7:1) = $0A # AD field Length = 10 bytes
adv_data(8:1) = $16 # AD field type = «Service Data»
adv_data(9:1) = $D8 # URI Beacon ID
Expand Down
2 changes: 1 addition & 1 deletion web-service/app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ handlers:
- url: /favicon\.ico
static_files: favicon.ico
upload: favicon\.ico

- url: /index\.html
static_files: static/index.html
upload: static/index\.html
Expand Down
62 changes: 31 additions & 31 deletions web-service/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,25 +44,25 @@ class ResolveScan(webapp2.RequestHandler):
def post(self):
input_data = self.request.body
input_object = json.loads(input_data) # Data is not sanitised.

metadata_output = []
output = {
"metadata": metadata_output
}

devices = []
if "objects" in input_object:
objects = input_object["objects"]
else:
objects = []

# Resolve the devices

for obj in objects:
key_id = None
url = None
force = False

if "id" in obj:
key_id = obj["id"]
elif "url" in obj:
Expand All @@ -71,27 +71,27 @@ def post(self):

if "force" in obj:
force = True

# We need to go and fetch. We probably want to asyncly fetch.

# We don't need RSSI yet.
#rssi = obj["rssi"]

# In this model we can only deal with one device with a given ID.
device = Device.get_or_insert(key_id, name = key_id, url = url)

device_data = {
"id": device.name
}

if force or device.url is not None:
# Really if we don't have the data we should not return it.
siteInfo = SiteInformation.get_by_id(device.url)

if force or siteInfo is None or siteInfo.updated_on < datetime.now() - timedelta(minutes=5):
# If we don't have the data or it is older than 5 minutes, fetch.
siteInfo = FetchAndStoreUrl(siteInfo, device.url)

if siteInfo is not None:
device_data["url"] = siteInfo.url
device_data["title"] = siteInfo.title
Expand All @@ -100,27 +100,27 @@ def post(self):
device_data["favicon_url"] = siteInfo.favicon_url
else:
device_data["url"] = device.url

metadata_output.append(device_data)

logging.info(output);
# Resolve from DB based off key.
self.response.headers['Content-Type'] = 'application/json'
json_data = json.dumps(output);
self.response.write(json_data)

class SaveUrl(webapp2.RequestHandler):
def post(self):
name = self.request.get("name")
url = self.request.get("url")

title = ""
icon = "/favicon.ico"

device = Device.get_or_insert(name, name = name, url = url)
device.url = url
device.put()

# Index the page
FetchAndStoreUrl(device.url)
self.redirect("/index.html")
Expand All @@ -144,35 +144,35 @@ def GetContentEncoding(content):
_, params = cgi.parse_header(content_type)
if 'charset' in params:
encoding = params['charset']

if encoding is None:
value = htmltree.xpath("//head//meta/attribute::charset")
if (len(value) > 0):
encoding = value[0]

if encoding is None:
try:
encoding = 'utf-8'
u_value = unicode(content, 'utf-8')
except UnicodeDecodeError:
encoding = 'iso-8859-1'
u_value = unicode(content, 'iso-8859-1')

return encoding

def StoreUrl(siteInfo, url, final_url, content, encoding):
title = None
description = None
icon = None

# parse the content

parser = etree.HTMLParser(encoding=encoding)
htmltree = etree.fromstring(content, parser)
value = htmltree.xpath("//head//title/text()");
if (len(value) > 0):
title = value[0]

# Try to use <meta name="description" content="...">.
value = htmltree.xpath("//head//meta[@name='description']/attribute::content")
if (len(value) > 0):
Expand All @@ -181,28 +181,28 @@ def StoreUrl(siteInfo, url, final_url, content, encoding):
description = None
if description == title:
description = None

# Try to use <div class="content">...</div>.
if description is None:
value = htmltree.xpath("//body//*[@class='content']//*[not(*|self::script|self::style)]/text()")
description = ' '.join(value)
if len(description) == 0:
description = None

# Try to use <div id="content">...</div>.
if description is None:
value = htmltree.xpath("//body//*[@id='content']//*[not(*|self::script|self::style)]/text()")
description = ' '.join(value)
if len(description) == 0:
description = None

# Fallback on <body>...</body>.
if description is None:
value = htmltree.xpath("//body//*[not(*|self::script|self::style)]/text()")
description = ' '.join(value)
if len(description) == 0:
description = None

# Cleanup.
if description is not None:
description = description.strip()
Expand All @@ -215,7 +215,7 @@ def StoreUrl(siteInfo, url, final_url, content, encoding):
description = description.replace(" ", " ");
if description is not None and len(description) > 500:
description = description[:500]

if icon is None:
value = htmltree.xpath("//head//link[@rel='shortcut icon']/attribute::href");
if (len(value) > 0):
Expand All @@ -228,14 +228,14 @@ def StoreUrl(siteInfo, url, final_url, content, encoding):
value = htmltree.xpath("//head//link[@rel='apple-touch-icon']/attribute::href");
if (len(value) > 0):
icon = value[0]

if icon is not None:
icon = urljoin(final_url, icon)
if icon is None:
icon = urljoin(final_url, "/favicon.ico")

if siteInfo is None:
siteInfo = SiteInformation.get_or_insert(url,
siteInfo = SiteInformation.get_or_insert(url,
url = final_url,
title = title,
favicon_url = icon,
Expand All @@ -247,7 +247,7 @@ def StoreUrl(siteInfo, url, final_url, content, encoding):
siteInfo.favicon_url = icon
siteInfo.description = description
siteInfo.put()

return siteInfo

class Index(webapp2.RequestHandler):
Expand Down
Loading

0 comments on commit 1119af2

Please sign in to comment.