// Copyright (C) 2025, uvok cheetah // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:logger/logger.dart'; import 'package:uvok_epaper_badge/first_where_ext.dart'; import 'package:uvok_epaper_badge/model/connection/device_connection.dart'; import 'package:uvok_epaper_badge/model/device/flutter_blue_plus_device.dart'; var logger = Logger(); class FlutterBluePlusDeviceConnection implements DeviceConnection { final ValueNotifier _status = ValueNotifier( ConnectionStatus.disconnected, ); // Just to have a resonable default subscription? StreamSubscription subs = Stream.empty().listen((e) => ()); BluetoothCharacteristic? current; BluetoothCharacteristic? available; final FlutterBluePlusDevice device; FlutterBluePlusDeviceConnection({required this.device}); @override Future connect() async { subs.cancel().ignore(); final dev = device.scanResult.device; subs = dev.connectionState.listen(_onConnStateChange); // connect timeout doesn't work under Linux await dev.connect().timeout(Duration(seconds: 2)); // // ???? WTF ???? // List svcs = await dev.discoverServices(); // dev.onServicesReset.listen((_) async { // logger.i("Services Reset"); // // try { // // List svcs = dev.servicesList; // // findCharac(svcs); // // } catch (e) { // // logger.e(e); // // } // }); // logger.i("services discovered"); // findCharac(svcs); // _status.value = ConnectionStatus.connected; // await Future.delayed(Duration(seconds: 5)); // logger.i("Try re-discover"); // svcs = await dev.discoverServices(); } @override Future disconnect() async { final dev = device.scanResult.device; subs.cancel().ignore(); await dev.disconnect(); _status.value = ConnectionStatus.disconnected; } @override ValueNotifier get status => _status; void _onConnStateChange(BluetoothConnectionState event) { logger.i("New conn state: ${event.toString()}"); } void findCharac(List svcs) { if (svcs.isEmpty) { logger.w("No services found!"); return; } logger.i("Services found!"); BluetoothService? badgeService = svcs.firstWhereOrNull( (s) => s.serviceUuid.str == "ca260000-b4bb-46b2-bd06-b7b7a61ea990", ); if (badgeService == null) { } else { logger.i("badge service found"); current = badgeService.characteristics.firstWhereOrNull( (c) => c.characteristicUuid.str == "ca260001-b4bb-46b2-bd06-b7b7a61ea990", ); available = badgeService.characteristics.firstWhereOrNull( (c) => c.characteristicUuid.str == "ca260002-b4bb-46b2-bd06-b7b7a61ea990", ); } if (current == null || available == null) { } else { logger.i("characteristics found"); } } }