Getting Started
IntroductionVision and MissionFor Users
Nodle IoTNodle AppNodle ClientNodle on zkSync EraNodle PortalNODL TokenNFT Minting ToolNodle ExplorerParticipateFor Developers
SubQuery IndexerNodle APIsNodle ParachainParachain ModulesNodle SDKNodle Android SDKNodle iOS SDKSmart MissionsMore Info
AppendixGlossaryiOS SDK Integration
Integrating the Nodle SDK into your iOS app is easy and straightforward. You can use our NodleSDK Quickstart application or just follow the steps below and you should be ready to go in no time.
- Generate Developer Key
- Go and Create a Nodle account
- Make sure you save your private key!
- Copy your
public_key
from the extension - Proceed with the next steps
- Install the SDK
- NodleSDK
- NodleSDK - Fetching specific version
- NodleSDK without CoreBluetooth
- NodleSDK - Fetching specific version - XCode 15
- NodleSDK without CoreBluetooth - XCode 15
- Add the SDK manually:
- NodleSDK issues with dependencies:
- NodleSDK requirements:
- Add the NodleSDK dependency: The SDK depends on Apple's
CoreLocation, CoreBluetooth
framework. In your target settings, go to General > Frameworks, Libraries, and Embedded Content and addCoreLocation, CoreBluetooth
if you haven't already. If you are using the build without CoreBluetooth you will need to add only CoreLocation - Initialize the Nodle SDK: You need to init the NodleSDK in your AppDelegate like below:
- Swift
- Swift
- Request Permissions: Before requesting permissions, you must add location usage strings to your
Info.plist
file. We require a couple permissions and they have to be added like below: - Request permissions manually for NodleSDK without any third party:
- Request permissions manually for NodleSDKWCB without any third party:
- Request permissions via third party - SPPermissions
- Run the Nodle SDK: In the
AppDelegate
orViewController
you can start Nodle by giving it your public key in the following formatss58:public_key
generated in Step 1:
Install the SDK via CocoaPods. If you don't have an existing Podfile, run pod init in your project directory. Add the following to your Podfile:
Swift
pod 'NodleSDK', :git => '
https://github.com/NodleCode/NodleSDK-Release
'
Swift
pod 'NodleSDK', :git => '
https://github.com/NodleCode/NodleSDK-Release
', :branch => 'main', :tag => '0.0.21'
Swift
pod 'NodleSDKWCB', :podspec => '
https://raw.githubusercontent.com/NodleCode/NodleSDK-Release/main/NodleSDKWCB.podspec
'
Swift
pod 'NodleSDK', :git => '
https://github.com/NodleCode/NodleSDK-Release
', :branch => 'night', :tag => '0.0.23-night'
Swift
pod 'NodleSDKWCB', :podspec => '
https://raw.githubusercontent.com/NodleCode/NodleSDK-Release/night/NodleSDKWCB.podspec
'
The latest version of the SDK is 0.0.23-night
We recommend to add the following dependency which should be automatically pulled but if you encounter any issues you can add them to your Podfile like this:
Pods for NodleSDK
pod 'SQLite.swift', '~> 0.15.3'
pod 'SwiftCBOR', '~> 0.4.5'
pod 'SwiftProtobuf', '~> 1.26.0'
Then, run pod install
. You may also need to run pod install --repo-update
.
You can also add the SDK to your project manually. Download the current release, unzip the package, and drag the version of the SDK that you want use for example the version with CoreBluetooth NodleSDK.xcframework into your Xcode project. It will automatically appear in the Frameworks, Libraries, and Embedded Content section of your target settings. Switch Do Not Embed to Embed & Sign. We recommend to add the following dependency which should be automatically pulled but if you encounter any issues you can add them to your Podfile like this:
Pods for NodleSDK
pod 'SQLite.swift', '~> 0.15.3'
pod 'SwiftCBOR', '~> 0.4.5'
pod 'SwiftProtobuf', '~> 1.26.0'
Then, run pod install
. You may also need to run pod repo update. If you run into trouble with pod please install cocoapods-deintegrate and run pod deintegrate and also you would need to remove your cache we recommend you do the following:
rm -rf ~/Library/Caches/CocoaPods; rm -rf Pods; rm -rf ~/Library/Developer/Xcode/DerivedData/*; pod deintegrate;
Then make sure you are using one of the latest cocoapods versions 1.11+ due to issues with cocoapods not picking dependency properly you need to set the following script on top of your Podfile. You can find example Podfile below:
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
end
end
end
# If any errors for example dyld: Symbol not found please use pod deintegrate and pod install again. You should remove your
# Podfile.lock and workspace and let cocoapods generate it for you if you are having
# trouble. Make sure you close and open the workspace when you are doing all above before
# pod install again.
platform :ios, '13.0'
# use_modular_headers!
target 'YourTarget' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for TestApp
pod 'NodleSDK'
pod 'SQLite.swift', '~> 0.15.3'
pod 'SwiftCBOR', '~> 0.4.5'
pod 'SwiftProtobuf', '~> 1.26.0'
endYou could do the same manually by adding the ['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES' to your Pod project settings. If you are on older version of cocoapods before 1.9- you will not need to do anything and you can simply proceed to next steps.
NodleSDK issues with dependencies:
If you are experiencing issues please make sure the correct version of the dependencies are in your Podfile.lock as an example with our latest version of the dependencies found here NodleSDK 0.0.21:
You could do the same manually by adding the ['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES' to your Pod project settings. If you are on older version of cocoapods before 1.9- you will not need to do anything and you can simply proceed to next steps.
If you are experiencing issues please make sure the correct version of the dependencies are in your Podfile.lock as an example with our latest version of the dependencies found here NodleSDK 0.0.23-night:
SQLite.swift: 8d054987f02728cc912b0eb5a9659650573a65a2
SwiftCBOR: ac340b74d3b2cf1f8884bb748bd09875848e3873
SwiftProtobuf: 5e8349171e7c2f88f5b9e683cb3cb79d1dc780b3
If you are having trouble with the dependencies loading for older versions of our SDK please make sure they are corrected in the Podfile.lock file. After you have corrected them in the file to the correct versions and CHECKSUMS simply run pod install.
We are currently using the following setup:
cocoapods: 1.13+
swift: 5+
XCode: 15 and above
build-system: New Build System
ios: 13.0+
import UIKit
import SwiftCBOR
import SwiftProtobuf
import NodleSDK
import SQLite
import CoreLocation
import CoreBluetooth
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
let nodle = Nodle.sharedInstance
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}
}
Or you can initialize the NodleSDK in your ViewController like below:
import UIKit
import SwiftCBOR
import SwiftProtobuf
import NodleSDK
import SQLite
import CoreLocation
import CoreBluetooth
class ViewController: UIViewController, CLLocationManagerDelegate, CBCentralManagerDelegate {
private let locationManager = CLLocationManager()
var centralManager: CBCentralManager?
let nodle = Nodle.sharedInstance
}
Then you can proceed to next steps below. Please make sure that you have added and request all permissions and dependency before you run the SDK.
// NodleSDK
NSBluetoothAlwaysUsageDescription - Need for our bluetooth scan
NSBluetoothPeripheralUsageDescription - Need for our bluetooth scan
NSLocationAlwaysUsageDescription - Need for our location request from the background
NSLocationAlwaysAndWhenInUseUsageDescription - Need for our location request from background
NSLocationWhenInUseUsageDescription - Need for our location request
NSLocationUsageDescription - Need to be able to perform additional changes to
location while in the background.
// NodleSDKWCB
NSLocationAlwaysUsageDescription - Need for our location request from the background
NSLocationAlwaysAndWhenInUseUsageDescription - Need for our location request from the background
NSLocationWhenInUseUsageDescription - Need for our location request
NSLocationUsageDescription - Need to be able to perform additional changes to
location while in the background.
Here is a small example how it should look like when configured:
The NodleSDK require Bluetooth and Location permissions to be added before it is started. The NodleSDKWCB doesn't require Bluetooth. Then you can proceed to next step and request permissions for Location and Bluetooth via one of the two approaches listed below depending on your choice:
import UIKit
import SwiftCBOR
import SwiftProtobuf
import NodleSDK
import SQLite
import CoreLocation
import CoreBluetooth
class ViewController: UIViewController, CLLocationManagerDelegate, CBCentralManagerDelegate {
private let locationManager = CLLocationManager()
var centralManager: CBCentralManager?
let nodle = Nodle.sharedInstance
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// set manager for permissions
locationManager.delegate = self
// check status for location permission
switch CLLocationManager.authorizationStatus() {
case .authorizedWhenInUse, .authorizedAlways:
// request always auth if you would use it in the background otherwise requestWhileInUse
locationManager.requestAlwaysAuthorization()
// ask for bluetooth permissions
centralManager = CBCentralManager(delegate: self, queue: nil)
case .notDetermined:
// request always auth if you would use it in the background otherwise requestWhileInUse
locationManager.requestAlwaysAuthorization()
default:
print("Location permission denied")
break;
}
}
func startNodle() {
// start the sdk
nodle.start(devKey: "ss58:5FUfDdHhtn5Bzgte69zr1NyNRS7zFqy7CnjVcRUUpWpXz3Cv", tags: "","")
}
func stopNodle() {
// stop the sdk
nodle.stop()
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .poweredOn:
// start Nodle after Bluetooth permissions have been granted
startNodle()
break
case .poweredOff:
// stop nodle
stopNodle()
break
default:
break
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
// handle success
if status == .authorizedWhenInUse || status == .authorizedAlways {
print("Location permission have been granted")
// ask for ble permissions
centralManager = CBCentralManager(delegate: self, queue: nil)
}
}
}
import UIKit
import SwiftCBOR
import SwiftProtobuf
import NodleSDK
import SQLite
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
private let locationManager = CLLocationManager()
let nodle = Nodle.sharedInstance
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// set manager for permissions
locationManager.delegate = self
// check status for location permission
switch CLLocationManager.authorizationStatus() {
case .authorizedWhenInUse, .authorizedAlways:
// request always auth if you would use it in the background otherwise requestWhileInUse
locationManager.requestAlwaysAuthorization()
case .notDetermined:
// request always auth if you would use it in the background otherwise requestWhileInUse
locationManager.requestAlwaysAuthorization()
default:
print("Location permission denied")
break;
}
}
func startNodle() {
// start the sdk
nodle.start(devKey: "ss58:5FUfDdHhtn5Bzgte69zr1NyNRS7zFqy7CnjVcRUUpWpXz3Cv", tags: "","")
}
func stopNodle() {
// stop the sdk
nodle.stop()
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
// handle success
if status == .authorizedWhenInUse || status == .authorizedAlways {
print("Location permission have been granted")
// start Nodle after Location permissions have been granted
startNodle()
} else {
// stop nodle if permissions revoked
stopNodle()
}
}
}
We recommend the SPPermissions third party library to request permissions:
// MARK: 1. Choose the permissions you need:
let permissions: [SPPermissions.Permission] = [.location, .bluetooth]
// MARK: 2. Choose present style:
// 2a. List Style
let controller = SPPermissions.list(permissions)
controller.present(on: self)
// 2b. Dialog Style
let controller = SPPermissions.dialog(permissions)
controller.present(on: self)
// 2c. Native Style
let controller = SPPermissions.native(permissions)
controller.present(on: self)
// MARK: 3. Optional: Check permission state (available `authorized`, `denied`, `notDetermined`):
let authorized = SPPermissions.Permission.calendar.authorized
Please follow their guide how to install and setup the request. After permissions are requested and given the NodleSDK should work as expected.
Nodle().start("ss58:public_key")
You can find more info here: Nodle SDK - iOS API and Configuration
And there you have it! You’re good to go!
Run Nodle SDK in Background (Optional)
With our latest update NodleSDK is able to perform background scanning. In order to work please make sure to allowAlwaysAuthorization for background permissions and Background Modes. Then the SDK will then be working in the background for you. You can chose one of the modes that you would want to adopt or you can disable it. Depending on the permissions that are allowed the SDK will be able to perform different actions in each of the modes.
Enabling background modes - required
The NodleSDK requires certain Background Modes to be enabled in order to perform background scanning. Here is example of the ones you need to enable:
Please head out to our configuration page here: Nodle SDK - iOS API and Configuration You have successfully configured the NodleSDK to perform background scanning.
Generate Privacy Report - XCode 15 support
With the latest version of XCode 15 and our SDK, we have a Privacy manifest generated automatically for you with all the required information that the SDK uses and needs to function properly. Here is a sample version of the report:
To generate the report, select Product -> Archive -> Right-click on your build and then select Generate Privacy Report. You should see all the entries like above image. Our SDK doesn't use any of the items in the report for anything else than app functionality. The SDK doesn't have any tracking domains that have been used.
Signing Requirements for Third Party SDK - XCode 15
With the latest version of XCode 15 and our SDK, we will have all future versions of the SDK signed with our identity, and Apple as authority to validate the SDK. The status of the SDK should be as below:
While our SDK isn't identified as privacy impacting, we want to take advantage of Apple’s new strategy for validating SDK authors. The future new versions will be always signed and with the correct identity as Nodle Technology. Please make sure to report anything suspicious when integrating our SDK.
Checking Your SDK Rewards
Currently we have our dashboard under development and rewards are not available. If you want see your rewards please go to our Nodle Subscan please follow the steps:
- Copy your
public_key
and paste it in the search bar - Slide down the page after it loads and head to allocations
- You should see you rewards which are allocated every 2 hours.
If you allow all the rules in SDK you should see the packets coming to the dashboard. Then rewards should be visible.
SDK Configuration
The SDK receives configuration remotely from Nodle servers as well as statically using API calls. The static configuration always takes precedence over the remote configuration.
Nodle SDK API
To interact with the SDK you need to call the Nodle.sharedInstance
method that will give you an Instance of the INodle class. The following are all the public methods for the Nodle API.
Swift
import UIKit
import SwiftCBOR
import SwiftProtobuf
import NodleSDK
import SQLite
import CoreLocation
import CoreBluetooth
let nodle = Nodle.sharedInstance
start
public func start(public_key: String)
Immediately starts the Nodle SDK
Parameters | |
public_key | The application public_key created in Step 1 |
Example:
Swift
Nodle().start("ss58:public_key")
isStarted
public func isStarted() -> Bool
Checks if the Nodle SDK is started
Parameters | |
boolean | true if the Nodle SDK is started, false otherwise |
Example:
let sdkStarted = Nodle().isStarted()
isScanning
public func isScanning() -> Bool
Checks if the Nodle SDK is currently scanning the BLE neighborhood. This is useful if you want to show that the SDK is working.
Parameters | |
boolean | true if the Nodle SDK is scanning, false otherwise |
Example:
let sdkScanning = Nodle().isScanning()
stop
public func stop()
Immediately stops the Nodle SDK
Example:
Nodle().stop()
clear
public func clear()
Clear any configs by Nodle SDK
Example:
Nodle().clear()
getVersion
public func getVersion() -> String
Get the version identifier of the Nodle SDK.
Parameters | |
String | the current version of the Nodle SDK |
Example:
let nodleSdkVersion = Nodle().getVersion()
getEvents
public func getEvents() -> NodleEvent
Get the raw bluetooth events from the Nodle SDK with the following type:
Returns | |
NodleEventType.BlePayloadEvent | Returns NodleBluetoothScanRecord |
NodleEventType.BleStartSearching | Returns NodleBluetoothEvent |
NodleEventType.BleStopSearching | Returns NodleBluetoothEvent |
NodleEventType.BeaconPayloadEvent | Returns NodleBeaconScanRecord |
NodleEventType.BeaconStartSearching | Returns NodleBeaconEvent |
NodleEventType.BeaconStopSearching | Returns NodleBeaconEvent |
Example of available return event classes below:
Returns | |
NodleBluetoothScanRecord | Raw Bluetooth Record from Nodle SDK |
NodleBluetoothEvent | Bluetooth Event when the SDK start/stop |
NodleBeaconScanRecord | Raw Beacon Record from Nodle SDK |
NodleBeaconEvent | Beacon Event when the SDK start/stop |
Example:
nodle.getEvents { event in
// collect the NodleEvent events by chosing a type
switch event.type {
case .BlePayloadEvent:
let payload = event as! NodleBluetoothRecord
print("Bluetooth payload available \(payload.device)")
break
case .BleStartSearching:
print("Bluetooth started searching")
break
case .BleStopSearching:
print("Bluetooth stopped searching")
break
@unknown default:
print("Failed to get any event")
}
}
NodleSDKWCB - Swift
nodle.getEvents { event in
// collect the NodleEvent events by chosing a type
switch event.type {
case .BeaconPayloadEvent:
let payload = event as! NodleBeaconRecord
print("iBeacon payload available \(payload.identifier) major: \(payload.major) minor: \(payload.minor) delivered at \(Date())")
break
case .BeaconStartSeaching:
print("iBeacon started searching \(Date())")
break
case .BeaconStopSearching:
print("iBeacon stop searching \(Date())")
break
@unknown default:
print("Failed to get any event")
}
}
The following data can be collected from the NodleEventType
:
Key | Description | Default Value |
type | returns nodle bluetooth event type | NodleEventType |
The following data can be collected from the NodleBluetoothScanRecord
:
Key | Description | Default Value |
device | returns device unique identifier | String |
rssi | returns received signal strength indicator | Int |
bytes | returns raw bytes of the record | [UInt8] |
manufacturerSpecificData | returns the manufacturer specific data associated with the manufacturer id | [Int : [UInt8]] |
servicesUuids | returns an array of services UUID's within the advertisement | Array<CBUUID> |
The following data can be collected from the NodleBluetoothEvent
:
Key | Description | Default Value |
scanning | returns bluetooth scanning state | Bool |
The following data can be collected from the NodleBeaconScanRecord
:
Key | Description | Default Value |
identifier | returns device unique identifier | String |
major | returns major value of the beacon | NSNumber |
minor | returns minor value of the beacon | NSNumber |
proximity | returns proximity value of the beacon | Int |
accuracy | returns accuracy value of the beacon | Double |
rssi | returns received signal strength value of the beacon | Int |
The following data can be collected from the NodleBeaconEvent
:
Key | Description | Default Value |
scanning | returns beacon scanning state | Bool |
The table shows rational range for the beacon devices that are found:
Key | Description | Range |
proximity | Int | unknown = 0, immediate = 1, near = 2, far = 3 |
accuracy | Double | unknown 0, 0 - 0.5 immediate, 0.5 - 3 near, 3+ far in meters |
rssi | Int | -128 |
registerNodleBackgroundTask
public func registerNodleBackgroundTask()
Register the Nodle SDK background task
Example:
Nodle().registerNodleBackgroundTask()
scheduleNodleBackgroundTask
public func scheduleNodleBackgroundTask()
Schedules the Nodle SDK background task
Example:
Nodle().scheduleNodleBackgroundTask()
config
public func config(path: Path)
public func <T> config(key: String, value: T)
configure the SDK either by supplying a json file located in ../config.json or by directly configuring a key. An example of a json configuration look like this:
{
"ble": {
"scan": {
"duration-msec": 10000,
"interval-msec": 90000,
"interval-x-factor": 1
}
},
"dtn": {
"use-cellular": false
}
}
The following are the table of all the keys available and their description:
Key | Description | Default Value |
ble.scan.duration-msec | duration of a single ble pass in milliseconds. Longer scan increase battery consumption but gives more reward. | 10000 |
ble.scan.interval-msec | wait time between two ble pass in milliseconds. Longer period reduce battery consumption but gives less reward | 90000 |
ble.scan.interval-x-factor | multiplier for the ble scan interval above. | 1 |
dtn.use-cellular | if true, the cellular connexion will be used. if false, only wifi connection will be used. | true |
cron.ios-bg-mode | If specified, the SDK will run in the specific background mode that it is selected. | 2 |
cron.ios-bg-mode-distance-meters | If specified, the SDK will trigger background scans for Normal mode depending on the meters that are specified with this option. | 20 |
cron.ios-infinite-scan | if true, the WCB SDK will perform infinite Beacon scanning. If false the WCB SDK won't perform infinite Beacon scannning. | false |
there is another table that will allow you to configure our SDK background modes. There are 4 available modes: NONE, ECO, NORMAL, AGGRESSIVE for the NodleSDK please check them in the table below:
Key | Description | Default Value |
NONE | The SDK will run in foreground mode only. You don't need to give allowAlways permissions. WhileInUse is enough for this mode. You may wish to only use Background Tasks for this mode. | 0 |
AGGRESSIVE | The SDK will run in aggressive mode that require all permissions we requested to allowAlways. Then you have to enable Background Modes as well. There is no need to register Background Tasks for this mode. This mode will work even when the phone is with locked screen. This mode will keep the SDK awake without suspending it. Once terminated it won't be able to restore it. | 1 |
NORMAL | The SDK will run in normal mode that require all permissions we requested to allowAlways since it still runs in the background. Then you have to enable Background Modes as well. This mode will be a bit less aggressive than the previous mode. It will trigger when there are location changes. You can change the distance with the config option. You may wish to combine Background Tasks for this mode. This mode will work even when the phone is with locked screen. This mode will be able to awake the SDK after it's fully suspended. Once terminated it won't be able to restore it. | 2 |
ECO | The SDK will run in eco mode that require all permissions we requested to allowAlways since it still runs in the background. Then you have to enable Background Modes as well. This mode will provide a very limited background work. It will trigger really rarely in the background. And when there are location changes. You may wish to combine Background Tasks for this mode. This mode will work even when the phone is with locked screen. This mode will be able to awake the SDK after it's fully suspended and even terminated. | 3 |
Example:
Swift
import UIKit
import SwiftCBOR
import SwiftProtobuf
import NodleSDK
import SQLite
import CoreLocation
import CoreBluetooth
// load the json config located in your app folder config.json
let bundle = Foundation.Bundle(identifier: "io.nodle.apptest.AppTest")
// path for the file in the project
let path = bundle!.path(forResource: "config", ofType: "json")
// or you can manually set the entries, for instance
Nodle().config("dtn.use-cellular", false);
// background mode selected - foreground only
Nodle().config("cron.ios-bg-mode", 0);
// then proceed to start Nodle
Nodle().start()
Debug Logs API
This API enable the debug logs for the SDK and allows developer to debug on their own and have better visiblity on their application. The default value will be false which will output PRODUCTION level logs going forward. Here is a sample how to enable/disable the API:
nodle.config(key: "core.debug-log.enable", value: false)
Production Logs
- Init of the SDK
- Dispatcher event logs from the API
- SDKCore logs
- init of the core
- SDK ID
- Feature logs
- Bluetooth Scanner lifecycle logs
- enabled/disabled
- success scan log
- failed scan log
- Cell Scanner lifecycle logs
- enabled/disabled
- scan started
- scan failed
- Heartbeat feature logs
- enabled/disabled
Debug Logs
- Init of the SDK
- Dispatcher event logs from the API
- SDKCore logs
- init of the core
- current SDK setup dump
- bundles in the DB
- SDK ID
- Feature logs
- Bluetooth Scanner lifecycle logs
- enabled/disabled
- success scan log
- each scan item found
- transmission for bundle
- failed scan log
- Cell Scanner lifecycle logs
- enabled/disabled
- scan started
- scan failed
- transmission for bundle
- Network feature logs
- network status log
- resume bundles logs
- networking logs over CLA Http
- networking bundle transmission logs
- Heartbeat feature logs
- enabled/disabled
- transmission log
- error logs
- Location Provider logs
- waiting for location log
- saved location fetch log
- timeout on location log
- fresh location fetch log
- error logs
Heartbeat API
public func getHeartbeats() -> Array<NodleHeartbeatRecord?>?
The following data can be collected from the NodleHeartbeatRecord
each parameter is optional:
Key | Description | Default Value |
id | returns hb unique identifier | Int64? |
timestamp | returns the generated timestamp when created | UInt64? |
timezone | returns the device timezone | String? |
locationH3 | returns the device last known location in h3 format string | String? |
geoHash | returns the device last known location in geohash format | String? |
isBlePermissionsGranted | returns the device ble permissions granted | Bool? |
isLocPermissionsGranted | returns the device location permissions granted | Bool? |
isWifiEnabled | returns the device wifi module status | Bool? |
isCellEnabled | returns the device cell module status | Bool? |
isBluetoothEnabled | returns the device bluetooth module status | Bool? |
sdkVersion | returns the sdk version | String? |
configVersion | returns the sdk config version | String? |
os | returns the device os | String? |
phone | returns the device model | String? |
release | returns the device release | String? |
api | returns the device api level | String? |
hardware | returns the device hardware name | String? |
appName | returns the app name | String? |
battery | returns the device battery | Int? |
charging | returns the device charging status | Bool? |
appInForeground | returns the app current status | Bool? |
phoneStorageTotal | returns the device total storage | String? |
phoneStorageAvailable | returns the device storage available | String? |
sdkStorage | returns the device storage consumed | String? |
httpIn | returns the sdk http input | String? |
httpOut | returns the sdk http output | String? |
bundleRxCount | returns the DTN RX | Int? |
bundleTxCount | returns the DTN TX | Int? |
bleScanSuccess | returns the BLE Scan success count | Int? |
bleScanFailed | returns the BLE Failed count | Int? |
blePayloadCount | returns the BLE payload found | Int? |
buildType | returns the buildType of the SDK | String? |
The HB API will provide a history of the heartbeats being generated by the SDK. It will always add the latest HB on top of the list being sorted by the timestamp. When there is a new heartbeat it will take the 0 element in the array. Here is a sample how to increase/decrease the storage size and be able to fetch all the heartbeats:
nodle.config(key: "core.heartbeat.history", value: 100)
Swift
nodle.getHeartbeats()?.forEach { it in
print("Heartbeat: \(String(describing: it))")
}
H3 API
public func getH3() -> H3?
Return the H3 instance exposing the H3 library methods to be used by the developer:
Returns | |
H3 | Returns H3Core |
The H3 interface with all the methods that the developer can take advantage is defined below:
Method | Description | Return Value |
h3IsValid(h3: Int64) | Returns true if the h3 index is valid | Bool |
h3IsValid(h3Address: String) | Returns true if the h3 index is valid | Bool |
h3GetBaseCell(h3: Int64) | Returns the base cell number for the index | Int |
h3GetBaseCell(h3Address: String) | Returns the base cell number for the index | Int |
h3IsPentagon(h3: Int64) | Returns true if this index is one of the twelve pentagons per resolution | Bool |
h3IsPentagon(h3Address: String) | Returns true if this index is one of the twelve pentagons per resolution | Bool |
geoToH3(lat: Double, lng: Double, res: Int) | Find the H3 index of the resolution res cell containing the lat/lon (in degrees) returns h3 index | Int64 |
geoToH3Address(lat: Double, lng: Double, res: Int) | Find the H3 index of the resolution res cell containing the lat/lon (in degrees) returns H3 index | String |
h3ToGeo(h3: Int64) | Find the latitude, longitude (both in degrees) center point of the cell. | (NodleLat, NodleLng) |
h3ToGeo(h3Address: String) | Find the latitude, longitude (degrees) center point of the cell. | (NodleLat, NodleLng) |
h3ToGeoBoundary(h3: Int64) | Find the cell boundary in latitude, longitude (degrees) coordinates for the cell | Array<(NodleLat, NodleLng)> |
h3ToGeoBoundary(h3Address: String) | Find the cell boundary in latitude, longitude (degrees) coordinates for the cell | Array<(NodleLat, NodleLng)> |
kRing(h3Address: String?, k: Int) | Neighboring indexes in all directions h3Address – Origin index k – Number of rings around the origin | Array<String?>? |
kRing(h3: Int64, k: Int) | Neighboring indexes in all directions h3Address – Origin index k – Number of rings around the origin | Array<Int64> |
h3Distance(a: String?, b: String?) | Returns the distance between a and b. This is the grid distance, or distance expressed in number of H3 cells. | Int |
h3Distance(a: Int64, b: Int64) | Returns the distance between a and b. This is the grid distance, or distance expressed in number of H3 cells. | Int |
h3Line(startAddress: String?, endAddress: String?) | Given two H3 indexes, return the line of indexes between them (inclusive of endpoints). | Array<String?>? |
h3Line(start: Int64, end: Int64) | Given two H3 indexes, return the line of indexes between them (inclusive of endpoints). | Array<Int64> |
h3GetResolution(h3Address: String?) | Returns the resolution of the provided index | Int |
h3GetResolution(h3: Int64) | Returns the resolution of the provided index | Int |
h3ToString(h3: Int64) | Converts from long representation of an index to String representation. | String? |
stringToH3(h3Address: String?) | Converts from String representation of an index to long representation. | Int64 |
numHexagons(res: Int) | Returns the number of unique H3 indexes at resolution res. | Int64 |
nodle.getH3()?.h3ToGeo(h3Address: "8a1eebbb461ffff")
SDK Troubleshooting
In this section, we will try to explain some of the common issues you may face on Android and how to troubleshoot them.
General Guidelines
Here are some of the common steps to take in case of issues in general.
- Please make sure to follow all steps carefully and ensure have done all that's requested from you for the integration.
- Make sure you have selected the right version of the SDK with Google Play services or without depending on your usage.
- Make sure you have your public key in the following format ss58:public_key.
- Make sure you have all permissions in your Android manifest file and you have added your application class inside the android tag.
- Make sure you have initialized the NodleSDK.
- Make sure to start the NodleSDK.
If you are still having issues, proceed with the next steps below.
Bluetooth Troubleshooting
Follow these steps to troubleshoot issues with your Bluetooth.
- Please disable your Bluetooth, Wifi, Mobile Data and proceed to next step.
- Go to your phone Settings-> Apps -> Bluetooth. Clear the cache and data for the system application. Some manufacturers hide that so you might need to enable it to find it.
- After you have done the above, restart your phone.
- If you still having Bluetooth related problems, contact your manufacturer or update your software. If the issue persists, try with another phone from a different manufacturer.
Location Troubleshooting
To troubleshoot issues with location, do the following:
- Make sure you have Location enabled on your phone.
- Make sure you followed all steps on our documentation for the integration and you are requesting all the permissions in your Manifest.
- Make sure you are requesting all runtime permissions for the user and that you have permissions for them to be used. You can verify that on the next step.
- Go to your phone Settings-> Apps -> Your Application and make sure you have Location permission enabled. Location can be enabled either Always or While in Use.
- If you are still having issues, disable your Location, Wifi, Mobile data.
- After you have done the above, restart your phone.
- If you still having Location related problems, contact your manufacturer or update your software.
Network Troubleshooting
Here are the steps to follow to troubleshoot issues with the network.
- Make sure you have Wifi or Mobile data enabled on your phone. We need this to be able to process data in our SDK.
- Make sure you have an internet connection (double check this). Also, check for weak connections. Our SDK will still keep any generated data on your phone until your connection is stable, so you aren't missing out.
- If you are having issues with either Wifi or Mobile data, go to your phone Settings-> Wifi / Mobile Data and make sure you have them enabled. If you have them enabled but still there’s no connection, follow the steps below.
- Go ahead and disable your Wifi, Mobile data.
- After you have done the above, restart your phone. If you’re still having internet related problems, contact your manufacturer or update your software.
- Once you have the internet connection, you can proceed.
Podfile Troubleshooting
Here’s how you can tackle common issues with Podfile:
- Make sure you have the latest version of Cocoapods installed. Each version has different scripts and performs differently. Also, dependency management and project structure is different.
- Follow each of the steps in our documentation and ensure you don’t skip anything.
- Make sure you generate the podfile correctly.
- During update, make sure to remove .lock file as well as the workspace that's generated.
- Perform pod install, which will generate a clear workspace for your project.
- Clear Cocoapods cache since they have a lot of local and remote issues. However, they are a valid option for dependency management.
- Make sure you are on the latest version of the SDK. You can see that from documentation page. This is to ensure optimum performance and issue resolution.
After all the above are done and you are still facing issues, please reach out to us or the Cocoapods team.
Changelog
In this page, you can find our latest releases and the changes that are being done in the new and old versions of the SDKs for iOS.
Version 0.0.23 (07.06.2024) - iOS SDK - Night branch
Updated
- Updated security later and optimizations
Version 0.0.22 (12.01.2024) - iOS SDK - Night branch
Added
- Added XCode 15 support
- Added Privacy manifest with all information required for the SDK
- Added Privacy report generation for latest XCode versions
- Added Signing the new versions of the SDK will always be signed going forward
- Added better error handling around the SDK
Updated
- Updated security layer to latest version
- Updated documentation with latest required changes
Fixed
Fixed a URL RFC related issue from latest Apple update
Version 0.0.21 (01.08.2023) - iOS SDK
- Increased the overall stability of the SDK
- Prevented false positive checks from the security layer that caused memory leaks
- Prevented potential crash that happen from the memory leaks in the Bluetooth,Network layer
- We have added Hotfixes around the codebase after we have received crash reports to improve stability on the following locations around the SDK:
- Prevented a crash after the SDK performs a succesful scan and passing records to getEvents API
- Prevented a crash where the Location Manager would receive bad location
- Prevented a crash where our Beacon Scanner instance could be nullable before performing a scan
- Prevented a crash on the condition where the permissions checks could be empty for our Beacon Manager
- Prevented a potential crash where the Beacon payloads could be corrupted and still passed forward to the internals of the SDK
- Prevented a crash where the beacon uuids could be invalid before starting/stopping monitoring
- Prevented a crash where the beacon regions were in range
- Prevented potential crash when receiving data from inbox/outbox in the Network layer
- Prevented the SDK from crashing randomly by depracating the Background Task API
- Awake API base
- Allow the developer to be able to restart the NodleSDK after their application is being terminated by setup the following methods:
nodleLocationManager.restartNodleInTerminatedState { result in }
- Infinite Scanning option
- Allow the developer to be able to configure the WCB SDK in a way that will enable them to do infinite scan without the need for the manager to stop/start and do the SDK rotation by using the following method:
nodle.config(key: "cron.ios-infinite-scan", value: true)
- HB API which can be used by developers to retrieve the last heartbeats that have been produced by their SDK:
nodle.config(key: "core.heartbeat.history", value: 100)
- H3 API which can be used by developers to use the Uber H3 Library features safely
- Debug Logs API that will allow the developers to debug their own SDK with two log levels PRODUCTION/DEBUG:
nodle.config(key: "core.debug-log.enable", value: true)
- Improved and extented capabilities for background mode scanning which will improve the overall capabilities of the SDK and the network
- Improved and extended capabilities for beacon scanning on CoreBluetooth variation of the SDK
- Fixed a issue with H3 causing buffer overflow for some swift runtimes
- Fixed a issue where H3 was causing a heap use after free for some swift runtimes
- Fixed a memory leaks caused by H3 module and swift runtimes
- Fixed a memory leaks caused by the security layer in the H3 module
- Fixed a memory leaks caused by the security layer in the Bluetooth, Network layer
- Fixed a issue where the SDK won't update the last known location all the time
- Security to latest version with last hardened protection mechanisms
- Suspended AwakeAPI until the stability of the SDK is back on track
- Update access modifiers for NodleLocationManager in order the developer to be able to init at application level and take advantage of the AwakeAPI
- Update Beacon Scanner logic to be able to scan infinitely
- Updated config so the developer can enable/disable the infinite scanning
- We have deprecated the Background Task API due receiving crash reports from clients and minimum value that the API capabilities brought to the network
Version 0.0.16 (05.12.2022) - iOS SDK
- Added XCode 14 support
- Added better error handling around the SDK
- Updated security layer
- Fixed a critical issue with Location layer
- Fixed issues with Network, Bluetooth, Config, DB, Location
Version 0.0.15 (26.09.2022) - iOS SDK
- Swift 5.7 support
- Fixed issues with background modes capabilities not being added by the developer
- Fixed crashes in SDK Core initialization
- Fixed crashes in Network, Bluetooth, Config, Location layer
Version 0.0.14 (11.07.2022) - iOS SDK
- Security updates
- Issues with background work
- Issues with background modes
- Issues with location providers
- Issues with config
- Issues with network
- We are deprecating MacOS support and catalyst in the future versions of our SDK
Version 0.0.13 (12.04.2022) - iOS SDK
- Background capabilities
- Background modes
- Performance improvements
- Config options
Unity SDK Plugin
Integrating the Nodle SDK into your Unity app is easy and straightforward. You can use our NodleSDK Quickstart application or just follow the steps below and you should be ready to go in no time.
- Step 1: Generate Developer Key
- Go and Create a Nodle account
- Make sure you save your private key!
- Copy your
public_key
from the extension - Proceed forward with next steps.
- Setup Developer Environments: Please make sure to follow our Android SDK and iOS SDK and configure your environement based on the requirements there.
- Create Unity Application: You can follow the steps to create a new project or skip below to just importing the plugin depending on your platform.
- Creating a new project - Android
- Please start by creating a new project Android in Unity Hub it is not required to use that template you can create a blank or 3D or other.
- After you have created the project you should see the following:
- Then proceed to switch the platform to Android go to File->Build Settings and select Android:
- Next go ahead and click Switch platform. After switching you can go to next step to import the plugin.
- Creating a new project - iOS
- Please start by creating a new project iOS in Unity Hub it is not required to use that template you can create a blank or 3D or other.
- After you have created the project you should see the following:
- Then proceed to switch the platform to Android go to File->Build Settings and select iOS.
- Next go ahead and click Switch platform. After switching you can go to next step to import the plugin.
- Updating Player Settings: You have to update your player settings for Android/iOS before you import the plugin.
- Player Settings - Android
- You have to set the player settings for you application and make sure to check the Custom Gradle Templates as shown in the picture. The minimum version for the SDK is Android 7. Please set that in Android -> Other Settings -> Minimum version when you change the player settings.
- After you import the plugin then copy/merge the following files: baseProjectTemplate.gradle, gradleTemplate.properties, mainTemplate.gradle from Assets -> Plugins -> Nodle -> Android to Assets -> Plugins -> Android then copy the content of AndroidManifest.xml into your application manifest. Then proceed with next steps.
- Player Settings - iOS
- There are no changes for iOS except your player base settings to be set and you can proceed to next steps.
- Import the Nodle Unity Plugin into your application: You can follow the steps to import the Nodle plugin depending on your platform into your application.
- Import the Nodle package - Android
- Start by selecting from Assets->Import Package-> Custom Package and then select the Nodle SDK package.
- Import everything from the package. We recommend to import the Sample Scene too.
- Import the TMP Essentials. If there is a problem with the buttons, please close and open the project there is a bug on Unity side.
- Open the Sample Scene: Assets/Plugins/Nodle/SampleScene/SampleScene.unity.
- Next, select the Main Camera object and in the inspector place your
public_key
with the following format:ss58:public_key
- Then, go to Build Settings If you scene didn't appear, click on the Add Open Scenes, and place it as 0 (Drag the scene name to the top of the list). Build and Run!
- That’s it! You can setup your Player Settings details from your application and run the NodleSDK.
- Import the Nodle package - iOS
- Start by selecting from Assets->Import Package-> Custom Package and then select the Nodle SDK package.
- Next, please go ahead and import everything from the package. We recommend to import the Sample Scene too.
- Next, open the Sample Scene located under Assets → Plugins → Nodle → Sample Scene
- Import the TMP Essentials. If there is a problem with the buttons please close and open the project there is a bug on Unity side.
- Next select the Main Camera object and in the inspector place your
public_key
with the following format:ss58:public_key
- Then go to Build Settings. If your scene didn't appear, click on the Add Open Scenes, and place it as 0 (Drag the scene name to the top of the list). Build the project!
- After making the build into a build folder. Copy the Podile from Plugins -> Nodle -> iOS -> NodleIOSPlugin -> XCodeFiles to the root of that build folder. Then open the build folder location in terminal and install the NodleSDK with the following command:
pod install
- You can go ahead and use the generated .workspace file from now on to run the project! Please make sure to add all permissions to your
Info.plist
before running the application. You can find how to do that here: NodleSDK Permissions.
And there you have it! You’re good to go!
Checking Your SDK Rewards
Currently we have our dashboard under development and rewards are not available. If you want see your rewards please go to our Nodle Subscan please follow the steps:
- Copy your
public_key
and paste it in the search bar. - Slide down the page after it loads and head to allocations.
- You should see you rewards which are allocated every 2 hours.
If you allow all the rules in SDK, you should see the packets coming to the dashboard. Then, rewards should be visible.
← Previous
Next →
On this page
- iOS SDK Integration
- Run Nodle SDK in Background (Optional)
- Checking Your SDK Rewards
- SDK Configuration
- Nodle SDK API
- start
- isStarted
- isScanning
- stop
- clear
- getVersion
- getEvents
- registerNodleBackgroundTask
- scheduleNodleBackgroundTask
- config
- Debug Logs API
- Production Logs
- Debug Logs
- Heartbeat API
- H3 API
- SDK Troubleshooting
- General Guidelines
- Bluetooth Troubleshooting
- Location Troubleshooting
- Network Troubleshooting
- Podfile Troubleshooting
- Changelog
- Unity SDK Plugin
- Checking Your SDK Rewards