Created
September 30, 2025 17:06
-
-
Save IgorDePaula/5dcf8351c28c45a46fe2d618c85cb0f5 to your computer and use it in GitHub Desktop.
rn bluetooth
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Sample React Native App | |
| * https://github.com/facebook/react-native | |
| * | |
| * @format | |
| * @flow strict-local | |
| */ | |
| import React, {useCallback, useEffect, useState} from 'react'; | |
| import type {Node} from 'react'; | |
| import { | |
| Button, FlatList, | |
| NativeEventEmitter, | |
| NativeModules, | |
| PermissionsAndroid, | |
| Platform, | |
| SafeAreaView, | |
| ScrollView, | |
| StatusBar, | |
| StyleSheet, | |
| Text, | |
| TouchableHighlight, | |
| useColorScheme, | |
| View, | |
| } from "react-native"; | |
| import { | |
| Colors, | |
| DebugInstructions, | |
| Header, | |
| LearnMoreLinks, | |
| ReloadInstructions, | |
| } from 'react-native/Libraries/NewAppScreen'; | |
| import BleManager from 'react-native-ble-manager'; | |
| const BleManagerModule = NativeModules.BleManager; | |
| const bleManagerEmitter = new NativeEventEmitter(BleManagerModule); | |
| //import {BleManager} from 'react-native-ble-plx'; | |
| //import RNBluetoothClassic, { | |
| // BluetoothDevice, | |
| //} from 'react-native-bluetooth-classic'; | |
| const Section = ({children, title}): Node => { | |
| const isDarkMode = useColorScheme() === 'dark'; | |
| return ( | |
| <View style={styles.sectionContainer}> | |
| <Text | |
| style={[ | |
| styles.sectionTitle, | |
| { | |
| color: isDarkMode ? Colors.white : Colors.black, | |
| }, | |
| ]}> | |
| {title} | |
| </Text> | |
| <Text | |
| style={[ | |
| styles.sectionDescription, | |
| { | |
| color: isDarkMode ? Colors.light : Colors.dark, | |
| }, | |
| ]}> | |
| {children} | |
| </Text> | |
| </View> | |
| ); | |
| }; | |
| const App: () => Node = () => { | |
| const isDarkMode = useColorScheme() === 'dark'; | |
| const [device, setDevice] = useState([]); | |
| const [conected, setConnected] = useState([]); | |
| const [loading, setLoading] = useState(true); | |
| const backgroundStyle = { | |
| backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, | |
| }; | |
| // eslint-disable-next-line react-hooks/exhaustive-deps | |
| //const manager = new BleManager(); | |
| const [isScanning, setIsScanning] = useState(false); | |
| const peripherals = new Map(); | |
| const [list, setList] = useState([]); | |
| const startScan = () => { | |
| if (!isScanning) { | |
| BleManager.scan([], 3, true) | |
| .then(results => { | |
| console.log('Scanning...'); | |
| setIsScanning(true); | |
| }) | |
| .catch(err => { | |
| console.error(err); | |
| }); | |
| } | |
| }; | |
| const handleStopScan = () => { | |
| console.log('Scan is stopped'); | |
| setIsScanning(false); | |
| }; | |
| const handleDisconnectedPeripheral = data => { | |
| let peripheral = peripherals.get(data.peripheral); | |
| if (peripheral) { | |
| peripheral.connected = false; | |
| peripherals.set(peripheral.id, peripheral); | |
| setList(Array.from(peripherals.values())); | |
| } | |
| console.log('Disconnected from ' + data.peripheral); | |
| }; | |
| const handleUpdateValueForCharacteristic = data => { | |
| console.log( | |
| 'Received data from ' + | |
| data.peripheral + | |
| ' characteristic ' + | |
| data.characteristic, | |
| data.value, | |
| ); | |
| }; | |
| const retrieveConnected = () => { | |
| BleManager.getConnectedPeripherals([]).then(results => { | |
| if (results.length == 0) { | |
| console.log('No connected peripherals'); | |
| } | |
| console.log(results); | |
| for (var i = 0; i < results.length; i++) { | |
| var peripheral = results[i]; | |
| peripheral.connected = true; | |
| peripherals.set(peripheral.id, peripheral); | |
| setList(Array.from(peripherals.values())); | |
| } | |
| }); | |
| }; | |
| const handleDiscoverPeripheral = peripheral => { | |
| console.log('Got ble peripheral', peripheral); | |
| if (!peripheral.name) { | |
| peripheral.name = 'NO NAME'; | |
| } | |
| peripherals.set(peripheral.id, peripheral); | |
| setList(Array.from(peripherals.values())); | |
| }; | |
| const testPeripheral = peripheral => { | |
| if (peripheral) { | |
| if (peripheral.connected) { | |
| BleManager.disconnect(peripheral.id); | |
| } else { | |
| BleManager.connect(peripheral.id) | |
| .then(() => { | |
| let p = peripherals.get(peripheral.id); | |
| if (p) { | |
| p.connected = true; | |
| peripherals.set(peripheral.id, p); | |
| setList(Array.from(peripherals.values())); | |
| } | |
| console.log('Connected to ' + peripheral.id); | |
| setTimeout(() => { | |
| /* Test read current RSSI value */ | |
| BleManager.retrieveServices(peripheral.id).then( | |
| peripheralData => { | |
| console.log('Retrieved peripheral services', peripheralData); | |
| BleManager.readRSSI(peripheral.id).then(rssi => { | |
| console.log('Retrieved actual RSSI value', rssi); | |
| let p = peripherals.get(peripheral.id); | |
| if (p) { | |
| p.rssi = rssi; | |
| peripherals.set(peripheral.id, p); | |
| setList(Array.from(peripherals.values())); | |
| } | |
| }); | |
| }, | |
| ); | |
| // Test using bleno's pizza example | |
| // https://github.com/sandeepmistry/bleno/tree/master/examples/pizza | |
| /* | |
| BleManager.retrieveServices(peripheral.id).then((peripheralInfo) => { | |
| console.log(peripheralInfo); | |
| var service = '13333333-3333-3333-3333-333333333337'; | |
| var bakeCharacteristic = '13333333-3333-3333-3333-333333330003'; | |
| var crustCharacteristic = '13333333-3333-3333-3333-333333330001'; | |
| setTimeout(() => { | |
| BleManager.startNotification(peripheral.id, service, bakeCharacteristic).then(() => { | |
| console.log('Started notification on ' + peripheral.id); | |
| setTimeout(() => { | |
| BleManager.write(peripheral.id, service, crustCharacteristic, [0]).then(() => { | |
| console.log('Writed NORMAL crust'); | |
| BleManager.write(peripheral.id, service, bakeCharacteristic, [1,95]).then(() => { | |
| console.log('Writed 351 temperature, the pizza should be BAKED'); | |
| //var PizzaBakeResult = { | |
| // HALF_BAKED: 0, | |
| // BAKED: 1, | |
| // CRISPY: 2, | |
| // BURNT: 3, | |
| // ON_FIRE: 4 | |
| //}; | |
| }); | |
| }); | |
| }, 500); | |
| }).catch((error) => { | |
| console.log('Notification error', error); | |
| }); | |
| }, 200); | |
| });*/ | |
| }, 900); | |
| }) | |
| .catch(error => { | |
| console.log('Connection error', error); | |
| }); | |
| } | |
| } | |
| }; | |
| const renderItem = item => { | |
| const color = item.connected ? 'green' : '#fff'; | |
| return ( | |
| <TouchableHighlight onPress={() => testPeripheral(item)}> | |
| <View style={[styles.row, {backgroundColor: color}]}> | |
| <Text | |
| style={{ | |
| fontSize: 12, | |
| textAlign: 'center', | |
| color: '#333333', | |
| padding: 10, | |
| }}> | |
| {item.name} | |
| </Text> | |
| <Text | |
| style={{ | |
| fontSize: 10, | |
| textAlign: 'center', | |
| color: '#333333', | |
| padding: 2, | |
| }}> | |
| RSSI: {item.rssi} | |
| </Text> | |
| <Text | |
| style={{ | |
| fontSize: 8, | |
| textAlign: 'center', | |
| color: '#333333', | |
| padding: 2, | |
| paddingBottom: 20, | |
| }}> | |
| {item.id} | |
| </Text> | |
| </View> | |
| </TouchableHighlight> | |
| ); | |
| }; | |
| // eslint-disable-next-line react-hooks/exhaustive-deps | |
| useEffect(async () => { | |
| console.log('to aki'); | |
| BleManager.start({showAlert: false}); | |
| bleManagerEmitter.addListener( | |
| 'BleManagerDiscoverPeripheral', | |
| handleDiscoverPeripheral, | |
| ); | |
| bleManagerEmitter.addListener('BleManagerStopScan', handleStopScan); | |
| bleManagerEmitter.addListener( | |
| 'BleManagerDisconnectPeripheral', | |
| handleDisconnectedPeripheral, | |
| ); | |
| bleManagerEmitter.addListener( | |
| 'BleManagerDidUpdateValueForCharacteristic', | |
| handleUpdateValueForCharacteristic, | |
| ); | |
| if (Platform.OS === 'android' && Platform.Version >= 23) { | |
| PermissionsAndroid.check( | |
| PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION, | |
| ).then(result => { | |
| if (result) { | |
| console.log('Permission is OK'); | |
| } else { | |
| PermissionsAndroid.request( | |
| PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION, | |
| ).then(result => { | |
| if (result) { | |
| console.log('User accept'); | |
| } else { | |
| console.log('User refuse'); | |
| } | |
| }); | |
| } | |
| }); | |
| } | |
| return () => { | |
| console.log('unmount'); | |
| bleManagerEmitter.removeListener( | |
| 'BleManagerDiscoverPeripheral', | |
| handleDiscoverPeripheral, | |
| ); | |
| bleManagerEmitter.removeListener('BleManagerStopScan', handleStopScan); | |
| bleManagerEmitter.removeListener( | |
| 'BleManagerDisconnectPeripheral', | |
| handleDisconnectedPeripheral, | |
| ); | |
| bleManagerEmitter.removeListener( | |
| 'BleManagerDidUpdateValueForCharacteristic', | |
| handleUpdateValueForCharacteristic, | |
| ); | |
| }; | |
| /*RNBluetoothClassic.startDiscovery().then(devices => { | |
| devices.map(async device => { | |
| setLoading(false); | |
| setDevice(prev => [...prev, device]); | |
| if (device.name == 'ESP32') { | |
| // const conn = await device. // .connect(); | |
| // console.log('conn', conn); | |
| RNBluetoothClassic.accept() | |
| RNBluetoothClassic.pairDevice(device.address) | |
| .then(async device2 => { | |
| const conn = await device2.connect(); | |
| const write = await device2.write("teste"); | |
| console.log('conn', conn); | |
| }) | |
| .catch(err => { | |
| console.error(err.message); | |
| }); | |
| } | |
| console.log('device name', device.name); | |
| }); | |
| });*/ | |
| //await manager.enable(); | |
| //await requestBluetoothPermission(); | |
| //scanAndConnect(manager); | |
| //setConnected(await manager.connectedDevices()); | |
| }, []); | |
| const requestBluetoothPermission = async () => { | |
| console.log('pedindo permissao'); | |
| try { | |
| const granted = await PermissionsAndroid.request( | |
| PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION, | |
| { | |
| title: 'Cool Photo App Camera Permission', | |
| message: | |
| 'Cool Photo App needs access to your camera ' + | |
| 'so you can take awesome pictures.', | |
| buttonNeutral: 'Ask Me Later', | |
| buttonNegative: 'Cancel', | |
| buttonPositive: 'OK', | |
| }, | |
| ); | |
| console.log('permissao', granted); | |
| if (granted === PermissionsAndroid.RESULTS.GRANTED) { | |
| console.log('You can use the camera'); | |
| } else { | |
| console.log('Camera permission denied'); | |
| } | |
| } catch (err) { | |
| console.warn(err); | |
| } | |
| }; | |
| // eslint-disable-next-line react-hooks/exhaustive-deps | |
| /*const scanAndConnect = manager => { | |
| console.log('start scan'); | |
| manager.startDeviceScan(null, null, resultScan); | |
| };*/ | |
| /*const resultScan = useCallback( | |
| async (error, device) => { | |
| if (error) { | |
| console.error(error); | |
| // Handle error (scanning will be stopped automatically) | |
| return; | |
| } | |
| if (device != null && device.name == 'ESP32') { | |
| console.log('device found'); | |
| setDevice(prevState => [...prevState, device.name]); | |
| manager.stopDeviceScan(); | |
| console.log('device', device.id); | |
| manager.connectToDevice(device.id).then(devi => { | |
| devi.discoverAllServicesAndCharacteristics().then(chars => { | |
| console.log('chars', chars); | |
| }); | |
| }); | |
| setLoading(false); | |
| } | |
| // Check if it is a device you are looking for based on advertisement data | |
| // or other criteria. | |
| if (device.name === 'Esp32') { | |
| // Stop scanning as it's not necessary if you are scanning for one device. | |
| manager.stopDeviceScan(); | |
| setLoading(false); | |
| // Proceed with connection. | |
| } | |
| }, | |
| [manager], | |
| );*/ | |
| return ( | |
| <> | |
| <StatusBar barStyle="dark-content" /> | |
| <SafeAreaView> | |
| <ScrollView | |
| contentInsetAdjustmentBehavior="automatic" | |
| style={styles.scrollView}> | |
| {global.HermesInternal == null ? null : ( | |
| <View style={styles.engine}> | |
| <Text style={styles.footer}>Engine: Hermes</Text> | |
| </View> | |
| )} | |
| <View style={styles.body}> | |
| <View style={{margin: 10}}> | |
| <Button | |
| title={'Scan Bluetooth (' + (isScanning ? 'on' : 'off') + ')'} | |
| onPress={() => startScan()} | |
| /> | |
| </View> | |
| <View style={{margin: 10}}> | |
| <Button | |
| title="Retrieve connected peripherals" | |
| onPress={() => retrieveConnected()} | |
| /> | |
| </View> | |
| {list.length == 0 && ( | |
| <View style={{flex: 1, margin: 20}}> | |
| <Text style={{textAlign: 'center'}}>No peripherals</Text> | |
| </View> | |
| )} | |
| </View> | |
| </ScrollView> | |
| <FlatList | |
| data={list} | |
| renderItem={({item}) => renderItem(item)} | |
| keyExtractor={item => item.id} | |
| /> | |
| </SafeAreaView> | |
| </> | |
| /*<SafeAreaView style={backgroundStyle}> | |
| <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} /> | |
| <ScrollView | |
| contentInsetAdjustmentBehavior="automatic" | |
| style={backgroundStyle}> | |
| <Header /> | |
| <View | |
| style={{ | |
| backgroundColor: isDarkMode ? Colors.black : Colors.white, | |
| }}> | |
| <Section title="Step One"> | |
| Edit <Text style={styles.highlight}>App.js</Text> to change this | |
| screen and then come back to see your edits. | |
| </Section> | |
| {loading && <Text>Buscando....</Text>} | |
| {/!*<Text>{JSON.stringify(conected)}</Text>*!/} | |
| {device.map((item, i) => ( | |
| <Text key={item.id}>{item.name}</Text> | |
| ))} | |
| </View> | |
| </ScrollView> | |
| </SafeAreaView>*/ | |
| ); | |
| }; | |
| const styles = StyleSheet.create({ | |
| sectionContainer: { | |
| marginTop: 32, | |
| paddingHorizontal: 24, | |
| }, | |
| sectionTitle: { | |
| fontSize: 24, | |
| fontWeight: '600', | |
| }, | |
| sectionDescription: { | |
| marginTop: 8, | |
| fontSize: 18, | |
| fontWeight: '400', | |
| }, | |
| highlight: { | |
| fontWeight: '700', | |
| }, | |
| }); | |
| export default App; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment