NordicSemiconductor / IOS-CoreBluetooth-Mock

Mocking library for CoreBluetooth framework.
BSD 3-Clause "New" or "Revised" License
225 stars 51 forks source link

Multiple advertisements per peripheral + option to change #81

Closed philips77 closed 1 year ago

philips77 commented 1 year ago

This PR modifies how the mock Central Manager simulates advertising.

Before

For each scanning CBMCentralManagerMock a list of timers was created, one for each CBMPeripheralSpec. Two instances of the manager could receive packets from the same peripheral in different time, as timers were independent and started on scanning of each manager. Connection to a device was immediate with just connection interval delay.

After

First of all, each CBMPeripheralSpec can have multiple advertising configurations. Each AdvertisingConfig has own advertising data, interval and a new parameter - a delay. If the interval is 0 and the delay > 0 the advertising will be sent only once, delay seconds after adding the peripheral to the simulation. There is a single set of timers that will emulate advertising of every advertising set. The advertising data is delivered to all scanning central managers at the same time. Also, connection now waits for an advertising packet to come and only then continues, like in real life.

API changes

The change should be backwards compatible.

When defining a CBMPeripheralSpec now it is possible to call advertising block multiple times, for example:

let blinky = CBMPeripheralSpec
    .simulatePeripheral(proximity: .immediate)
    .advertising(
        advertisementData: [
            CBAdvertisementDataIsConnectable : true as NSNumber,
            CBAdvertisementDataLocalNameKey : "Blinky"
        ],
        withInterval: 0.100,
        delay: 4.0,
        alsoWhenConnected: false
    )
    .advertising(
        advertisementData: [
            CBAdvertisementDataIsConnectable : false as NSNumber,
            CBAdvertisementDataLocalNameKey : "iBeacon",
        ],
        withInterval: 4.0,
        delay: 2.5,
        alsoWhenConnected: false
    )
    // [...]
    .build()

It is also possible to change advertising set during a simulation with the new CBMPeripheralSpec.simulateAdvertisingChange(:[AdvertisingConfig]?)