sensor_link_package 0.0.1
sensor_link_package: ^0.0.1 copied to clipboard
A Flutter package for connecting to Bluetooth devices using MAC address and reading data
A Flutter package for connecting to Bluetooth devices using MAC address and reading data
Usage #
To use this plugin, add 'sensor_link_package' as a dependency in your pubspec.yaml file.
dependencies:
sensor_link_package:
Example #
import 'package:example/sensor_data_record.dart';
import 'package:flutter/material.dart';
import 'package:sensor_link_package/sensor_link_package.dart';
import 'connection_control_card.dart';
import 'connection_status_card.dart';
import 'connection_status_manager.dart';
import 'data_history_card.dart';
import 'latest_data_card.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 _sensorMacController;
late final TextEditingController _lightMacController;
final List<SensorDataRecord> _sensorHistory = [];
static const int _maxHistoryCount = 100;
// 상태 변수들
bool _isConnected = false;
bool _isLightConnected = false;
String _statusMessage = '연결되지 않음';
SensorData? _latestSensorData;
bool _isConnecting = false;
@override
void initState() {
super.initState();
_initializeComponents();
_setupEventListeners();
_performInitialChecks();
}
void _initializeComponents() {
_sensorManager = SensorDeviceManager();
_sensorMacController = TextEditingController(text: 'A4:C1:38:7F:2F:FE');
_lightMacController = TextEditingController();
}
void _setupEventListeners() {
_sensorManager.connectionStream.listen(_handleConnectionStateChange, onError: (error) => _showError('연결 상태 오류: $error'));
_sensorManager.dataStream.listen(_handleSensorData, onError: (error) => _showError('데이터 수신 오류: $error'));
}
Future<void> _performInitialChecks() async {
try {
await _sensorManager.initialize();
_updateStatus('블루투스 초기화 완료');
} catch (e) {
_showError('초기화 실패: $e');
}
}
void _handleConnectionStateChange(DeviceConnectionState state) {
if (!mounted) return;
setState(() {
_isConnected = state.isConnected;
_isConnecting = state.state == DeviceConnectionStateType.connecting;
final stateText = ConnectionStatusManager.getConnectionStateText(state.state);
if (state.isConnected) {
_statusMessage = '${state.deviceAddress}에 $stateText';
} else {
_statusMessage = state.errorMessage ?? stateText;
}
});
// 연결 완료 시 경광봉 연결 시도
if (state.isConnected && _lightMacController.text.isNotEmpty) {
_connectToWarningLight();
}
}
void _handleSensorData(SensorData sensorData) {
if (!mounted) return;
setState(() {
_latestSensorData = sensorData;
_addToHistory(sensorData);
});
}
void _addToHistory(SensorData data) {
_sensorHistory.insert(0, SensorDataRecord(timestamp: DateTime.now(), data: data));
if (_sensorHistory.length > _maxHistoryCount) {
_sensorHistory.removeLast();
}
}
Future<void> _connectToSensor() async {
final sensorMac = _sensorMacController.text.trim();
final lightMac = _lightMacController.text.trim();
if (sensorMac.isEmpty) {
_showError('센서 MAC 주소를 입력해주세요');
return;
}
if (!MacAddressUtils.isValid(sensorMac)) {
_showError('올바른 센서 MAC 주소 형식이 아닙니다');
return;
}
if (lightMac.isNotEmpty && !MacAddressUtils.isValid(lightMac)) {
_showError('올바른 경광봉 MAC 주소 형식이 아닙니다');
return;
}
try {
_updateStatus('연결 시도 중...');
setState(() => _isConnecting = true);
_clearHistory();
bool success;
if (lightMac.isNotEmpty) {
success = await _sensorManager.connectToSensorAndLight(sensorMac, lightMac);
} else {
success = await _sensorManager.connectToSensor(sensorMac);
}
if (!success) {
_showError('센서 연결에 실패했습니다');
setState(() => _isConnecting = false);
}
} catch (e) {
_showError('연결 실패: $e');
setState(() => _isConnecting = false);
}
}
Future<void> _connectToWarningLight() async {
final lightMac = _lightMacController.text.trim();
if (lightMac.isEmpty) return;
try {
final success = await _sensorManager.connectToWarningLight(lightMac);
setState(() => _isLightConnected = success);
if (success) {
_showSuccess('경광봉 연결 성공');
} else {
_showError('경광봉 연결 실패');
}
} catch (e) {
_showError('경광봉 연결 오류: $e');
setState(() => _isLightConnected = false);
}
}
Future<void> _disconnect() async {
try {
await _sensorManager.disconnect();
setState(() {
_latestSensorData = null;
_isLightConnected = false;
});
_updateStatus('연결 해제됨');
} catch (e) {
_showError('연결 해제 실패: $e');
}
}
Future<void> _testWarningLight() async {
if (!_isLightConnected) {
_showError('경광봉이 연결되지 않았습니다');
return;
}
try {
await _sensorManager.testWarningLight();
_showSuccess('경광봉 테스트 완료');
} catch (e) {
_showError('경광봉 테스트 실패: $e');
}
}
void _clearHistory() {
setState(() => _sensorHistory.clear());
}
void _updateStatus(String message) {
if (mounted) {
setState(() => _statusMessage = message);
}
}
void _showError(String message) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message), backgroundColor: Colors.red, duration: const Duration(seconds: 3)));
}
void _showSuccess(String message) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message), backgroundColor: Colors.green, duration: const Duration(seconds: 2)));
}
@override
void dispose() {
_sensorManager.dispose();
_sensorMacController.dispose();
_lightMacController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('온/습도 센서 모니터'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
actions: [if (_isLightConnected) IconButton(onPressed: _testWarningLight, icon: const Icon(Icons.lightbulb), tooltip: '경광봉 테스트')],
),
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// ConnectionStatusCard(isConnected: _isConnected, isLightConnected: _isLightConnected, statusMessage: _statusMessage),
// const SizedBox(height: 8),
ConnectionControlCard(
sensorMacController: _sensorMacController,
lightMacController: _lightMacController,
isConnected: _isConnected,
isConnecting: _isConnecting,
onConnect: _connectToSensor,
onDisconnect: _disconnect,
),
const SizedBox(height: 5),
LatestDataCard(data: _latestSensorData),
const SizedBox(height: 5),
SizedBox(
height: 320, // 고정 높이 설정
child: DataHistoryCard(history: _sensorHistory, onClearHistory: _clearHistory),
),
],
),
),
),
);
}
}