Skip to content

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

License

Notifications You must be signed in to change notification settings

evva-sfw/abrevva-capacitor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

58 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

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

  • Capacitor >= 5.0.0
  • Java 17+ (Android)
  • Android SDK (Android)
  • Android 10+ (API level 29) (Android)
  • Xcode 15.4 (iOS)
  • iOS 15.0+ (iOS)

Installation

Capacitor 6

npm install @evva/abrevva-capacitor
npx cap sync

Capacitor 5

npm install @evva/[email protected]
npx cap sync

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 in the form of access media metadata from the Xesar software.

const status = await AbrevvaBLEClient.disengage(
  'deviceId',
  'mobileId',
  'mobileDeviceKey',
  'mobileGroupId',
  'mediumAccessData',
  false,
);

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",
}

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>
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

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; }>