Estimote/iOS-Fleet-Management-SDK

Nearable Sticker stopped working on iOS 13 with EstimoteSDK

Closed this issue · 22 comments

Basic information

Estimote iOS SDK version: pod 'Estimote SDK' newest
iOS device(s) affected: all iOS devices
iOS version(s) affected: iOS 13
Estimote device hardware version: Nearable Sticker
Estimote device firmware version:

Additional information

Please read the checklist and place x sign where apropriate for your use case.

  • [? ] My beacons have Estimote Monitoring enabled (check it in the Estimote Cloud, or via app).
  • My iOS device/devices supports BLE (iOS must be 5.0 or higher).
  • My iOS device/devices have Bluetooth enabled.
  • My app has NSBluetoothPeripheralUsageDescription in its Info.plist file.
  • My app has Location Permissions granted.
  • My app has NSLocationWhenInUseUsageDescription and NSLocationAlwaysAndWhenInUseUsageDescription keys in its Info.plist file.
  • My app has NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription in its Info.plist file.
  • If my app is supporting iOS 10 and earlier, and has NSLocationAlwaysUsageDescription key in its Info.plist file.
  • [?] If my app has to run in the background, it has UIBackgroundModes key with value bluetooth-central in its Info.plist file.

Description

After upgrade to iOS 13 working code that detects Nearble stickers stopped working. Now delegate method is never called.

Here are my code snippets:

 private func startRangingNearables() {
        
        self.tables.forEach { table in
            guard let nearableIdentifier = table.beaconId else { return }
           
            self.nearableManager.startRanging(forIdentifier: nearableIdentifier)
            
        }
    }

func nearableManager(_ manager: ESTNearableManager, didRangeNearable nearable: ESTNearable) {
       
        if nearable.rssi <= 0 {
            print("Did range nearable: \(nearable.identifier), power: \(nearable.txPowerInDbm), rssi: \(nearable.rssi), interval: \(nearable.advInterval)")
            
            beaconContainer.addBeacon(nearable.toBeacon())
        }

I haven’t changed recently nothing in my code, maybe there was update of EstimodeSDK pod and update from iOS 12.4 to iOS 13.

Thay are still detected in Estimote iOS app so they are live and identifiers are correct

Ranging nearables failed with error: Error Domain=com.estimote.nearables Code=301 “Blueooth is not powerd on.” UserInfo={NSLocalizedDescription=Blueooth is not powerd on.}

Additional information

The same code worked when run on iOS 12 device, but doesn't work on iOS 13.
iBeacons work correctly, only Nearable Stickers stopped working.

Thanks for spotting bug, we'll try release fix asap.

btw would be nice to use pod 'EstimoteFleetManagementSDK' after all we switched a while back to a different naming and as well newest version would be 4.31.0 (instead of 4.28.0 ;) )

4.31.1 will have fix for missing nearables

OK, thanks :)

I have the same issue on EstimoteSDK (iOS 13.1.2). My iPhone is not able to range or discover any beacons. I tried both 'EstimoteFleetManagementSDK' and 'EstimoteBluetoothScanning.framework' but it is still not working.
On iOS 12, ranging and discovering beacon work correctly.

We're working on fixing that as we speak :)
though can you specify which version of EstimoteBluetoothScanning do you have? This library should work (starting with https://github.com/Estimote/iOS-Bluetooth-Scanning/releases/tag/v1.0.6).. if it's not then please submit the issue there as well.

Glad we helped :) if you need only ranging for packets I'd recommend using EBS (Estimote Bluetooth Scanning), if monitoring then Proximity SDK would be the best.
Unless you have some legacy code requiring you to go with this SDK (which is mostly now deprecated and unattended - unless there is some critical bug).

Unfortunately, I am using "EstimoteSDK" for ranging all beacons around the iPhone (about 100 beacons).

- (void)utilityManager:(ESTUtilityManager *)manager
    didDiscoverBeacons:(NSArray<ESTBluetoothBeacon *> *)beacons;

But "EstimoteBluetoothScanning" only allow to range and receive 1 beacon a time.
- (void)universalScanner:(id<EBSUniversalScannerProtocol>)universalScanner didScanEstimoteDevice:(EBSScanInfo *)scanInfo;
I hope the next release of EstimoteSDK will fix the issue on iOS 13 like EstimoteBluetoothScanning.

I get it. Will let you know when we're done fixing.
Out of curiosity:

  1. do you really need to range 100 different beacons or just recognize "yours" from the crowd?
  2. do you need ranging or monitoring would be enough?
  1. Yes, I need to range all beacons around.
  2. Currently, I am using ESTUtilityManager for ranging, ESTDeviceManager for discovering and ESTBeaconConnection for establishing connection and write data.

Ok I will check it today or tomorrow and give you info how it works now :)

@chwastek Thanks a lot for the 4.31.1 release.
With this release my devices (iOS 13 and iOS 12) can range beacons perfectly �by ESTUtilityManager. (I know this class is deprecated but I don’t know a replaced class).

But I am still unable to connect to my beacons which are the first generation Estimote Proximity Beacon (hardware revision “D”).
If I use ESTBeaconConnection (deprecated), my app will crash with reason 'Invalid domain=nil in -[NSError initWithDomain:code:userInfo:]’

Then I try ESTDeviceLocationBeacon but it is unable to connect to my beacons.
It seem the 1st-generation beacons are not supported on SDK 4 APIs.

Will look into it.

@HoangNguyenBigLabs can you share how do you exactly scan for old beacons etc?

@chwastek Here is the class to discover beacon exactly by MAC address.

class ImmediateBeaconDetector: NSObject, ESTDeviceManagerDelegate, CBCentralManagerDelegate {

    @objc let deviceManager = ESTDeviceManager()
    
    @objc var bluetoothManager: CBCentralManager!

    unowned var delegate: ImmediateBeaconDetectorDelegate

    var macAddr : String?
    
    init(delegate: ImmediateBeaconDetectorDelegate) {
        self.delegate = delegate
        super.init()
        deviceManager.delegate = self
        bluetoothManager = CBCentralManager(delegate: self, queue: nil)
    }

    @objc func start() {
        deviceManager.startDeviceDiscovery(with: ESTDeviceFilterBeaconV1())
    }

    @objc func stop() {
        deviceManager.stopDeviceDiscovery()
    }
    
    // MARK: ESTDeviceManagerDelegate

    func deviceManager(_ manager: ESTDeviceManager, didDiscover devices: [ESTDevice]) {
        if macAddr != nil {
            findCorrectDevice(devices: devices)
        }
    }
    
    func findCorrectDevice(devices: [ESTDevice]) {
        if devices.count > 0 {
            let correctDevice = devices.first { $0.identifier.lowercased() == macAddr!.replace(":", withString: "").lowercased() }
            if let correctDevice = correctDevice {
                if let beacon = correctDevice as? ESTBluetoothBeacon {
                    delegate.immediateBeaconDetector(self, didDiscoverBeacon: beacon)
                } else {
                }
            }
        }
    }
    
    func deviceManagerDidFailDiscovery(_ manager: ESTDeviceManager) {
        if bluetoothManager.state != .poweredOn {
            delegate.immediateBeaconDetector(self, didFailDiscovery: .bluetoothDisabled)
        } else {
            delegate.immediateBeaconDetector(self, didFailDiscovery: .unknown)
        }
    }

    // MARK: CBCentralManagerDelegate
}

After receiving ESTBluetoothBeacon, I use ESTBeaconConnection to connect to the beacon.

func immediateBeaconDetector(_ immediateBeaconDetector: ImmediateBeaconDetector, didDiscoverBeacon beacon: ESTBluetoothBeacon) {
        immediateBeaconDetector.stop()
        let locationBeacon = ESTDeviceLocationBeacon(deviceIdentifier: beacon.identifier, peripheralIdentifier: beacon.peripheralIdentifier, rssi: beacon.rssi, discoveryDate: beacon.discoveryDate)
        immediateBeacon = locationBeacon
        // This first generation of Proximity Beacons has a different API for connection: ESTBeaconConnection.
        estBeaconConnection = ESTBeaconConnection(identifier: beacon.identifier, delegate: self, startImmediately: true)
    }
func beaconConnectionDidSucceed(_ connection: ESTBeaconConnection) {
        print("SettingsInteractor - beaconConnectionDidSucceed")
        writeSettingsToProximityBeacon()
    }

Here is the code to write data into the connected beacon.

func writeSettingsToProximityBeacon() {
        let expectedPower = ESTBeaconPower(rawValue: rangePowerLevel!.level.rawValue)!
        print("Connection writePower expectedPower: \(expectedPower)")
        estBeaconConnection?.writePower(expectedPower) { (power, error) in
            if let powerError = error {
                NSLog("SettingsInteractor - Error while writing beacon setting with power error: \(powerError)")
                self.output?.errorWhileWritingSettings()
                return
            }
            print("Connection writePower powerResult: \(power.rawValue)")
            let lat = NSNumber(value: (self.locationForSaving?.coordinate.latitude)!)
            let long = NSNumber(value: (self.locationForSaving?.coordinate.longitude)!)
            print("Connection write lat: [\(lat)], long: [\(long)]")
            self.estBeaconConnection?.writeLatitude(lat, longitude: long) { (error) in
                print("Connection finish write lat: [\(lat)], long: [\(long)]")
                if let err = error {
                    NSLog("SettingsInteractor - Error while writing beacon setting with lat, long error: \(err)")
                    self.output?.errorWhileWritingSettings()
                } else {
                    self.finishWriteSettings()
                }
            }
        }
    }

In my case Nearble seems to be detected correctly. I use ESTNearableManager and ESTBeaconManager.
I have some problems but I think it can be in my code not in Estimote framework. Give more details soon if we better test them

@michzio @HoangNguyenBigLabs we released just now a new version https://github.com/Estimote/iOS-Fleet-Management-SDK/releases/tag/4.31.2 (this one should mainly fix issue with legacy beacons). LMK if it works for you

@chwastek Thanks, I will try this new version and let you know ASAP.

@chwastek Wonderful, it work perfectly on iOS 13 and iOS 12 as well.
Thanks a lot for you support.
No need to change any lines of code.

🙇 pleasure is mine! Glad we helped!