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>
43 lines
1.3 KiB
Dart
43 lines
1.3 KiB
Dart
import 'dart:collection';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
|
|
/// Small in-memory log the client can copy from the Debug screen and send
|
|
/// back with a bug report. Keeps the newest [_capacity] lines only.
|
|
class AppLog {
|
|
AppLog._();
|
|
|
|
static const int _capacity = 400;
|
|
static final ListQueue<String> _lines = ListQueue<String>();
|
|
|
|
static void i(String msg) => _add('I', msg);
|
|
static void w(String msg) => _add('W', msg);
|
|
static void e(String msg, [Object? error, StackTrace? stack]) {
|
|
final b = StringBuffer(msg);
|
|
if (error != null) b.write(' | $error');
|
|
if (stack != null) {
|
|
// First few frames are enough to locate a crash.
|
|
final frames = stack.toString().split('\n').take(8).join('\n ');
|
|
b.write('\n $frames');
|
|
}
|
|
_add('E', b.toString());
|
|
}
|
|
|
|
static void _add(String level, String msg) {
|
|
final t = DateTime.now();
|
|
String two(int v) => v.toString().padLeft(2, '0');
|
|
final ts = '${two(t.hour)}:${two(t.minute)}:${two(t.second)}.'
|
|
'${t.millisecond.toString().padLeft(3, '0')}';
|
|
final line = '$ts $level $msg';
|
|
_lines.addLast(line);
|
|
while (_lines.length > _capacity) {
|
|
_lines.removeFirst();
|
|
}
|
|
debugPrint(line);
|
|
}
|
|
|
|
static String dump() => _lines.join('\n');
|
|
|
|
static int get length => _lines.length;
|
|
}
|