Origo SDK

Flutter plugin for Origo SDK integration, providing mobile key functionality for access control systems including endpoint setup, reader scanning, and lock management.

Features

  • Initialize Origo SDK with service codes and app credentials
  • Set up endpoints using 16-digit activation codes
  • Scan for and connect to nearby readers
  • Open the closest available reader
  • Update endpoint configurations
  • Debug logging and log retrieval
  • Cross-platform support (Android & iOS)

Installation

Add this to your package's pubspec.yaml file:

dependencies:
  origo_sdk: ^0.1.2

Then run:

flutter pub get

Platform Configuration

Android

Add the following permissions to your android/app/src/main/AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Required for Bluetooth communication -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    
    <!-- Required for Android 12+ Bluetooth permissions -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    
    <!-- Required for file operations (SDK versions ≤ 32) -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
    
    <!-- Required for notifications -->
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    
    <!-- Required for network operations -->
    <uses-permission android:name="android.permission.INTERNET"/>

    <application>
        <!-- Your app configuration -->
    </application>
</manifest>

Local Repository Setup (Required)

The Origo SDK uses a local Maven repository to distribute the native Android SDK. You must replicate this repository structure in your project to consume the SDK properly.

Step 1: Create the repository directory structure

Create the following directory structure in your Android project root (same level as your app folder):

your_flutter_project/
├── android/
│   ├── app/
│   └── repo/
│       └── com/
│           └── example/
│               └── origo/
│                   └── 3.4.0/
│                       ├── origo-3.4.0.aar
│                       └── origo-3.4.0.pom

Step 2: Copy the required files

Copy the following files from the Origo SDK plugin to your project:

  1. AAR file: Copy origo-3.4.0.aar from the plugin's android/repo/com/example/origo/3.4.0/ directory to your android/repo/com/example/origo/3.4.0/ directory

  2. POM file: Copy origo-3.4.0.pom from the plugin's android/repo/com/example/origo/3.4.0/ directory to your android/repo/com/example/origo/3.4.0/ directory

iOS

Add the following keys to your ios/Runner/Info.plist:

<!-- Location permissions required by OrigoSDK -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app uses location services to detect nearby readers for secure access.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app uses location services to detect nearby readers for secure access, even when the app is in the background.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app uses location services to detect nearby readers for secure access, even when the app is in the background.</string>

<!-- Bluetooth permissions required by OrigoSDK -->
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app uses Bluetooth to communicate with secure readers.</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app uses Bluetooth to communicate with secure readers.</string>

<!-- Background modes for location and Bluetooth -->
<key>UIBackgroundModes</key>
<array>
    <string>location</string>
    <string>bluetooth-central</string>
    <string>bluetooth-peripheral</string>
    <string>background-processing</string>
</array>

Usage

Basic Setup

import 'package:origo_sdk/origo_sdk.dart';
import 'package:flutter/services.dart';

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _origoSdk = OrigoSdk();
  bool _isInitialized = false;

  @override
  void initState() {
    super.initState();
    _initializeSDK();
  }

  Future<void> _initializeSDK() async {
    try {
      final isInitialized = await _origoSdk.initialize(
        'YOUR_ORIGO_LOCK_SERVICE_CODE',
        'YOUR_ORIGO_APP_ID',
        'YOUR_ORIGO_APP_ID_DESCRIPTION',
      );
      
      setState(() {
        _isInitialized = isInitialized;
      });
      
      if (isInitialized) {
        // Perform application startup
        final startupResult = await _origoSdk.applicationStartup();
        print('Startup result: $startupResult');
      }
    } on PlatformException catch (e) {
      print('Failed to initialize SDK: ${e.message}');
    }
  }

  Future<void> _setupEndpoint() async {
    try {
      final result = await _origoSdk.endpointSetup('YOUR_16_DIGIT_CODE');
      print('Endpoint setup result: $result');
    } on PlatformException catch (e) {
      print('Failed to setup endpoint: ${e.message}');
    }
  }

  Future<void> _startScanning() async {
    try {
      final result = await _origoSdk.startScan();
      print('Scan started: $result');
    } on PlatformException catch (e) {
      print('Failed to start scan: ${e.message}');
    }
  }

  Future<void> _openClosestReader() async {
    try {
      final result = await _origoSdk.openClosestReader();
      print('Open reader result: $result');
    } on PlatformException catch (e) {
      print('Failed to open reader: ${e.message}');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Origo SDK Example')),
        body: Padding(
          padding: EdgeInsets.all(16.0),
          child: Column(
            children: [
              Text('SDK Initialized: $_isInitialized'),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: _isInitialized ? _setupEndpoint : null,
                child: Text('Setup Endpoint'),
              ),
              ElevatedButton(
                onPressed: _isInitialized ? _startScanning : null,
                child: Text('Start Scanning'),
              ),
              ElevatedButton(
                onPressed: _isInitialized ? _openClosestReader : null,
                child: Text('Open Closest Reader'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Available Methods

Core Methods

  • initialize(String origoLockServiceCode, String origoAppId, String origoAppIdDescription) - Initialize the SDK
  • applicationStartup() - Perform application startup sequence
  • getEndpointSetupStatus() - Get current endpoint setup status
  • endpointSetup(String sixteenDigitCode) - Setup endpoint with activation code
  • endpointUpdate() - Update endpoint configuration

Reader Operations

  • startScan() - Start scanning for nearby readers
  • stopScan() - Stop scanning for readers
  • openClosestReader() - Open the closest available reader

Debugging

  • toggleLogging() - Toggle debug logging on/off
  • getLogs() - Retrieve debug logs

Permission Handling

⚠️ Important: The Origo SDK only checks if permissions are granted but does not request them. Your client application must handle permission requests before calling SDK methods that require them.

Required Permissions

Android:

  • BLUETOOTH_SCAN - Required for scanning nearby readers
  • BLUETOOTH_CONNECT - Required for connecting to readers
  • BLUETOOTH_ADVERTISE - Required for advertising capabilities
  • ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION - Required for Bluetooth scanning on Android versions < 12

iOS:

  • Bluetooth permissions - Required for reader communication
  • Location permissions (when in use) - Required for reader detection

Implementation

Use packages like permission_handler to request permissions before calling SDK methods:

dependencies:
  permission_handler: ^11.3.1
  origo_sdk: ^0.1.2
import 'package:permission_handler.dart';

Future<void> _startScanning() async {
  // Request permissions before scanning
  Map<Permission, PermissionStatus> statuses = await [
    Permission.bluetoothScan,
    Permission.bluetoothConnect,
    Permission.bluetoothAdvertise,
    Permission.locationWhenInUse,
  ].request();

  bool allGranted = statuses.values.every(
    (status) => status == PermissionStatus.granted
  );

  if (!allGranted) {
    // Handle permission denial - guide user to settings if needed
    if (statuses.values.any((status) => status == PermissionStatus.permanentlyDenied)) {
      await openAppSettings();
    }
    return;
  }

  try {
    final result = await _origoSdk.startScan();
    print('Scan started: $result');
  } on PlatformException catch (e) {
    if (e.code == 'SCAN_ERROR' && e.message?.contains('permissions') == true) {
      // Permission was revoked, request again
      print('Permissions not granted: ${e.message}');
    }
  }
}

Error Handling

All methods may throw PlatformException. It's recommended to wrap calls in try-catch blocks:

try {
  final result = await _origoSdk.someMethod();
  // Handle success
} on PlatformException catch (e) {
  print('Error: ${e.message}');
  // Handle error
}

Requirements

  • Flutter >=3.3.0
  • Dart SDK >=3.6.0
  • Android API level 21+
  • iOS 11.0+

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

For issues and feature requests, please visit our GitHub repository.