UNPKG

rxpoweredup

Version:

A Typescript RxJS-based library for controlling LEGO Powered UP hubs & peripherals.

70 lines (69 loc) 2.64 kB
import { ReplaySubject, from, of, switchMap, take, tap } from 'rxjs'; import { PortCommandExecutionStatus } from '../../../hub'; export var PortOutputCommandTaskState; (function (PortOutputCommandTaskState) { PortOutputCommandTaskState[PortOutputCommandTaskState["pending"] = 0] = "pending"; PortOutputCommandTaskState[PortOutputCommandTaskState["waitingForResponse"] = 1] = "waitingForResponse"; PortOutputCommandTaskState[PortOutputCommandTaskState["inProgress"] = 2] = "inProgress"; })(PortOutputCommandTaskState || (PortOutputCommandTaskState = {})); export class TaskPortOutputCommand { message; result = new ReplaySubject(); _state = PortOutputCommandTaskState.pending; responseReceived = new ReplaySubject(1); terminalExecutionStates = new Set([ PortCommandExecutionStatus.completed, PortCommandExecutionStatus.discarded, PortCommandExecutionStatus.executionError, ]); stateTransitions = new Map([ [PortOutputCommandTaskState.pending, PortOutputCommandTaskState.waitingForResponse], [PortOutputCommandTaskState.waitingForResponse, PortOutputCommandTaskState.inProgress], [PortOutputCommandTaskState.inProgress, PortOutputCommandTaskState.waitingForResponse], ]); constructor(message) { this.message = message; } get portId() { return this.message.portId; } get state() { return this._state; } set state(value) { if (this._state === value) { return; } if (this.stateTransitions.get(this._state) === value) { this._state = value; } else { throw new Error(`Invalid state transition from ${this._state} to ${value}`); } } discard() { this.result.complete(); } emitError(error) { this.result.error(error); } setExecutionStatus(status) { this.result.next(status); this.responseReceived.next(true); if (this.terminalExecutionStates.has(status)) { this.result.complete(); } } dispose() { return void 0; } accept(visitor) { visitor.visitTaskPortOutputCommand(this); } execute(channel) { if (this.message.waitForFeedback) { return of(null).pipe(switchMap(() => from(channel.sendMessage(this.message, () => (this.state = PortOutputCommandTaskState.waitingForResponse)))), switchMap(() => this.responseReceived), take(1)); } return from(channel.sendMessage(this.message)).pipe(tap(() => this.setExecutionStatus(PortCommandExecutionStatus.completed))); } }