mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-12 17:45:22 +00:00
convert terminal sagas to typed-redux-saga/macro
This commit is contained in:
+27
-31
@@ -1,7 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2021 The Pybricks Authors
|
||||
|
||||
import { Channel } from 'redux-saga';
|
||||
import {
|
||||
actionChannel,
|
||||
delay,
|
||||
@@ -12,16 +11,11 @@ import {
|
||||
select,
|
||||
take,
|
||||
takeEvery,
|
||||
} from 'redux-saga/effects';
|
||||
} from 'typed-redux-saga/macro';
|
||||
import PushStream from 'zen-push';
|
||||
import { Action } from '../actions';
|
||||
import { AppActionType, AppDidStartAction } from '../actions/app';
|
||||
import {
|
||||
BleUartActionType,
|
||||
BleUartNotifyAction,
|
||||
BleUartWriteAction,
|
||||
write,
|
||||
} from '../actions/ble-uart';
|
||||
import { BleUartActionType, BleUartNotifyAction, write } from '../actions/ble-uart';
|
||||
import { HubRuntimeStatusType, checksum, updateStatus } from '../actions/hub';
|
||||
import {
|
||||
TerminalActionType,
|
||||
@@ -32,13 +26,14 @@ import {
|
||||
import { SafeTxCharLength } from '../protocols/nrf-uart';
|
||||
import { RootState } from '../reducers';
|
||||
import { HubRuntimeState } from '../reducers/hub';
|
||||
import { defined } from '../utils';
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
const decoder = new TextDecoder();
|
||||
const terminalDataSource = new PushStream<string>();
|
||||
|
||||
function* startup(_action: AppDidStartAction): Generator {
|
||||
yield put(setDataSource(terminalDataSource.observable));
|
||||
yield* put(setDataSource(terminalDataSource.observable));
|
||||
}
|
||||
|
||||
function* handleMatch(
|
||||
@@ -50,24 +45,24 @@ function* handleMatch(
|
||||
}
|
||||
|
||||
if (match[1]) {
|
||||
yield put(sendData(match[1]));
|
||||
yield* put(sendData(match[1]));
|
||||
}
|
||||
|
||||
yield put(updateStatus(status));
|
||||
yield* put(updateStatus(status));
|
||||
|
||||
if (match[2]) {
|
||||
yield put(sendData(match[2]));
|
||||
yield* put(sendData(match[2]));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function* receiveUartData(action: BleUartNotifyAction): Generator {
|
||||
const hubState = (yield select((s: RootState) => s.hub.runtime)) as HubRuntimeState;
|
||||
const hubState = yield* select((s: RootState) => s.hub.runtime);
|
||||
|
||||
if (hubState === HubRuntimeState.Loading && action.value.buffer.byteLength === 1) {
|
||||
const view = new DataView(action.value.buffer);
|
||||
yield put(checksum(view.getUint8(0)));
|
||||
yield* put(checksum(view.getUint8(0)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -97,40 +92,41 @@ function* receiveUartData(action: BleUartNotifyAction): Generator {
|
||||
return;
|
||||
}
|
||||
|
||||
yield put(sendData(value));
|
||||
yield* put(sendData(value));
|
||||
}
|
||||
|
||||
function* receiveTerminalData(): Generator {
|
||||
const channel = (yield actionChannel(
|
||||
const channel = yield* actionChannel<TerminalDataReceiveDataAction>(
|
||||
TerminalActionType.ReceivedData,
|
||||
)) as Channel<TerminalDataReceiveDataAction>;
|
||||
);
|
||||
while (true) {
|
||||
// wait for input from terminal
|
||||
const action = (yield take(channel)) as TerminalDataReceiveDataAction;
|
||||
const action = yield* take(channel);
|
||||
let value = action.value;
|
||||
|
||||
// Try to collect more data so that we aren't sending just one byte at time
|
||||
while (value.length < SafeTxCharLength) {
|
||||
const [action, timeout] = (yield race([take(channel), delay(20)])) as [
|
||||
TerminalDataReceiveDataAction,
|
||||
boolean,
|
||||
];
|
||||
const { action, timeout } = yield* race({
|
||||
action: take(channel),
|
||||
timeout: delay(20),
|
||||
});
|
||||
if (timeout) {
|
||||
break;
|
||||
}
|
||||
defined(action);
|
||||
value += action.value;
|
||||
}
|
||||
|
||||
const nextMessageId = (yield getContext('nextMessageId')) as () => number;
|
||||
const nextMessageId = yield* getContext<() => number>('nextMessageId');
|
||||
|
||||
// stdin gets piped to BLE connection
|
||||
const data = encoder.encode(value);
|
||||
for (let i = 0; i < data.length; i += SafeTxCharLength) {
|
||||
const { id } = (yield put(
|
||||
const { id } = yield* put(
|
||||
write(nextMessageId(), data.slice(i, i + SafeTxCharLength)),
|
||||
)) as BleUartWriteAction;
|
||||
);
|
||||
|
||||
yield take(
|
||||
yield* take(
|
||||
(a: Action) =>
|
||||
(a.type === BleUartActionType.DidWrite ||
|
||||
a.type === BleUartActionType.DidFailToWrite) &&
|
||||
@@ -138,7 +134,7 @@ function* receiveTerminalData(): Generator {
|
||||
);
|
||||
|
||||
// wait for echo so tht we don't overrun the hub with messages
|
||||
yield race([take(BleUartActionType.Notify), delay(100)]);
|
||||
yield* race([take(BleUartActionType.Notify), delay(100)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,8 +145,8 @@ function sendTerminalData(action: TerminalDataReceiveDataAction): void {
|
||||
}
|
||||
|
||||
export default function* (): Generator {
|
||||
yield takeEvery(AppActionType.DidStart, startup);
|
||||
yield takeEvery(BleUartActionType.Notify, receiveUartData);
|
||||
yield fork(receiveTerminalData);
|
||||
yield takeEvery(TerminalActionType.SendData, sendTerminalData);
|
||||
yield* takeEvery(AppActionType.DidStart, startup);
|
||||
yield* takeEvery(BleUartActionType.Notify, receiveUartData);
|
||||
yield* fork(receiveTerminalData);
|
||||
yield* takeEvery(TerminalActionType.SendData, sendTerminalData);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user