SaveEye Flutter SDK
The SaveEye Flutter SDK provides a Dart API to interact with SaveEye devices for provisioning over BLE, pairing, checking online status, querying historic usage, and subscribing to realtime readings.
Example app
A complete Flutter example is available at https://github.com/saveeye/Flutter-SDK-Example
Installation
Add the SDK to your pubspec.yaml
dependencies:
saveeye_flutter_sdk: ^x.y.z
Initialization
import 'package:saveeye_flutter_sdk/saveeye_flutter_sdk.dart';
Future<String> getJwtToken() async {
// Return a fresh Firebase (or other) JWT for the current user
// e.g. await FirebaseAuth.instance.currentUser?.getIdToken() ?? '';
return '';
}
void main() {
SaveEyeClient.instance.initialize(
'APP_SDK_KEY',
getJwtToken,
// environment: SaveEyeEnvironment.prod, // default is prod
// debug: false, // default is false, set to true to enable debug print statements
);
}
appSDKKey: Your SDK key from the SaveEye Manager portal.onJWTRequest: A callback that must return a fresh JWT when called.environment: Optional. Defaults toSaveEyeEnvironment.prod. This is for SaveEye internal development; partners should use production.debug: Optional. Defaults tofalse. Set totrueto enable debug print statements from the SDK. Whenfalse, all SDK print statements are suppressed.
Provisioning
Scan for nearby devices
final devices = await SaveEyeClient.instance.getSaveEyeDevicesNearby();
// devices: List<String> of BLE names like 'SAVEEYE_XXXXXXXX'
Provision a device and list available Wi‑Fi networks
Provide either a QR code string (containing the device id) or a BLE name (e.g., SAVEEYE_XXXXXXXX).
final wifiSsids = await SaveEyeClient.instance.provisionDevice(
qrCodeOrBLEName,
/* externalId: */ null, // Optional: pair with this externalId; otherwise the JWT claim defined for the appSDKKey is ued
);
if (wifiSsids != null && wifiSsids.isNotEmpty) {
// Show available Wi‑Fi networks to the user
}
Provisioning status events
Listen to the provisioning status via a stream of StatusEvent:
final sub = SaveEyeClient.instance.events.listen((event) {
// event.topic == SaveEyeClient.deviceStatusTopic
// event.stage is a ConnectionStage
});
ConnectionStage values (in typical sequence):
fetchingDeviceConfigfetchedDeviceConfigsearchingconnectedpairingpairederror
Connect device to Wi‑Fi
await SaveEyeClient.instance.connectToWifi(
'SAVEEYE_XXXXXXXX', // BLE name
'YourSSID',
'YourPassphrase',
);
Pair a device
final paired = await SaveEyeClient.instance.pairDevice(
qrCodeOrBLEName,
/* externalId: */ null, // Optional
);
Unpair a device
await SaveEyeClient.instance.unpairDevice(
deviceId,
/* externalId: */ null, // Optional
);
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 (String)externalId: (Optional) External ID as a String to unpair the device from. This is mandatory if the app SDK key uses a list claim for externalId (As configured when creating app SDK key in the SaveEye Manager).
Check if a device is online
If a device is found via BLE it's not online and have to be onboarded via provisionDevice
final isOnline = await SaveEyeClient.instance.isDeviceOnline(qrCodeOrBLEName);
User devices
Get my devices
final myDevices = await SaveEyeClient.instance.getMyDevices();
for (final d in myDevices) {
// See MyDevice below (id, serial, alias, deviceType, ...)
}
// MyDevice response
class MyDevice {
String id;
String? alias;
String serial;
double allTimesHighConsumption;
double allTimesHighProduction;
bool hasProduction;
int? blinksPerKwh;
String? errorCode;
double rmsCurrentMaxPerPhaseAmpere;
DeviceType deviceType; // name, profile
List<IdOnly> remoteDevices; // id
IdOnly? baseDevice; // id
}
class DeviceType {
String name;
int? profile; // optional
}
class IdOnly {
String id;
}
Device data
Historic usage
import 'package:saveeye_flutter_sdk/gql/schema.graphql.dart' show Enum$IntervalType;
final start = DateTime.utc(2024, 1, 1);
final end = DateTime.utc(2024, 1, 31);
// interval: Enum$IntervalType.DAY | Enum$IntervalType.HOUR | Enum$IntervalType.MONTH
final energy = await SaveEyeClient.instance.getEnergyUsageHistory(
deviceId,
start,
end,
Enum$IntervalType.DAY,
);
final power = await SaveEyeClient.instance.getPowerUsageHistory(
deviceId,
start,
end,
Enum$IntervalType.HOUR,
);
// EnergyUsageHistory response
class EnergyUsageHistory {
String deviceId;
List<EnergyUsageSummary> energyUsageSummaries; // aggregationPeriod, consumed/produced
bool hasProduction;
String intervalType; // e.g., DAY, HOUR, MONTH
double peakEnergyProductionKWh;
double peakEnergyConsumptionKWh;
double lowestEnergyProductionKWh;
double lowestEnergyConsumptionKWh;
double totalEnergyConsumedKWh;
double totalEnergyProducedKWh;
double allTimesHighEnergyConsumedKWh;
double allTimesHighEnergyProducedKWh;
}
class EnergyUsageSummary {
DateTime aggregationPeriod; // UTC start of period
double energyConsumedKWh;
double energyProducedKWh;
}
// PowerUsageHistory response
class PowerUsageHistory {
String deviceId;
String intervalType; // e.g., DAY, HOUR, MONTH
List<PowerUsageSummary> powerUsageSummaries;
}
class PowerUsageSummary {
DateTime aggregationPeriod; // UTC start of period
double averageConsumptionWatt;
double maxConsumptionWatt;
double minConsumptionWatt;
double averageProductionWatt;
double maxProductionWatt;
double minProductionWatt;
}
Set device alarm thresholds
Set alarm thresholds for a device to monitor energy consumption.
await SaveEyeClient.instance.setDeviceAlarmThresholds(
deviceId,
alarmMaxWh: 5000, // Optional: Maximum consumption threshold in Wh
);
Sets the alarm threshold for a specific device. This method updates the maximum alarm threshold for the device on the server. When the threshold is reached your backend can be notified. Pass null to clear the threshold.
Realtime
Subscribe to realtime readings
import 'package:saveeye_flutter_sdk/saveeye_flutter_sdk.dart';
await SaveEyeClient.instance.subscribeToRealtimeData(
deviceId,
(RealtimeReading? data, WebSocketErrorEvent? error) {
if (data != null) {
// Use data.currentConsumptionW.total, data.timestamp, etc.
} else if (error != null) {
// Handle websocket error
}
},
);
Unsubscribe
await SaveEyeClient.instance.unsubscribeFromRealtimeData();
Platform permissions
iOS
Add the following to your Info.plist:
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Used for connecting to SaveEye devices</string>
If your app scans QR codes, also include:
<key>NSCameraUsageDescription</key>
<string>Camera access is needed for scanning QR codes</string>
Android
Add required permissions to your app manifest:
<!-- BLE permissions for nearby device scanning -->
<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" />
<!-- For Android 12+ -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- Camera permission for QR scanning (optional) -->
<uses-permission android:name="android.permission.CAMERA" />
On Android 12+, you must request runtime permissions for BLUETOOTH_SCAN and BLUETOOTH_CONNECT (and location on older versions). Use your preferred permissions package to prompt the user.
Notes
- Passing either a QR code string (containing a device id) or a BLE name like
SAVEEYE_XXXXXXXXis supported where indicated. The SDK resolves the device id internally.
Support
For support or questions, please contact dst@saveeye.dk.
Libraries
- gql/mutations/pairDeviceWithExternalId.graphql
- gql/mutations/startOnboardingSession.graphql
- gql/mutations/unpairDeviceWithExternalId.graphql
- gql/mutations/UpdatePlusDeviceOnboardingSession.graphql
- gql/queries/getDeviceById.graphql
- gql/queries/getDevicePopAndSerial.graphql
- gql/queries/getEnergyUsageHistory.graphql
- gql/queries/getMyDevices.graphql
- gql/queries/getPowerUsageHistory.graphql
- gql/queries/isDeviceOnline.graphql
- gql/queries/publicCoreDeviceBySerial.graphql
- gql/queries/updateDeviceAlarmThreshold.graphql
- gql/schema.graphql
- saveeye_flutter_sdk
- SaveEye Flutter SDK