Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@

## [Unreleased]

### Fixed
- Fixed Bluetooth firmware updates sometimes failing on macOS. ([support#1787])
- Fixed multibyte unicode characters not printing correctly in terminal when
split across Bluetooth packets. ([support#1743])

[support#1743]: https://github.com/pybricks/support/issues/1743
[support#1787]: https://github.com/pybricks/support/issues/1787

## [2.3.0-beta.1] - 2023-11-24

### Changed
Expand Down
5 changes: 3 additions & 2 deletions config/licenses.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const dexieLicense = fs.readFileSync(

const shopifyLicense = `MIT License

Copyright (c) 2021 Shopify
Copyright (c) 2018-present Shopify

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -498,9 +498,10 @@ const licenseTextOverrides = {
'@shopify/decorators': shopifyLicense,
'@shopify/function-enhancers': shopifyLicense,
'@shopify/i18n': shopifyLicense,
'@shopify/react': shopifyLicense,
'@shopify/name': shopifyLicense,
'@shopify/react-hooks': shopifyLicense,
'@shopify/react-i18n': shopifyLicense,
'@shopify/react': shopifyLicense,
'@swc/helpers': spdxMIT,
'dexie-observable': dexieLicense,
'dexie-react-hooks': dexieLicense,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"@pybricks/python-program-analysis": "^2.0.0",
"@pyodide/webpack-plugin": "^1.3.2",
"@reduxjs/toolkit": "^1.9.7",
"@shopify/react-i18n": "^7.8.0",
"@shopify/react-i18n": "^7.13.1",
"@svgr/webpack": "^8.1.0",
"@testing-library/dom": "^9.3.4",
"@testing-library/jest-dom": "^6.4.0",
Expand Down
22 changes: 11 additions & 11 deletions src/firmware/sagas.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2021-2022 The Pybricks Authors
// Copyright (c) 2021-2024 The Pybricks Authors

import {
FirmwareMetadata,
Expand Down Expand Up @@ -200,12 +200,12 @@ describe('flashFirmware', () => {
break;
}

if (count % 10 === 0) {
if (count % 8 === 0) {
action = await saga.take();
expect(action).toEqual(checksumRequest(++id));

saga.put(didRequest(id));
saga.put(checksumResponse(0));
saga.put(checksumResponse(0xee));
}
}

Expand Down Expand Up @@ -366,7 +366,7 @@ describe('flashFirmware', () => {
break;
}

if (count % 10 === 0) {
if (count % 8 === 0) {
action = await saga.take();
expect(action).toEqual(checksumRequest(++id));

Expand Down Expand Up @@ -1331,12 +1331,12 @@ describe('flashFirmware', () => {
break;
}

if (count % 10 === 0) {
if (count % 8 === 0) {
action = await saga.take();
expect(action).toEqual(checksumRequest(++id));

saga.put(didRequest(id));
saga.put(checksumResponse(0));
saga.put(checksumResponse(0xeb));
}
}

Expand Down Expand Up @@ -1507,12 +1507,12 @@ describe('flashFirmware', () => {
break;
}

if (count % 10 === 0) {
if (count % 8 === 0) {
action = await saga.take();
expect(action).toEqual(checksumRequest(++id));

saga.put(didRequest(id));
saga.put(checksumResponse(0));
saga.put(checksumResponse(0xeb));
}
}

Expand Down Expand Up @@ -1689,7 +1689,7 @@ describe('flashFirmware', () => {
break;
}

if (count % 10 === 0) {
if (count % 8 === 0) {
action = await saga.take();
expect(action).toEqual(checksumRequest(++id));

Expand Down Expand Up @@ -2254,12 +2254,12 @@ describe('flashFirmware', () => {
break;
}

if (count % 10 === 0) {
if (count % 8 === 0) {
action = await saga.take();
expect(action).toEqual(checksumRequest(++id));

saga.put(didRequest(id));
saga.put(checksumResponse(0));
saga.put(checksumResponse(0xeb));
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/firmware/sagas.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2020-2022 The Pybricks Authors
// Copyright (c) 2020-2024 The Pybricks Authors

import {
FirmwareReader,
Expand Down Expand Up @@ -529,11 +529,11 @@ function* handleFlashFirmware(action: ReturnType<typeof flashFirmware>): Generat
break;
}

// Request checksum every 10 packets to prevent buffer overrun on
// Request checksum every 8 packets to prevent buffer overrun on
// the hub because of sending too much data at once. The actual
// number of packets that can be queued in the Bluetooth chip on
// the hub is not known and could vary by device.
if (count % 10 === 0) {
if (count % 8 === 0) {
const checksumAction = yield* put(checksumRequest(nextMessageId()));

const { response } = yield* all({
Expand Down
10 changes: 9 additions & 1 deletion src/terminal/sagas.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2020-2023 The Pybricks Authors
// Copyright (c) 2020-2024 The Pybricks Authors

import PushStream from 'zen-push';
import { AsyncSaga, delay } from '../../test';
Expand Down Expand Up @@ -86,6 +86,14 @@ describe('receiving stdout from hub', () => {

await expect(saga.take()).resolves.toEqual(sendData(' '));

// ensure that unicode characters are handled correctly when split
// across buffers

saga.put(didReceiveWriteStdout(new Uint8Array([0xe4]).buffer));
await expect(saga.take()).resolves.toEqual(sendData(''));
saga.put(didReceiveWriteStdout(new Uint8Array([0xb8, 0xad]).buffer));
await expect(saga.take()).resolves.toEqual(sendData('中'));

await saga.end();
});
});
Expand Down
8 changes: 4 additions & 4 deletions src/terminal/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ import { receiveData, sendData } from './actions';
export type TerminalSagaContext = { terminal: TerminalContextValue };

const encoder = new TextEncoder();
const decoder = new TextDecoder();
const uartDecoder = new TextDecoder();
const stdoutDecoder = new TextDecoder();

function* receiveUartData(action: ReturnType<typeof didNotify>): Generator {
const { runtime: hubState, useLegacyStdio } = yield* select(
Expand All @@ -56,15 +57,14 @@ function* receiveUartData(action: ReturnType<typeof didNotify>): Generator {
return;
}

const value = decoder.decode(action.value.buffer);
const value = uartDecoder.decode(action.value.buffer, { stream: true });
yield* put(sendData(value));
}

function* handleReceiveWriteStdout(
action: ReturnType<typeof didReceiveWriteStdout>,
): Generator {
const value = decoder.decode(action.payload);
// console.log('>>> term.sagas', value);
const value = stdoutDecoder.decode(action.payload, { stream: true });
yield* put(sendData(value));
}

Expand Down
Loading