Exploring Google Eddystone with the Proximity Beacon API

Google recently announced the release of their cross-platform BLE Beacon format. Here we look at what we can do with it and how to use this new API to manage our beacons.

We recently saw the announcement of Google’s open beacon format, known as Eddystone. Released alongside this was the Proximity Beacon API, used to register and manage these beacons. Pairing this with the soon-to-be-released Nearby API – used by applications to interact with beacons – brings numerous possibilities for location experiences.

I’ve had the chance to explore this API and its documentation. In this post I hope to give an insight into exactly what it is and how you can use it.


To really understand how the API works, I decided to build a sample app, allowing me to really test the API’s functionality. Android users can find this on github here.


So what‘s new?

Previously, a beacon’s sole capability was to emit a signal to state its presence. Using the beacon’s physical position to determine location, you’re able to create a location-aware experience. And though beacons have been around for a while, they’ve never been easily capable of more than this.

What makes Eddystone different is the ability to use beacons to provide an increased sense of context to locations

Not only can we now be aware of a beacon’s presence, we can easily retrieve real-time data related to its physical position. This could be in situations such as:

  • Public transport – On buses or trains, providing live service updates
  • Restaurants – creating a personalised experience between customers and staff
  • Hotels – providing automatic room allocation and check-in
  • Taxi ranks – providing a more customised, convenient and integrated service
Beacons now provide a much greater depth of information regarding their deployed location.

What’s also great is that Eddystone is compatible with both Android and iOS, along with any platform that supports Bluetooth LE beacons.

Beacon Properties

Beacon properties allow us to do more than distinguishing one beacon from another. We can also store a collection of data specific to that beacon. This not only helps provide context based on its deployed location, but can also be dynamically updated using the Proximity Beacon API. This allows users to be pushed real-time and up-to-date information.

Beacon objects can store a vast collection of data regarding its deployed location.
  • beaconName – The automatically-assigned, read-only, unique identifier of the beacon.
  • advertisedId – The pre-defined ID assigned during the manufacturing process. It’s required during registration and cannot be overridden in future requests.
  • status – The required current operational status of the beacon. This can be either ACTIVE (visible to mobile devices), INACTIVE (not visible to mobile devices) or DECOMMISSIONED (the beacon is no longer being used; irreversible once set). Whilst the status property can return STATUS_UNSPECIFIED, this cannot be set manually during a request.
  • placeId – The (optional) Google Places ID referring to the beacons deployed location, assigned manually during registration or updates.
  • latLng – The beacon’s deployed location, containing both latitude and longitude coordinates. This is not automatically detected and must be updated if the beacon is repositioned.
  • indoorLevel – Returned from the Google Maps API, this optional value is used to indicate which floor of a building the beacon is located on.
  • expectedStability – The beacon’s manually assigned operational stability within its deployed location. This can be either STABLE (not expected to move), PORTABLE (may move but rarely expected to), MOBILE (frequently moves) or ROVING (continuously moves). Whilst the expectedStability property can return STATUS_UNSPECIFIED, this cannot be set manually during a request.
Beacons can be either Stable (e.g an entrance to a building), Mobile (personal item), Portable (store product display) and Roving (public transport)
  • description – The beacon’s optional 140 character description which can be used to provide a little more information on it.
  • properties – An optional key-value set containing details about the beacon, such as a firmware version or battery details.

The Proximity Beacon API

As a part of the Bluetooth LE platform, the Proximity beacon API is used to register, manage and carry out diagnostics on beacons. Alongside various properties, the API can be used to assign beacons’ attachments containing associated data. These can be dynamically updated, even when the beacons are in their deployed location, to create personalised and real-time experiences for the user. When released, apps using the Nearby API will be able to harness the data provided by these attachments.

This API is fairly simple to use, but first you’ll need to get an authorisation token, in order to access the endpoints we’ll look at.

Authorization

Whilst you only require an application API key to make request for public data from the API, you will require an OAuth token when making requests to manage beacon data. I suggest you follow this guide to get your API calls authenticated for the following requests.

Registering Beacons

We can register a beacon by sending a POST request to:

https://proximitybeacon.googleapis.com/v1beta1/beacons:register

When registering, the beacon must be sent as the body of the request. Other than the advertisedId and status, which are required, all other fields are optional.

We do not set the beaconName property of the beacon as this is returned as part of the returned Beacon object if our request is successful. Any unpopulated properties will not be returned as part of the Beacon object.

Upon a successful registration we retrieve back a Beacon object with an assigned beaconName

Note: Attempting to register a beacon with non-unique advertisedId will return an ALREADY_EXISTS status.

Retrieving a list of beacons

We are able to retrieve a list registered beacons by making a GET request to:

https://proximitybeacon.googleapis.com/v1beta1/beacons

It is possible to filter the beacons we retrieve by a specified property value. This is done using the query string (q) parameter in the request, for example:

  • description:“Downstairs” will filter results by beacons whose description matches the String “Downstairs”.
  • status:ACTIVE will return only beacons that are active.
  • stability:MOBILE will return only beacons that are mobile.
  • place_id:“ChIJ63qGvQuFdUgRqXYcmL5iKYM” will return all of the beacons located at the ribot studio.
  • registration_time:>=1433116800 will return all beacons registered after the specified time.
  • lat:50.830745 lng:-0.145628 radius:1000 will return all beacons that are within 1000 meters of the ribot studio.
  • property: “firmware-version=v2.2” will return all beacons using the custom defined property that matches the specified value.
  • attachment_type:“ribot-api/json” will return all registered beacons which have at least one attachment of the data type json.

A successful request returns a paginated list of complete beacon objects. The response also contains a totalCount of registered beacons, with a nextPageToken used to fetch the next n paginated beacons.

Requesting beacons will return back a list of all beacons registered under the authorised account

Retrieving a single beacon

We can retrieve a single Beacon using the beaconName and making a GET request to:

https://proximitybeacon.googleapis.com/v1beta1/{beaconName}

If the request is successful then we are returned the requested Beacon object, as illustrated below:

Using a beaconName will return us the specified Beacon object

Updating a beacon

A beacon can be updated by using the beaconName as a path parameter, passing the Beacon as the body and making a PUT request to:

https://proximitybeacon.googleapis.com/v1beta1/{beaconName}

You must send all fields (regardless of whether they have changed) that you want to persist. If you don’t, any absent properties will be permanently erased server-side.

Note: Changing the status property of the beacon here will be silently ignored. You must use one of the following endpoints to set this:

Activate

Activating a beacon will mark it as ACTIVE, marking it as in-use and visible to any mobile devices in range.

https://proximitybeacon.googleapis.com/v1beta1/{beaconName}:activate

Deactivate

Deactivating a beacon will mark it as INACTIVE, meaning it is no longer visible to mobile devices. It is possible to re-activate the beacon after this state has been set.

https://proximitybeacon.googleapis.com/v1beta1/{beaconName}:deactivate

Decommission

Decommissioning a beacon marks it as having no further use, causing it to be completely disregarded. Setting this state is irreversible, so should only be done if it is certain to not be used again.

https://proximitybeacon.googleapis.com/v1beta1/{beaconName}:decommission

A successful request will return an empty object. A sensible approach here would be to retrieve the corresponding Beacon object after updating the status, giving you the up-to-date Beacon object and a guarantee that the new status has been assigned.

Beacon Diagnostics

Each beacon instance has accessible diagnostics information. This contains an estimated low battery date and any alerts that have been raised.

  • beaconName – The name of the beacon that the diagnostics belong to.
  • estimatedLowBatteryDate – The date in which the beacon is estimated to reach a state of low battery power.
  • alerts – A list of alerts belonging to the beacon. An alert can be either WRONG_LOCATION (for cases where the beacon may have been relocated) or LOW_BATTERY (for cases where the battery level reaches < 60 days).

We can retrieve a list of beacon diagnostics by using the beaconName and making a GET request to:

https://proximitybeacon.googleapis.com/v1beta1/{beaconName}/diagnostics

Beacon Attachments

Using the beaconName property, we can assign Attachments allowing us to associate beacons with specific data in relation to its deployed location.

  • attachmentName – The attachment’s unique identifier, automatically-assigned server-side during registration.
  • namespacedType – The required attachment data type. The type defined is the data format being used for the attachment, used client side during data parsing. For example, your-namessspace/json informs the client that the attachment data is in json format.
  • data – The required data assigned to the attachment. It can be a maximum of 1024 bytes in size and must be base64 encoded within requests.

Attachment Namespaces

Namespaces are used to create a client-side separation between types of attachment data that may be received. Before we are able to add attachments to beacons, we need to retrieve a list of available namespaces to use by making a GET request to:

https://proximitybeacon.googleapis.com/v1beta1/namespaces

Add Attachments to Beacons

Attachments can be added to beacons by sending a POST request to the following endpoint, using the Attachment as the body of the request:

https://proximitybeacon.googleapis.com/v1beta1/{beaconName}/attachments

A successful request will return our registered Attachment, with the addition of the assigned attachmentName used for future API requests.

Deleting an Attachment

Obsolete attachments can be deleted using the attachmentName as a path parameter and making a DELETE request to the attachments endpoint:

https://proximitybeacon.googleapis.com/v1beta1/{beaconName}/attachments/{attachmentName}

A successful request will return an empty object will be returned. A sensible approach here would be to re-retrieve the beacon’s attachments to ensure that the correct list of beacon attachments is being used.

Deleting multiple attachments

Removing multiple attachments from a beacon can be done by making a POST request to:

https://proximitybeacon.googleapis.com/v1beta1/{beaconName}/attachments:batchDelete

By default, all of the beacons attachments will be deleted. However, the optional namespacedType query parameter can be used:

  • */*” will delete all of the beacons attachments.
  • A specific namespacedType will delete all attachments of that type. E.g the name-space/json will delete all json attachments and so on…

If the request is successful, then you will be returned the number of deleted attachments.

Deleting a batch of attachments will return us the number that were successfully deleted

Retrieve Attachments

Retrieving all of a beacon’s attachments can be done using the beaconName as a path parameter and making a GET request to:

https://proximitybeacon.googleapis.com/v1beta1/{beaconName}/attachments

A successful request will return a full list (without pagination) of the beacon’s attachments. If no attachments exist, then an empty list will be returned.

Using the beaconName property, we can retrieve a list of attachments belonging to a beacon

And that’s it!

From the areas of this new beacon format we’ve just explored, you’ll be able to see that beacons are now capable of so much more than they’ve been in the past. Whilst it’s still early days (and we’re still waiting for release of the Nearby API), this new format opens a lot of doors in terms of the kind of experiences you’ll now be able to create with beacon technology.

Now is the perfect time to begin conceptualising how these beacons can be made use of and implemented out there in the world. I’d love to hear the ideas you have!

If you know of any interesting beacons projects that we can help on, drop us a message over at ribot.co.uk.