summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/App.tsx107
-rw-r--r--src/ble-service.ts186
2 files changed, 293 insertions, 0 deletions
diff --git a/src/App.tsx b/src/App.tsx
new file mode 100644
index 0000000..7972da9
--- /dev/null
+++ b/src/App.tsx
@@ -0,0 +1,107 @@
1import React, {useEffect, useState} from 'react';
2import type {PropsWithChildren} from 'react';
3import {
4 Button,
5 FlatList,
6 SafeAreaView,
7 ScrollView,
8 StatusBar,
9 StyleSheet,
10 Text,
11 useColorScheme,
12 View,
13} from 'react-native';
14
15import Toast from 'react-native-toast-message';
16import BleService, {Peripheral} from './ble-service';
17
18const bleService = new BleService();
19
20function App(): React.JSX.Element {
21 bleService: BleService;
22
23 const [isScanning, setIsScanning] = useState<boolean>(false);
24 const [peripherals, setPeripherals] = useState<
25 Map<Peripheral['id'], Peripheral>
26 >([]);
27
28 useEffect(() => {
29 bleService.setEvents({
30 bleManagerConnectPeripheral: e => console.log(e.peripheral),
31 bleManagerStartSuccess: () => {
32 Toast.show({
33 type: 'info',
34 text1: 'BleManager started..',
35 });
36 },
37 bleManagerDiscoverPeripheral: p => {
38 console.log(p.advertising.localName);
39 },
40 bleManagerStopScan: () => {
41 setIsScanning(false);
42 setPeripherals(bleService.getPeripherals());
43
44 console.log('scan: stop;');
45 Toast.show({
46 type: 'success',
47 text1: 'Scan stop..',
48 position: 'bottom',
49 });
50 },
51 bleManagerStartScan: () => {
52 setIsScanning(true);
53 console.log('scan: start;');
54 Toast.show({
55 type: 'info',
56 text1: 'Scan start..',
57 position: 'bottom',
58 });
59 },
60 bleManagerDidUpdateValueForCharacteristic: a => {
61 console.log(a.value);
62 },
63 });
64
65 return () => bleService.destroy();
66 });
67
68 return (
69 <>
70 <Toast />
71 <View>
72 <Text>Hello, World!!!!</Text>
73 {isScanning ? <Text>SKANUJE!</Text> : <Text>Juz nie</Text>}
74 <Button
75 onPress={() => {
76 bleService.scan();
77 }}
78 title="Scan!"
79 />
80 <FlatList
81 data={[...peripherals.values()]}
82 renderItem={({item}) => (
83 <>
84 <Text>id: {item.id}</Text>
85 <Text>name: {item.name}</Text>
86 <Button
87 onPress={() => {
88 bleService.connect(item);
89 }}
90 title="Connect!"
91 />
92 <Button
93 onPress={() => {
94 console.log(bleService.read(item));
95 }}
96 title="Read!"
97 />
98 <Text>-------</Text>
99 </>
100 )}
101 />
102 </View>
103 </>
104 );
105}
106
107export default App;
diff --git a/src/ble-service.ts b/src/ble-service.ts
new file mode 100644
index 0000000..f2a08a3
--- /dev/null
+++ b/src/ble-service.ts
@@ -0,0 +1,186 @@
1import BleManager, {
2 BleConnectPeripheralEvent,
3 BleDisconnectPeripheralEvent,
4 BleManagerDidUpdateValueForCharacteristicEvent,
5 BleScanCallbackType,
6 BleScanMatchMode,
7 BleScanMode,
8 Peripheral as PeripheralWithoutConnectInfo,
9} from 'react-native-ble-manager';
10import {
11 EmitterSubscription,
12 NativeEventEmitter,
13 NativeModules,
14 PermissionsAndroid,
15 Platform,
16} from 'react-native';
17
18import Buffer from 'buffer';
19
20export type Peripheral = PeripheralWithoutConnectInfo & {
21 connected?: boolean;
22 connecting?: boolean;
23};
24
25type Events = {
26 bleManagerStartSuccess: () => void | undefined;
27 bleManagerStartError: () => void | undefined;
28 bleManagerStopScan: () => void | undefined;
29 bleManagerStartScan: () => void | undefined;
30 bleManagerDiscoverPeripheral: (peripheral: Peripheral) => void | undefined;
31 bleManagerDisconnectPeripheral: (
32 event: BleDisconnectPeripheralEvent,
33 ) => void | undefined;
34 bleManagerDidUpdateValueForCharacteristic: (
35 event: BleManagerDidUpdateValueForCharacteristicEvent,
36 ) => void | undefined;
37 bleManagerConnectPeripheral: (
38 event: BleConnectPeripheralEvent,
39 ) => void | undefined;
40};
41
42export default class BleService {
43 private _bleManagerModule = NativeModules.BleManager;
44 private _bleManagerEmitter = new NativeEventEmitter(this._bleManagerModule);
45 private _events: Events;
46 private _listeners: EmitterSubscription[];
47 private _peripherals: Map<Peripheral['id'], Peripheral>;
48
49 constructor() {
50 this._listeners = [];
51 this._events = {};
52 this._peripherals = new Map();
53 BleManager.start({showAlert: false})
54 .then(() => {
55 this.runEvent(this._events.bleManagerStartSuccess);
56 console.debug('[BleService]: BleManager started.');
57 })
58 .catch((err: any) => {
59 this.runEvent(this._events.bleManagerStartError);
60 console.debug('[BleService]: BeManager could not be started.', err);
61 });
62 this.handle_permissions();
63 }
64
65 setEvents(events: Events) {
66 this._events = events;
67 this.setupListiners(events);
68 }
69
70 handle_permissions() {
71 // po requestach, jak sie zrobi .then() nastepnie gdy (resoult) cos zwroci to oznacza, że ma perma jak nie to nie ma.
72 if (Platform.OS === 'android') {
73 if (Platform.Version >= 31)
74 PermissionsAndroid.requestMultiple([
75 PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
76 PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
77 ]);
78 else if (Platform.Version >= 23)
79 PermissionsAndroid.request(
80 PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
81 );
82 }
83 }
84
85 scan() {
86 this.runEvent(this._events.bleManagerStartScan);
87 this.clearPeripherals();
88 BleManager.scan([], 3, false, {
89 matchMode: BleScanMatchMode.Sticky,
90 scanMode: BleScanMode.LowLatency,
91 callbackType: BleScanCallbackType.AllMatches,
92 })
93 .then(() => {
94 console.debug('[startScan] scan promise returned successfully.');
95 })
96 .catch((err: any) => {
97 console.error('[startScan] ble scan returned in error', err);
98 });
99 }
100
101 destroy() {
102 this.destroyListiners();
103 }
104
105 getPeripherals() {
106 return this._peripherals;
107 }
108
109 connect(p: Peripheral) {
110 return BleManager.connect(p.id);
111 }
112
113 async read(peripheral: Peripheral) {
114 await BleManager.requestMTU(peripheral.id, 512);
115 BleManager.startNotification(
116 peripheral.id,
117 '6e400001-b5a3-f393-e0a9-e50e24dcca9e',
118 '6e400003-b5a3-f393-e0a9-e50e24dcca9e',
119 )
120 .then(a => {
121 // Success code
122 console.log('--------');
123 console.log(a);
124 console.log('--------');
125 })
126 .catch(error => {
127 // Failure code
128 console.log(error);
129 });
130 }
131
132 private addPeripheral(p: Peripheral) {
133 this._peripherals.set(p.id, p);
134 }
135
136 private clearPeripherals() {
137 this._peripherals = new Map();
138 }
139
140 private destroyListiners() {
141 for (const listener of this._listeners) {
142 if (listener) listener.remove();
143 }
144 }
145
146 private setupListiners(events: Events) {
147 this.destroyListiners();
148 this._listeners = [
149 this._bleManagerEmitter.addListener(
150 'BleManagerDiscoverPeripheral',
151 peripheral => {
152 this.addPeripheral(peripheral);
153 this.runEvent(events.bleManagerDiscoverPeripheral, peripheral);
154 },
155 ),
156 this._bleManagerEmitter.addListener('BleManagerStopScan', () =>
157 this.runEvent(events.bleManagerStopScan),
158 ),
159 this._bleManagerEmitter.addListener(
160 'BleManagerDisconnectPeripheral',
161 event => this.runEvent(events.bleManagerDisconnectPeripheral, event),
162 ),
163 this._bleManagerEmitter.addListener(
164 'BleManagerDidUpdateValueForCharacteristic',
165 event =>
166 this.runEvent(
167 events.bleManagerDidUpdateValueForCharacteristic,
168 event,
169 ),
170 ),
171 this._bleManagerEmitter.addListener(
172 'BleManagerConnectPeripheral',
173 event => this.runEvent(events.bleManagerConnectPeripheral, event),
174 ),
175 ];
176 }
177
178 private runEvent(
179 event: CallableFunction | undefined,
180 ...optionalParams: any[]
181 ): void {
182 if (event) {
183 event(...optionalParams);
184 }
185 }
186}