hondavert-dev/lib/main.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

63 lines
2.0 KiB
Dart

import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'core/logging/app_log.dart';
import 'core/providers/theme_provider.dart';
import 'ui/theme/app_theme.dart';
import 'ui/screens/bt_picker/bt_picker_screen.dart';
void main() {
runZonedGuarded(() {
WidgetsFlutterBinding.ensureInitialized();
// Catch every Dart-side error, log it (copyable from the Debug screen)
// and keep the app running instead of showing a red/grey error screen.
FlutterError.onError = (FlutterErrorDetails details) {
AppLog.e('Flutter error', details.exception, details.stack);
};
WidgetsBinding.instance.platformDispatcher.onError = (error, stack) {
AppLog.e('Uncaught platform error', error, stack);
return true;
};
// Release only: keep Flutter's red error screen in debug builds so
// layout/build errors stay visible during development.
if (kReleaseMode) {
ErrorWidget.builder = (FlutterErrorDetails details) => const Center(
child: Padding(
padding: EdgeInsets.all(16),
child: Text(
'Something went wrong on this screen.\n'
'Open Debug → Copy log and send it to support.',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.grey),
),
),
);
}
AppLog.i('App start');
runApp(const ProviderScope(child: HvbtApp()));
}, (error, stack) {
AppLog.e('Uncaught zone error', error, stack);
});
}
class HvbtApp extends ConsumerWidget {
const HvbtApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final themeVariant = ref.watch(themeProvider);
return MaterialApp(
title: 'HV BT Dashboard',
debugShowCheckedModeBanner: false,
theme: AppTheme.build(themeVariant),
home: const BtPickerScreen(),
);
}
}