Puppet: updated help
Manual Scanner: fix table layout warnings while in background Simulated target: handle disconnections
|
|
@ -28,6 +28,8 @@
|
|||
<string>This app needs access to Bluetooth to connect to Circuit Playground Bluefruit devices</string>
|
||||
<key>NSBluetoothPeripheralUsageDescription</key>
|
||||
<string>This app needs access to Bluetooth to connect to Circuit Playground Bluefruit devices</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Puppet module requires access to the camera</string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
|
|
|
|||
|
|
@ -1347,7 +1347,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 12;
|
||||
CURRENT_PROJECT_VERSION = 13;
|
||||
DEVELOPMENT_TEAM = 2X94RM7457;
|
||||
INFOPLIST_FILE = BluefruitPlayground/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
|
|
@ -1372,7 +1372,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 12;
|
||||
CURRENT_PROJECT_VERSION = 13;
|
||||
DEVELOPMENT_TEAM = 2X94RM7457;
|
||||
INFOPLIST_FILE = BluefruitPlayground/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
|
|
@ -1436,7 +1436,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 12;
|
||||
CURRENT_PROJECT_VERSION = 13;
|
||||
DEVELOPMENT_TEAM = 2X94RM7457;
|
||||
INFOPLIST_FILE = "BluefruitPlayground-SimulatedBluetooth-Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
|
|
@ -1446,7 +1446,7 @@
|
|||
);
|
||||
MARKETING_VERSION = 1.2.0;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -D SIMULATEBLUETOOTH";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.adafruit.BluefruitPlayground;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.adafruit.BluefruitPlayground.simulated;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "BluefruitPlayground/BluefruitPlayground-SimulateBluetooth-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
|
|
@ -1462,7 +1462,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 12;
|
||||
CURRENT_PROJECT_VERSION = 13;
|
||||
DEVELOPMENT_TEAM = 2X94RM7457;
|
||||
INFOPLIST_FILE = "BluefruitPlayground-SimulatedBluetooth-Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
|
|
@ -1472,7 +1472,7 @@
|
|||
);
|
||||
MARKETING_VERSION = 1.2.0;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -D SIMULATEBLUETOOTH";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.adafruit.BluefruitPlayground;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.adafruit.BluefruitPlayground.simulated;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "BluefruitPlayground/BluefruitPlayground-SimulateBluetooth-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class BleManager: NSObject {
|
|||
internal var scanningStartTime: TimeInterval? // Time when the scanning started. nil if stopped
|
||||
private var scanningServicesFilter: [CBUUID]?
|
||||
internal var peripheralsFound = [UUID: BlePeripheral]()
|
||||
private var peripheralsFoundLock = NSLock()
|
||||
internal var peripheralsFoundLock = NSLock()
|
||||
|
||||
// Connecting
|
||||
private var connectionTimeoutTimers = [UUID: MSWeakTimer]()
|
||||
|
|
@ -353,6 +353,10 @@ extension BleManager: CBCentralManagerDelegate {
|
|||
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
|
||||
DLog("didFailToConnect")
|
||||
|
||||
// Clean
|
||||
peripheralsFound[peripheral.identifier]?.reset()
|
||||
|
||||
// Notify
|
||||
NotificationCenter.default.post(name: .didDisconnectFromPeripheral, object: nil, userInfo: [NotificationUserInfoKey.uuid.rawValue: peripheral.identifier])
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -337,7 +337,7 @@ class BlePeripheral: NSObject {
|
|||
}
|
||||
|
||||
// MARK: - Command Queue
|
||||
private class BleCommand: Equatable {
|
||||
internal class BleCommand: Equatable {
|
||||
enum CommandType {
|
||||
case discoverService
|
||||
case discoverCharacteristic
|
||||
|
|
@ -404,7 +404,7 @@ class BlePeripheral: NSObject {
|
|||
return "\(descriptor.characteristic.service.uuid.uuidString)-\(descriptor.characteristic.uuid.uuidString)-\(descriptor.uuid.uuidString)"
|
||||
}
|
||||
|
||||
private func finishedExecutingCommand(error: Error?) {
|
||||
internal func finishedExecutingCommand(error: Error?) {
|
||||
//DLog("finishedExecutingCommand")
|
||||
|
||||
// Result Callback
|
||||
|
|
@ -523,7 +523,7 @@ class BlePeripheral: NSObject {
|
|||
peripheral.readValue(for: descriptor)
|
||||
}
|
||||
|
||||
private func disconnect(with command: BleCommand) {
|
||||
internal func disconnect(with command: BleCommand) {
|
||||
let centralManager = command.parameters!.first as! CBCentralManager
|
||||
centralManager.cancelPeripheralConnection(self.peripheral)
|
||||
finishedExecutingCommand(error: nil)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ class BleManagerSimulated: BleManager {
|
|||
|
||||
}
|
||||
|
||||
// MARK: - Scanning
|
||||
override func startScan(withServices services: [CBUUID]? = nil) {
|
||||
scanningStartTime = CACurrentMediaTime()
|
||||
|
||||
|
|
@ -31,8 +32,12 @@ class BleManagerSimulated: BleManager {
|
|||
override func stopScan() {
|
||||
}
|
||||
|
||||
// MARK: - Connect
|
||||
override func connect(to peripheral: BlePeripheral, timeout: TimeInterval? = nil, shouldNotifyOnConnection: Bool = false, shouldNotifyOnDisconnection: Bool = false, shouldNotifyOnNotification: Bool = false) {
|
||||
|
||||
guard let blePeripheral = peripheral as? BlePeripheralSimulated else { return }
|
||||
blePeripheral.simulateConnect()
|
||||
|
||||
// Send notification
|
||||
NotificationCenter.default.post(name: .didConnectToPeripheral, object: nil, userInfo: [NotificationUserInfoKey.uuid.rawValue: peripheral.identifier])
|
||||
}
|
||||
|
|
@ -40,4 +45,34 @@ class BleManagerSimulated: BleManager {
|
|||
override func reconnecToPeripherals(withIdentifiers identifiers: [UUID], withServices services: [CBUUID], timeout: Double? = nil) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// MARK: - Disconnect
|
||||
override func disconnect(from peripheral: BlePeripheral, waitForQueuedCommands: Bool = false) {
|
||||
guard let blePeripheral = peripheral as? BlePeripheralSimulated else { return }
|
||||
|
||||
DLog("disconnect")
|
||||
NotificationCenter.default.post(name: .willDisconnectFromPeripheral, object: nil, userInfo: [NotificationUserInfoKey.uuid.rawValue: peripheral.identifier])
|
||||
|
||||
if waitForQueuedCommands {
|
||||
// Send the disconnection to the command queue, so all the previous command are executed before disconnecting
|
||||
if let centralManager = centralManager {
|
||||
blePeripheral.disconnect(centralManager: centralManager)
|
||||
}
|
||||
}
|
||||
else {
|
||||
didDisconnectPeripheral(blePeripheral: blePeripheral)
|
||||
}
|
||||
}
|
||||
|
||||
func didDisconnectPeripheral(blePeripheral: BlePeripheralSimulated) {
|
||||
DLog("didDisconnectPeripheral")
|
||||
|
||||
// Clean
|
||||
peripheralsFound[blePeripheral.identifier]?.reset()
|
||||
|
||||
// Notify
|
||||
NotificationCenter.default.post(name: .didDisconnectFromPeripheral, object: nil, userInfo: [NotificationUserInfoKey.uuid.rawValue: blePeripheral.identifier])
|
||||
|
||||
// Don't remove the peripheral from the peripheral list (so we can select again the simulated peripheral)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,20 +10,19 @@ import Foundation
|
|||
import CoreBluetooth
|
||||
|
||||
class BlePeripheralSimulated: BlePeripheral {
|
||||
// Constants
|
||||
private static let kSimulatedUUID = UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")!
|
||||
|
||||
// Data
|
||||
private var simulatedIdentifier = UUID()
|
||||
override var identifier: UUID {
|
||||
return BlePeripheralSimulated.kSimulatedUUID
|
||||
return simulatedIdentifier
|
||||
}
|
||||
|
||||
override var name: String? {
|
||||
return "Simulated Peripheral"
|
||||
}
|
||||
|
||||
private var simulatedState: CBPeripheralState = .disconnected
|
||||
override var state: CBPeripheralState {
|
||||
return .connected
|
||||
return simulatedState
|
||||
}
|
||||
|
||||
// MARK: - Lifecycle
|
||||
|
|
@ -46,5 +45,20 @@ class BlePeripheralSimulated: BlePeripheral {
|
|||
override func discover(serviceUuids: [CBUUID]?, completion: ((Error?) -> Void)?) {
|
||||
completion?(nil)
|
||||
}
|
||||
|
||||
// MARK: - Connect
|
||||
func simulateConnect() {
|
||||
simulatedState = .connected
|
||||
}
|
||||
|
||||
// MARK: - Disconnect
|
||||
override internal func disconnect(with command: BleCommand) {
|
||||
// Simulate disconnection
|
||||
simulatedState = .disconnected
|
||||
BleManagerSimulated.simulated.didDisconnectPeripheral(blePeripheral: self)
|
||||
|
||||
// Finished
|
||||
finishedExecutingCommand(error: nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 128 KiB |
|
|
@ -12,6 +12,7 @@
|
|||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "scanproblems_powerup@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 124 KiB |
|
|
@ -205,14 +205,13 @@ Download it from the Bluefruit Playground guide at learn.adafruit.com";
|
|||
|
||||
// Puppet
|
||||
"puppet_title" = "Puppets";
|
||||
"puppet_help_header" = "This Puppet module allows you to animate a 3D puppets in real time using the Circuit Playground Bluefruit board.
|
||||
"puppet_help_header" = "The Puppets module allows you to animate a 3D puppet in real time using Circuit Playground Bluefruit.
|
||||
|
||||
To control the puppet, attach Circuit Playground Bluefruit to the back of your fingers using a rubber band as seen below:";
|
||||
"puppet_help_details" = "• Tilt your board forward or backwards to open and close the mouth of the puppet(Sparky The Blue Smoke Monster).
|
||||
• Try turning your board to turn your puppet’s head left and right.
|
||||
• Press the A or B button on the board to trigger present animations.
|
||||
|
||||
You can also screen record and share your interaction with the puppet.";
|
||||
To control Sparky the Blue Smoke Monster, attach Circuit Playground Bluefruit to the back of your fingers using a rubber band as seen below:";
|
||||
"puppet_help_details" = "• Tilt your board forward or backwards to open and close the mouth of the puppet.
|
||||
• Try tilting your board to tilt the puppet’s head left or right.
|
||||
• Press the A or B button on Circuit Playground Bluefruit to trigger preset animations.
|
||||
• Use the buttons at the bottom to record the screen, change background, camera, & fullscreen mode. ";
|
||||
|
||||
|
||||
"puppet_recording_error_title" = "Recording Error";
|
||||
|
|
|
|||
|
|
@ -43,7 +43,32 @@ class HelpViewController: UIViewController {
|
|||
loadViewIfNeeded()
|
||||
|
||||
let imageView = UIImageView(image: image)
|
||||
contentStackView.addArrangedSubview(imageView)
|
||||
imageView.tintColor = UIColor(named: "text_default")
|
||||
imageView.contentMode = .scaleAspectFit
|
||||
imageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
imageView.setContentHuggingPriority(UILayoutPriority(rawValue: 1000), for: .vertical)
|
||||
|
||||
// Add imageView inside container to adjust proportions
|
||||
let containerView = UIView()
|
||||
containerView.backgroundColor = .clear
|
||||
containerView.addSubview(imageView)
|
||||
|
||||
imageView.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true
|
||||
imageView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true
|
||||
|
||||
imageView.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).isActive = true
|
||||
//imageView.leadingAnchor.constraint(greaterThanOrEqualTo: containerView.leadingAnchor).isActive = true
|
||||
//imageView.trailingAnchor.constraint(greaterThanOrEqualTo: containerView.trailingAnchor).isActive = true
|
||||
|
||||
let proportionalWidthConstraint = imageView.widthAnchor.constraint(equalTo: containerView.widthAnchor, multiplier: 0.75)
|
||||
proportionalWidthConstraint.priority = UILayoutPriority(rawValue: 999)
|
||||
proportionalWidthConstraint.isActive = true
|
||||
imageView.widthAnchor.constraint(lessThanOrEqualToConstant: 350).isActive = true // Limit image to 350 width
|
||||
|
||||
imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor, multiplier: image.size.height / image.size.width).isActive = true
|
||||
|
||||
|
||||
contentStackView.addArrangedSubview(containerView)
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
|
|
|||
|
|
@ -62,8 +62,6 @@ class ScannerViewController: UIViewController {
|
|||
// Hide automatic scanning if needed
|
||||
scanAutomaticallyButton.isHidden = !Config.isAutomaticConnectionEnabled
|
||||
|
||||
// Ble Notifications
|
||||
registerNotifications(enabled: true)
|
||||
|
||||
// Localization
|
||||
let localizationManager = LocalizationManager.shared
|
||||
|
|
@ -83,6 +81,14 @@ class ScannerViewController: UIViewController {
|
|||
customNavigationBar.setRightButton(topViewController: self, image: UIImage(named: "info"), target: self, action: #selector(about(_:)))
|
||||
}
|
||||
|
||||
// Ble Notifications
|
||||
registerNotifications(enabled: true)
|
||||
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
// Disconnect if needed
|
||||
let connectedPeripherals = bleManager.connectedPeripherals()
|
||||
if connectedPeripherals.count == 1, let peripheral = connectedPeripherals.first {
|
||||
|
|
@ -90,10 +96,6 @@ class ScannerViewController: UIViewController {
|
|||
// Disconnect from peripheral
|
||||
disconnect(peripheral: peripheral)
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
// Update UI
|
||||
updateScannedPeripherals()
|
||||
|
|
@ -111,6 +113,9 @@ class ScannerViewController: UIViewController {
|
|||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
|
||||
// Ble Notifications
|
||||
registerNotifications(enabled: false)
|
||||
|
||||
// Stop scanning
|
||||
bleManager.stopScan()
|
||||
|
||||
|
|
@ -118,11 +123,6 @@ class ScannerViewController: UIViewController {
|
|||
peripheralList.clear()
|
||||
}
|
||||
|
||||
deinit {
|
||||
// Ble Notifications
|
||||
registerNotifications(enabled: false)
|
||||
}
|
||||
|
||||
// MARK: - BLE Notifications
|
||||
private weak var didDiscoverPeripheralObserver: NSObjectProtocol?
|
||||
private weak var willConnectToPeripheralObserver: NSObjectProtocol?
|
||||
|
|
|
|||