Following on from part 1 and part 2, let's now create the basis of a beacon solution for museums. The museum visitor walks into the museum and installs the museum app on their device. As they walk around the museum, the museum app detects beacons located near the visitor and, since each beacon has a unique ID, the app is able to distinguish between beacons. Each beacon is attached to a specific painting in the museum. Beacons are small, so can be neatly tucked away behind a painting. The museum app identifies the beacon and provides the related information about the painting to the museum app.
The below is an actual Android app installed on my Android device, i.e., the screenshot below is of a functioning Android app that implements the ideas sketched out above.
(Yes, I know the above is not by Vincent van Gogh. All this is a simulation of a real museum app, including the content of the app itself.)
Something else to quickly point out—what we are talking about here has some interesting terminology: (1) the beaconizing of a museum and (2) creating a museum experience and (3) developing a beacon platform for museums and (4) modernizing the museum experience and (5) Museum 2.0 and (6) etc. Nice power terms can be used to orientate a potential customer to beacon technology.
We'll code this in two phases in an Oracle JET module. In the first phase, we won't incorporate images, just text.
The simple UI:
<div class="oj-hybrid-padding"> <h3>Museum</h3> <hr/> <div> Status: <span data-bind="text: indicator"></span> <br/><br/>Painter:<br/><br/> <h2><span data-bind="text: beaconSpecificMessage"></span></h2> <hr/> <br/><br/><button data-bind="click: detectBeacons">Enter here.</button> </div> </div>
And the business logic:
var self = this; self.indicator = ko.observable(); self.beaconSpecificMessage = ko.observable(); self.beacons = [ { uuid: 'E2C56DB5-DFFB-48D2-B060-D0F5A71096E0', identifier: 'Rembrandt van Rijn', minor: 1, major: 1 }, { uuid: 'A164DFF8-9C6B-4FB5-A131-F5328DF48664', identifier: 'Vincent Van Gogh', minor: 1, major: 1 }, { uuid: '74278BDA-B644-4520-8F0C-720EAF059935', identifier: 'Jacob van Ruisdael', minor: 1, major: 1 } ]; self.beaconRegions = []; self.detectBeacons = function () { for (var i in self.beacons) { var b = self.beacons[i]; self.beaconRegions[b.identifier] = new cordova.plugins.locationManager.BeaconRegion(b.identifier, b.uuid, b.major, b.minor); } var delegate = new cordova.plugins.locationManager.Delegate(); delegate.didStartMonitoringForRegion = function (pluginResult) { self.indicator('Started!'); }; delegate.didDetermineStateForRegion = function (pluginResult) { var painter = pluginResult.region.identifier; self.beaconSpecificMessage(painter); }; cordova.plugins.locationManager.setDelegate(delegate); for (var i in self.beaconRegions) { var b = self.beaconRegions[i]; if (b === undefined) continue; cordova.plugins.locationManager.startMonitoringForRegion(b); } };
The above is based on this:
https://github.com/petermetz/cordova-plugin-ibeacon/issues/190
Now, let's do the second phase, where we incorporate images. Based on the above, a different image could be provided matching the painting that the beacon represents:
delegate.didDetermineStateForRegion = function (pluginResult) { var painter = pluginResult.region.identifier; if (painter === "Rembrandt van Rijn"){ self.beaconSpecificImage("css/images/rijn.png"); } else if (painter === "Vincent Van Gogh") { self.beaconSpecificImage("css/images/gogh.jpg"); } else { self.beaconSpecificImage("css/images/ruisdael.jpg"); } self.beaconSpecificMessage(painter); };
Maybe even neater than the if/else approach would be to integrate the images into the "self.beacons" array, i.e., add a new item in there called "image" and read it out via "pluginResult.region.image". And here's the rewritten view, incorporating the images:
<div class="oj-hybrid-padding"> <h3>Museum</h3> <hr/> <div> <input type="image" style="border:1px solid black" data-bind="attr:{src: beaconSpecificImage}" width="250" height="250" alt="No picture found."/> <br/><br/>Painter:<br/><br/> <h2><span data-bind="text: beaconSpecificMessage"></span></h2> <hr/> <br/><br/><button data-bind="click: detectBeacons">Enter!</button> Status: <span data-bind="text: indicator"></span> </div> </div>
The key point here is that the beacon does not provide messages such as the name of the painter or the related image. Instead, the beacon simply provides its unique ID. It is up to the app to decide what to do with that information. In this particular case, each unique ID is mapped to a painter's name and related image, though it could be anything else as well.
Note: In doing all of the above, and while you don't have actual beacons, the software provided by Radius Networks is immensely helpful. Without something like MacBeacon, how are you going to simulate the multiple beacons you will be detecting and monitoring via the museum app described in this article? Take a look at the UI below and now you'll understand its relevance much better than in the earlier article where I introduced it, since you can switch from one simulated beacon to the other, switching a different one on, one at a time, simulating the experience of a visitor walking around a museum:
Finally, bear in mind that Bluetooth is used here and throughout everything that you do with beacons—the user of the app does not need to be connected to a Wifi network to use the museum app. However, somehow the museum app needs to be installed, though even that could be done without a Wifi network, e.g., via a barcode scanner.