Skip to content

Commit 63af63c

Browse files
Upgrade connection library to preview version
This contains the pre-1.0 breaking API changes and USB serial re-work. This should improve serial issues after first physical connection + flash and extra serial from previous programs leaking into subsequent ones. This is a preview version for testing on a review branch, we won't merge this directly.
1 parent 509b01b commit 63af63c

21 files changed

Lines changed: 246 additions & 228 deletions

package-lock.json

Lines changed: 97 additions & 53 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"@codemirror/view": "^6.26.3",
1717
"@emotion/react": "^11.11.4",
1818
"@emotion/styled": "^11.11.5",
19-
"@microbit/microbit-connection": "^0.0.0-alpha.36",
19+
"@microbit/microbit-connection": "^0.9.0-apps.alpha.17",
2020
"@microbit/microbit-fs": "^0.10.0",
2121
"@sanity/block-content-to-react": "^3.0.0",
2222
"@sanity/image-url": "^1.0.1",

src/App.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import "./App.css";
1010
import { DialogProvider } from "./common/use-dialogs";
1111
import VisualViewPortCSSVariables from "./common/VisualViewportCSSVariables";
1212
import { deployment, useDeployment } from "./deployment";
13-
import { createWebUSBConnection } from "@microbit/microbit-connection";
13+
import { createUSBConnection } from "@microbit/microbit-connection/usb";
1414
import { DeviceContextProvider } from "./device/device-hooks";
1515
import { MockDeviceConnection } from "./device/mock";
1616
import DocumentationProvider from "./documentation/documentation-hooks";
@@ -40,7 +40,7 @@ const isMockDeviceMode = () =>
4040
const logging = deployment.logging;
4141
const device = isMockDeviceMode()
4242
? new MockDeviceConnection()
43-
: createWebUSBConnection({ logging });
43+
: createUSBConnection({ logging });
4444

4545
const host = createHost(logging);
4646
const fs = new FileSystem(logging, host, fetchMicroPython);

src/deployment/default/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66
import { ReactNode, createContext } from "react";
77
import { CookieConsent, DeploymentConfigFactory } from "..";
8-
import { NullLogging } from "./logging";
8+
import { ConsoleLogging } from "./logging";
99
import theme from "./theme";
1010

1111
const stubConsentValue: CookieConsent = {
@@ -20,7 +20,7 @@ const defaultDeploymentFactory: DeploymentConfigFactory = () => ({
2020
chakraTheme: theme,
2121
// This isn't ideal as it's the branded version. You can just remove the field to remove the welcome dialog.
2222
welcomeVideoYouTubeId: "mREwMW69qKc",
23-
logging: new NullLogging(),
23+
logging: new ConsoleLogging(),
2424
compliance: {
2525
ConsentProvider: ({ children }: { children: ReactNode }) => (
2626
<stubConsentContext.Provider value={stubConsentValue}>

src/deployment/default/logging.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@
55
*/
66
import { Event, Logging } from "../../logging/logging";
77

8-
export class NullLogging implements Logging {
9-
event(_event: Event): void {}
10-
error(_e: any): void {}
11-
log(_e: any): void {}
8+
export class ConsoleLogging implements Logging {
9+
event(event: Event): void {
10+
console.log(event);
11+
}
12+
error(e: any): void {
13+
console.error(e);
14+
}
15+
log(e: any): void {
16+
console.log(e);
17+
}
1218
}

src/device/device-hooks.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ import { useFileSystem } from "../fs/fs-hooks";
1515
import { useLogging } from "../logging/logging-hooks";
1616
import {
1717
ConnectionStatus,
18-
MicrobitWebUSBConnection,
19-
SerialDataEvent,
20-
ConnectionStatusEvent,
18+
ConnectionStatusChange,
2119
} from "@microbit/microbit-connection";
20+
import {
21+
MicrobitUSBConnection,
22+
SerialData,
23+
} from "@microbit/microbit-connection/usb";
2224
import { SimulatorDeviceConnection } from "./simulator";
2325

24-
const DeviceContext = React.createContext<undefined | MicrobitWebUSBConnection>(
26+
const DeviceContext = React.createContext<undefined | MicrobitUSBConnection>(
2527
undefined
2628
);
2729

@@ -56,7 +58,7 @@ export const useConnectionStatus = () => {
5658
const device = useDevice();
5759
const [status, setStatus] = useState<ConnectionStatus>(device.status);
5860
useEffect(() => {
59-
const statusListener = (event: ConnectionStatusEvent) => {
61+
const statusListener = (event: ConnectionStatusChange) => {
6062
setStatus(event.status);
6163
};
6264
device.addEventListener("status", statusListener);
@@ -185,7 +187,7 @@ export const useDeviceTraceback = () => {
185187

186188
useEffect(() => {
187189
const buffer = new TracebackScrollback();
188-
const dataListener = (event: SerialDataEvent) => {
190+
const dataListener = (event: SerialData) => {
189191
const latest = buffer.push(event.data);
190192
setRuntimeError((current) => {
191193
if (!current && latest) {
@@ -234,7 +236,7 @@ export const DeviceContextProvider = ({
234236
value: device,
235237
children,
236238
}: {
237-
value: MicrobitWebUSBConnection;
239+
value: MicrobitUSBConnection;
238240
children: ReactNode;
239241
}) => {
240242
const syncStatusState = useState<SyncStatus>(SyncStatus.OUT_OF_SYNC);

src/device/mock.ts

Lines changed: 28 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,14 @@ import {
88
ConnectionStatus,
99
DeviceConnectionEventMap,
1010
FlashDataSource,
11-
FlashEvent,
12-
SerialDataEvent,
13-
ConnectionStatusEvent,
11+
FlashOptions,
12+
ProgressStage,
1413
DeviceError,
1514
DeviceErrorCode,
1615
TypedEventTarget,
17-
MicrobitWebUSBConnection,
18-
SerialConnectionEventMap,
1916
} from "@microbit/microbit-connection";
17+
import { SerialConnectionEventMap } from "@microbit/microbit-connection/usb";
18+
import { MicrobitUSBConnection } from "@microbit/microbit-connection/usb";
2019

2120
/**
2221
* A mock device used during end-to-end testing.
@@ -27,11 +26,9 @@ import {
2726
*/
2827
export class MockDeviceConnection
2928
extends TypedEventTarget<DeviceConnectionEventMap & SerialConnectionEventMap>
30-
implements MicrobitWebUSBConnection
29+
implements MicrobitUSBConnection
3130
{
32-
status: ConnectionStatus = (navigator as any).usb
33-
? ConnectionStatus.NO_AUTHORIZED_DEVICE
34-
: ConnectionStatus.NOT_SUPPORTED;
31+
status: ConnectionStatus = ConnectionStatus.NoAuthorizedDevice;
3532

3633
private connectResults: DeviceErrorCode[] = [];
3734

@@ -42,34 +39,38 @@ export class MockDeviceConnection
4239
}
4340

4441
mockSerialWrite(data: string) {
45-
this.dispatchTypedEvent("serialdata", new SerialDataEvent(data));
42+
this.dispatchEvent("serialdata", { data });
4643
}
4744

4845
mockConnect(code: DeviceErrorCode) {
4946
this.connectResults.push(code);
5047
}
5148

5249
async initialize(): Promise<void> {}
50+
async checkAvailability() {
51+
return "available" as const;
52+
}
5353

5454
dispose() {}
55-
getDeviceId(): number | undefined {
56-
return undefined;
55+
getDeviceId(): number {
56+
return 0;
5757
}
5858
setRequestDeviceExclusionFilters(): void {}
59-
getDevice() {}
59+
getDevice() {
60+
return undefined;
61+
}
6062
async softwareReset(): Promise<void> {}
6163

62-
async connect(): Promise<ConnectionStatus> {
64+
async connect(): Promise<void> {
6365
const next = this.connectResults.shift();
6466
if (next) {
6567
throw new DeviceError({ code: next, message: "Mocked failure" });
6668
}
6769

68-
this.setStatus(ConnectionStatus.CONNECTED);
69-
return this.status;
70+
this.setStatus(ConnectionStatus.Connected);
7071
}
7172

72-
getBoardVersion(): BoardVersion | undefined {
73+
getBoardVersion(): BoardVersion {
7374
return "V2";
7475
}
7576

@@ -81,42 +82,32 @@ export class MockDeviceConnection
8182
*/
8283
async flash(
8384
_dataSource: FlashDataSource,
84-
options: {
85-
/**
86-
* True to use a partial flash where possible, false to force a full flash.
87-
*/
88-
partial: boolean;
89-
/**
90-
* A progress callback. Called with undefined when the process is complete or has failed.
91-
*/
92-
progress: (percentage: number | undefined) => void;
93-
}
85+
options: FlashOptions
9486
): Promise<void> {
9587
await new Promise((resolve) => setTimeout(resolve, 100));
96-
options.progress(0.5);
88+
options.progress?.(ProgressStage.PartialFlashing, 0.5);
9789
await new Promise((resolve) => setTimeout(resolve, 100));
98-
options.progress(undefined);
99-
this.dispatchTypedEvent("flash", new FlashEvent());
90+
this.dispatchEvent("flash");
10091
}
10192

10293
async disconnect(): Promise<void> {
103-
this.setStatus(ConnectionStatus.DISCONNECTED);
94+
this.setStatus(ConnectionStatus.Disconnected);
10495
}
10596

10697
async serialWrite(data: string): Promise<void> {
10798
console.log("[Serial] ", data);
10899
}
109100

110101
private setStatus(newStatus: ConnectionStatus) {
102+
const previousStatus = this.status;
111103
this.status = newStatus;
112-
this.dispatchTypedEvent("status", new ConnectionStatusEvent(this.status));
104+
this.dispatchEvent("status", {
105+
status: newStatus,
106+
previousStatus,
107+
});
113108
}
114109

115110
clearDevice(): void {
116-
this.setStatus(ConnectionStatus.NO_AUTHORIZED_DEVICE);
117-
}
118-
119-
mockWebUsbNotSupported(): void {
120-
this.setStatus(ConnectionStatus.NOT_SUPPORTED);
111+
this.setStatus(ConnectionStatus.NoAuthorizedDevice);
121112
}
122113
}

0 commit comments

Comments
 (0)