hondavert-dev/lib/ui/widgets/bt_status_chip.dart
metatroncubeswdev 9a56baef61 Rework BT poller and S300 decoding after client feedback
Client reported crashes, wrong/frozen data and that the app floods the
adapter MCU. See docs/FIX_2026-10-12.md for the full analysis.

- Poller: strictly one request outstanding; next request only after a valid
  128-byte reply or a 500 ms timeout, then a quiet period + buffer flush.
  Default 100 ms (10 Hz), minimum 80 ms. DTC clear/probe share the same lock.
- BtNotifier: filter the adapter's default (no-ECU-data) frame instead of
  holding last values; EcuDataStatus + status banner; auto-reconnect on link
  loss, stalls or long default-only runs (rate-limited). A reconnect still in
  flight when the user disconnects is discarded.
- S300 offsets corrected by column counting (trims, PA, ERR00-03, Eth, SW5,
  AF); INJ/AIN little-endian; fan = SW5 FANC only. Default-frame detection
  requires bytes 0-16 and 32-36.
- KPro RPM/MAP2/AIN little-endian (RPM still needs a bench check).
- Crash hardening: zone/Flutter/platform error handlers to an in-app log
  (copyable from Debug); permissions requested before listing devices.
- Remove temporary debug prints; graph redraws live; polling options
  100-300 ms, persisted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:02:54 -04:00

41 lines
1.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../core/providers/bt_provider.dart';
class BtStatusChip extends ConsumerWidget {
const BtStatusChip({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final status = ref.watch(btProvider.select((s) => s.status));
final name = ref.watch(btProvider.select((s) => s.deviceName));
final (color, icon, label) = switch (status) {
BtStatus.connected => (Colors.green, Icons.bluetooth_connected, name ?? 'Connected'),
BtStatus.connecting => (Colors.orange, Icons.bluetooth_searching, 'Connecting…'),
BtStatus.reconnecting => (Colors.orange, Icons.bluetooth_searching, 'Reconnecting…'),
BtStatus.error => (Colors.red, Icons.bluetooth_disabled, 'Error'),
BtStatus.disconnected => (Colors.grey, Icons.bluetooth, 'Disconnected'),
};
return Padding(
padding: const EdgeInsets.only(right: 8),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(icon, size: 14, color: color),
const SizedBox(width: 4),
Text(
label,
style: TextStyle(
color: color,
fontSize: 11,
fontWeight: FontWeight.w600,
),
),
],
),
);
}
}