Nous allons voir comment créer une application React Native pour Adnroid permettant la communication BLE (Bluetooth Low Energy) avec un ESP32. Nous utilisons React Native pour développer un terminal BLE sur Android permettant la communication avec un NodeMCU ESP32 ou tout autres appareils compatibles.
Matériel
- Un ordinateur avec installation de React Native et Node.js
- Un appareil Android avec BLE
- Un câble USB pour relier l’ordinateur à l’appareil
- Un appareil BLE (ESP32)
Code de gestion du BLE pour ESP32
Pour tester l’application React Native, nous allons utiliser le code de gestion du BLE pour ESP32.
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleWrite.cpp
Ported to Arduino ESP32 by Evandro Copercini
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
BLECharacteristic *pCharacteristic = NULL;
std::string msg;
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0) {
Serial.println("*********");
Serial.print("New value: ");
for (int i = 0; i < value.length(); i++)
Serial.print(value[i]);
Serial.println();
Serial.println("*********");
}
}
};
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
Serial.println("Client connected");
}
void onDisconnect(BLEServer* pServer) {
Serial.println("Client disconnected");
BLEDevice::startAdvertising(); // needed for reconnection
}
};
void setup() {
Serial.begin(115200);
Serial.println("1- Download and install an BLE Terminal Free");
Serial.println("2- Scan for BLE devices in the app");
Serial.println("3- Connect to ESP32BLE");
Serial.println("4- Go to CUSTOM CHARACTERISTIC in CUSTOM SERVICE and write something");
BLEDevice::init("ESP32BLE");
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->setValue("Hello World");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
pAdvertising->setMinPreferred(0x12);
pAdvertising->start();
Serial.print("Server address:");
Serial.println(BLEDevice::getAddress().toString().c_str());
}
void loop() {
readSerialPort();
//Send data to slave
if(msg!=""){
pCharacteristic->setValue(msg);
msg="";
}
delay(2000);
}
void readSerialPort(){
while (Serial.available()) {
delay(10);
if (Serial.available() >0) {
char c = Serial.read(); //gets one byte from serial buffer
msg += c; //add to String
}
}
Serial.flush(); //clean buffer
}
Nous rajoutons la fonction BLEServerCallbacks à la gestion du Serveur BLE pour détecter la déconnexion et démarrer l’advertising pour pouvoir reconnecter l’ESP32
pServer->setCallbacks(new MyServerCallbacks());
Application React Native pour la gestion du BLE
Pour gérer la communciation BLE (Bluetooth Low Energy) sur l’appareil Android, nous utilisons la librairie react-native-ble-manager
npm install react-native-ble-manager --save
Pour mettre en place le projet de l’application, suivez le tutoriel précédent.
Dans le fichier App.tsx, pour utiliser la bibliothèque nous l’importons à l’aide de la commande
import BleManager from 'react-native-ble-manager';
Nous créons un composant fonctionnel qui contiendra les éléments nous permettant de gérer la communication BLE
let serviceid="4fafc201-1fb5-459e-8fcc-c5c9c331914b";
let caracid="beb5483e-36e1-4688-b7f5-ea07361b26a8";
const BluetoothBLETerminal = () => {
const [devices, setDevices] = useState<any[]>([]);
const [paired, setPaired] = useState<any[]>([]);
const [selectedDevice, setSelectedDevice] = useState<Peripheral>();
const [messageToSend, setMessageToSend] = useState("");
const [receivedMessage, setReceivedMessage] = useState("");
const [isConnected, setIsConnected] = useState(false);
const [intervalId, setIntervalId] = useState<NodeJS.Timer>();
const [isScanning, setIsScanning] = useState(false);
N.B.: il est possible de créer un composant qui dérive de ReactNative.Components
Gestion des permissions
Pour pouvoir découvrir et se connecter à des appareils Bluetooth, il faut 3 permissions au minimum:
- BLUETOOTH_SCAN
- BLUETOOTH_CONNECT
- ACCESS_FINE_LOCATION
N.B.: ces permissions dépendent de la version et de l’OS utilisé
Voici les balises à ajouter dans le fichier AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Dans le fichier App.tsx, nous créons la fonction requestBluetoothPermission()
if (Platform.OS === 'android' && Platform.Version >= 23) {
PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
]).then(result => {
if (
(result['android.permission.BLUETOOTH_SCAN'] &&
result['android.permission.BLUETOOTH_CONNECT'] &&
result['android.permission.ACCESS_FINE_LOCATION'] === 'granted')
||
(result['android.permission.BLUETOOTH_SCAN'] &&
result['android.permission.BLUETOOTH_CONNECT'] &&
result['android.permission.ACCESS_FINE_LOCATION'] === 'never_ask_again')
) {
console.log('User accepted');
} else {
console.log('User refused'); }
});
}
Fonction de gestion du BLE
Les fonctions permettant la gestion du Bluetooth LE sont les suivantes:
- découvrir des appareils bluetooth startDeviceDiscovery() (j’utilise les appareils apairés)
- se connecter à l’appareil connectToDevice()
- se déconnecter disconnectFromDevice()
- envoyer des messages sendMessage()
- lire les messages provenant de la communication readData()
N.B.: Dans cet exemple, nous écrivons et lisons sur la même caractéristique. Nous lisons donc la valeur enregistré avec un appui bouton
const checkBluetoothEnabled = async () => {
try {
// turn on bluetooth if it is not on
BleManager.enableBluetooth().then(() => {
console.log('Bluetooth is turned on!');
});
} catch (error) {
console.error('BLE is not available on this device.');
}
}
const startScan = () => {
if (!isScanning) {
BleManager.scan([], 5, true)
.then(() => {
console.log('Scanning...');
setIsScanning(true);
})
.catch(error => {
console.error(error);
});
}
};
const startDeviceDiscovery = async () => {
BleManager.getBondedPeripherals().then((bondedPeripheralsArray) => {
// Each peripheral in returned array will have id and name properties
console.log("Bonded peripherals: " + bondedPeripheralsArray.length);
setPaired(bondedPeripheralsArray);
});
/*BleManager.getDiscoveredPeripherals().then((peripheralsArray) => {
// Success code
console.log("Discovered peripherals: " + peripheralsArray.length);
});*/
}
const connectToDevice = async (device: Peripheral) => {
BleManager.connect(device.id)
.then(() => {
// Success code
console.log("Connected");
setSelectedDevice(device);
setIsConnected(true);
BleManager.retrieveServices(device.id).then(
(deviceInfo) => {
// Success code
console.log("Device info:", deviceInfo);
}
);
})
.catch((error) => {
// Failure code
console.log(error);
});
}
const sendMessage = async () => {
if(selectedDevice && isConnected){
try {
const buffer = Buffer.from(messageToSend);
BleManager.write(
selectedDevice.id,
serviceid,
caracid,
buffer.toJSON().data
).then(() => {
// Success code
console.log("Write: " + buffer.toJSON().data);
})
.catch((error) => {
// Failure code
console.log(error);
});
} catch (error) {
console.error('Error sending message:', error);
}
}
}
const readData = async () => {
if (selectedDevice && isConnected) {
BleManager.read(
selectedDevice.id,
serviceid,
caracid
)
.then((readData) => {
// Success code
console.log("Read: " + readData);
const message = Buffer.from(readData);
//const sensorData = buffer.readUInt8(1, true);
if(receivedMessage.length>300){
setReceivedMessage(""); //reset received message if length higher than 300
}
setReceivedMessage(receivedMessage => receivedMessage + message +"\n" );
console.log("receivedMessage length",receivedMessage.length)
})
.catch((error) => {
// Failure code
console.log("Error reading message:",error);
});
}
}
// disconnect from device
const disconnectFromDevice = (device: Peripheral) => {
BleManager.disconnect(device.id)
.then(() => {
setSelectedDevice(undefined);
setIsConnected(false);
setReceivedMessage("");
clearInterval(intervalId);
console.log("Disconnected from device");
})
.catch((error) => {
// Failure code
console.log("Error disconnecting:",error);
});
};
La fonction de rendu de l’écran
Pour l’affichage, nous choisissons de tous mettre sur un même écran. Il y aura :
- Un titre
- La liste des appareils qui n’apparait que si on n’est pas connecté (!isConnected &&)
- Un encart type terminal de communication qui n’apparait que si on est connecté (selectedDevice && isConnected &&)
- TextInput pour écrire le message à envoyer messageToSend
- Un bouton d’envoi
- Un bouton de lecture
- Une zone de texte pour afficher receivedMessage
- Un bouton de déconnexion
return (
<View>
<Text
style={{
fontSize: 30,
textAlign: 'center',
borderBottomWidth: 1,
}}>
AC Bluetooth Terminal
</Text>
<ScrollView>
{!isConnected && (
<>
{/*
<Text>Available Devices:</Text>
{devices.map((device) => (
<Button
key={device.id}
title={device.name || 'Unnamed Device'}
onPress={() => this.connectToDevice(device)}
/>
))}
*/}
<Text>Paired Devices:</Text>
{paired.map((pair: BluetoothDevice) => (
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 2,
}}>
<View style={styles.deviceItem}>
<Text style={styles.deviceName}>{pair.name}</Text>
<Text style={styles.deviceInfo}>{pair.id}</Text>
</View>
<TouchableOpacity
onPress={() =>
isConnected
? disconnect()
: connectToDevice(pair)
}
style={styles.deviceButton}>
<Text
style={[
styles.scanButtonText,
{fontWeight: 'bold', fontSize: 12},
]}>
{isConnected ? 'Disconnect' : 'Connect'}
</Text>
</TouchableOpacity>
</View>
))}
</>
)}
{selectedDevice && isConnected && (
<>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
margin: 5,
}}>
<View style={styles.deviceItem}>
<Text style={styles.deviceName}>{selectedDevice.name}</Text>
<Text style={styles.deviceInfo}>{selectedDevice.id}</Text>
</View>
<TouchableOpacity
onPress={() =>
isConnected
? disconnect()
: connectToDevice(selectedDevice)
}
style={styles.deviceButton}>
<Text
style={styles.scanButtonText}>
{isConnected ? 'Disconnect' : 'Connect'}
</Text>
</TouchableOpacity>
</View>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
margin: 5,
}}>
<TextInput
style={{
backgroundColor: '#888888',
margin: 2,
borderRadius: 15,
flex:3,
}}
placeholder="Enter a message"
value={messageToSend}
onChangeText={(text) => setMessageToSend(text )}
/>
<TouchableOpacity
onPress={() => sendMessage()
}
style={[styles.sendButton]}>
<Text
style={[
styles.scanButtonText,
]}>
SEND
</Text>
</TouchableOpacity>
</View>
<Text>Received Message:</Text>
<TextInput
editable = {false}
multiline
numberOfLines={20}
maxLength={100}
style={{
backgroundColor: '#333333',
margin: 10,
borderRadius: 2,
borderWidth: 1,
borderColor: '#EEEEEE',
textAlignVertical: 'top',
}} >
{receivedMessage}
</TextInput>
</>
)}
</ScrollView>
</View>
);
Résultat
Comme l’appairage n’est pas gérer par l’application, il faut appairer l’ESP32 avant l’utilisation de l’application. Une fois le code chargé sur l’ESP32, vous pouvez lancer l’application sur le téléphone à l’aide de la commande
npx react-native start



Code complet de l’application React Native
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* https://github.com/innoveit/react-native-ble-manager
* https://blog.logrocket.com/using-react-native-ble-manager-mobile-app/
*/
import React, {useState, useEffect} from 'react';
import {
StyleSheet,
Dimensions,
View,
ScrollView,
Text,
TextInput,
PermissionsAndroid,
TouchableOpacity,
Platform} from 'react-native';
import BleManager,{Peripheral} from 'react-native-ble-manager';
import { Buffer } from 'buffer';
let serviceid="4fafc201-1fb5-459e-8fcc-c5c9c331914b";
let caracid="beb5483e-36e1-4688-b7f5-ea07361b26a8";
const BluetoothBLETerminal = () => {
const [devices, setDevices] = useState<any[]>([]);
const [paired, setPaired] = useState<any[]>([]);
const [selectedDevice, setSelectedDevice] = useState<Peripheral>();
const [messageToSend, setMessageToSend] = useState("");
const [receivedMessage, setReceivedMessage] = useState("");
const [isConnected, setIsConnected] = useState(false);
const [intervalId, setIntervalId] = useState<NodeJS.Timer>();
const [isScanning, setIsScanning] = useState(false);
const checkBluetoothEnabled = async () => {
try {
// turn on bluetooth if it is not on
BleManager.enableBluetooth().then(() => {
console.log('Bluetooth is turned on!');
});
} catch (error) {
console.error('BLE is not available on this device.');
}
}
const startScan = () => {
if (!isScanning) {
BleManager.scan([], 5, true)
.then(() => {
console.log('Scanning...');
setIsScanning(true);
})
.catch(error => {
console.error(error);
});
}
};
const startDeviceDiscovery = async () => {
BleManager.getBondedPeripherals().then((bondedPeripheralsArray) => {
// Each peripheral in returned array will have id and name properties
console.log("Bonded peripherals: " + bondedPeripheralsArray.length);
setPaired(bondedPeripheralsArray);
});
/*BleManager.getDiscoveredPeripherals().then((peripheralsArray) => {
// Success code
console.log("Discovered peripherals: " + peripheralsArray.length);
});*/
}
const connectToDevice = async (device: Peripheral) => {
BleManager.connect(device.id)
.then(() => {
// Success code
console.log("Connected");
setSelectedDevice(device);
setIsConnected(true);
BleManager.retrieveServices(device.id).then(
(deviceInfo) => {
// Success code
console.log("Device info:", deviceInfo);
}
);
})
.catch((error) => {
// Failure code
console.log(error);
});
}
const sendMessage = async () => {
if(selectedDevice && isConnected){
try {
const buffer = Buffer.from(messageToSend);
BleManager.write(
selectedDevice.id,
serviceid,
caracid,
buffer.toJSON().data
).then(() => {
// Success code
console.log("Write: " + buffer.toJSON().data);
})
.catch((error) => {
// Failure code
console.log(error);
});
} catch (error) {
console.error('Error sending message:', error);
}
}
}
const readData = async () => {
if (selectedDevice && isConnected) {
BleManager.read(
selectedDevice.id,
serviceid,
caracid
)
.then((readData) => {
// Success code
console.log("Read: " + readData);
const message = Buffer.from(readData);
//const sensorData = buffer.readUInt8(1, true);
if(receivedMessage.length>300){
setReceivedMessage("");
}
setReceivedMessage(receivedMessage => receivedMessage + message +"\n" );
console.log("receivedMessage length",receivedMessage.length)
})
.catch((error) => {
// Failure code
console.log("Error reading message:",error);
});
}
}
/*useEffect(() => {
let intervalId: string | number | NodeJS.Timer | undefined;
if (selectedDevice && isConnected) {
intervalId = setInterval(() => readData(), 100);
setIntervalId(intervalId);
}
return () => {
clearInterval(intervalId);
};
}, [isConnected,selectedDevice]);*/
// disconnect from device
const disconnectFromDevice = (device: Peripheral) => {
BleManager.disconnect(device.id)
.then(() => {
setSelectedDevice(undefined);
setIsConnected(false);
setReceivedMessage("");
clearInterval(intervalId);
console.log("Disconnected from device");
})
.catch((error) => {
// Failure code
console.log("Error disconnecting:",error);
});
/*BleManager.removeBond(peripheral.id)
.then(() => {
peripheral.connected = false;
peripherals.set(peripheral.id, peripheral);
setConnectedDevices(Array.from(peripherals.values()));
setDiscoveredDevices(Array.from(peripherals.values()));
Alert.alert(`Disconnected from ${peripheral.name}`);
})
.catch(() => {
console.log('fail to remove the bond');
});*/
};
useEffect(() => {
checkBluetoothEnabled();
if (Platform.OS === 'android' && Platform.Version >= 23) {
PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
]).then(result => {
if (
(result['android.permission.BLUETOOTH_SCAN'] &&
result['android.permission.BLUETOOTH_CONNECT'] &&
result['android.permission.ACCESS_FINE_LOCATION'] === 'granted')
||
(result['android.permission.BLUETOOTH_SCAN'] &&
result['android.permission.BLUETOOTH_CONNECT'] &&
result['android.permission.ACCESS_FINE_LOCATION'] === 'never_ask_again')
) {
console.log('User accepted');
} else {
console.log('User refused'); }
});
}
BleManager.start({showAlert: false}).then(() => {
console.log('BleManager initialized');
startDeviceDiscovery();
}).catch((error) => {
// Failure code
console.log("Error requesting permission:",error);
});
BleManager.checkState().then((state) =>
console.log(`current BLE state = '${state}'.`)
);
BleManager.getConnectedPeripherals([]).then((peripheralsArray) => {
// Success code
console.log("Connected peripherals: " + peripheralsArray.length);
});
BleManager.getBondedPeripherals().then((bondedPeripheralsArray) => {
// Each peripheral in returned array will have id and name properties
console.log("Bonded peripherals: " + bondedPeripheralsArray.length);
//setBoundedDevices(bondedPeripheralsArray);
});
BleManager.getDiscoveredPeripherals().then((peripheralsArray) => {
// Success code
console.log("Discovered peripherals: " + peripheralsArray.length);
});
/*let stopDiscoverListener = BleManagerEmitter.addListener(
'BleManagerDiscoverPeripheral',
peripheral => {
peripherals.set(peripheral.id, peripheral);
},
);*/
/*let stopConnectListener = BleManagerEmitter.addListener(
'BleManagerConnectPeripheral',
peripheral => {
console.log('BleManagerConnectPeripheral:', peripheral);
peripherals.set(peripheral.id, peripheral);
setConnectedDevices(Array.from(peripherals.values()));
},
);*/
/*let stopScanListener = BleManagerEmitter.addListener(
'BleManagerStopScan',
() => {
setIsScanning(false);
console.log('scan stopped');
BleManager.getDiscoveredPeripherals().then((peripheralsArray) => {
// Success code
console.log("Discovered peripherals: " + peripheralsArray.length);
for (let i = 0; i < peripheralsArray.length; i++) {
let peripheral = peripheralsArray[i];
console.log("item:", peripheral);
//peripheral.connected = true;
peripherals.set(peripheral.id, peripheral);
setDiscoveredDevices(peripheralsArray);
}
});
},
);*/
return () => {
/*stopDiscoverListener.remove();
stopConnectListener.remove();
stopScanListener.remove();*/
};
}, [])
return (
<View style={[styles.mainBody]}>
<Text
style={{
fontSize: 30,
textAlign: 'center',
borderBottomWidth: 1,
}}>
AC BLE Terminal
</Text>
<ScrollView>
{!isConnected && (
<>
<TouchableOpacity
onPress={() => startDeviceDiscovery()
}
style={[styles.deviceButton]}>
<Text
style={[
styles.scanButtonText,
]}>
SCAN
</Text>
</TouchableOpacity>
{/*
<Text>Available Devices:</Text>
{devices.map((device) => (
<Button
key={device.id}
title={device.name || 'Unnamed Device'}
onPress={() => this.connectToDevice(device)}
/>
))}
*/}
<Text>Paired Devices:</Text>
{paired.map((pair,i) => (
<View key={i}
style={{
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 2,
}}>
<View style={styles.deviceItem}>
<Text style={styles.deviceName}>{pair.name}</Text>
<Text style={styles.deviceInfo}>{pair.id}, rssi: {pair.rssi}</Text>
</View>
<TouchableOpacity
onPress={() =>
isConnected
? disconnectFromDevice(pair)
: connectToDevice(pair)
}
style={styles.deviceButton}>
<Text
style={[
styles.scanButtonText,
{fontWeight: 'bold', fontSize: 12},
]}>
{isConnected ? 'Disconnect' : 'Connect'}
</Text>
</TouchableOpacity>
</View>
))}
</>
)}
{selectedDevice && isConnected && (
<>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
margin: 5,
}}>
<View style={styles.deviceItem}>
<Text style={styles.deviceName}>{selectedDevice.name}</Text>
<Text style={styles.deviceInfo}>{selectedDevice.id}, rssi: {selectedDevice.rssi}</Text>
</View>
<TouchableOpacity
onPress={() =>
isConnected
? disconnectFromDevice(selectedDevice)
: connectToDevice(selectedDevice)
}
style={styles.deviceButton}>
<Text
style={styles.scanButtonText}>
{isConnected ? 'Disconnect' : 'Connect'}
</Text>
</TouchableOpacity>
</View>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
margin: 5,
}}>
<TextInput
style={{
backgroundColor: '#888888',
margin: 2,
borderRadius: 15,
flex:3,
}}
placeholder="Enter a message"
value={messageToSend}
onChangeText={(text) => setMessageToSend(text)}
/>
<TouchableOpacity
onPress={() => sendMessage()
}
style={[styles.sendButton]}>
<Text
style={[
styles.scanButtonText,
]}>
SEND
</Text>
</TouchableOpacity>
</View>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
margin: 5,
}}>
<Text style={{textAlignVertical: 'center'}}>Received Message:</Text>
<TouchableOpacity
onPress={() => readData()
}
style={[styles.deviceButton]}>
<Text
style={[
styles.scanButtonText,
]}>
READ
</Text>
</TouchableOpacity>
</View>
<TextInput
editable = {false}
multiline
numberOfLines={20}
maxLength={300}
style={{
backgroundColor: '#333333',
margin: 10,
borderRadius: 2,
borderWidth: 1,
borderColor: '#EEEEEE',
textAlignVertical: 'top',
}} >
{receivedMessage}
</TextInput>
</>
)}
</ScrollView>
</View>
);
};//end of component
//https://medium.com/supercharges-mobile-product-guide/reactive-styles-in-react-native-79a41fbdc404
export const theme = {
smallPhone: 0,
phone: 290,
tablet: 750,
}
const windowHeight = Dimensions.get('window').height;
const styles = StyleSheet.create({
mainBody: {
flex: 1,
justifyContent: 'center',
height: windowHeight,
...Platform.select ({
ios: {
fontFamily: "Arial",
},
android: {
fontFamily: "Roboto",
},
}),
},
scanButtonText: {
color: 'white',
fontWeight: 'bold',
fontSize: 12,
textAlign: 'center',
},
noDevicesText: {
textAlign: 'center',
marginTop: 10,
fontStyle: 'italic',
},
deviceItem: {
marginBottom: 2,
},
deviceName: {
fontSize: 14,
fontWeight: 'bold',
},
deviceInfo: {
fontSize: 8,
},
deviceButton: {
backgroundColor: '#2196F3',
padding: 10,
borderRadius: 10,
margin: 2,
paddingHorizontal: 20,
},
sendButton: {
backgroundColor: '#2196F3',
padding: 15,
borderRadius: 15,
margin: 2,
paddingHorizontal: 20,
},
});
export default BluetoothBLETerminal;