///////////////////////// filename: main.dart // ble demo // uses hm19 ble module - amazon item #8541588324 // pico pin4 - hm-19 rxd // pico pin5 - hm-19 txd // pico pin40 - hm-19 vcc /* flutter 2.2.0 channel stable tools dart 2.13.0 pubspec.yaml dependencies: flutter: sdk: flutter flutter_reactive_ble: ^3.1.1 pico uart test from machine import UART, Pin import time uart=UART(1,9600) while 1: while uart.any() > 0: print(ord(uart.read(1))) */ import 'package:flutter/material.dart'; import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'; import 'ble.dart'; import 'sendbutton.dart'; import 'connectbutton.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', home: MyHomePage(title: 'BLE demo'),);}} class MyHomePage extends StatefulWidget { MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override MyHomePageState createState() => MyHomePageState(); } class MyHomePageState extends State with TickerProviderStateMixin { late TabController tabController; BLE ble = BLE(); String status = 'not connected'; @override void initState(){ super.initState(); tabController = TabController(length: 3, vsync: this); tabController.addListener((){ setState((){ status = ble.getStatus(); }); }); } @override Widget build(BuildContext context) { status = ble.getStatus(); return Scaffold( appBar: AppBar( title: Text(widget.title), backgroundColor: Colors.black, bottom: TabBar( controller: tabController, indicator: BoxDecoration( borderRadius: BorderRadius.circular(50), color: Colors.greenAccent), tabs: const [ Tab(icon: Icon(Icons.home)), Tab(icon: Icon(Icons.light_mode)), Tab(icon: Icon(Icons.thermostat)), ],),), body: TabBarView( controller: tabController, children: [ ConnectButton(ble), SendButton(ble), Text('ble is: $status') ]));}} //////////////////////////// filename: ble.dart import 'package:flutter/material.dart'; import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'; import 'dart:async'; class BLE{ BLE(); final frb = FlutterReactiveBle(); StreamSubscription? subscription; late StreamSubscription connection; late QualifiedCharacteristic tx; String status = 'not connected'; Future stopScan() async { await subscription?.cancel(); subscription = null; } String getStatus(){ return status; } void sendData() async { print('sending...'); await frb.writeCharacteristicWithResponse(tx, value:[0x41,0x42,0x43]); } void connectToBLE() async { subscription = frb.scanForDevices(withServices: [Uuid.parse("0000ffe0-0000-1000-8000-00805f9b34fb")]).listen((device){ connection = frb.connectToDevice(id: device.id).listen((state){ if (state.connectionState == DeviceConnectionState.connected) { tx = QualifiedCharacteristic( serviceId: Uuid.parse("0000ffe0-0000-1000-8000-00805f9b34fb"), characteristicId: Uuid.parse("0000ffe1-0000-1000-8000-00805f9b34fb"), deviceId: device.id ); status = 'connected'; stopScan(); } }, onError: (Object e) { // connecting error print('error: $e\n'); }); }, onError:(Object e){ // scan error print('error: $e\n'); }); } } ///////////////////////////// filename: connectbutton.dart import 'package:flutter/material.dart'; import 'ble.dart'; class ConnectButton extends StatelessWidget { final BLE ble; ConnectButton(this.ble); @override Widget build(BuildContext c){ return RaisedButton( child: Text('connect'), onPressed: ble.connectToBLE); } } /////////////////////// filename: sendbutton.dart import 'package:flutter/material.dart'; import 'ble.dart'; class SendButton extends StatelessWidget { final BLE ble; SendButton(this.ble); @override Widget build(BuildContext c){ return ElevatedButton( child: Text('send ABC'), onPressed: ble.sendData); } }