diff --git a/nervous/Controllers/AxonController.swift b/nervous/Controllers/AxonController.swift index 4a9aa03..4e3e02a 100755 --- a/nervous/Controllers/AxonController.swift +++ b/nervous/Controllers/AxonController.swift @@ -25,8 +25,7 @@ class AxonController { init(){ startAxonHTTPServer() } - - + func startAxonHTTPServer(){ do { @@ -69,44 +68,51 @@ class AxonController { } - // route to get any axon resource self.server.GET["/nervousnet-axons/:axonname/:resource"] = { r in if let filename = r.params[":resource"], axonname = r.params[":axonname"] { return self.returnRawResponse("\(self.axonDir)/\(axonname)/\(axonname)-master/\(filename)"); } return .NotFound - } - - - - + + // route to get any axon resource + self.server.POST["/nervousnet-api/log"] = { r in + print("axon debug:") + print(String(bytes: r.body, encoding: NSUTF8StringEncoding)) + return .OK(.Json("")) + } + + self.server.GET["/nervousnet-api/deviceid"] = { r in + let uuid = UIDevice.currentDevice().identifierForVendor!.UUIDString + return .OK(.Json(["uuid": uuid])) + } + // route to get any axon resource self.server.GET["/nervousnet-api/raw-sensor-data/:sensor/"] = { r in - + if let sensor = r.params[":sensor"] { - + print(sensor) + let data = self.laeController.getData(sensor) print(data) + if(sensor == "BLE"){ let jsonObject: NSDictionary = ["blepacket": data[0] as! String] return .OK(.Json(jsonObject)) - }else if(sensor == "GPS"){ - let jsonObject: NSDictionary = ["lat": data[0], "long":data[1]] - return .OK(.Json(jsonObject)) + }else if(sensor == "GPS"){ + let jsonObject: NSDictionary = ["lat": data[0], "long":data[1]] + return .OK(.Json(jsonObject)) + }else if(sensor == "Beacon"){ + return .OK(.Json(data)) }else{ let jsonObject: NSDictionary = ["x": data[0], "y":data[1], "z": data[2]] return .OK(.Json(jsonObject)) - } - } - return .NotFound - } diff --git a/nervous/Controllers/BeaconController.swift b/nervous/Controllers/BeaconController.swift index a95755a..103b719 100755 --- a/nervous/Controllers/BeaconController.swift +++ b/nervous/Controllers/BeaconController.swift @@ -15,40 +15,61 @@ protocol BeaconControllerDelegate { } +let _sharedInstance = BeaconController() + class BeaconController : NSObject, SensorProtocol{ var delegate: BeaconControllerDelegate? let locationManager : CLLocationManager - let beaconRegion : CLBeaconRegion - let beaconUUIDString = NSUUID(UUIDString: "3C77C2A5-5D39-420F-97FD-E7735CC7F317")! - let beaconIdentifier = "ch.ethz.nervous" - let beaconMajor:CLBeaconMajorValue = 33091 - - + + var beaconRegions = [CLBeaconRegion]() + var beaconData = [AnyObject]() + + var _tmpBeacons = [String:AnyObject]() + override init() { - self.locationManager = CLLocationManager() - self.beaconRegion = CLBeaconRegion(proximityUUID: beaconUUIDString, identifier: beaconIdentifier) } - + class var sharedInstance: BeaconController { + return _sharedInstance + } + func requestAuthorization() { locationManager.requestAlwaysAuthorization() } - - + + func getdata() -> [AnyObject] { + var xx = [AnyObject]() + _tmpBeacons.keys.forEach({ (key:String) in + xx.append(_tmpBeacons[key]!) + }) + return xx + } + + func addBeaconData(data:[[String:String]]) { + beaconRegions = [] + data.forEach { (kv:[String:String]) in + let br = CLBeaconRegion(proximityUUID: NSUUID(UUIDString: kv["uuid"]!)!, identifier: kv["identity"]!) + beaconRegions.append(br) + } + } + func startSensorUpdates() { locationManager.delegate = self - locationManager.startMonitoringForRegion(beaconRegion) - locationManager.startRangingBeaconsInRegion(beaconRegion) + for beaconRegion in beaconRegions { + locationManager.startMonitoringForRegion(beaconRegion) + locationManager.startRangingBeaconsInRegion(beaconRegion) + } } - - + func stopSensorUpdates() { - locationManager.stopMonitoringForRegion(beaconRegion) - locationManager.stopRangingBeaconsInRegion(beaconRegion) + for beaconRegion in beaconRegions { + locationManager.stopMonitoringForRegion(beaconRegion) + locationManager.stopRangingBeaconsInRegion(beaconRegion) + } + beaconData = [] } - } extension BeaconController: CLLocationManagerDelegate { @@ -62,7 +83,14 @@ extension BeaconController: CLLocationManagerDelegate { } func locationManager(manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], inRegion region: CLBeaconRegion) { - + + self.beaconData = beacons.map({ (beacon) -> [String:String] in + let bb = ["uuid": beacon.proximityUUID.UUIDString, "major": String(beacon.major), "minor": String(beacon.minor), "proximity": String(beacon.proximity.rawValue), "accuracy": String(format:"%f", beacon.accuracy)] + _tmpBeacons[bb["uuid"]!] = bb + return bb + }) + + //send new beacons to delegates if let delegate = self.delegate { delegate.controller(self, didRangeBeacons: beacons) diff --git a/nervous/Controllers/LAEController.swift b/nervous/Controllers/LAEController.swift index 2cde17d..e2332c8 100755 --- a/nervous/Controllers/LAEController.swift +++ b/nervous/Controllers/LAEController.swift @@ -66,7 +66,13 @@ class LAEController : NSObject { data.append(sen.lat) data.append(sen.long) } - + + if sensor == "Beacon" { + let sen = BeaconController.sharedInstance +// data = sen.beaconData + data = sen.getdata() + } + return data } diff --git a/nervous/Controllers/ViewControllers/AxonViewController.swift b/nervous/Controllers/ViewControllers/AxonViewController.swift index bc042ac..76ed193 100644 --- a/nervous/Controllers/ViewControllers/AxonViewController.swift +++ b/nervous/Controllers/ViewControllers/AxonViewController.swift @@ -26,7 +26,10 @@ class AxonViewController: UIViewController { } @IBAction func closeAxonButton(sender: AnyObject) { - self.dismissViewControllerAnimated(true, completion: {}); + self.dismissViewControllerAnimated(true, completion: { + let beaconController = BeaconController.sharedInstance + beaconController.stopSensorUpdates() + }); } override func viewWillAppear(animated: Bool) { @@ -38,12 +41,18 @@ class AxonViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. - - + print("firing up the axon...") let url = AxonStore.getLocalAxonURL(axonName); let request = NSURLRequest(URL: url!) + let beacons = AxonStore.getLocalAxonBeacons(axonName) + if beacons.count > 0 { + let beaconController = BeaconController.sharedInstance + beaconController.addBeaconData(beacons) + beaconController.startSensorUpdates() + } + axonWebView.loadRequest(request); axonWebView.scrollView.bounces = false; } diff --git a/nervous/Info.plist b/nervous/Info.plist index 07f7e08..dd95314 100755 --- a/nervous/Info.plist +++ b/nervous/Info.plist @@ -30,6 +30,16 @@ NSAllowsArbitraryLoads + NSExceptionDomains + + xip.io + + NSExceptionAllowsInsecureHTTPLoads + + NSIncludesSubdomains + + + NSLocationAlwaysUsageDescription Provides access to bluetooth beacons. diff --git a/nervous/Stores/AxonStore.swift b/nervous/Stores/AxonStore.swift index 25f321b..c6cb26d 100755 --- a/nervous/Stores/AxonStore.swift +++ b/nervous/Stores/AxonStore.swift @@ -1,7 +1,7 @@ // // AxonStore.swift // nervousnet-iOS -// +// // Created by Sam Sulaimanov on 03 Mar 2016. // Copyright (c) 2016 ETHZ . All rights reserved. // @@ -15,177 +15,189 @@ import Zip /// Axon Store gets Axon information from the local disk. /// class AxonStore : NSObject { - - static let includedAxonDir = "\(NSBundle.mainBundle().resourcePath)/Assets/included-axons/" - static let remoteAxonTestingRepo = "https://api.github.com/repos/nervousnet/nervousnet-axons/contents/testing?ref=master" - static let remoteAxonRepoZipSuffix = "/archive/master.zip" - static let installedAxonsDir = "\(NSHomeDirectory())/Documents/nervousnet-installed-axons" - static let singleAxonRootURL = "http://localhost:8080/nervousnet-axons" - static let axonIndexFile = "axon.html" - - static var remoteAxonList = Array>() - - - class func getInstalledAxonsList() -> Array>{ - var installedAxons = Array>() - let filemanager:NSFileManager = NSFileManager() - let files = filemanager.enumeratorAtPath(installedAxonsDir) - - while let file = files?.nextObject() { - if(file.hasSuffix("/package.json")){ - let appPackageJSON = JSON(data: NSData(contentsOfFile: "\(installedAxonsDir)/\(file)")!) - - let arrayOfStrings: [String] = [appPackageJSON["name"].string!, appPackageJSON["title"].string!, appPackageJSON["description"].string!, appPackageJSON["icon"].string!]; - - installedAxons.append(arrayOfStrings) - } - } - - return installedAxons - } - - - - // download axon in a blocking fashion - class func downloadAndInstall(axonIndex: Int) -> Bool { - - let axon = getRemoteAxon(axonIndex) - - //Get documents directory URL - let fileManager = NSFileManager.defaultManager() - let documentsDirectory = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first - let sourceUrl = NSURL(string: "\(axon[4])/\(remoteAxonRepoZipSuffix)")! - - - //Get the file name and create a LOCAL destination URL - let fileName = sourceUrl.lastPathComponent! - let destinationURL = documentsDirectory!.URLByAppendingPathComponent(fileName) - - //Hold this file as an NSData and write it to the new location - if let fileData = NSData(contentsOfURL: sourceUrl) { - fileData.writeToURL(destinationURL, atomically: false) // true - print(destinationURL.path!) - }else{ - print("couldn't download repo zip") - return false - } - - - do { - let axonName = axon[0] - let axonZipFile = destinationURL - let unzipDirectory = try Zip.quickUnzipFile(axonZipFile) // Unzip - - do { - try fileManager.createDirectoryAtPath(installedAxonsDir, withIntermediateDirectories: true, attributes: nil); - } catch let err as NSError { - print(err) - print("install dir already exists, not creating") - - return false - - } - - do { - try fileManager.moveItemAtPath(unzipDirectory.path!, toPath: "\(installedAxonsDir)/\(axonName)") - } catch let err as NSError { - print(err) - print("unable to move axon to install path") - - return false - - } - - - return true - - } - catch let err as NSError { - print(err) - print("Something went wrong") - - return false - } - - - } - - - - - class func getRemoteAxonIndexByName(axonName: String) -> Int { - - for (index,_) in remoteAxonList.enumerate() { - - if(self.remoteAxonList[index][0] == axonName){ - return index - } - - } - - return -1 - - } - - - class func getRemoteAxon(axonIndex: Int) -> Array { - return remoteAxonList[axonIndex] - } - - - class func getLocalAxon(axonIndex: Int) -> Array { - return getInstalledAxonsList()[axonIndex] - } - - - class func getLocalAxonURL(axonName: String) -> NSURL? { - let url = NSURL(string: "\(singleAxonRootURL)/\(axonName)/\(axonIndexFile)") - return url - } - - class func removeLocalAxon(axonName: String) -> Bool { - let path = "\(installedAxonsDir)/\(axonName)" - let fileManager = NSFileManager.defaultManager() - - //DELETE SUBFOLDER - do { - try fileManager.removeItemAtPath(path) - return true - } - catch let error as NSError { - print("Ooops! Something went wrong: \(error)") - } - - return false - - } - - - //blocking task, TODO: implement caching - class func getRemoteAxonList() -> Array>{ - - let endpoint = NSURL(string: remoteAxonTestingRepo) - - if let data = NSData(contentsOfURL: endpoint!) { - - let json = JSON(data: data); - remoteAxonList = Array>() - - //get the individual package details by going through the jsons in the repo - for (_,axon_metadata) in json{ - - let axon_json_url = NSURL(string: axon_metadata["download_url"].stringValue) - let axon_json = NSData(contentsOfURL: axon_json_url!) - let axon = JSON(data: axon_json!); - let arrayOfStrings: [String] = [axon["name"].stringValue, axon["title"].stringValue, axon["description"].stringValue, axon["icon"].stringValue, axon["repository"]["url"].stringValue, axon["author"].stringValue] - remoteAxonList.append(arrayOfStrings) - } - }else{ - print("cannot download remote axon list") - } - - return remoteAxonList - } - + + static let includedAxonDir = "\(NSBundle.mainBundle().resourcePath)/Assets/included-axons/" + static let remoteAxonTestingRepo = "https://api.github.com/repos/nervousnet/nervousnet-axons/contents/testing?ref=master" + static let remoteAxonRepoZipSuffix = "/archive/master.zip" + static let installedAxonsDir = "\(NSHomeDirectory())/Documents/nervousnet-installed-axons" + static let singleAxonRootURL = "http://localhost:8080/nervousnet-axons" + static let axonIndexFile = "axon.html" + + static var remoteAxonList = Array>() + + + class func getInstalledAxonsList() -> Array>{ + var installedAxons = Array>() + let filemanager:NSFileManager = NSFileManager() + let files = filemanager.enumeratorAtPath(installedAxonsDir) + + while let file = files?.nextObject() { + if(file.hasSuffix("/package.json")){ + let appPackageJSON = JSON(data: NSData(contentsOfFile: "\(installedAxonsDir)/\(file)")!) + + let arrayOfStrings: [String] = [appPackageJSON["name"].string!, appPackageJSON["title"].string!, appPackageJSON["description"].string!, appPackageJSON["icon"].string!]; + + installedAxons.append(arrayOfStrings) + } + } + + return installedAxons + } + + // download axon in a blocking fashion + class func downloadAndInstall(axonIndex: Int) -> Bool { + + let axon = getRemoteAxon(axonIndex) + + //Get documents directory URL + let fileManager = NSFileManager.defaultManager() + let documentsDirectory = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first + let sourceUrl = NSURL(string: "\(axon[4])/\(remoteAxonRepoZipSuffix)")! + + + //Get the file name and create a LOCAL destination URL + let fileName = sourceUrl.lastPathComponent! + let destinationURL = documentsDirectory!.URLByAppendingPathComponent(fileName) + + //Hold this file as an NSData and write it to the new location + if let fileData = NSData(contentsOfURL: sourceUrl) { + fileData.writeToURL(destinationURL, atomically: false) // true + print(destinationURL.path!) + }else{ + print("couldn't download repo zip") + return false + } + + + do { + let axonName = axon[0] + let axonZipFile = destinationURL + let unzipDirectory = try Zip.quickUnzipFile(axonZipFile) // Unzip + + do { + try fileManager.createDirectoryAtPath(installedAxonsDir, withIntermediateDirectories: true, attributes: nil); + } catch let err as NSError { + print(err) + print("install dir already exists, not creating") + + return false + + } + + do { + try fileManager.moveItemAtPath(unzipDirectory.path!, toPath: "\(installedAxonsDir)/\(axonName)") + } catch let err as NSError { + print(err) + print("unable to move axon to install path") + + return false + + } + + + return true + + } + catch let err as NSError { + print(err) + print("Something went wrong") + + return false + } + + + } + + class func getRemoteAxonIndexByName(axonName: String) -> Int { + + for (index,_) in remoteAxonList.enumerate() { + + if(self.remoteAxonList[index][0] == axonName){ + return index + } + + } + + return -1 + + } + + + class func getRemoteAxon(axonIndex: Int) -> Array { + return remoteAxonList[axonIndex] + } + + + class func getLocalAxon(axonIndex: Int) -> Array { + return getInstalledAxonsList()[axonIndex] + } + + + class func getLocalAxonURL(axonName: String) -> NSURL? { + let url = NSURL(string: "\(singleAxonRootURL)/\(axonName)/\(axonIndexFile)") + return url + } + + class func getLocalAxonBeacons(axonName: String) -> [[String:String]] { + var ret = [] + let filemanager:NSFileManager = NSFileManager() + let path = "\(installedAxonsDir)/\(axonName)/\(axonName)-master/beacons.json" + if filemanager.fileExistsAtPath(path) { + let beaconJSON = JSON(data: NSData(contentsOfFile: path)!) + ret = beaconJSON.arrayValue.map({ (json) -> [String:String] in + var dict = [String:String]() + for (key, val):(String, JSON) in json { + dict[key] = val.stringValue + } + return dict + }) + } + + return ret as! [[String : String]] + } + + class func removeLocalAxon(axonName: String) -> Bool { + let path = "\(installedAxonsDir)/\(axonName)" + let fileManager = NSFileManager.defaultManager() + + //DELETE SUBFOLDER + do { + try fileManager.removeItemAtPath(path) + return true + } + catch let error as NSError { + print("Ooops! Something went wrong: \(error)") + } + + return false + + } + + //blocking task, TODO: implement caching + class func getRemoteAxonList() -> Array>{ + + let endpoint = NSURL(string: remoteAxonTestingRepo) + + if let data = NSData(contentsOfURL: endpoint!) { + + let json = JSON(data: data); + remoteAxonList = Array>() + + //get the individual package details by going through the jsons in the repo + for (_,axon_metadata) in json{ + + let axon_json_url = NSURL(string: axon_metadata["download_url"].stringValue) + let axon_json = NSData(contentsOfURL: axon_json_url!) + let axon = JSON(data: axon_json!); + let arrayOfStrings: [String] = [axon["name"].stringValue, axon["title"].stringValue, axon["description"].stringValue, axon["icon"].stringValue, axon["repository"]["url"].stringValue, axon["author"].stringValue] + remoteAxonList.append(arrayOfStrings) + } + }else{ + print("cannot download remote axon list") + } + + return remoteAxonList + } + } diff --git a/nervous/Stores/SensorStore.swift b/nervous/Stores/SensorStore.swift index 1339f0e..980dbe2 100755 --- a/nervous/Stores/SensorStore.swift +++ b/nervous/Stores/SensorStore.swift @@ -21,7 +21,7 @@ class SensorStore : NSObject, BeaconControllerDelegate { let Magnetometer : MagnetometerController //let Proximity : ProximityController let Accelerometer : AccelerometerController - //let Beacon : BeaconController + let Beacon : BeaconController let BLE : BLEController let GPS : GPSController @@ -32,7 +32,6 @@ class SensorStore : NSObject, BeaconControllerDelegate { //initialise all sensor controllers override init(){ - self.Gyroscope = GyroscopeController.sharedInstance self.Gyroscope.initializeUpdate(self.VM.defaults.doubleForKey("freqGyr")) @@ -52,13 +51,11 @@ class SensorStore : NSObject, BeaconControllerDelegate { self.GPS = GPSController.sharedInstance self.GPS.initializeUpdate(self.VM.defaults.doubleForKey("freqGPS")) - //self.Beacon = BeaconController() - - // BEACONS - //attach delegates - /*self.Beacon.delegate = self; - self.Beacon.requestAuthorization() - self.Beacon.startSensorUpdates()*/ + + // BEACONS + self.Beacon = BeaconController.sharedInstance + + super.init() } @@ -66,7 +63,12 @@ class SensorStore : NSObject, BeaconControllerDelegate { func controller(controller: BeaconController, didRangeBeacons: [CLBeacon]) { //here are new beacons: didRangeBeacons, do something with them - print("%d beacons found!", didRangeBeacons.count); +// print("\(didRangeBeacons.count) beacons found!"); + +// if didRangeBeacons.count > 0 { +// let b = didRangeBeacons.first +// print(b.debugDescription) +// } } func controller() { @@ -84,5 +86,10 @@ class SensorStore : NSObject, BeaconControllerDelegate { self.GPS.requestAuthorization() self.GPS.startSensorUpdates() + + self.Beacon.delegate = self; + self.Beacon.requestAuthorization() +// self.Beacon.startSensorUpdates() + } } diff --git a/nervousnet.xcodeproj/project.pbxproj b/nervousnet.xcodeproj/project.pbxproj index ac6f1e7..633b52b 100755 --- a/nervousnet.xcodeproj/project.pbxproj +++ b/nervousnet.xcodeproj/project.pbxproj @@ -355,7 +355,7 @@ TargetAttributes = { 22316DD619BFB422006FD165 = { CreatedOnToolsVersion = 6.0; - DevelopmentTeam = 5R8S596684; + DevelopmentTeam = CTYNX6RBRP; }; 22316DEA19BFB422006FD165 = { CreatedOnToolsVersion = 6.0;