Giter VIP home page Giter VIP logo

ios-sdk's Introduction

ActiveLookSDK

Requirements

In order to use the ActiveLook SDK for iOS, you should have XCode installed together with cocoapods. The SDK is also available using SPM.

License

See LICENCE. TLDR: Apache License 2.0

Installation

CocoaPods

To integrate ActiveLookSDK into your Xcode project using CocoaPods, specify it in your Podfile:

pod 'ActiveLookSDK',
    :git => 'https://github.com/ActiveLook/ios-sdk.git',
    :tag = 'v4.5.4'

Then run the command: `pod install'

An example Podfile is included in the demo-app repo available on github at demo-app

Swift Package Manager

To integrate ActiveLookSDK into your Xcode project using SPM, add a new package with the url https://github.com/ActiveLook/ios-sdk.git using the main branch.

Info.plist

To access Core Bluetooth APIs on apps linked on or after iOS 13, fill in the NSBluetoothAlwaysUsageDescription key in your app's Info.plist.

Also, add the App Transport Security Settings dictionary with the Allow Arbitrary Loads key set to YES.

Example

To test the SDK, clone the demo-app: git clone https://github.com/ActiveLook/demo-app.git

Documentation

The code is commented so that the documentation can be built on your machine using Xcode's Build configuration command, enabling symbolic documentation.

Initialization

To start using the SDK, first import the ActiveLookSDK module:

import ActiveLookSDK

Then, use its shared property to access the shared singleton. This can be called from anywhere within your application.

var activeLook: ActiveLookSDK = ActiveLookSDK.shared

Then, use its shared property to access the shared singleton. This can be called from anywhere within your application.

Scanning

To scan for available ActiveLook glasses, simply use startScanning( onGlassesDiscovered: onScanError: ).

When a device is discovered, the onGlassesDiscovered callback will be called. Upon failure, the onScanError callback will be called instead.

You can handle these cases by providing closures as parameters:

activeLook.startScanning(
    onGlassesDiscovered: { [weak self] (discoveredGlasses: DiscoveredGlasses) in
        print("discovered glasses: \(discoveredGlasses.name)")
        self?.addDiscoveredGlasses(discoveredGlasses)

    }, onScanError: { (error: Error) in
        print("error while scanning: \(error.localizedDescription)")
    }
)

To stop scanning, call stopScanning().

Connect to ActiveLook glasses

To connect to a pair of discovered glasses, use the connect(onGlassesConnected:onGlassesDisconnected:onConnectionError:) method on the DiscoveredGlasses object.

If the connection is successful, the onGlassesConnected callback will be called and will return a Glasses object, which can then be used to get information about the connected ActiveLook glasses or send commands.

If the connection fails, the onConnectionError callback will be called instead.

Finally, if the connection to the glasses is lost at any point, later, while the app is running, the onGlassesDisconnected callback will be called.

discoveredGlasses.connect(
    onGlassesConnected: { (glasses: Glasses) in
        print("glasses connected: \(glasses.name)")
}, onGlassesDisconnected: {
        print("disconnected from glasses")
}, onConnectionError: { (error: Error) in
        print("error while connecting to glasses: \(error.localizedDescription)")
})

If you need to share the Glasses object between several View Controllers, and you find it hard or inconvenient to hold onto the onGlassesDisconnected callback, you can reset it or provide a new one by using the onDisconnect() method on the Glasses object:

glasses.onDisconnect { [weak self] in
    guard let self = self else { return }

    let alert = UIAlertController(title: "Glasses disconnected", message: "Connection to glasses lost", preferredStyle: .alert)
    self.present(alert, animated: true)
}

Device information

To get information relative to discovered glasses as published over Bluetooth, you can access the following public properties:

// Print the name of the glasses
print(discoveredGlasses.name)

// Print the glasses' manufacturer id
print(discoveredGlasses.manufacturerId)

// Print the glasses' identifier
print(discoveredGlasses.identifier)

Once connected, you can access more information about the device such as its firmware version, the model number etc... by using the getDeviceInformation() method:

// Print the model number
print(connectedGlasses.getDeviceInformation().modelNumber)

Commands

All available commands are exposed as methods in the Glasses class. Examples are available in the Example application.

Most commands require parameters to be sent.

// Power on the glasses
glasses.power(on: true)

// Set the display luminance level
glasses.luma(level: 15)

// Draw a circle at the center of the screen
glasses.circ(x: 152, y: 128, radius: 50)

// Enable gesture detection sensor
glasses.gesture(enabled: true)

When a response is expected from the glasses, a closure can be provided to the callback parameter. (The callback will be called asynchronously)

glasses.battery { (batteryLevel : Int) in
    print("current battery level: \(batteryLevel)")
}

Notifications

It is possible to subscribe to three types of notifications from the glasses. Once notified, the corresponding closure is called, if provided.

  • Battery level updates:
glasses.subscribeToBatteryLevelNotifications(onBatteryLevelUpdate: { (batteryLevel: Int) -> (Void) in
    print("battery level update: \(batteryLevel)")
})

-> An update is sent periodically, every 30 second.

  • Gesture detection sensor triggered
glasses.subscribeToFlowControlNotifications(onFlowControlUpdate: { (flowControlState: FlowControlState) -> (Void) in
    print("flow control state update: \(flowControlState)")
})
  • Flow control events (when the state of the flow control changes)
glasses.subscribeToSensorInterfaceNotifications(onSensorInterfaceTriggered: { () -> (Void) in
    print("sensor interface triggered")
})

-> Only non-internal states are passed thru. See Public > ActiveLookType.swift : public enum FlowControlState{} for more information.

Disconnect

When done interacting with ActiveLook glasses, simply call the disconnect() method:

glasses.disconnect()

Acknolegment

We are currently using code from nobre84/heatshrink-objc (thanks to him). We did'nt find a easiest way to use it than add it to our code.

ios-sdk's People

Contributors

activelook-dev avatar kiiks avatar pierrerougeotf avatar sylvainromillon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

ios-sdk's Issues

SDK unusable because of required updater calls

It seems we need to instantiate the SDK using:

public static func shared(token: String? = nil,
                              onUpdateStartCallback: StartClosureSignature? = nil,
                              onUpdateAvailableCallback: UpdateAvailableClosureSignature? = nil,
                              onUpdateProgressCallback: ProgressClosureSignature? = nil,
                              onUpdateSuccessCallback: SuccessClosureSignature? = nil,
                              onUpdateFailureCallback: FailureClosureSignature? = nil) throws -> ActiveLookSDK

Which for normal development purposes is useless, as we can leave the entire update responsibility to the ActiveLook app.

Because a normal developer does not have the token nor the possibility to download firmware updates, the only solution is to pass bogus parameters and return false in onUpdateAvailableCallback. This however stops the SDK from functioning returning:

                        discoveredGlasses.connectionErrorCallback?(ActiveLookError.sdkUpdateFailed)
                        self.updateParameters.notify(.updateFailed)

The error originates in:

            guard httpResponse.statusCode != 403 else {
                self.failed(with: GlassesUpdateError.invalidToken)
                return
            }

which makes sense since we don't have the right token to check for updates.

I forked the repo and I fixed it by putting this in the code:

                glasses.fixInDeviceCmdStack {
                    glasses.cfgSet(name: "ALooK")
//                    parent.updateInitializedGlasses(glasses) --> this is not needed for 3rd party devs!
                    discoveredGlasses.connectionCallback?(glasses)
                }

Problème de scan si instantiation "trop rapide" de ActivelookSDK

Lorsqu'on instancie ActiveLookSDK et qu'on souhaite démarrer un scan dans la foulée, cela ne fonctionne pas.

En effet, startScanning nécessite la condition centralManager.state == .poweredOn, ce qui n'est pas le cas à l'instantiation du SDK.
Je pense que :

  • l'état initial doit être unknown
  • Il faut attendre que le delegate centralManagerDidUpdateState recoive l'état poweredOn avant de lancer le scan.

Propositions :

  • Empêcher le scan seulement si le bluetooth est en état powerOff, unauthorized ou unsupported.
  • Ou "garder" en mémoire la demande de scan (et toutes autres actions ?) pour l'effectuer lors de la notification de l'état poweredOn.
    Voir ici pour la liste des différents états possibles.

(Pour info, le fix "temporaire" réalisé de mon côté a été d'ajouter un timer de 300 ms avant de demander le scan).

Background Mode crash on watchOS

After many switches between foreground and background modes on the Apple Watch application, a crash in Glasses.sendBytes occurs

Force cast provoque des crashs

La présence de force-cast provoque parfois des crashs.

Notamment, j'ai déjà eu 2-3 crashs lié à la classe Glasses, ligne 234 :
peripheral.writeValue(value, for: rxCharacteristic!, type: .withResponse)

Pour éviter les problèmes, remplacer par :

if let rxCharacteristic = rxCharacteristic {
  peripheral.writeValue(value, for: rxCharacteristic, type: .withResponse)
}

Wrong firmware comparison

There is an issue with the following methods

public func isFirmwareAtLeast(version: String) -> Bool {
let gVersion = self.getDeviceInformation().firmwareVersion
guard gVersion != nil else { return false }
if (gVersion ?? "" >= "v\(version).0b") {
return true
} else {
return false
}
}
/// Compare the firmware against a certain version
/// - Parameter version: the version to compare to
public func compareFirmwareAtLeast(version: String) -> ComparisonResult {
let gVersion = self.getDeviceInformation().firmwareVersion
return (gVersion ?? "").compare("v\(version).0b")
}

Indeed, with this comparison we have: 4.3.0 <= 4.10.0 == false.

You should use this option to compare https://developer.apple.com/documentation/foundation/nsstring/compareoptions/1415530-numeric.

You can refer to this article for a working solution

ActiveLookSDK.shared() does not reflect its documentation

The documentation for ActiveLookSDK.shared method states either to fill all parameters or to give no parameters at all to the method

// This is the method used to initialize the ActiveLookSDK singleton and access it later on.
// To initialize it, this function is called with all parameters set.
// To access it afterwards, just call it without any arguments: ActiveLookSDK.shared()
// - throws:
// - ActiveLookError.sdkInitMissingParameters
// if the function is called with incomplete parameters.
// - ActiveLookError.sdkCannotChangeParameters
// if the function is called more than once during the application's lifetime, with all the parameters correctly set.
// - parameters:
// - token: The token used for authenticating with the firmware repository.
// - onUpdateStart Registered callback for update start event notification
// - onUpdateProgress Registered callback for update progress event notification.
// - onUpdateSuccess Registered callback for update success event notification.
// - onUpdateError Registered callback for update error event notification.
// - returns: the ActiveLookSDK's singleton
//

The method signature is not compliant with that

public static func shared(token: String? = nil,
                              onUpdateStartCallback: startClosureSignature? = nil,
                              onUpdateProgressCallback: progressClosureSignature? = nil,
                              onUpdateSuccessCallback: successClosureSignature? = nil,
                              onUpdateFailureCallback: failureClosureSignature? = nil) throws -> ActiveLookSDK

Furthermore, in swift coding style Type names start with an uppercase

Changelog 4.2 does not reflect some updates

For instance,
ActiveLook.shared is deprecated, ActiveLook.shared() should be called instead, it however requires a unique prior call to

ActiveLook.shared(token: String,
                  onUpdateStartCallback: @escaping StartClosureSignature,
                  onUpdateProgressCallback: @escaping ProgressClosureSignature,
                  onUpdateSuccessCallback: @escaping SuccessClosureSignature,
                  onUpdateFailureCallback: @escaping FailureClosureSignature)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.