synheart_wear 0.2.3 copy "synheart_wear: ^0.2.3" to clipboard
synheart_wear: ^0.2.3 copied to clipboard

Unified wearable SDK for Synheart (HR, HRV, steps, energy, stress).

Synheart Wear #

Version Flutter License

Unified wearable SDK for Flutter β€” Stream HR, HRV, steps, calories, and distance from Apple Watch, Fitbit, Garmin, Whoop, and Samsung devices with a single, standardized API.

✨ Features #

Feature Description
πŸ“± Cross-Platform iOS & Android support
⌚ Multi-Device Apple Watch, Fitbit, Garmin, Whoop, Samsung
πŸ”„ Real-Time Live HR and HRV streaming
πŸ“Š Unified Schema Consistent data format across all devices
πŸ”’ Privacy-First Consent-based access with encryption
πŸ’Ύ Offline Support Encrypted local data persistence

πŸš€ Quick Start #

Installation #

dependencies:
  synheart_wear: ^0.2.3
flutter pub get

Basic Usage #

Recommended Pattern (Explicit Permission Control):

import 'dart:io';
import 'package:flutter/widgets.dart';
import 'package:synheart_wear/synheart_wear.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Step 1: Create SDK instance
  final adapters = <DeviceAdapter>{
    DeviceAdapter.appleHealthKit, // Uses Health Connect on Android
  };

  // Use withAdapters() to explicitly specify which adapters to enable
  // Note: Default constructor includes fitbit by default, so use withAdapters() for clarity
  final synheart = SynheartWear(
    config: SynheartWearConfig.withAdapters(adapters),
  );

  // Step 2: Request permissions (with reason for better UX)
  final result = await synheart.requestPermissions(
    permissions: {
      PermissionType.heartRate,
      PermissionType.steps,
      PermissionType.calories,
    },
    reason: 'This app needs access to your health data.',
  );

  // Step 3: Initialize SDK (validates permissions and data availability)
  if (result.values.any((s) => s == ConsentStatus.granted)) {
    try {
      await synheart.initialize();
      
      // Step 4: Read metrics
      final metrics = await synheart.readMetrics();
      print('HR: ${metrics.getMetric(MetricType.hr)} bpm');
      print('Steps: ${metrics.getMetric(MetricType.steps)}');
    } on SynheartWearError catch (e) {
      print('Initialization failed: $e');
      // Handle errors: NO_WEARABLE_DATA, STALE_DATA, etc.
    }
  }
}

Alternative Pattern (Simplified):

If you don't need to provide a custom reason, you can let initialize() handle permissions automatically:

final synheart = SynheartWear(
  config: SynheartWearConfig.withAdapters({DeviceAdapter.appleHealthKit}),
);

// Initialize will request permissions internally if needed
await synheart.initialize();
final metrics = await synheart.readMetrics();

Note: initialize() validates that wearable data is available and not stale (>24 hours old). If no data is available or data is too old, it will throw a SynheartWearError with codes NO_WEARABLE_DATA or STALE_DATA.

Real-Time Streaming #

// Stream heart rate every 5 seconds
// Note: Streams are created lazily when first listener subscribes
// Multiple calls to streamHR() return the same stream controller
final hrSubscription = synheart.streamHR(interval: Duration(seconds: 5))
  .listen((metrics) {
    final hr = metrics.getMetric(MetricType.hr);
    if (hr != null) print('Current HR: $hr bpm');
  }, onError: (error) {
    print('Stream error: $error');
  });

// Stream HRV in 5-second windows
final hrvSubscription = synheart.streamHRV(windowSize: Duration(seconds: 5))
  .listen((metrics) {
    final hrv = metrics.getMetric(MetricType.hrvRmssd);
    if (hrv != null) print('HRV RMSSD: $hrv ms');
  }, onError: (error) {
    print('HRV stream error: $error');
  });

// Don't forget to cancel subscriptions when done
// hrSubscription.cancel();
// hrvSubscription.cancel();

πŸ“Š Data Schema #

All data follows the Synheart Data Schema v1.0:

{
  "timestamp": "2025-10-20T18:30:00Z",
  "device_id": "applewatch_1234",
  "source": "apple_healthkit",
  "metrics": {
    "hr": 72,
    "hrv_rmssd": 45,
    "hrv_sdnn": 62,
    "steps": 1045,
    "calories": 120.4,
    "distance": 2.5
  },
  "meta": {
    "battery": 0.82,
    "firmware_version": "10.1",
    "synced": true
  }
}

Access in code:

final metrics = await synheart.readMetrics();
print(metrics.getMetric(MetricType.hr));        // 72
print(metrics.getMetric(MetricType.steps));     // 1045
print(metrics.getMetric(MetricType.distance));  // 2.5
print(metrics.batteryLevel);                     // 0.82

πŸ“š Full API Documentation | Data Schema Details

⌚ Supported Devices #

Device Platform Status
Apple Watch iOS βœ… Ready
Health Connect Android βœ… Ready
Whoop iOS/Android βœ… Ready
Fitbit iOS/Android πŸ”„ In Development
Garmin iOS/Android πŸ”„ In Development
Samsung Watch Android πŸ“‹ Planned

βš™οΈ Platform Configuration #

Android #

Add to android/app/src/main/AndroidManifest.xml:

<!-- Health Connect Permissions -->
<uses-permission android:name="android.permission.health.READ_HEART_RATE"/>
<uses-permission android:name="android.permission.health.WRITE_HEART_RATE"/>
<uses-permission android:name="android.permission.health.READ_HEART_RATE_VARIABILITY"/>
<uses-permission android:name="android.permission.health.WRITE_HEART_RATE_VARIABILITY"/>
<uses-permission android:name="android.permission.health.READ_STEPS"/>
<uses-permission android:name="android.permission.health.WRITE_STEPS"/>
<uses-permission android:name="android.permission.health.READ_ACTIVE_CALORIES_BURNED"/>
<uses-permission android:name="android.permission.health.WRITE_ACTIVE_CALORIES_BURNED"/>
<uses-permission android:name="android.permission.health.READ_DISTANCE"/>
<uses-permission android:name="android.permission.health.WRITE_DISTANCE"/>

<!-- Health Connect Package Query -->
<queries>
    <package android:name="com.google.android.apps.healthdata" />
    <intent>
        <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
    </intent>
</queries>

<application>
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
        </intent-filter>
    </activity>

    <!-- Required: Privacy Policy Activity Alias -->
    <activity-alias
        android:name="ViewPermissionUsageActivity"
        android:exported="true"
        android:targetActivity=".MainActivity"
        android:permission="android.permission.START_VIEW_PERMISSION_USAGE">
        <intent-filter>
            <action android:name="android.intent.action.VIEW_PERMISSION_USAGE" />
            <category android:name="android.intent.category.HEALTH_PERMISSIONS" />
        </intent-filter>
    </activity-alias>
</application>

Note: MainActivity must extend FlutterFragmentActivity (not FlutterActivity) for Android 14+.

iOS #

Add to ios/Runner/Info.plist:

<key>NSHealthShareUsageDescription</key>
<string>This app needs access to your health data to provide insights.</string>

<key>NSHealthUpdateUsageDescription</key>
<string>This app needs permission to update your health data.</string>

⚠️ Platform Limitations #

Platform Limitation SDK Behavior
Android HRV: Only HRV_RMSSD supported Automatically maps to supported type
Android Distance: Uses DISTANCE_DELTA Automatically uses correct type
iOS Full support for all metrics No limitations

πŸ”’ Privacy & Security #

  • βœ… Consent-first design
  • βœ… AES-256-CBC encryption
  • βœ… Automatic key management
  • βœ… Anonymized UUIDs
  • βœ… Right to forget (revoke & delete)

🧠 Flux (HSI compute) #

This package includes Flux, a compute pipeline that converts vendor payloads (WHOOP/Garmin) into HSI 1.0 compliant human state signals.

For pub.dev users: Flux native binaries are automatically included - no setup required! Just enable Flux in your config and start using it.

What Flux does:

  • Transforms raw vendor data (WHOOP/Garmin) into standardized HSI 1.0 format
  • Organizes data into daily windows with sleep, physiology, and activity metrics
  • Provides baseline calculations for personalized insights
  • Ensures data privacy with on-device processing

Install (native Rust Flux binaries) #

Flux is implemented in Rust and called via Dart FFI. To activate Flux, your app must bundle the native library for your platform.

For pub.dev Users (Most Developers)

βœ… No setup required! When you install synheart_wear from pub.dev, Flux native binaries are automatically included and bundled with your app. Just add the dependency and use Flux:

dependencies:
  synheart_wear: ^0.2.3
final wear = SynheartWear(
  config: SynheartWearConfig(enableFlux: true),
);
// Flux is ready to use!

For SDK Developers (Source Code)

If you're developing the SDK itself or using it from source, you need to download Flux binaries:

  • Download the pinned Flux release artifacts into vendor/flux/** by running:
bash tool/fetch_flux_binaries.sh
  • Pinned version: vendor/flux/VERSION (tag in the Flux repo)
  • Private releases / rate limits (optional): set FLUX_GITHUB_TOKEN
  • Override version (optional): set FLUX_VERSION=vX.Y.Z
  • Override repo (optional): set FLUX_REPO=org/repo

What gets bundled (by platform)

  • Android: vendor/flux/android/jniLibs/<abi>/libsynheart_flux.so
    Bundled automatically via android/build.gradle (main.jniLibs.srcDirs += ['../vendor/flux/android/jniLibs']).
  • iOS: vendor/flux/ios/SynheartFlux.xcframework
    Bundled automatically via ios/synheart_wear.podspec (adds vendored_frameworks when present).
  • Desktop (optional):
    • macOS: vendor/flux/desktop/mac/macos-arm64/libsynheart_flux.dylib
    • Linux: vendor/flux/desktop/linux/linux-x86_64/libsynheart_flux.so
    • Windows: vendor/flux/desktop/win/synheart_flux.dll

Desktop runtime note (FFI loading)

Vendoring a .dylib/.so/.dll in the package doesn’t automatically copy it into your desktop app bundle. If Flux isn’t found at runtime, either bundle/copy the library into your app, or set one of:

  • SYNHEART_FLUX_LIB_PATH=/absolute/path/to/libsynheart_flux.(dylib|so) (or synheart_flux.dll)
  • SYNHEART_FLUX_VENDOR_DIR=/absolute/path/to/vendor/flux (Flux will try desktop/<platform>/... under this directory)

Where the binaries come from / custom builds

  • Release artifacts: synheart-flux releases
  • Custom binaries: build Flux from source and drop the artifacts into the same vendor/flux/** layout (or point SYNHEART_FLUX_LIB_PATH at your built library).

Activate (runtime check) #

Flux will only run if the native library can be loaded. Check availability before calling:

import 'package:synheart_wear/flux.dart';

if (!isFluxAvailable) {
  // Common causes: missing .so / missing xcframework / not linked into the app.
  throw Exception('Flux not available: $fluxLoadError');
}

The easiest way to use Flux is through SynheartWear.readFluxSnapshot(). This method handles fetching raw vendor data and converting it to HSI format:

import 'dart:convert';
import 'package:synheart_wear/synheart_wear.dart';

// Step 1: Fetch raw data from WHOOP or Garmin
final whoopProvider = WhoopProvider(
  appId: 'your-app-id',
  userId: 'user-123',
);
final rawData = await whoopProvider.fetchRawDataForFlux(
  start: DateTime.now().subtract(const Duration(days: 30)),
  end: DateTime.now(),
);
final rawJson = jsonEncode(rawData);

// Step 2: Process with Flux
final wear = SynheartWear(
  config: SynheartWearConfig(enableFlux: true),
);
final hsiSnapshot = await wear.readFluxSnapshot(
  vendor: Vendor.whoop,
  deviceId: 'whoop-device-123',
  timezone: 'America/New_York',
  rawVendorJson: rawJson,
);

// Step 3: Use HSI data
print('HSI Version: ${hsiSnapshot.hsiVersion}');
print('Windows: ${hsiSnapshot.windows.length}');
print('Observed At: ${hsiSnapshot.observedAtUtc}');
print('Computed At: ${hsiSnapshot.computedAtUtc}');

// Access window data
hsiSnapshot.windows.forEach((windowId, window) {
  if (window.sleep != null) {
    print('Sleep duration: ${window.sleep!.durationMinutes} min');
  }
  if (window.physiology != null) {
    print('Resting HR: ${window.physiology!.restingHrBpm} bpm');
  }
  if (window.activity != null) {
    print('Steps: ${window.activity!.steps}');
  }
});

For Garmin:

final garminProvider = GarminProvider(
  appId: 'your-app-id',
  userId: 'user-123',
);
final rawData = await garminProvider.fetchRawDataForFlux(
  start: DateTime.now().subtract(const Duration(days: 30)),
  end: DateTime.now(),
);
final rawJson = jsonEncode(rawData);

final hsiSnapshot = await wear.readFluxSnapshot(
  vendor: Vendor.garmin,
  deviceId: 'garmin-device-456',
  timezone: 'America/Los_Angeles',
  rawVendorJson: rawJson,
);

Use (stateless - low-level API) #

import 'package:synheart_wear/flux.dart';

final hsiPayloads = whoopToHsiDaily(rawWhoopJson, 'America/New_York', 'device-123');
// or:
// final hsiPayloads = garminToHsiDaily(rawGarminJson, 'America/Los_Angeles', 'device-456');

for (final hsiJson in hsiPayloads) {
  print(hsiJson); // each item is a JSON string (one per day)
}

Use (stateful baselines - low-level API) #

Use this when you need rolling baselines across multiple calls. Don't forget to dispose.

import 'package:synheart_wear/flux.dart';

final processor = FluxProcessor(); // default baseline window = 14 days

final day1 = processor.processWhoop(whoopJsonDay1, 'America/New_York', 'device-123');
final day2 = processor.processWhoop(whoopJsonDay2, 'America/New_York', 'device-123');

final savedBaselinesJson = processor.saveBaselines();
// ... persist savedBaselinesJson somewhere ...

processor.dispose();

Fetching Raw Data for Flux #

Both WhoopProvider and GarminProvider include fetchRawDataForFlux() methods that fetch and format vendor data for Flux processing:

WHOOP:

final whoopProvider = WhoopProvider(appId: 'your-app-id', userId: 'user-123');
final rawData = await whoopProvider.fetchRawDataForFlux(
  start: DateTime.now().subtract(const Duration(days: 30)),
  end: DateTime.now(),
  limit: 50,
);
// Returns: { 'sleep': [...], 'recovery': [...], 'cycle': [...] }

Garmin:

final garminProvider = GarminProvider(appId: 'your-app-id', userId: 'user-123');
final rawData = await garminProvider.fetchRawDataForFlux(
  start: DateTime.now().subtract(const Duration(days: 30)),
  end: DateTime.now(),
);
// Returns: { 'dailies': [...], 'sleep': [...] }

These methods automatically:

  • Fetch data from the appropriate vendor endpoints
  • Transform data to match Flux's expected format
  • Handle missing fields and data validation
  • Return data ready for Flux processing

πŸ“– Additional Resources #


πŸ“‹ Detailed Sections #

Initialization Flow & Best Practices

The SDK supports two initialization patterns:

1. Explicit Permission Control (Recommended):

// Step 1: Create SDK instance
final synheart = SynheartWear(
  config: SynheartWearConfig.withAdapters({DeviceAdapter.appleHealthKit}),
);

// Step 2: Request permissions with reason
final result = await synheart.requestPermissions(
  permissions: {PermissionType.heartRate, PermissionType.steps},
  reason: 'This app needs access to your health data.',
);

// Step 3: Initialize (validates permissions and data)
if (result.values.any((s) => s == ConsentStatus.granted)) {
  await synheart.initialize();
}

2. Automatic Permission Handling:

// Let initialize() handle permissions automatically
final synheart = SynheartWear(
  config: SynheartWearConfig.withAdapters({DeviceAdapter.appleHealthKit}),
);

await synheart.initialize(); // Requests permissions internally if needed

What initialize() Does #

The initialize() method:

  1. Requests permissions (if not already granted)
  2. Initializes all enabled adapters
  3. Validates that wearable data is available
  4. Checks that data is not stale (>24 hours old)

Important: initialize() will throw SynheartWearError if:

  • No wearable data is available (NO_WEARABLE_DATA)
  • Latest data is older than 24 hours (STALE_DATA)
  • Permissions are denied (PERMISSION_DENIED)

Permission Request Behavior #

  • Calling requestPermissions() before initialize() allows you to provide a custom reason
  • initialize() will also request permissions internally if not already granted
  • If permissions are already granted, initialize() will skip the permission request
Data Schema Details

Field Descriptions #

Field Type Description Example
timestamp string (ISO 8601) When data was recorded "2025-10-20T18:30:00Z"
device_id string Unique device identifier "applewatch_1234"
source string Data source adapter "apple_healthkit", "fitbit", "whoop"
metrics.hr number Heart rate (bpm) 72
metrics.hrv_rmssd number HRV RMSSD (ms) 45
metrics.hrv_sdnn number HRV SDNN (ms) 62
metrics.steps number Step count 1045
metrics.calories number Calories (kcal) 120.4
metrics.distance number Distance (km) 2.5
meta.battery number Battery level (0.0-1.0) 0.82 (82%)
meta.synced boolean Sync status true

Notes:

  • Optional fields may be null if unavailable
  • Platform limitations may affect metric availability
  • meta object may contain device-specific fields
Platform-Specific Permission Handling
// Determine platform-specific permissions
Set<PermissionType> permissions;
if (Platform.isAndroid) {
  // Android Health Connect limitations:
  // - HRV: Only RMSSD supported (SDNN not available)
  // - Distance: Not directly supported (would need DISTANCE_DELTA)
  permissions = {
    PermissionType.heartRate,
    PermissionType.heartRateVariability, // Maps to RMSSD on Android
    PermissionType.steps,
    PermissionType.calories,
    // Note: Distance is not included as Health Connect doesn't support it
  };
} else {
  // iOS HealthKit supports all metrics
  permissions = {
    PermissionType.heartRate,
    PermissionType.heartRateVariability, // Supports both RMSSD and SDNN
    PermissionType.steps,
    PermissionType.calories,
    PermissionType.distance,
  };
}

final result = await synheart.requestPermissions(
  permissions: permissions,
  reason: 'This app needs access to your health data.',
);

// Check if permissions were granted before initializing
if (result.values.any((s) => s == ConsentStatus.granted)) {
  await synheart.initialize();
} else {
  // Handle permission denial
  print('Permissions were not granted');
}
Usage Examples

Complete Health Monitoring App #

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:synheart_wear/synheart_wear.dart';

class HealthMonitor extends StatefulWidget {
  @override
  _HealthMonitorState createState() => _HealthMonitorState();
}

class _HealthMonitorState extends State<HealthMonitor> {
  late SynheartWear _sdk;
  StreamSubscription<WearMetrics>? _hrSubscription;
  WearMetrics? _latestMetrics;
  bool _isConnected = false;

  @override
  void initState() {
    super.initState();
    _sdk = SynheartWear(
      config: SynheartWearConfig.withAdapters({DeviceAdapter.appleHealthKit}),
    );
  }

  Future<void> _connect() async {
    try {
      // Step 1: Request permissions
      final result = await _sdk.requestPermissions(
        permissions: {
          PermissionType.heartRate,
          PermissionType.steps,
          PermissionType.calories,
        },
        reason: 'This app needs access to your health data.',
      );

      // Step 2: Initialize if permissions granted
      if (result.values.any((s) => s == ConsentStatus.granted)) {
        await _sdk.initialize();
        
        // Step 3: Read initial metrics
        final metrics = await _sdk.readMetrics();
        setState(() {
          _isConnected = true;
          _latestMetrics = metrics;
        });
      } else {
        setState(() {
          _isConnected = false;
          // Show error: permissions denied
        });
      }
    } on SynheartWearError catch (e) {
      // Handle SDK-specific errors (NO_WEARABLE_DATA, STALE_DATA, etc.)
      print('SDK Error: $e');
      setState(() {
        _isConnected = false;
        // Show error message
      });
    } catch (e) {
      // Handle other errors
      print('Error: $e');
      setState(() {
        _isConnected = false;
      });
    }
  }

  void _startStreaming() {
    _hrSubscription = _sdk.streamHR(interval: Duration(seconds: 3))
      .listen((metrics) {
        setState(() => _latestMetrics = metrics);
      });
  }

  @override
  void dispose() {
    _hrSubscription?.cancel();
    _sdk.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Health Monitor')),
      body: _isConnected
          ? Column(
              children: [
                if (_latestMetrics != null) ...[
                  Text('HR: ${_latestMetrics!.getMetric(MetricType.hr)} bpm'),
                  Text('Steps: ${_latestMetrics!.getMetric(MetricType.steps)}'),
                ],
                ElevatedButton(
                  onPressed: _startStreaming,
                  child: Text('Start Streaming'),
                ),
              ],
            )
          : Center(
              child: ElevatedButton(
                onPressed: _connect,
                child: Text('Connect to Health'),
              ),
            ),
    );
  }
}

Error Handling #

try {
  // Request permissions
  final result = await synheart.requestPermissions(
    permissions: {PermissionType.heartRate, PermissionType.steps},
    reason: 'This app needs access to your health data.',
  );

  if (result.values.any((s) => s == ConsentStatus.granted)) {
    // Initialize (may throw if no data or stale data)
    await synheart.initialize();
    
    // Read metrics
    final metrics = await synheart.readMetrics();
    if (metrics.hasValidData) {
      print('Data available');
    }
  }
} on PermissionDeniedError catch (e) {
  print('Permission denied: $e');
  // User denied permissions - show message or retry
} on DeviceUnavailableError catch (e) {
  print('Device unavailable: $e');
  // Health data source not available - check device connection
} on SynheartWearError catch (e) {
  // Handle SDK-specific errors
  if (e.code == 'NO_WEARABLE_DATA') {
    print('No wearable data available. Please check device connection.');
  } else if (e.code == 'STALE_DATA') {
    print('Data is stale. Please sync your wearable device.');
  } else {
    print('SDK error: $e');
  }
} catch (e) {
  print('Unexpected error: $e');
}

Common Error Codes:

  • NO_WEARABLE_DATA: No health data available from connected devices
  • STALE_DATA: Latest data is older than 24 hours
  • PERMISSION_DENIED: User denied required permissions
  • DEVICE_UNAVAILABLE: Health data source is not available
Architecture
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   synheart_wear SDK     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Device Adapters Layer   β”‚
β”‚ (Apple, Fitbit, etc.)   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Normalization Engine    β”‚
β”‚ (standard output schema)β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   Local Cache & Storage β”‚
β”‚   (encrypted, offline)  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Roadmap
Version Goal Status
v0.1 Core SDK βœ… Complete
v0.2 Real-time streaming βœ… Complete
v0.3 Extended device support πŸ”„ In Progress
v0.4 SWIP integration πŸ“‹ Planned
v1.0 Public Release πŸ“‹ Planned

🀝 Contributing #

We welcome contributions! Please see our Contributing Guidelines or:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“„ License #

Apache 2.0 License

πŸ‘₯ Authors #

  • Israel Goytom - Initial work - @isrugeek
  • Synheart AI Team - RFC Design & Architecture

Made with ❀️ by the Synheart AI Team

Technology with a heartbeat.

Patent Pending Notice #

This project is provided under an open-source license. Certain underlying systems, methods, and architectures described or implemented herein may be covered by one or more pending patent applications.

Nothing in this repository grants any license, express or implied, to any patents or patent applications, except as provided by the applicable open-source license.

6
likes
120
points
133
downloads

Publisher

verified publishersynheart.ai

Weekly Downloads

Unified wearable SDK for Synheart (HR, HRV, steps, energy, stress).

Documentation

API reference

License

unknown (license)

Dependencies

collection, encrypt, ffi, flutter, health, http, path_provider, platform, shared_preferences, url_launcher, uuid

More

Packages that depend on synheart_wear

Packages that implement synheart_wear