diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/App.tsx | 107 | ||||
-rw-r--r-- | src/ble-service.ts | 186 |
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 @@ | |||
1 | import React, {useEffect, useState} from 'react'; | ||
2 | import type {PropsWithChildren} from 'react'; | ||
3 | import { | ||
4 | Button, | ||
5 | FlatList, | ||
6 | SafeAreaView, | ||
7 | ScrollView, | ||
8 | StatusBar, | ||
9 | StyleSheet, | ||
10 | Text, | ||
11 | useColorScheme, | ||
12 | View, | ||
13 | } from 'react-native'; | ||
14 | |||
15 | import Toast from 'react-native-toast-message'; | ||
16 | import BleService, {Peripheral} from './ble-service'; | ||
17 | |||
18 | const bleService = new BleService(); | ||
19 | |||
20 | function 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 | |||
107 | export 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 @@ | |||
1 | import BleManager, { | ||
2 | BleConnectPeripheralEvent, | ||
3 | BleDisconnectPeripheralEvent, | ||
4 | BleManagerDidUpdateValueForCharacteristicEvent, | ||
5 | BleScanCallbackType, | ||
6 | BleScanMatchMode, | ||
7 | BleScanMode, | ||
8 | Peripheral as PeripheralWithoutConnectInfo, | ||
9 | } from 'react-native-ble-manager'; | ||
10 | import { | ||
11 | EmitterSubscription, | ||
12 | NativeEventEmitter, | ||
13 | NativeModules, | ||
14 | PermissionsAndroid, | ||
15 | Platform, | ||
16 | } from 'react-native'; | ||
17 | |||
18 | import Buffer from 'buffer'; | ||
19 | |||
20 | export type Peripheral = PeripheralWithoutConnectInfo & { | ||
21 | connected?: boolean; | ||
22 | connecting?: boolean; | ||
23 | }; | ||
24 | |||
25 | type 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 | |||
42 | export 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 | } | ||