mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-12 01:23:52 +00:00
drop polyfill for chromimum < v85
This removes the polyfill for using older chrome browsers before the writeWithResponse and writeWithoutResponse APIs were added.
This commit is contained in:
@@ -54,14 +54,10 @@ export function connect(): BootloaderConnectionConnectAction {
|
||||
return { type: BootloaderConnectionActionType.Connect };
|
||||
}
|
||||
|
||||
export type BootloaderConnectionDidConnectAction = Action<BootloaderConnectionActionType.DidConnect> & {
|
||||
canWriteWithoutResponse: boolean;
|
||||
};
|
||||
export type BootloaderConnectionDidConnectAction = Action<BootloaderConnectionActionType.DidConnect>;
|
||||
|
||||
export function didConnect(
|
||||
canWriteWithoutResponse: boolean,
|
||||
): BootloaderConnectionDidConnectAction {
|
||||
return { type: BootloaderConnectionActionType.DidConnect, canWriteWithoutResponse };
|
||||
export function didConnect(): BootloaderConnectionDidConnectAction {
|
||||
return { type: BootloaderConnectionActionType.DidConnect };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"ble": {
|
||||
"cannotWriteWithoutResponse": "This web browser does not support Web Bluetooth Write Characteristic Without Response. Flashing firmware will take a long time.",
|
||||
"gattPermission": "The web browser did not give permission to use Bluetooth Low Energy",
|
||||
"gattServiceNotFound": "Connected to hub but failed to get {serviceName} service. Try removing the \"{hubName}\" device in your OS Bluetooth settings, then try again.",
|
||||
"noWebBluetooth": "This web browser does not support Web Bluetooth or it is not enabled.",
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
// Notification translation keys.
|
||||
|
||||
export enum MessageId {
|
||||
BleCannotWriteWithoutResponse = 'ble.cannotWriteWithoutResponse',
|
||||
BleConnectFailed = 'ble.connectFailed',
|
||||
BleGattPermission = 'ble.gattPermission',
|
||||
BleGattServiceNotFound = 'ble.gattServiceNotFound',
|
||||
|
||||
@@ -93,17 +93,6 @@ const list: Reducer<NotificationList, Action> = (state = [], action) => {
|
||||
return append(state, Level.Error, MessageId.BleConnectFailed);
|
||||
}
|
||||
return state;
|
||||
case BootloaderConnectionActionType.DidConnect:
|
||||
if (!action.canWriteWithoutResponse) {
|
||||
return append(
|
||||
state,
|
||||
Level.Warning,
|
||||
MessageId.BleCannotWriteWithoutResponse,
|
||||
undefined,
|
||||
'https://github.com/WebBluetoothCG/web-bluetooth/blob/master/implementation-status.md',
|
||||
);
|
||||
}
|
||||
return state;
|
||||
case BootloaderConnectionActionType.DidFailToConnect:
|
||||
switch (action.reason) {
|
||||
case BootloaderConnectionFailureReason.GattServiceNotFound:
|
||||
|
||||
+7
-13
@@ -33,10 +33,6 @@ import {
|
||||
import { ServiceUUID as pybricksServiceUUID } from '../protocols/pybricks';
|
||||
import { RootState } from '../reducers';
|
||||
import { BleConnectionState } from '../reducers/ble';
|
||||
import {
|
||||
PolyfillBluetoothRemoteGATTCharacteristic,
|
||||
polyfillBluetoothRemoteGATTCharacteristic,
|
||||
} from '../utils/web-bluetooth';
|
||||
|
||||
function disconnect(
|
||||
server: BluetoothRemoteGATTServer,
|
||||
@@ -50,11 +46,11 @@ function* handleValueChanged(data: DataView): Generator {
|
||||
}
|
||||
|
||||
function* write(
|
||||
rxChar: PolyfillBluetoothRemoteGATTCharacteristic,
|
||||
rxChar: BluetoothRemoteGATTCharacteristic,
|
||||
action: BleUartWriteAction,
|
||||
): Generator {
|
||||
try {
|
||||
yield call(() => rxChar.xWriteValueWithoutResponse(action.value.buffer));
|
||||
yield call(() => rxChar.writeValueWithoutResponse(action.value.buffer));
|
||||
yield put(didWrite(action.id));
|
||||
} catch (err) {
|
||||
yield put(didFailToWrite(action.id, err));
|
||||
@@ -129,14 +125,12 @@ function* connect(_action: BleDeviceConnectAction): Generator {
|
||||
return;
|
||||
}
|
||||
|
||||
let rxChar: PolyfillBluetoothRemoteGATTCharacteristic;
|
||||
let rxChar: BluetoothRemoteGATTCharacteristic;
|
||||
try {
|
||||
rxChar = polyfillBluetoothRemoteGATTCharacteristic(
|
||||
(yield call(
|
||||
[service, 'getCharacteristic'],
|
||||
urtRxCharUUID,
|
||||
)) as BluetoothRemoteGATTCharacteristic,
|
||||
);
|
||||
rxChar = (yield call(
|
||||
[service, 'getCharacteristic'],
|
||||
urtRxCharUUID,
|
||||
)) as BluetoothRemoteGATTCharacteristic;
|
||||
} catch (err) {
|
||||
server.disconnect();
|
||||
yield takeMaybe(disconnectChannel);
|
||||
|
||||
+18
-35
@@ -236,21 +236,6 @@ function* flashFirmware(action: FlashFirmwareFlashAction): Generator {
|
||||
}
|
||||
}
|
||||
|
||||
// City hub bootloader is buggy. See note in encodeRequest().
|
||||
if (info[0].hubType === HubType.CityHub && !connectResult.canWriteWithoutResponse) {
|
||||
yield put(
|
||||
notification.add(
|
||||
'error',
|
||||
'City Hub bootloader is not compatible with this web browser.',
|
||||
),
|
||||
);
|
||||
const disconnectAction = (yield put(
|
||||
disconnectRequest(),
|
||||
)) as BootloaderDisconnectRequestAction;
|
||||
yield waitForDidSend(disconnectAction.id);
|
||||
return;
|
||||
}
|
||||
|
||||
const eraseAction = (yield put(eraseRequest())) as BootloaderEraseRequestAction;
|
||||
const [, erase] = (yield all([
|
||||
waitForDidSend(eraseAction.id),
|
||||
@@ -296,26 +281,24 @@ function* flashFirmware(action: FlashFirmwareFlashAction): Generator {
|
||||
break;
|
||||
}
|
||||
|
||||
if (connectResult.canWriteWithoutResponse) {
|
||||
// Request checksum every 10 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) {
|
||||
const checksumAction = (yield put(
|
||||
checksumRequest(),
|
||||
)) as BootloaderChecksumRequestAction;
|
||||
const [, checksum] = (yield all([
|
||||
waitForDidSend(checksumAction.id),
|
||||
waitForResponse(BootloaderResponseActionType.Checksum, 5000),
|
||||
])) as [
|
||||
BootloaderDidRequestAction,
|
||||
WaitResponse<BootloaderChecksumResponseAction>,
|
||||
];
|
||||
if (!checksum[0]) {
|
||||
// TODO: proper error handling
|
||||
throw Error(`Failed to get checksum: ${checksum}`);
|
||||
}
|
||||
// Request checksum every 10 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) {
|
||||
const checksumAction = (yield put(
|
||||
checksumRequest(),
|
||||
)) as BootloaderChecksumRequestAction;
|
||||
const [, checksum] = (yield all([
|
||||
waitForDidSend(checksumAction.id),
|
||||
waitForResponse(BootloaderResponseActionType.Checksum, 5000),
|
||||
])) as [
|
||||
BootloaderDidRequestAction,
|
||||
WaitResponse<BootloaderChecksumResponseAction>,
|
||||
];
|
||||
if (!checksum[0]) {
|
||||
// TODO: proper error handling
|
||||
throw Error(`Failed to get checksum: ${checksum}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,24 +17,20 @@ import {
|
||||
didSend,
|
||||
} from '../actions/lwp3-bootloader';
|
||||
import { CharacteristicUUID, ServiceUUID } from '../protocols/lwp3-bootloader';
|
||||
import {
|
||||
PolyfillBluetoothRemoteGATTCharacteristic,
|
||||
polyfillBluetoothRemoteGATTCharacteristic,
|
||||
} from '../utils/web-bluetooth';
|
||||
|
||||
function* handleNotify(data: DataView): Generator {
|
||||
yield put(didReceive(data));
|
||||
}
|
||||
|
||||
function* write(
|
||||
characteristic: PolyfillBluetoothRemoteGATTCharacteristic,
|
||||
characteristic: BluetoothRemoteGATTCharacteristic,
|
||||
action: BootloaderConnectionSendAction,
|
||||
): Generator {
|
||||
try {
|
||||
if (action.withResponse) {
|
||||
yield call(() => characteristic.xWriteValueWithResponse(action.data));
|
||||
yield call(() => characteristic.writeValueWithResponse(action.data));
|
||||
} else {
|
||||
yield call(() => characteristic.xWriteValueWithoutResponse(action.data));
|
||||
yield call(() => characteristic.writeValueWithoutResponse(action.data));
|
||||
}
|
||||
yield put(didSend());
|
||||
} catch (err) {
|
||||
@@ -110,14 +106,12 @@ function* connect(_action: BootloaderConnectionAction): Generator {
|
||||
return;
|
||||
}
|
||||
|
||||
let characteristic: PolyfillBluetoothRemoteGATTCharacteristic;
|
||||
let characteristic: BluetoothRemoteGATTCharacteristic;
|
||||
try {
|
||||
characteristic = polyfillBluetoothRemoteGATTCharacteristic(
|
||||
(yield call(
|
||||
[service, 'getCharacteristic'],
|
||||
CharacteristicUUID,
|
||||
)) as BluetoothRemoteGATTCharacteristic,
|
||||
);
|
||||
characteristic = (yield call(
|
||||
[service, 'getCharacteristic'],
|
||||
CharacteristicUUID,
|
||||
)) as BluetoothRemoteGATTCharacteristic;
|
||||
} catch (err) {
|
||||
server.disconnect();
|
||||
yield takeMaybe(disconnectChannel);
|
||||
@@ -150,13 +144,7 @@ function* connect(_action: BootloaderConnectionAction): Generator {
|
||||
yield takeEvery(notificationChannel, handleNotify);
|
||||
yield takeEvery(BootloaderConnectionActionType.Send, write, characteristic);
|
||||
|
||||
// writeValueWithoutResponse() was introduced in Chrome 85.
|
||||
// Older versions of Chrome for Android will write without response
|
||||
// by default when using the deprecated writeValue().
|
||||
const canWriteWithoutResponse =
|
||||
characteristic.writeValueWithoutResponse !== undefined ||
|
||||
/Android/i.test(navigator.userAgent);
|
||||
yield put(didConnect(canWriteWithoutResponse));
|
||||
yield put(didConnect());
|
||||
|
||||
yield takeMaybe(disconnectChannel);
|
||||
notificationChannel.close();
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020 The Pybricks Authors
|
||||
|
||||
import { polyfillBluetoothRemoteGATTCharacteristic } from './web-bluetooth';
|
||||
|
||||
describe('polyfillBluetoothRemoteGATTCharacteristic', () => {
|
||||
test('old browser falls back to writeValue', () => {
|
||||
const char = {} as BluetoothRemoteGATTCharacteristic;
|
||||
Object.defineProperty(char, 'writeValue', { value: 'writeValue' });
|
||||
expect(polyfillBluetoothRemoteGATTCharacteristic(char)).toEqual({
|
||||
xWriteValueWithResponse: 'writeValue',
|
||||
xWriteValueWithoutResponse: 'writeValue',
|
||||
});
|
||||
});
|
||||
test('new browser uses writeValueWith(out)Response', () => {
|
||||
const char = {} as BluetoothRemoteGATTCharacteristic;
|
||||
Object.defineProperty(char, 'writeValue', { value: 'writeValue' });
|
||||
Object.defineProperty(char, 'writeValueWithResponse', {
|
||||
value: 'writeValueWithResponse',
|
||||
});
|
||||
Object.defineProperty(char, 'writeValueWithoutResponse', {
|
||||
value: 'writeValueWithoutResponse',
|
||||
});
|
||||
expect(polyfillBluetoothRemoteGATTCharacteristic(char)).toEqual({
|
||||
xWriteValueWithResponse: 'writeValueWithResponse',
|
||||
xWriteValueWithoutResponse: 'writeValueWithoutResponse',
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,35 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020 The Pybricks Authors
|
||||
|
||||
/**
|
||||
* Current definition of BluetoothRemoteGATTCharacteristic doesn't include
|
||||
* new Web Bluetooth APIs.
|
||||
*/
|
||||
export interface PolyfillBluetoothRemoteGATTCharacteristic
|
||||
extends BluetoothRemoteGATTCharacteristic {
|
||||
/**
|
||||
* Calls writeValueWithResponse() if available otherwise falls back to writeValue()
|
||||
* @param value data to send
|
||||
*/
|
||||
xWriteValueWithResponse(value: BufferSource): Promise<void>;
|
||||
/**
|
||||
* Calls writeValueWithoutResponse() if available otherwise falls back to writeValue()
|
||||
* @param value data to send
|
||||
*/
|
||||
xWriteValueWithoutResponse(value: BufferSource): Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills in writeValueWithResponse and writeValueWithoutResponse for backward
|
||||
* compatibility.
|
||||
* @param char a remote GATT characteristic object
|
||||
*/
|
||||
export function polyfillBluetoothRemoteGATTCharacteristic(
|
||||
char: BluetoothRemoteGATTCharacteristic,
|
||||
): PolyfillBluetoothRemoteGATTCharacteristic {
|
||||
const polyfill = (char as unknown) as PolyfillBluetoothRemoteGATTCharacteristic;
|
||||
polyfill.xWriteValueWithResponse = char.writeValueWithResponse || char.writeValue;
|
||||
polyfill.xWriteValueWithoutResponse =
|
||||
char.writeValueWithoutResponse || char.writeValue;
|
||||
return polyfill;
|
||||
}
|
||||
Reference in New Issue
Block a user