| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- import 'package:flutter/services.dart';
- import '../models/bluetooth_device_info.dart';
- import '../models/gps_speed.dart';
- import '../models/location_reading.dart';
- import '../models/obd_state.dart';
- class TelemetryException implements Exception {
- TelemetryException(this.message);
- final String message;
- @override
- String toString() => message;
- }
- /// Bluetooth OBD and location boundary. Kept separate from LauncherPlatform so
- /// package/launcher fakes do not need telemetry methods.
- abstract class TelemetryPlatform {
- Future<List<BluetoothDeviceInfo>> listBondedDevices();
- Future<bool> isBluetoothEnabled();
- Future<bool> ensureBluetoothPermission();
- Future<bool> ensureLocationPermission();
- Future<LocationReading> getLocation();
- Future<void> connectObd(String address);
- Future<void> disconnectObd();
- Future<ObdState> getObdState();
- /// Starts GPS speed updates only when precise location is already allowed.
- Future<bool> startGpsSpeed();
- Future<void> stopGpsSpeed();
- Future<GpsSpeed> getGpsSpeed();
- }
- class NativeTelemetryBridge implements TelemetryPlatform {
- static const _channel = MethodChannel('com.wasp.cardash_launcher/telemetry');
- @override
- Future<List<BluetoothDeviceInfo>> listBondedDevices() async {
- try {
- final raw = await _channel.invokeMethod<dynamic>('listBondedDevices');
- if (raw is! List) return const [];
- return raw
- .whereType<Map>()
- .map(BluetoothDeviceInfo.fromMap)
- .where((device) => device.address.isNotEmpty)
- .toList(growable: false);
- } on PlatformException catch (error) {
- throw TelemetryException(
- error.message ?? 'Could not list Bluetooth devices.',
- );
- } on MissingPluginException {
- throw TelemetryException('The telemetry bridge is unavailable.');
- }
- }
- @override
- Future<bool> isBluetoothEnabled() async {
- try {
- return await _channel.invokeMethod<bool>('isBluetoothEnabled') ?? false;
- } on PlatformException {
- return false;
- } on MissingPluginException {
- return false;
- }
- }
- @override
- Future<bool> ensureBluetoothPermission() async {
- try {
- return await _channel.invokeMethod<bool>('ensureBluetoothPermission') ??
- false;
- } on PlatformException {
- return false;
- } on MissingPluginException {
- return false;
- }
- }
- @override
- Future<bool> ensureLocationPermission() async {
- try {
- return await _channel.invokeMethod<bool>('ensureLocationPermission') ??
- false;
- } on PlatformException {
- return false;
- } on MissingPluginException {
- return false;
- }
- }
- @override
- Future<LocationReading> getLocation() async {
- try {
- final raw = await _channel.invokeMethod<dynamic>('getLocation');
- if (raw is! Map) {
- throw TelemetryException('Could not read the current location.');
- }
- return LocationReading.fromMap(raw);
- } on PlatformException catch (error) {
- throw TelemetryException(error.message ?? 'Could not read location.');
- } on MissingPluginException {
- throw TelemetryException('The telemetry bridge is unavailable.');
- }
- }
- @override
- Future<void> connectObd(String address) async {
- try {
- await _channel.invokeMethod<dynamic>('connectObd', {'address': address});
- } on PlatformException catch (error) {
- throw TelemetryException(error.message ?? 'Could not connect to OBD.');
- } on MissingPluginException {
- throw TelemetryException('The telemetry bridge is unavailable.');
- }
- }
- @override
- Future<void> disconnectObd() async {
- try {
- await _channel.invokeMethod<dynamic>('disconnectObd');
- } on PlatformException {
- // Nothing useful to do when already disconnected.
- } on MissingPluginException {
- // No-op outside Android.
- }
- }
- @override
- Future<bool> startGpsSpeed() async {
- try {
- return await _channel.invokeMethod<bool>('startGpsSpeed') ?? false;
- } on PlatformException {
- return false;
- } on MissingPluginException {
- return false;
- }
- }
- @override
- Future<void> stopGpsSpeed() async {
- try {
- await _channel.invokeMethod<dynamic>('stopGpsSpeed');
- } on PlatformException {
- // Nothing useful to do when already stopped.
- } on MissingPluginException {
- // No-op outside Android.
- }
- }
- @override
- Future<GpsSpeed> getGpsSpeed() async {
- try {
- final raw = await _channel.invokeMethod<dynamic>('getGpsSpeed');
- return raw is Map ? GpsSpeed.fromMap(raw) : const GpsSpeed();
- } on PlatformException {
- return const GpsSpeed();
- } on MissingPluginException {
- return const GpsSpeed();
- }
- }
- @override
- Future<ObdState> getObdState() async {
- try {
- final raw = await _channel.invokeMethod<dynamic>('getObdState');
- return raw is Map ? ObdState.fromMap(raw) : const ObdState();
- } on PlatformException {
- return const ObdState();
- } on MissingPluginException {
- return const ObdState();
- }
- }
- }
|