Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/bundler/example/rexml-3.3.6
Browse files Browse the repository at this point in the history
  • Loading branch information
0x7061 authored Aug 26, 2024
2 parents ebd4754 + 079e5a4 commit 3281bc8
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 165 deletions.
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,19 @@ async function scanForBleDevices(androidNeverForLocation: Boolean = true, timeou
With the signalize method you can localize EVVA components. On a successful signalization the component will emit a melody indicating its location.

```typescript
await AbrevvaBle.signalize({ deviceId: 'deviceId' });
const success = await AbrevvaBle.signalize('deviceId');
```
### Perform disengage on EVVA components

For the component disengage you have to provide access credentials to the EVVA component. Those are generally acquired in the form of access media metadata from the Xesar software.

```typescript
const status = await AbrevvaBle.disengage({
deviceId: 'deviceId',
mobileId: 'mobileId',
mobileDeviceKey: 'mobileDeviceKey',
mobileGroupId: 'mobileGroupId',
mobileAccessData: 'mobileAccessData',
isPermanentRelease: false,
});
const status = await AbrevvaBle.disengage(
'deviceId',
'mobileId',
'mobileDeviceKey',
'mobileGroupId',
'mobileAccessData',
false,
);
```
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,13 @@ import java.util.UUID

class AbrevvaBleModule(reactContext: ReactApplicationContext) :
ReactContextBaseJavaModule(reactContext) {
private lateinit var manager: BleManager
private lateinit var aliases: Array<String>
private var manager: BleManager = BleManager(reactContext)
private var aliases: Array<String>

init {
manager = BleManager(reactContext)
aliases = arrayOf()
}

@SuppressLint("MissingPermission")
@ReactMethod
fun signalize(options: ReadableMap, promise: Promise) {
val deviceId = options.getString("deviceId") ?: ""

manager.signalize(deviceId) { success: Boolean ->
if (success) {
promise.resolve("success")
} else {
promise.reject(Exception("signalize() failed"))
}
}
}

@ReactMethod
fun initialize(options: ReadableMap, promise: Promise) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
Expand Down Expand Up @@ -255,7 +240,7 @@ class AbrevvaBleModule(reactContext: ReactApplicationContext) :
ret.putString("value", bytesToString(data!!))
promise.resolve(ret)
} else {
promise.reject("read(): failed to read from device")
promise.reject(Exception("read(): failed to read from device"))
}
},
timeout
Expand All @@ -274,7 +259,7 @@ class AbrevvaBleModule(reactContext: ReactApplicationContext) :

val characteristic =
getCharacteristic(options, promise)
?: return promise.reject("read(): bad characteristic")
?: return promise.reject(Exception("read(): bad characteristic"))
val value =
options.getString("value")
?: return promise.reject(Exception("write(): missing value for write"))
Expand All @@ -295,6 +280,20 @@ class AbrevvaBleModule(reactContext: ReactApplicationContext) :
)
}

@SuppressLint("MissingPermission")
@ReactMethod
fun signalize(options: ReadableMap, promise: Promise) {
val deviceId = options.getString("deviceId") ?: ""

manager.signalize(deviceId) { success: Boolean ->
if (success) {
promise.resolve("success")
} else {
promise.reject(Exception("signalize() failed"))
}
}
}

@ReactMethod
@RequiresPermission(value = "android.permission.BLUETOOTH_CONNECT")
fun disengage(options: ReadableMap, promise: Promise) {
Expand Down Expand Up @@ -449,7 +448,7 @@ class AbrevvaBleModule(reactContext: ReactApplicationContext) :
if (scanRecordBytes != null) {
try {
// Extract EVVA manufacturer-id
var arr = byteArrayOf(0x01)
val arr = byteArrayOf(0x01)
arr.toHexString()
val keyHex = byteArrayOf(scanRecordBytes.getByte(6)!!).toHexString() + byteArrayOf(
scanRecordBytes.getByte(5)!!
Expand Down Expand Up @@ -508,4 +507,4 @@ class AbrevvaBleModule(reactContext: ReactApplicationContext) :
fun removeListeners(type: Int?) {
// Keep: Required for RN built in Event Emitter Calls.
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,9 @@ import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.ReadableMap
import com.hivemq.client.mqtt.mqtt3.Mqtt3AsyncClient.Mqtt3SubscribeAndCallbackBuilder.Call.Ex
import org.bouncycastle.util.encoders.Base64
import org.bouncycastle.util.encoders.Hex
import java.io.BufferedInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.net.URL
import java.nio.file.Paths

Expand Down Expand Up @@ -88,17 +84,17 @@ class AbrevvaCryptoModule(reactContext: ReactApplicationContext) :
try {
val privateKey = options.getString("privateKey")
if (privateKey == null || privateKey == "") {
promise.reject("computeSharedSecret(): invalid private key")
promise.reject(Exception("computeSharedSecret(): invalid private key"))
return
}
val peerPublicKey = options.getString("peerPublicKey")
if (peerPublicKey == null || peerPublicKey == "") {
promise.reject("computeSharedSecret(): invalid peer public key")
promise.reject(Exception("computeSharedSecret(): invalid peer public key"))
return
}
val sharedSecret: ByteArray = X25519Wrapper.computeSharedSecret(
Hex.decode(privateKey),
Hex.decode(peerPublicKey)
Hex.decode(privateKey),
Hex.decode(peerPublicKey)
)

val ret = Arguments.createMap()
Expand Down Expand Up @@ -168,8 +164,8 @@ class AbrevvaCryptoModule(reactContext: ReactApplicationContext) :
promise.reject(e)
}
}
fun writeToFile(ctPath: String, url: String) {

fun writeToFile(ctPath: String, url: String) {
BufferedInputStream(URL(url).openStream()).use { `in` ->
FileOutputStream(ctPath).use { fileOutputStream ->
val dataBuffer = ByteArray(4096)
Expand Down Expand Up @@ -258,4 +254,4 @@ class AbrevvaCryptoModule(reactContext: ReactApplicationContext) :
const val NAME = "AbrevvaCrypto"
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,4 @@ class AbrevvaNfcModule(reactContext: ReactApplicationContext) :
companion object {
const val NAME = "AbrevvaNfc"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ class ExampleAppPackage : ReactPackage {
AbrevvaBleModule(reactContext)
)
}

override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
return emptyList()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import com.evva.xesar.abrevva.ble.BleManager
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.Promise
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.WritableArray
import io.mockk.MockKAnnotations
import io.mockk.every
Expand Down Expand Up @@ -39,9 +38,6 @@ class AbrevvaBleModuleTest {
@MockK(relaxed = true)
private lateinit var promiseMock: Promise

@MockK(relaxed = true)
private lateinit var readableMapMock: ReadableMap

@MockK(relaxed = true)
private lateinit var writeableArrayMock: WritableArray

Expand All @@ -63,7 +59,6 @@ class AbrevvaBleModuleTest {
unmockkAll()
}


/* https://github.com/mockk/mockk/issues/586#issuecomment-1404973825 */
@SuppressLint("MissingPermission")
@Test
Expand Down Expand Up @@ -164,6 +159,7 @@ class AbrevvaBleModuleTest {
val scanResult = WritableMapTestImplementation()
val manufacturerData = WritableMapTestImplementation()
val serviceDataMap = WritableMapTestImplementation()

every { result.data } returns null andThen data
every { result.device } returns device
every { result.device.hasName } returns true
Expand All @@ -190,6 +186,5 @@ class AbrevvaBleModuleTest {
)
)
assert(ref == scanResult)

}
}
41 changes: 19 additions & 22 deletions example/src/BleScreenComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import {
dataViewToNumbers,
hexStringToDataView,
numbersToDataView,
type ReadResult,
type ScanResult,
type StringResult,
} from '@evva-sfw/abrevva-react-native';
import { hex } from '@scure/base';
import { Parser } from 'binary-parser-encoder';
Expand Down Expand Up @@ -186,26 +186,23 @@ async function mobileIdentificationMediumService(data: ScanResult, setStatus: an

try {
await AbrevvaBle.stopLEScan();
await AbrevvaBle.connect({
deviceId: data.device.deviceId,
timeout: 10000,
});
await AbrevvaBle.connect(data.device.deviceId, 10000);

await AbrevvaBle.startNotifications(
data.device.deviceId,
SERVICE,
CHARACTERISTICS.ACCESS_STATUS,
(event: ReadResult) => {
(event: StringResult) => {
newStatus = event.value!;
},
);

const challenge = await AbrevvaBle.read({
deviceId: data.device.deviceId,
service: SERVICE,
characteristic: CHARACTERISTICS.CHALLENGE,
timeout: 10000,
});
const challenge = await AbrevvaBle.read(
data.device.deviceId,
SERVICE,
CHARACTERISTICS.CHALLENGE,
10000,
);

const challengeDataView = hexStringToDataView(challenge.value!);
const challengeBuffer = Buffer.from(dataViewToNumbers(challengeDataView));
Expand Down Expand Up @@ -255,15 +252,15 @@ async function mobileIdentificationMediumService(data: ScanResult, setStatus: an
authTag: authTagBuffer,
});

void AbrevvaBle.write({
deviceId: data.device.deviceId,
service: SERVICE,
characteristic: CHARACTERISTICS.MOBILE_ACCESS_DATA,
value: dataViewToHexString(numbersToDataView(mdf)),
timeout: 1000,
});
void AbrevvaBle.write(
data.device.deviceId,
SERVICE,
CHARACTERISTICS.MOBILE_ACCESS_DATA,
dataViewToHexString(numbersToDataView(mdf)),
1000,
);
} catch (error: any) {
void AbrevvaBle.disconnect({ deviceId: data.device.deviceId });
void AbrevvaBle.disconnect(data.device.deviceId);
serviceIsActive = false;
Alert.alert('Error', error.code, [
{
Expand All @@ -284,7 +281,7 @@ async function mobileIdentificationMediumService(data: ScanResult, setStatus: an
setStatus(() => {
return newStatus;
});
AbrevvaBle.disconnect({ deviceId: data.device.deviceId });
AbrevvaBle.disconnect(data.device.deviceId);
serviceIsActive = false;
resolve();
}
Expand All @@ -300,7 +297,7 @@ async function mobileIdentificationMediumService(data: ScanResult, setStatus: an
text: 'Ok',
},
]);
AbrevvaBle.disconnect({ deviceId: data.device.deviceId });
AbrevvaBle.disconnect(data.device.deviceId);
serviceIsActive = false;
resolve();
}, 20000);
Expand Down
2 changes: 1 addition & 1 deletion ios/ble/AbrevvaBle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ public class AbrevvaBle: RCTEventEmitter {
return
}

let timeout = optionsSwift["timeout"] as? Int ?? nil
let timeout = optionsSwift["timeout"] as? Int ?? 10000

Task {
let success = await self.bleManager!.connect(device, timeout)
Expand Down
35 changes: 13 additions & 22 deletions src/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,44 +111,35 @@ describe('AbrevvaBleModule', () => {
expect(AbrevvaBleMock.stopLEScan).toHaveBeenCalledTimes(1);
});
it('should run connect()', async () => {
await AbrevvaBle.connect({ deviceId: 'deviceId' });
await AbrevvaBle.connect('deviceId');
expect(AbrevvaBleMock.connect).toHaveBeenCalledTimes(1);
});
it('should run disconnect()', async () => {
await AbrevvaBle.disconnect({ deviceId: 'deviceId' });
await AbrevvaBle.disconnect('deviceId');
expect(AbrevvaBleMock.disconnect).toHaveBeenCalledTimes(1);
expect(AbrevvaBleMock.setSupportedEvents).toHaveBeenCalledTimes(1);
});
it('should run read()', async () => {
await AbrevvaBle.read({
deviceId: 'deviceId',
service: 'service',
characteristic: 'characteristic',
});
await AbrevvaBle.read('deviceId', 'service', 'characteristic');
expect(AbrevvaBleMock.read).toHaveBeenCalledTimes(1);
});
it('should run write()', async () => {
await AbrevvaBle.write({
deviceId: 'deviceId',
service: 'service',
characteristic: 'characteristic',
value: 'value',
});
await AbrevvaBle.write('deviceId', 'service', 'characteristic', 'value');
expect(AbrevvaBleMock.write).toHaveBeenCalledTimes(1);
});
it('should run signalize()', async () => {
await AbrevvaBle.signalize({ deviceId: 'deviceId' });
await AbrevvaBle.signalize('deviceId');
expect(AbrevvaBleMock.signalize).toHaveBeenCalledTimes(1);
});
it('should run disengage()', async () => {
await AbrevvaBle.disengage({
deviceId: 'deviceId',
mobileId: 'mobileId',
mobileDeviceKey: 'mobileDeviceKey',
mobileGroupId: 'mobileGroupId',
mobileAccessData: 'mobileAccessData',
isPermanentRelease: false,
});
await AbrevvaBle.disengage(
'deviceId',
'mobileId',
'mobileDeviceKey',
'mobileGroupId',
'mobileAccessData',
false,
);
expect(AbrevvaBleMock.disengage).toHaveBeenCalledTimes(1);
});
describe('startNotifications()', () => {});
Expand Down
Loading

0 comments on commit 3281bc8

Please sign in to comment.