Skip to content

Commit

Permalink
Merge pull request #7 from bricklife/release/1.5.0
Browse files Browse the repository at this point in the history
Release/1.5.0
  • Loading branch information
Shinichiro Oba authored Apr 26, 2018
2 parents ab72cd4 + 56abcb6 commit 8ff17d7
Show file tree
Hide file tree
Showing 67 changed files with 1,245 additions and 471 deletions.
84 changes: 45 additions & 39 deletions BoostRemote.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?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>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
9 changes: 8 additions & 1 deletion BoostRemote/Action.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import Foundation
import ReSwift
import BoostBLEKit

enum ConnectAction: Action {

Expand All @@ -20,7 +21,13 @@ enum ConnectAction: Action {

struct NotificationAction: Action {

let notification: Notification
let notification: BoostBLEKit.Notification
}

enum SettingsAction: Action {

case step(SettingsState.Step)
case mode(SettingsState.Mode)
}

struct ActionCenter {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@
"images" : [
{
"idiom" : "universal",
"filename" : "left.pdf",
"filename" : "base.pdf",
"resizing" : {
"mode" : "3-part-horizontal",
"mode" : "9-part",
"center" : {
"mode" : "tile",
"width" : 1
"width" : 1,
"height" : 1
},
"cap-insets" : {
"right" : 32,
"left" : 31
"bottom" : 15,
"top" : 15,
"right" : 15,
"left" : 15
}
}
}
Expand Down
Binary file not shown.
12 changes: 12 additions & 0 deletions BoostRemote/Assets.xcassets/portAB.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "portAB.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.
23 changes: 0 additions & 23 deletions BoostRemote/Assets.xcassets/right.imageset/Contents.json

This file was deleted.

12 changes: 12 additions & 0 deletions BoostRemote/Assets.xcassets/settings.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "settings.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.
16 changes: 15 additions & 1 deletion BoostRemote/Assets.xcassets/thumb.imageset/Contents.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,21 @@
"images" : [
{
"idiom" : "universal",
"filename" : "thumb.pdf"
"filename" : "thumb.pdf",
"resizing" : {
"mode" : "9-part",
"center" : {
"mode" : "tile",
"width" : 1,
"height" : 1
},
"cap-insets" : {
"bottom" : 15,
"top" : 15,
"right" : 15,
"left" : 15
}
}
}
],
"info" : {
Expand Down
10 changes: 7 additions & 3 deletions BoostRemote/Base.lproj/LaunchScreen.storyboard
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
<?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">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
Expand Down
493 changes: 398 additions & 95 deletions BoostRemote/Base.lproj/Main.storyboard

Large diffs are not rendered by default.

29 changes: 0 additions & 29 deletions BoostRemote/Command.swift

This file was deleted.

19 changes: 19 additions & 0 deletions BoostRemote/Controller.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// Controller.swift
// BoostRemote
//
// Created by Shinichiro Oba on 2018/01/26.
// Copyright © 2018 bricklife.com. All rights reserved.
//

import Foundation
import ReactiveSwift
import Result
import BoostBLEKit

protocol Controller {

var signals: [BoostBLEKit.Port: Signal<Double, NoError>] { get }

func setEnable(_ enable: Bool, port: BoostBLEKit.Port)
}
101 changes: 39 additions & 62 deletions BoostRemote/ControllerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,54 +7,37 @@
//

import UIKit
import ReactiveCocoa
import ReactiveSwift
import Result
import ReSwift
import BoostBLEKit

class ControllerViewController: UIViewController {

@IBOutlet private weak var stickA: StickView!
@IBOutlet private weak var stickB: StickView!
@IBOutlet private weak var stickC: StickView!
@IBOutlet private weak var stickD: StickView!

@IBOutlet private weak var connectButtonImageView: UIImageView!
@IBOutlet private weak var joystickView: UIView!
@IBOutlet private weak var twinSticksView: UIView!

private var controllers: [Controller] {
return childViewControllers.compactMap { $0 as? Controller }
}

private let connectionState = MutableProperty(ConnectionState.disconnected)
private let settingsState = MutableProperty<SettingsState>(SettingsState())

private var motors: [Port: Motor] = [:] {
private var motors: [BoostBLEKit.Port: Motor] = [:] {
didSet {
stickC?.isHidden = !motors.keys.contains(.C)
stickD?.isHidden = !motors.keys.contains(.D)
controllers.forEach {
$0.setEnable(motors.keys.contains(.C), port: .C)
$0.setEnable(motors.keys.contains(.D), port: .D)
}
}
}

override func viewDidLoad() {
super.viewDidLoad()

setupConnectButtonImageView()

stickA.port = .A
stickB.port = .B
stickC.port = .C
stickD.port = .D

stickC.isHidden = true
stickD.isHidden = true

signal(for: stickA.slider).observeValues { [weak self] (value) in
self?.sendCommand(port: .A, power: value)
}
signal(for: stickB.slider).observeValues { [weak self] (value) in
self?.sendCommand(port: .B, power: value)
}
signal(for: stickC.slider).observeValues { [weak self] (value) in
self?.sendCommand(port: .C, power: value)
}
signal(for: stickD.slider).observeValues { [weak self] (value) in
self?.sendCommand(port: .D, power: value)
}
setupSticks()
}

override func viewWillAppear(_ animated: Bool) {
Expand All @@ -70,43 +53,38 @@ class ControllerViewController: UIViewController {
private func setupConnectButtonImageView() {
connectButtonImageView.animationDuration = 1
connectButtonImageView.animationRepeatCount = -1
connectButtonImageView.animationImages = (1...4).map { "connecting\($0)" }.flatMap { UIImage(named: $0) }
connectButtonImageView.animationImages = UIImage.connectingImages()

connectionState.producer.startWithValues { [weak self] (state) in
if state == .connecting {
self?.connectButtonImageView.startAnimating()
} else {
self?.connectButtonImageView.stopAnimating()
}

let imageName: String
switch state {
case .disconnected:
imageName = "disconnected"
case .connecting:
imageName = "disconnected"
case .connected:
imageName = "connected"
case .offline, .unsupported:
imageName = "offline"
}
self?.connectButtonImageView.image = UIImage(named: imageName)
self?.connectButtonImageView.image = UIImage(connectionState: state)
}
}

private func signal(for slider: UISlider) -> Signal<Int8, NoError> {
let valueSignal = slider.reactive.values.map { Int8($0) * 10 }

let touchUpSignal = Signal<UISlider, NoError>
.merge(slider.reactive.controlEvents(.touchUpInside),
slider.reactive.controlEvents(.touchUpOutside))
.on(value: { $0.value = 0 })
.map { _ in Int8(0) }
private func setupSticks() {
controllers.forEach {
$0.signals.forEach { (port, signal) in
signal
.withLatest(from: settingsState.signal.map { $0.step })
.map { (value, step) in Int8(round(value * step) * 100 / step) }
.skipRepeats()
.observeValues { [weak self] (value) in
self?.sendCommand(port: port, power: value)
}
}
}

return Signal<Int8, NoError>.merge(valueSignal, touchUpSignal).skipRepeats()
settingsState.signal.observeValues { [weak self] (state) in
self?.joystickView.isHidden = state.mode != .joystick
self?.twinSticksView.isHidden = state.mode != .twinsticks
}
}

private func sendCommand(port: Port, power: Int8) {
private func sendCommand(port: BoostBLEKit.Port, power: Int8) {
if let command = motors[port]?.powerCommand(power: power) {
ActionCenter.send(command: command)
}
Expand All @@ -118,6 +96,8 @@ class ControllerViewController: UIViewController {
present(alert, animated: true, completion: nil)
}

@IBAction func close(_ segue: UIStoryboardSegue) {}

@IBAction private func connectButtonPushed(_ sender: Any) {
switch connectionState.value {
case .disconnected:
Expand All @@ -139,17 +119,14 @@ extension ControllerViewController: StoreSubscriber {
func newState(state: State) {
connectionState.value = state.connectionState

let ports: [Port] = [.A, .B, .C, .D]
let ports: [BoostBLEKit.Port] = [.A, .B, .C, .D]
for port in ports {
motors[port] = state.portState[port].flatMap { type -> Motor? in
guard state.connectionState == .connected else { return nil }
switch type {
case .builtInMotor, .interactiveMotor:
return Motor(port: port)
default:
return nil
}
return Motor(port: port, deviceType: type)
}
}

settingsState.value = state.settingsState
}
}
2 changes: 1 addition & 1 deletion BoostRemote/Data+HexString.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ extension Data {
let even = hexString.enumerated().filter { $0.offset % 2 == 0 }.map { $0.element }
let odd = hexString.enumerated().filter { $0.offset % 2 == 1 }.map { $0.element }

let bytes = zip(even, odd).flatMap { UInt8(String([$0.0, $0.1]), radix: 16) }
let bytes = zip(even, odd).compactMap { UInt8(String([$0.0, $0.1]), radix: 16) }

self.init(bytes: bytes)
}
Expand Down
Loading

0 comments on commit 8ff17d7

Please sign in to comment.