flutter_sdk/example/lib/tabs/device_scan_tab.dart

184 lines
6.3 KiB
Dart
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:flutter_sdk/starcloud_flutter_sdk.dart';
import 'package:starcloud/entity/star_cloud_lock_list.dart' as scl;
import '../l10n.dart';
import '../global.dart';
import '../widgets/common_widgets.dart';
class DeviceScanTab extends StatefulWidget {
const DeviceScanTab({super.key});
@override
State<DeviceScanTab> createState() => _DeviceScanTabState();
}
class _DeviceScanTabState extends State<DeviceScanTab> {
bool _scanning = false;
bool _pairing = false;
List<dynamic> _devices = [];
final List<String> _log = [];
void _log_(String msg) {
final ts = DateTime.now().toIso8601String().substring(11, 19);
setState(() => _log.add('[$ts] $msg'));
}
Future<void> _scan() async {
if (!sdkCloudAccountReady.value) {
_log_(S.isEn
? 'Set an SDK cloud account before scanning and pairing a lock.'
: '请先在“登录”页创建或设置 SDK 星云账户,再扫描绑定锁。');
return;
}
setState(() {
_scanning = true;
_devices = [];
});
_log_(S.isEn ? 'Scan start (10s)...' : '开始扫描(10 秒超时)...');
try {
await StarCloudClient.instance.device.scanDeviceList(
timeout: 10,
onScan: (results) {
setState(() => _devices = results);
});
_log_(S.isEn
? 'Done. Found ${_devices.length}'
: '扫描完成,发现 ${_devices.length} 个设备');
} catch (e) {
_log_('${S.isEn ? "Failed" : "失败"}: $e');
} finally {
setState(() => _scanning = false);
}
}
Future<void> _pair(int idx) async {
if (!sdkCloudAccountReady.value) {
_log_(
S.isEn ? 'Please set an SDK cloud account first.' : '请先设置 SDK 星云账户。');
return;
}
setState(() => _pairing = true);
_log_(S.isEn ? 'Pairing...' : '正在配对...');
try {
final lock = await StarCloudClient.instance.device
.pairDevice(scanResult: _devices[idx]);
// 更新 ValueNotifier 的值
wifiConfiguredLockId.value = null;
pairedLockId.value = lock.lockId;
pairedLock.value = lock;
_log_('${S.isEn ? "Success" : "成功"}! ID: ${lock.lockId}');
} catch (e) {
_log_('${S.isEn ? "Failed" : "失败"}: $e');
} finally {
setState(() => _pairing = false);
}
}
@override
Widget build(BuildContext context) {
return ValueListenableBuilder<bool>(
valueListenable: S.langNotifier,
builder: (context, isEn, _) {
return Column(
children: [
Padding(
padding: const EdgeInsets.all(12),
child: Row(
children: [
Expanded(
child: ElevatedButton.icon(
onPressed: _scanning ? null : _scan,
icon: _scanning
? const SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(strokeWidth: 2))
: const Icon(Icons.bluetooth_searching),
label: Text(_scanning ? S.btnScanning : S.btnScan),
),
),
const SizedBox(width: 8),
ElevatedButton(
onPressed: _scanning
? () => StarCloudClient.instance.device
.stopScan()
.then((_) => setState(() => _scanning = false))
: null,
child: Text(S.btnStop)),
],
),
),
// 使用 ValueListenableBuilder 监听配对状态
ValueListenableBuilder<int?>(
valueListenable: pairedLockId,
builder: (context, id, _) {
if (id == null) return const SizedBox.shrink();
return Container(
padding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
alignment: Alignment.centerLeft,
child: Chip(
label: Text('${S.pairedStatus}: #$id'),
backgroundColor: Colors.green.shade50,
onDeleted: () {
wifiConfiguredLockId.value = null;
pairedLockId.value = null;
pairedLock.value = null;
},
),
);
},
),
Expanded(
child: ValueListenableBuilder<scl.StarCloudLock?>(
valueListenable: pairedLock,
builder: (context, paired, _) {
if (_devices.isEmpty) {
return Center(
child: Text(
S.scanHint,
style: const TextStyle(color: Colors.grey),
),
);
}
return ListView.separated(
padding: const EdgeInsets.symmetric(horizontal: 12),
itemCount: _devices.length,
separatorBuilder: (_, __) => const Divider(height: 1),
itemBuilder: (context, i) {
final device = _devices[i] as StarCloudScanResult;
final isPaired = _isPairedDevice(device, paired);
return ListTile(
title: Text(device.advName.isNotEmpty
? device.advName
: (S.isEn ? 'Unknown' : '未知设备')),
subtitle: Text('MAC: ${device.id}'),
trailing: ElevatedButton(
onPressed:
_pairing || isPaired ? null : () => _pair(i),
child: Text(isPaired ? S.pairedStatus : S.btnPair),
),
);
},
);
},
),
),
LogArea(log: _log),
],
);
},
);
}
bool _isPairedDevice(
StarCloudScanResult device,
scl.StarCloudLock? paired,
) {
if (paired == null) return false;
return paired.mac == device.id ||
paired.bluetooth.bluetoothDeviceName == device.advName;
}
}