hondavert-dev/test/units_and_flags_test.dart
metatroncubeswdev 6b8d069ef4 O2 in volts, injector duty, Fuel Pump default flag, raw frame log
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>
2026-10-12 23:47:12 -04:00

108 lines
3.5 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:typed_data';
import 'package:flutter_test/flutter_test.dart';
import 'package:hvbt_dash/core/models/sensor_defs.dart';
import 'package:hvbt_dash/core/models/units.dart';
import 'package:hvbt_dash/core/protocol/neg8.dart';
import 'package:hvbt_dash/core/protocol/s300_parser.dart';
/// S300 frame with header, the given bytes set, and a valid checksum.
Uint8List _s300(Map<int, int> bytes) {
final f = Uint8List(128);
f[0] = 0x1B;
bytes.forEach((i, v) => f[i] = v);
f[127] = calculateNeg8(f.sublist(0, 127));
return f;
}
void main() {
group('display units', () {
test('metric defaults are unchanged', () {
final v = sensorView('vss', const UnitPrefs());
expect(v.unit, 'km/h');
expect(v.convert(100), 100);
});
test('speed in mph', () {
final v = sensorView('vss', const UnitPrefs(speed: SpeedUnit.mph));
expect(v.unit, 'mph');
expect(v.convert(100), closeTo(62.14, 0.01));
});
test('temperatures in °F, range converted too', () {
final v =
sensorView('ect', const UnitPrefs(temp: TempUnit.fahrenheit));
expect(v.unit, '°F');
expect(v.convert(100), closeTo(212, 0.001));
expect(v.min, closeTo(-40, 0.001));
expect(v.max, closeTo(302, 0.001));
});
test('MAP and baro in bar and psi', () {
final bar = sensorView('map', const UnitPrefs(pressure: PressureUnit.bar));
expect(bar.unit, 'bar');
expect(bar.format(101.3), '1.01');
final psi = sensorView('pa', const UnitPrefs(pressure: PressureUnit.psi));
expect(psi.unit, 'psi');
expect(psi.convert(100), closeTo(14.50, 0.01));
});
test('unit choice does not touch unrelated sensors', () {
const u = UnitPrefs(
speed: SpeedUnit.mph,
temp: TempUnit.fahrenheit,
pressure: PressureUnit.psi,
);
expect(sensorView('rpm', u).convert(3000), 3000);
expect(sensorView('bat', u).unit, 'V');
});
});
group('values checked against the USB tool (bench, 3210 rpm)', () {
test('O2 volts = raw × 5/256 (raw 195 → 3.81 V)', () {
expect(parseS300(_s300({16: 195})).o2, closeTo(3.81, 0.005));
});
test('injector duty = INJ ms × RPM / 1200 (16.67 ms @ 3210 → 44 %)', () {
final s = parseS300(_s300({})).copyWith(inj: 16.67, rpm: 3210);
expect(sensorValue(s, 'duty'), closeTo(44.6, 0.1));
});
});
group('S300 flags', () {
test('SW3 cut/launch bits (byte 19)', () {
final s = parseS300(_s300({19: 0x20 | 0x08}));
expect(s.ignCut, isTrue);
expect(s.boostCut, isTrue);
expect(s.shiftCut, isFalse);
expect(s.launch, isFalse);
});
test('SW1 brake/AC/VTP (byte 17), SW5 closed loop (byte 49)', () {
final s = parseS300(_s300({17: 0x04 | 0x02 | 0x01, 49: 0x04}));
expect(s.brakeSwitch, isTrue);
expect(s.acSwitch, isTrue);
expect(s.vtp, isTrue);
expect(s.closedLoop, isTrue);
});
test('IAT / CLT / WBO error flags come from stored DTC bits', () {
// ERR01 bit1 = P0113 IAT, ERR00 bit5 = ECT, ERR00 bit0 = O2A
final s = parseS300(_s300({38: 0x02, 37: 0x20 | 0x01}));
expect(s.iatError, isTrue);
expect(s.ectError, isTrue);
expect(s.o2Error, isTrue);
final clean = parseS300(_s300({}));
expect(clean.iatError || clean.ectError || clean.o2Error, isFalse);
});
test('every flag id resolves and reads a value', () {
final s = parseS300(_s300({}));
for (final f in flagDefs) {
expect(flagDef(f.id).id, f.id);
expect(f.read(s), isA<bool>());
}
});
});
}