I’m trying to create an application to exchange data with an ESP-32 but I can’t keep the bluetooth connection when navigating between the pages of my application. I then tried to make a bluetooth context with “react” but without success. If anyone could help me, I’d be very grateful.
here’s my BluetoothContext.tsx :
import React, { createContext, useState, useEffect, useRef } from 'react';
import { BleManager } from 'react-native-ble-plx';
import { atob } from 'react-native-quick-base64';
const SERVICE_UUID = '4fafc201-1fb5-459e-8fcc-c5c9c331914b';
const STEP_DATA_CHAR_UUID = 'beefcafe-36e1-4688-b7f5-00000000000b';
const initialState = {
devices: [],
scanning: false,
connecting: false,
connectedDevice: null,
stepCount: 0,
startScan: () => {},
stopScan: () => {},
connectToDevice: (device) => Promise.resolve(),
};
export const BluetoothContext = createContext(initialState);
export const BluetoothProvider = ({ children }) => {
const [devices, setDevices] = useState([]);
const [scanning, setScanning] = useState(false);
const [connecting, setConnecting] = useState(false);
const [connectedDevice, setConnectedDevice] = useState(null);
const [stepCount, setStepCount] = useState(0);
const bleManager = useRef(new BleManager()).current;
const deviceRef = useRef(null);
useEffect(() => {
return () => {
if (deviceRef.current) {
deviceRef.current.cancelConnection().catch((error) => console.error('Disconnect error:', error));
deviceRef.current = null;
}
bleManager.destroy();
};
}, [bleManager]);
const startScan = () => {
setDevices([]);
setScanning(true);
console.log('Scanning started...');
bleManager.startDeviceScan(null, null, (error, scannedDevice) => {
if (error) {
console.error('Scan error:', error);
setScanning(false);
return;
}
if (scannedDevice.name) {
setDevices((prevDevices) => {
const existingDeviceIndex = prevDevices.findIndex((dev) => dev.id === scannedDevice.id);
if (existingDeviceIndex !== -1) {
prevDevices[existingDeviceIndex] = scannedDevice;
return [...prevDevices];
} else {
return [...prevDevices, scannedDevice];
}
});
}
});
setTimeout(() => stopScan(), 10000); // Stop scanning after 10 seconds
};
const stopScan = () => {
console.log('Scanning stopped.');
bleManager.stopDeviceScan();
setScanning(false);
};
const connectToDevice = async (device) => {
try {
setConnecting(true);
await stopScan();
const connectedDevice = await device.connect();
setConnectedDevice(connectedDevice);
deviceRef.current = connectedDevice;
await connectedDevice.discoverAllServicesAndCharacteristics();
const services = await connectedDevice.services();
const service = services.find((s) => s.uuid === SERVICE_UUID);
const characteristics = await service.characteristics();
const stepDataCharacteristic = characteristics.find((c) => c.uuid === STEP_DATA_CHAR_UUID);
stepDataCharacteristic.monitor((error, char) => {
if (error) {
console.error('Error monitoring:', error);
return;
}
const rawStepData = atob(char.value);
const stepCount = parseInt(rawStepData, 10);
setStepCount(stepCount);
});
setConnecting(false);
console.log('Connected to:', connectedDevice.name);
} catch (error) {
console.error('Connection error:', error);
setConnecting(false);
}
};
return (
<BluetoothContext.Provider
value={{
devices,
scanning,
connecting,
connectedDevice,
stepCount,
startScan,
stopScan,
connectToDevice,
}}
>
{children}
</BluetoothContext.Provider>
);
};
_layout.tsx :
import { Stack } from 'expo-router';
export default function RootLayout() {
return (
<Stack
screenOptions={{
headerStyle: {
backgroundColor: '#FFFFF0',
},
headerTintColor: '#000',
headerTitleStyle: {
fontWeight: 'bold',
},
}}>
<Stack.Screen name="index" />
<Stack.Screen name="BluetoothConnectionPage" />
</Stack>
);
}
index.tsx :
import { StyleSheet, Text, View, Image } from "react-native";
import React from "react";
import { Link } from "expo-router";
export default function Page() {
return (
<View style={styles.container}>
<View style={styles.main}>
<Image source={require('./assets/images/xxxx.png')} style={styles.logo} />
<Text style={styles.title}>Bienvenue</Text>
<Text style={styles.subtitle}>Cette application vous aidera à xxxxxx.</Text>
<Link href={'/BluetoothConnectionPage'} asChild>
<Text style={styles.link}>Go to connexion page</Text>
</Link>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
marginTop: 30,
flex: 0.9,
alignItems: "center",
padding: 24,
},
main: {
flex: 0.8,
justifyContent: "center",
maxWidth: 960,
marginHorizontal: "auto",
},
logo: {
width: 140,
height: 110,
marginBottom: 50,
alignSelf: 'center', // Center the logo
},
title: {
fontSize: 60,
fontWeight: "bold",
textAlign: "center",
marginBottom: 20,
},
subtitle: {
fontSize: 20,
color: "#38434D",
textAlign: "center",
marginBottom: 30,
},
link: {
fontSize: 18,
color: "#1E90FF",
marginTop: 20,
textAlign: "center",
},
});
New contributor
arthur masson is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.