Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bluetooth/Usb automatic reconnection #516

Merged

Conversation

EricLin-BBpos
Copy link
Collaborator

Summary

  • Support Bluetooth/Usb automatic reconnection while a reader loses connection unexpected .

Motivation

  • Add automatic reconnection support for Bluetooth in iOS and Bluetooth and USB in Android SDK . So that while a reader loses connection unexpected , the sdk will automatically attempts to reconnect to the reader.
  • This works for M2, WisePad 3 and Chipper.

Testing

  • I tested this manually
  • I added automated tests

Documentation

Select one:

  • I have added relevant documentation for my changes.
  • This PR does not result in any developer-facing changes.

@@ -35,11 +35,13 @@ export type GetLocationsParams = {
export type ConnectBluetoothReaderParams = {
reader: Reader.Type;
locationId?: string;
autoReconnect: boolean;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like this param is named autoReconnectOnUnexpectedDisconnect on the native SDKs, can we stick to that here as well?

};

export type ConnectUsbReaderParams = {
reader: Reader.Type;
locationId?: string;
autoReconnect: boolean;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

}, [onDidStartReaderReconnect]);

const terminalDidSucceedReaderReconnect = useCallback(() => {
console.log('Eric userStripeTerminal terminalDidSucceedReaderReconnect');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✂️

}, [onTerminalDidSucceedReaderReconnect]);

const terminalDidFailReaderReconnect = useCallback(() => {
console.log('Eric userStripeTerminal terminalDidFailReaderReconnect');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✂️

Comment on lines 182 to 195
const didStartReaderReconnect = useCallback(() => {
log('didStartReaderReconnect');
emitter?.emit(START_READER_RECONNECT);
}, [log]);

const terminalDidSucceedReaderReconnect = useCallback(() => {
log('terminalDidSucceedReaderReconnect');
emitter?.emit(TERMINAL_SUCCEED_READER_RECONNECT);
}, [log]);

const terminalDidFailReaderReconnect = useCallback(() => {
log('terminalDidFailReaderReconnect');
emitter?.emit(TERMINAL_FAIL_READER_RECONNECT);
}, [log]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should there be results emitted here?

Comment on lines 94 to 98
export const setEnableAutoReconnect = async (autoReconnection: boolean) =>
await AsyncStorage.setItem(
AUTOMATIC_RECONNECTION_KEY,
JSON.stringify(autoReconnection)
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asyncStorage seems like a bit of an overkill to persist this. maybe we can leverage AppContext instead https://github.com/stripe/stripe-terminal-react-native/blob/4bfa8622/dev-app/src/AppContext.ts#L8-L14

Comment on lines 247 to 257
var connectionConfig: BluetoothConnectionConfiguration
if autoReconnectOnUnexpectedDisconnect {
connectionConfig = BluetoothConnectionConfiguration(
locationId: locationId ?? selectedReader.locationId ?? "",
autoReconnectOnUnexpectedDisconnect: true,
autoReconnectionDelegate: self
)
} else {
connectionConfig = BluetoothConnectionConfiguration(
locationId: locationId ?? selectedReader.locationId ?? "")
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could be simplified to a single BluetoothConnectionConfiguration if you use the autoReconnetOnUnexpectedDisconnect variable as the value in the init, so:

let connectionConfig = BluetoothConnectionConfiguration(
                        locationId: locationId ?? selectedReader.locationId ?? "",
                        autoReconnectOnUnexpectedDisconnect: autoReconnectOnUnexpectedDisconnect,
                        autoReconnectionDelegate: autoReconnectOnUnexpectedDisconnect ? self : nil

Comment on lines 17 to 18
TERMINAL_SUCCEED_READER_RECONNECT("terminalDidSucceedReaderReconnect"),
TERMINAL_FAIL_READER_RECONNECT("terminalDidFailReaderReconnect"),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should drop TERMINAL from these. "Terminal" is implied (for the native iOS callbacks it was added for consistency with other Terminal delegates but in a future version of the SDK its switching to be a reader delegate and will include the instance of the reader that succeeded or failed).

    SUCCEED_READER_RECONNECT("didSucceedReaderReconnect"),
    FAIL_READER_RECONNECT("didFailReaderReconnect"),

Comment on lines 15 to 19
override fun onReaderReconnectFailed(reader: Reader) {
context.sendEvent(TERMINAL_FAIL_READER_RECONNECT.listenerName) {
putMap("reader", mapFromReader(reader))
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to put a failure message here similar to

putMap("error", nativeMapOf {
putString("code", TerminalErrorCode.UNEXPECTED_SDK_ERROR.toString())
putString("message", "Reader has been disconnected unexpectedly")
})
}

cc @chr-stripe

Comment on lines 536 to 538
func terminalDidFailReaderReconnect(_ terminal: Terminal) {
sendEvent(withName: ReactNativeConstants.TERMINAL_FAIL_READER_RECONNECT.rawValue, body: nil)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 528 to 534
func terminal(_ terminal: Terminal, didStartReaderReconnect cancelable: Cancelable) {
sendEvent(withName: ReactNativeConstants.START_READER_RECONNECT.rawValue, body: nil)
}

func terminalDidSucceedReaderReconnect(_ terminal: Terminal) {
sendEvent(withName: ReactNativeConstants.TERMINAL_SUCCEED_READER_RECONNECT.rawValue, body: nil)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the Android listener we use mapFromReader to send the reader in body, should that here as well instead of sending nil

@@ -513,6 +525,18 @@ class StripeTerminalReactNative: RCTEventEmitter, DiscoveryDelegate, BluetoothRe
sendEvent(withName: ReactNativeConstants.CHANGE_CONNECTION_STATUS.rawValue, body: ["result": result])
}

func terminal(_ terminal: Terminal, didStartReaderReconnect cancelable: Cancelable) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like we are not doing much with the cancelable here. We should save that to var like cancelReaderConnectionCancellable and then expose a cancelReaderReconnection method for users to call
cc @bric-stripe

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, good catch. Yeah that should be made available to the integrations so it can be used 👍

}
}

override fun onReaderReconnectStarted(reader: Reader, cancelReconnect: Cancelable) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -0,0 +1,32 @@
package com.stripeterminalreactnative.listener
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 190 to 193
const didFailReaderReconnect = useCallback(() => {
log('didFailReaderReconnect');
}, [log]);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should emit the error message here

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 182 to 188
const didStartReaderReconnect = useCallback(() => {
log('didStartReaderReconnect');
}, [log]);

const didSucceedReaderReconnect = useCallback(() => {
log('didSucceedReaderReconnect');
}, [log]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should emit the connection reader here

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nazli-stripe nazli-stripe merged commit 22fe81a into stripe:main Aug 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants