├── DETAIL.md ├── README.md ├── client-iphone ├── .DS_Store ├── piBeacon-iphone.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── matt.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── matt.xcuserdatad │ │ └── xcschemes │ │ ├── piBeacon-iphone.xcscheme │ │ └── xcschememanagement.plist ├── piBeacon-iphone │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ └── Main.storyboard │ ├── FirstViewController.h │ ├── FirstViewController.m │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── LaunchImage.launchimage │ │ │ └── Contents.json │ │ ├── first.imageset │ │ │ ├── Contents.json │ │ │ ├── first.png │ │ │ └── first@2x.png │ │ ├── second.imageset │ │ │ ├── Contents.json │ │ │ ├── second.png │ │ │ └── second@2x.png │ │ └── unknown-user.imageset │ │ │ ├── Contents.json │ │ │ └── unknown-user.png │ ├── SecondViewController.h │ ├── SecondViewController.m │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── main.m │ ├── piBeacon-iphone-Info.plist │ ├── piBeacon-iphone-Prefix.pch │ └── piBeacon │ │ ├── ModelEngagement.h │ │ ├── ModelEngagement.m │ │ ├── piBeacon.h │ │ ├── piBeacon.m │ │ ├── piBeaconDetailViewController.h │ │ ├── piBeaconDetailViewController.m │ │ ├── piBeaconDetailViewController.xib │ │ ├── piBeaconProximityAlertViewController.h │ │ ├── piBeaconProximityAlertViewController.m │ │ ├── piBeaconProximityAlertViewController.xib │ │ ├── piBeaconUserDetailViewController.h │ │ ├── piBeaconUserDetailViewController.m │ │ └── piBeaconUserDetailViewController.xib └── piBeacon-iphoneTests │ ├── en.lproj │ └── InfoPlist.strings │ ├── piBeacon-iphoneTests-Info.plist │ └── piBeacon_iphoneTests.m ├── ibeacon-node-collector ├── app.js ├── app.json ├── boot │ └── init.js ├── datasources.json ├── models.json └── package.json └── screenshots ├── api-ibeacons.png ├── ble-analytics.png ├── ble-apps-2.png ├── ble-apps.png ├── ble-mobile-multi.png ├── ble-mobile.png ├── ble-ranging.png ├── console-run.png ├── estimote-ibeacon.png ├── explorer-ibeacons.png ├── image1.png ├── image2.png ├── loopback-explorer-beacon.png ├── loopback-explorer.png └── loopback-filter-near.png /DETAIL.md: -------------------------------------------------------------------------------- 1 | 2 | UNSTABLE - WORK IN PROGRESS 3 | 4 | 5 | Tracking mobile iBeacons and BlueTooth Low Energy engagements with Node.js 6 | -- 7 | 8 | ###iBeacons are Apples convention for handling Bluetooth Low Energy engagements 9 | 10 | iBeacons are Bluetooth Low Energy(BLE) wireless sensors that support a specific [HID profile schema ](https://developer.bluetooth.org/TechnologyOverview/Pages/HID.aspx) instead of the traditional [GATT profile ](http://en.wikipedia.org/wiki/Bluetooth_profile#Attribute_Profile_.28ATT.29). Additionally Apple iBeacons provide convention, libraries and integration into mobile location services. iBeacons breaks down BLE into 3 core features: broadcast, monitoring and ranging. 11 | 12 | Bluetooth Low Energy Energy Beacons have come into the world around us. Apple's integration of Bluetooth technology into branded iBeacons will inevitable proliferate the technology. Large implementations of the technology such as [ MLB's installation into ball parks ](http://techcrunch.com/2013/09/29/mlbs-ibeacon-experiment-may-signal-a-whole-new-ball-game-for-location-tracking/), and [PayPal's Beacon ](https://www.paypal.com/us/webapps/mpp/beacon ) payment system are making facilities and locations smart. Startups like [estimote](http://estimote.com) , [Brick Trends](http://bricktrends.com), [Pebble](http://pebble.com) are making it easier for developers and businesses to integrate the technology into their customers daily lives. All this is making your mobile device 'the new endpoint' and mobile application's more of a digital proxy for users interacting in real world. 13 | 14 | ###GPS gives devices 'vicinity' awareness, BLE iBeacons gives devices 'proximity' awareness 15 | 16 | Leveraging Bluetooth your mobile device can tell how far away your user is from a bluetooth 'beacon'. GPS gave mobile devices the power of vicinity; your device knows where it is with a neighborhood block accuracy (provided you had line of sight to a GPS satellite). This singular technology gave way to location targeted push notifications with geo fencing, time and location relevant mobile Ad's, geo caching games and of course everyone's favorite "Dude Where's my Car" mobile apps. 17 | 18 | BlueTooth LE and iBeacons will extend these use cases by illuminate the regions of our lives in the shadow of GPS line of Sight. In-store retail "brick" analytics (currently brick and mortar retailers have no idea where you are in their store or how your spending your time ) is likely to see the largest shift. 19 | 20 | Retail kiosks, end-caps, and payment terminals are blind, dumb and mute to your mobile device. Effectively **the urinal in the men's bathroom is smarter than your average retail kiosk; at least the urinal knew to flush when you stepped away**. iBeacons will make facilities, displays and the devices that power them aware of the mobile device ( and user ) in front of them. 21 | 22 | ### Location Aware devices are going to change Retail 23 | 24 | With [70 percent of smartphone shoppers use a store locator to plan their shopping trip](http://www.nielsen.com/us/en/newswire/2013/a-mobile-shoppers-journey--from-the-couch-to-the-store--and-back.html). Mobile apps will play an integral roll in store shopping experience. 25 | 26 | Retail and real world 'brick and mortar' vendors know the power of Mobile applications, justified by stats such as [Forty-six percent of shoppers say they are less likely to comparison shop when using a mobile app](http://www.comscore.com/Insights/Presentations_and_Whitepapers/2013/Choices_Channels_and_Convenience_Enhancing_the_Online_Shopping_Experience) 27 | 28 | Coupling purchases and the fact that [25 million Americans use Coupon apps each month](https://www.npd.com/wps/portal/npd/us/news/press-releases/pr_120523/) and the [prediction that the number of U.S. adult smartphone users who also use mobile coupons will jump to 40.8 million at the end of 2013](http://www.emarketer.com/Article/Digital-Coupons-Mobile-Give-Cheapskates-Staying-Power/1009847#Jy3uKPRgRE7lZiuJ.99) gives ecosystem opportunity around BLE and iBeacon technology. 29 | 30 | Bluetooth enabled accessories are projected to experience massive growth—220 million units this year to nearly 1 billion per year by 2016 (ABI Research) 31 | 32 | ###Why does Node Matter 33 | Bluetooth engagements can create analytic 'engagement' 100 packages every millisecond, and bursting this information to another mobile devices; possibly in the hands of retail associate. This information needs to be in the hands ( or devices ) of people that can engage with the potential customer in realtime. Pairing in store realtime analytics with shopper loyalty programs gives retail floor associates opportunity to engage at the moment of interest. Node apps can collect this information and trigger Push Notifications, email alerts and realtime at the time of opportunity. 34 | 35 | Additionally dashboards can give daily and realtime analytics to floor managers on which associates are effectively engaging with their customers. 36 | 37 | Node.js realtime low latency response and request architecture makes it a perfect collector, and aggregator for this information. Node can be deployed on the cloud or even in the facility on a device that is collecting this information. 38 | 39 | Combined with the variety of NPM modules available for displaying this data, delivering it cloud or storing it in databases or 3rd party analytics engines makes Node.js the perfect technology for the middle tier. Weather you are running the bluetooth sniffing Node application on site in a Raspberry Pi, a Laptop or as a cloud aggregator Node fits the need perfectly. 40 | 41 | ### How intro : 42 | 43 | All Bluetooth Low Energy devices (including iBeacons) are identified via a UUID (Device Identifier). Devices either operate as Central or a Peripheral configuration. The Mobile Application 'Herald' that goes along with this posting can operate as both a Central (connecting and interacting with Peripheral's in its proximity) and also as Peripheral allowing other Central's to discover and interact with it. 44 | 45 | The users iPhone and Android device acts as an moving blueTooth 'endpoint' in which the dynamic BLE 'network' discovers and connects to the application. Once the 'Herald' app on the users device connects and interacts with the beacon devices in the word; Herald will report back the interaction ( referred to as an engagement in this sample ) to the server. 46 | 47 | Since we want to share and report these interactions platform then your going to need to store the data on the Server. So I built a small node.js mobile servlet that catches the BLE Beacon engagement and stores the information for later analysis and review. 48 | 49 | If you want to test it out the mobile application is preconfigured to use a staged instance of the server; of course you can also stand up your own supporting server by deploying the LoopBack Node.js Server on your Cloud Provider of choice or on your own machine. 50 | 51 | ### How mobile client : iBeacon iPhone Application 52 | 53 | The [iBeacon iPhone Application](/client-iphone) is a simple native iOS application that allows configuration as a Central, a Peripheral or both. Once you download the github repo you can run the application from XCode in the simulator ( you will not be able to activate the BlueTooth features unless you have a secondary blueTooth device attached to your dev machine), or install on an iOS device connected to your host machine. 54 | 55 | The initial splash screen will give you an idea where the app name came from. The Second tab is where the magic happens. you can enable your iPhone to to 'Advertise', making your phone look like a Peripheral to other Central devices in the vicinity. Additionally you can enable 'BLE ranging' and your device will look for other iBeacons and report back the 'range' or proximity of the BLE Peripheral. The TextField below each of the switches shows the identification the device is advertising and ranging as. 56 | 57 | #### iPhone iBeacon Demo App 58 | 59 | tab Home 60 | tab Home 61 | 62 | You can find the source code on [github](http://github.com/mschmulen/tracking-bluetooth-ibeacons-with-node) and experiment with iBeacons and BLE devices yourself. 63 | 64 | 1. Start from simple Tab application 65 | 66 | 2. Add the iOS frameworkS 67 | CoreBluetooth.framework 68 | CoreLocation.framework 69 | 70 | ##### Generating your unique proximityUUID 71 | 72 | To genette a unique proximityUUID open the terminal and run the ```uuidgen``` tool. 73 | 74 | ``` 75 | AF23CFD3-1F95-42B8-8F2C-FEAC039D6F92 76 | ``` 77 | 78 | you can update the harald application with your unique proximityUUID by modifying the kUUID string in iBeaconViewController.m 79 | 80 | ``` 81 | static NSString * const kUUID = @"AF23CFD3-1F95-42B8-8F2C-FEAC039D6F92"; 82 | ``` 83 | 84 | major and minor 85 | 86 | ### Track you mobile BlueTooth engagements with a node.js servlet : 87 | 88 | TBD 89 | 90 | ### How hardware 91 | 92 | If you have 2 iOS7 devices then you can explore the interaction. Additionally if you have a BlueTooth embedded device such as the 93 | [Ti cc2540 & cc2541 sensor tag](http://www.ti.com/ww/en/wireless_connectivity/sensortag/index.shtml?DCMP=sensortag&HQS=sensortag-bn) then you can explore the use case as it would be for most real world use cases. Check out the [Ti SensorTag User Guide](http://processors.wiki.ti.com/index.php/SensorTag_User_Guide) for more information on the Ti sensor tag and kit. 94 | 95 | ** a quick note on debugging, ios7 will not allow you to debug via the simulator, so you will have debug through a connected iOS device ** 96 | 97 | Also check out some of these BLE device vendors that provide hardware beacon devices: 98 | 99 | - [redbearlab] (http://redbearlab.com/ibeacon/) 100 | - [kontakt.io](http://kontakt.io/) 101 | 102 | ### References 103 | 104 | --- 105 | 106 | Developer resources and reference documents 107 | 108 | - [corebluetooth-doesnt-let-you-see-ibeacons](http://developer.radiusnetworks.com/2013/10/21/corebluetooth-doesnt-let-you-see-ibeacons.html) 109 | - [Lost-and-Found Bluetooth Accessory 'Tile' Passes $1 Million in Pre-Orders](http://www.macrumors.com/2013/07/15/lost-and-found-bluetooth-accessory-tile-passes-1-million-in-pre-orders/) 110 | - [Android iBeacon Library](http://developer.radiusnetworks.com/ibeacon/android/) 111 | - [Bluetooth devices to gain notification support in iOS 7 & Mavericks with Apple's new APIs](http://appleinsider.com/articles/13/06/13/bluetooth-devices-to-gain-notification-support-in-ios-7-mavericks-with-apples-new-apis) 112 | - [With iBeacon, Apple is going to dump on NFC and embrace the internet of things](http://gigaom.com/2013/09/10/with-ibeacon-apple-is-going-to-dump-on-nfc-and-embrace-the-internet-of-things/) 113 | - [github.com/manishnath/iBeaconCenter](https://github.com/manishnath/iBeaconCenter) 114 | - [How to Make an iBeacon Out of a Raspberry Pi](http://developer.radiusnetworks.com/2013/10/09/how-to-make-an-ibeacon-out-of-a-raspberry-pi.html) 115 | - [http://stackoverflow.com/questions/16151360/use-bluez-stack-as-a-peripheral-advertiser/19039963#19039963](http://stackoverflow.com/questions/16151360/use-bluez-stack-as-a-peripheral-advertiser/19039963#19039963) 116 | - [whats-new-in-bluetooth-le-ios-7](http://www.doubleencore.com/2013/09/whats-new-in-bluetooth-le-ios-7/) 117 | - [few-ios-7-tidbits-you-probably-didn-t-hear-about](http://blog.greggant.com/post/62060213476/a-few-ios-7-tidbits-you-probably-didn-t-hear-about) 118 | - [developer.apple.com/AboutCoreBluetooth/Introduction.html](https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/AboutCoreBluetooth/Introduction.html#//apple_ref/doc/uid/TP40013257-CH1-SW1) 119 | - [Getting started with Xcode 4.x and Bluetooth Smart (BLE) on iOS](http://web.stalliance.no/blelogg/?page_id=52) 120 | - [BLE Tutorial 2](http://web.stalliance.no/blelogg/?page_id=180) 121 | - [A look at the CBCentralManager class of iOS](http://web.stalliance.no/blelogg/?page_id=131) 122 | - [iBeacons !](http://web.stalliance.no/blelogg/?p=269) 123 | - [Ti Bluetooth SensorTag ](http://processors.wiki.ti.com/index.php/Bluetooth_SensorTag?DCMP=lprf-stdroid&HQS=lprf-stdroid-pr-wiki1) 124 | 125 | 126 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Tracking mobile BlueTooth LE iBeacon engagements with Node.js 2 | -- 3 | 4 | ###iBeacons and Bluetooth Low Energy (BLE) 5 | Bluetooth Low Energy (BLE) beacons have come into the world around us with Apple’s branded iBeacon which gives branded convention and integration of the BLE devices. iBeacons break down BLE into 3 core features: broadcast, monitoring and ranging. 6 | 7 | tab 1 8 | 9 | iBeacon is similar in some ways to mobile GPS Geolocation services. Unlike GPS Geolocation, which gives mobile apps vicinity awareness (limited to outdoor scenarios that have line of sight to GPS satellites), BLE iBeacon gives mobile application’s proximity awareness from other iBeacon devices. The distance can be used to triangulate where the user is from a known fixed beacon location or identify if the user is within a predefined nominal “immediate”, “near” or “far” proximity to a device. 10 | 11 | tab 1 12 | 13 | ###Bluetooth proliferation 14 | The branding and assimilation of BLE into Apples iOS7 platform is causing a proliferation of Bluetooth ‘beacon-ing’ technology. Large implementations of the technology such as [ MLB's installation into ball parks ](http://techcrunch.com/2013/09/29/mlbs-ibeacon-experiment-may-signal-a-whole-new-ball-game-for-location-tracking/), and [PayPal's Beacon ](https://www.paypal.com/us/webapps/mpp/beacon ) payment system are making facilities and locations smart. Startups like [Estimote](http://), [Shelf Bucks](http://shelfbucks.com/), [Pebble](http://pebble.com) are making it easier for developers and businesses to integrate the technology into their customers’ daily lives and their mobile app’s. The technology is poised to forever change kiosks, retail end-caps, payment terminals and the facilities around us. Historically these engagement touch points were blind, dumb and mute to your mobile device. Historically *the restrooms in the bathroom were the smartest machine in your average retail facility; at least the toilet knew to flush when a person stepped away*. iBeacons will make stores, and the devices inside them aware of the mobile devices (more importantly user) in the facility. This gives analytics and insight into the previously dark world of “in store” behavior and engagement [changing everything in retail](http://www.forbes.com/sites/centurylink/2013/10/31/how-apples-ibeacon-will-change-everything-for-retail-analytics/) shopping experiences. 15 | 16 | ###You are your mobile ‘signature' 17 | When you open a BLE enabled mobile app your Blue Tooth ‘signature' tracks your location and behavior by your proximity to other BLE aware machines and devices. In a similar way to how a web cookie allows retailers to track your journey through a web site, your real world engagements can be tracked as you interact with BLE aware devices. 18 | 19 | ###The Power of Node.js 20 | Using StrongLoops [LoopBack](http://strongloop.com/mobile-application-development/loopback/) and the open source [bleacon npm](https://npmjs.org/package/bleacon) package it’s very easy to track an iBeacon enabled mobile app using Node.js. Will show you how to do this on your local machine and track the engagements from the machine interaction for later analysis and reporting. 21 | 22 | ###Tracking BLE engagements with 6 commands and 25 LOC 23 | You can build the demo on your own and see it run on a mac book pro (requires Mavericks) with Node.js by simply cloning the repo ‘git clone https://github.com/mschmulen/tracking-bluetooth-ibeacons-with-node’ and running it with ‘slc run app.js’ 24 | or build it from scratch by following the instructions below: 25 | 26 | **Commands:** 27 | 28 | ``` 29 | npm install -g strong-cli 30 | slc lb project ibeacon-node-collector 31 | cd ibeacon-node-collector 32 | npm install --save bleacon 33 | slc lb model ibeacon 34 | slc lb model engagement 35 | ``` 36 | 37 | The commands above installs the [strong-cli](http://https://npmjs.org/package/strong-cli)making giving us access to the ```slc lb``` commands to quickly scaffold an API tier and add our ```beacon``` and ```engagement``` data models. Installs the [bleacon](https://npmjs.org/package/bleacon) npm package and dependencies. 38 | 39 | **Code:** 40 | 41 | 42 | Create a folder /boot under the ibeacon-node-collector folder and a file init.js . Add the 10 lines of code below to the newly created ~/ibeacon-node-collector/boot/init.js file. 43 | 44 | ``` 45 | var ibeacon = app.models.ibeacon; 46 | var Bleacon = require('bleacon'); 47 | var ibeaconCache = new Array(); 48 | 49 | Bleacon.on('discover', function(bleacon) { 50 | console.log( bleacon ); 51 | 52 | var myID = 0; 53 | var guid = bleacon.uuid + bleacon.major + bleacon.minor; 54 | console.log ( guid + ":" + bleacon.uuid + "," + bleacon.major + "," + bleacon.minor ); 55 | 56 | if ( guid in ibeaconCache ) { myID = ibeaconCache[guid]; } 57 | 58 | ibeacon.upsert( 59 | { id: myID , guid:guid, uuid:bleacon.uuid, major:bleacon.major, minor:bleacon.minor}, 60 | function( error, _ibeacon) 61 | { 62 | ibeaconCache[guid] = _ibeacon.id; 63 | if ( error ) { console.log( "error on upsert " ); } 64 | else { 65 | console.log( "upsert - :" + _ibeacon.id + " guid " + _ibeacon.guid ); 66 | var eng = app.models.engagement; 67 | eng.create({ pBeaconID: _ibeacon.id, timestamp: Date.now(), rssi: bleacon.rssi, proximity: bleacon.proximity }); 68 | } //end else success 69 | }); //end upser 70 | 71 | var signal = [bleacon.rssi/5]; 72 | var xs = new Array(Math.floor(-bleacon.rssi/2) + 1).join('x'); 73 | console.log("rssi:" +xs); 74 | 75 | });//end on discover 76 | 77 | Bleacon.startScanning(); 78 | ``` 79 | 80 | Test the implementation by installing an app that has iBeacon support. I'm using the [Estimote Virtual Beacon on the App Store](https://itunes.apple.com/us/app/estimote-virtual-beacon/id686915066?mt=8) for this demo. 81 | 82 | Start the Estimote App in 'iBeacon broadcasting' mode. 83 | 84 | tab 1 85 | 86 | Run the node application on your host machine with 87 | 88 | ```slc run app.js``` 89 | 90 | In addition to entering the engagement in the in memory data store the code above will shows the BLE [ Received signal strength indication (RSSI) ](http://en.wikipedia.org/wiki/Received_signal_strength_indication) to the console log as your Node application receives Bleacon discover events. The RSSI value is used to determine the proximity (distance) of a BLE peripheral. 91 | 92 | tab 1 93 | 94 | ###Run your node app anywhere and persist the data to MongoDB 95 | 96 | Since the app is using Node can run the collector anywhere that supports the Node.js runtime, such as on a Raspberry-Pi. Allowing you to to create a simple “sniffer” device that when plugged into the wall will track all the Bluetooth engagements that occur in your home, office or store. 97 | 98 | If you want to persist your analytics data you can simply change the LoopBack model binding in ```datasources.json``` to point to supported data store such as MongoDB, MySQL, or Oracle. you can find more information on configuring your Node.js API to work with LoopBack supported data stores and connectors [in the StrongLoop documentation](http://docs.strongloop.com/display/DOC/Data+sources+and+connectors). 99 | 100 | Lets look at some of the beacon signatures and engagements that we have captured using the LoopBack Explorer feature on our local machine by opening [http://localhost:3000/explorer/](http://localhost:3000/explorer/) in our web browser. 101 | 102 | tab 1 103 | 104 | ###Search and filter API for engagement analysis 105 | 106 | Using the LoopBack API you can get all the beacon signatures in the system from JSON API endpoint at [http://localhost:3000/api/engagements](http://localhost:3000/api/engagements). 107 | 108 | tab 1 109 | 110 | We can also filter engagements based on a GUID using the built in 111 | [filter functionality] (http://localhost:3000/api/engagements?filter[where][cBeaconGUID]=87209302c7f24d56b1d114eadd0ce41f15) with the following url request ```http://localhost:3000/api/engagements?filter[where][id]=1``` . 112 | 113 | We can also do complex filtering against engagement [time] (http://localhost:3000/api/engagements?filter[where][id]=87209302c7f24d56b1d114eadd0ce41f15&filter[where][time][gt]=87209302c7f24d56b1d114eadd0ce41f16), [proximity] (http://localhost:3000/api/engagements?filter[where][proximity]=near ) or any mix of the available parameters. 114 | 115 | ``` http://localhost:3000/api/engagements?filter[where][id]=2&filter[where][proximity]=near ``` 116 | 117 | tab 1 118 | 119 | ###Identify anonymous mobile beacon signatures and track people 120 | 121 | Match the user to the anonymous signature and start tracking people within 100 feet of our machine. 122 | 123 | If you want to go the extra mile, simply use the built in LoopBack ```user model``` object by adding an index reference to the ```beacon model```. When you convert all the anonymous beacon signatures to known users the engagements analytics show real world user behavior. 124 | 125 | The conversion from an anonymous unknown user BLE iBeacon signature to known user behavior is the reason that retailers want you to open their customer loyalty app in the store and login. Binding your user profiler to the device and allowing them to track your in store loitering and behavior (and possibly target engagements at you) in the same way they track your shopping behaviors online. 126 | -------------------------------------------------------------------------------- /client-iphone/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/client-iphone/.DS_Store -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | AEB0E7B1186A7A83005475E0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AEB0E7B0186A7A83005475E0 /* Foundation.framework */; }; 11 | AEB0E7B3186A7A83005475E0 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AEB0E7B2186A7A83005475E0 /* CoreGraphics.framework */; }; 12 | AEB0E7B5186A7A83005475E0 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AEB0E7B4186A7A83005475E0 /* UIKit.framework */; }; 13 | AEB0E7BB186A7A83005475E0 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = AEB0E7B9186A7A83005475E0 /* InfoPlist.strings */; }; 14 | AEB0E7BD186A7A83005475E0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB0E7BC186A7A83005475E0 /* main.m */; }; 15 | AEB0E7C1186A7A83005475E0 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB0E7C0186A7A83005475E0 /* AppDelegate.m */; }; 16 | AEB0E7C4186A7A83005475E0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AEB0E7C2186A7A83005475E0 /* Main.storyboard */; }; 17 | AEB0E7C7186A7A83005475E0 /* FirstViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB0E7C6186A7A83005475E0 /* FirstViewController.m */; }; 18 | AEB0E7CA186A7A83005475E0 /* SecondViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB0E7C9186A7A83005475E0 /* SecondViewController.m */; }; 19 | AEB0E7CC186A7A83005475E0 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AEB0E7CB186A7A83005475E0 /* Images.xcassets */; }; 20 | AEB0E7D3186A7A83005475E0 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AEB0E7D2186A7A83005475E0 /* XCTest.framework */; }; 21 | AEB0E7D4186A7A83005475E0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AEB0E7B0186A7A83005475E0 /* Foundation.framework */; }; 22 | AEB0E7D5186A7A83005475E0 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AEB0E7B4186A7A83005475E0 /* UIKit.framework */; }; 23 | AEB0E7DD186A7A83005475E0 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = AEB0E7DB186A7A83005475E0 /* InfoPlist.strings */; }; 24 | AEB0E7DF186A7A83005475E0 /* piBeacon_iphoneTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB0E7DE186A7A83005475E0 /* piBeacon_iphoneTests.m */; }; 25 | AEB0E7E9186A7B82005475E0 /* CoreBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AEB0E7E8186A7B82005475E0 /* CoreBluetooth.framework */; }; 26 | AEB0E7EB186A7B89005475E0 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AEB0E7EA186A7B89005475E0 /* CoreLocation.framework */; }; 27 | AEB0E7EF186C9324005475E0 /* ModelEngagement.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB0E7EE186C9324005475E0 /* ModelEngagement.m */; }; 28 | AEB0E7F2186C94B3005475E0 /* piBeacon.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB0E7F1186C94B3005475E0 /* piBeacon.m */; }; 29 | AEB0E7F9186CD9E8005475E0 /* piBeaconDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB0E7F7186CD9E8005475E0 /* piBeaconDetailViewController.m */; }; 30 | AEB0E7FA186CD9E8005475E0 /* piBeaconDetailViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = AEB0E7F8186CD9E8005475E0 /* piBeaconDetailViewController.xib */; }; 31 | AEB0E7FE186CDAE9005475E0 /* piBeaconUserDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB0E7FC186CDAE9005475E0 /* piBeaconUserDetailViewController.m */; }; 32 | AEB0E7FF186CDAE9005475E0 /* piBeaconUserDetailViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = AEB0E7FD186CDAE9005475E0 /* piBeaconUserDetailViewController.xib */; }; 33 | AEB0E8031870B8FE005475E0 /* piBeaconProximityAlertViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AEB0E8011870B8FE005475E0 /* piBeaconProximityAlertViewController.m */; }; 34 | AEB0E8041870B8FE005475E0 /* piBeaconProximityAlertViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = AEB0E8021870B8FE005475E0 /* piBeaconProximityAlertViewController.xib */; }; 35 | /* End PBXBuildFile section */ 36 | 37 | /* Begin PBXContainerItemProxy section */ 38 | AEB0E7D6186A7A83005475E0 /* PBXContainerItemProxy */ = { 39 | isa = PBXContainerItemProxy; 40 | containerPortal = AEB0E7A5186A7A83005475E0 /* Project object */; 41 | proxyType = 1; 42 | remoteGlobalIDString = AEB0E7AC186A7A83005475E0; 43 | remoteInfo = "piBeacon-iphone"; 44 | }; 45 | /* End PBXContainerItemProxy section */ 46 | 47 | /* Begin PBXFileReference section */ 48 | AEB0E7AD186A7A83005475E0 /* piBeacon-iphone.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "piBeacon-iphone.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | AEB0E7B0186A7A83005475E0 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 50 | AEB0E7B2186A7A83005475E0 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 51 | AEB0E7B4186A7A83005475E0 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 52 | AEB0E7B8186A7A83005475E0 /* piBeacon-iphone-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "piBeacon-iphone-Info.plist"; sourceTree = ""; }; 53 | AEB0E7BA186A7A83005475E0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 54 | AEB0E7BC186A7A83005475E0 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 55 | AEB0E7BE186A7A83005475E0 /* piBeacon-iphone-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "piBeacon-iphone-Prefix.pch"; sourceTree = ""; }; 56 | AEB0E7BF186A7A83005475E0 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 57 | AEB0E7C0186A7A83005475E0 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 58 | AEB0E7C3186A7A83005475E0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 59 | AEB0E7C5186A7A83005475E0 /* FirstViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FirstViewController.h; sourceTree = ""; }; 60 | AEB0E7C6186A7A83005475E0 /* FirstViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FirstViewController.m; sourceTree = ""; }; 61 | AEB0E7C8186A7A83005475E0 /* SecondViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecondViewController.h; sourceTree = ""; }; 62 | AEB0E7C9186A7A83005475E0 /* SecondViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecondViewController.m; sourceTree = ""; }; 63 | AEB0E7CB186A7A83005475E0 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 64 | AEB0E7D1186A7A83005475E0 /* piBeacon-iphoneTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "piBeacon-iphoneTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 65 | AEB0E7D2186A7A83005475E0 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 66 | AEB0E7DA186A7A83005475E0 /* piBeacon-iphoneTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "piBeacon-iphoneTests-Info.plist"; sourceTree = ""; }; 67 | AEB0E7DC186A7A83005475E0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 68 | AEB0E7DE186A7A83005475E0 /* piBeacon_iphoneTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = piBeacon_iphoneTests.m; sourceTree = ""; }; 69 | AEB0E7E8186A7B82005475E0 /* CoreBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBluetooth.framework; path = System/Library/Frameworks/CoreBluetooth.framework; sourceTree = SDKROOT; }; 70 | AEB0E7EA186A7B89005475E0 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; 71 | AEB0E7ED186C9324005475E0 /* ModelEngagement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModelEngagement.h; sourceTree = ""; }; 72 | AEB0E7EE186C9324005475E0 /* ModelEngagement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ModelEngagement.m; sourceTree = ""; }; 73 | AEB0E7F0186C94B3005475E0 /* piBeacon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = piBeacon.h; sourceTree = ""; }; 74 | AEB0E7F1186C94B3005475E0 /* piBeacon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = piBeacon.m; sourceTree = ""; }; 75 | AEB0E7F6186CD9E8005475E0 /* piBeaconDetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = piBeaconDetailViewController.h; sourceTree = ""; }; 76 | AEB0E7F7186CD9E8005475E0 /* piBeaconDetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = piBeaconDetailViewController.m; sourceTree = ""; }; 77 | AEB0E7F8186CD9E8005475E0 /* piBeaconDetailViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = piBeaconDetailViewController.xib; sourceTree = ""; }; 78 | AEB0E7FB186CDAE9005475E0 /* piBeaconUserDetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = piBeaconUserDetailViewController.h; sourceTree = ""; }; 79 | AEB0E7FC186CDAE9005475E0 /* piBeaconUserDetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = piBeaconUserDetailViewController.m; sourceTree = ""; }; 80 | AEB0E7FD186CDAE9005475E0 /* piBeaconUserDetailViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = piBeaconUserDetailViewController.xib; sourceTree = ""; }; 81 | AEB0E8001870B8FE005475E0 /* piBeaconProximityAlertViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = piBeaconProximityAlertViewController.h; sourceTree = ""; }; 82 | AEB0E8011870B8FE005475E0 /* piBeaconProximityAlertViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = piBeaconProximityAlertViewController.m; sourceTree = ""; }; 83 | AEB0E8021870B8FE005475E0 /* piBeaconProximityAlertViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = piBeaconProximityAlertViewController.xib; sourceTree = ""; }; 84 | /* End PBXFileReference section */ 85 | 86 | /* Begin PBXFrameworksBuildPhase section */ 87 | AEB0E7AA186A7A83005475E0 /* Frameworks */ = { 88 | isa = PBXFrameworksBuildPhase; 89 | buildActionMask = 2147483647; 90 | files = ( 91 | AEB0E7EB186A7B89005475E0 /* CoreLocation.framework in Frameworks */, 92 | AEB0E7E9186A7B82005475E0 /* CoreBluetooth.framework in Frameworks */, 93 | AEB0E7B3186A7A83005475E0 /* CoreGraphics.framework in Frameworks */, 94 | AEB0E7B5186A7A83005475E0 /* UIKit.framework in Frameworks */, 95 | AEB0E7B1186A7A83005475E0 /* Foundation.framework in Frameworks */, 96 | ); 97 | runOnlyForDeploymentPostprocessing = 0; 98 | }; 99 | AEB0E7CE186A7A83005475E0 /* Frameworks */ = { 100 | isa = PBXFrameworksBuildPhase; 101 | buildActionMask = 2147483647; 102 | files = ( 103 | AEB0E7D3186A7A83005475E0 /* XCTest.framework in Frameworks */, 104 | AEB0E7D5186A7A83005475E0 /* UIKit.framework in Frameworks */, 105 | AEB0E7D4186A7A83005475E0 /* Foundation.framework in Frameworks */, 106 | ); 107 | runOnlyForDeploymentPostprocessing = 0; 108 | }; 109 | /* End PBXFrameworksBuildPhase section */ 110 | 111 | /* Begin PBXGroup section */ 112 | AEB0E7A4186A7A83005475E0 = { 113 | isa = PBXGroup; 114 | children = ( 115 | AEB0E7B6186A7A83005475E0 /* piBeacon-iphone */, 116 | AEB0E7D8186A7A83005475E0 /* piBeacon-iphoneTests */, 117 | AEB0E7AF186A7A83005475E0 /* Frameworks */, 118 | AEB0E7AE186A7A83005475E0 /* Products */, 119 | ); 120 | sourceTree = ""; 121 | }; 122 | AEB0E7AE186A7A83005475E0 /* Products */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | AEB0E7AD186A7A83005475E0 /* piBeacon-iphone.app */, 126 | AEB0E7D1186A7A83005475E0 /* piBeacon-iphoneTests.xctest */, 127 | ); 128 | name = Products; 129 | sourceTree = ""; 130 | }; 131 | AEB0E7AF186A7A83005475E0 /* Frameworks */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | AEB0E7EA186A7B89005475E0 /* CoreLocation.framework */, 135 | AEB0E7E8186A7B82005475E0 /* CoreBluetooth.framework */, 136 | AEB0E7B0186A7A83005475E0 /* Foundation.framework */, 137 | AEB0E7B2186A7A83005475E0 /* CoreGraphics.framework */, 138 | AEB0E7B4186A7A83005475E0 /* UIKit.framework */, 139 | AEB0E7D2186A7A83005475E0 /* XCTest.framework */, 140 | ); 141 | name = Frameworks; 142 | sourceTree = ""; 143 | }; 144 | AEB0E7B6186A7A83005475E0 /* piBeacon-iphone */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | AEB0E7BF186A7A83005475E0 /* AppDelegate.h */, 148 | AEB0E7C0186A7A83005475E0 /* AppDelegate.m */, 149 | AEB0E7C2186A7A83005475E0 /* Main.storyboard */, 150 | AEB0E7C5186A7A83005475E0 /* FirstViewController.h */, 151 | AEB0E7C6186A7A83005475E0 /* FirstViewController.m */, 152 | AEB0E7C8186A7A83005475E0 /* SecondViewController.h */, 153 | AEB0E7C9186A7A83005475E0 /* SecondViewController.m */, 154 | AEB0E7EC186C9324005475E0 /* piBeacon */, 155 | AEB0E7CB186A7A83005475E0 /* Images.xcassets */, 156 | AEB0E7B7186A7A83005475E0 /* Supporting Files */, 157 | ); 158 | path = "piBeacon-iphone"; 159 | sourceTree = ""; 160 | }; 161 | AEB0E7B7186A7A83005475E0 /* Supporting Files */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | AEB0E7B8186A7A83005475E0 /* piBeacon-iphone-Info.plist */, 165 | AEB0E7B9186A7A83005475E0 /* InfoPlist.strings */, 166 | AEB0E7BC186A7A83005475E0 /* main.m */, 167 | AEB0E7BE186A7A83005475E0 /* piBeacon-iphone-Prefix.pch */, 168 | ); 169 | name = "Supporting Files"; 170 | sourceTree = ""; 171 | }; 172 | AEB0E7D8186A7A83005475E0 /* piBeacon-iphoneTests */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | AEB0E7DE186A7A83005475E0 /* piBeacon_iphoneTests.m */, 176 | AEB0E7D9186A7A83005475E0 /* Supporting Files */, 177 | ); 178 | path = "piBeacon-iphoneTests"; 179 | sourceTree = ""; 180 | }; 181 | AEB0E7D9186A7A83005475E0 /* Supporting Files */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | AEB0E7DA186A7A83005475E0 /* piBeacon-iphoneTests-Info.plist */, 185 | AEB0E7DB186A7A83005475E0 /* InfoPlist.strings */, 186 | ); 187 | name = "Supporting Files"; 188 | sourceTree = ""; 189 | }; 190 | AEB0E7EC186C9324005475E0 /* piBeacon */ = { 191 | isa = PBXGroup; 192 | children = ( 193 | AEB0E7F0186C94B3005475E0 /* piBeacon.h */, 194 | AEB0E7F1186C94B3005475E0 /* piBeacon.m */, 195 | AEB0E7ED186C9324005475E0 /* ModelEngagement.h */, 196 | AEB0E7EE186C9324005475E0 /* ModelEngagement.m */, 197 | AEB0E7F6186CD9E8005475E0 /* piBeaconDetailViewController.h */, 198 | AEB0E7F7186CD9E8005475E0 /* piBeaconDetailViewController.m */, 199 | AEB0E7F8186CD9E8005475E0 /* piBeaconDetailViewController.xib */, 200 | AEB0E7FB186CDAE9005475E0 /* piBeaconUserDetailViewController.h */, 201 | AEB0E7FC186CDAE9005475E0 /* piBeaconUserDetailViewController.m */, 202 | AEB0E7FD186CDAE9005475E0 /* piBeaconUserDetailViewController.xib */, 203 | AEB0E8001870B8FE005475E0 /* piBeaconProximityAlertViewController.h */, 204 | AEB0E8011870B8FE005475E0 /* piBeaconProximityAlertViewController.m */, 205 | AEB0E8021870B8FE005475E0 /* piBeaconProximityAlertViewController.xib */, 206 | ); 207 | path = piBeacon; 208 | sourceTree = ""; 209 | }; 210 | /* End PBXGroup section */ 211 | 212 | /* Begin PBXNativeTarget section */ 213 | AEB0E7AC186A7A83005475E0 /* piBeacon-iphone */ = { 214 | isa = PBXNativeTarget; 215 | buildConfigurationList = AEB0E7E2186A7A83005475E0 /* Build configuration list for PBXNativeTarget "piBeacon-iphone" */; 216 | buildPhases = ( 217 | AEB0E7A9186A7A83005475E0 /* Sources */, 218 | AEB0E7AA186A7A83005475E0 /* Frameworks */, 219 | AEB0E7AB186A7A83005475E0 /* Resources */, 220 | ); 221 | buildRules = ( 222 | ); 223 | dependencies = ( 224 | ); 225 | name = "piBeacon-iphone"; 226 | productName = "piBeacon-iphone"; 227 | productReference = AEB0E7AD186A7A83005475E0 /* piBeacon-iphone.app */; 228 | productType = "com.apple.product-type.application"; 229 | }; 230 | AEB0E7D0186A7A83005475E0 /* piBeacon-iphoneTests */ = { 231 | isa = PBXNativeTarget; 232 | buildConfigurationList = AEB0E7E5186A7A83005475E0 /* Build configuration list for PBXNativeTarget "piBeacon-iphoneTests" */; 233 | buildPhases = ( 234 | AEB0E7CD186A7A83005475E0 /* Sources */, 235 | AEB0E7CE186A7A83005475E0 /* Frameworks */, 236 | AEB0E7CF186A7A83005475E0 /* Resources */, 237 | ); 238 | buildRules = ( 239 | ); 240 | dependencies = ( 241 | AEB0E7D7186A7A83005475E0 /* PBXTargetDependency */, 242 | ); 243 | name = "piBeacon-iphoneTests"; 244 | productName = "piBeacon-iphoneTests"; 245 | productReference = AEB0E7D1186A7A83005475E0 /* piBeacon-iphoneTests.xctest */; 246 | productType = "com.apple.product-type.bundle.unit-test"; 247 | }; 248 | /* End PBXNativeTarget section */ 249 | 250 | /* Begin PBXProject section */ 251 | AEB0E7A5186A7A83005475E0 /* Project object */ = { 252 | isa = PBXProject; 253 | attributes = { 254 | LastUpgradeCheck = 0500; 255 | ORGANIZATIONNAME = "Matt Schmulen"; 256 | TargetAttributes = { 257 | AEB0E7AC186A7A83005475E0 = { 258 | SystemCapabilities = { 259 | com.apple.BackgroundModes = { 260 | enabled = 1; 261 | }; 262 | }; 263 | }; 264 | AEB0E7D0186A7A83005475E0 = { 265 | TestTargetID = AEB0E7AC186A7A83005475E0; 266 | }; 267 | }; 268 | }; 269 | buildConfigurationList = AEB0E7A8186A7A83005475E0 /* Build configuration list for PBXProject "piBeacon-iphone" */; 270 | compatibilityVersion = "Xcode 3.2"; 271 | developmentRegion = English; 272 | hasScannedForEncodings = 0; 273 | knownRegions = ( 274 | en, 275 | Base, 276 | ); 277 | mainGroup = AEB0E7A4186A7A83005475E0; 278 | productRefGroup = AEB0E7AE186A7A83005475E0 /* Products */; 279 | projectDirPath = ""; 280 | projectRoot = ""; 281 | targets = ( 282 | AEB0E7AC186A7A83005475E0 /* piBeacon-iphone */, 283 | AEB0E7D0186A7A83005475E0 /* piBeacon-iphoneTests */, 284 | ); 285 | }; 286 | /* End PBXProject section */ 287 | 288 | /* Begin PBXResourcesBuildPhase section */ 289 | AEB0E7AB186A7A83005475E0 /* Resources */ = { 290 | isa = PBXResourcesBuildPhase; 291 | buildActionMask = 2147483647; 292 | files = ( 293 | AEB0E8041870B8FE005475E0 /* piBeaconProximityAlertViewController.xib in Resources */, 294 | AEB0E7FA186CD9E8005475E0 /* piBeaconDetailViewController.xib in Resources */, 295 | AEB0E7CC186A7A83005475E0 /* Images.xcassets in Resources */, 296 | AEB0E7BB186A7A83005475E0 /* InfoPlist.strings in Resources */, 297 | AEB0E7C4186A7A83005475E0 /* Main.storyboard in Resources */, 298 | AEB0E7FF186CDAE9005475E0 /* piBeaconUserDetailViewController.xib in Resources */, 299 | ); 300 | runOnlyForDeploymentPostprocessing = 0; 301 | }; 302 | AEB0E7CF186A7A83005475E0 /* Resources */ = { 303 | isa = PBXResourcesBuildPhase; 304 | buildActionMask = 2147483647; 305 | files = ( 306 | AEB0E7DD186A7A83005475E0 /* InfoPlist.strings in Resources */, 307 | ); 308 | runOnlyForDeploymentPostprocessing = 0; 309 | }; 310 | /* End PBXResourcesBuildPhase section */ 311 | 312 | /* Begin PBXSourcesBuildPhase section */ 313 | AEB0E7A9186A7A83005475E0 /* Sources */ = { 314 | isa = PBXSourcesBuildPhase; 315 | buildActionMask = 2147483647; 316 | files = ( 317 | AEB0E7FE186CDAE9005475E0 /* piBeaconUserDetailViewController.m in Sources */, 318 | AEB0E7CA186A7A83005475E0 /* SecondViewController.m in Sources */, 319 | AEB0E7C1186A7A83005475E0 /* AppDelegate.m in Sources */, 320 | AEB0E7C7186A7A83005475E0 /* FirstViewController.m in Sources */, 321 | AEB0E7F9186CD9E8005475E0 /* piBeaconDetailViewController.m in Sources */, 322 | AEB0E7EF186C9324005475E0 /* ModelEngagement.m in Sources */, 323 | AEB0E8031870B8FE005475E0 /* piBeaconProximityAlertViewController.m in Sources */, 324 | AEB0E7F2186C94B3005475E0 /* piBeacon.m in Sources */, 325 | AEB0E7BD186A7A83005475E0 /* main.m in Sources */, 326 | ); 327 | runOnlyForDeploymentPostprocessing = 0; 328 | }; 329 | AEB0E7CD186A7A83005475E0 /* Sources */ = { 330 | isa = PBXSourcesBuildPhase; 331 | buildActionMask = 2147483647; 332 | files = ( 333 | AEB0E7DF186A7A83005475E0 /* piBeacon_iphoneTests.m in Sources */, 334 | ); 335 | runOnlyForDeploymentPostprocessing = 0; 336 | }; 337 | /* End PBXSourcesBuildPhase section */ 338 | 339 | /* Begin PBXTargetDependency section */ 340 | AEB0E7D7186A7A83005475E0 /* PBXTargetDependency */ = { 341 | isa = PBXTargetDependency; 342 | target = AEB0E7AC186A7A83005475E0 /* piBeacon-iphone */; 343 | targetProxy = AEB0E7D6186A7A83005475E0 /* PBXContainerItemProxy */; 344 | }; 345 | /* End PBXTargetDependency section */ 346 | 347 | /* Begin PBXVariantGroup section */ 348 | AEB0E7B9186A7A83005475E0 /* InfoPlist.strings */ = { 349 | isa = PBXVariantGroup; 350 | children = ( 351 | AEB0E7BA186A7A83005475E0 /* en */, 352 | ); 353 | name = InfoPlist.strings; 354 | sourceTree = ""; 355 | }; 356 | AEB0E7C2186A7A83005475E0 /* Main.storyboard */ = { 357 | isa = PBXVariantGroup; 358 | children = ( 359 | AEB0E7C3186A7A83005475E0 /* Base */, 360 | ); 361 | name = Main.storyboard; 362 | sourceTree = ""; 363 | }; 364 | AEB0E7DB186A7A83005475E0 /* InfoPlist.strings */ = { 365 | isa = PBXVariantGroup; 366 | children = ( 367 | AEB0E7DC186A7A83005475E0 /* en */, 368 | ); 369 | name = InfoPlist.strings; 370 | sourceTree = ""; 371 | }; 372 | /* End PBXVariantGroup section */ 373 | 374 | /* Begin XCBuildConfiguration section */ 375 | AEB0E7E0186A7A83005475E0 /* Debug */ = { 376 | isa = XCBuildConfiguration; 377 | buildSettings = { 378 | ALWAYS_SEARCH_USER_PATHS = NO; 379 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 380 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 381 | CLANG_CXX_LIBRARY = "libc++"; 382 | CLANG_ENABLE_MODULES = YES; 383 | CLANG_ENABLE_OBJC_ARC = YES; 384 | CLANG_WARN_BOOL_CONVERSION = YES; 385 | CLANG_WARN_CONSTANT_CONVERSION = YES; 386 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 387 | CLANG_WARN_EMPTY_BODY = YES; 388 | CLANG_WARN_ENUM_CONVERSION = YES; 389 | CLANG_WARN_INT_CONVERSION = YES; 390 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 391 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 392 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 393 | COPY_PHASE_STRIP = NO; 394 | GCC_C_LANGUAGE_STANDARD = gnu99; 395 | GCC_DYNAMIC_NO_PIC = NO; 396 | GCC_OPTIMIZATION_LEVEL = 0; 397 | GCC_PREPROCESSOR_DEFINITIONS = ( 398 | "DEBUG=1", 399 | "$(inherited)", 400 | ); 401 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 402 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 403 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 404 | GCC_WARN_UNDECLARED_SELECTOR = YES; 405 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 406 | GCC_WARN_UNUSED_FUNCTION = YES; 407 | GCC_WARN_UNUSED_VARIABLE = YES; 408 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 409 | ONLY_ACTIVE_ARCH = YES; 410 | SDKROOT = iphoneos; 411 | }; 412 | name = Debug; 413 | }; 414 | AEB0E7E1186A7A83005475E0 /* Release */ = { 415 | isa = XCBuildConfiguration; 416 | buildSettings = { 417 | ALWAYS_SEARCH_USER_PATHS = NO; 418 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 419 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 420 | CLANG_CXX_LIBRARY = "libc++"; 421 | CLANG_ENABLE_MODULES = YES; 422 | CLANG_ENABLE_OBJC_ARC = YES; 423 | CLANG_WARN_BOOL_CONVERSION = YES; 424 | CLANG_WARN_CONSTANT_CONVERSION = YES; 425 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 426 | CLANG_WARN_EMPTY_BODY = YES; 427 | CLANG_WARN_ENUM_CONVERSION = YES; 428 | CLANG_WARN_INT_CONVERSION = YES; 429 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 430 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 431 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 432 | COPY_PHASE_STRIP = YES; 433 | ENABLE_NS_ASSERTIONS = NO; 434 | GCC_C_LANGUAGE_STANDARD = gnu99; 435 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 436 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 437 | GCC_WARN_UNDECLARED_SELECTOR = YES; 438 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 439 | GCC_WARN_UNUSED_FUNCTION = YES; 440 | GCC_WARN_UNUSED_VARIABLE = YES; 441 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 442 | SDKROOT = iphoneos; 443 | VALIDATE_PRODUCT = YES; 444 | }; 445 | name = Release; 446 | }; 447 | AEB0E7E3186A7A83005475E0 /* Debug */ = { 448 | isa = XCBuildConfiguration; 449 | buildSettings = { 450 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 451 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 452 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 453 | GCC_PREFIX_HEADER = "piBeacon-iphone/piBeacon-iphone-Prefix.pch"; 454 | INFOPLIST_FILE = "piBeacon-iphone/piBeacon-iphone-Info.plist"; 455 | PRODUCT_NAME = "$(TARGET_NAME)"; 456 | WRAPPER_EXTENSION = app; 457 | }; 458 | name = Debug; 459 | }; 460 | AEB0E7E4186A7A83005475E0 /* Release */ = { 461 | isa = XCBuildConfiguration; 462 | buildSettings = { 463 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 464 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 465 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 466 | GCC_PREFIX_HEADER = "piBeacon-iphone/piBeacon-iphone-Prefix.pch"; 467 | INFOPLIST_FILE = "piBeacon-iphone/piBeacon-iphone-Info.plist"; 468 | PRODUCT_NAME = "$(TARGET_NAME)"; 469 | WRAPPER_EXTENSION = app; 470 | }; 471 | name = Release; 472 | }; 473 | AEB0E7E6186A7A83005475E0 /* Debug */ = { 474 | isa = XCBuildConfiguration; 475 | buildSettings = { 476 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 477 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/piBeacon-iphone.app/piBeacon-iphone"; 478 | FRAMEWORK_SEARCH_PATHS = ( 479 | "$(SDKROOT)/Developer/Library/Frameworks", 480 | "$(inherited)", 481 | "$(DEVELOPER_FRAMEWORKS_DIR)", 482 | ); 483 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 484 | GCC_PREFIX_HEADER = "piBeacon-iphone/piBeacon-iphone-Prefix.pch"; 485 | GCC_PREPROCESSOR_DEFINITIONS = ( 486 | "DEBUG=1", 487 | "$(inherited)", 488 | ); 489 | INFOPLIST_FILE = "piBeacon-iphoneTests/piBeacon-iphoneTests-Info.plist"; 490 | PRODUCT_NAME = "$(TARGET_NAME)"; 491 | TEST_HOST = "$(BUNDLE_LOADER)"; 492 | WRAPPER_EXTENSION = xctest; 493 | }; 494 | name = Debug; 495 | }; 496 | AEB0E7E7186A7A83005475E0 /* Release */ = { 497 | isa = XCBuildConfiguration; 498 | buildSettings = { 499 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 500 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/piBeacon-iphone.app/piBeacon-iphone"; 501 | FRAMEWORK_SEARCH_PATHS = ( 502 | "$(SDKROOT)/Developer/Library/Frameworks", 503 | "$(inherited)", 504 | "$(DEVELOPER_FRAMEWORKS_DIR)", 505 | ); 506 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 507 | GCC_PREFIX_HEADER = "piBeacon-iphone/piBeacon-iphone-Prefix.pch"; 508 | INFOPLIST_FILE = "piBeacon-iphoneTests/piBeacon-iphoneTests-Info.plist"; 509 | PRODUCT_NAME = "$(TARGET_NAME)"; 510 | TEST_HOST = "$(BUNDLE_LOADER)"; 511 | WRAPPER_EXTENSION = xctest; 512 | }; 513 | name = Release; 514 | }; 515 | /* End XCBuildConfiguration section */ 516 | 517 | /* Begin XCConfigurationList section */ 518 | AEB0E7A8186A7A83005475E0 /* Build configuration list for PBXProject "piBeacon-iphone" */ = { 519 | isa = XCConfigurationList; 520 | buildConfigurations = ( 521 | AEB0E7E0186A7A83005475E0 /* Debug */, 522 | AEB0E7E1186A7A83005475E0 /* Release */, 523 | ); 524 | defaultConfigurationIsVisible = 0; 525 | defaultConfigurationName = Release; 526 | }; 527 | AEB0E7E2186A7A83005475E0 /* Build configuration list for PBXNativeTarget "piBeacon-iphone" */ = { 528 | isa = XCConfigurationList; 529 | buildConfigurations = ( 530 | AEB0E7E3186A7A83005475E0 /* Debug */, 531 | AEB0E7E4186A7A83005475E0 /* Release */, 532 | ); 533 | defaultConfigurationIsVisible = 0; 534 | defaultConfigurationName = Release; 535 | }; 536 | AEB0E7E5186A7A83005475E0 /* Build configuration list for PBXNativeTarget "piBeacon-iphoneTests" */ = { 537 | isa = XCConfigurationList; 538 | buildConfigurations = ( 539 | AEB0E7E6186A7A83005475E0 /* Debug */, 540 | AEB0E7E7186A7A83005475E0 /* Release */, 541 | ); 542 | defaultConfigurationIsVisible = 0; 543 | defaultConfigurationName = Release; 544 | }; 545 | /* End XCConfigurationList section */ 546 | }; 547 | rootObject = AEB0E7A5186A7A83005475E0 /* Project object */; 548 | } 549 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone.xcodeproj/project.xcworkspace/xcuserdata/matt.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/client-iphone/piBeacon-iphone.xcodeproj/project.xcworkspace/xcuserdata/matt.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone.xcodeproj/xcuserdata/matt.xcuserdatad/xcschemes/piBeacon-iphone.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone.xcodeproj/xcuserdata/matt.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | piBeacon-iphone.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | AEB0E7AC186A7A83005475E0 16 | 17 | primary 18 | 19 | 20 | AEB0E7D0186A7A83005475E0 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // piBeacon-iphone 4 | // 5 | // Created by Matt Schmulen on 12/24/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // piBeacon-iphone 4 | // 5 | // Created by Matt Schmulen on 12/24/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 49 | 55 | 61 | 68 | 69 | 70 | 71 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 119 | 125 | 126 | 127 | 128 | 129 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/FirstViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // FirstViewController.h 3 | // piBeacon-iphone 4 | // 5 | // Created by Matt Schmulen on 12/24/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "piBeacon.h" 11 | 12 | @interface FirstViewController : UIViewController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/FirstViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // FirstViewController.m 3 | // piBeacon-iphone 4 | // 5 | // Created by Matt Schmulen on 12/24/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import "FirstViewController.h" 10 | 11 | @interface FirstViewController () 12 | 13 | @property ( nonatomic ) UIDynamicAnimator* animator; 14 | @property ( nonatomic ) UIGravityBehavior* gravity; 15 | @property ( nonatomic ) UICollisionBehavior* collisionBehavior; 16 | 17 | @end 18 | 19 | @implementation FirstViewController 20 | 21 | - (IBAction)actionTest:(id)sender { 22 | NSLog(@"action Test"); 23 | 24 | [piBeacon simulateProximityEvent]; 25 | 26 | // piBeaconProximityAlertViewController* vController = [[piBeaconProximityAlertViewController alloc] init]; 27 | //[self presentViewController:vController animated:YES completion:nil]; 28 | } 29 | 30 | - (void) receiveNewEngagementNotification:(NSNotification *) notification 31 | { 32 | NSLog (@"Successfully received notification!"); 33 | 34 | if ([[notification name] isEqualToString:notification_NewEngagement]){ 35 | NSLog (@"Successfully received the engagement notification!"); 36 | 37 | piBeaconProximityAlertViewController* vController = [[piBeaconProximityAlertViewController alloc] init]; 38 | [self presentViewController:vController animated:YES completion:nil]; 39 | } 40 | 41 | //ModelEngagement *engagement = notification.object; 42 | //[self.tableData addObject:engagement]; 43 | //[self.myTableView reloadData]; 44 | } 45 | 46 | -(void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id)item withBoundaryIdentifier:(id)identifier atPoint:(CGPoint)p 47 | { 48 | // Lighten the background color when the view is in contact with a boundary. 49 | [(UIView*)item setBackgroundColor:[UIColor lightGrayColor]]; 50 | } 51 | 52 | 53 | -(void)collisionBehavior:(UICollisionBehavior *)behavior endedContactForItem:(id)item withBoundaryIdentifier:(id)identifier 54 | { 55 | // Restore the default color when ending a contcact. 56 | [(UIView*)item setBackgroundColor:[UIColor grayColor]]; 57 | } 58 | 59 | - (void)viewDidLoad 60 | { 61 | [super viewDidLoad]; 62 | // Do any additional setup after loading the view, typically from a nib. 63 | 64 | //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNewEngagementNotification:) name:notification_NewEngagement object:nil]; 65 | 66 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNewEngagementNotification:) name:notification_NewEngagement object:nil]; 67 | 68 | // ------------------ 69 | //Configure dynamics 70 | //configure 71 | //_animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; 72 | //_gravity = [[UIGravityBehavior alloc] initWithItems:@[self.imageViewBeaconNotify]]; 73 | 74 | //configure the collision behavior 75 | //_collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[self.imageViewBeaconNotify]]; 76 | //_collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; 77 | 78 | //run the animation 79 | //[_animator addBehavior:_gravity]; 80 | //[_animator addBehavior:_collisionBehavior]; 81 | //_collisionBehavior.collisionDelegate = self; 82 | // ------------------ 83 | 84 | } 85 | 86 | - (void)didReceiveMemoryWarning 87 | { 88 | [super didReceiveMemoryWarning]; 89 | // Dispose of any resources that can be recreated. 90 | } 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/Images.xcassets/first.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "first.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "first@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/Images.xcassets/first.imageset/first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/client-iphone/piBeacon-iphone/Images.xcassets/first.imageset/first.png -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/Images.xcassets/first.imageset/first@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/client-iphone/piBeacon-iphone/Images.xcassets/first.imageset/first@2x.png -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/Images.xcassets/second.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "second.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "second@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/Images.xcassets/second.imageset/second.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/client-iphone/piBeacon-iphone/Images.xcassets/second.imageset/second.png -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/Images.xcassets/second.imageset/second@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/client-iphone/piBeacon-iphone/Images.xcassets/second.imageset/second@2x.png -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/Images.xcassets/unknown-user.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "unknown-user.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/Images.xcassets/unknown-user.imageset/unknown-user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/client-iphone/piBeacon-iphone/Images.xcassets/unknown-user.imageset/unknown-user.png -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/SecondViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SecondViewController.h 3 | // piBeacon-iphone 4 | // 5 | // Created by Matt Schmulen on 12/24/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | @interface SecondViewController : UIViewController < UITableViewDelegate, UITableViewDataSource, CLLocationManagerDelegate, CBPeripheralManagerDelegate> 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/SecondViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SecondViewController.m 3 | // piBeacon-iphone 4 | // 5 | // Created by Matt Schmulen on 12/24/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import "SecondViewController.h" 10 | #import "piBeacon.h" 11 | 12 | // TableView Cell Identifier 13 | static NSString * const kCellIdentifier = @"iBeaconCell"; 14 | 15 | @interface SecondViewController () 16 | 17 | @property (weak, nonatomic) IBOutlet UISwitch *switchAdvertising; 18 | @property (weak, nonatomic) IBOutlet UISwitch *switchRanging; 19 | @property (weak, nonatomic) IBOutlet UITextField *textFieldUUID; 20 | @property (weak, nonatomic) IBOutlet UITextField *textFieldBeaconRegionID; 21 | @property (weak, nonatomic) IBOutlet UITableView *myTableView; 22 | 23 | 24 | @property (strong, nonatomic) piBeacon *piBeacon; 25 | 26 | @property ( strong, nonatomic ) NSArray *tableData; 27 | @property (nonatomic, strong) CLBeaconRegion *beaconRegion; 28 | @property (nonatomic, strong) CBPeripheralManager *peripheralManager; 29 | @property (nonatomic, strong) CLLocationManager *locationManager; 30 | 31 | @end 32 | 33 | @implementation SecondViewController 34 | 35 | - (NSArray *) tableData 36 | { 37 | if (! _tableData ) _tableData = [[NSArray alloc] init]; 38 | return _tableData; 39 | } 40 | 41 | - (piBeacon *) piBeacon 42 | { 43 | if (! _piBeacon ) { 44 | _piBeacon = [[piBeacon alloc] init]; 45 | [_piBeacon initWithConfig:@"87209302-C7F2-4D56-B1D1-14EADD0CE41F" beaconRegionId:@"org.pibeacon" beaconMajor:1 beaconMinor:1]; 46 | } 47 | return _piBeacon; 48 | } 49 | 50 | 51 | 52 | #pragma mark - Beacon ranging 53 | - (void)createBeaconRegion 54 | { 55 | if (self.beaconRegion) 56 | return; 57 | 58 | NSUUID *proximityUUID = [[NSUUID alloc] initWithUUIDString:self.piBeacon.piUUID]; 59 | self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:proximityUUID identifier:self.piBeacon.piRegionIdentifier]; 60 | } 61 | 62 | - (void)turnOnRanging 63 | { 64 | if (![CLLocationManager isRangingAvailable]) { 65 | self.switchRanging.on = NO; 66 | return; 67 | } 68 | if (self.locationManager.rangedRegions.count > 0) { 69 | return; 70 | } 71 | 72 | [self createBeaconRegion]; 73 | [self.locationManager startRangingBeaconsInRegion:self.beaconRegion]; 74 | } 75 | 76 | 77 | - (void)changeRangingState:sender 78 | { 79 | UISwitch *theSwitch = (UISwitch *)sender; 80 | if (theSwitch.on) { 81 | [self startRangingForBeacons]; 82 | } else { 83 | [self stopRangingForBeacons]; 84 | } 85 | } 86 | 87 | - (void)startRangingForBeacons 88 | { 89 | self.locationManager = [[CLLocationManager alloc] init]; 90 | self.locationManager.delegate = self; 91 | self.locationManager.activityType = CLActivityTypeFitness; 92 | self.locationManager.distanceFilter = kCLDistanceFilterNone; 93 | self.locationManager.desiredAccuracy = kCLLocationAccuracyBest; 94 | 95 | [self turnOnRanging]; 96 | } 97 | 98 | - (void)stopRangingForBeacons 99 | { 100 | if (self.locationManager.rangedRegions.count == 0) { 101 | return; 102 | } 103 | 104 | [self.locationManager stopRangingBeaconsInRegion:self.beaconRegion]; 105 | 106 | self.tableData = nil; 107 | [self.myTableView reloadData]; 108 | } 109 | 110 | #pragma mark - Beacon ranging delegate methods 111 | - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status 112 | { 113 | if (![CLLocationManager locationServicesEnabled]) { 114 | self.switchRanging.on = NO; 115 | return; 116 | } 117 | 118 | if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorized) { 119 | self.switchRanging.on = NO; 120 | return; 121 | } 122 | 123 | self.switchRanging.on = YES; 124 | } 125 | 126 | - (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons 127 | inRegion:(CLBeaconRegion *)region { 128 | 129 | if ([beacons count] == 0) { 130 | //NSLog(@"No beacons found nearby."); 131 | } else { 132 | //NSLog(@"Found beacons! %@", region.identifier); 133 | } 134 | 135 | //MAS Todo startEngagement 136 | // ModelEngagement *engagement = [self engagementFactory:self.piBeacon.piUUID]; 137 | // engagement.iBeaconRegionIdentifier = region.identifier; 138 | 139 | self.tableData = beacons; 140 | [self.myTableView reloadData]; 141 | } 142 | 143 | #pragma mark - Beacon advertising 144 | - (void)turnOnAdvertising 145 | { 146 | if (self.peripheralManager.state != 5) { 147 | self.switchAdvertising.on = NO; 148 | return; 149 | } 150 | 151 | CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:self.beaconRegion.proximityUUID 152 | major: self.piBeacon.piMajor 153 | minor: self.piBeacon.piMinor 154 | identifier:self.beaconRegion.identifier]; 155 | 156 | NSDictionary *beaconPeripheralData = [region peripheralDataWithMeasuredPower:nil]; 157 | [self.peripheralManager startAdvertising:beaconPeripheralData]; 158 | } 159 | 160 | 161 | - (void)changeAdvertisingState:sender 162 | { 163 | UISwitch *theSwitch = (UISwitch *)sender; 164 | if (theSwitch.on) { 165 | [self startAdvertisingBeacon]; 166 | } else { 167 | [self stopAdvertisingBeacon]; 168 | } 169 | } 170 | 171 | 172 | - (void)startAdvertisingBeacon 173 | { 174 | [self createBeaconRegion]; 175 | 176 | if (!self.peripheralManager) 177 | self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil options:nil]; 178 | 179 | [self turnOnAdvertising]; 180 | } 181 | 182 | - (void)stopAdvertisingBeacon 183 | { 184 | [self.peripheralManager stopAdvertising]; 185 | } 186 | 187 | #pragma mark - Beacon advertising delegate methods 188 | - (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheralManager error:(NSError *)error 189 | { 190 | if (error) { 191 | self.switchAdvertising.on = NO; 192 | return; 193 | } 194 | 195 | if (peripheralManager.isAdvertising) { 196 | self.switchAdvertising.on = YES; 197 | } 198 | } 199 | 200 | - (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheralManager 201 | { 202 | if (peripheralManager.state != 5) { 203 | self.switchAdvertising.on = NO; 204 | return; 205 | } 206 | [self turnOnAdvertising]; 207 | } 208 | 209 | 210 | #pragma mark - UITableView Delegate 211 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 212 | { 213 | return [self.tableData count]; 214 | } 215 | 216 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 217 | { 218 | CLBeacon *beacon = self.tableData[indexPath.row]; 219 | 220 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier]; 221 | 222 | if (cell == nil) { 223 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:kCellIdentifier]; 224 | } 225 | 226 | cell.textLabel.text = beacon.proximityUUID.UUIDString; 227 | 228 | NSString *proximityString; 229 | switch (beacon.proximity) { 230 | case CLProximityNear: 231 | proximityString = @"Near"; 232 | break; 233 | case CLProximityImmediate: 234 | proximityString = @"Immediate"; 235 | break; 236 | case CLProximityFar: 237 | proximityString = @"Far"; 238 | break; 239 | case CLProximityUnknown: 240 | default: 241 | proximityString = @"Unknown"; 242 | break; 243 | } 244 | cell.detailTextLabel.text = [NSString stringWithFormat:@"%@, %@ • %@ • %f • %li", 245 | beacon.major.stringValue, 246 | beacon.minor.stringValue, 247 | proximityString, 248 | beacon.accuracy, 249 | (long)beacon.rssi]; 250 | cell.detailTextLabel.textColor = [UIColor grayColor]; 251 | return cell; 252 | } 253 | 254 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 255 | 256 | piBeaconDetailViewController *detailController = [[piBeaconDetailViewController alloc] init]; 257 | detailController.model = [self.tableData objectAtIndex:indexPath.row]; 258 | [self.tabBarController presentViewController: detailController animated:YES completion:nil]; 259 | 260 | } 261 | 262 | -(void) tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath 263 | { 264 | //myCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 265 | //cell.customHelpButton.hidden = true; 266 | 267 | piBeaconDetailViewController *detailController = [[piBeaconDetailViewController alloc] init]; 268 | detailController.model = [self.tableData objectAtIndex:indexPath.row]; 269 | [self.tabBarController presentViewController: detailController animated:YES completion:nil]; 270 | } 271 | 272 | /* 273 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 274 | { 275 | if ([segue.identifier isEqualToString:@"showDetail"]) { 276 | 277 | NSInteger row = [[self myTableView].indexPathForSelectedRow row]; 278 | NSObject *rowObject = [[self tableData] objectAtIndex:row]; 279 | 280 | piBeaconDetailViewController *detailController = segue.destinationViewController; 281 | detailController.model = rowObject; 282 | } 283 | } 284 | */ 285 | 286 | 287 | - (void)viewDidLoad 288 | { 289 | [super viewDidLoad]; 290 | 291 | self.textFieldUUID.text = self.piBeacon.piUUID; 292 | self.textFieldBeaconRegionID.text = self.piBeacon.piRegionIdentifier; 293 | 294 | [self.switchAdvertising addTarget:self action:@selector(changeAdvertisingState:) forControlEvents:UIControlEventValueChanged]; 295 | [self.switchRanging addTarget:self action:@selector(changeRangingState:) forControlEvents:UIControlEventValueChanged]; 296 | 297 | } 298 | 299 | - (void)didReceiveMemoryWarning 300 | { 301 | [super didReceiveMemoryWarning]; 302 | // Dispose of any resources that can be recreated. 303 | } 304 | 305 | @end 306 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // piBeacon-iphone 4 | // 5 | // Created by Matt Schmulen on 12/24/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/piBeacon-iphone-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.mattschmulen.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIBackgroundModes 28 | 29 | bluetooth-peripheral 30 | 31 | UIMainStoryboardFile 32 | Main 33 | UIRequiredDeviceCapabilities 34 | 35 | armv7 36 | 37 | UIStatusBarTintParameters 38 | 39 | UINavigationBar 40 | 41 | Style 42 | UIBarStyleDefault 43 | Translucent 44 | 45 | 46 | 47 | UISupportedInterfaceOrientations 48 | 49 | UIInterfaceOrientationPortrait 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/piBeacon-iphone-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/piBeacon/ModelEngagement.h: -------------------------------------------------------------------------------- 1 | // 2 | // ModelEngagement.h 3 | // herald 4 | // 5 | // Created by Matt Schmulen on 10/28/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, BLE_TYPE) { BLE_TYPE_IBEACON, BLE_TYPE_UNKNOWN }; 12 | 13 | @interface ModelEngagement : NSObject 14 | 15 | @property(nonatomic) NSDate *startTime; 16 | @property(nonatomic) NSDate *endTime; 17 | 18 | @property(nonatomic) NSString *iBeaconProximityUUID; 19 | @property(nonatomic) NSString *iBeaconRegionIdentifier; 20 | 21 | @property(nonatomic) NSNumber *iBeaconProximityMajor; 22 | @property(nonatomic) NSNumber *iBeaconProximityMinor; 23 | 24 | @property(nonatomic) BLE_TYPE bleType; 25 | 26 | //arc4random() 27 | //http://stackoverflow.com/questions/7363840/using-a-unique-identifier-of-iphone-or-ios-device 28 | //CFUUIDRef theUUID = CFUUIDCreate(NULL); 29 | @property(nonatomic) CFUUIDRef engagementID; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/piBeacon/ModelEngagement.m: -------------------------------------------------------------------------------- 1 | // 2 | // ModelEngagement.m 3 | // herald 4 | // 5 | // Created by Matt Schmulen on 10/28/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import "ModelEngagement.h" 10 | 11 | 12 | @implementation ModelEngagement 13 | 14 | @synthesize engagementID; 15 | 16 | - (id)init { 17 | if(self = [super init]) { 18 | self.engagementID = CFUUIDCreate(NULL); 19 | } 20 | 21 | return self; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/piBeacon/piBeacon.h: -------------------------------------------------------------------------------- 1 | // 2 | // piBeacon.h 3 | // piBeacon-iphone 4 | // 5 | // Created by Matt Schmulen on 12/26/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ModelEngagement.h" 11 | #import "piBeaconDetailViewController.h" 12 | #import "piBeaconProximityAlertViewController.h" 13 | 14 | 15 | //Notifications 16 | static NSString * const notification_NewEngagement = @"NewEngagementNotification"; 17 | //static NSString * const notification_NewEngagement = @"NewEngagementNotification"; 18 | //static NSString * const notification_NewEngagement = @"NewEngagementNotification"; 19 | 20 | @interface piBeacon : NSObject 21 | 22 | -(void) initWithConfig:(NSString *)beaconUUID beaconRegionId:(NSString*) beaconRegionId beaconMajor:(NSInteger)beaconMajor beaconMinor:(NSInteger)beaconMinor; 23 | 24 | //Beacon config 25 | @property(nonatomic) NSInteger piMajor; 26 | @property(nonatomic) NSInteger piMinor; 27 | @property(nonatomic) NSString *piUUID; 28 | @property(nonatomic) NSString *piRegionIdentifier; 29 | 30 | @property(nonatomic,retain) NSString *strUserName; 31 | @property(nonatomic,retain) NSString *strUserTitle; 32 | 33 | + (void) simulateProximityEvent; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/piBeacon/piBeacon.m: -------------------------------------------------------------------------------- 1 | // 2 | // piBeacon.m 3 | // piBeacon-iphone 4 | // 5 | // Created by Matt Schmulen on 12/26/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import "piBeacon.h" 10 | 11 | 12 | @interface piBeacon () 13 | 14 | @property (nonatomic, assign) NSUserDefaults * userDefaults; 15 | 16 | @end 17 | 18 | @implementation piBeacon 19 | 20 | @synthesize piMajor,piMinor,piUUID,strUserName,strUserTitle; 21 | 22 | -(void) initWithConfig:(NSString *)beaconUUID beaconRegionId:(NSString*) beaconRegionId beaconMajor:(NSInteger)beaconMajor beaconMinor:(NSInteger)beaconMinor; 23 | { 24 | //[NSUserDefaults resetStandardUserDefaults]; 25 | //self.userDefaults = [NSUserDefaults standardUserDefaults]; 26 | 27 | //create NSUserDefault keys 28 | time_t t; 29 | srand((unsigned) time(&t)); //seed the rand with the time 30 | 31 | int randomMinor = rand() % 65535; 32 | 33 | self.piMajor = beaconMajor; // piBeacon convention is iOS devices are Major = 2;//major; 34 | self.piMinor = randomMinor; 35 | self.piUUID = beaconUUID; 36 | self.piRegionIdentifier = beaconRegionId; 37 | 38 | self.strUserName = @"King Harald Bluetooth"; 39 | self.strUserTitle = @"The Last Viking"; 40 | 41 | NSLog(@"piBeacon region: %@ ", self.piRegionIdentifier); 42 | NSLog(@"piBeacon uuid:%@", self.piUUID ); 43 | NSLog(@"major: %ld minor: %ld ", (long)self.piMajor, (long)self.piMinor ); 44 | 45 | /* 46 | if(self.userDefaults) 47 | { 48 | if([[NSUserDefaults standardUserDefaults] objectForKey:@"strUserName"] == nil) { 49 | 50 | //create NSUserDefault keys 51 | time_t t; 52 | srand((unsigned) time(&t)); //seed the rand with the time 53 | 54 | self.piMajor = rand(); 55 | self.piMinor = rand(); 56 | 57 | //Set 58 | [self.userDefaults setInteger: self.piMajor forKey:@"piBeaconProximityMajor"]; 59 | [self.userDefaults setInteger: self.piMinor forKey:@"piBeaconProximityMinor"]; 60 | [self.userDefaults setObject: self.piUUID forKey:@"piBeaconUUID"]; 61 | 62 | //user defaults 63 | [self.userDefaults setObject: @"King Harald Bluetooth" forKey:@"strUserName"]; 64 | [self.userDefaults setObject: @"The Last Viking" forKey:@"strUserTitle"]; 65 | 66 | //Sync the userDefatuls 67 | //[self.userDefaults synchronize]; 68 | } 69 | 70 | //Retrieve 71 | self.piMajor = [self.userDefaults integerForKey:@"piBeaconProximityMajor"]; 72 | self.piMinor = [self.userDefaults integerForKey:@"piBeaconProximityMinor"]; 73 | self.piUUID = [self.userDefaults stringForKey:@"piBeaconUUID"]; 74 | 75 | self.strUserName = [self.userDefaults stringForKey:@"strUserName"]; 76 | self.strUserTitle = [self.userDefaults stringForKey:@"strUserTitle"]; 77 | } 78 | else { 79 | NSLog(@"applicationDidFinishLaunching: Error reading config file."); 80 | } 81 | */ 82 | 83 | } 84 | 85 | 86 | #pragma mark - Engagment 87 | - (ModelEngagement *) engagementFactory: (NSString*) beaconProximityUUID 88 | { 89 | ModelEngagement *engagement = [[ModelEngagement alloc] init]; 90 | 91 | engagement.startTime = [[NSDate alloc] init]; 92 | engagement.endTime = [[NSDate alloc] init]; 93 | 94 | engagement.iBeaconProximityUUID = beaconProximityUUID; 95 | engagement.iBeaconRegionIdentifier = self.piRegionIdentifier; 96 | engagement.bleType = BLE_TYPE_IBEACON; 97 | 98 | //[[NSNotificationCenter defaultCenter] postNotificationName:notification_NewEngagement object:engagement]; 99 | 100 | return engagement; 101 | }//end engagementFactory 102 | 103 | - (void) startEngagement 104 | { 105 | //[self.engagementFactory 106 | //ModelEngagement *engagement = [self engagementFactory:self.piBeacon.piUUID]; 107 | //engagement.iBeaconRegionIdentifier = region.identifier; 108 | 109 | //engagement.iBeaconProximityMajor = region.major; 110 | //engagement.iBeaconProximityMinor = region.minor; 111 | //engagement.bleType = 112 | 113 | } 114 | 115 | - (void) endEngagement 116 | { 117 | 118 | } 119 | 120 | + (void) simulateProximityEvent 121 | { 122 | NSLog(@"Simulate Proximity Event"); 123 | 124 | [[NSNotificationCenter defaultCenter] postNotificationName:notification_NewEngagement object:nil]; 125 | } 126 | 127 | 128 | 129 | @end 130 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/piBeacon/piBeaconDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // piBeaconDetailViewController.h 3 | // piBeacon-iphone 4 | // 5 | // Created by Matt Schmulen on 12/26/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface piBeaconDetailViewController : UIViewController 12 | 13 | @property NSObject *model; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/piBeacon/piBeaconDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // piBeaconDetailViewController.m 3 | // piBeacon-iphone 4 | // 5 | // Created by Matt Schmulen on 12/26/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import "piBeaconDetailViewController.h" 10 | 11 | @interface piBeaconDetailViewController () 12 | 13 | @end 14 | 15 | @implementation piBeaconDetailViewController 16 | 17 | @synthesize model; 18 | 19 | - (IBAction)actionClose:(id)sender { 20 | [self dismissViewControllerAnimated:YES completion:nil]; 21 | } 22 | 23 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 24 | { 25 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 26 | //self = [[NSBundle mainBundle] loadNibNamed:@"piBeaconDetailViewController" owner:self options:nil][0] 27 | if (self) { 28 | // Custom initialization 29 | } 30 | return self; 31 | } 32 | 33 | - (void)viewDidLoad 34 | { 35 | [super viewDidLoad]; 36 | // Do any additional setup after loading the view from its nib. 37 | } 38 | 39 | - (void)didReceiveMemoryWarning 40 | { 41 | [super didReceiveMemoryWarning]; 42 | // Dispose of any resources that can be recreated. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/piBeacon/piBeaconDetailViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 23 | 29 | 35 | 41 | 47 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/piBeacon/piBeaconProximityAlertViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // piBeaconProximityAlertViewController.h 3 | // piBeacon-iphone 4 | // 5 | // Created by Matt Schmulen on 12/29/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface piBeaconProximityAlertViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/piBeacon/piBeaconProximityAlertViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // piBeaconProximityAlertViewController.m 3 | // piBeacon-iphone 4 | // 5 | // Created by Matt Schmulen on 12/29/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import "piBeaconProximityAlertViewController.h" 10 | 11 | @interface piBeaconProximityAlertViewController () 12 | 13 | @end 14 | 15 | @implementation piBeaconProximityAlertViewController 16 | - (IBAction)actionClose:(id)sender { 17 | [self dismissViewControllerAnimated:YES completion:nil]; 18 | } 19 | 20 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 21 | { 22 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 23 | if (self) { 24 | // Custom initialization 25 | } 26 | return self; 27 | } 28 | 29 | - (void)viewDidLoad 30 | { 31 | [super viewDidLoad]; 32 | // Do any additional setup after loading the view from its nib. 33 | } 34 | 35 | - (void)didReceiveMemoryWarning 36 | { 37 | [super didReceiveMemoryWarning]; 38 | // Dispose of any resources that can be recreated. 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/piBeacon/piBeaconProximityAlertViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 24 | 31 | 32 | 33 | 34 | 35 | 43 | 50 | 57 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/piBeacon/piBeaconUserDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // piBeaconUserDetailViewController.h 3 | // piBeacon-iphone 4 | // 5 | // Created by Matt Schmulen on 12/26/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface piBeaconUserDetailViewController : UIViewController 12 | @property NSObject *model; 13 | @end 14 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/piBeacon/piBeaconUserDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // piBeaconUserDetailViewController.m 3 | // piBeacon-iphone 4 | // 5 | // Created by Matt Schmulen on 12/26/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import "piBeaconUserDetailViewController.h" 10 | 11 | @interface piBeaconUserDetailViewController () 12 | 13 | @end 14 | 15 | @implementation piBeaconUserDetailViewController 16 | 17 | @synthesize model; 18 | 19 | 20 | - (IBAction)actionClose:(id)sender { 21 | 22 | [self dismissViewControllerAnimated:YES completion:nil]; 23 | } 24 | 25 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 26 | { 27 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 28 | if (self) { 29 | // Custom initialization 30 | } 31 | return self; 32 | } 33 | 34 | - (void)viewDidLoad 35 | { 36 | [super viewDidLoad]; 37 | // Do any additional setup after loading the view from its nib. 38 | } 39 | 40 | - (void)didReceiveMemoryWarning 41 | { 42 | [super didReceiveMemoryWarning]; 43 | // Dispose of any resources that can be recreated. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphone/piBeacon/piBeaconUserDetailViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 55 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphoneTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphoneTests/piBeacon-iphoneTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.mattschmulen.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /client-iphone/piBeacon-iphoneTests/piBeacon_iphoneTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // piBeacon_iphoneTests.m 3 | // piBeacon-iphoneTests 4 | // 5 | // Created by Matt Schmulen on 12/24/13. 6 | // Copyright (c) 2013 Matt Schmulen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface piBeacon_iphoneTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation piBeacon_iphoneTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /ibeacon-node-collector/app.js: -------------------------------------------------------------------------------- 1 | var loopback = require('loopback'); 2 | var path = require('path'); 3 | var app = module.exports = loopback(); 4 | var started = new Date(); 5 | 6 | /* 7 | * 1. Configure LoopBack models and datasources 8 | * 9 | * Read more at http://apidocs.strongloop.com/loopback#appbootoptions 10 | */ 11 | 12 | app.boot(__dirname); 13 | 14 | /* 15 | * 2. Configure request preprocessing 16 | * 17 | * LoopBack support all express-compatible middleware. 18 | */ 19 | 20 | app.use(loopback.favicon()); 21 | app.use(loopback.logger(app.get('env') === 'development' ? 'dev' : 'default')); 22 | app.use(loopback.cookieParser(app.get('cookieSecret'))); 23 | app.use(loopback.token({model: app.models.accessToken})); 24 | app.use(loopback.bodyParser()); 25 | app.use(loopback.methodOverride()); 26 | 27 | /* 28 | * EXTENSION POINT 29 | * Add your custom request-preprocessing middleware here. 30 | * Example: 31 | * app.use(loopback.limit('5.5mb')) 32 | */ 33 | 34 | /* 35 | * 3. Setup request handlers. 36 | */ 37 | 38 | // LoopBack REST interface 39 | app.use(app.get('restApiRoot'), loopback.rest()); 40 | 41 | // API explorer (if present) 42 | try { 43 | var explorer = require('loopback-explorer')(app); 44 | app.use('/explorer', explorer); 45 | app.once('started', function(baseUrl) { 46 | console.log('Browse your REST API at %s%s', baseUrl, explorer.route); 47 | }); 48 | } catch(e){ 49 | console.log( 50 | 'Run `npm install loopback-explorer` to enable the LoopBack explorer' 51 | ); 52 | } 53 | 54 | /* 55 | * EXTENSION POINT 56 | * Add your custom request-handling middleware here. 57 | * Example: 58 | * app.use(function(req, resp, next) { 59 | * if (req.url == '/status') { 60 | * // send status response 61 | * } else { 62 | * next(); 63 | * } 64 | * }); 65 | */ 66 | 67 | // Let express routes handle requests that were not handled 68 | // by any of the middleware registered above. 69 | // This way LoopBack REST and API Explorer take precedence over 70 | // express routes. 71 | app.use(app.router); 72 | 73 | // The static file server should come after all other routes 74 | // Every request that goes through the static middleware hits 75 | // the file system to check if a file exists. 76 | app.use(loopback.static(path.join(__dirname, 'public'))); 77 | 78 | // Requests that get this far won't be handled 79 | // by any middleware. Convert them into a 404 error 80 | // that will be handled later down the chain. 81 | app.use(loopback.urlNotFound()); 82 | 83 | /* 84 | * 4. Setup error handling strategy 85 | */ 86 | 87 | /* 88 | * EXTENSION POINT 89 | * Add your custom error reporting middleware here 90 | * Example: 91 | * app.use(function(err, req, resp, next) { 92 | * console.log(req.url, ' failed: ', err.stack); 93 | * next(err); 94 | * }); 95 | */ 96 | 97 | // The ultimate error handler. 98 | app.use(loopback.errorHandler()); 99 | 100 | 101 | /* 102 | * 5. Add a basic application status route at the root `/`. 103 | * 104 | * (remove this to handle `/` on your own) 105 | */ 106 | 107 | app.get('/', loopback.status()); 108 | 109 | /* 110 | * 6. Enable access control and token based authentication. 111 | */ 112 | 113 | var swaggerRemote = app.remotes().exports.swagger; 114 | if (swaggerRemote) swaggerRemote.requireToken = false; 115 | 116 | app.enableAuth(); 117 | 118 | /* 119 | * 7. Optionally start the server 120 | * 121 | * (only if this module is the main module) 122 | */ 123 | 124 | app.start = function() { 125 | return app.listen(function() { 126 | var baseUrl = 'http://' + app.get('host') + ':' + app.get('port'); 127 | app.emit('started', baseUrl); 128 | console.log('LoopBack server listening @ %s%s', baseUrl, '/'); 129 | }); 130 | }; 131 | 132 | if(require.main === module) { 133 | app.start(); 134 | } 135 | -------------------------------------------------------------------------------- /ibeacon-node-collector/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "port": 3000, 3 | "host": "0.0.0.0", 4 | "cookieSecret": "993a5e14-783a-41de-9224-e7f72e014419" 5 | } 6 | -------------------------------------------------------------------------------- /ibeacon-node-collector/boot/init.js: -------------------------------------------------------------------------------- 1 | 2 | var loopback = require('loopback'); 3 | var app = require('../app'); 4 | 5 | var ibeacon = app.models.ibeacon; 6 | var Bleacon = require('bleacon'); 7 | var ibeaconCache = new Array(); 8 | 9 | Bleacon.on('discover', function(bleacon) { 10 | //console.log( bleacon ); 11 | 12 | var dbID = 0; 13 | var guid = bleacon.uuid + bleacon.major + bleacon.minor; 14 | if ( guid in ibeaconCache ) { dbID = ibeaconCache[guid]; } 15 | 16 | ibeacon.upsert( 17 | { id: dbID , guid:guid, uuid:bleacon.uuid, major:bleacon.major, minor:bleacon.minor}, 18 | function( error, _ibeacon) 19 | { 20 | ibeaconCache[guid] = _ibeacon.id; 21 | if ( error ) { console.log( "error on upsert " ); } 22 | else { 23 | //console.log( "upsert - :" + _ibeacon.id + " guid " + _ibeacon.guid ); 24 | var eng = app.models.engagement; 25 | eng.create({ pBeaconID: _ibeacon.id, timestamp: Date.now(), rssi: bleacon.rssi, proximity: bleacon.proximity }); 26 | } //end else success 27 | }); //end upser 28 | 29 | var signal = [bleacon.rssi/5]; 30 | var xs = new Array(Math.floor(-bleacon.rssi/2) + 1).join('x'); 31 | console.log("rssi:" +xs); 32 | 33 | });//end on discover 34 | 35 | Bleacon.startScanning(); 36 | -------------------------------------------------------------------------------- /ibeacon-node-collector/datasources.json: -------------------------------------------------------------------------------- 1 | { 2 | "db": { 3 | "defaultForType": "db", 4 | "connector": "memory" 5 | }, 6 | "push": { 7 | "defaultForType": "push", 8 | "connector": "loopback-push-notification", 9 | "installation": "installation", 10 | "notification": "notification", 11 | "application": "application" 12 | }, 13 | "mail": { 14 | "defaultForType": "mail", 15 | "connector": "mail" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ibeacon-node-collector/models.json: -------------------------------------------------------------------------------- 1 | { 2 | "email": { 3 | "options": { 4 | "base": "Email" 5 | }, 6 | "dataSource": "mail", 7 | "public": false 8 | }, 9 | "user": { 10 | "options": { 11 | "base": "User", 12 | "relations": { 13 | "accessTokens": { 14 | "model": "accessToken", 15 | "type": "hasMany", 16 | "foreignKey": "userId" 17 | } 18 | } 19 | }, 20 | "dataSource": "db", 21 | "public": true 22 | }, 23 | "accessToken": { 24 | "options": { 25 | "base": "AccessToken" 26 | }, 27 | "dataSource": "db", 28 | "public": true 29 | }, 30 | "application": { 31 | "options": { 32 | "base": "Application" 33 | }, 34 | "dataSource": "db", 35 | "public": true 36 | }, 37 | "acl": { 38 | "options": { 39 | "base": "ACL" 40 | }, 41 | "dataSource": "db", 42 | "public": false 43 | }, 44 | "roleMapping": { 45 | "options": { 46 | "base": "RoleMapping" 47 | }, 48 | "dataSource": "db", 49 | "public": false 50 | }, 51 | "role": { 52 | "options": { 53 | "base": "Role", 54 | "relations": { 55 | "principals": { 56 | "type": "hasMany", 57 | "model": "roleMapping", 58 | "foreignKey": "roleId" 59 | } 60 | } 61 | }, 62 | "dataSource": "db", 63 | "public": false 64 | }, 65 | "scope": { 66 | "options": { 67 | "base": "Scope" 68 | }, 69 | "dataSource": "db", 70 | "public": false 71 | }, 72 | "push": { 73 | "options": { 74 | "base": "Push", 75 | "plural": "push" 76 | }, 77 | "dataSource": "push" 78 | }, 79 | "installation": { 80 | "options": { 81 | "base": "Installation" 82 | }, 83 | "dataSource": "db", 84 | "public": true 85 | }, 86 | "notification": { 87 | "options": { 88 | "base": "Notification" 89 | }, 90 | "dataSource": "db", 91 | "public": true 92 | }, 93 | "ibeacon": { 94 | "properties": {}, 95 | "public": true, 96 | "dataSource": "db" 97 | }, 98 | "engagement": { 99 | "properties": {}, 100 | "public": true, 101 | "dataSource": "db" 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /ibeacon-node-collector/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.0.0", 3 | "main": "app.js", 4 | "bin": "server.js", 5 | "scripts": { 6 | "start": "node app.js" 7 | }, 8 | "dependencies": { 9 | "loopback": "1.5.x", 10 | "bleacon": "~0.2.0" 11 | }, 12 | "optionalDependencies": { 13 | "loopback-explorer": "~1.1.0", 14 | "loopback-push-notification": "~1.1.0" 15 | }, 16 | "name": "ibeacon-node-collector" 17 | } 18 | -------------------------------------------------------------------------------- /screenshots/api-ibeacons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/screenshots/api-ibeacons.png -------------------------------------------------------------------------------- /screenshots/ble-analytics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/screenshots/ble-analytics.png -------------------------------------------------------------------------------- /screenshots/ble-apps-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/screenshots/ble-apps-2.png -------------------------------------------------------------------------------- /screenshots/ble-apps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/screenshots/ble-apps.png -------------------------------------------------------------------------------- /screenshots/ble-mobile-multi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/screenshots/ble-mobile-multi.png -------------------------------------------------------------------------------- /screenshots/ble-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/screenshots/ble-mobile.png -------------------------------------------------------------------------------- /screenshots/ble-ranging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/screenshots/ble-ranging.png -------------------------------------------------------------------------------- /screenshots/console-run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/screenshots/console-run.png -------------------------------------------------------------------------------- /screenshots/estimote-ibeacon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/screenshots/estimote-ibeacon.png -------------------------------------------------------------------------------- /screenshots/explorer-ibeacons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/screenshots/explorer-ibeacons.png -------------------------------------------------------------------------------- /screenshots/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/screenshots/image1.png -------------------------------------------------------------------------------- /screenshots/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/screenshots/image2.png -------------------------------------------------------------------------------- /screenshots/loopback-explorer-beacon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/screenshots/loopback-explorer-beacon.png -------------------------------------------------------------------------------- /screenshots/loopback-explorer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/screenshots/loopback-explorer.png -------------------------------------------------------------------------------- /screenshots/loopback-filter-near.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mschmulen/tracking-bluetooth-ibeacons-with-node/2798b01ac4af5ff7ad8a46019ea8ea1b8178d6a2/screenshots/loopback-filter-near.png --------------------------------------------------------------------------------