Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
10ceabd
Publish raw test report to help with investigations
ebariaux Apr 16, 2026
f75b358
Make wifiScan test more robust, not based on timings but more instrum…
ebariaux Apr 27, 2026
4b546fb
Make wifiScanUpdatedRssi() more robust, also removing conditions base…
ebariaux Apr 27, 2026
8097b7b
Make timeout tests more robust, not relying on timing but events
ebariaux Apr 27, 2026
bd710de
Make provisionDeviceFailureTimeout() not dependent on timing, importa…
ebariaux Apr 27, 2026
9c127aa
Improve other tests by using the CallbackRecoder helper
ebariaux Apr 27, 2026
d8b781c
More tests improvements by removing dependency on sleep
ebariaux Apr 27, 2026
b5fa5ee
More test clean-up, fully using CallbackRecorder to wait for messages
ebariaux Apr 27, 2026
b384f2a
Make ESPProvisionProvider tests deterministic with step-driven mocks
ebariaux Apr 27, 2026
a25c64a
Extract ORESPProvisionManager mock to its own file and use name align…
ebariaux Apr 27, 2026
82df9c0
Add monotonic (non wall clock) time source that's iOS 15 compatible a…
ebariaux Apr 27, 2026
1e6731e
ESPProvisionProvider code now using the new time source instead of wa…
ebariaux Apr 27, 2026
5e2c5d2
Use instrumented time source in tests to avoid non determinism
ebariaux Apr 27, 2026
82cbeab
Remove unused code, not using time interval for tests
ebariaux Apr 27, 2026
b3d3a13
Some pipeline runs have been stuck running tests forever, add timeout…
ebariaux Apr 27, 2026
d0dd168
Fix race condition
ebariaux Apr 27, 2026
5fae266
Using 18.6 on simulator when running tests, got some errors of non av…
ebariaux Apr 28, 2026
880f084
Some tests tweaking, hopefully improving stability
ebariaux Apr 28, 2026
bd1270c
Changes that should prevent some additional race condition in tests
ebariaux Apr 28, 2026
1d4ba2a
Changes that should prevent some additional race condition in testss
ebariaux Apr 28, 2026
7786497
Some more try to avoid edge conditions in tests
ebariaux May 4, 2026
1e99426
Some more try to avoid edge conditions in tests
ebariaux May 4, 2026
6b30324
Some more try to avoid edge conditions in tests
ebariaux May 4, 2026
5978259
Some more try to avoid edge conditions in tests
ebariaux May 4, 2026
31d2cf8
Some more try to avoid edge conditions in tests
ebariaux May 4, 2026
5aeab7c
Some more try to avoid edge conditions in tests
ebariaux May 4, 2026
0d92caf
Properly handle communication failures during provisioning
ebariaux May 15, 2026
d888e23
Fix bug that re-setting LoopDetector instance mid-scan could produce …
ebariaux May 15, 2026
56f256e
Implement timeouts within test with explicit messages and don't rely …
ebariaux May 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion .github/workflows/ci_cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,22 @@ jobs:
swiftlint lint --no-cache --quiet --config .swiftlint.yml --reporter json ORLib > swiftlint.json || true

- name: Build and test
timeout-minutes: 20
run: |
xcodebuild test -project ORLib.xcodeproj -sdk iphoneos \
-destination 'platform=iOS Simulator,name=iPhone 16,OS=18.5' -scheme ORLib -resultBundlePath ORLib.xcresult
-destination 'platform=iOS Simulator,name=iPhone 16,OS=18.6' -scheme ORLib \
-test-timeouts-enabled YES \
-default-test-execution-time-allowance 60 \
-maximum-test-execution-time-allowance 60 \
-resultBundlePath ORLib.xcresult

- name: Upload XCResult bundle
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
if: ${{ always() && !cancelled() && hashFiles('ORLib.xcresult/**') != '' }}
with:
name: ORLib-xcresult
path: ORLib.xcresult
if-no-files-found: error

- name: Extract JUnit test report
run: |
Expand Down
98 changes: 55 additions & 43 deletions ORLib.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,18 @@
91F2165C2D887BCF008F9CA7 /* ORConfigChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216552D887BCF008F9CA7 /* ORConfigChannel.swift */; };
91F2165E2D887BCF008F9CA7 /* DeviceRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216522D887BCF008F9CA7 /* DeviceRegistry.swift */; };
91F2165F2D887BCF008F9CA7 /* ORESPDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216572D887BCF008F9CA7 /* ORESPDevice.swift */; };
91F216602D887BCF008F9CA7 /* WifiProvisioner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216582D887BCF008F9CA7 /* WifiProvisioner.swift */; };
91F216612D887BCF008F9CA7 /* ESPProvisionProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216532D887BCF008F9CA7 /* ESPProvisionProvider.swift */; };
91F216622D887BCF008F9CA7 /* ORConfigChannelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216562D887BCF008F9CA7 /* ORConfigChannelProtocol.swift */; };
91F216632D887BCF008F9CA7 /* DeviceConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216512D887BCF008F9CA7 /* DeviceConnection.swift */; };
91F216642D887BCF008F9CA7 /* CallbackChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216502D887BCF008F9CA7 /* CallbackChannel.swift */; };
91F216692D887C53008F9CA7 /* DeviceProvisionAPIMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216652D887C53008F9CA7 /* DeviceProvisionAPIMock.swift */; };
91F2166A2D887C53008F9CA7 /* ESPProvisionProviderTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216662D887C53008F9CA7 /* ESPProvisionProviderTest.swift */; };
91F2166B2D887C53008F9CA7 /* ORESPDeviceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216682D887C53008F9CA7 /* ORESPDeviceMock.swift */; };
91F2166C2D887C53008F9CA7 /* ORConfigChannelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216672D887C53008F9CA7 /* ORConfigChannelTest.swift */; };
91F216602D887BCF008F9CA7 /* WifiProvisioner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216582D887BCF008F9CA7 /* WifiProvisioner.swift */; };
91F216612D887BCF008F9CA7 /* ESPProvisionProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216532D887BCF008F9CA7 /* ESPProvisionProvider.swift */; };
91F216622D887BCF008F9CA7 /* ORConfigChannelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216562D887BCF008F9CA7 /* ORConfigChannelProtocol.swift */; };
91F216632D887BCF008F9CA7 /* DeviceConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216512D887BCF008F9CA7 /* DeviceConnection.swift */; };
91F216642D887BCF008F9CA7 /* CallbackChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216502D887BCF008F9CA7 /* CallbackChannel.swift */; };
91F216702D887BCF008F9CA7 /* TimeSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216712D887BCF008F9CA7 /* TimeSource.swift */; };
91F216692D887C53008F9CA7 /* DeviceProvisionAPIMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216652D887C53008F9CA7 /* DeviceProvisionAPIMock.swift */; };
91F2166A2D887C53008F9CA7 /* ESPProvisionProviderTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216662D887C53008F9CA7 /* ESPProvisionProviderTest.swift */; };
91F2166B2D887C53008F9CA7 /* ORESPDeviceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216682D887C53008F9CA7 /* ORESPDeviceMock.swift */; };
91F2166C2D887C53008F9CA7 /* ORConfigChannelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216672D887C53008F9CA7 /* ORConfigChannelTest.swift */; };
91F2166D2D887C53008F9CA7 /* ORESPProvisionManagerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F2166E2D887C53008F9CA7 /* ORESPProvisionManagerMock.swift */; };
91F216722D887C53008F9CA7 /* TestTimeSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91F216732D887C53008F9CA7 /* TestTimeSource.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -174,14 +177,17 @@
91F216522D887BCF008F9CA7 /* DeviceRegistry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceRegistry.swift; sourceTree = "<group>"; };
91F216532D887BCF008F9CA7 /* ESPProvisionProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ESPProvisionProvider.swift; sourceTree = "<group>"; };
91F216542D887BCF008F9CA7 /* LoopDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopDetector.swift; sourceTree = "<group>"; };
91F216552D887BCF008F9CA7 /* ORConfigChannel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ORConfigChannel.swift; sourceTree = "<group>"; };
91F216562D887BCF008F9CA7 /* ORConfigChannelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ORConfigChannelProtocol.swift; sourceTree = "<group>"; };
91F216572D887BCF008F9CA7 /* ORESPDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ORESPDevice.swift; sourceTree = "<group>"; };
91F216582D887BCF008F9CA7 /* WifiProvisioner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiProvisioner.swift; sourceTree = "<group>"; };
91F216652D887C53008F9CA7 /* DeviceProvisionAPIMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceProvisionAPIMock.swift; sourceTree = "<group>"; };
91F216662D887C53008F9CA7 /* ESPProvisionProviderTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ESPProvisionProviderTest.swift; sourceTree = "<group>"; };
91F216672D887C53008F9CA7 /* ORConfigChannelTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ORConfigChannelTest.swift; sourceTree = "<group>"; };
91F216682D887C53008F9CA7 /* ORESPDeviceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ORESPDeviceMock.swift; sourceTree = "<group>"; };
91F216552D887BCF008F9CA7 /* ORConfigChannel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ORConfigChannel.swift; sourceTree = "<group>"; };
91F216562D887BCF008F9CA7 /* ORConfigChannelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ORConfigChannelProtocol.swift; sourceTree = "<group>"; };
91F216572D887BCF008F9CA7 /* ORESPDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ORESPDevice.swift; sourceTree = "<group>"; };
91F216582D887BCF008F9CA7 /* WifiProvisioner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiProvisioner.swift; sourceTree = "<group>"; };
91F216712D887BCF008F9CA7 /* TimeSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeSource.swift; sourceTree = "<group>"; };
91F216652D887C53008F9CA7 /* DeviceProvisionAPIMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceProvisionAPIMock.swift; sourceTree = "<group>"; };
91F216662D887C53008F9CA7 /* ESPProvisionProviderTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ESPProvisionProviderTest.swift; sourceTree = "<group>"; };
91F216672D887C53008F9CA7 /* ORConfigChannelTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ORConfigChannelTest.swift; sourceTree = "<group>"; };
91F216682D887C53008F9CA7 /* ORESPDeviceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ORESPDeviceMock.swift; sourceTree = "<group>"; };
91F2166E2D887C53008F9CA7 /* ORESPProvisionManagerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ORESPProvisionManagerMock.swift; sourceTree = "<group>"; };
91F216732D887C53008F9CA7 /* TestTimeSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestTimeSource.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -345,13 +351,15 @@
91A9A8FA28BF6A4900DF8928 /* ConfigManagerTest.swift */,
91A9A90028BF6EA000DF8928 /* FileApiManager.swift */,
91AA79F228D628E9005B9913 /* Fixture.swift */,
91F216652D887C53008F9CA7 /* DeviceProvisionAPIMock.swift */,
91F216662D887C53008F9CA7 /* ESPProvisionProviderTest.swift */,
91F216672D887C53008F9CA7 /* ORConfigChannelTest.swift */,
91F216682D887C53008F9CA7 /* ORESPDeviceMock.swift */,
9154E29F2D9EB0D50055E565 /* StringUtilsTest.swift */,
9154E2A12D9EB3220055E565 /* URLTest.swift */,
);
91F216652D887C53008F9CA7 /* DeviceProvisionAPIMock.swift */,
91F216662D887C53008F9CA7 /* ESPProvisionProviderTest.swift */,
91F216672D887C53008F9CA7 /* ORConfigChannelTest.swift */,
91F216682D887C53008F9CA7 /* ORESPDeviceMock.swift */,
91F2166E2D887C53008F9CA7 /* ORESPProvisionManagerMock.swift */,
91F216732D887C53008F9CA7 /* TestTimeSource.swift */,
9154E29F2D9EB0D50055E565 /* StringUtilsTest.swift */,
9154E2A12D9EB3220055E565 /* URLTest.swift */,
);
path = Tests;
sourceTree = "<group>";
};
Expand All @@ -363,13 +371,14 @@
91F216522D887BCF008F9CA7 /* DeviceRegistry.swift */,
91F216532D887BCF008F9CA7 /* ESPProvisionProvider.swift */,
91F216542D887BCF008F9CA7 /* LoopDetector.swift */,
91F216552D887BCF008F9CA7 /* ORConfigChannel.swift */,
91F216562D887BCF008F9CA7 /* ORConfigChannelProtocol.swift */,
91F216572D887BCF008F9CA7 /* ORESPDevice.swift */,
91F216582D887BCF008F9CA7 /* WifiProvisioner.swift */,
91DD55A02DE7306100957233 /* BLEPermissionsChecker.swift */,
915CCC942EF163E8006B65AA /* DeviceProvisionAPI.swift */,
915CCC962EF16456006B65AA /* DeviceProvision.swift */,
91F216552D887BCF008F9CA7 /* ORConfigChannel.swift */,
91F216562D887BCF008F9CA7 /* ORConfigChannelProtocol.swift */,
91F216572D887BCF008F9CA7 /* ORESPDevice.swift */,
91F216582D887BCF008F9CA7 /* WifiProvisioner.swift */,
91F216712D887BCF008F9CA7 /* TimeSource.swift */,
91DD55A02DE7306100957233 /* BLEPermissionsChecker.swift */,
915CCC942EF163E8006B65AA /* DeviceProvisionAPI.swift */,
915CCC962EF16456006B65AA /* DeviceProvision.swift */,
);
path = ESPProvision;
sourceTree = "<group>";
Expand Down Expand Up @@ -547,13 +556,14 @@
91F2165C2D887BCF008F9CA7 /* ORConfigChannel.swift in Sources */,
91DD55A12DE7306100957233 /* BLEPermissionsChecker.swift in Sources */,
91F2165E2D887BCF008F9CA7 /* DeviceRegistry.swift in Sources */,
91F2165F2D887BCF008F9CA7 /* ORESPDevice.swift in Sources */,
91F216602D887BCF008F9CA7 /* WifiProvisioner.swift in Sources */,
91F216612D887BCF008F9CA7 /* ESPProvisionProvider.swift in Sources */,
91F216622D887BCF008F9CA7 /* ORConfigChannelProtocol.swift in Sources */,
91F216632D887BCF008F9CA7 /* DeviceConnection.swift in Sources */,
915CCC952EF163E8006B65AA /* DeviceProvisionAPI.swift in Sources */,
91F216642D887BCF008F9CA7 /* CallbackChannel.swift in Sources */,
91F2165F2D887BCF008F9CA7 /* ORESPDevice.swift in Sources */,
91F216602D887BCF008F9CA7 /* WifiProvisioner.swift in Sources */,
91F216612D887BCF008F9CA7 /* ESPProvisionProvider.swift in Sources */,
91F216622D887BCF008F9CA7 /* ORConfigChannelProtocol.swift in Sources */,
91F216632D887BCF008F9CA7 /* DeviceConnection.swift in Sources */,
91F216702D887BCF008F9CA7 /* TimeSource.swift in Sources */,
915CCC952EF163E8006B65AA /* DeviceProvisionAPI.swift in Sources */,
91F216642D887BCF008F9CA7 /* CallbackChannel.swift in Sources */,
4CBDF2CA2AE2869D00C7D94C /* ApiManager.swift in Sources */,
4CBDF2CB2AE2869D00C7D94C /* ORTextInput.swift in Sources */,
914348322F05400200D4B3D3 /* ORConfigChannelProtocol.proto in Sources */,
Expand All @@ -576,11 +586,13 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
91F216692D887C53008F9CA7 /* DeviceProvisionAPIMock.swift in Sources */,
91F2166A2D887C53008F9CA7 /* ESPProvisionProviderTest.swift in Sources */,
91F2166B2D887C53008F9CA7 /* ORESPDeviceMock.swift in Sources */,
91F2166C2D887C53008F9CA7 /* ORConfigChannelTest.swift in Sources */,
91A9A90128BF6EA000DF8928 /* FileApiManager.swift in Sources */,
91F216692D887C53008F9CA7 /* DeviceProvisionAPIMock.swift in Sources */,
91F2166A2D887C53008F9CA7 /* ESPProvisionProviderTest.swift in Sources */,
91F2166B2D887C53008F9CA7 /* ORESPDeviceMock.swift in Sources */,
91F2166C2D887C53008F9CA7 /* ORConfigChannelTest.swift in Sources */,
91F2166D2D887C53008F9CA7 /* ORESPProvisionManagerMock.swift in Sources */,
91F216722D887C53008F9CA7 /* TestTimeSource.swift in Sources */,
91A9A90128BF6EA000DF8928 /* FileApiManager.swift in Sources */,
9154E2A22D9EB3220055E565 /* URLTest.swift in Sources */,
9154E2A02D9EB0D50055E565 /* StringUtilsTest.swift in Sources */,
91A9A8FB28BF6A4900DF8928 /* ConfigManagerTest.swift in Sources */,
Expand Down
19 changes: 10 additions & 9 deletions ORLib/ConsoleProviders/ESPProvision/DeviceProvision.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,16 @@ class DeviceProvision {
private var deviceConnection: DeviceConnection?
var callbackChannel: CallbackChannel?

private let timeSource: any TimeSource
var apiURL: URL
var deviceProvisionAPI: DeviceProvisionAPI

var backendConnectionTimeout: TimeInterval = 60

init (deviceConnection: DeviceConnection?, callbackChannel: CallbackChannel?, apiURL: URL) {
init (deviceConnection: DeviceConnection?, callbackChannel: CallbackChannel?, apiURL: URL, timeSource: any TimeSource = SystemTimeSource()) {
self.deviceConnection = deviceConnection
self.callbackChannel = callbackChannel
self.timeSource = timeSource
self.apiURL = apiURL
self.deviceProvisionAPI = DeviceProvisionAPIREST(apiURL: apiURL)
}
Expand All @@ -64,22 +66,21 @@ class DeviceProvision {
try await deviceConnection!.sendOpenRemoteConfig(mqttBrokerUrl: mqttURL, mqttUser: userName, mqttPassword: password, assetId: assetId)

var status = BackendConnectionStatus.connecting
// TODO: what about other status values ? Is status connecting while it connects ? or disconnected ? -> test with real device
let startTime = Date.now
let startTime = timeSource.now
while status != .connected {
if Date.now.timeIntervalSince(startTime) > backendConnectionTimeout {
if timeSource.now - startTime > backendConnectionTimeout {
sendProvisionDeviceStatus(connected: false, error: .timeoutError, errorMessage: "Timeout waiting for backend to get connected")
return
}
status = try await deviceConnection!.getBackendConnectionStatus()
Self.logger.info("ModuleOne reported connection status \(String(describing: status))")
if status == .failed {
sendProvisionDeviceStatus(connected: false, error: .communicationError, errorMessage: "Backend connection failed")
return
}
}

// TODO: review, if we're out of the loop, this is always true

if status == .connected {
sendProvisionDeviceStatus(connected: true)
}
sendProvisionDeviceStatus(connected: true)
} catch let error as ESPProviderError {
sendProvisionDeviceStatus(connected: false, error: error.errorCode, errorMessage: error.errorMessage)
} catch let error as RandomPasswordGeneratorError {
Expand Down
10 changes: 6 additions & 4 deletions ORLib/ConsoleProviders/ESPProvision/DeviceRegistry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,14 @@ class DeviceRegistry {

var callbackChannel: CallbackChannel?

private let timeSource: any TimeSource
private var loopDetector: LoopDetector
var searchDeviceTimeout: TimeInterval {
get {
loopDetector.timeout
}
set {
self.loopDetector = LoopDetector(timeout: newValue, maxIterations: searchDeviceMaxIterations)
self.loopDetector.timeout = newValue
}

}
Expand All @@ -79,7 +80,7 @@ class DeviceRegistry {
loopDetector.maxIterations
}
set {
self.loopDetector = LoopDetector(timeout: searchDeviceTimeout, maxIterations: newValue)
self.loopDetector.maxIterations = newValue
}

}
Expand All @@ -92,8 +93,9 @@ class DeviceRegistry {

public private(set) var bleScanning = false

init(searchDeviceTimeout: TimeInterval, searchDeviceMaxIterations: Int) {
self.loopDetector = LoopDetector(timeout: searchDeviceTimeout, maxIterations: searchDeviceMaxIterations)
init(searchDeviceTimeout: TimeInterval, searchDeviceMaxIterations: Int, timeSource: any TimeSource = SystemTimeSource()) {
self.timeSource = timeSource
self.loopDetector = LoopDetector(timeout: searchDeviceTimeout, maxIterations: searchDeviceMaxIterations, timeSource: timeSource)
}

func enable() {
Expand Down
Loading
Loading