@evva/abrevva-capacitor
v6.1.1
Published
Collection of tools to work with electronic EVVA access components.
Readme
Abrevva Capacitor Plugin
The EVVA Abrevva Capacitor Plugin is a collection of tools to work with electronical EVVA access components. It allows for scanning and connecting via BLE.
Features
- BLE Scanner for EVVA components
- Localize scanned EVVA components
- Disengage scanned EVVA components
- Read / Write data via BLE
Requirements
| Platform | Version | |-------------|---------| | Capacitor | 7+ | | Java | 17+ | | Android | 11+ | | Android API | 30+ | | Kotlin | 2.x | | iOS | 16.0+ | | Xcode | 15.3+ | | Swift | 5.10+ |
Installation
Capacitor 7
npm install @evva/abrevva-capacitor
npx cap synciOS
In your app add a post_install hook in your Podfile to resolve a nasty CocoaPods limitation with XCFrameworks.
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
end
end
endExamples
Initialize and scan for EVVA components
import { AbrevvaBLEClient, BleDevice } from "@evva/abrevva-capacitor";
class ExampleClass {
private devices: BleDevice[];
async startScan(event: any) {
this.devices = [];
await AbrevvaBLEClient.initialize()
await AbrevvaBLEClient.startScan({ timeout: 5_000 }, (device: BleDevice) => {
this.devices.push(device);
}, (success: boolean) => {
console.log(`Scan started, success: ${success}`);
}, (success: boolean) => {
console.log(`Scan stopped, success: ${success}`);
});
}
}Read EVVA component advertisement
Get the EVVA advertisement data from a scanned EVVA component.
const ad = device.advertisementData
console.log(ad?.rssi)
console.log(ad?.isConnectable)
const md = ad?.manufacturerData
console.log(md?.batteryStatus)
console.log(md?.isOnline)
console.log(md?.officeModeEnabled)
console.log(md?.officeModeActive)
// ...There are several properties that can be accessed from the advertisement.
export interface BleDeviceAdvertisementData {
rssi?: number;
isConnectable?: boolean;
manufacturerData?: BleDeviceManufacturerData;
}
export interface BleDeviceManufacturerData {
companyIdentifier?: string;
version?: number;
componentType?: "handle" | "escutcheon" | "cylinder" | "wallreader" | "emzy" | "iobox" | "unknown";
mainFirmwareVersionMajor?: number;
mainFirmwareVersionMinor?: number;
mainFirmwareVersionPatch?: number;
componentHAL?: string;
batteryStatus?: "battery-full" | "battery-empty";
mainConstructionMode?: boolean;
subConstructionMode?: boolean;
isOnline?: boolean;
officeModeEnabled?: boolean;
twoFactorRequired?: boolean;
officeModeActive?: boolean;
identifier?: string;
subFirmwareVersionMajor?: number;
subFirmwareVersionMinor?: number;
subFirmwareVersionPatch?: number;
subComponentIdentifier?: string;
}Localize EVVA component
With the signalize method you can localize scanned EVVA components. On a successful signalization the component will emit a melody indicating its location.
const success = await AbrevvaBLEClient.signalize('deviceId');Disengage EVVA components
For the component disengage you have to provide access credentials to the EVVA component. Those are generally acquired from the Xesar software.
Note: Since 6.1.0 the
mobileIdstring can be passed as is, without sha256 hashing the input first.
const result = await AbrevvaBLEClient.disengageWithXvnResponse(
'deviceId',
'mobileId', // `xsMobileId` string from medium blob data
'mobileDeviceKey', // `xsMOBDK` string from medium blob data
'mobileGroupId', // `xsMOBGID` string from medium blob data
'mediumAccessData', // `mediumDataFrame` string from medium blob data
false, // office mode flag
);
console.log(`status=${result.status} xvnData=${result.xvnData}`)There are several access status types upon attempting the component disengage.
export enum DisengageStatusType {
/// Component
Authorized = "AUTHORIZED",
AuthorizedPermanentEngage = "AUTHORIZED_PERMANENT_ENGAGE",
AuthorizedPermanentDisengage = "AUTHORIZED_PERMANENT_DISENGAGE",
AuthorizedBatteryLow = "AUTHORIZED_BATTERY_LOW",
AuthorizedOffline = "AUTHORIZED_OFFLINE",
Unauthorized = "UNAUTHORIZED",
UnauthorizedOffline = "UNAUTHORIZED_OFFLINE",
SignalLocalization = "SIGNAL_LOCALIZATION",
MediumDefectOnline = "MEDIUM_DEFECT_ONLINE",
MediumBlacklisted = "MEDIUM_BLACKLISTED",
Error = "ERROR",
/// Interface
UnableToConnect = "UNABLE_TO_CONNECT",
UnableToSetNotifications = "UNABLE_TO_SET_NOTIFICATIONS",
UnableToReadChallenge = "UNABLE_TO_READ_CHALLENGE",
UnableToWriteMDF = "UNABLE_TO_WRITE_MDF",
AccessCipherError = "ACCESS_CIPHER_ERROR",
BleAdapterDisabled = "BLE_ADAPTER_DISABLED",
UnknownDevice = "UNKNOWN_DEVICE",
UnknownStatusCode = "UNKNOWN_STATUS_CODE",
Timeout = "TIMEOUT",
}Coding Identification Media
Use the CodingStation to write or update access data onto an EVVA identification medium.
import { AbrevvaCodingStation } from "@evva/abrevva-capacitor";
export class ExampleClass {
async writeMedium() {
try {
await AbrevvaCodingStation.register({
url: "url",
clientId: "clientId",
username: "username",
password: "password",
});
await AbrevvaCodingStation.connect();
await AbrevvaCodingStation.write();
await AbrevvaCodingStation.disconnect();
} catch (e) {
console.log(`Failed to write medium: ${e}`);
}
}
}API
Interfaces
AbrevvaBLEInterface
| Method | Signature | | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | initialize | (options?: InitializeOptions | undefined) => Promise<void> | | isEnabled | () => Promise<BooleanResult> | | isLocationEnabled | () => Promise<BooleanResult> | | startEnabledNotifications | () => Promise<void> | | stopEnabledNotifications | () => Promise<void> | | openLocationSettings | () => Promise<void> | | openBluetoothSettings | () => Promise<void> | | openAppSettings | () => Promise<void> | | startScan | (options?: BleScannerOptions | undefined) => Promise<void> | | stopScan | () => Promise<void> | | addListener | (eventName: "onEnabledChanged", listenerFunc: (result: BooleanResult) => void) => PluginListenerHandle | | addListener | (eventName: string, listenerFunc: (event: ReadResult) => void) => PluginListenerHandle | | addListener | (eventName: "onScanResult", listenerFunc: (result: BleDevice) => void) => PluginListenerHandle | | addListener | (eventName: "onScanStart", listenerFunc: (success: BooleanResult) => void) => PluginListenerHandle | | addListener | (eventName: "onScanStop", listenerFunc: (success: BooleanResult) => void) => PluginListenerHandle | | connect | (options: DeviceIdOptions & TimeoutOptions) => Promise<void> | | disconnect | (options: DeviceIdOptions) => Promise<void> | | read | (options: ReadOptions & TimeoutOptions) => Promise<ReadResult> | | write | (options: WriteOptions & TimeoutOptions) => Promise<void> | | signalize | (options: SignalizeOptions) => Promise<void> | | disengage | (options: DisengageOptions) => Promise<StringResult> | | disengageWithXvnResponse | (options: DisengageOptions) => Promise<DisengageResult> | | startNotifications | (options: ReadOptions) => Promise<void> | | stopNotifications | (options: ReadOptions) => Promise<void> |
InitializeOptions
| Prop | Type |
| ----------------------------- | -------------------- |
| androidNeverForLocation | boolean |
BooleanResult
| Prop | Type |
| ----------- | -------------------- |
| value | boolean |
BleScannerOptions
| Prop | Type |
| --------------------- | -------------------- |
| macFilter | string |
| allowDuplicates | boolean |
| timeout | number |
PluginListenerHandle
| Prop | Type |
| ------------ | ----------------------------------------- |
| remove | () => Promise<void> |
ReadResult
| Prop | Type |
| ----------- | ------------------- |
| value | string |
BleDevice
| Prop | Type |
| ----------------------- | --------------------------------------------------------------------------------- |
| deviceId | string |
| name | string |
| advertisementData | BleDeviceAdvertisementData |
BleDeviceAdvertisementData
| Prop | Type |
| ---------------------- | ------------------------------------------------------------------------------- |
| rssi | number |
| isConnectable | boolean |
| manufacturerData | BleDeviceManufacturerData |
BleDeviceManufacturerData
| Prop | Type |
| ------------------------------ | ----------------------------------------------------------------------------------------------------- |
| companyIdentifier | string |
| version | number |
| componentType | 'handle' | 'escutcheon' | 'cylinder' | 'wallreader' | 'emzy' | 'iobox' | 'unknown' |
| mainFirmwareVersionMajor | number |
| mainFirmwareVersionMinor | number |
| mainFirmwareVersionPatch | number |
| componentHAL | string |
| batteryStatus | 'battery-full' | 'battery-empty' |
| mainConstructionMode | boolean |
| subConstructionMode | boolean |
| isOnline | boolean |
| officeModeEnabled | boolean |
| twoFactorRequired | boolean |
| officeModeActive | boolean |
| identifier | string |
| subFirmwareVersionMajor | number |
| subFirmwareVersionMinor | number |
| subFirmwareVersionPatch | number |
| subComponentIdentifier | string |
DeviceIdOptions
| Prop | Type |
| -------------- | ------------------- |
| deviceId | string |
TimeoutOptions
| Prop | Type |
| ------------- | ------------------- |
| timeout | number |
ReadOptions
| Prop | Type |
| -------------------- | ------------------- |
| deviceId | string |
| service | string |
| characteristic | string |
WriteOptions
| Prop | Type |
| -------------------- | ------------------- |
| deviceId | string |
| service | string |
| characteristic | string |
| value | string |
SignalizeOptions
| Prop | Type |
| -------------- | ------------------- |
| deviceId | string |
StringResult
| Prop | Type |
| ----------- | ------------------- |
| value | string |
DisengageOptions
| Prop | Type |
| ------------------------ | -------------------- |
| deviceId | string |
| mobileId | string |
| mobileDeviceKey | string |
| mobileGroupId | string |
| mediumAccessData | string |
| isPermanentRelease | boolean |
DisengageResult
| Prop | Type |
| ------------- | ------------------------------------------------------------------- |
| status | DisengageStatusType |
| xvnData | string |
AbrevvaCryptoInterface
| Method | Signature | | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | encrypt | (options: { key: string; iv: string; adata: string; pt: string; tagLength: number; }) => Promise<{ cipherText: string; authTag: string; }> | | encryptFile | (options: { sharedSecret: string; ptPath: string; ctPath: string; }) => Promise<void> | | decrypt | (options: { key: string; iv: string; adata: string; ct: string; tagLength: number; }) => Promise<{ plainText: string; authOk: boolean; }> | | decryptFile | (options: { sharedSecret: string; ctPath: string; ptPath: string; }) => Promise<void> | | decryptFileFromURL | (options: { sharedSecret: string; url: string; ptPath: string; }) => Promise<void> | | generateKeyPair | () => Promise<{ privateKey: string; publicKey: string; }> | | computeSharedSecret | (options: { privateKey: string; peerPublicKey: string; }) => Promise<{ sharedSecret: string; }> | | computeED25519PublicKey | (options: { privateKey: string; }) => Promise<{ publicKey: string; }> | | sign | (options: { privateKey: string; data: string; }) => Promise<{ signature: string; }> | | verify | (options: { publicKey: string; data: string; signature: string; }) => Promise<void> | | random | (options: { numBytes: number; }) => Promise<{ value: string; }> | | derive | (options: { key: string; salt: string; info: string; length: number; }) => Promise<{ value: string; }> |
AbrevvaCodingStationInterface
| Method | Signature | | -------------- | ------------------------------------------------------------------------------------------- | | register | (options: CSConnectionOptions) => Promise<void> | | connect | () => Promise<void> | | disconnect | () => Promise<void> | | write | () => Promise<void> |
CSConnectionOptions
| Prop | Type |
| -------------- | ------------------- |
| url | string |
| clientId | string |
| username | string |
| password | string |
Enums
DisengageStatusType
| Members | Value |
| ---------------------------------- | --------------------------------------------- |
| Authorized | "AUTHORIZED" |
| AuthorizedPermanentEngage | "AUTHORIZED_PERMANENT_ENGAGE" |
| AuthorizedPermanentDisengage | "AUTHORIZED_PERMANENT_DISENGAGE" |
| AuthorizedBatteryLow | "AUTHORIZED_BATTERY_LOW" |
| AuthorizedOffline | "AUTHORIZED_OFFLINE" |
| Unauthorized | "UNAUTHORIZED" |
| UnauthorizedOffline | "UNAUTHORIZED_OFFLINE" |
| SignalLocalization | "SIGNAL_LOCALIZATION" |
| MediumDefectOnline | "MEDIUM_DEFECT_ONLINE" |
| MediumBlacklisted | "MEDIUM_BLACKLISTED" |
| Error | "ERROR" |
| UnableToConnect | "UNABLE_TO_CONNECT" |
| UnableToSetNotifications | "UNABLE_TO_SET_NOTIFICATIONS" |
| UnableToReadChallenge | "UNABLE_TO_READ_CHALLENGE" |
| UnableToWriteMDF | "UNABLE_TO_WRITE_MDF" |
| AccessCipherError | "ACCESS_CIPHER_ERROR" |
| BleAdapterDisabled | "BLE_ADAPTER_DISABLED" |
| UnknownDevice | "UNKNOWN_DEVICE" |
| UnknownStatusCode | "UNKNOWN_STATUS_CODE" |
| Timeout | "TIMEOUT" |
