Skip to content

Instantly share code, notes, and snippets.

@IgorDePaula
Created September 30, 2025 17:06
Show Gist options
  • Select an option

  • Save IgorDePaula/5dcf8351c28c45a46fe2d618c85cb0f5 to your computer and use it in GitHub Desktop.

Select an option

Save IgorDePaula/5dcf8351c28c45a46fe2d618c85cb0f5 to your computer and use it in GitHub Desktop.
rn bluetooth
/**
* 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