Skip to content

Instantly share code, notes, and snippets.

@drewandre
Last active January 31, 2020 14:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save drewandre/4c865d35e51fd6567d3fdf66c7eec28c to your computer and use it in GitHub Desktop.
Save drewandre/4c865d35e51fd6567d3fdf66c7eec28c to your computer and use it in GitHub Desktop.
export class App extends Component {
constructor(props) {
super(props)
this.BLEManager = new BleManager({
restoreStateIdentifier: 'bleManagerRestoredState',
restoreStateFunction: bleRestoredState => this.handleBLEManagerStateRestoration(bleRestoredState)
})
this.BLEManager.setLogLevel(LogLevel.Verbose)
this.BLEManager.onDeviceDisconnected(() => console.log('hey, device disconnected'))
this.props.actions.saveBLEManager(this.BLEManager)
}
handleBLEManagerStateRestoration = state => {
console.log('BLE manager state restoration', state)
state && this.connectToBLEDevice(state.connectedPeripherals[0])
}
componentDidMount() {
this.initializeBluetooth()
}
componentWillUnmount() {
this.characteristicListener.remove()
this.subscription.remove()
this.BLEManager.detroy()
}
initializeBluetooth = () => {
this.props.actions.resetBLERequests()
this.subscription = this.BLEManager.onStateChange(state => {
this.props.actions.setBluetoothManagerState(state)
if (state === 'PoweredOn') this.beginBLEScan()
}, true)
}
beginBLEScan = () => {
this.props.actions.setBleDeviceConnecting(true)
this.BLEManager.startDeviceScan(null, null, async (error, device) => {
if (error /* && error === 'Error: BluetoothLE is powered off' */) {
console.warn('Bluetooth scan error', error)
return this.props.actions.setBluetoothError(error)
}
if (POSSIBLE_DEVICE_NAMES.includes(device.name)) {
this.BLEManager.stopDeviceScan()
this.connectToBLEDevice(device)
}
})
}
connectToBLEDevice = async device => {
console.log('Connecting to BLE device')
// Connect to our BLE device and save it to redux state
let connectedBLEDevice = await device.connect()
connectedBLEDevice.onDisconnected(this.handleBLEDeviceDisconnect)
this.props.actions.setConnectedBLEDevice(connectedBLEDevice)
this.props.actions.setConnectedBLEDeviceStatus(true)
// Discover all services and characteristics of our BLE device
await connectedBLEDevice.discoverAllServicesAndCharacteristics()
// Save all BLE device services to state
let connectedBLEDeviceServices = await connectedBLEDevice.services()
connectedBLEDeviceServices = connectedBLEDeviceServices.map(service => new Service(service, this.BLEManager))
this.props.actions.setConnectedBLEDeviceServices(connectedBLEDeviceServices)
// Save all BLE device characteristics to state
let connectedBLEDeviceCharacteristics = await connectedBLEDeviceServices[0].characteristics()
connectedBLEDeviceCharacteristics = connectedBLEDeviceCharacteristics.map(characteristic => new Characteristic(characteristic, this.BLEManager))
this.props.actions.setConnectedBLEDeviceCharacteristics(connectedBLEDeviceCharacteristics)
// Handle a base64 encoded message from our BLE device's writable characteristic
this.characteristicWithResponseListener = connectedBLEDeviceCharacteristics[0].monitor(this.handleCharacteristicWithResponse)
this.characteristicWithoutResponseListener = connectedBLEDeviceCharacteristics[1].monitor(this.handleCharacteristicWithoutResponse)
// Send a base64 encoded message to our BLE device's writable characteristic
this.props.actions.writeWithResponseToBLEDevice(`Hello from ${Platform.OS === 'ios' ? 'iPhone' : 'Android'}!`)
}
handleCharacteristicWithResponse = (error, characteristic) => {
if (error && error.code !== 201) { // 201 means device was disconnected
console.warn('BLE receive error', error)
this.handleBLEDeviceDisconnect();
return this.props.actions.setBluetoothError(error)
}
// Read our BLE device's writable characteristic's base64 encoded value
let response = JSON.parse(base64.decode(characteristic.value))
if (response.ok) {
this.handleBLEResponse(response, true)
}
this.props.actions.concatBLEWriteWithResponseResponse(response.value)
}
handleCharacteristicWithoutResponse = (error, characteristic) => {
if (error && error.code !== 201) { // 201 means device was disconnected
console.warn('BLE receive error', error)
this.handleBLEDeviceDisconnect();
return this.props.actions.setBluetoothError(error)
}
// Read our BLE device's writable characteristic's base64 encoded value
let response = JSON.parse(base64.decode(characteristic.value))
if (response.ok) {
this.handleBLEResponse(response, false)
}
this.props.actions.concatBLEWriteWithoutResponseResponse(response.value)
}
handleBLEDeviceDisconnect = () => {
console.warn("BLE device disconnected! Resetting bluetooth state and restarting scan.")
this.characteristicWithResponseListener.remove()
this.characteristicWithoutResponseListener.remove()
this.props.actions.resetBLEState()
this.beginBLEScan()
}
handleBLEResponse = (response, withResponse) => {
switch (response.type) {
default:
return console.log(`👋🏻 from BLE device with${!withResponse ? 'out' : ''} response:`, response)
}
}
render() {
return (
<View style={{ flex: 1, backgroundColor: Colors.blurredBlack }}>
<Header />
<AppNavigator />
</View>
)
}
}
const mapStateToProps = state => ({
bluetooth: state.bluetooth
})
const mapDispatchToProps = dispatch => {
return {
actions: bindActionCreators({
resolveBLERequest,
resetBLEState,
resetBLERequests,
saveBLEManager,
writeWithResponseToBLEDevice,
writeWithoutResponseToBLEDevice,
setBluetoothError,
concatBLEWriteWithResponseCommand,
concatBLEWriteWithoutResponseCommand,
concatBLEWriteWithResponseResponse,
concatBLEWriteWithoutResponseResponse,
setBleDeviceConnecting,
setConnectedBLEDevice,
setConnectedBLEDeviceStatus,
setConnectedBLEDeviceServices,
setConnectedBLEDeviceCharacteristics,
setBluetoothManagerState,
}, dispatch)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(App)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment