npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@saveeye/saveeye-sdk-reactnative

v1.0.7

Published

An SDK to integrate SaveEye devices, including device provisioning

Downloads

525

Readme

Saveeye SDK

The Saveeye SDK provides a set of methods to interact with Saveeye devices, including provisioning, connecting to WiFi, and retrieving device information. Below is a description of the different methods available in the SDK.

Example app

An example app is available here: SaveEye SDK Example App

Permissions

iOS

  • Since iOS 13, apps that want to access the SSID (Wi-Fi network name) are required to have location permission. Add the key NSLocationWhenInUseUsageDescription in Info.plist with an appropriate description.
  • Since iOS 14, apps that communicate over the local network are required to have local network permission. Add the key NSLocalNetworkUsageDescription in Info.plist with an appropriate description.
  • NSBluetoothAlwaysUsageDescription is needed to communicate with the SaveEye device over BLE

Android

  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
  <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

  <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
  <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

  <!-- Request legacy Bluetooth permissions on older devices. -->
  <uses-permission
      android:name="android.permission.BLUETOOTH"
      android:maxSdkVersion="30" />
  <uses-permission
      android:name="android.permission.BLUETOOTH_ADMIN"
      android:maxSdkVersion="30" />

On newer android versions a prompt to the user is required for BLUETOOTH_SCAN, BLUETOOTH_CONNECT and ACCESS_FINE_LOCATION. It can be done via https://github.com/zoontek/react-native-permissions using the following code:

  async function requestBluetoothPermissions(setError: (msg: string) => void) {
    try {
      if (Platform.OS === "android") {
        // Android 12+ permissions
        const permissions = [
          PERMISSIONS.ANDROID.BLUETOOTH_SCAN,
          PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
          PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
        ];
        for (const perm of permissions) {
          const result = await request(perm);
          if (result !== RESULTS.GRANTED) {
            setError("Bluetooth and location permissions are required.");
            return false;
          }
        }
      }
      // iOS: Add iOS permissions if needed
      return true;
    } catch (e) {
      setError("Failed to request permissions.");
      return false;
    }
  }

General

getInstance

getInstance();

Returns the singleton instance of the SaveeyeSdk class.

initialize

initialize(appSDKKey: string, onJWTRequest: () => Promise<string>, environment?: 'dev' | 'staging' | 'prod', locale?: string): void

Initializes the SDK with the provided appSDKKey (can be generated in the SaveEye manager portal) and a callback returning a fresh JWT.

Parameters:

  • appSDKKey: The SDK key generated in the SaveEye manager portal
  • onJWTRequest: A callback function that returns a fresh JWT token
  • environment: (Optional) The environment to use. Defaults to 'prod'.
  • locale: (Optional) Locale for the app (e.g. 'en-US', 'da-DK'). Used for localized error descriptions on your SaveEye devices. If the locale is not supported by the service, English is used as the default.

⚠️ Important: The environment parameter is for internal SaveEye development use only. Partners should not use this parameter and should always use the production environment.

Example

import SaveeyeSdk from '@saveeye/saveeye-sdk-reactnative';

async function getJWTToken(): Promise<string> {
  let token = await auth.currentUser?.getIdToken();
  return token ?? '';
}

// Standard initialization (production environment)
SaveeyeSdk.getInstance().initialize(APP_SDK_KEY, getJWTToken);

// With locale for localized device error descriptions (e.g. from expo-localization)
SaveeyeSdk.getInstance().initialize(APP_SDK_KEY, getJWTToken, 'prod', 'da-DK');

// Note: Partners should always use the standard initialization above.
// The environment parameter is for internal SaveEye development only.

healthCheck

healthCheck(): Promise<Boolean>

Checks if the SaveEye service is healthy and accessible. This method queries the GraphQL API to verify the service status.

Returns:

  • A Promise that resolves to true if the service is healthy, or false if it's not.

Example:

const isHealthy = await SaveeyeSdk.getInstance().healthCheck();
if (isHealthy) {
  console.log('SaveEye service is healthy');
} else {
  console.log('SaveEye service is not healthy');
}

getSaveEyeDevicesNearby

getSaveEyeDevicesNearby(): Promise<ESPDevice[]>

Scans for SaveEye devices nearby using Bluetooth Low Energy (BLE).

Returns a Promise that resolves to an array of ESPDevice objects representing the SaveEye devices found in the vicinity. This is typically used during the provisioning process to discover devices that are ready to be configured or paired.

Example:

const devices = await SaveeyeSdk.getInstance().getSaveEyeDevicesNearby();
console.log('Nearby SaveEye devices:', devices);

Provisioning

getDeviceIdBySerialOrBLEName

getDeviceIdBySerialOrBLEName(serialOrBLEName: string): Promise<string>

Resolves a device ID from a device's serial number or BLE name. This is useful if you have a serial or BLE name and need to obtain the device's unique ID before provisioning or other operations.

  • serialOrBLEName: The serial number or BLE name of the device (e.g., SAVEEYE_KV7G8JVT).
  • Returns: A promise that resolves to the device ID string.

Example:

const deviceId =
  await SaveeyeSdk.getInstance().getDeviceIdBySerialOrBLEName(
    'SAVEEYE_KV7G8JVT'
  );

getDeviceTypeById

getDeviceTypeById(deviceId: string): Promise<DeviceTypeFragment>

Retrieves the device type and profile for a device by its ID. This uses public device metadata and does not require the device to be paired with the user. Useful during provisioning to determine the device profile (e.g. for setEncryptionKey) before the device is paired.

Parameters:

  • deviceId: The unique identifier of the device.

Returns:

  • A Promise that resolves to a DeviceTypeFragment containing:
    • saveEyePlusDeviceTypeProfile: The device profile (e.g. 4, 5, or 6). Used to determine which encryption key(s) to pass to setEncryptionKey.
    • deviceType: The device type enum (e.g. EYE_Q100, EYE_Q300, PLUS, SPLITTER).

Example:

const deviceType = await SaveeyeSdk.getInstance().getDeviceTypeById(deviceId);
// Use deviceType.saveEyePlusDeviceTypeProfile to choose the right key(s) for setEncryptionKey
if (deviceType.saveEyePlusDeviceTypeProfile === 5) {
  await SaveeyeSdk.getInstance().setEncryptionKey(deviceId, 'your-mep-key-20-chars');
}

provisionDevice

provisionDevice(qrCodeOrId: string, externalId?: string): Promise<{ espDevice: ESPDevice; deviceId: string }>

Provisions a device using a QR code or device ID. The function will extract the device ID from the QR code string using the SDK's internal logic. If you have a serial or BLE name, use getDeviceIdBySerialOrBLEName first to resolve the device ID.

💡 Tip: Before provisioning a device, you can check if it's already online using isDeviceOnline(). If the device is online, you can simply use pairDevice() instead of the full provisioning process, which is more efficient and doesn't require a device reset.

Returns: A promise that resolves to an object containing:

  • espDevice: The discovered and connected ESPDevice instance.
  • deviceId: The resolved device ID used for provisioning.

Parameters:

  • qrCodeOrId: The QR code string or device ID. If a QR code is provided, the device ID will be extracted automatically.
  • externalId?: (Optional) External ID to pair the device with. If not provided, the device will be paired with the userId within the JWT.

Status updates follow this sequence during device provisioning:

export enum ConnectionStages {
  NONE = 'None', // Initial state
  FETCHING_DEVICE_CONFIG = 'FetchingDeviceConfig', // Fetching device config from SaveEye server
  FETCHED_DEVICE_CONFIG = 'FetchedDeviceConfig', // Device config retrieved
  SEARCHING = 'Searching', // Searching for device via BLE
  CONNECTED = 'Connected', // Connected to device via BLE
  PAIRING = 'Pairing', // Pairing device with user
  PAIRED = 'Paired', // Device successfully paired
  ERROR = 'Error', // An error occurred during any stage
}

getAvailableSSIDForDevice

getAvailableSSIDForDevice(device: ESPDevice): Promise<ESPWifiList[]>

Retrieves the available WiFi networks for the specified device.

connectToWiFi

connectToWiFi(device: ESPDevice, deviceId: string, ssid: string, passphrase?: string): Promise<void>

Connects the specified device to the provided WiFi network. This method also updates the onboarding status to indicate that WiFi setup is complete.

Parameters:

  • device: The ESPDevice instance to connect.
  • deviceId: The unique identifier of the device (as returned from provisioning).
  • ssid: The SSID (network name) to connect to.
  • passphrase?: (Optional) The WiFi password. Leave empty for open networks.

Returns:

  • A Promise that resolves when the device is successfully connected to the WiFi network.

Example:

// Assume you have already provisioned the device and have both the ESPDevice instance and deviceId
const { espDevice, deviceId } =
  await SaveeyeSdk.getInstance().provisionDevice(qrOrSerial);

// Scan for available WiFi networks
const wifiList =
  await SaveeyeSdk.getInstance().getAvailableSSIDForDevice(espDevice);

// Connect to a selected WiFi network (with or without passphrase)
await SaveeyeSdk.getInstance().connectToWiFi(
  espDevice,
  deviceId,
  wifiList[0].ssid,
  'your_wifi_password'
);

console.log('Device connected to WiFi and onboarding status updated.');

getOnboardingSession

getOnboardingSession(deviceId: string): Promise<{
  status: PlusDeviceOnboardingSessionStatus;
  startedOn: Date;
  lastUpdatedOn: Date;
  completedOn: Date;
  errorCode: string;
}>

Retrieves the current onboarding session status for a specific device. This method is useful for checking the progress or result of the device onboarding process, including timestamps and any error codes.

Parameters:

  • deviceId: The unique identifier of the device whose onboarding session you want to query.

Returns:

  • A Promise that resolves to an object containing:
    • status: The current onboarding session status (enum value).
    • startedOn: The timestamp when onboarding started.
    • lastUpdatedOn: The timestamp of the last update to the onboarding session.
    • completedOn: The timestamp when onboarding was completed (if available).
    • errorCode: Any error code associated with the onboarding session (if any).

Example:

const session = await SaveeyeSdk.getInstance().getOnboardingSession(deviceId);
console.log('Onboarding status:', session.status);
console.log('Started on:', session.startedOn);
console.log('Last updated on:', session.lastUpdatedOn);
console.log('Completed on:', session.completedOn);
console.log('Error code:', session.errorCode);

PlusDeviceOnboardingSessionStatus (enum)

The PlusDeviceOnboardingSessionStatus enum describes the possible states of a device's onboarding session:

  • BLE_CONNECTED: The device has been connected via Bluetooth Low Energy (BLE).
  • WI_FI_SETUP_DONE: The device has successfully connected to WiFi.
  • FIRMWARE_UPDATE_IN_PROGRESS: The device is currently updating its firmware.
  • FIRMWARE_UPDATE_DONE: The device has completed a firmware update.
  • DONE: The onboarding process is complete.
  • ERROR_MESSAGES: An error occurred during onboarding.

You can use these values to interpret the status field returned by getOnboardingSession().

onDeviceStatusUpdate

onDeviceStatusUpdate(callback: (status: string) => void)

Registers`a callback to receive device status updates when the device is provisioning using BLE.

Status updates follow this sequence during device provisioning:

export enum ConnectionStages {
  NONE = 'None', // Initial state
  FETCHING_DEVICE_CONFIG = 'FetchingDeviceConfig', // Fetching device config from SaveEye server
  FETCHED_DEVICE_CONFIG = 'FetchedDeviceConfig', // Device config retrieved
  SEARCHING = 'Searching', // Searching for device via BLE
  CONNECTED = 'Connected', // Connected to device via BLE
  PAIRING = 'Pairing', // Pairing device with user
  PAIRED = 'Paired', // Device successfully paired
  ERROR = 'Error', // An error occurred during any stage
}

stopDeviceStatusUpdates

stopDeviceStatusUpdates();

Stops receiving device status updates.

setEncryptionKey

Encryption Key Requirements by Device Profile:

| Device Profile | Key Parameter(s) | Required Length(s) | | :------------: | :--------------------- | :----------------- | | 4 | opticalKey | Any (string) | | 5 | mepKey | 20 characters | | 6 | gpk60Key, gpk61Key | 32 characters each |

⚠️ Note: Supplying a key with an incorrect length will result in an error. Only provide the key(s) relevant to the device's profile. Other parameters can be left as undefined or omitted.

setEncryptionKey(
  deviceId: string,
  mepKey?: string,
  gpk60Key?: string,
  gpk61Key?: string,
  opticalKey?: string
): Promise<void>

Sets the encryption key(s) for a specific device. The type of key(s) required depends on the device's profile. You can determine the device profile from the profile field in the device's deviceType (see getMyDevices or getDeviceById), or use getDeviceTypeById to get the profile by device ID without requiring the device to be paired.

Parameters:

  • deviceId: The ID of the device to update
  • mepKey?: (Profile 5) The MEP encryption key
  • gpk60Key?: (Profile 6) The GPK60 encryption key
  • gpk61Key?: (Profile 6) The GPK61 encryption key
  • opticalKey?: (Profile 4) The Optical encryption key

Examples:

// For a profile 5 device (MEP)
await SaveeyeSdk.getInstance().setEncryptionKey(
  deviceId,
  '12345678901234567890'
);

// For a profile 6 device (GPK)
await SaveeyeSdk.getInstance().setEncryptionKey(
  deviceId,
  undefined,
  '12345678901234567890123456789012',
  'abcdefghijabcdefghijabcdefghijabcd'
);

// For a profile 4 device (Optical)
await SaveeyeSdk.getInstance().setEncryptionKey(
  deviceId,
  undefined,
  undefined,
  undefined,
  'optical-key-value'
);

setEncryptionKeysFromInputs

setEncryptionKeysFromInputs(
  deviceId: string,
  encryptionInputs: EncryptionInput[]
): Promise<void>

Sets encryption key(s) for a device using the same input structure returned by getDeviceSettings. Use this when you have already fetched device settings and want to submit user-entered values for the encryption fields (e.g. from a form). Each item in encryptionInputs must include the id from the device's encryptionInputs, with value set to the user's input.

Parameters:

  • deviceId: The ID of the device to update.
  • encryptionInputs: Array of objects with id and value (the key value to set). Match the structure from getDeviceSettings().encryptionInputs, filling in value with the user's input.

Example:

const settings = await SaveeyeSdk.getInstance().getDeviceSettings(deviceId);
const encryptionInputs = (settings.encryptionInputs ?? []).map((input) => ({
  id: input.id,
  value: userEnteredValues[input.id] ?? input.value ?? '',
}));
await SaveeyeSdk.getInstance().setEncryptionKeysFromInputs(deviceId, encryptionInputs);

pairDevice

pairDevice(qrCodeOrId: string, externalId?: string): Promise<void>

Pair a device with an optional externalId. If no externalId is provided, the UserId from the JWT token will be used instead. Also called automatically from provisionDevice, but this can be used to avoid having to reprovision a device.

Parameters:

  • qrCodeOrId: The QR code string or device ID to pair
  • externalId?: (Optional) External ID to pair the device with. If not provided, the device will be paired with the userId within the JWT

pairRemoteDeviceWithBaseDevice

pairRemoteDeviceWithBaseDevice(deviceId: string, baseDeviceId: string, externalId?: string): Promise<void>

Pairs a remote device with a base device and optionally with an external ID. This method creates a pairing between the remote device and the base device, and if an external ID is provided, it also pairs the remote device with that external ID. If no external ID is provided, the UserId from the JWT token will be used instead.

Parameters:

  • deviceId: The ID of the remote device to pair
  • baseDeviceId: The ID of the base device to pair the remote device with
  • externalId?: (Optional) External ID to pair the device with. If not provided, the device will be paired with the userId within the JWT

Example:

await SaveeyeSdk.getInstance().pairRemoteDeviceWithBaseDevice(
  'remote-device-id',
  'base-device-id',
  'optional-external-id'
);

unpairDevice

unpairDevice(deviceId: string, externalId?: string): Promise<void>

Unpairs a device from the current user. This removes the association between the device and the user, allowing the device to be paired with a different user.

Parameters:

  • deviceId: The ID of the device to unpair
  • externalId?: (Optional) External ID to unpair the device from. This is mandatory if the externalId is a listclaim (As provided when creating app SDK key in the SaveEye Manager).

User

getMyDevices

getMyDevices(): Promise<MyDeviceFragment[]>

Retrieves the devices associated with the user. Use this to list all devices linked to the user's account. The previous pairedDevices / getMyPairedDevices API has been removed in favor of getMyDevices.

getDeviceById

getDeviceById(deviceId: string): Promise<MyDeviceFragment>

Retrieves a specific device by its ID. Note: This function will only return the device if the user's JWT token is paired with the device.

Parameters:

  • deviceId: The ID of the device to retrieve

The MyDeviceFragment type contains the following fields:

type MyDeviceFragment = {
  id: string; // Unique identifier of the device
  alias?: string | null; // User-defined name for the device
  errorCode?: string | null; // Latest error code from the device (null when there is no error)
  errorCodeDescriptionLocalized?: string | null; // Human-readable description of the error
  firmwareUpdateState: FirmwareUpdateState; // Current firmware update state (see FirmwareUpdateState enum)
  serial: string; // Device serial number
  plusDevice?: {
    allTimesHighConsumption: number; // Highest recorded consumption value
    allTimesHighProduction: number; // Highest recorded production value
    hasProduction: boolean; // Whether the device has recorded production
    rmsCurrentMaxPerPhaseAmpere: number; // Maximum current limit per phase
    deviceType: {
      name: string; // Name of the device type
      profile?: number | null; // Device profile configuration
    };
  } | null;
};

Note: errorCodeDescriptionLocalized is localized using the locale passed to initialize(). If no locale was provided or the locale is not supported, English is used. The value is in markdown format and can be rendered with a markdown-capable UI component.

FirmwareUpdateState (enum)

The firmwareUpdateState field on MyDeviceFragment (returned by getMyDevices and getDeviceById) uses the FirmwareUpdateState enum:

  • IDLE: The device is idle and not performing any firmware update.
  • UPDATING: The device is currently applying a firmware update.
  • FAILED: A firmware update failed; the device was unable to complete the update.

Use this to show update status in the UI (e.g. a progress or status indicator while UPDATING, or an error state when FAILED).

Device data

Historic

getEnergyUsageHistory

  getEnergyUsageHistory(deviceId: string, startUTC: Date, endUTC: Date, interval: IntervalType): Promise<EnergyUsageHistory>

Retrieves the energy usage history of a device within a specified time range and interval. The interval parameter determines the granularity of the data points (e.g. hourly, daily, monthly). Returns a Promise containing the energy usage data for the specified period.

Parameters:

  • deviceId: The ID of the device to get history for
  • startUTC: Start date/time in UTC
  • endUTC: End date/time in UTC
  • interval: The data point interval (IntervalType)

getPowerUsageHistory

getPowerUsageHistory(deviceId: string, startUTC: Date, endUTC: Date, interval: IntervalType): Promise<PowerUsageHistory>

Retrieves the power usage history of a device within a specified time range and interval. The interval parameter determines the granularity of the data points (e.g. hourly, daily, monthly). Returns a Promise containing the power usage data for the specified period.

Parameters:

  • deviceId: The ID of the device to get history for
  • startUTC: Start date/time in UTC
  • endUTC: End date/time in UTC
  • interval: The data point interval (IntervalType)

The PowerUsageHistory type contains the following fields:

type PowerUsageHistory = {
  deviceId: string; // The unique identifier of the device
  intervalType: IntervalType; // The time interval used for aggregating power usage data
  powerUsageSummaries: Array<PowerUsageSummary>; // Collection of power usage summaries
};

type PowerUsageSummary = {
  aggregationPeriod: Date; // The timestamp representing the start of the aggregation period (UTC)
  averageConsumptionWatt: number; // The average power consumption (in watts) during the aggregation period
  averageProductionWatt: number; // The average power production (in watts) during the aggregation period
  maxConsumptionWatt: number; // The maximum power consumption (in watts) recorded during the aggregation period
  maxProductionWatt: number; // The maximum power production (in watts) recorded during the aggregation period
  minConsumptionWatt: number; // The minimum power consumption (in watts) recorded during the aggregation period
  minProductionWatt: number; // The minimum power production (in watts) recorded during the aggregation period
};

Realtime

subscribeToRealtimeData

  async subscribeToRealtimeData(
    deviceId: string,
    callback: (data: RealtimeReading, error?: WebSocketErrorEvent) => void
  )

Subscribes to real-time data updates for a specific device. This method establishes a WebSocket connection to receive real-time data from the device and invokes the provided callback function whenever new data is received or when an error occurs.

Multiple Device Support:

  • You can subscribe to multiple different devices simultaneously (one WebSocket per device)
  • Each device maintains its own independent WebSocket connection
  • Subscribing to different devices will create separate connections

Multiple Callbacks Per Device:

  • You can register multiple callbacks for the same device
  • If you subscribe to a device that is already connected, the callback will be added to the existing subscription
  • A CONCURRENT_SUBSCRIPTION error will be returned to notify you of the duplicate subscription
  • Important: Even though an error is returned, your callback will still receive data from the existing WebSocket connection
  • All callbacks registered for a device will receive the same data when it arrives

Parameters:

  • deviceId: The ID of the device to subscribe to
  • callback: A function that receives real-time data or error events

Error Handling:

If you subscribe to a device that is already connected, you will receive a WebSocketErrorEvent with:

  • type: 'CONCURRENT_SUBSCRIPTION'
  • message: A description indicating the callback was added to an existing subscription

Despite the error, your callback will be registered and will receive data from the existing WebSocket connection.

Example - Multiple Devices:

// Subscribe to device 1
sdk.subscribeToRealtimeData('device-1', (data, error) => {
  if (error) {
    console.log('Device 1 error:', error);
  } else {
    console.log('Device 1 data:', data);
  }
});

// Subscribe to device 2 (different device - creates new WebSocket)
sdk.subscribeToRealtimeData('device-2', (data, error) => {
  console.log('Device 2 data:', data);
});

// Subscribe to device 1 again (same device - error but callback added)
sdk.subscribeToRealtimeData('device-1', (data, error) => {
  // This callback will receive CONCURRENT_SUBSCRIPTION error initially
  // But will still receive data from the existing WebSocket connection
  if (error && error.type === 'CONCURRENT_SUBSCRIPTION') {
    console.log('Already subscribed, but will receive data');
  } else if (data) {
    console.log('Device 1 data (second callback):', data);
  }
});

unsubscribeFromRealtimeData

unsubscribeFromRealtimeData(deviceId?: string): Promise<void>

Unsubscribes from real-time data updates. This method closes the WebSocket connection(s) that were established for receiving real-time data.

Parameters:

  • deviceId?: (Optional) The ID of the device to unsubscribe from. If not provided, unsubscribes from all devices.

Behavior:

  • If deviceId is provided: Closes the WebSocket connection for that specific device and removes all callbacks for that device
  • If deviceId is not provided: Closes all WebSocket connections for all devices and removes all callbacks

Best Practices:

Best implemented with a return function in eg. a useEffect, to make sure the websocket is closed when not in use.

React Native Example:

useEffect(() => {
  SaveeyeSdk.getInstance().subscribeToRealtimeData(deviceId, (data, error) => {
    if (error) {
      if (error.type === 'CONCURRENT_SUBSCRIPTION') {
        // Already subscribed, but callback will still receive data
        console.log('Already subscribed to device');
      } else {
        console.error('WebSocket error:', error);
      }
    } else if (data) {
      console.log('Got realtime data:', data);
    }
  });

  return () => {
    // Unsubscribe from this specific device
    SaveeyeSdk.getInstance().unsubscribeFromRealtimeData(deviceId);
  };
}, [deviceId]);

Expo Router Example:

useFocusEffect(
  useCallback(() => {
    SaveeyeSdk.getInstance().subscribeToRealtimeData(
      deviceId,
      (data, error) => {
        if (error) {
          if (error.type === 'CONCURRENT_SUBSCRIPTION') {
            // Already subscribed, but callback will still receive data
            console.log('Already subscribed to device');
          } else {
            console.error('WebSocket error:', error);
          }
        } else if (data) {
          console.log('Got realtime data:', data);
        }
      }
    );

    return () => {
      // Unsubscribe from this specific device
      SaveeyeSdk.getInstance().unsubscribeFromRealtimeData(deviceId);
    };
  }, [deviceId])
);

Multiple Devices Example:

useEffect(() => {
  const sdk = SaveeyeSdk.getInstance();
  const deviceIds = ['device-1', 'device-2', 'device-3'];

  // Subscribe to multiple devices
  deviceIds.forEach((id) => {
    sdk.subscribeToRealtimeData(id, (data, error) => {
      if (error) {
        console.error(`Error for device ${id}:`, error);
      } else if (data) {
        console.log(`Data from device ${id}:`, data);
      }
    });
  });

  return () => {
    // Unsubscribe from all devices
    sdk.unsubscribeFromRealtimeData();
  };
}, []);

Settings

getDeviceSettings

getDeviceSettings(deviceId: string): Promise<DeviceSettingsFragment>

Retrieves the settings of a specific device. DeviceSettingsFragment has the following shape:

type DeviceSettingsFragment = {
  __typename?: 'Device';
  alias?: string | null;
  plusDevice?: {
    localMqttBroker?: string | null;
    localMqttEnabled?: boolean | null;
    localMqttPassword?: string | null;
    localMqttPort?: number | null;
    localMqttUser?: string | null;
    consumptionAlarmMaxWh?: number | null;
    blinksPerKwh?: number | null;
    errorCode?: string | null;
  } | null;
  encryptionInputs?: Array<{
    id: string;
    value?: string | null;
    placeholder: string;
  }> | null;
};

Changes: consumptionAlarmMinWh has been removed. MQTT and alarm fields now live under plusDevice. The new encryptionInputs array describes encryption-related fields (e.g. for device provisioning).

setDeviceAlias

setDeviceAlias(deviceId: string, name: string): Promise<void>

Sets the alias (name) for a specific device. This method updates the device's alias on the server.

setLocalMQTTSettings

setLocalMQTTSettings(
    deviceId: string,
    enabled: boolean,
    broker: string,
    port: number,
    username: string,
    password: string
): Promise<void>

Sets the local MQTT settings for a specific device. This method updates the local MQTT configuration on the server for the specified device.

setDeviceAlarmThresholds

setDeviceAlarmThresholds(
    deviceId: string,
    alarmMaxWh?: number,
    alarmMinWh?: number
  ): Promise<void>

Sets the alarm thresholds for a specific device. This method updates the maximum and minimum alarm thresholds for the device on the server. When the threshold is reached your backend can be notified.

Parameters:

  • deviceId: The ID of the device to update
  • alarmMaxWh?: (Optional) The maximum alarm threshold in watt-hours
  • alarmMinWh?: (Optional) The minimum alarm threshold in watt-hours

setRmsCurrentMaxPerPhase

setRmsCurrentMaxPerPhase(deviceId: string, rmsCurrentMax: number): Promise<void>

Sets the maximum RMS current per phase for a specific device. This method updates the maximum allowed current (in amperes) that can flow through each phase of the meter. This can be retrieved again through the getMyDevices function.

Parameters:

  • deviceId: The ID of the device to update
  • rmsCurrentMax: The maximum RMS current in amperes per phase

setBlinksPerKwh

setBlinksPerKwh(deviceId: string, blinksPerKwh: number): Promise<void>

Sets the number of blinks per kilowatt-hour (kWh) for a specific device. This value is used for devices that measure energy consumption via an optical sensor (e.g., by counting LED blinks on a traditional electricity meter). Setting the correct value ensures accurate energy measurement and reporting.

Parameters:

  • deviceId: The ID of the device to update.
  • blinksPerKwh: The number of LED blinks that correspond to 1 kWh on the meter (typically found on the meter label, e.g., 1000 or 2000).

Returns:

  • A Promise that resolves when the value has been set successfully.

Example:

await SaveeyeSdk.getInstance().setBlinksPerKwh(deviceId, 1000);

This will set the device to interpret 1000 blinks as 1 kWh.

isDeviceOnline

isDeviceOnline(qrCodeOrId: string): Promise<boolean>

Checks if a specific device is currently online and connected to the SaveEye network. This method can be used to determine the connectivity status of a device before attempting to retrieve data or perform operations that require an active connection.

Parameters:

  • qrCodeOrId: The QR code string or device ID to check the online status for.

Returns:

  • A Promise that resolves to true if the device is online and connected, or false if the device is offline.

Example:

const isOnline = await SaveeyeSdk.getInstance().isDeviceOnline(qrCodeOrId);
if (isOnline) {
  console.log('Device is online and ready for data retrieval');
} else {
  console.log('Device is offline or unreachable');
}

Alarms

The SDK provides access to device alarm configurations. These configurations define when and how alarms are triggered (e.g., when energy usage exceeds a threshold or when a device goes offline).

PlusDeviceAlarmConfiguration

The alarmConfigurations field returns an array of configurations. Use __typename to distinguish between different alarm types:

type PlusDeviceAlarmConfiguration = {
  id: string;
  isEnabled: boolean;
  createdOnUtc: string;
  updatedOnUtc: string;
} & (
  | EnergyUsageAlarmConfig
  | FuseOverloadAlarmConfig
  | LowPowerAlarmConfig
  | OfflineAlarmConfig
);

// Energy usage limit alarm
type EnergyUsageAlarmConfig = {
  id: string;
  isEnabled: boolean;
  createdOnUtc: string;
  updatedOnUtc: string;
  __typename: 'PlusDeviceEnergyUsageLimitAlarmConfiguration';
  energyThresholdWh: number;
  evaluationWindowMinutes: number;
  minimumObservedMinutesBeforeProjection?: number;
};

// Fuse overload alarm
type FuseOverloadAlarmConfig = {
  id: string;
  isEnabled: boolean;
  createdOnUtc: string;
  updatedOnUtc: string;
  __typename: 'PlusDeviceFuseOverloadAlarmConfiguration';
  criticalThresholdPercent: number;
  warningThresholdPercent: number;
  triggerMode: AlarmTriggerMode;
  criticalDatapoints?: number;
  criticalDurationSeconds?: number;
  warningDatapoints?: number;
  warningDurationSeconds?: number;
};

// Low power alarm
type LowPowerAlarmConfig = {
  id: string;
  isEnabled: boolean;
  createdOnUtc: string;
  updatedOnUtc: string;
  __typename: 'PlusDeviceLowPowerAlarmConfiguration';
  powerThresholdW: number;
  triggerMode: AlarmTriggerMode;
  datapoints?: number;
  durationSeconds?: number;
};

// Offline alarm
type OfflineAlarmConfig = {
  id: string;
  isEnabled: boolean;
  createdOnUtc: string;
  updatedOnUtc: string;
  __typename: 'PlusDeviceOfflineAlarmConfiguration';
  offlineThresholdSeconds: number;
};

Retrieving Alarm Configurations

Use the specialized functions to fetch the current alarm settings for a device by type. Each function returns the specialized configuration or undefined if the alarm is not configured.

getEnergyUsageLimitAlarmConfiguration

getEnergyUsageLimitAlarmConfiguration(deviceId: string): Promise<EnergyUsageLimitAlarmConfigurationFragment | undefined>

getFuseOverloadAlarmConfiguration

getFuseOverloadAlarmConfiguration(deviceId: string): Promise<FuseOverloadAlarmConfigurationFragment | undefined>

getLowPowerAlarmConfiguration

getLowPowerAlarmConfiguration(deviceId: string): Promise<LowPowerAlarmConfigurationFragment | undefined>

getOfflineAlarmConfiguration

getOfflineAlarmConfiguration(deviceId: string): Promise<OfflineAlarmConfigurationFragment | undefined>

Example:

const energyAlarm = await SaveeyeSdk.getInstance().getEnergyUsageLimitAlarmConfiguration(deviceId);
if (energyAlarm) {
  console.log(`Energy alarm ${energyAlarm.id} is ${energyAlarm.isEnabled ? 'enabled' : 'disabled'}`);
  console.log(`Threshold: ${energyAlarm.energyThresholdWh} Wh`);
}

Setting Alarm Configurations

The SDK provides methods to add or update different types of alarm configurations:

addOrUpdateEnergyUsageLimitAlarm

addOrUpdateEnergyUsageLimitAlarm(input: AddOrUpdateEnergyUsageLimitAlarmConfigurationInput): Promise<void>

Adds or updates an energy usage limit alarm. This alarm triggers when energy usage exceeds a specified threshold within an evaluation window.

Input fields:

  • deviceId: The ID of the device.
  • isEnabled: Whether the alarm is enabled.
  • energyThresholdWh: The energy threshold in watt-hours.
  • evaluationWindowMinutes: The time window in minutes (must divide evenly into 60).
  • minimumObservedMinutesBeforeProjection: (Optional) Min minutes to observe before projecting usage.

addOrUpdateFuseOverloadAlarm

addOrUpdateFuseOverloadAlarm(input: AddOrUpdatePlusDeviceFuseOverloadAlarmConfigurationInput): Promise<void>

Adds or updates a fuse overload alarm. This alarm triggers when the electrical current exceeds safe levels based on the device's phase limit.

Input fields:

  • deviceId: The ID of the device.
  • isEnabled: Whether the alarm is enabled.
  • triggerMode: How the alarm is triggered (SINGLE_DATAPOINT, CONSECUTIVE_DATAPOINTS, or DURATION).
  • warningThresholdPercent: Warning level as a percentage of the phase limit.
  • criticalThresholdPercent: Critical level as a percentage (must be > warning).
  • warningDatapoints / criticalDatapoints: (Optional) Required consecutive points.
  • warningDurationSeconds / criticalDurationSeconds: (Optional) Required duration.

addOrUpdateLowPowerAlarm

addOrUpdateLowPowerAlarm(input: AddOrUpdatePlusDeviceLowPowerAlarmConfigurationInput): Promise<void>

Adds or updates a low power alarm. This alarm triggers when power levels drop below a certain threshold.

Input fields:

  • deviceId: The ID of the device.
  • isEnabled: Whether the alarm is enabled.
  • triggerMode: Triggering logic (SINGLE_DATAPOINT, etc.).
  • consumptionThresholdW: Power threshold in watts.
  • datapoints: (Optional) Required consecutive points.
  • durationSeconds: (Optional) Required duration.

addOrUpdateOfflineAlarm

addOrUpdateOfflineAlarm(input: AddOrUpdatePlusDeviceOfflineAlarmConfigurationInput): Promise<void>

Adds or updates an offline alarm. This alarm triggers when the device has been disconnected for longer than a specified duration.

Input fields:

  • deviceId: The ID of the device.
  • isEnabled: Whether the alarm is enabled.
  • offlineThresholdSeconds: Time in seconds before triggering (min 300 seconds).

Support

For support or questions, please contact [email protected].