mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-12 01:23:52 +00:00
Fix city hub bootloader compatibility
The city hub requires that certain messages are write with response and others are write without response, otherwise it will cause BlueZ to disconnect because it does not follow proper BLE protocol.
This commit is contained in:
committed by
David Lechner
parent
21208344be
commit
ac6c798148
@@ -84,7 +84,7 @@ export interface BootloaderConnectionSendAction
|
||||
|
||||
export function send(
|
||||
data: ArrayBuffer,
|
||||
withResponse = false,
|
||||
withResponse = true,
|
||||
): BootloaderConnectionSendAction {
|
||||
return { type: BootloaderConnectionActionType.Send, data, withResponse };
|
||||
}
|
||||
|
||||
@@ -146,7 +146,8 @@ describe('message encoder', () => {
|
||||
expect(dispatched[0]).toEqual({
|
||||
type: BootloaderConnectionActionType.Send,
|
||||
data: message,
|
||||
withResponse: false,
|
||||
// Program is write without response, all others are write with response
|
||||
withResponse: request.type !== BootloaderRequestActionType.Program,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -185,7 +186,7 @@ describe('message encoder', () => {
|
||||
expect(dispatched[i]).toEqual({
|
||||
type: BootloaderConnectionActionType.Send,
|
||||
data: message,
|
||||
withResponse: false,
|
||||
withResponse: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+25
-1
@@ -38,6 +38,7 @@ import {
|
||||
checksumResponse,
|
||||
connect,
|
||||
didRequest,
|
||||
disconnectRequest,
|
||||
eraseRequest,
|
||||
eraseResponse,
|
||||
errorResponse,
|
||||
@@ -53,6 +54,7 @@ import {
|
||||
stateResponse,
|
||||
} from '../actions/bootloader';
|
||||
import { MpyCompiledAction, compile } from '../actions/mpy';
|
||||
import * as notification from '../actions/notification';
|
||||
import {
|
||||
Command,
|
||||
ErrorBytecode,
|
||||
@@ -92,13 +94,23 @@ function* encodeRequest(): Generator {
|
||||
while (true) {
|
||||
const action = (yield take(chan)) as BootloaderRequestAction;
|
||||
|
||||
// NB: Commands other than program on city hub will cause BlueZ to
|
||||
// disconnect because they will send a response even if we write without
|
||||
// response, so we always write with response on those commands. The
|
||||
// program command needs to be write without response for performance
|
||||
// reasons (and also the city hub will disconnect if write with response
|
||||
// is used on this command).
|
||||
|
||||
switch (action.type) {
|
||||
case BootloaderRequestActionType.Erase:
|
||||
yield put(send(createEraseFlashRequest()));
|
||||
break;
|
||||
case BootloaderRequestActionType.Program:
|
||||
yield put(
|
||||
send(createProgramFlashRequest(action.address, action.payload)),
|
||||
send(
|
||||
createProgramFlashRequest(action.address, action.payload),
|
||||
/* withResponse */ false,
|
||||
),
|
||||
);
|
||||
break;
|
||||
case BootloaderRequestActionType.Reboot:
|
||||
@@ -294,6 +306,18 @@ function* flashFirmware(action: BootloaderFlashFirmwareAction): Generator {
|
||||
);
|
||||
}
|
||||
|
||||
// City hub bootloader is buggy. See note in encodeRequest().
|
||||
if (info[0].hubType === HubType.CityHub && !didConnect.canWriteWithoutResponse) {
|
||||
yield put(
|
||||
notification.add(
|
||||
'error',
|
||||
'City Hub is not compatible with this web browser.',
|
||||
),
|
||||
);
|
||||
yield put(disconnectRequest());
|
||||
return;
|
||||
}
|
||||
|
||||
yield put(eraseRequest());
|
||||
const erase = (yield wait(
|
||||
BootloaderResponseActionType.Erase,
|
||||
|
||||
@@ -86,6 +86,10 @@ async function connect(action: Action, dispatch: Dispatch): Promise<void> {
|
||||
!char.writeValueWithoutResponse &&
|
||||
!/Android/i.test(navigator.userAgent)
|
||||
) {
|
||||
// TODO: this needs to be an error if connected to city hub
|
||||
// however it is not currently possible to get mfg-specific
|
||||
// advertising data, so we don't know what type of hub it is
|
||||
// until after we connect
|
||||
dispatch(
|
||||
notification.add(
|
||||
'warning',
|
||||
|
||||
Reference in New Issue
Block a user