Skip to content

evva-sfw/abrevva-capacitor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Abrevva Capacitor Plugin

NPM Version NPM Downloads NPM Unpacked Size (with version) GitHub last commit GitHub branch check runs EVVA License

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 sync

iOS

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   
end

Examples

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 mobileId string 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"

About

Collection of tools to work with electronic EVVA access components - for Ionic development.

Resources

License

Contributing

Stars

Watchers

Forks