Full Code of michaeldorner/BeeTee for AI

master 34149af004ad cached
30 files
103.6 KB
29.5k tokens
9 symbols
1 requests
Download .txt
Repository: michaeldorner/BeeTee
Branch: master
Commit: 34149af004ad
Files: 30
Total size: 103.6 KB

Directory structure:
gitextract_giyuhi4h/

├── .gitignore
├── .travis.yml
├── BeeTee/
│   ├── BeeTee-Bridging-Header.h
│   ├── BeeTee.swift
│   ├── BeeTeeDevice.swift
│   ├── BeeTeeModel.swift
│   ├── BluetoothDevice.h
│   ├── BluetoothDeviceHandler.h
│   ├── BluetoothDeviceHandler.m
│   ├── BluetoothManager.h
│   ├── BluetoothManagerHandler.h
│   ├── BluetoothManagerHandler.m
│   ├── DeviceDetailViewController.swift
│   └── DeviceListingViewController.swift
├── BeeTee Demo/
│   ├── AppDelegate.swift
│   ├── Assets.xcassets/
│   │   ├── AppIcon.appiconset/
│   │   │   └── Contents.json
│   │   ├── Contents.json
│   │   ├── DeviceListing.imageset/
│   │   │   └── Contents.json
│   │   └── MissionControl.imageset/
│   │       └── Contents.json
│   ├── Base.lproj/
│   │   ├── LaunchScreen.storyboard
│   │   └── Main.storyboard
│   ├── Info.plist
│   └── MissionControlViewController.swift
├── BeeTee.xcodeproj/
│   ├── project.pbxproj
│   └── project.xcworkspace/
│       └── contents.xcworkspacedata
├── BeeTeeTests/
│   ├── BeeTeeTests.swift
│   └── Info.plist
├── LICENSE
├── README.md
└── landingPage/
    └── BeeTeeLayer.graphml

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Xcode
.DS_Store
*/build/*
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
profile
*.moved-aside
DerivedData
.idea/
*.hmap
*.xccheckout

#CocoaPods
Pods


================================================
FILE: .travis.yml
================================================
branches:
  only:
  - master

language: objective-c
osx_image: xcode10

script:
- xcodebuild -project BeeTee.xcodeproj -target BeeTee -sdk iphonesimulator

after_success:
- bash <(curl -s https://codecov.io/bash)


================================================
FILE: BeeTee/BeeTee-Bridging-Header.h
================================================
/*
 This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/michaeldorner/BeeTee/blob/master/LICENSE. No part of BeeTee Project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.
 */

#import "BluetoothManagerHandler.h"
#import "BluetoothDeviceHandler.h"


================================================
FILE: BeeTee/BeeTee.swift
================================================
/*
 This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/michaeldorner/BeeTee/blob/master/LICENSE. No part of BeeTee Project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.
 */

import Foundation


public enum BeeTeeNotification: String {
    case PowerChanged               = "BluetoothPowerChangedNotification"
    case AvailabilityChanged        = "BluetoothAvailabilityChangedNotification"
    case DeviceDiscovered           = "BluetoothDeviceDiscoveredNotification"
    case DeviceRemoved              = "BluetoothDeviceRemovedNotification"
    case ConnectabilityChanged      = "BluetoothConnectabilityChangedNotification"
    case DeviceUpdated              = "BluetoothDeviceUpdatedNotification"
    case DiscoveryStateChanged      = "BluetoothDiscoveryStateChangedNotification"
    case DeviceConnectSuccess       = "BluetoothDeviceConnectSuccessNotification"
    case ConnectionStatusChanged    = "BluetoothConnectionStatusChangedNotification"
    case DeviceDisconnectSuccess    = "BluetoothDeviceDisconnectSuccessNotification"
    
    public static let allNotifications: [BeeTeeNotification] = [.PowerChanged, .AvailabilityChanged, .DeviceDiscovered, .DeviceRemoved, .ConnectabilityChanged, .DeviceUpdated, .DiscoveryStateChanged, .DeviceConnectSuccess, .ConnectionStatusChanged, .DeviceDisconnectSuccess]
}



public protocol BeeTeeDelegate {
    func receivedBeeTeeNotification(notification: BeeTeeNotification)
}



public class BeeTee {
    
    public var delegate: BeeTeeDelegate? = nil
    public var availableDevices: [BeeTeeDevice] {
        get {
            return Array(_availableDevices)
        }
    }
    
    private let bluetoothManagerHandler = BluetoothManagerHandler.sharedInstance()!
    private var _availableDevices = Set<BeeTeeDevice>()
    private var tokenCache = [BeeTeeNotification: NSObjectProtocol]()
    
    public init() {
        
        for beeTeeNotification in BeeTeeNotification.allNotifications {
            print("Registered \(beeTeeNotification)")
            
            let notification = NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: beeTeeNotification.rawValue), object: nil, queue: OperationQueue.main) { [unowned self] (notification) in
                let beeTeeNotification = BeeTeeNotification.init(rawValue: notification.name.rawValue)!
                switch beeTeeNotification {
                case .DeviceDiscovered:
                    let beeTeeDevice = self.extractBeeTeeDevice(from: notification)
                    self._availableDevices.insert(beeTeeDevice)
                case .DeviceRemoved:
                    let beeTeeDevice = self.extractBeeTeeDevice(from: notification)
                    self._availableDevices.remove(beeTeeDevice)
                default:
                    break
                }
                if (self.delegate != nil) {
                    self.delegate?.receivedBeeTeeNotification(notification: beeTeeNotification)
                }
            }
            self.tokenCache[beeTeeNotification] = notification
        }
    }
    
    deinit {
        for key in tokenCache.keys {
            NotificationCenter.default.removeObserver(tokenCache[key]!)
        }
    }
    
    public func enableBluetooth() {
        bluetoothManagerHandler.enable()
    }
    
    public func disableBluetooth() {
        bluetoothManagerHandler.disable()
    }

    public func bluetoothIsEnabled() -> Bool {
        return bluetoothManagerHandler.enabled()
    }
    
    public func startScanForDevices() {
        bluetoothManagerHandler.startScan()
    }
    
    public func stopScan() {
        bluetoothManagerHandler.stopScan()
        resetAvailableDevices()
    }
    
    public func isScanning() -> Bool {
        return bluetoothManagerHandler.isScanning()
    }
    
    public static func debugLowLevel() {
        print("This is a dirty C hack and only for demonstration and deep debugging, but not for production.") // credits to http://stackoverflow.com/a/3738387/1864294
        CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
                                        nil,
                                        { (_, observer, name, _, _) in
                                            let n = name?.rawValue as! String
                                            if n.hasPrefix("B") { // notice only notification they are associated with the BluetoothManager.framework
                                               print("Received notification: \(name)")
                                            }
                                        },
                                        nil,
                                        nil,
                                        .deliverImmediately)
    }
    
    private func resetAvailableDevices() {
        _availableDevices.removeAll()
    }
    
    private func extractBeeTeeDevice(from notification: Notification) -> BeeTeeDevice {
        let bluetoothDevice = BluetoothDeviceHandler(notification: notification)!
        let beeTeeDevice = BeeTeeDevice(name: bluetoothDevice.name, address: bluetoothDevice.address, majorClass: bluetoothDevice.majorClass, minorClass: bluetoothDevice.minorClass, type: bluetoothDevice.type, supportsBatteryLevel: bluetoothDevice.supportsBatteryLevel, detectingDate: Date())
        return beeTeeDevice
    }
}



================================================
FILE: BeeTee/BeeTeeDevice.swift
================================================
/*
 This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/michaeldorner/BeeTee/blob/master/LICENSE. No part of BeeTee Project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.
 */

import Foundation


public class BeeTeeDevice: Hashable, CustomStringConvertible {
    let name: String
    let address: String
    let majorClass: UInt
    let minorCass: UInt
    let type: Int
    let supportsBatteryLevel: Bool
    let detectingDate: Date
    
    convenience init(notification: Notification) {
        let bluetoothDevice = BluetoothDeviceHandler(notification: notification)!
        self.init(name: bluetoothDevice.name, address: bluetoothDevice.address, majorClass: bluetoothDevice.majorClass, minorClass: bluetoothDevice.minorClass, type: bluetoothDevice.type, supportsBatteryLevel: bluetoothDevice.supportsBatteryLevel, detectingDate: Date())
    }
    
    init(name: String, address: String, majorClass: UInt, minorClass: UInt, type: Int, supportsBatteryLevel: Bool, detectingDate: Date) {
        self.name = name
        self.address = address
        self.majorClass = majorClass
        self.minorCass = minorClass
        self.type = type
        self.supportsBatteryLevel = supportsBatteryLevel
        self.detectingDate = detectingDate
    }
    
    public var description: String {
        return "\(name) (\(address)) @ \(detectingDate))"
    }
    
    public var hashValue: Int {
        return address.hashValue
    }
    
    public static func ==(lhs: BeeTeeDevice, rhs: BeeTeeDevice) -> Bool {
        return lhs.address == rhs.address
    }
}


================================================
FILE: BeeTee/BeeTeeModel.swift
================================================
/*
 This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/michaeldorner/BeeTee/blob/master/LICENSE. No part of BeeTee Project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.
 */

import Foundation

class BeeTeeModel: BeeTeeDelegate {

    static let sharedInstance = BeeTeeModel()

    private let beeTee = BeeTee()
    private var subscribers = [BeeTeeDelegate]()
        
    public var availableDevices: [BeeTeeDevice] {
        get {
            return beeTee.availableDevices
        }
    }
    
    private init() {
        beeTee.delegate = self
    }
    
    func receivedBeeTeeNotification(notification: BeeTeeNotification) {
        for subscriber in subscribers {
            subscriber.receivedBeeTeeNotification(notification: notification)
        }
        print("BeeTeeNotification: " + String(describing: notification))
    }
    
    public func turnBluetoothOn() {
        beeTee.enableBluetooth()
        print("Bluetooth turned on")

    }
    
    public func turnBluetoothOff() {
        beeTee.disableBluetooth()
        print("Bluetooth turned off")

    }
    
    public func bluetoothIsOn() -> Bool {
        return beeTee.bluetoothIsEnabled()
    }
    
    public func startScanForDevices() {
        beeTee.startScanForDevices()
        print("Bluetooth started scanning for new devices")

    }
    
    public func stopScan() {
        beeTee.stopScan()
        print("Bluetooth stopped scanning")
    }
    
    public func isScanning() -> Bool {
        return beeTee.isScanning()
    }
    
    public func subscribe(subscriber: BeeTeeDelegate) {
        subscribers.append(subscriber)
    }
    
    public func unsubscribe(subscriber: BeeTeeDelegate) {
        //todo: add remove
    }
    
}


================================================
FILE: BeeTee/BluetoothDevice.h
================================================
/*
 This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/michaeldorner/BeeTee/blob/master/LICENSE. No part of BeeTee Project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.
 */

/* Generated by RuntimeBrowser
   Image: /System/Library/PrivateFrameworks/BluetoothManager.framework/BluetoothManager
 */

@interface BluetoothDevice : NSObject {
    NSString * _address;
    struct BTDeviceImpl { } * _device;
    NSString * _name;
}

- (void)_clearName;
- (BOOL)_isNameCached;
- (void)acceptSSP:(int)arg1;
- (id)address;
- (int)batteryLevel;
- (BOOL)cloudPaired;
- (int)compare:(id)arg1;
- (void)connect;
- (void)connectWithServices:(unsigned int)arg1;
- (BOOL)connected;
- (unsigned int)connectedServices;
- (unsigned int)connectedServicesCount;
- (id)copyWithZone:(struct _NSZone { }*)arg1;
- (void)dealloc;
- (id)description;
- (struct BTDeviceImpl*)device;
- (void)disconnect;
- (unsigned int)doubleTapAction;
- (void)endVoiceCommand;
- (id)getServiceSetting:(unsigned int)arg1 key:(id)arg2;
- (BOOL)inEarDetectEnabled;
- (id)initWithDevice:(struct BTDeviceImpl { }*)arg1 address:(id)arg2;
- (BOOL)isAccessory;
- (BOOL)isAppleAudioDevice;
- (BOOL)isServiceSupported:(unsigned int)arg1;
- (BOOL)magicPaired;
- (BOOL)magicPairedDeviceNameUpdated;
- (unsigned int)majorClass;
- (unsigned int)micMode;
- (unsigned int)minorClass;
- (id)name;
- (BOOL)paired;
- (unsigned int)productId;
- (id)scoUID;
- (void)setDevice:(struct BTDeviceImpl { }*)arg1;
- (BOOL)setDoubleTapAction:(unsigned int)arg1;
- (BOOL)setInEarDetectEnabled:(BOOL)arg1;
- (BOOL)setMicMode:(unsigned int)arg1;
- (void)setPIN:(id)arg1;
- (void)setServiceSetting:(unsigned int)arg1 key:(id)arg2 value:(id)arg3;
- (void)setSyncGroup:(int)arg1 enabled:(BOOL)arg2;
- (void)setSyncSettings:(struct { BOOL x1; BOOL x2; BOOL x3; BOOL x4; })arg1;
- (BOOL)setUserName:(id)arg1;
- (void)startVoiceCommand;
- (BOOL)supportsBatteryLevel;
- (id)syncGroups;
- (struct { BOOL x1; BOOL x2; BOOL x3; BOOL x4; })syncSettings;
- (int)type;
- (void)unpair;
- (unsigned int)vendorId;

@end


================================================
FILE: BeeTee/BluetoothDeviceHandler.h
================================================
/*
 This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/michaeldorner/BeeTee/blob/master/LICENSE. No part of BeeTee Project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.
 */

#import <Foundation/Foundation.h>

@interface BluetoothDeviceHandler : NSObject

@property (strong, nonatomic, readonly) NSString* name;
@property (strong, nonatomic, readonly) NSString* address;
@property (assign, nonatomic, readonly) NSUInteger majorClass;
@property (assign, nonatomic, readonly) NSUInteger minorClass;
@property (assign, nonatomic, readonly) NSInteger type;
@property (assign, nonatomic, readonly) BOOL supportsBatteryLevel;

- (instancetype)initWithNotification:(NSNotification*) notification;

@end


================================================
FILE: BeeTee/BluetoothDeviceHandler.m
================================================
/*
 This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/michaeldorner/BeeTee/blob/master/LICENSE. No part of BeeTee Project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.
 */

#import "BluetoothDeviceHandler.h"
#import "BluetoothDevice.h"


@interface BluetoothDeviceHandler ()

@property (strong, nonatomic, readwrite) NSString* name;
@property (strong, nonatomic, readwrite) NSString* address;
@property (assign, nonatomic, readwrite) NSUInteger majorClass;
@property (assign, nonatomic, readwrite) NSUInteger minorClass;
@property (assign, nonatomic, readwrite) NSInteger type;
@property (assign, nonatomic, readwrite) BOOL supportsBatteryLevel;

@end


@implementation BluetoothDeviceHandler

- (instancetype)initWithNotification:(NSNotification*) notification {
    BluetoothDevice *bluetoothDevice = [notification object];
    
    self = [super init];
    if (self) {
        self.name = bluetoothDevice.name;
        self.address = bluetoothDevice.address;
        self.majorClass = bluetoothDevice.majorClass;
        self.minorClass = bluetoothDevice.minorClass;
        self.type = bluetoothDevice.type;
        self.supportsBatteryLevel = bluetoothDevice.supportsBatteryLevel;
    }
    return self;
}

@end


================================================
FILE: BeeTee/BluetoothManager.h
================================================
/*
 This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/michaeldorner/BeeTee/blob/master/LICENSE. No part of BeeTee Project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.
 */

/* Generated by RuntimeBrowser
   Image: /System/Library/PrivateFrameworks/BluetoothManager.framework/BluetoothManager
 */

@interface BluetoothManager : NSObject {
    struct BTAccessoryManagerImpl { } * _accessoryManager;
    BOOL  _audioConnected;
    int  _available;
    NSMutableDictionary * _btAddrDict;
    NSMutableDictionary * _btDeviceDict;
    struct BTDiscoveryAgentImpl { } * _discoveryAgent;
    struct BTLocalDeviceImpl { } * _localDevice;
    struct BTPairingAgentImpl { } * _pairingAgent;
    BOOL  _scanningEnabled;
    BOOL  _scanningInProgress;
    unsigned int  _scanningServiceMask;
    struct BTSessionImpl { } * _session;
}

// Image: /System/Library/PrivateFrameworks/BluetoothManager.framework/BluetoothManager

+ (int)lastInitError;
+ (void)setSharedInstanceQueue:(id)arg1;
+ (id)sharedInstance;

- (struct BTAccessoryManagerImpl*)_accessoryManager;
- (void)_advertisingChanged;
- (BOOL)_attach;
- (void)_cleanup:(BOOL)arg1;
- (void)_connectabilityChanged;
- (void)_connectedStatusChanged;
- (void)_discoveryStateChanged;
- (void)_pairedStatusChanged;
- (void)_postNotification:(id)arg1;
- (void)_postNotificationWithArray:(id)arg1;
- (void)_powerChanged;
- (void)_removeDevice:(id)arg1;
- (void)_restartScan;
- (void)_scanForServices:(unsigned int)arg1 withMode:(int)arg2;
- (void)_setScanState:(int)arg1;
- (BOOL)_setup:(struct BTSessionImpl { }*)arg1;
- (void)acceptSSP:(int)arg1 forDevice:(id)arg2;
- (id)addDeviceIfNeeded:(struct BTDeviceImpl { }*)arg1;
- (BOOL)audioConnected;
- (BOOL)available;
- (void)cancelPairing;
- (void)connectDevice:(id)arg1;
- (void)connectDevice:(id)arg1 withServices:(unsigned int)arg2;
- (BOOL)connectable;
- (BOOL)connected;
- (id)connectedDevices;
- (id)connectingDevices;
- (void)dealloc;
- (BOOL)devicePairingEnabled;
- (BOOL)deviceScanningEnabled;
- (BOOL)deviceScanningInProgress;
- (void)disconnectDevice:(id)arg1;
- (void)enableTestMode;
- (BOOL)enabled;
- (void)endVoiceCommand:(id)arg1;
- (id)init;
- (BOOL)isAnyoneAdvertising;
- (BOOL)isAnyoneScanning;
- (BOOL)isDiscoverable;
- (BOOL)isServiceSupported:(unsigned int)arg1;
- (id)localAddress;
- (id)pairedDevices;
- (void)postNotification:(id)arg1;
- (void)postNotificationName:(id)arg1 object:(id)arg2;
- (void)postNotificationName:(id)arg1 object:(id)arg2 error:(id)arg3;
- (int)powerState;
- (BOOL)powered;
- (void)resetDeviceScanning;
- (void)scanForConnectableDevices:(unsigned int)arg1;
- (void)scanForServices:(unsigned int)arg1;
- (void)setAudioConnected:(BOOL)arg1;
- (void)setConnectable:(BOOL)arg1;
- (void)setDevicePairingEnabled:(BOOL)arg1;
- (void)setDeviceScanningEnabled:(BOOL)arg1;
- (void)setDiscoverable:(BOOL)arg1;
- (BOOL)setEnabled:(BOOL)arg1;
- (void)setPincode:(id)arg1 forDevice:(id)arg2;
- (BOOL)setPowered:(BOOL)arg1;
- (void)showPowerPrompt;
- (void)startVoiceCommand:(id)arg1;
- (void)unpairDevice:(id)arg1;
- (BOOL)wasDeviceDiscovered:(id)arg1;

// Image: /System/Library/PrivateFrameworks/GameKitServices.framework/GameKitServices

- (int)localDeviceSupportsService:(unsigned int)arg1;

@end


================================================
FILE: BeeTee/BluetoothManagerHandler.h
================================================
/*
 This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/michaeldorner/BeeTee/blob/master/LICENSE. No part of BeeTee Project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.
 */

#import <Foundation/Foundation.h>


@interface BluetoothManagerHandler : NSObject

+ (BluetoothManagerHandler*) sharedInstance;

- (bool) powered;
- (void) setPower: (bool)powerStatus;
- (void) startScan;
- (void) stopScan;
- (bool) isScanning;
- (bool) enabled;
- (void) disable;
- (void) enable;

@end


================================================
FILE: BeeTee/BluetoothManagerHandler.m
================================================
/*
 This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/michaeldorner/BeeTee/blob/master/LICENSE. No part of BeeTee Project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.
 */

#import "BluetoothManagerHandler.h"
#import "BluetoothManager.h"

static BluetoothManager *_bluetoothManager = nil;
static BluetoothManagerHandler *_handler = nil;

@implementation BluetoothManagerHandler


+ (BluetoothManagerHandler*) sharedInstance {

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSBundle *b = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/BluetoothManager.framework"];
        if (![b load]) {
            NSLog(@"Error"); // maybe throw an exception
        } else {
            _bluetoothManager = [NSClassFromString(@"BluetoothManager") valueForKey:@"sharedInstance"];
            _handler = [[BluetoothManagerHandler alloc] init];
        }
    });
    return _handler;
}


- (bool) powered {
    return [_bluetoothManager powered];
}


- (void) setPower: (bool)powerStatus {
    [_bluetoothManager setPowered:powerStatus];
}


- (void) startScan {
    [_bluetoothManager setDeviceScanningEnabled: true];
    [_bluetoothManager scanForServices: 0xFFFFFFFF];
}


- (void) stopScan {
    [_bluetoothManager setDeviceScanningEnabled: false];
}


- (bool)isScanning {
    return [_bluetoothManager deviceScanningEnabled];
}


- (bool)enabled {
    return [_bluetoothManager enabled];
}

- (void)disable {
    [_bluetoothManager setEnabled:false];
}

- (void)enable {
    [_bluetoothManager setEnabled:true];
}

@end


================================================
FILE: BeeTee/DeviceDetailViewController.swift
================================================
/*
 This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/michaeldorner/BeeTee/blob/master/LICENSE. No part of BeeTee Project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.
 */

import UIKit


class DeviceDetailViewController: UITableViewController {
    
    var device: BeeTeeDevice? = nil
    let attributes = ["Name", "Address", "Major Class", "Minor Class", "Type", "Battery"]
    
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return attributes.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        var value: String = ""
        if (device != nil) {
            switch indexPath.row {
            case 0:
                value = device!.name
            case 1:
                value = device!.address
            case 2:
                value = String(device!.majorClass)
            case 3:
                value = String(device!.minorCass)
            case 4:
                value = String(device!.type)
            case 5:
                value = device!.supportsBatteryLevel ? "Yes" : "No"
            default: break
            }
        }
        let cell = tableView.dequeueReusableCell(withIdentifier: "DeviceDetailCellIdentifier")!
        cell.textLabel?.text = attributes[indexPath.row]
        cell.detailTextLabel?.text = value
        
        return cell
    }
    
    override func tableView(_ tableView: UITableView, shouldShowMenuForRowAt indexPath: IndexPath) -> Bool {
        return (tableView.cellForRow(at: indexPath)?.detailTextLabel?.text) != nil
    }
    
    override func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
        return action == #selector(copy(_:))
    }
    
    override func tableView(_ tableView: UITableView, performAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) {
        if action == #selector(copy(_:)) {
            let cell = tableView.cellForRow(at: indexPath)
            let pasteboard = UIPasteboard.general
            pasteboard.string = cell?.detailTextLabel?.text
        }
    }
    
    
    
}


================================================
FILE: BeeTee/DeviceListingViewController.swift
================================================
/*
 This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/michaeldorner/BeeTee/blob/master/LICENSE. No part of BeeTee Project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.
 */

import UIKit

class DeviceListingViewController: UITableViewController, BeeTeeDelegate {
    let beeTeeModel = BeeTeeModel.sharedInstance
    
    override func viewDidLoad() {
        super.viewDidLoad()
        beeTeeModel.subscribe(subscriber: self)
    }
    
    func receivedBeeTeeNotification(notification: BeeTeeNotification) {
        tableView.reloadData()
    }
    
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return beeTeeModel.availableDevices.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let beeTeeDevice = beeTeeModel.availableDevices[indexPath.row]
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "DeviceCellIdentifier")!
        cell.textLabel?.text = beeTeeDevice.name
        cell.detailTextLabel?.text = beeTeeDevice.address
        
        return cell
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let indexPath = tableView.indexPath(for: sender as! UITableViewCell)!
        let selectedDevice = beeTeeModel.availableDevices[indexPath.row]

        let deviceDetailViewController: DeviceDetailViewController = segue.destination as! DeviceDetailViewController
        deviceDetailViewController.device = selectedDevice
    }
}


================================================
FILE: BeeTee Demo/AppDelegate.swift
================================================
/*
 This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/michaeldorner/BeeTee/blob/master/LICENSE. No part of BeeTee Project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.
 */

import UIKit
import CoreLocation

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }
}



================================================
FILE: BeeTee Demo/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "iphone",
      "size" : "20x20",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "20x20",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "3x"
    },
    {
      "idiom" : "ipad",
      "size" : "20x20",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "20x20",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "29x29",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "29x29",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "40x40",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "40x40",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "76x76",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "76x76",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "83.5x83.5",
      "scale" : "2x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: BeeTee Demo/Assets.xcassets/Contents.json
================================================
{
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: BeeTee Demo/Assets.xcassets/DeviceListing.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "noun_18353-2.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "filename" : "noun_18353-1.png",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "filename" : "noun_18353.png",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: BeeTee Demo/Assets.xcassets/MissionControl.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "noun_655374_cc-2.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "filename" : "noun_655374_cc-1.png",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "filename" : "noun_655374_cc.png",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: BeeTee Demo/Base.lproj/LaunchScreen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="EHf-IW-A2E">
            <objects>
                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
                        <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="53" y="375"/>
        </scene>
    </scenes>
</document>


================================================
FILE: BeeTee Demo/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="xHc-kc-34a">
    <device id="retina4_7" orientation="portrait">
        <adaptation id="fullscreen"/>
    </device>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--Available Devices-->
        <scene sceneID="HH2-jY-xzd">
            <objects>
                <tableViewController id="TsF-5F-cgi" customClass="DeviceListingViewController" customModule="BeeTee" customModuleProvider="target" sceneMemberID="viewController">
                    <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="9xF-RZ-fRr">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                        <prototypes>
                            <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="DeviceCellIdentifier" textLabel="iug-kI-3XO" detailTextLabel="abr-Dm-LY2" style="IBUITableViewCellStyleSubtitle" id="dmk-tp-LaW">
                                <rect key="frame" x="0.0" y="28" width="375" height="44"/>
                                <autoresizingMask key="autoresizingMask"/>
                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="dmk-tp-LaW" id="rFy-eZ-28k">
                                    <rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
                                    <autoresizingMask key="autoresizingMask"/>
                                    <subviews>
                                        <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="iug-kI-3XO">
                                            <rect key="frame" x="15" y="4" width="34" height="21"/>
                                            <autoresizingMask key="autoresizingMask"/>
                                            <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                            <nil key="textColor"/>
                                            <nil key="highlightedColor"/>
                                        </label>
                                        <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Subtitle" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="abr-Dm-LY2">
                                            <rect key="frame" x="15" y="25" width="44" height="15"/>
                                            <autoresizingMask key="autoresizingMask"/>
                                            <fontDescription key="fontDescription" type="system" pointSize="12"/>
                                            <nil key="textColor"/>
                                            <nil key="highlightedColor"/>
                                        </label>
                                    </subviews>
                                </tableViewCellContentView>
                                <connections>
                                    <segue destination="5TA-Ix-vPu" kind="show" id="kDR-Wq-g2n"/>
                                </connections>
                            </tableViewCell>
                        </prototypes>
                        <connections>
                            <outlet property="dataSource" destination="TsF-5F-cgi" id="uaY-He-PhK"/>
                            <outlet property="delegate" destination="TsF-5F-cgi" id="9Qm-2Z-Pdf"/>
                        </connections>
                    </tableView>
                    <navigationItem key="navigationItem" title="Available Devices" id="280-gc-yOW"/>
                </tableViewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="DPM-11-kJf" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="1420" y="-348"/>
        </scene>
        <!--Available Devices-->
        <scene sceneID="rcb-3O-ext">
            <objects>
                <navigationController id="VNV-Qq-KCB" sceneMemberID="viewController">
                    <tabBarItem key="tabBarItem" title="Available Devices" image="DeviceListing" selectedImage="DeviceListing" id="ocy-CZ-wvo"/>
                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="iOT-9T-MhV">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
                        <autoresizingMask key="autoresizingMask"/>
                    </navigationBar>
                    <connections>
                        <segue destination="TsF-5F-cgi" kind="relationship" relationship="rootViewController" id="6eB-Qw-Lqt"/>
                    </connections>
                </navigationController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="kAm-LY-Hg8" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="666" y="-347"/>
        </scene>
        <!--Device Detail View Controller-->
        <scene sceneID="52t-EE-eng">
            <objects>
                <tableViewController id="5TA-Ix-vPu" customClass="DeviceDetailViewController" customModule="BeeTee" customModuleProvider="target" sceneMemberID="viewController">
                    <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="8Zo-gy-HEA">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
                        <prototypes>
                            <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="DeviceDetailCellIdentifier" textLabel="Vqg-q7-c2s" detailTextLabel="fr6-aL-aq6" style="IBUITableViewCellStyleValue2" id="do9-3x-Dlr">
                                <rect key="frame" x="0.0" y="56" width="375" height="44"/>
                                <autoresizingMask key="autoresizingMask"/>
                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="do9-3x-Dlr" id="L1U-5Q-4ab">
                                    <rect key="frame" x="0.0" y="0.0" width="375" height="43"/>
                                    <autoresizingMask key="autoresizingMask"/>
                                    <subviews>
                                        <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Vqg-q7-c2s">
                                            <rect key="frame" x="15" y="14" width="91" height="16"/>
                                            <autoresizingMask key="autoresizingMask"/>
                                            <fontDescription key="fontDescription" type="system" pointSize="13"/>
                                            <nil key="textColor"/>
                                            <nil key="highlightedColor"/>
                                        </label>
                                        <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Detail" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="fr6-aL-aq6">
                                            <rect key="frame" x="112" y="14" width="35" height="16"/>
                                            <autoresizingMask key="autoresizingMask"/>
                                            <fontDescription key="fontDescription" type="system" pointSize="13"/>
                                            <nil key="textColor"/>
                                            <nil key="highlightedColor"/>
                                        </label>
                                    </subviews>
                                </tableViewCellContentView>
                            </tableViewCell>
                        </prototypes>
                        <sections/>
                        <connections>
                            <outlet property="dataSource" destination="5TA-Ix-vPu" id="oLS-ao-ysc"/>
                            <outlet property="delegate" destination="5TA-Ix-vPu" id="oxJ-a7-bjy"/>
                        </connections>
                    </tableView>
                </tableViewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="6js-V9-RDK" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="2167" y="-348"/>
        </scene>
        <!--Tab Bar Controller-->
        <scene sceneID="qe4-Se-N6W">
            <objects>
                <tabBarController id="xHc-kc-34a" sceneMemberID="viewController">
                    <tabBar key="tabBar" contentMode="scaleToFill" id="CTN-Ye-6Yb">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="49"/>
                        <autoresizingMask key="autoresizingMask"/>
                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
                    </tabBar>
                    <connections>
                        <segue destination="ZfG-JE-bog" kind="relationship" relationship="viewControllers" id="Rav-B4-nBh"/>
                        <segue destination="VNV-Qq-KCB" kind="relationship" relationship="viewControllers" id="buX-QH-cXp"/>
                    </connections>
                </tabBarController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="gjt-1t-U8j" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="-310" y="7"/>
        </scene>
        <!--Mission Control-->
        <scene sceneID="WJS-H0-eeD">
            <objects>
                <navigationController id="ZfG-JE-bog" sceneMemberID="viewController">
                    <tabBarItem key="tabBarItem" title="Mission Control" id="SjI-Rp-Y8P"/>
                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="r35-rj-mYK">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
                        <autoresizingMask key="autoresizingMask"/>
                    </navigationBar>
                    <connections>
                        <segue destination="To5-CM-11h" kind="relationship" relationship="rootViewController" id="x4x-F7-MUN"/>
                    </connections>
                </navigationController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="0kZ-di-AJi" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="665" y="322"/>
        </scene>
        <!--Mission Control-->
        <scene sceneID="Rds-kC-Pw5">
            <objects>
                <tableViewController id="To5-CM-11h" customClass="MissionControlViewController" customModule="BeeTee" customModuleProvider="target" sceneMemberID="viewController">
                    <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="5CV-P7-yu6">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
                        <sections>
                            <tableViewSection id="hSf-U8-TQa">
                                <cells>
                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="5Z3-dQ-JQO">
                                        <rect key="frame" x="0.0" y="35" width="375" height="44"/>
                                        <autoresizingMask key="autoresizingMask"/>
                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="5Z3-dQ-JQO" id="3uE-sw-9uL">
                                            <rect key="frame" x="0.0" y="0.0" width="375" height="43"/>
                                            <autoresizingMask key="autoresizingMask"/>
                                            <subviews>
                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Bluetooth Power" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="l0H-g9-rqU">
                                                    <rect key="frame" x="8" y="11" width="126" height="21"/>
                                                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                                                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                                    <nil key="textColor"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                                <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jok-JS-aLg">
                                                    <rect key="frame" x="318" y="6" width="51" height="31"/>
                                                    <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
                                                    <connections>
                                                        <action selector="switchBluetoothPower" destination="To5-CM-11h" eventType="valueChanged" id="tjT-tA-2qx"/>
                                                    </connections>
                                                </switch>
                                            </subviews>
                                        </tableViewCellContentView>
                                    </tableViewCell>
                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="lhU-XG-7Jy">
                                        <rect key="frame" x="0.0" y="79" width="375" height="44"/>
                                        <autoresizingMask key="autoresizingMask"/>
                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="lhU-XG-7Jy" id="Vlc-ml-3jV">
                                            <rect key="frame" x="0.0" y="0.0" width="375" height="43"/>
                                            <autoresizingMask key="autoresizingMask"/>
                                            <subviews>
                                                <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OuI-qn-KPi">
                                                    <rect key="frame" x="318" y="6" width="51" height="31"/>
                                                    <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
                                                    <connections>
                                                        <action selector="switchBluetoothScanStatus" destination="To5-CM-11h" eventType="valueChanged" id="DzG-oJ-XxE"/>
                                                    </connections>
                                                </switch>
                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Scan for new Devices" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TRc-dc-AKL">
                                                    <rect key="frame" x="8" y="11" width="165" height="21"/>
                                                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                                                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                                    <nil key="textColor"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                            </subviews>
                                        </tableViewCellContentView>
                                    </tableViewCell>
                                </cells>
                            </tableViewSection>
                        </sections>
                        <connections>
                            <outlet property="dataSource" destination="To5-CM-11h" id="HLZ-3K-9Sj"/>
                            <outlet property="delegate" destination="To5-CM-11h" id="x0Z-Ix-JH0"/>
                        </connections>
                    </tableView>
                    <tabBarItem key="tabBarItem" title="Mission Control" image="MissionControl" selectedImage="MissionControl" id="jqF-To-HJq"/>
                    <navigationItem key="navigationItem" title="Mission Control" id="zi5-Wx-1w1"/>
                    <connections>
                        <outlet property="bluetoothPowerSwitch" destination="jok-JS-aLg" id="Ag9-T7-d8X"/>
                        <outlet property="bluetoothScanSwitch" destination="OuI-qn-KPi" id="VM5-Ay-EHV"/>
                    </connections>
                </tableViewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="NfO-K2-ccY" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="1420" y="322"/>
        </scene>
    </scenes>
    <resources>
        <image name="DeviceListing" width="25" height="25"/>
        <image name="MissionControl" width="25" height="25"/>
    </resources>
</document>


================================================
FILE: BeeTee Demo/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>3.0</string>
	<key>CFBundleVersion</key>
	<string>$(CURRENT_PROJECT_VERSION)</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIMainStoryboardFile</key>
	<string>Main</string>
	<key>UIRequiredDeviceCapabilities</key>
	<array>
		<string>armv7</string>
	</array>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
</dict>
</plist>


================================================
FILE: BeeTee Demo/MissionControlViewController.swift
================================================
/*
 This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/michaeldorner/BeeTee/blob/master/LICENSE. No part of BeeTee Project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.
 */

import UIKit


class MissionControlViewController: UITableViewController, BeeTeeDelegate {
    
    private let beeTeeModel = BeeTeeModel.sharedInstance
    
    @IBOutlet weak var bluetoothPowerSwitch: UISwitch!
    @IBOutlet weak var bluetoothScanSwitch: UISwitch!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        beeTeeModel.subscribe(subscriber: self)
        bluetoothPowerSwitch.setOn(beeTeeModel.bluetoothIsOn(), animated: false)
        bluetoothScanSwitch.setOn(beeTeeModel.isScanning(), animated: false)
    }

    @IBAction func switchBluetoothPower() {
        if beeTeeModel.bluetoothIsOn() {
            beeTeeModel.turnBluetoothOff()
        } else {
            beeTeeModel.turnBluetoothOn()
        }
    }
    
    @IBAction func switchBluetoothScanStatus() {
        if beeTeeModel.isScanning() {
            beeTeeModel.stopScan()
        } else {
            beeTeeModel.startScanForDevices()
        }
    }
    
    func receivedBeeTeeNotification(notification: BeeTeeNotification) {
        tableView.reloadData()
        bluetoothPowerSwitch.setOn(beeTeeModel.bluetoothIsOn(), animated: true)
        bluetoothScanSwitch.setOn(beeTeeModel.isScanning(), animated: true)
    }
}


================================================
FILE: BeeTee.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 46;
	objects = {

/* Begin PBXBuildFile section */
		5F0893721E17F82500197FAD /* MissionControlViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F0893711E17F82500197FAD /* MissionControlViewController.swift */; };
		5F0893761E181C7B00197FAD /* BeeTeeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F0893751E181C7B00197FAD /* BeeTeeModel.swift */; };
		5F08937D1E19021500197FAD /* DeviceListingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F08937C1E19021500197FAD /* DeviceListingViewController.swift */; };
		5F08937F1E19071800197FAD /* DeviceDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F08937E1E19071800197FAD /* DeviceDetailViewController.swift */; };
		5F1764F71E0EBFB0003F888A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F1764F61E0EBFB0003F888A /* AppDelegate.swift */; };
		5F1764F91E0EBFBA003F888A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5F1764F81E0EBFBA003F888A /* Assets.xcassets */; };
		5F1764FE1E0EBFC2003F888A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5F1764FA1E0EBFC2003F888A /* LaunchScreen.storyboard */; };
		5F1764FF1E0EBFC2003F888A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5F1764FC1E0EBFC2003F888A /* Main.storyboard */; };
		5F2409071E0C0134004AF90F /* BeeTeeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F2409061E0C0134004AF90F /* BeeTeeTests.swift */; };
		5F9F63371E0EB9300014A043 /* BeeTee.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F9F632F1E0EB9300014A043 /* BeeTee.swift */; };
		5F9F63381E0EB9300014A043 /* BeeTeeDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F9F63301E0EB9300014A043 /* BeeTeeDevice.swift */; };
		5F9F63391E0EB9300014A043 /* BluetoothDeviceHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F9F63331E0EB9300014A043 /* BluetoothDeviceHandler.m */; };
		5F9F633A1E0EB9300014A043 /* BluetoothManagerHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F9F63361E0EB9300014A043 /* BluetoothManagerHandler.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
		5F2409031E0C0134004AF90F /* PBXContainerItemProxy */ = {
			isa = PBXContainerItemProxy;
			containerPortal = 5F2408E61E0C0134004AF90F /* Project object */;
			proxyType = 1;
			remoteGlobalIDString = 5F2408ED1E0C0134004AF90F;
			remoteInfo = BeeTee;
		};
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
		5F0893711E17F82500197FAD /* MissionControlViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MissionControlViewController.swift; path = "BeeTee Demo/MissionControlViewController.swift"; sourceTree = SOURCE_ROOT; };
		5F0893751E181C7B00197FAD /* BeeTeeModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeeTeeModel.swift; sourceTree = "<group>"; };
		5F08937C1E19021500197FAD /* DeviceListingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceListingViewController.swift; sourceTree = "<group>"; };
		5F08937E1E19071800197FAD /* DeviceDetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceDetailViewController.swift; sourceTree = "<group>"; };
		5F1764F61E0EBFB0003F888A /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = "BeeTee Demo/AppDelegate.swift"; sourceTree = SOURCE_ROOT; };
		5F1764F81E0EBFBA003F888A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = "BeeTee Demo/Assets.xcassets"; sourceTree = SOURCE_ROOT; };
		5F1764FB1E0EBFC2003F888A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = "BeeTee Demo/Base.lproj/LaunchScreen.storyboard"; sourceTree = SOURCE_ROOT; };
		5F1764FD1E0EBFC2003F888A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = "BeeTee Demo/Base.lproj/Main.storyboard"; sourceTree = SOURCE_ROOT; };
		5F1765001E0EBFD2003F888A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = "BeeTee Demo/Info.plist"; sourceTree = SOURCE_ROOT; };
		5F2408EE1E0C0134004AF90F /* BeeTee.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BeeTee.app; sourceTree = BUILT_PRODUCTS_DIR; };
		5F2409021E0C0134004AF90F /* BeeTeeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BeeTeeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
		5F2409061E0C0134004AF90F /* BeeTeeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BeeTeeTests.swift; sourceTree = "<group>"; };
		5F2409081E0C0134004AF90F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		5F9F632E1E0EB9300014A043 /* BeeTee-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "BeeTee-Bridging-Header.h"; path = "BeeTee/BeeTee-Bridging-Header.h"; sourceTree = "<group>"; };
		5F9F632F1E0EB9300014A043 /* BeeTee.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BeeTee.swift; path = BeeTee/BeeTee.swift; sourceTree = "<group>"; };
		5F9F63301E0EB9300014A043 /* BeeTeeDevice.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BeeTeeDevice.swift; path = BeeTee/BeeTeeDevice.swift; sourceTree = "<group>"; };
		5F9F63311E0EB9300014A043 /* BluetoothDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BluetoothDevice.h; path = BeeTee/BluetoothDevice.h; sourceTree = "<group>"; };
		5F9F63321E0EB9300014A043 /* BluetoothDeviceHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BluetoothDeviceHandler.h; path = BeeTee/BluetoothDeviceHandler.h; sourceTree = "<group>"; };
		5F9F63331E0EB9300014A043 /* BluetoothDeviceHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BluetoothDeviceHandler.m; path = BeeTee/BluetoothDeviceHandler.m; sourceTree = "<group>"; };
		5F9F63341E0EB9300014A043 /* BluetoothManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BluetoothManager.h; path = BeeTee/BluetoothManager.h; sourceTree = "<group>"; };
		5F9F63351E0EB9300014A043 /* BluetoothManagerHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BluetoothManagerHandler.h; path = BeeTee/BluetoothManagerHandler.h; sourceTree = "<group>"; };
		5F9F63361E0EB9300014A043 /* BluetoothManagerHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BluetoothManagerHandler.m; path = BeeTee/BluetoothManagerHandler.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		5F2408EB1E0C0134004AF90F /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		5F2408FF1E0C0134004AF90F /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		5F0893791E18F95B00197FAD /* View */ = {
			isa = PBXGroup;
			children = (
				5F1764F81E0EBFBA003F888A /* Assets.xcassets */,
				5F1764FA1E0EBFC2003F888A /* LaunchScreen.storyboard */,
				5F1764FC1E0EBFC2003F888A /* Main.storyboard */,
			);
			name = View;
			sourceTree = "<group>";
		};
		5F08937A1E18F96900197FAD /* Controller */ = {
			isa = PBXGroup;
			children = (
				5F0893711E17F82500197FAD /* MissionControlViewController.swift */,
				5F08937C1E19021500197FAD /* DeviceListingViewController.swift */,
				5F08937E1E19071800197FAD /* DeviceDetailViewController.swift */,
			);
			name = Controller;
			sourceTree = "<group>";
		};
		5F08937B1E18F97000197FAD /* Model */ = {
			isa = PBXGroup;
			children = (
				5F0893751E181C7B00197FAD /* BeeTeeModel.swift */,
			);
			name = Model;
			sourceTree = "<group>";
		};
		5F2408E51E0C0134004AF90F = {
			isa = PBXGroup;
			children = (
				5F9F632D1E0EB60A0014A043 /* BeeTee */,
				5F2408F01E0C0134004AF90F /* BeeTee Demo */,
				5F2409051E0C0134004AF90F /* BeeTeeTests */,
				5F2408EF1E0C0134004AF90F /* Products */,
			);
			sourceTree = "<group>";
		};
		5F2408EF1E0C0134004AF90F /* Products */ = {
			isa = PBXGroup;
			children = (
				5F2408EE1E0C0134004AF90F /* BeeTee.app */,
				5F2409021E0C0134004AF90F /* BeeTeeTests.xctest */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		5F2408F01E0C0134004AF90F /* BeeTee Demo */ = {
			isa = PBXGroup;
			children = (
				5F1765001E0EBFD2003F888A /* Info.plist */,
				5F1764F61E0EBFB0003F888A /* AppDelegate.swift */,
				5F0893791E18F95B00197FAD /* View */,
				5F08937A1E18F96900197FAD /* Controller */,
				5F08937B1E18F97000197FAD /* Model */,
			);
			name = "BeeTee Demo";
			path = BeeTee;
			sourceTree = "<group>";
		};
		5F2409051E0C0134004AF90F /* BeeTeeTests */ = {
			isa = PBXGroup;
			children = (
				5F2409061E0C0134004AF90F /* BeeTeeTests.swift */,
				5F2409081E0C0134004AF90F /* Info.plist */,
			);
			path = BeeTeeTests;
			sourceTree = "<group>";
		};
		5F9F63281E0D75EC0014A043 /* Objective-C */ = {
			isa = PBXGroup;
			children = (
				5F9F632E1E0EB9300014A043 /* BeeTee-Bridging-Header.h */,
				5F9F63321E0EB9300014A043 /* BluetoothDeviceHandler.h */,
				5F9F63331E0EB9300014A043 /* BluetoothDeviceHandler.m */,
				5F9F63351E0EB9300014A043 /* BluetoothManagerHandler.h */,
				5F9F63361E0EB9300014A043 /* BluetoothManagerHandler.m */,
				5F9F63291E0D75F70014A043 /* Private Headers */,
			);
			name = "Objective-C";
			sourceTree = "<group>";
		};
		5F9F63291E0D75F70014A043 /* Private Headers */ = {
			isa = PBXGroup;
			children = (
				5F9F63311E0EB9300014A043 /* BluetoothDevice.h */,
				5F9F63341E0EB9300014A043 /* BluetoothManager.h */,
			);
			name = "Private Headers";
			sourceTree = "<group>";
		};
		5F9F632D1E0EB60A0014A043 /* BeeTee */ = {
			isa = PBXGroup;
			children = (
				5F9F632F1E0EB9300014A043 /* BeeTee.swift */,
				5F9F63301E0EB9300014A043 /* BeeTeeDevice.swift */,
				5F9F63281E0D75EC0014A043 /* Objective-C */,
			);
			name = BeeTee;
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		5F2408ED1E0C0134004AF90F /* BeeTee */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 5F24090B1E0C0134004AF90F /* Build configuration list for PBXNativeTarget "BeeTee" */;
			buildPhases = (
				5F2408EA1E0C0134004AF90F /* Sources */,
				5F2408EB1E0C0134004AF90F /* Frameworks */,
				5F2408EC1E0C0134004AF90F /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = BeeTee;
			productName = BeeTee;
			productReference = 5F2408EE1E0C0134004AF90F /* BeeTee.app */;
			productType = "com.apple.product-type.application";
		};
		5F2409011E0C0134004AF90F /* BeeTeeTests */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 5F24090E1E0C0134004AF90F /* Build configuration list for PBXNativeTarget "BeeTeeTests" */;
			buildPhases = (
				5F2408FE1E0C0134004AF90F /* Sources */,
				5F2408FF1E0C0134004AF90F /* Frameworks */,
				5F2409001E0C0134004AF90F /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
				5F2409041E0C0134004AF90F /* PBXTargetDependency */,
			);
			name = BeeTeeTests;
			productName = BeeTeeTests;
			productReference = 5F2409021E0C0134004AF90F /* BeeTeeTests.xctest */;
			productType = "com.apple.product-type.bundle.unit-test";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		5F2408E61E0C0134004AF90F /* Project object */ = {
			isa = PBXProject;
			attributes = {
				LastSwiftUpdateCheck = 0820;
				LastUpgradeCheck = 0820;
				ORGANIZATIONNAME = "Michael Dorner";
				TargetAttributes = {
					5F2408ED1E0C0134004AF90F = {
						CreatedOnToolsVersion = 8.2.1;
						LastSwiftMigration = 0820;
						ProvisioningStyle = Manual;
					};
					5F2409011E0C0134004AF90F = {
						CreatedOnToolsVersion = 8.2.1;
						ProvisioningStyle = Automatic;
						TestTargetID = 5F2408ED1E0C0134004AF90F;
					};
				};
			};
			buildConfigurationList = 5F2408E91E0C0134004AF90F /* Build configuration list for PBXProject "BeeTee" */;
			compatibilityVersion = "Xcode 3.2";
			developmentRegion = English;
			hasScannedForEncodings = 0;
			knownRegions = (
				en,
				Base,
			);
			mainGroup = 5F2408E51E0C0134004AF90F;
			productRefGroup = 5F2408EF1E0C0134004AF90F /* Products */;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				5F2408ED1E0C0134004AF90F /* BeeTee */,
				5F2409011E0C0134004AF90F /* BeeTeeTests */,
			);
		};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
		5F2408EC1E0C0134004AF90F /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				5F1764F91E0EBFBA003F888A /* Assets.xcassets in Resources */,
				5F1764FF1E0EBFC2003F888A /* Main.storyboard in Resources */,
				5F1764FE1E0EBFC2003F888A /* LaunchScreen.storyboard in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		5F2409001E0C0134004AF90F /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		5F2408EA1E0C0134004AF90F /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				5F9F633A1E0EB9300014A043 /* BluetoothManagerHandler.m in Sources */,
				5F9F63371E0EB9300014A043 /* BeeTee.swift in Sources */,
				5F1764F71E0EBFB0003F888A /* AppDelegate.swift in Sources */,
				5F08937D1E19021500197FAD /* DeviceListingViewController.swift in Sources */,
				5F9F63381E0EB9300014A043 /* BeeTeeDevice.swift in Sources */,
				5F08937F1E19071800197FAD /* DeviceDetailViewController.swift in Sources */,
				5F0893761E181C7B00197FAD /* BeeTeeModel.swift in Sources */,
				5F9F63391E0EB9300014A043 /* BluetoothDeviceHandler.m in Sources */,
				5F0893721E17F82500197FAD /* MissionControlViewController.swift in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		5F2408FE1E0C0134004AF90F /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				5F2409071E0C0134004AF90F /* BeeTeeTests.swift in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
		5F2409041E0C0134004AF90F /* PBXTargetDependency */ = {
			isa = PBXTargetDependency;
			target = 5F2408ED1E0C0134004AF90F /* BeeTee */;
			targetProxy = 5F2409031E0C0134004AF90F /* PBXContainerItemProxy */;
		};
/* End PBXTargetDependency section */

/* Begin PBXVariantGroup section */
		5F1764FA1E0EBFC2003F888A /* LaunchScreen.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				5F1764FB1E0EBFC2003F888A /* Base */,
			);
			name = LaunchScreen.storyboard;
			sourceTree = "<group>";
		};
		5F1764FC1E0EBFC2003F888A /* Main.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				5F1764FD1E0EBFC2003F888A /* Base */,
			);
			name = Main.storyboard;
			sourceTree = "<group>";
		};
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
		5F2409091E0C0134004AF90F /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = dwarf;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				ENABLE_TESTABILITY = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 10.2;
				MTL_ENABLE_DEBUG_INFO = YES;
				ONLY_ACTIVE_ARCH = YES;
				SDKROOT = iphoneos;
				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
				SWIFT_OBJC_BRIDGING_HEADER = "";
				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Debug;
		};
		5F24090A1E0C0134004AF90F /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_NS_ASSERTIONS = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 10.2;
				MTL_ENABLE_DEBUG_INFO = NO;
				SDKROOT = iphoneos;
				SWIFT_OBJC_BRIDGING_HEADER = "";
				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
				TARGETED_DEVICE_FAMILY = "1,2";
				VALIDATE_PRODUCT = YES;
			};
			name = Release;
		};
		5F24090C1E0C0134004AF90F /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CLANG_ENABLE_MODULES = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				DEVELOPMENT_TEAM = "";
				INFOPLIST_FILE = "$(SRCROOT)/BeeTee Demo/Info.plist";
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				OTHER_LDFLAGS = (
					"-ObjC",
					"$(inherited)",
				);
				PRODUCT_BUNDLE_IDENTIFIER = de.michaeldorner.BeeTee;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_OBJC_BRIDGING_HEADER = "BeeTee/BeeTee-Bridging-Header.h";
				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
				SWIFT_VERSION = 3.0;
			};
			name = Debug;
		};
		5F24090D1E0C0134004AF90F /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CLANG_ENABLE_MODULES = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				DEVELOPMENT_TEAM = "";
				INFOPLIST_FILE = "$(SRCROOT)/BeeTee Demo/Info.plist";
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				OTHER_LDFLAGS = (
					"-ObjC",
					"$(inherited)",
				);
				PRODUCT_BUNDLE_IDENTIFIER = de.michaeldorner.BeeTee;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_OBJC_BRIDGING_HEADER = "BeeTee/BeeTee-Bridging-Header.h";
				SWIFT_VERSION = 3.0;
			};
			name = Release;
		};
		5F24090F1E0C0134004AF90F /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
				BUNDLE_LOADER = "$(TEST_HOST)";
				INFOPLIST_FILE = BeeTeeTests/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
				PRODUCT_BUNDLE_IDENTIFIER = de.michaeldorner.BeeTeeTests;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_VERSION = 3.0;
				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/BeeTee.app/BeeTee";
			};
			name = Debug;
		};
		5F2409101E0C0134004AF90F /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
				BUNDLE_LOADER = "$(TEST_HOST)";
				INFOPLIST_FILE = BeeTeeTests/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
				PRODUCT_BUNDLE_IDENTIFIER = de.michaeldorner.BeeTeeTests;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_VERSION = 3.0;
				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/BeeTee.app/BeeTee";
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		5F2408E91E0C0134004AF90F /* Build configuration list for PBXProject "BeeTee" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				5F2409091E0C0134004AF90F /* Debug */,
				5F24090A1E0C0134004AF90F /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		5F24090B1E0C0134004AF90F /* Build configuration list for PBXNativeTarget "BeeTee" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				5F24090C1E0C0134004AF90F /* Debug */,
				5F24090D1E0C0134004AF90F /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		5F24090E1E0C0134004AF90F /* Build configuration list for PBXNativeTarget "BeeTeeTests" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				5F24090F1E0C0134004AF90F /* Debug */,
				5F2409101E0C0134004AF90F /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = 5F2408E61E0C0134004AF90F /* Project object */;
}


================================================
FILE: BeeTee.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "self:BeeTee.xcodeproj">
   </FileRef>
</Workspace>


================================================
FILE: BeeTeeTests/BeeTeeTests.swift
================================================
/*
 This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at https://github.com/michaeldorner/BeeTee/blob/master/LICENSE. No part of BeeTee Project, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file.
 */

import XCTest
@testable import BeeTee

class BeeTeeTests: XCTestCase {
    
    override func setUp() {
        super.setUp()
        let beeTee = BeeTee()
        for device in beeTee.availableDevices {
            print(device)
        }
    }
    
    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }
    
    func testExample() {
        // This is an example of a functional test case.
        // Use XCTAssert and related functions to verify your tests produce the correct results.
    }
    
    func testPerformanceExample() {
        // This is an example of a performance test case.
        self.measure {
            // Put the code you want to measure the time of here.
        }
    }
    
}


================================================
FILE: BeeTeeTests/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>BNDL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleVersion</key>
	<string>1</string>
</dict>
</plist>


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2016 Michael Dorner

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

================================================
FILE: README.md
================================================
[![Build Status](https://travis-ci.org/michaeldorner/BeeTee.svg?branch=master)](https://travis-ci.org/michaeldorner/BeeTee)
[![codebeat badge](https://codebeat.co/badges/65bf4b44-cbbc-4807-a9e9-b3cd68c4378d)](https://codebeat.co/projects/github-com-michaeldorner-beetee)
[![codecov](https://codecov.io/gh/michaeldorner/BeeTee/branch/master/graph/badge.svg)](https://codecov.io/gh/michaeldorner/BeeTee)
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)


# BeeTee

> BeeTee is an easy to use Swift framework, that allows simple access to the Bluetooth classic in iOS for turning on/off and scanning for Bluetooth devices. 

Besides BeeTee demonstrates how to access the private `BluetoothManager.framework` in iOS. 


## Table of Contents

- [Limitations](#limitations)
- [Installation](#installation)
- [Usage](#usage)
- [API](#api)
- [Known Issues](#known-issues)
- [Contributions](#contributions)
- [Versions](#versions)
- [License](#license)


## Limitations

Based on the [AppStore guideline §2.5](https://developer.apple.com/appstore/resources/approval/guidelines.html) on private (undocumented) functions it is not possible to publish apps with the _BeeTee_ and `BluetoothManager.framework` in the AppStore. 

You need a valid membership of the [iOS Developer Program](https://developer.apple.com/programs/ios/), because the _BeeTee_ does not work in the iOS simulator.

Connecting to devices is not possible in most cases and, therefore, not yet supported. 

There are currently no known limitations on iOS versions. 


## Installation

Copy all files in the _BeeTee_ folder to your project and done. That means there are 9 files to copy:

* `BluetoothDevice.h`
* `BluetoothManager.h`
* `BluetoothDeviceHandler.h`
* `BluetoothDeviceHandler.m`
* `BluetoothManagerHandler.h`
* `BluetoothManagerHandler.m`
* `BeeTee-Bridge-Header.h`
* `BeeTee.swift`
* `BeeTeeDevice.swift`


## Usage

Here is a small code snippet, how easily you can use _BeeTee_:

	class Demo: BeeTeeDelegate {
	    let beeTee = BeeTee()
	    
	   init() {
	        beeTee.delegate = self
	        beeTee.enableBluetooth()
	        beeTee.startScanForDevices()
	    }
	    
	    func receivedBeeTeeNotification(notification: BeeTeeNotification) {
	        switch notification {
	        case .DeviceDiscovered:
	            for device in beeTee.availableDevices {
	                print(device)
	            }
	        default:
	            print(notification)
	        }
	    }
	}


## API

### BeeTee

The API is based on the other hardware managers, such as [`CLLocationManager`](https://developer.apple.com/reference/corelocation/cllocationmanager) or the underlaying `BluetoothManager.framework`. 

I focused on a clear distinction between the different layers, also by using different programming languages:

![Layer architecture of BeeTee](landingPage/BeeTeeLayer.png)

#### `BeeTeeNotification`

	public enum BeeTeeNotification {
	    case PowerChanged
	    case AvailabilityChanged
	    case DeviceDiscovered
	    case DeviceRemoved
	    case ConnectabilityChanged
	    case DeviceUpdated
	    case DiscoveryStateChanged
	    case DeviceConnectSuccess
	    case ConnectionStatusChanged
	    case DeviceDisconnectSuccess
	    
	    static let allNotifications: [BeeTeeNotification]
	}

So all known notification from `BluetoothManager.framework` are passed through (see next section). I used only `PowerChanged`, `DeviceDiscovered`, `DeviceRemoved` in my demo application.

#### `BeeTeeDelegate`

	public protocol BeeTeeDelegate {
	    func receivedBeeTeeNotification(notification: BeeTeeNotification)
	}

#### `BeeTee`

	public class BeeTee {
		public var delegate: BeeTeeDelegate?
		public var availableDevices: [BeeTeeDevice]
		convenience init(delegate: BeeTeeDelegate)
		public func enableBluetooth()
		public func disableBluetooth()
		public func bluetoothIsEnabled() -> Bool
		public func startScanForDevices()
		public func stopScan()
		public func isScanning() -> Bool
		public static func debugLowLevel() // see section BluetoothManager.framework/Available Notification
	}


### `BluetoothManager.framework`

If you want to dive deeper into `BluetoothManager.framework` this section is interesting for you. 

#### Available Notifications

I found the following notification regarding Bluetooth

    BluetoothAvailabilityChangedNotification
    BluetoothDiscoveryStateChangedNotification
    BluetoothDeviceDiscoveredNotification
    BluetoothDeviceRemovedNotification
    BluetoothPowerChangedNotification
    BluetoothConnectabilityChangedNotification
    BluetoothDeviceUpdatedNotification
    BluetoothDeviceConnectSuccessNotification
    BluetoothConnectionStatusChangedNotification
    BluetoothDeviceDisconnectSuccessNotification
    
Maybe the list is not complete. You can look for them yourself using

	CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
	        nil,
	        { (_, observer, name, _, _) in
	            let n = name?.rawValue as! String
	            if n.hasPrefix("B") { // notice only notification they are associated with the BluetoothManager.framework
	                print("Received notification: \(name)")
	            }
	        },
	        nil,
	        nil,
	        .deliverImmediately)
or with in `BeeTee`:

	BeeTee.debugLowLevel()


## Known Issues

* Actually I wanted to encapsulate BeeTee in a formal framework. But it seems that [Swift does not allow framework-internal (protected) Objective-C code](http://stackoverflow.com/questions/41303716/objective-c-code-swift-framework-internal). 

* Some notifications are sent multiple times ([issue](https://github.com/michaeldorner/BeeTee/issues/13)). I am not sure how to deal with it. 

If you have problems make this project running have a look at [Stackoverflow](http://stackoverflow.com/search?q=beetee). If you have other questions or suggestions, feel free to contact me here in GitHub or somehow else. :-)


## Contributions

Help is welcome! If you do not know what to do, just pick one item and send me a pull request.

- [ ] Fix issue with multiple notifications
- [ ] Restructure BeeTee in a framework (`BeeTee.framework`, see [discussion on stackoverflow](http://stackoverflow.com/questions/41303716/objective-c-code-swift-framework-internal))
- [ ] Write test cases
- [ ] Support Cocoapods
- [ ] Improve documentation, especially inline documentation
- [ ] Provide app icons
- [x] Support Travis support


## Versions

### 3.0
* Rewritten in Swift 3
* New API
* Clear separation of Objective-C and Swift code
* Dynamically loading of `Bluetooth.framework` (so no more header and import trouble)
* Released now under MIT license 

### 2.0
* Wrapper classes `MDBluetoothManager` and `MDBluetoothDevice` introduced 
* Updated to ARC
* Extented GUI

### 1.0
* Initial Commit as demo project for `BluetoothManager.framework`, Non-ARC


## License 

BeeTee is released under the MIT license. See [LICENSE](LICENSE) for more details.
The list icon was created by Aya Sofya (thenounproject.com).


================================================
FILE: landingPage/BeeTeeLayer.graphml
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
  <!--Created by yEd 3.16-->
  <key attr.name="Beschreibung" attr.type="string" for="graph" id="d0"/>
  <key for="port" id="d1" yfiles.type="portgraphics"/>
  <key for="port" id="d2" yfiles.type="portgeometry"/>
  <key for="port" id="d3" yfiles.type="portuserdata"/>
  <key attr.name="url" attr.type="string" for="node" id="d4"/>
  <key attr.name="description" attr.type="string" for="node" id="d5"/>
  <key for="node" id="d6" yfiles.type="nodegraphics"/>
  <key for="graphml" id="d7" yfiles.type="resources"/>
  <key attr.name="url" attr.type="string" for="edge" id="d8"/>
  <key attr.name="description" attr.type="string" for="edge" id="d9"/>
  <key for="edge" id="d10" yfiles.type="edgegraphics"/>
  <graph edgedefault="directed" id="G">
    <data key="d0"/>
    <node id="n0">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="177.0" x="487.0" y="255.0"/>
          <y:Fill color="#CCFFCC" transparent="false"/>
          <y:BorderStyle hasColor="false" raised="false" type="dotted" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="76.76171875" x="50.119140625" y="5.93359375">BeeTee.swift<y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="rectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n1">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="177.0" x="487.0" y="315.0"/>
          <y:Fill color="#FFCC99" transparent="false"/>
          <y:BorderStyle hasColor="false" raised="false" type="dotted" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="121.029296875" x="27.9853515625" y="5.93359375">BluetoothManager.h<y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="rectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n2">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="177.0" x="664.0" y="315.0"/>
          <y:Fill color="#FFCC99" transparent="false"/>
          <y:BorderStyle hasColor="false" raised="false" type="dotted" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="109.099609375" x="33.9501953125" y="5.93359375">BluetoothDevice.h<y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="rectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n3">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="177.0" x="487.0" y="285.0"/>
          <y:Fill color="#FFFF99" transparent="false"/>
          <y:BorderStyle hasColor="false" raised="false" type="dotted" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="166.5390625" x="5.23046875" y="5.93359375">BluetoothManagerHandler.h<y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="rectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n4">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="177.0" x="664.0" y="285.0"/>
          <y:Fill color="#FFFF99" transparent="false"/>
          <y:BorderStyle hasColor="false" raised="false" type="dotted" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="154.609375" x="11.1953125" y="5.93359375">BluetoothDeviceHandler.h<y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="rectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n5">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="177.0" x="664.0" y="255.0"/>
          <y:Fill color="#CCFFCC" transparent="false"/>
          <y:BorderStyle hasColor="false" raised="false" type="dotted" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="114.947265625" x="31.0263671875" y="5.93359375">BeeTeeDevice.swift<y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="rectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n6">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="70.0" x="851.0" y="255.0"/>
          <y:Fill color="#CCFFCC" transparent="false"/>
          <y:BorderStyle hasColor="false" raised="false" type="dotted" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="39.63671875" x="15.181640625" y="5.93359375">public<y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="rectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n7">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="70.0" x="851.0" y="285.0"/>
          <y:Fill color="#FFFF99" transparent="false"/>
          <y:BorderStyle hasColor="false" raised="false" type="dotted" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="59.880859375" x="5.0595703125" y="5.93359375">protected<y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="rectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n8">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="70.0" x="851.0" y="315.0"/>
          <y:Fill color="#FFCC99" transparent="false"/>
          <y:BorderStyle hasColor="false" raised="false" type="dotted" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="43.943359375" x="13.0283203125" y="5.93359375">private<y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="rectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n9">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="177.0" x="931.0" y="255.0"/>
          <y:Fill color="#CCFFCC" transparent="false"/>
          <y:BorderStyle hasColor="false" raised="false" type="dotted" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="151.087890625" x="12.9560546875" y="5.93359375">BeeTee framework (Swift)<y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="rectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n10">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="177.0" x="931.0" y="285.0"/>
          <y:Fill color="#FFFF99" transparent="false"/>
          <y:BorderStyle hasColor="false" raised="false" type="dotted" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="124.73828125" x="26.130859375" y="5.93359375">Objective-C wrapper<y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="rectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n11">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="177.0" x="931.0" y="315.0"/>
          <y:Fill color="#FFCC99" transparent="false"/>
          <y:BorderStyle hasColor="false" raised="false" type="dotted" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="175.9609375" x="0.51953125" y="5.93359375">BluetoothManager.framework<y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="rectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n12">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="177.0" x="931.0" y="213.0"/>
          <y:Fill hasColor="false" transparent="false"/>
          <y:BorderStyle hasColor="false" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="75.337890625" x="50.8310546875" y="4.0">Description<y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="-0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="4.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="rectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n13">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="70.0" x="851.0" y="213.0"/>
          <y:Fill hasColor="false" transparent="false"/>
          <y:BorderStyle hasColor="false" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="32.265625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="82.228515625" x="-6.1142578125" y="-1.1328125">Framework
Access Level<y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="rectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n14">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="354.0" x="487.0" y="213.0"/>
          <y:Fill hasColor="false" transparent="false"/>
          <y:BorderStyle hasColor="false" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="101.27734375" x="126.361328125" y="5.93359375">Implementation<y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="rectangle"/>
        </y:ShapeNode>
      </data>
    </node>
  </graph>
  <data key="d7">
    <y:Resources/>
  </data>
</graphml>
Download .txt
gitextract_giyuhi4h/

├── .gitignore
├── .travis.yml
├── BeeTee/
│   ├── BeeTee-Bridging-Header.h
│   ├── BeeTee.swift
│   ├── BeeTeeDevice.swift
│   ├── BeeTeeModel.swift
│   ├── BluetoothDevice.h
│   ├── BluetoothDeviceHandler.h
│   ├── BluetoothDeviceHandler.m
│   ├── BluetoothManager.h
│   ├── BluetoothManagerHandler.h
│   ├── BluetoothManagerHandler.m
│   ├── DeviceDetailViewController.swift
│   └── DeviceListingViewController.swift
├── BeeTee Demo/
│   ├── AppDelegate.swift
│   ├── Assets.xcassets/
│   │   ├── AppIcon.appiconset/
│   │   │   └── Contents.json
│   │   ├── Contents.json
│   │   ├── DeviceListing.imageset/
│   │   │   └── Contents.json
│   │   └── MissionControl.imageset/
│   │       └── Contents.json
│   ├── Base.lproj/
│   │   ├── LaunchScreen.storyboard
│   │   └── Main.storyboard
│   ├── Info.plist
│   └── MissionControlViewController.swift
├── BeeTee.xcodeproj/
│   ├── project.pbxproj
│   └── project.xcworkspace/
│       └── contents.xcworkspacedata
├── BeeTeeTests/
│   ├── BeeTeeTests.swift
│   └── Info.plist
├── LICENSE
├── README.md
└── landingPage/
    └── BeeTeeLayer.graphml
Download .txt
SYMBOL INDEX (9 symbols across 2 files)

FILE: BeeTee/BluetoothDevice.h
  function interface (line 9) | interface BluetoothDevice : NSObject {
  type _NSZone (line 27) | struct _NSZone { }
  type BTDeviceImpl (line 30) | struct BTDeviceImpl
  type BTDeviceImpl (line 36) | struct BTDeviceImpl { }
  type BTDeviceImpl (line 49) | struct BTDeviceImpl { }

FILE: BeeTee/BluetoothManager.h
  function interface (line 9) | interface BluetoothManager : NSObject {
  type BTAccessoryManagerImpl (line 30) | struct BTAccessoryManagerImpl
  type BTSessionImpl (line 45) | struct BTSessionImpl { }
  type BTDeviceImpl (line 47) | struct BTDeviceImpl { }
Condensed preview — 30 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (115K chars).
[
  {
    "path": ".gitignore",
    "chars": 237,
    "preview": "# Xcode\n.DS_Store\n*/build/*\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspecti"
  },
  {
    "path": ".travis.yml",
    "chars": 213,
    "preview": "branches:\n  only:\n  - master\n\nlanguage: objective-c\nosx_image: xcode10\n\nscript:\n- xcodebuild -project BeeTee.xcodeproj -"
  },
  {
    "path": "BeeTee/BeeTee-Bridging-Header.h",
    "chars": 455,
    "preview": "/*\n This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level d"
  },
  {
    "path": "BeeTee/BeeTee.swift",
    "chars": 5590,
    "preview": "/*\n This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level d"
  },
  {
    "path": "BeeTee/BeeTeeDevice.swift",
    "chars": 1771,
    "preview": "/*\n This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level d"
  },
  {
    "path": "BeeTee/BeeTeeModel.swift",
    "chars": 1937,
    "preview": "/*\n This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level d"
  },
  {
    "path": "BeeTee/BluetoothDevice.h",
    "chars": 2238,
    "preview": "/*\n This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level d"
  },
  {
    "path": "BeeTee/BluetoothDeviceHandler.h",
    "chars": 905,
    "preview": "/*\n This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level d"
  },
  {
    "path": "BeeTee/BluetoothDeviceHandler.m",
    "chars": 1428,
    "preview": "/*\n This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level d"
  },
  {
    "path": "BeeTee/BluetoothManager.h",
    "chars": 3432,
    "preview": "/*\n This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level d"
  },
  {
    "path": "BeeTee/BluetoothManagerHandler.h",
    "chars": 688,
    "preview": "/*\n This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level d"
  },
  {
    "path": "BeeTee/BluetoothManagerHandler.m",
    "chars": 1769,
    "preview": "/*\n This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level d"
  },
  {
    "path": "BeeTee/DeviceDetailViewController.swift",
    "chars": 2540,
    "preview": "/*\n This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level d"
  },
  {
    "path": "BeeTee/DeviceListingViewController.swift",
    "chars": 1857,
    "preview": "/*\n This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level d"
  },
  {
    "path": "BeeTee Demo/AppDelegate.swift",
    "chars": 2433,
    "preview": "/*\n This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level d"
  },
  {
    "path": "BeeTee Demo/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 1495,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\""
  },
  {
    "path": "BeeTee Demo/Assets.xcassets/Contents.json",
    "chars": 62,
    "preview": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "BeeTee Demo/Assets.xcassets/DeviceListing.imageset/Contents.json",
    "chars": 385,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"noun_18353-2.png\",\n      \"scale\" : \"1x\"\n    },\n "
  },
  {
    "path": "BeeTee Demo/Assets.xcassets/MissionControl.imageset/Contents.json",
    "chars": 397,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"noun_655374_cc-2.png\",\n      \"scale\" : \"1x\"\n    "
  },
  {
    "path": "BeeTee Demo/Base.lproj/LaunchScreen.storyboard",
    "chars": 1740,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "BeeTee Demo/Base.lproj/Main.storyboard",
    "chars": 20506,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3"
  },
  {
    "path": "BeeTee Demo/Info.plist",
    "chars": 1356,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "BeeTee Demo/MissionControlViewController.swift",
    "chars": 1612,
    "preview": "/*\n This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level d"
  },
  {
    "path": "BeeTee.xcodeproj/project.pbxproj",
    "chars": 22935,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "BeeTee.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 151,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:BeeTee.xcodepro"
  },
  {
    "path": "BeeTeeTests/BeeTeeTests.swift",
    "chars": 1210,
    "preview": "/*\n This file is part of BeeTee Project. It is subject to the license terms in the LICENSE file found in the top-level d"
  },
  {
    "path": "BeeTeeTests/Info.plist",
    "chars": 680,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "LICENSE",
    "chars": 1080,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2016 Michael Dorner\n\nPermission is hereby granted, free of charge, to any person ob"
  },
  {
    "path": "README.md",
    "chars": 7037,
    "preview": "[![Build Status](https://travis-ci.org/michaeldorner/BeeTee.svg?branch=master)](https://travis-ci.org/michaeldorner/BeeT"
  },
  {
    "path": "landingPage/BeeTeeLayer.graphml",
    "chars": 17944,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:java"
  }
]

About this extraction

This page contains the full source code of the michaeldorner/BeeTee GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 30 files (103.6 KB), approximately 29.5k tokens, and a symbol index with 9 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!