// 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_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 { ConnectionStatus _status = 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 = ConnectionStatus.connected; await Future.delayed(Duration(seconds: 5)); logger.i("Try re-discover"); svcs = await dev.discoverServices(); } @override Future disconnect() async { subs.cancel().ignore(); _status = ConnectionStatus.disconnected; } @override ConnectionStatus 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"); } } }