샤오미 3세대 온/습도계(MJWSD05MMC)에 연결하여 온도, 습도 및 체감온도와 위험도를 전달받는 라이브러리

Usage

To use this plugin, add 'sensor_link_package' as a dependency in your pubspec.yaml file.

dependencies:
  sensor_link_package:

Setup

ANDROID

Add permissions for Android

in the android/app/src/main/AndroidManifest.xml add:

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-feature android:name="android.hardware.bluetooth" android:required="true" />

IOS

Add permissions for iOS

  1. In the ios/Runner/Info.plist let’s add:
<dict>
...
    <key>NSBluetoothAlwaysUsageDescription</key>
    <string>This app needs Bluetooth to function</string>
...
</dict>
  1. Add the following to your Podfile file:
post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)

    target.build_configurations.each do |config|
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        '$(inherited)',

        ## dart: PermissionGroup.bluetooth
        'PERMISSION_BLUETOOTH=1',
      ]
    end
  end
end

How to use

import 'package:sensor_link_package/sensor_link_package.dart';

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

  @override
  State<BluetoothDemo> createState() => _BluetoothDemoState();
}

class _BluetoothDemoState extends State<BluetoothDemo> {
  late final SensorDeviceManager _sensorManager;
  late final TextEditingController _macController;

  bool _isConnected = false;
  String _statusMessage = '연결되지 않음';
  SensorData? _sensorData;

  @override
  void initState() {
    super.initState();
    _sensorManager = SensorDeviceManager();
    _macController = TextEditingController(text: '');
    _setupListeners();
  }

  void _setupListeners() {
    _sensorManager.connectionStream.listen((state) {
      if (!mounted) return;
      setState(() {
        _isConnected = state.isConnected;
        _statusMessage = state.isConnected ? '${state.deviceAddress}에 연결됨' : state.errorMessage ?? '연결되지 않음';
      });
    });

    _sensorManager.dataStream.listen((sensorData) {
      setState(() {
        _sensorData = sensorData;
      });
    });
  }

  Future<void> _connect() async {
    try {
      // Android는 Mac address 필수 - _sensorManager.connectToSensor('11:22:33:44:55:66')
      // IOS는 Mac address 공백 가능 - _sensorManager.connectToSensor('')
      bool success = await _sensorManager.connectToSensor(_macController.text.trim());

      if (!success) {
        print('연결에 실패했습니다');
      }
    } catch (e) {
      print('연결 오류: $e');
    }
  }

  Future<void> _disconnect() async {
    try {
      await _sensorManager.disconnect();
    } catch (e) {
      print('연결 해제 오류: $e');
    }
  }

  @override
  void dispose() {
    _sensorManager.disconnect();
    _macController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('온/습도계 연결')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(controller: _macController, decoration: const InputDecoration(labelText: '온/습도계 MAC 주소', border: OutlineInputBorder(), hintText: '예: 11:22:33:44:55:66'), enabled: !_isConnected),
            const SizedBox(height: 20),
            Text(_statusMessage),
            const SizedBox(height: 20),
            Text('$_sensorData'),
            ElevatedButton(onPressed: _isConnected ? _disconnect : _connect, child: Text(_isConnected ? '연결 해제' : '연결')),
          ],
        ),
      ),
    );
  }
}