     /// CoreBluetooth Central Manager Options
     public let options: Options
     
-    internal lazy var internalManager = CBCentralManager(
+    private lazy var internalManager = CBCentralManager(
         delegate: self.delegate,
         queue: self.managerQueue,
         options: self.options.optionsDictionary
     )
     
-    internal lazy var managerQueue = DispatchQueue(label: "\(type(of: self)) Manager Queue")
-    
-    internal lazy var queue = DispatchQueue(label: "\(type(of: self)) Queue")
-    
-    internal private(set) var peripheralQueue = [Peripheral: DispatchQueue]()
-    
-    internal lazy var delegate = Delegate(self)
-
-    internal private(set) var cache = Cache()
-    
-    internal private(set) var combine = Combine()
+    private lazy var managerQueue = DispatchQueue(label: "\(type(of: self)) Manager Queue")
+    
+    private lazy var queue = DispatchQueue(label: "\(type(of: self)) Queue")
+    
+    private var peripheralQueue = [Peripheral: DispatchQueue]()
+    
+    private lazy var delegate = Delegate(self)
+
+    private var cache = Cache()
+    
+    private var combine = Combine()
     
     // MARK: - Initialization
     

            CBCentralManagerScanOptionAllowDuplicatesKey: NSNumber(value: filterDuplicates == false)
        ]
        
        let subject: PassthroughSubject<ScanData<Peripheral, Advertisement>, Error> = self.queue.sync { [unowned self] in
            self.combine = .init()
            self.peripheralQueue.removeAll(keepingCapacity: true)
            self.peripherals.removeAll(keepingCapacity: true)
            return self.combine.scan
        }
        
        centralManager { [unowned self] (central) in
            precondition(central.isScanning == false)
            do {
                let state = self.state
                guard state == .poweredOn
                    else { throw DarwinCentralError.invalidState(state) }
                self.log.send("Scanning...")
                // start scanning
                self.internalManager.scanForPeripherals(withServices: serviceUUIDs, options: options)
                assert(self.internalManager.isScanning)
            } catch {
                self.combine.scan.send(completion: .failure(error))
            }
        }
        
        return subject.eraseToAnyPublisher()
    }
    
    /// Stops scanning for peripherals.
    public func stopScan() {
        self.queue.async { [unowned self] in
            assert(self.internalManager.isScanning)
            defer { assert(self.internalManager.isScanning == false) }
            self.internalManager.stopScan()
            self.combine.scan.send(completion: .finished)
            self.log.send("Discovered \(self.cache.peripherals.count) peripherals")
        }

    /// Get the maximum transmission unit for the specified peripheral.
    func maximumTransmissionUnit(for peripheral: Peripheral) -> AnyPublisher<ATTMaximumTransmissionUnit, Error> {
        
        return self.centralManager.tryMap { _ in
            guard self.state == .poweredOn else { throw DarwinCentralError.invalidState(self.state) }
        }
        .flatMap { _ in
            self.peripheral(for: peripheral)
        }
        .tryMap {
            let mtu = $0.maximumWriteValueLength(for: .withoutResponse) + 3
            assert(($0.value(forKey: "mtuLength") as! NSNumber).intValue == mtu)
            return ATTMaximumTransmissionUnit(rawValue: UInt16(mtu)) ?? .default
        }
        .eraseToAnyPublisher()
    }
    
    // MARK: - Private Methods
    
    private lazy var centralManager: AnyPublisher<CBCentralManager, Never> = Just(self.internalManager)
            .receive(on: self.queue)
            .eraseToAnyPublisher()
    
    private func peripheral(for peripheral: Peripheral) -> AnyPublisher<CBPeripheral, Error> {
        return self.centralManager.tryMap { _ in
            if let corePeripheral = self.cache.peripherals[peripheral] {
                return corePeripheral
            } else {
                throw CentralError.unknownPeripheral
            }
        }
        .receive(on: queue(for: peripheral))
        .eraseToAnyPublisher()
    }
    
    private func queue(for peripheral: Peripheral) -> DispatchQueue {
        return self.peripheralQueue[peripheral, default: DispatchQueue(label: "Peripheral \(peripheral) Queue")]
    }
}

// MARK: - Supporting Types
