diff --git a/Modules/RobotKit/Examples/RobotKitExample/Sources/Views/RobotKitExperimentView.swift b/Modules/RobotKit/Examples/RobotKitExample/Sources/Views/RobotKitExperimentView.swift index b425ba542..452bbcc19 100644 --- a/Modules/RobotKit/Examples/RobotKitExample/Sources/Views/RobotKitExperimentView.swift +++ b/Modules/RobotKit/Examples/RobotKitExample/Sources/Views/RobotKitExperimentView.swift @@ -17,6 +17,7 @@ struct RobotKitExperimentView: View { .motion(.stop, duration: .seconds(3), parallel: [ // .lights(.full(.belt, in: .red), duration: .seconds(3)), ]), + .blink(.seconds(0.2), duration: .seconds(5), parallel: []), // .motion(.spin(.counterclockwise, speed: 0.8), duration: .seconds(4), parallel: [ // .blink(.seconds(0.2), duration: .seconds(2), parallel: []), // ]), @@ -29,7 +30,7 @@ struct RobotKitExperimentView: View { .tint(.green) Button("STOP", systemImage: "stop.circle.fill") { - self.robotkit.stop() + self.robotkit.cancel() } .buttonStyle(.bordered) .tint(.red) diff --git a/Modules/RobotKit/Sources/RobotKit.swift b/Modules/RobotKit/Sources/RobotKit.swift index 2ef892533..86376a5c7 100644 --- a/Modules/RobotKit/Sources/RobotKit.swift +++ b/Modules/RobotKit/Sources/RobotKit.swift @@ -13,120 +13,50 @@ public class RobotKit { public static var shared: RobotKit = .init() -// public func append(actions: RobotAction...) { -// for action in actions { -// self.actions.append(action.object) -// } -// } - public func append(actions: [RobotAction]) { self.actions = actions } -// public func execute() { -// for action in self.actions { -// action.execute() -// } -// } - public func executeSync() { guard self.task == nil else { log.trace("Task already running, ignoring new execution") return } -// for action in self.actions { -// log.debug("execute action \(action)") -// await action.object.execute() -// log.debug("execute action \(action) ✅") -// } self.task = Task { for action in self.actions { guard self.task?.isCancelled == false else { log.debug("Task cancelled, stopping robot kit") - // action.object.stop() return } self.currentAction = action log.debug("execute action \(action)") - async let _ = action.object.execute() - // async let currentTask: () = action.object.execute() - // await currentTask + try await action.object.execute() +// async let _ = action.object.execute() log.debug("execute action \(action) ✅") } - self.stop() + self.terminate() } - -// self.task = Task { -// for action in self.actions { -// guard self.task?.isCancelled == false else { -// log.debug("Task cancelled, stopping robot kit") - //// action.object.stop() -// return -// } -// self.currentAction = action -// log.debug("execute action \(action)") -// await action.object.execute() - //// async let currentTask: () = action.object.execute() - //// await currentTask -// log.debug("execute action \(action) ✅") -// } -// self.stop() -// } } -// public func executeSync() { -// guard self.task == nil else { -// log.trace("Task already running, ignoring new execution") -// return -// } -// -// self.task = Task { -// for action in self.actions { -// guard self.task?.isCancelled == false else { return } -// guard let action = action.object else { -// self.stop() -// return -// } -// -// action.execute() -// -// action.parallelActions.forEach { -// guard let action = $0.object else { return } -// action.execute() -// } -// -// try? await Task.sleep(for: action.duration) -// -// action.stop() -// action.parallelActions.forEach { -// guard let action = $0.object else { return } -// action.stop() -// } -// } -// } -// } - - public func stop() { - log.debug("stop robot kit") -// self.actions[self.currentActionIndex].object.stop() + public func cancel() { + log.debug("cancel sequence") + self.currentAction?.object.cancel() self.task?.cancel() -// self.currentAction?.object.cancel() - self.task = nil + self.currentAction = nil + self.task = nil -// for action in self.actions { -// action.object.stop() -// if let parallelActions = action.object.parallelActions { -// for parallelAction in parallelActions { -// parallelAction.object.stop() -// } -// } -// } - self.actions = [] + self.terminate() + } + public func terminate() { + log.debug("terminate sequence") + self.task?.cancel() + self.task = nil + self.actions = [] self.robot.stop() } @@ -136,5 +66,5 @@ public class RobotKit { private var actions: [RobotAction] = [] private var currentAction: RobotAction? - private var task: Task? + private var task: Task? } diff --git a/Modules/RobotKit/Sources/RobotKit/ActionBlink.swift b/Modules/RobotKit/Sources/RobotKit/ActionBlink.swift index 39204e3be..3a3a12e94 100644 --- a/Modules/RobotKit/Sources/RobotKit/ActionBlink.swift +++ b/Modules/RobotKit/Sources/RobotKit/ActionBlink.swift @@ -4,48 +4,69 @@ import Foundation -// -// final class ActionBlink: RobotActionProtocol { -// // MARK: Lifecycle -// -// init(delay: Duration, duration: Duration, and parallelActions: [RobotAction] = []) { -// self.delay = delay -// self.duration = duration -// self.parallelActions = parallelActions -// } -// -// // MARK: Internal -// -// var delay: Duration -// var duration: Duration -// var parallelActions: [RobotAction] -// -// var isRunning: Bool = false -// -// func execute() { -// self.isRunning = true +final class ActionBlink: RobotActionProtocol { + // MARK: Lifecycle + + init(delay: Duration, duration: Duration, and parallelActions: [RobotAction] = []) { + self.delay = delay + self.duration = duration + self.parallelActions = parallelActions + + self.task = Task { + repeat { + guard self.task?.isCancelled == false else { return } + self.robot.shine(.all(in: .white)) + try await Task.sleep(for: self.delay) + self.robot.shine(.all(in: .black)) + try await Task.sleep(for: self.delay) + try Task.checkCancellation() + } while !Task.isCancelled && self.isRunning + } + } + + // MARK: Internal + + var delay: Duration + var duration: Duration + var parallelActions: [RobotAction] + + var isRunning: Bool = false + + func execute() async throws { + self.isRunning = true + DispatchQueue.global().asyncAfter(deadline: .now() + .seconds(Int(self.duration.components.seconds))) { + log.debug("toggle is running to false") + self.isRunning = false + } // Task { -// // TODO: (@ladislas) NOT WORKING - count number of steps first // repeat { // guard self.task?.isCancelled == false else { return } // self.robot.shine(.all(in: .white)) -// try? await Task.sleep(for: self.delay) +// try await Task.sleep(for: self.delay) // self.robot.shine(.all(in: .black)) -// try? await Task.sleep(for: self.delay) +// try await Task.sleep(for: self.delay) +// try Task.checkCancellation() // } while !Task.isCancelled && self.isRunning // } -// } -// -// func stop() { -// log.debug("stop action blink") -// self.isRunning = false -// self.task?.cancel() -// self.task = nil -// } -// -// // MARK: Private -// -// private var task: Task? -// -// private var robot = Robot.shared -// } + + async let _ = self.task?.result + } + + func end() { + log.debug("blink - END") + self.robot.stopLights() + } + + func cancel() { + self.isRunning = false + self.task?.cancel() + self.task = nil + self.end() + } + + // MARK: Private + + private var task: Task? + + private var robot = Robot.shared +} diff --git a/Modules/RobotKit/Sources/RobotKit/ActionMotion.swift b/Modules/RobotKit/Sources/RobotKit/ActionMotion.swift index 9f5a03f56..ed46b7d33 100644 --- a/Modules/RobotKit/Sources/RobotKit/ActionMotion.swift +++ b/Modules/RobotKit/Sources/RobotKit/ActionMotion.swift @@ -19,15 +19,7 @@ final class ActionMotion: RobotActionProtocol { } log.debug("motion - start task - move") self.robot.move(self.motion) - do { - log.debug("motion - run task - sleep") - try await Task.sleep(for: self.duration) - log.debug("motion - run task - sleep done") - } catch { - log.debug("error \(error)") - self.cancel() - return - } + try await Task.sleep(for: self.duration) log.debug("motion - end task") } } @@ -42,7 +34,7 @@ final class ActionMotion: RobotActionProtocol { self.task?.isCancelled == false } - func execute() async { + func execute() async throws { // log.debug("motion - before task") // self.task = Task { @@ -82,5 +74,5 @@ final class ActionMotion: RobotActionProtocol { // MARK: Private private let robot = Robot.shared - private var task: Task? + private var task: Task? } diff --git a/Modules/RobotKit/Sources/RobotKit/RobotAction.swift b/Modules/RobotKit/Sources/RobotKit/RobotAction.swift index c50248a02..0883ed487 100644 --- a/Modules/RobotKit/Sources/RobotKit/RobotAction.swift +++ b/Modules/RobotKit/Sources/RobotKit/RobotAction.swift @@ -7,7 +7,7 @@ import Foundation public enum RobotAction { case motion(Robot.Motion, duration: Duration, parallel: [RobotAction] = []) // case lights(Robot.Lights, duration: Duration, parallel: [RobotAction] = []) -// case blink(Duration, duration: Duration, parallel: [RobotAction] = []) + case blink(Duration, duration: Duration, parallel: [RobotAction] = []) // case pause(duration: Duration) // MARK: Public @@ -18,8 +18,8 @@ public enum RobotAction { ActionMotion(motion, duration: duration, and: parallel) // case let .lights(lights, duration, parallel): // ActionLights(lights, duration: duration, and: parallel) -// case let .blink(delay, duration, parallel): -// ActionBlink(delay: delay, duration: duration, and: parallel) + case let .blink(delay, duration, parallel): + ActionBlink(delay: delay, duration: duration, and: parallel) // case let .pause(duration): // ActionStop(duration: duration) } diff --git a/Modules/RobotKit/Sources/RobotKit/RobotActionProtocol.swift b/Modules/RobotKit/Sources/RobotKit/RobotActionProtocol.swift index 08cc8d79f..523b5f668 100644 --- a/Modules/RobotKit/Sources/RobotKit/RobotActionProtocol.swift +++ b/Modules/RobotKit/Sources/RobotKit/RobotActionProtocol.swift @@ -9,7 +9,7 @@ public protocol RobotActionProtocol { var duration: Duration { get } var parallelActions: [RobotAction] { get } - func execute() async + func execute() async throws func end() func cancel() }