Checked against the USB tool on the bench (3210 rpm): - O2: raw x 5/256 V (raw 195 -> 3.81 V, as the USB tool shows). - New derived sensor: injector duty = INJ ms x RPM / 1200 (16.67 ms @ 3210 rpm -> 44 %, as the USB tool shows). - Default dashboard flags: MIL, Fuel Pump, FAN Out, VTEC Out (the requirement's "FuelCut" is the fuel pump flag on the S300). - Log one raw frame (bytes 0-63) every 5 s so USB-tool readings can be matched to bytes; INJ, IGN, TPS, MIL, AF and PA still need that check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
126 lines
3.5 KiB
Dart
126 lines
3.5 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
import 'package:shared_preferences/shared_preferences.dart';
|
||
|
||
import '../../../core/models/sensor_defs.dart';
|
||
|
||
/// What the dashboard shows, per the requirement document: a selectable
|
||
/// main sensor (gauge) + sub sensor, 10 selectable values (landscape: 5 left
|
||
/// + 5 right; portrait: 2×5) and 4 selectable flags. Persisted.
|
||
class DashboardConfig {
|
||
static const valueCount = 10;
|
||
static const flagCount = 4;
|
||
|
||
final String main;
|
||
final String sub;
|
||
final List<String> values;
|
||
final List<String> flags;
|
||
|
||
const DashboardConfig({
|
||
required this.main,
|
||
required this.sub,
|
||
required this.values,
|
||
required this.flags,
|
||
});
|
||
|
||
static const defaults = DashboardConfig(
|
||
main: 'rpm',
|
||
sub: 'vss',
|
||
values: [
|
||
'vss', 'ect', 'iat', 'map', 'o2', // left
|
||
'tps', 'bat', 'ign', 'inj', 'eth', // right
|
||
],
|
||
// Requirement picture: MIL, FuelCut, FAN Out, VTEC Out. On the S300
|
||
// the fuel flag is the fuel pump relay (client).
|
||
flags: ['mil', 'fuelpump', 'fanout', 'vtec'],
|
||
);
|
||
|
||
DashboardConfig copyWith({
|
||
String? main,
|
||
String? sub,
|
||
List<String>? values,
|
||
List<String>? flags,
|
||
}) =>
|
||
DashboardConfig(
|
||
main: main ?? this.main,
|
||
sub: sub ?? this.sub,
|
||
values: values ?? this.values,
|
||
flags: flags ?? this.flags,
|
||
);
|
||
}
|
||
|
||
const _kMain = 'dash.main';
|
||
const _kSub = 'dash.sub';
|
||
const _kValues = 'dash.values';
|
||
const _kFlags = 'dash.flags';
|
||
|
||
class DashboardConfigNotifier extends StateNotifier<DashboardConfig> {
|
||
DashboardConfigNotifier() : super(DashboardConfig.defaults) {
|
||
_load();
|
||
}
|
||
|
||
static bool _isSensor(String id) => sensorDefs.any((d) => d.id == id);
|
||
static bool _isFlag(String id) => flagDefs.any((f) => f.id == id);
|
||
|
||
Future<void> _load() async {
|
||
try {
|
||
final p = await SharedPreferences.getInstance();
|
||
const d = DashboardConfig.defaults;
|
||
List<String> list(String key, int n, bool Function(String) valid,
|
||
List<String> fallback) {
|
||
final saved = p.getStringList(key);
|
||
if (saved == null || saved.length != n || !saved.every(valid)) {
|
||
return fallback;
|
||
}
|
||
return saved;
|
||
}
|
||
|
||
final main = p.getString(_kMain);
|
||
final sub = p.getString(_kSub);
|
||
final next = DashboardConfig(
|
||
main: main != null && _isSensor(main) ? main : d.main,
|
||
sub: sub != null && _isSensor(sub) ? sub : d.sub,
|
||
values: list(_kValues, DashboardConfig.valueCount, _isSensor, d.values),
|
||
flags: list(_kFlags, DashboardConfig.flagCount, _isFlag, d.flags),
|
||
);
|
||
if (mounted) state = next;
|
||
} catch (_) {
|
||
// Keep defaults if preferences can't be read.
|
||
}
|
||
}
|
||
|
||
void _persist() {
|
||
final s = state;
|
||
SharedPreferences.getInstance().then((p) {
|
||
p.setString(_kMain, s.main);
|
||
p.setString(_kSub, s.sub);
|
||
p.setStringList(_kValues, s.values);
|
||
p.setStringList(_kFlags, s.flags);
|
||
}).catchError((Object _) {});
|
||
}
|
||
|
||
void setMain(String id) {
|
||
state = state.copyWith(main: id);
|
||
_persist();
|
||
}
|
||
|
||
void setSub(String id) {
|
||
state = state.copyWith(sub: id);
|
||
_persist();
|
||
}
|
||
|
||
void setValue(int index, String id) {
|
||
state = state.copyWith(values: [...state.values]..[index] = id);
|
||
_persist();
|
||
}
|
||
|
||
void setFlag(int index, String id) {
|
||
state = state.copyWith(flags: [...state.flags]..[index] = id);
|
||
_persist();
|
||
}
|
||
}
|
||
|
||
final dashboardConfigProvider =
|
||
StateNotifierProvider<DashboardConfigNotifier, DashboardConfig>(
|
||
(ref) => DashboardConfigNotifier(),
|
||
);
|