npm package: @hkraftno/han-onboarder
Description: Functionality for onboarding HAN-devices
Author: Haugaland Kraft Energi AS
Latest version: 2.0.0

## HAN Device onboarding library

Use this library in a react-native app to run the onboarding process of a HAN
Device.

### Prerequesites

The library expects a bleManager object from the
[react-native-ble-plx](https://github.com/Polidea/react-native-ble-plx) library.

### Known issues

- The HAN-device require a new pairing process (reset button held for ~16 seconds until until both LEDs blink twice in a row) if you want to connect to it via bluetooth.
- Once the onboarding is complete, there is no verification of wi-fi or client connection. To see if the process was successful, check the client's server for incoming data.

### Example code

```ts
import { BleManager } from 'react-native-ble-plx';
import {
  HANOnboarder,
  OnboardingError,
  StrommeClientInfo,
  HANError,
  HANErrorCodes,
} from '@hkraftno/han-onboarder';

// Set up info for the onboarding API.
// Include query-params in url
const url =
  'https://theserveraddress.net/version/API?key=apikey&optionalparam=opt';
const headers: {
  Authorization: `Bearer token`;
  // Add other header fields here
};
const body = {}; // optional
var strommeClientInfo = new StrommeClientInfo(url, headers, body);

// Create a ble scanner and HAN onboarder
// IMPORTANT: Make these const and not recreate them, or bugs will happen!
const bleManager = new BleManager();
const hanOnboarder = new HANOnboarder(
  bleManager,
  strommeClientInfo,
  console.log
);

// Start scanning for nearby devices
hanOnboarder
  .StartScan(deviceDiscovered)
  .then(() => {
    console.log('Scan stopped');
  })
  .catch(error => {
    // This typically happens if the app is missing access to Bluetooth
    // and/or Location service (or if either is turned off)
    console.log('Scan error');
    console.log(error);
  });

async function deviceDiscovered(hanDevice) {
  // Optional, stop scanning for more devices
  // Note: In this example, this will prevent multiple devices from auto-connecting at once
  hanOnboarder.StopScan();

  // Connecting to the device
  try {
    // Connect to the HAN device, with a timeout parameter
    await hanDevice.Connect(15000);

    // Handle unexpected disconnections
    hanDevice.RegisterUnexpectedDisconnectHandler(
      deviceDisconnectedUnexpectedly
    );
  } catch (ex) {
    if (ex instanceof HANError) {
      log(ex);
      if (ex.InnerError) {
        log(ex.InnerError); // For BLE related errors, this will contain the inner error from ble-plx
      }

      if (ex.ErrorCode === HANErrorCodes.ReadMeterError) {
        // Read meter id failed (this happens during the Connect() call)
        log('Could not read meter id, is the han port opened?');
      } else if (ex.ErrorCode === HANErrorCodes.BLEConnetcionError) {
        // BLE error, see https://polidea.github.io/react-native-ble-plx/#bleerror
        log('Connection BLE error');
      } else {
        log('Unkown HAN error (this should not happen..)');
        log('Error code: ' + ex.ErrorCode);
      }
    } else {
      log('Connection error');
      log(ex);
    }
  }

  // Onboarding the device
  try {
    // Setup wifi
    await hanDevice.SetupWifi(mySSID, myWifiPassword);

    // Start the onboarding process (see docs for details)
    await this.StartOnboarding();

    // At this point the HAN device will reboot and thereby disconnect from
    // the phone (but not trigger the deviceDisconnectedUnexpectedly call
  } catch (ex) {
    log('Onboarding error');
    log(ex);
    if (ex.InnerError) {
      log(ex.InnerError);
    }
    if (ex instanceof HANError) {
      if (ex.ErrorCode === HANErrorCodes.SendWifiDataFailed) {
        log('Send wifi info to device failed');
      } else if (ex.ErrorCode === HANErrorCodes.ClientConnectionFailed) {
        log('Client connection failed');
      } else if (ex.ErrorCode === HANErrorCodes.ClientAuthenticationError) {
        log('Client authentication failed');
      } else if (ex.ErrorCode === HANErrorCodes.SendOnboardingKeysFailed) {
        log('Send onboard data to device failed');
      } else {
        log('Unkown HAN error (this should not happen..)');
        log('Error code: ' + ex.ErrorCode);
      }
    }
  }
}

// Handle disconnection. The bleError is documented here:
// https://polidea.github.io/react-native-ble-plx/#bleerror
// The disconnectedDevice is a reference to the HANDevice object.
// This usually happens if the device reboots unexpectedly, or the BLE connection is otherwise broken
function deviceDisconnectedUnexpectedly(bleError, disconnectedDevice) {
  console.log('Disconnected from ' + disconnectedDevice.GetId());
  if (bleError) {
    console.log('Disconnect error:');
    console.log(bleError);
  }
}
```