Skip to content

Commit 6a58260

Browse files
author
Ivan Kudinov
committed
CCS-105439 Add bluetooth & nfc methods
1 parent 040cab0 commit 6a58260

File tree

12 files changed

+351
-124
lines changed

12 files changed

+351
-124
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@expressms/smartapp-sdk",
3-
"version": "1.12.0-alpha.5",
3+
"version": "1.12.0-alpha.9",
44
"description": "Smartapp SDK",
55
"main": "build/main/index.js",
66
"typings": "build/main/index.d.ts",

src/index.ts

+11-102
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,12 @@
1-
import Bridge from '@expressms/smartapp-bridge'
2-
import {
3-
cleanCache,
4-
clientStorageClear,
5-
clientStorageGet,
6-
clientStorageRemove,
7-
clientStorageSet,
8-
createDeeplink,
9-
getAppVisibility,
10-
getChats,
11-
getConnectionStatus,
12-
getLayoutType,
13-
getSmartAppList,
14-
getUnreadCounter,
15-
handleDeeplink,
16-
openChatMessage,
17-
openClientSettings,
18-
openGroupChat,
19-
requestLocation,
20-
searchCorporatePhonebook,
21-
searchLocalPhonebook,
22-
sendBotCommand,
23-
subscribeClientEvents,
24-
unsubscribeClientEvents,
25-
} from './lib/client'
26-
import { openFile, uploadFile, uploadFiles } from './lib/client/file'
27-
import {
28-
addContact,
29-
createPersonalChat,
30-
getContact,
31-
openContactCard,
32-
openPersonalChat,
33-
requestSelfProfile,
34-
sendMessage,
35-
} from './lib/contacts'
36-
import { useQuery } from './lib/helpers/helpers'
37-
import { ready } from './lib/logging'
38-
import { onNotification } from './lib/notification'
39-
import {
40-
getCredentials,
41-
runWebCommandsPipeline,
42-
setAllowedNavigationDomains,
43-
setCredentials,
44-
setWebResourceCookies,
45-
} from './lib/proxy'
46-
import {
47-
closeSmartApp,
48-
exitSmartAppToCatalog,
49-
onBackPressed,
50-
onMoveToRoot,
51-
openSmartApp,
52-
routingChanged,
53-
} from './lib/routing'
1+
export * from './lib/client'
2+
export * from './lib/client/file'
3+
export * from './lib/contacts'
4+
export * from './lib/helpers/helpers'
5+
export * from './lib/logging'
6+
export * from './lib/notification'
7+
export * from './lib/routing'
8+
export * from './lib/proxy'
9+
export * from './lib/devices'
5410

55-
export {
56-
Bridge,
57-
ready,
58-
routingChanged,
59-
onBackPressed,
60-
addContact,
61-
getContact,
62-
createPersonalChat,
63-
onNotification,
64-
sendMessage,
65-
openSmartApp,
66-
openFile,
67-
uploadFile,
68-
uploadFiles,
69-
exitSmartAppToCatalog,
70-
useQuery,
71-
openClientSettings,
72-
getChats,
73-
searchCorporatePhonebook,
74-
sendBotCommand,
75-
openGroupChat,
76-
onMoveToRoot,
77-
requestLocation,
78-
openContactCard,
79-
requestSelfProfile,
80-
closeSmartApp,
81-
getAppVisibility,
82-
getConnectionStatus,
83-
subscribeClientEvents,
84-
unsubscribeClientEvents,
85-
createDeeplink,
86-
openChatMessage,
87-
clientStorageGet,
88-
clientStorageSet,
89-
clientStorageRemove,
90-
clientStorageClear,
91-
openPersonalChat,
92-
handleDeeplink,
93-
searchLocalPhonebook,
94-
getUnreadCounter,
95-
getLayoutType,
96-
cleanCache,
97-
getSmartAppList,
98-
setWebResourceCookies,
99-
setAllowedNavigationDomains,
100-
runWebCommandsPipeline,
101-
getCredentials,
102-
setCredentials,
103-
}
11+
import Bridge from '@expressms/smartapp-bridge'
12+
export { Bridge }

src/lib/client/index.ts

-8
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,6 @@ const sendBotCommand = ({
6767
})
6868
}
6969

70-
const requestLocation = () => {
71-
return bridge?.sendClientEvent({
72-
method: METHODS.REQUEST_LOCATION,
73-
params: {},
74-
})
75-
}
76-
7770
/**
7871
* Get client current connection status. It's based on client's WebSocket connection state.
7972
* @returns Promise that'll be fullfilled with status data on success, otherwise rejected with reason
@@ -243,7 +236,6 @@ export {
243236
searchCorporatePhonebook,
244237
openGroupChat,
245238
sendBotCommand,
246-
requestLocation,
247239
getConnectionStatus,
248240
createDeeplink,
249241
openChatMessage,

src/lib/devices/bluetooth.ts

+195
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
import bridge from '@expressms/smartapp-bridge'
2+
import {
3+
BleDeviceCallback,
4+
BluetoothBleDeviceFoundEvent,
5+
BluetoothDiscoverGattServicesResponse,
6+
BluetoothReadBleGattCharacteristicResponse,
7+
BluetoothScanBleDevicesResponse,
8+
BluetoothStatusResponse,
9+
ERROR_CODES,
10+
METHODS,
11+
} from '../../types'
12+
13+
const deviceCallbacks: Array<BleDeviceCallback> = []
14+
15+
/**
16+
* Install bridge event listener for founded devices during scan
17+
*/
18+
const installBridgeEventListener = () => {
19+
if (!bridge) return
20+
21+
bridge.onReceive(event => {
22+
if (event.type !== 'ble_device_found') return
23+
24+
const {
25+
payload: { bleDevice },
26+
} = event as BluetoothBleDeviceFoundEvent
27+
28+
deviceCallbacks.map(cb => cb(bleDevice))
29+
})
30+
}
31+
32+
/**
33+
* Add callback to list
34+
*/
35+
const addDeviceCallback = (callback?: BleDeviceCallback) => {
36+
if (callback) deviceCallbacks.push(callback)
37+
}
38+
39+
/**
40+
* Remove callback from list
41+
*/
42+
const removeDeviceCallback = (callback?: BleDeviceCallback) => {
43+
if (!callback) return
44+
45+
const index = deviceCallbacks.findIndex(cb => cb === callback)
46+
if (index !== -1) deviceCallbacks.splice(index, 1)
47+
}
48+
49+
/**
50+
* Enable bluetooth
51+
* @returns Promise that'll be fullfilled on success, otherwise rejected with reason
52+
*/
53+
export const enable = (): Promise<BluetoothStatusResponse> => {
54+
if (!bridge) return Promise.reject(ERROR_CODES.NO_BRIDGE)
55+
56+
return bridge
57+
.sendClientEvent({
58+
method: METHODS.ENABLE_BLUETOOTH,
59+
params: {},
60+
})
61+
.then(event => event as BluetoothStatusResponse)
62+
}
63+
64+
/**
65+
* Scan BLE devices nearby
66+
* @param scanDuration Duration to scan devices in milliseconds
67+
* @param deviceCallback Callback that triggered on device found
68+
* @returns Promise that'll be fullfilled with `payload.bleDevices` on success, otherwise rejected with reason
69+
*/
70+
export const scanBleDevices = ({
71+
scanDuration,
72+
deviceCallback,
73+
}: {
74+
scanDuration: number
75+
deviceCallback?: BleDeviceCallback
76+
}): Promise<BluetoothScanBleDevicesResponse> => {
77+
if (!bridge) return Promise.reject(ERROR_CODES.NO_BRIDGE)
78+
79+
addDeviceCallback(deviceCallback)
80+
81+
return bridge
82+
.sendClientEvent({
83+
method: METHODS.SCAN_BLE_DEVICES,
84+
params: {
85+
scanDuration,
86+
},
87+
})
88+
.then(event => {
89+
removeDeviceCallback(deviceCallback)
90+
return event as BluetoothScanBleDevicesResponse
91+
})
92+
.catch(() => {
93+
removeDeviceCallback(deviceCallback)
94+
return Promise.reject()
95+
})
96+
}
97+
98+
/**
99+
* Connect bluetooth BLE device
100+
* @param bleDeviceAddress Address of the BLE device
101+
* @returns Promise that'll be fullfilled on success, otherwise rejected with reason
102+
*/
103+
export const connectBleDevice = ({
104+
bleDeviceAddress,
105+
}: {
106+
bleDeviceAddress: string
107+
}): Promise<BluetoothStatusResponse> => {
108+
if (!bridge) return Promise.reject(ERROR_CODES.NO_BRIDGE)
109+
110+
return bridge
111+
.sendClientEvent({
112+
method: METHODS.CONNECT_BLE_DEVICE,
113+
params: {
114+
bleDeviceAddress,
115+
},
116+
})
117+
.then(event => event as BluetoothStatusResponse)
118+
}
119+
120+
/**
121+
* Disonnect bluetooth BLE device
122+
* @param bleDeviceAddress Address of the BLE device
123+
* @returns Promise that'll be fullfilled on success, otherwise rejected with reason
124+
*/
125+
export const disconnectBleDevice = ({
126+
bleDeviceAddress,
127+
}: {
128+
bleDeviceAddress: string
129+
}): Promise<BluetoothStatusResponse> => {
130+
if (!bridge) return Promise.reject(ERROR_CODES.NO_BRIDGE)
131+
132+
return bridge
133+
.sendClientEvent({
134+
method: METHODS.DISCONNECT_BLE_DEVICE,
135+
params: {
136+
bleDeviceAddress,
137+
},
138+
})
139+
.then(event => event as BluetoothStatusResponse)
140+
}
141+
142+
/**
143+
* Discover services and characteristics of the BLE device
144+
* @param bleDeviceAddress Address of the BLE device
145+
* @returns Promise that'll be fullfilled with `payload.gattServices` on success, otherwise rejected with reason
146+
*/
147+
export const discoverGattServices = ({
148+
bleDeviceAddress,
149+
}: {
150+
bleDeviceAddress: string
151+
}): Promise<BluetoothDiscoverGattServicesResponse> => {
152+
if (!bridge) return Promise.reject(ERROR_CODES.NO_BRIDGE)
153+
154+
return bridge
155+
.sendClientEvent({
156+
method: METHODS.DISCOVER_BLE_GATT_SERVICES,
157+
params: {
158+
bleDeviceAddress,
159+
},
160+
})
161+
.then(event => event as BluetoothDiscoverGattServicesResponse)
162+
}
163+
164+
/**
165+
* Read BLE GATT characteristic
166+
* @param bleDeviceAddress Address of the BLE device
167+
* @param gattServiceUuid UUID of the GATT service
168+
* @param gattCharacteristicUuid UUID of the GATT characteristic
169+
* @returns Promise that'll be fullfilled with `payload.value` on success, otherwise rejected with reason
170+
*/
171+
export const readBleGattCharacteristic = ({
172+
bleDeviceAddress,
173+
gattServiceUuid,
174+
gattCharacteristicUuid,
175+
}: {
176+
bleDeviceAddress: string,
177+
gattServiceUuid: string,
178+
gattCharacteristicUuid: string,
179+
}): Promise<BluetoothReadBleGattCharacteristicResponse> => {
180+
if (!bridge) return Promise.reject(ERROR_CODES.NO_BRIDGE)
181+
182+
return bridge
183+
.sendClientEvent({
184+
method: METHODS.READ_BLE_GATT_CHARACTERISTIC,
185+
params: {
186+
bleDeviceAddress,
187+
gattServiceUuid,
188+
gattCharacteristicUuid,
189+
},
190+
})
191+
.then(event => event as BluetoothReadBleGattCharacteristicResponse)
192+
}
193+
194+
// Init device event listener
195+
installBridgeEventListener()

src/lib/devices/gps.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import bridge from '@expressms/smartapp-bridge'
2+
import { METHODS } from '../../types'
3+
4+
/**
5+
* Request GPS position
6+
* @returns Promise that'll be fullfilled with `payload.*` on success, otherwise rejected with reason
7+
*/
8+
export const requestLocation = () => {
9+
return bridge?.sendClientEvent({
10+
method: METHODS.REQUEST_LOCATION,
11+
params: {},
12+
})
13+
}

src/lib/devices/index.ts

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import * as Bluetooth from './bluetooth'
2+
import * as GPS from './gps'
3+
import { requestLocation } from './gps'
4+
import * as NFC from './nfc'
5+
6+
export { Bluetooth, NFC, GPS, requestLocation }

src/lib/devices/nfc.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import bridge from '@expressms/smartapp-bridge'
2+
import {
3+
ERROR_CODES,
4+
METHODS,
5+
NfcReadTagResponse,
6+
} from '../../types'
7+
8+
/**
9+
* Enable bluetooth
10+
* @returns Promise that'll be fullfilled with `payload.nfcTag` on success, otherwise rejected with reason
11+
*/
12+
export const readTag = (): Promise<NfcReadTagResponse> => {
13+
if (!bridge) return Promise.reject(ERROR_CODES.NO_BRIDGE)
14+
15+
return bridge
16+
.sendClientEvent({
17+
method: METHODS.READ_NFC_TAG,
18+
params: {},
19+
})
20+
.then(event => event as NfcReadTagResponse)
21+
}

0 commit comments

Comments
 (0)