Skip to content
This repository has been archived by the owner on Sep 17, 2024. It is now read-only.

Commit

Permalink
Merge pull request #248 from MXCzkEVM/blueberry_ring
Browse files Browse the repository at this point in the history
Blueberry ring
  • Loading branch information
reasje authored Jul 10, 2024
2 parents 39edc0f + 94d2133 commit b1f08f1
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 44 deletions.
5 changes: 4 additions & 1 deletion assets/flutter_i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,9 @@
"activity_reminder": "Activity reminder",
"sleep_insight": "Sleep insight",
"heart_alert": "Heart alert",
"low_battery": "Low battery"
"low_battery": "Low battery",
"blueberry_background_notifications_requirements_title": "This service requires: ",
"blueberry_background_notifications_requirements_text_1": "1. Bluetooth to be ON",
"blueberry_background_notifications_requirements_text_2": "2. Blueberry to be reachable"

}
16 changes: 11 additions & 5 deletions assets/js/bluetooth/bluetooth.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,18 +125,23 @@ class BluetoothRemoteGATTCharacteristic extends EventTarget {
);
return response;
}

async readValue() {
const data = { this: this.uuid, serviceUUID: this.service.uuid };
const response = await window.axs.callHandler(
"BluetoothRemoteGATTCharacteristic.readValue",
data
);
return response;

const bytes = new Uint8Array(response);
console.log("Bytes : ", bytes);
const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
selectedCharacteristic.value = dv;

return dv;
}

async writeValue(value) {
// We will need to change the value to Base64 for having a standard type to bridge data on that type.

const data = {
this: this.uuid,
serviceUUID: this.service.uuid,
Expand Down Expand Up @@ -295,9 +300,10 @@ class AXSBluetooth {
}
}

updateCharacteristicValue(characteristicUUID, base64String) {
const bytes = new Uint8Array(base64String);
updateCharacteristicValue(characteristicUUID, value) {
const bytes = new Uint8Array(value);
console.log("Bytes : ", bytes);
console.log("Bytes type: ", typeof bytes);
const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
let selectedCharacteristic =
this.getCharacteristicByUUID(characteristicUUID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import 'package:mxc_logic/mxc_logic.dart';
import 'package:datadashwallet/core/core.dart';
import 'package:datadashwallet/features/settings/subfeatures/chain_configuration/domain/chain_configuration_use_case.dart';

import '../../../../../../app/logger.dart';

class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase {
BlueberryRingBackgroundNotificationsUseCase(
this._repository,
Expand All @@ -25,6 +27,7 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase {

Future<void> checkActivityReminder() async {
final data = await _blueberryRingUseCase.readSteps();
collectLog('checkActivityReminder:data ${data.map((e) => e.toJson()).toList()}');
// Get spteps data from cache and compare
// If steps is below a certain number then show a
// Below 5000
Expand All @@ -39,14 +42,15 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase {

if (isToday && latestData.step < 5000) {
AXSNotification().showNotification(
cTranslate('blueberry_ring_inactive_alert_title'),
cTranslate('activity_reminder'),
cTranslate('blueberry_ring_inactive_alert_text'),
);
}
}

Future<void> checkSleepInsight() async {
final data = await _blueberryRingUseCase.readSleep();
collectLog('checkSleepInsight:data ${data.map((e) => e.toJson()).toList()}');
// If sleeps is below standard level
// loop throug all and get average
final now = DateTime.now();
Expand All @@ -69,14 +73,15 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase {

if (!isNormal) {
AXSNotification().showNotification(
cTranslate('blueberry_ring_sleep_alert_title'),
cTranslate('sleep_insight'),
cTranslate('blueberry_ring_sleep_alert_text'),
);
}
}

Future<void> checkHeartAlert() async {
final data = await _blueberryRingUseCase.readHeartRate();
collectLog('checkHeartAlert:data ${data.map((e) => e.toJson()).toList()}');
// If below standard but between person to person different
final latestData = data.first;
final lastDate = DateTime.fromMillisecondsSinceEpoch(
Expand All @@ -89,19 +94,20 @@ class BlueberryRingBackgroundNotificationsUseCase extends ReactiveUseCase {

if (isToday && latestData.value >= 100) {
AXSNotification().showNotification(
cTranslate('blueberry_ring_heart_rate_alert_title'),
cTranslate('heart_alert'),
cTranslate('blueberry_ring_heart_rate_alert_text'),
);
}
}

Future<void> checkLowBattery() async {
final data = await _blueberryRingUseCase.readLevel();
collectLog('checkLowBattery:data $data');
// What si the low battery level
// Is 10 OK
if (data < 20) {
AXSNotification().showNotification(
cTranslate('blueberry_ring_battery_alert_title'),
cTranslate('low_battery'),
cTranslate('blueberry_ring_battery_alert_text'),
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:typed_data';

import 'package:datadashwallet/app/logger.dart';
import 'package:datadashwallet/common/common.dart';
import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
Expand Down Expand Up @@ -52,9 +53,9 @@ class BlueberryRingUseCase extends ReactiveUseCase {

Future<void> getBlueberryRingBackground() async {
// if (bluetoothStatus.value == BluetoothAdapterState.off || bluetoothStatus.value = BluetoothAdapterState.unauthorized)
// TODO: bluetooth should be on before bg notifications
_bluetoothUseCase.startScanning(
withServices: [bluetoothServiceUUID],
// withServices: [bluetoothServiceUUID],
withNames: ['Mi Smart Band 4']
);

await Future.delayed(const Duration(seconds: 2), () async {
Expand Down Expand Up @@ -107,14 +108,18 @@ class BlueberryRingUseCase extends ReactiveUseCase {

/// This function will check the blueberry ring, connection
Future<T> checkEstablishment<T>(Future<T> Function() func) async {
final isBlueberryRingAvailable = selectedBlueberryRing.value != null;
collectLog('checkEstablishment');

final isBlueberryRingAvailable = selectedBlueberryRing.hasValue;
collectLog('checkEstablishment:isBlueberryRingAvailable $isBlueberryRingAvailable');

if (!isBlueberryRingAvailable) {
await getBlueberryRingBackground();
}

bool isBlueberryRingConnected =
selectedBlueberryRing.value?.device.isConnected ?? false;
collectLog('checkEstablishment:isBlueberryRingConnected $isBlueberryRingConnected');

if (!isBlueberryRingConnected) {
await selectedBlueberryRing.value?.device.connect();
Expand All @@ -126,7 +131,8 @@ class BlueberryRingUseCase extends ReactiveUseCase {
}

final isBlueberryRingCharacteristicAvailable =
blueberryRingCharacteristic.value != null;
blueberryRingCharacteristic.hasValue;
collectLog('checkEstablishment:isBlueberryRingCharacteristicAvailable $isBlueberryRingCharacteristicAvailable');
if (!isBlueberryRingCharacteristicAvailable) {
await getBlueberryRingCharacteristic();
}
Expand All @@ -138,8 +144,10 @@ class BlueberryRingUseCase extends ReactiveUseCase {
return checkEstablishment<int>(
() async {
final command = BlueberryCommands.readLevel();
collectLog('readLevel:command $command');
await blueberryRingCharacteristic.value?.write(command);
final value = await blueberryRingCharacteristic.value?.read();
collectLog('readLevel:value $value');
return BlueberryResolves.readLevel(Uint8List.fromList(value!));
},
);
Expand All @@ -149,8 +157,10 @@ class BlueberryRingUseCase extends ReactiveUseCase {
return checkEstablishment<String>(
() async {
final command = BlueberryCommands.readVersion();
collectLog('readVersion:command $command');
await blueberryRingCharacteristic.value?.write(command);
final value = await blueberryRingCharacteristic.value?.read();
collectLog('readVersion:value $value');
return BlueberryResolves.readVersion(Uint8List.fromList(value!));
},
);
Expand All @@ -160,8 +170,10 @@ class BlueberryRingUseCase extends ReactiveUseCase {
return checkEstablishment<Uint8List>(
() async {
final command = BlueberryCommands.readTime();
collectLog('readTime:command $command');
await blueberryRingCharacteristic.value?.write(command);
final value = await blueberryRingCharacteristic.value?.read();
collectLog('readTime:value $value');
return BlueberryResolves.readTime(Uint8List.fromList(value!));
},
);
Expand All @@ -171,8 +183,10 @@ class BlueberryRingUseCase extends ReactiveUseCase {
return checkEstablishment<List<PeriodicSleepData>>(
() async {
final command = BlueberryCommands.readSleep();
collectLog('readSleep:command $command');
await blueberryRingCharacteristic.value?.write(command);
final value = await blueberryRingCharacteristic.value?.read();
collectLog('readSleep:value $value');
return BlueberryResolves.readSleep(Uint8List.fromList(value!));
},
);
Expand All @@ -182,8 +196,10 @@ class BlueberryRingUseCase extends ReactiveUseCase {
return checkEstablishment<List<BloodOxygensData>>(
() async {
final command = BlueberryCommands.readBloodOxygens();
collectLog('readBloodOxygens:command $command');
await blueberryRingCharacteristic.value?.write(command);
final value = await blueberryRingCharacteristic.value?.read();
collectLog('readBloodOxygens:value $value');
return BlueberryResolves.readBloodOxygens(Uint8List.fromList(value!));
},
);
Expand All @@ -193,8 +209,10 @@ class BlueberryRingUseCase extends ReactiveUseCase {
return checkEstablishment<List<StepsData>>(
() async {
final command = BlueberryCommands.readSteps();
collectLog('readSteps:command $command');
await blueberryRingCharacteristic.value?.write(command);
final value = await blueberryRingCharacteristic.value?.read();
collectLog('readSteps:value $value');
return BlueberryResolves.readSteps(Uint8List.fromList(value!));
},
);
Expand All @@ -204,8 +222,10 @@ class BlueberryRingUseCase extends ReactiveUseCase {
return checkEstablishment<List<HeartRateData>>(
() async {
final command = BlueberryCommands.readHeartRates();
collectLog('readHeartRate:command $command');
await blueberryRingCharacteristic.value?.write(command);
final value = await blueberryRingCharacteristic.value?.read();
collectLog('readHeartRate:value $value');
return BlueberryResolves.readHeartRates(Uint8List.fromList(value!));
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:convert';
import 'dart:developer';
import 'package:clipboard/clipboard.dart';
import 'package:collection/collection.dart';
import 'package:datadashwallet/app/logger.dart';
import 'package:datadashwallet/common/common.dart';
import 'package:datadashwallet/core/core.dart';
import 'package:datadashwallet/features/common/common.dart';
Expand Down Expand Up @@ -844,6 +845,7 @@ class OpenDAppPresenter extends CompletePresenter<OpenDAppState> {
final value = Uint8List.fromList(List<int>.from(data['value']));

try {
collectLog('handleWrites:value $value');
if (withResponse) {
await selectedCharacteristic.write(value);
} else {
Expand Down Expand Up @@ -881,9 +883,11 @@ class OpenDAppPresenter extends CompletePresenter<OpenDAppState> {
final value = selectedCharacteristic.lastValue;

final uInt8List = Uint8List.fromList(value);
final base64String = base64Encode(uInt8List);

return base64String;
collectLog('characteristicValueStreamSubscription:value $value');
collectLog('characteristicValueStreamSubscription:uInt8List ${uInt8List.toString()}');

return uInt8List;
}

Timer? characteriticListnerTimer;
Expand All @@ -901,7 +905,8 @@ class OpenDAppPresenter extends CompletePresenter<OpenDAppState> {
characteristic.lastValueStream.listen((event) {
final uInt8List = Uint8List.fromList(event);
print(uInt8List);
print('lastValueStream');
collectLog('characteristicValueStreamSubscription:event $event');
collectLog('characteristicValueStreamSubscription:uInt8List ${uInt8List.toString()}');
final script = '''
navigator.bluetooth.updateCharacteristicValue('${characteristic.uuid.str}', ${uInt8List.toString()},);
''';
Expand Down
Loading

0 comments on commit b1f08f1

Please sign in to comment.