Skip to content

Commit

Permalink
Unsupported gear check and initial min version work
Browse files Browse the repository at this point in the history
  • Loading branch information
Codel1417 committed May 22, 2024
1 parent fa96d3b commit d93d3a8
Show file tree
Hide file tree
Showing 11 changed files with 210 additions and 124 deletions.
3 changes: 2 additions & 1 deletion lib/Backend/Bluetooth/bluetooth_manager_plus.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import 'package:tail_app/Backend/Definitions/Device/device_definition.dart';
import 'package:tail_app/Backend/device_registry.dart';
import 'package:wakelock_plus/wakelock_plus.dart';

import '../../Frontend/utils.dart';
import '../../constants.dart';
import '../sensors.dart';
import 'bluetooth_manager.dart';
Expand Down Expand Up @@ -208,7 +209,7 @@ Future<void> initFlutterBluePlus(InitFlutterBluePlusRef ref) async {
statefulDevice.messageHistory.add(MessageHistoryEntry(type: MessageHistoryType.receive, message: value));
// Firmware Version
if (value.startsWith("VER")) {
statefulDevice.fwVersion.value = value.substring(value.indexOf(" "));
statefulDevice.fwVersion.value = getVersionSemVer(value.substring(value.indexOf(" ")));
// Sent after VER message
} else if (value.startsWith("GLOWTIP")) {
statefulDevice.hasGlowtip.value = "TRUE" == value.substring(value.indexOf(" "));
Expand Down
31 changes: 19 additions & 12 deletions lib/Backend/Definitions/Device/device_definition.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hive/hive.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:tail_app/Backend/Bluetooth/bluetooth_manager.dart';
import 'package:tail_app/Backend/Bluetooth/bluetooth_manager_plus.dart';
Expand Down Expand Up @@ -67,8 +68,10 @@ class BaseDeviceDefinition {
final String bleTxCharacteristic;
final DeviceType deviceType;
final String fwURL;
final Version? minVersion;
final bool unsupported;

const BaseDeviceDefinition(this.uuid, this.btName, this.bleDeviceService, this.bleRxCharacteristic, this.bleTxCharacteristic, this.deviceType, this.fwURL);
const BaseDeviceDefinition({required this.uuid, required this.btName, required this.bleDeviceService, required this.bleRxCharacteristic, required this.bleTxCharacteristic, required this.deviceType, this.fwURL = "", this.minVersion, this.unsupported = false});

@override
String toString() {
Expand All @@ -85,7 +88,7 @@ class BaseStatefulDevice extends ChangeNotifier {
final ValueNotifier<bool> batteryLow = ValueNotifier(false);
final ValueNotifier<bool> gearReturnedError = ValueNotifier(false);

final ValueNotifier<String> fwVersion = ValueNotifier("");
final ValueNotifier<Version> fwVersion = ValueNotifier(Version.none);
final ValueNotifier<String> hwVersion = ValueNotifier("");
final ValueNotifier<bool> hasGlowtip = ValueNotifier(false);
final ValueNotifier<DeviceState> deviceState = ValueNotifier(DeviceState.standby);
Expand All @@ -102,7 +105,7 @@ class BaseStatefulDevice extends ChangeNotifier {
Stopwatch stopWatch = Stopwatch();
bool disableAutoConnect = false;
bool forgetOnDisconnect = false;

ValueNotifier<bool> mandatoryOtaRequired = ValueNotifier(false);
final CircularBuffer<MessageHistoryEntry> messageHistory = CircularBuffer(50);

BaseStatefulDevice(this.baseDeviceDefinition, this.baseStoredDevice, this.ref) {
Expand All @@ -116,7 +119,7 @@ class BaseStatefulDevice extends ChangeNotifier {
reset();
} else if (deviceConnectionState.value == ConnectivityState.connected) {
// Add initial commands to the queue
Future.delayed(const Duration(seconds: 5), () {
Future.delayed(const Duration(seconds: 2), () {
commandQueue.addCommand(BluetoothMessage(message: "VER", device: this, priority: Priority.low, type: Type.system, responseMSG: "VER "));
commandQueue.addCommand(BluetoothMessage(message: "HWVER", device: this, priority: Priority.low, type: Type.system, responseMSG: "HWVER "));
});
Expand All @@ -127,11 +130,19 @@ class BaseStatefulDevice extends ChangeNotifier {
batteryLow.value = batteryLevel.value < 20;
});
fwInfo.addListener(() {
if (fwInfo.value != null && fwVersion.value.isNotEmpty) {
if (fwInfo.value?.version.split(" ")[1] != fwVersion.value) {
hasUpdate.value = true;
if (fwInfo.value != null && fwVersion.value.compareTo(Version.none) > 0 && fwVersion.value.compareTo(Version.parse(fwInfo.value!.version)) < 0) {
hasUpdate.value = true;
}
});
fwVersion.addListener(() {
if (baseDeviceDefinition.minVersion != null) {
if (baseDeviceDefinition.minVersion!.compareTo(fwVersion.value) < 0) {
mandatoryOtaRequired.value = true;
}
}
if (fwInfo.value != null && fwVersion.value.compareTo(Version.none) > 0 && fwVersion.value.compareTo(getVersionSemVer(fwInfo.value!.version)) < 0) {
hasUpdate.value = true;
}
});
getFirmwareInfo();
}
Expand All @@ -148,11 +159,6 @@ class BaseStatefulDevice extends ChangeNotifier {
(value) {
if (value.statusCode == 200) {
fwInfo.value = FWInfo.fromJson(const JsonDecoder().convert(value.data.toString()));
if (fwVersion.value != "") {
if (fwInfo.value?.version.split(" ")[1] != fwVersion.value) {
hasUpdate.value = true;
}
}
}
},
).onError((error, stackTrace) {
Expand All @@ -172,6 +178,7 @@ class BaseStatefulDevice extends ChangeNotifier {
batlevels = [];
stopWatch.reset();
mtu.value = -1;
mandatoryOtaRequired.value = false;
}
}

Expand Down
98 changes: 50 additions & 48 deletions lib/Backend/device_registry.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:logging/logging.dart' as log;
import 'package:pub_semver/pub_semver.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:tail_app/Backend/Bluetooth/bluetooth_manager.dart';
import 'package:tail_app/Backend/Definitions/Action/base_action.dart';
Expand All @@ -12,60 +13,61 @@ final deviceRegistryLogger = log.Logger('DeviceRegistry');
@immutable
class DeviceRegistry {
static Set<BaseDeviceDefinition> allDevices = {
BaseDeviceDefinition(
uuid: "798e1528-2832-4a87-93d7-4d1b25a2f418",
btName: "MiTail",
bleDeviceService: "3af2108b-d066-42da-a7d4-55648fa0a9b6",
bleRxCharacteristic: "c6612b64-0087-4974-939e-68968ef294b0",
bleTxCharacteristic: "5bfd6484-ddee-4723-bfe6-b653372bbfd6",
deviceType: DeviceType.tail,
fwURL: "https://thetailcompany.com/fw/mitail",
minVersion: Version(5, 0, 0)),
const BaseDeviceDefinition(
"798e1528-2832-4a87-93d7-4d1b25a2f418",
"MiTail",
"3af2108b-d066-42da-a7d4-55648fa0a9b6",
"c6612b64-0087-4974-939e-68968ef294b0",
"5bfd6484-ddee-4723-bfe6-b653372bbfd6",
DeviceType.tail,
"https://thetailcompany.com/fw/mitail",
uuid: "9c5f3692-1c6e-4d46-b607-4f6f4a6e28ee",
btName: "(!)Tail1",
bleDeviceService: "3af2108b-d066-42da-a7d4-55648fa0a9b6",
bleRxCharacteristic: "c6612b64-0087-4974-939e-68968ef294b0",
bleTxCharacteristic: "5bfd6484-ddee-4723-bfe6-b653372bbfd6",
deviceType: DeviceType.tail,
unsupported: true),
BaseDeviceDefinition(
uuid: "5fb21175-fef4-448a-a38b-c472d935abab",
btName: "minitail",
bleDeviceService: "3af2108b-d066-42da-a7d4-55648fa0a9b6",
bleRxCharacteristic: "c6612b64-0087-4974-939e-68968ef294b0",
bleTxCharacteristic: "5bfd6484-ddee-4723-bfe6-b653372bbfd6",
deviceType: DeviceType.tail,
fwURL: "https://thetailcompany.com/fw/mini",
minVersion: Version(5, 0, 0),
),
const BaseDeviceDefinition(
"9c5f3692-1c6e-4d46-b607-4f6f4a6e28ee",
"(!)Tail1",
"3af2108b-d066-42da-a7d4-55648fa0a9b6",
"c6612b64-0087-4974-939e-68968ef294b0",
"5bfd6484-ddee-4723-bfe6-b653372bbfd6",
DeviceType.tail,
"",
),
const BaseDeviceDefinition(
"5fb21175-fef4-448a-a38b-c472d935abab",
"minitail",
"3af2108b-d066-42da-a7d4-55648fa0a9b6",
"c6612b64-0087-4974-939e-68968ef294b0",
"5bfd6484-ddee-4723-bfe6-b653372bbfd6",
DeviceType.tail,
"https://thetailcompany.com/fw/mini",
BaseDeviceDefinition(
uuid: "e790f509-f95b-4eb4-b649-5b43ee1eee9c",
btName: "flutter",
bleDeviceService: "3af2108b-d066-42da-a7d4-55648fa0a9b6",
bleRxCharacteristic: "c6612b64-0087-4974-939e-68968ef294b0",
bleTxCharacteristic: "5bfd6484-ddee-4723-bfe6-b653372bbfd6",
deviceType: DeviceType.wings,
fwURL: "https://thetailcompany.com/fw/flutter",
minVersion: Version(5, 0, 0),
),
const BaseDeviceDefinition(
"e790f509-f95b-4eb4-b649-5b43ee1eee9c",
"flutter",
"3af2108b-d066-42da-a7d4-55648fa0a9b6",
"c6612b64-0087-4974-939e-68968ef294b0",
"5bfd6484-ddee-4723-bfe6-b653372bbfd6",
DeviceType.wings,
"https://thetailcompany.com/fw/flutter",
uuid: "927dee04-ddd4-4582-8e42-69dc9fbfae66",
btName: "EG2",
bleDeviceService: "927dee04-ddd4-4582-8e42-69dc9fbfae66",
bleRxCharacteristic: "0b646a19-371e-4327-b169-9632d56c0e84",
bleTxCharacteristic: "05e026d8-b395-4416-9f8a-c00d6c3781b9",
deviceType: DeviceType.ears,
fwURL: "https://thetailcompany.com/fw/eg",
),
const BaseDeviceDefinition(
"927dee04-ddd4-4582-8e42-69dc9fbfae66",
"EG2",
"927dee04-ddd4-4582-8e42-69dc9fbfae66",
"0b646a19-371e-4327-b169-9632d56c0e84",
"05e026d8-b395-4416-9f8a-c00d6c3781b9",
DeviceType.ears,
"https://thetailcompany.com/fw/eg",
),
const BaseDeviceDefinition(
"ba2f2b00-8f65-4cc3-afad-58ba1fccd62d",
"EarGear",
"927dee04-ddd4-4582-8e42-69dc9fbfae66",
"0b646a19-371e-4327-b169-9632d56c0e84",
"05e026d8-b395-4416-9f8a-c00d6c3781b9",
DeviceType.ears,
"",
),
uuid: "ba2f2b00-8f65-4cc3-afad-58ba1fccd62d",
btName: "EarGear",
bleDeviceService: "927dee04-ddd4-4582-8e42-69dc9fbfae66",
bleRxCharacteristic: "0b646a19-371e-4327-b169-9632d56c0e84",
bleTxCharacteristic: "05e026d8-b395-4416-9f8a-c00d6c3781b9",
deviceType: DeviceType.ears,
unsupported: true,
)
};

static BaseDeviceDefinition getByUUID(String uuid) {
Expand Down
23 changes: 23 additions & 0 deletions lib/Frontend/Widgets/base_card.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import 'package:flutter/material.dart';

class BaseCard extends StatelessWidget {
const BaseCard({super.key, required this.child, this.elevation = 1, this.color});

final double elevation;
final Widget child;
final Color? color;

@override
Widget build(BuildContext context) {
return Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
color: color,
elevation: elevation,
child: child,
),
),
);
}
}
29 changes: 24 additions & 5 deletions lib/Frontend/Widgets/known_gear.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ class KnownGear extends ConsumerStatefulWidget {
class _KnownGearState extends ConsumerState<KnownGear> {
@override
Widget build(BuildContext context) {
List<BaseStatefulDevice> knownDevices = ref.watch(knownDevicesProvider).values.toList();
List<BaseStatefulDevice> knownDevices = ref
.watch(knownDevicesProvider)
.values
.toList();
return Row(
children: [
...knownDevices.map((BaseStatefulDevice baseStatefulDevice) => KnownGearCard(baseStatefulDevice: baseStatefulDevice)),
Expand All @@ -45,7 +48,10 @@ class ScanForNewGearButton extends ConsumerWidget {
padding: const EdgeInsets.all(8.0),
child: SizedBox(
height: 50 * MediaQuery.textScalerOf(context).scale(1),
width: ref.watch(knownDevicesProvider).values.length > 1 ? 100 * MediaQuery.textScalerOf(context).scale(1) : 200 * MediaQuery.textScalerOf(context).scale(1),
width: ref
.watch(knownDevicesProvider)
.values
.length > 1 ? 100 * MediaQuery.textScalerOf(context).scale(1) : 200 * MediaQuery.textScalerOf(context).scale(1),
child: Center(
child: Text(
scanDevicesTitle(),
Expand All @@ -72,7 +78,10 @@ class ScanForNewGearButton extends ConsumerWidget {
ListTile(
title: Text(
scanDevicesTitle(),
style: Theme.of(context).textTheme.titleLarge,
style: Theme
.of(context)
.textTheme
.titleLarge,
),
),
Expanded(
Expand Down Expand Up @@ -116,7 +125,9 @@ class _KnownGearCardState extends ConsumerState<KnownGearCard> {
return Badge(
isLabelVisible: value,
largeSize: 35,
backgroundColor: Theme.of(context).primaryColor,
backgroundColor: Theme
.of(context)
.primaryColor,
label: const Icon(Icons.system_update),
child: child,
);
Expand Down Expand Up @@ -190,6 +201,12 @@ class _KnownGearCardState extends ConsumerState<KnownGearCard> {
);
},
),
AnimatedCrossFade(
firstChild: const Icon(Icons.warning),
secondChild: Container(),
crossFadeState: widget.baseStatefulDevice.baseDeviceDefinition.unsupported ? CrossFadeState.showFirst : CrossFadeState.showSecond,
duration: animationTransitionDuration,
),
ValueListenableBuilder(
valueListenable: widget.baseStatefulDevice.rssi,
builder: (BuildContext context, value, Widget? child) {
Expand All @@ -215,7 +232,9 @@ class _KnownGearCardState extends ConsumerState<KnownGearCard> {
builder: (BuildContext context, double value, Widget? child) {
return Card(
clipBehavior: Clip.antiAlias,
color: Color.lerp(Theme.of(context).cardColor, Color(widget.baseStatefulDevice.baseStoredDevice.color), value),
color: Color.lerp(Theme
.of(context)
.cardColor, Color(widget.baseStatefulDevice.baseStoredDevice.color), value),
child: child,
);
},
Expand Down
2 changes: 2 additions & 0 deletions lib/Frontend/intn_defs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -312,3 +312,5 @@ String onboardingDoneButtonLabel() => Intl.message("Done", name: 'onboardingDone
String onboardingCompletedTitle() => Intl.message("Happy Wagging!", name: 'onboardingCompletedTitle', desc: 'Title of the final page of the onboarding screen');

String doubleBackToClose() => Intl.message("Press again to exit ", name: 'doubleBackToClose', desc: 'Snackbar message which appears when the back button is pressed at the main screen');

String noLongerSupported() => Intl.message("This gear is no longer supported.", name: 'noLongerSupported', desc: 'Warning message which appears for unsupported gear on the manage gear page');
Loading

0 comments on commit d93d3a8

Please sign in to comment.