Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
package edu.kit.teco.openWearable

import android.content.Intent
import android.provider.Settings
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity: FlutterActivity()
class MainActivity : FlutterActivity() {
companion object {
private const val SYSTEM_SETTINGS_CHANNEL = "edu.kit.teco.open_wearable/system_settings"
}

override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)

MethodChannel(
flutterEngine.dartExecutor.binaryMessenger,
SYSTEM_SETTINGS_CHANNEL,
).setMethodCallHandler { call, result ->
if (call.method == "openBluetoothSettings") {
try {
val intent = Intent(Settings.ACTION_BLUETOOTH_SETTINGS).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
startActivity(intent)
result.success(true)
} catch (_: Exception) {
result.success(false)
}
} else {
result.notImplemented()
}
}
}
}
66 changes: 64 additions & 2 deletions open_wearable/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,40 @@ import UIKit

@main
@objc class AppDelegate: FlutterAppDelegate {
private var sensorShutdownBackgroundTask: UIBackgroundTaskIdentifier = .invalid
private var lifecycleChannel: FlutterMethodChannel?

private func beginSensorShutdownBackgroundTask() {
guard sensorShutdownBackgroundTask == .invalid else {
return
}

sensorShutdownBackgroundTask = UIApplication.shared.beginBackgroundTask(
withName: "SensorShutdown"
) { [weak self] in
self?.endSensorShutdownBackgroundTask()
}
}

private func endSensorShutdownBackgroundTask() {
guard sensorShutdownBackgroundTask != .invalid else {
return
}

UIApplication.shared.endBackgroundTask(sensorShutdownBackgroundTask)
sensorShutdownBackgroundTask = .invalid
}

override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(name: "edu.teco.open_folder", binaryMessenger: controller.binaryMessenger)
let openFolderChannel = FlutterMethodChannel(name: "edu.teco.open_folder", binaryMessenger: controller.binaryMessenger)
let systemSettingsChannel = FlutterMethodChannel(name: "edu.kit.teco.open_wearable/system_settings", binaryMessenger: controller.binaryMessenger)
lifecycleChannel = FlutterMethodChannel(name: "edu.kit.teco.open_wearable/lifecycle", binaryMessenger: controller.binaryMessenger)

channel.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) in
openFolderChannel.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) in
if call.method == "openFolder", let args = call.arguments as? [String: Any], let path = args["path"] as? String {
guard let url = URL(string: path) else {
result(FlutterError(code: "INVALID_ARGUMENT", message: "Invalid folder path", details: nil))
Expand All @@ -27,6 +53,42 @@ import UIKit
}
}

systemSettingsChannel.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) in
if call.method == "openBluetoothSettings" {
guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
result(false)
return
}

if UIApplication.shared.canOpenURL(settingsUrl) {
UIApplication.shared.open(settingsUrl, options: [:]) { success in
result(success)
}
} else {
result(false)
}
} else {
result(FlutterMethodNotImplemented)
}
}

lifecycleChannel?.setMethodCallHandler { [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) in
guard let self = self else {
result(false)
return
}

if call.method == "beginBackgroundExecution" {
self.beginSensorShutdownBackgroundTask()
result(true)
} else if call.method == "endBackgroundExecution" {
self.endSensorShutdownBackgroundTask()
result(true)
} else {
result(FlutterMethodNotImplemented)
}
}

GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
Expand Down
33 changes: 30 additions & 3 deletions open_wearable/lib/apps/heart_tracker/model/band_pass_filter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,35 @@ class BandPassFilter {
late final double a0, a1, a2, b1, b2;
double x1 = 0, x2 = 0;
double y1 = 0, y2 = 0;
bool _isInitialized = false;

BandPassFilter({
required this.sampleFreq,
required this.lowCut,
required this.highCut,
}) {
final centerFreq = sqrt(lowCut * highCut);
final bandwidth = highCut - lowCut;
final safeSampleFreq =
sampleFreq.isFinite && sampleFreq > 0 ? sampleFreq : 50.0;
final nyquist = safeSampleFreq / 2.0;

var safeLow = lowCut;
if (!safeLow.isFinite || safeLow <= 0) {
safeLow = 0.45;
}

var safeHigh = highCut;
if (!safeHigh.isFinite || safeHigh <= safeLow) {
safeHigh = safeLow + 0.6;
}
safeHigh = min(safeHigh, nyquist - 0.05);
safeLow = min(safeLow, safeHigh - 0.15);
safeLow = max(0.05, safeLow);

final centerFreq = sqrt(safeLow * safeHigh);
final bandwidth = max(0.15, safeHigh - safeLow);
final q = centerFreq / bandwidth;

final omega = 2 * pi * centerFreq / sampleFreq;
final omega = 2 * pi * centerFreq / safeSampleFreq;
final alpha = sin(omega) / (2 * q);

final cosOmega = cos(omega);
Expand All @@ -32,6 +50,15 @@ class BandPassFilter {
}

double filter(double x) {
if (!_isInitialized) {
_isInitialized = true;
x1 = x;
x2 = x;
y1 = 0;
y2 = 0;
return 0;
}

final y = a0 * x + a1 * x1 + a2 * x2 - b1 * y1 - b2 * y2;
x2 = x1;
x1 = x;
Expand Down
Loading