feat: redesign and lots of progress
This commit is contained in:
@ -1,3 +1,5 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:cbor/simple.dart';
|
||||
|
||||
const String universalShifterControlServiceUuid =
|
||||
@ -249,6 +251,9 @@ enum ControlConnectionState {
|
||||
}
|
||||
if (raw is String) {
|
||||
final normalized = raw.toLowerCase();
|
||||
if (normalized.contains('disconnected')) {
|
||||
return ControlConnectionState.disconnected;
|
||||
}
|
||||
if (normalized.contains('connected')) {
|
||||
return ControlConnectionState.connected;
|
||||
}
|
||||
@ -294,32 +299,21 @@ class TrainerStatus {
|
||||
|
||||
static TrainerStatus fromRaw(dynamic raw) {
|
||||
if (raw is int) {
|
||||
switch (raw) {
|
||||
case 1:
|
||||
return const TrainerStatus(state: TrainerConnectionState.connecting);
|
||||
case 2:
|
||||
return const TrainerStatus(state: TrainerConnectionState.pairing);
|
||||
case 3:
|
||||
return const TrainerStatus(state: TrainerConnectionState.connected);
|
||||
case 4:
|
||||
return const TrainerStatus(
|
||||
state: TrainerConnectionState.discoveringFtms);
|
||||
case 5:
|
||||
return const TrainerStatus(state: TrainerConnectionState.ftmsReady);
|
||||
default:
|
||||
return const TrainerStatus(state: TrainerConnectionState.idle);
|
||||
}
|
||||
return _trainerStatusFromVariant(raw);
|
||||
}
|
||||
|
||||
if (raw is List && raw.isNotEmpty) {
|
||||
final variant = raw.first;
|
||||
final value = raw.length > 1 ? raw[1] : null;
|
||||
if (variant is int && (variant == 5 || variant == 6)) {
|
||||
if (variant is int && variant == 6) {
|
||||
return TrainerStatus(
|
||||
state: TrainerConnectionState.error,
|
||||
errorCode: value is int ? value : null,
|
||||
);
|
||||
}
|
||||
if (variant is int) {
|
||||
return _trainerStatusFromVariant(variant);
|
||||
}
|
||||
}
|
||||
|
||||
if (raw is Map) {
|
||||
@ -327,13 +321,16 @@ class TrainerStatus {
|
||||
if (entry != null) {
|
||||
final key = entry.key;
|
||||
final value = entry.value;
|
||||
if ((key is int && (key == 5 || key == 6)) ||
|
||||
if ((key is int && key == 6) ||
|
||||
(key is String && key.toLowerCase().contains('error'))) {
|
||||
return TrainerStatus(
|
||||
state: TrainerConnectionState.error,
|
||||
errorCode: value is int ? value : null,
|
||||
);
|
||||
}
|
||||
if (key is int) {
|
||||
return _trainerStatusFromVariant(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,6 +359,26 @@ class TrainerStatus {
|
||||
|
||||
return const TrainerStatus(state: TrainerConnectionState.idle);
|
||||
}
|
||||
|
||||
static TrainerStatus _trainerStatusFromVariant(int variant) {
|
||||
switch (variant) {
|
||||
case 1:
|
||||
return const TrainerStatus(state: TrainerConnectionState.connecting);
|
||||
case 2:
|
||||
return const TrainerStatus(state: TrainerConnectionState.pairing);
|
||||
case 3:
|
||||
return const TrainerStatus(state: TrainerConnectionState.connected);
|
||||
case 4:
|
||||
return const TrainerStatus(
|
||||
state: TrainerConnectionState.discoveringFtms);
|
||||
case 5:
|
||||
return const TrainerStatus(state: TrainerConnectionState.ftmsReady);
|
||||
case 6:
|
||||
return const TrainerStatus(state: TrainerConnectionState.error);
|
||||
default:
|
||||
return const TrainerStatus(state: TrainerConnectionState.idle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CentralStatus {
|
||||
@ -384,16 +401,26 @@ class CentralStatus {
|
||||
String get statusLine =>
|
||||
'Control: ${control.name}, Trainer: ${trainer.label}${lastFailure != null ? ', Last failure: $lastFailure' : ''}';
|
||||
|
||||
static CentralStatus disconnected({dynamic raw}) {
|
||||
return CentralStatus(
|
||||
control: ControlConnectionState.disconnected,
|
||||
trainer: const TrainerStatus(state: TrainerConnectionState.idle),
|
||||
hasSavedBond: false,
|
||||
connectedTrainerAddr: null,
|
||||
lastFailure: null,
|
||||
raw: raw,
|
||||
);
|
||||
}
|
||||
|
||||
static CentralStatus fromCborBytes(List<int> bytes) {
|
||||
if (bytes.isEmpty) {
|
||||
throw const FormatException('Status payload is empty.');
|
||||
}
|
||||
|
||||
final decoded = cbor.decode(bytes);
|
||||
if (decoded is! Map) {
|
||||
return CentralStatus(
|
||||
control: ControlConnectionState.disconnected,
|
||||
trainer: const TrainerStatus(state: TrainerConnectionState.idle),
|
||||
hasSavedBond: false,
|
||||
connectedTrainerAddr: null,
|
||||
lastFailure: null,
|
||||
raw: decoded,
|
||||
throw FormatException(
|
||||
'Status payload must decode to a CBOR map, got ${decoded.runtimeType}.',
|
||||
);
|
||||
}
|
||||
|
||||
@ -428,6 +455,9 @@ List<int>? _toByteList(dynamic value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
if (value is Uint8List) {
|
||||
return value.toList(growable: false);
|
||||
}
|
||||
if (value is List) {
|
||||
return value.whereType<int>().toList(growable: false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user