Unable to scan ibeacon in Flutter

97 views Asked by At

I am a student studying flutter. While implementing BLE communication in Flutter, information about ibeacon is not received. I am using flutter_blue_plus, but I would appreciate it if you could provide a better library or example code that can receive the value of ibeacon.

I tried using flutter_blue_plus, beacons_plugin, etc., but it was difficult to utilize them due to insufficient examples. I would like to receive a statefulwidget code that can detect ibeacon.


import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  FlutterBluePlus flutterBlue = FlutterBluePlus.instance;
  List<ScanResult> scanResultList = [];
  bool _isScanning = false;



  @override
  initState() {
    super.initState();
    // 블루투스 초기화
    initBle();
  }

  void initBle() {
    // BLE 스캔 상태 얻기 위한 리스너
    flutterBlue.isScanning.listen((isScanning) {
      _isScanning = isScanning;
      setState(() {});
    });
  }
  bool _isIBeacon(List<String> data) {

    print(data);
    return data.length == 25 &&
        data[0] == '0x4c' &&
        data[1] == '0x00' &&
        data[2] == '0x02' &&
        data[3] == '0x15';
  }
  scan() async {

    if (!_isScanning) {
      // 스캔 중이 아니라면
      // 기존에 스캔된 리스트 삭제
      scanResultList.clear();
      // 스캔 시작, 제한 시간 4초
      flutterBlue.startScan(
          timeout: Duration(seconds: 10));
      print('scanResults : ${flutterBlue.scanResults}');
      // 스캔 결과 리스너
      flutterBlue.scanResults.listen((results) {
        print('result : $results');
        for (ScanResult result in results) {
          // Get all the data from advertisement
          Map<int, List<int>> adData = result.advertisementData.manufacturerData;

          for (int id in adData.keys) {
            print('Manufacturer ID: $id');
            List<int> data = adData[id]!;
            List<String> hex = [];
            String bytesToHex(List<int> bytes) {
              return bytes.map((byte) {
                // 각 바이트를 2자리 16진수로 포맷팅
                hex.add(byte.toRadixString(16).padLeft(2, '0'));
                return byte.toRadixString(16).padLeft(2, '0');
              }).join(' '); // 각 16진수를 공백으로 구분
            }

            String hexString = bytesToHex(data);
            print('hexString : ${hex}');
            if (_isIBeacon(hex)) {
              print('This is an iBeacon');
              // Now you can parse the array 'data' as an iBeacon.
            }
          }
        }

        // List<ScanResult> 형태의 results 값을 scanResultList에 복사
        scanResultList = results;
        List data = scanResultList.toList();
        for (ScanResult r in results) {
          final serviceData = r.advertisementData.serviceData;
          final serviceUuids = r.advertisementData.serviceUuids;

          print('${r.device.id}: $serviceUuids $serviceData');
        }
        // UI 갱신
        setState(() {});
      });

    } else {
      // 스캔 중이라면 스캔 정지
      flutterBlue.stopScan();
    }
  }

  Widget deviceSignal(ScanResult r) {
    return Text(r.rssi.toString());
  }

  /* 장치의 MAC 주소 위젯  */
  Widget deviceMacAddress(ScanResult r) {
    return Text(r.device.id.id);
  }

  /* 장치의 명 위젯  */
  Widget deviceName(ScanResult r) {
    String name = '';

    if (r.device.name.isNotEmpty) {
      // device.name에 값이 있다면
      name = r.device.name;
    } else if (r.advertisementData.localName.isNotEmpty) {
      // advertisementData.localName에 값이 있다면
      name = r.advertisementData.localName;
    } else {
      // 둘다 없다면 이름 알 수 없음...
      name = 'N/A';
    }
    return Text(name);
  }
  Widget leading(ScanResult r) {
    return CircleAvatar(
      child: Icon(
        Icons.bluetooth,
        color: Colors.white,
      ),
      backgroundColor: Colors.cyan,
    );
  }

  /* 장치 아이템을 탭 했을때 호출 되는 함수 */
  void onTap(ScanResult r) {
    // 단순히 이름만 출력
    print('${r.device.name}');
  }

  /* 장치 아이템 위젯 */
  Widget listItem(ScanResult r) {
    return ListTile(
      onTap: () => onTap(r),
      leading: leading(r),
      title: deviceName(r),
      subtitle: deviceMacAddress(r),
      trailing: deviceSignal(r),
    );
  }

  /* UI */
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        useMaterial3: true
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Ble'),
        ),
        body: Center(
          /* 장치 리스트 출력 */
          child: ListView.separated(
            itemCount: scanResultList.length,
            itemBuilder: (context, index) {
              return listItem(scanResultList[index]);
            },
            separatorBuilder: (BuildContext context, int index) {
              return Divider();
            },
          ),
        ),
        /* 장치 검색 or 검색 중지  */
        floatingActionButton: FloatingActionButton(
          onPressed: scan,
          // 스캔 중이라면 stop 아이콘을, 정지상태라면 search 아이콘으로 표시
          child: Icon(_isScanning ? Icons.stop : Icons.search),
        ),
      ),
    );
  }
}
0

There are 0 answers