diff --git a/CHANGELOG.md b/CHANGELOG.md index 75d440d58..fd1ac91d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## 5.0.0-alpha.5 (November 22, 2017) + +Improvements: + +- Estimote Cloud's Analytics events are cached and sent in batches. +- `ESTProximityObserver`'s error block is invoked with error object having domain & error codes defined in `ESTProximityObserver.h`. +- Renamed `ESTProximityZone`'s `onEnterBlock`, `onExitBlock`, `onChangeBlock` to `onEnterAction`, `onExitAction`, `onChangeAction` for better compatibility with Android Proximity SDK. + +Bugfixes: + +- Fixed a bug where Estimote Monitoring would ignore use motion detection. + ## 5.0.0-alpha.4 (October 20, 2017) Improvements: diff --git a/EstimoteSDK.podspec b/EstimoteSDK.podspec deleted file mode 100644 index f2d895792..000000000 --- a/EstimoteSDK.podspec +++ /dev/null @@ -1,22 +0,0 @@ -Pod::Spec.new do |s| - s.name = "EstimoteSDK" - s.version = "5.0.0-alpha.4" - s.summary = "iOS library for Estimote devices" - s.homepage = "https://estimote.com" - s.author = { "Estimote, Inc" => "contact@estimote.com" } - s.platform = :ios - s.source = { :git => "https://github.com/Estimote/iOS-SDK.git", :tag => "5.0.0-alpha.4" } - s.source_files = 'EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/*.h' - s.vendored_frameworks = 'EstimoteSDKv5/EstimoteSDKv5.framework' - s.ios.deployment_target = '8.0' - s.frameworks = 'UIKit', 'Foundation', 'SystemConfiguration', 'MobileCoreServices', 'CoreLocation', 'CoreBluetooth' - s.requires_arc = true - s.xcconfig = { 'LIBRARY_SEARCH_PATHS' => '"$(PODS_ROOT)/EstimoteSDKv5"', - 'HEADER_SEARCH_PATHS' => '"${PODS_ROOT}/Headers/EstimoteSDKv5"' } - s.license = { - :type => 'Copyright', - :text => <<-LICENSE - Copyright 2017 Estimote, Inc. All rights reserved. - LICENSE - } -end diff --git a/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/EstimoteSDKv5 b/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/EstimoteSDKv5 index d76767f1b..fd15498dd 100644 Binary files a/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/EstimoteSDKv5 and b/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/EstimoteSDKv5 differ diff --git a/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/ESTCloudCredentials.h b/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/ESTCloudCredentials.h index 1700c7b64..c8a64c3af 100644 --- a/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/ESTCloudCredentials.h +++ b/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/ESTCloudCredentials.h @@ -15,11 +15,8 @@ NS_ASSUME_NONNULL_BEGIN /** - Estimote Cloud credentials available as a singleton. - Go to https://cloud.estimote.com/#/apps to acquire them. - - You should call `+setUpSharedInstanceWithAppID:appToken:` and `+sharedInstance` to get an instance of this class. - However, if you really need a non-singleton instance, use `-initWithAppID:appToken`. + Estimote Cloud credentials encapsulated in a value object. To acquire App ID & App Token go to + https://cloud.estimote.com/#/apps. */ @interface ESTCloudCredentials : NSObject @@ -33,14 +30,6 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, strong, readonly) NSString *appToken; -/** - Cloud credentials singleton. - - Note: this property is set by `+setUpSharedInstanceWithAppID:appToken:`. If the method wasn't called yet, or - after `+removeSharedInstance` was called, this property is nil. - */ -@property (nonatomic, strong, readonly, class, nullable) ESTCloudCredentials *sharedInstance NS_SWIFT_NAME(shared); - /** Init is disabled for this class. */ @@ -59,21 +48,6 @@ NS_ASSUME_NONNULL_BEGIN */ - (instancetype)initWithAppID:(NSString *)appID appToken:(NSString *)appToken NS_DESIGNATED_INITIALIZER; -/** - Create a shared instance and store it globally. Calling this method causes +sharedInstance - to return an object instead of nil. - - @param appID App ID generated in Estimote Cloud. - @param appToken App Token generated in Estimote Cloud. - */ -+ (void)setUpSharedInstanceWithAppID:(NSString *)appID - appToken:(NSString *)appToken NS_SWIFT_NAME(setUpSharedInstance(appID:appToken:)); - -/** - Remove shared instance. Calling this method causes `+sharedInstance` to return nil. - */ -+ (void)removeSharedInstance; - @end NS_ASSUME_NONNULL_END diff --git a/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/ESTProximityObserver.h b/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/ESTProximityObserver.h index bcc6d43bb..4b5557562 100644 --- a/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/ESTProximityObserver.h +++ b/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/ESTProximityObserver.h @@ -16,6 +16,32 @@ NS_ASSUME_NONNULL_BEGIN +FOUNDATION_EXPORT NSString * const ESTProximityObserverErrorDomain; + +/** + Possible errors invoked with Proximity Observer's error block. + */ +typedef NS_ENUM(NSUInteger, ESTProximityObserverError) { + /* Unknown error probably due to a bug. If you're getting errors with this code please report it on + * https://forums.estimote.com, using contact@estimote.com or filing an issue on Github. */ + ESTProximityObserverErrorUnknown = 0, + + /* Fetching attachments from Cloud failed. */ + ESTProximityObserverErrorFetchingAttachmentsFailed, + + /* Observed zone doesn't match any attachments fetched from Cloud. */ + ESTProximityObserverErrorNoAttachmentsMatchingZone, + + /* Bluetooth is unsupported on this iOS device. */ + ESTProximityObserverErrorBluetoothUnsupported, + + /* Bluetooth is turned off. */ + ESTProximityObserverErrorBluetoothOff, + + /* Couldn't use motion detection. */ + ESTProximityObserverErrorMotionDetectionFailed, +}; + /** Observes and reports proximity of Estimote devices. Uses Estimote Monitoring under the hood. Encapsulates it under tag-based beacon identification and callback blocks. @@ -33,10 +59,10 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype)new NS_UNAVAILABLE; /** - Designated initializer. - - @param credentials Cloud Credentials object. You can use `+[ESTCloudCredentials sharedInstance]` to get it. - @param errorBlock Cloud Credentials object. You can use `+[ESTCloudCredentials sharedInstance]` to get it. + Default initializer. + @param credentials Cloud Credentials object used to authorize requests sent to Estimote Cloud. + @param errorBlock Block invoked whenever error occurs. The parameter is an NSError object, with + domain equal to ESTProximityObserverErrorDomain and code from ESTProximityObserverError enum. */ - (instancetype)initWithCredentials:(ESTCloudCredentials *)credentials errorBlock:(void (^)(NSError *error))errorBlock; @@ -47,10 +73,20 @@ NS_ASSUME_NONNULL_BEGIN - start Estimote Monitoring at registered ranges, - call registered enter/exit/change blocks when proximity event occurs. + Subsequent calls of this method cause overwriting previously observed zones. + @param zones Zones to be observed */ - (void)startObservingZones:(NSArray *)zones; +/** + Stop observing and calling callbacks for all zones that were provided with -startObservingZones:, + release memory resources allocated for monitoring the zones. + + Subsequent calls of this method (without re-starting observing zones) have the same effect as calling it just once. + */ +- (void)stopObservingZones; + @end NS_ASSUME_NONNULL_END diff --git a/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/ESTProximityZone.h b/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/ESTProximityZone.h index aa94c8041..ea4fdf603 100644 --- a/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/ESTProximityZone.h +++ b/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/ESTProximityZone.h @@ -41,19 +41,19 @@ NS_ASSUME_NONNULL_BEGIN Register block to be called when user enters proximity of Estimote devices with matching attachment. Beacon identification is attachment-based (see https://github.com/Estimote/iOS-SDK/blob/sdk_5/README.md for more info). */ -@property (nonatomic, copy, readwrite, nullable) void (^onEnterBlock)(ESTProximityDeviceAttachment *triggeringDeviceAttachment); +@property (nonatomic, copy, readwrite, nullable) void (^onEnterAction)(ESTProximityDeviceAttachment *triggeringDeviceAttachment); /** Block to be called when user exits proximity of Estimote devices with matching attachment. Beacon identification is attachment-based (see https://github.com/Estimote/iOS-SDK/blob/sdk_5/README.md for more info). */ -@property (nonatomic, copy, readwrite, nullable) void (^onExitBlock)(ESTProximityDeviceAttachment *triggeringDeviceAttachment); +@property (nonatomic, copy, readwrite, nullable) void (^onExitAction)(ESTProximityDeviceAttachment *triggeringDeviceAttachment); /** Block to be called each time a new beacon is detected in user's range and each time a beacon disappears from user's range. */ -@property (nonatomic, copy, readwrite, nullable) void (^onChangeBlock)(NSSet *attachmentsCurrentlyInside); +@property (nonatomic, copy, readwrite, nullable) void (^onChangeAction)(NSSet *attachmentsCurrentlyInside); /** Init is unavailable. diff --git a/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/EstimoteSDKv5.h b/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/EstimoteSDKv5.h index b994ba72f..a9cad85df 100644 --- a/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/EstimoteSDKv5.h +++ b/EstimoteSDKv5/EstimoteSDKv5.framework/Versions/A/Headers/EstimoteSDKv5.h @@ -7,7 +7,7 @@ // |______|___/\__|_|_| |_| |_|\___/ \__\___| |_____/|_____/|_|\_\ // // -// Version: 5.0.0-alpha.4 +// Version: 5.0.0-alpha.5 // Copyright (c) 2017 Estimote. All rights reserved. #import "ESTCloudCredentials.h" diff --git a/Examples/swift/DeskObserver/DeskObserver/AppDelegate.swift b/Examples/swift/DeskObserver/DeskObserver/AppDelegate.swift index 14bc09acc..8fba3b4db 100644 --- a/Examples/swift/DeskObserver/DeskObserver/AppDelegate.swift +++ b/Examples/swift/DeskObserver/DeskObserver/AppDelegate.swift @@ -12,10 +12,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { - // TODO: put your App ID and App Token here - // You can get them by adding your app on https://cloud.estimote.com/#/apps - ESTCloudCredentials.setUpSharedInstance(appID: "<#App ID#>", appToken: "<#App Token#>") - return true } diff --git a/Examples/swift/DeskObserver/DeskObserver/ViewController.swift b/Examples/swift/DeskObserver/DeskObserver/ViewController.swift index 9e784a5fb..0ff10e7e1 100644 --- a/Examples/swift/DeskObserver/DeskObserver/ViewController.swift +++ b/Examples/swift/DeskObserver/DeskObserver/ViewController.swift @@ -41,6 +41,10 @@ class ViewController: UIViewController { self.venueLabel.textColor = self.venueColor // ---- Proximity config ---- + + // TODO: put your App ID and App Token here + // You can get them by adding your app on https://cloud.estimote.com/#/apps + let credentials = ESTCloudCredentials(appID: <#your-app-id#>, appToken: <#your-app-token#>) // There's just a one Proximity Observer object used to configure reactions to proximity changes. // The configuration of a zone consists of defining a desired approximate range (0.5m or 1.5m in this example), @@ -55,57 +59,61 @@ class ViewController: UIViewController { // - one of the beacons has a tag `{"attachment":{"blueberry_desk":true,"venue":"office"}}` // - another beacon has a tag `{"attachment":{"mint_desk":true,"venue":"office"}}` - self.proximityObserver = ESTProximityObserver(credentials: ESTCloudCredentials.shared!, errorBlock: { error in - print("Ooops! \(error.localizedDescription)") + self.proximityObserver = ESTProximityObserver(credentials: credentials, errorBlock: { error in + print("Ooops! \(error)") }) let blueberryZone = ESTProximityZone(range: ESTProximityRange.custom(desiredMeanTriggerDistance: 0.5)!, - attachmentKey: "blueberry_desk") - blueberryZone.onEnterBlock = { attachment in + attachmentKey: "desk", + attachmentValue: "blueberry") + blueberryZone.onEnterAction = { attachment in print("Enter blueberry 0.5") self.blueberryDeskLabel.backgroundColor = self.blueberryColor self.blueberryDeskLabel.textColor = UIColor.white } - blueberryZone.onExitBlock = { attachment in + blueberryZone.onExitAction = { attachment in print("Exit blueberry 0.5") self.blueberryDeskLabel.backgroundColor = UIColor.white self.blueberryDeskLabel.textColor = self.blueberryColor } let mintZone = ESTProximityZone(range: ESTProximityRange.custom(desiredMeanTriggerDistance: 0.5)!, - attachmentKey: "mint_desk") - mintZone.onEnterBlock = { attachment in + attachmentKey: "desk", + attachmentValue: "mint") + mintZone.onEnterAction = { attachment in print("Enter mint 0.5") self.mintDeskLabel.backgroundColor = self.mintColor self.mintDeskLabel.textColor = UIColor.white } - mintZone.onExitBlock = { attachment in + mintZone.onExitAction = { attachment in print("Exit mint 0.5") self.mintDeskLabel.backgroundColor = UIColor.white self.mintDeskLabel.textColor = self.mintColor } let closeVenueZone = ESTProximityZone(range: ESTProximityRange.custom(desiredMeanTriggerDistance: 0.5)!, - attachmentKey: "venue") - closeVenueZone.onChangeBlock = { attachmentsInside in + attachmentKey: "venue", + attachmentValue: "office") + closeVenueZone.onChangeAction = { attachmentsInside in print("Currently, there are \(attachmentsInside.count) attachments in ~0.5m range:") print("\(attachmentsInside.map({ $0.json.description }).joined(separator: "\n"))") print("") } let midVenueZone = ESTProximityZone(range: ESTProximityRange.custom(desiredMeanTriggerDistance: 1.5)!, - attachmentKey: "venue") - midVenueZone.onEnterBlock = { attachment in + attachmentKey: "venue", + attachmentValue: "office") + midVenueZone.onEnterAction = { attachment in print("Enter venue 1.5") self.venueLabel.backgroundColor = self.venueColor self.venueLabel.textColor = UIColor.white } - midVenueZone.onExitBlock = { attachment in + midVenueZone.onExitAction = { attachment in print("Exit venue 1.5") self.venueLabel.backgroundColor = UIColor.white self.venueLabel.textColor = self.venueColor } - midVenueZone.onChangeBlock = { attachmentsInside in + midVenueZone.onChangeAction = { attachmentsInside in print("Currently, there are \(attachmentsInside.count) attachments in ~1.5m range:") print("\(attachmentsInside.map({ $0.json.description }).joined(separator: "\n"))") print("") diff --git a/README.md b/README.md index cbf40f92b..765ef2526 100644 --- a/README.md +++ b/README.md @@ -66,8 +66,8 @@ To get a working prototype, check out the [Desk Observer](Examples/swift/DeskObs The demo requires at least two Proximity or Location beacons configured for Estimote Monitoring. It's enabled by default in dev kits shipped after mid-September 2017; to enable it on your own check out the [instructions](https://community.estimote.com/hc/en-us/articles/226144728-How-to-enable-Estimote-Monitoring-). The demo expects beacons having specific tags assigned: -- `{"attachment":{"blueberry_desk":true,"venue":"office"}}` for the first one, -- `{"attachment":{"mint_desk":true,"venue":"office"}}` for the second one. +- `{"attachment":{"desk":"blueberry","venue":"office"}}` for the first one, +- `{"attachment":{"desk":"mint","venue":"office"}}` for the second one. These attachments can be used to define the zones presented below: @@ -98,29 +98,30 @@ Tags are Cloud-only settings — no additional connecting to the beacons with th To use the SDK within your app, go to the [apps section](https://cloud.estimote.com/#/apps) in Estimote Cloud. Register a new app or use one of the available templates to obtain App ID & App Token credentials pair. -In your app (i.e. in AppDelegate), set up the credentials using `ESTCloudCredentials`: +In your app, set up the credentials using `ESTCloudCredentials`: ```swift -ESTCloudCredentials.setUpSharedInstance(appID: "your-app-id", appToken: "your-app-token") +let credentials = ESTCloudCredentials(appID: "your-app-id", appToken: "your-app-token") ``` Then, configure proximity discovery with `ESTProximityObserver`. For more info on attachments, see [this section](#attachment-based-identification). ```swift // Create observer instance -self.proximityObserver = ESTProximityObserver(credentials: ESTCloudCredentials.shared!, errorBlock: { error in - print("Ooops! \(error.localizedDescription)") +self.proximityObserver = ESTProximityObserver(credentials: credentials, errorBlock: { error in + print("Ooops! \(error)") }) // Define zones let blueberryZone = ESTProximityZone(range: ESTProximityRange.custom(meanTriggerDistance: 0.5)!, - attachmentKey: "blueberry_desk") -blueberryZone.onEnterBlock = { attachment in - print("Entered near range of 'blueberry_desk'. Full beacon attachment: (attachment.attachmentJSON)") + attachmentKey: "desk", + attachmentValue: "blueberry") +blueberryZone.onEnterAction = { attachment in + print("Entered near range of 'desk':'blueberry'. Full beacon attachment: (attachment.attachmentJSON)") } -blueberryZone.onExitBlock = { (attachment) in - print("Exited near range of 'blueberry_desk'. Full beacon attachment: (attachment.attachmentJSON)") +blueberryZone.onExitAction = { (attachment) in + print("Exited near range of 'desk':'blueberry'. Full beacon attachment: (attachment.attachmentJSON)") } // ... etc. You can define as many zones as you need. diff --git a/readme_images/adding_attachment_json_tag.png b/readme_images/adding_attachment_json_tag.png index edc7b02ab..c4ecdfd0b 100644 Binary files a/readme_images/adding_attachment_json_tag.png and b/readme_images/adding_attachment_json_tag.png differ diff --git a/readme_images/demo_attachments.png b/readme_images/demo_attachments.png index 584cc3062..9f3aabebb 100644 Binary files a/readme_images/demo_attachments.png and b/readme_images/demo_attachments.png differ