You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

298 lines
8.3 KiB

import 'dart:async';
import 'dart:typed_data';
import 'package:get/get.dart';
import 'package:logger/logger.dart';
import 'package:jieli/jieli.dart';
/// 杰理测试控制器
class JieliTestController extends GetxController {
static final Logger logger = Logger();
// Jieli插件实例
late Jieli jieli;
// 状态变量
var isScanning = false.obs;
var deviceInfo = '未获取'.obs;
var connectStatus = '未连接'.obs;
var currentDevice = Rx<BleDevice?>(null);
var scannedDevices = RxList<BleDevice>([]);
var wakeupReceived = false.obs;
var audioDataSize = 0.obs;
var receivedFrames = 0.obs;
var audioDataReceiving = false.obs;
// 事件订阅
StreamSubscription? _scanSubscription;
StreamSubscription? _connectionSubscription;
StreamSubscription? _wakeupSubscription;
StreamSubscription? _audioSubscription;
@override
void onInit() {
super.onInit();
logger.d('JieliTestController 初始化');
_initializeJieli();
}
@override
void onClose() {
logger.d('JieliTestController 关闭');
_cancelAllSubscriptions();
_disposeJieli();
super.onClose();
}
/// 取消所有订阅
void _cancelAllSubscriptions() {
_scanSubscription?.cancel();
_connectionSubscription?.cancel();
_wakeupSubscription?.cancel();
_audioSubscription?.cancel();
}
/// 初始化杰理SDK
void _initializeJieli() {
try {
logger.d('初始化Jieli插件');
jieli = Jieli();
_setupEventListeners();
} catch (e) {
logger.e('初始化Jieli插件错误', error: e);
}
}
/// 设置事件监听器
void _setupEventListeners() {
// 监听扫描结果
_scanSubscription = jieli.scanResults.listen((devices) {
// logger.d('扫描到设备: ${devices.length}个');
scannedDevices.assignAll(devices);
});
// 监听连接状态
_connectionSubscription = jieli.connectionState.listen((state) {
logger.d('连接状态变化: $state');
switch (state) {
case ConnectionState.connected:
connectStatus.value = '已连接';
break;
case ConnectionState.disconnected:
connectStatus.value = '已断开';
currentDevice.value = null;
break;
case ConnectionState.connecting:
connectStatus.value = '连接中...';
break;
case ConnectionState.disconnecting:
connectStatus.value = '断开中...';
break;
case ConnectionState.error:
connectStatus.value = '连接错误';
break;
}
});
// 监听唤醒信号
_wakeupSubscription = jieli.wakeupStream.listen((wakeup) {
logger.d('收到唤醒信号');
wakeupReceived.value = true;
Get.snackbar('收到唤醒信号', '耳机发送了唤醒信号');
});
// 监听音频数据
_audioSubscription = jieli.audioDataStream.listen((data) {
// 更新音频数据统计
audioDataSize.value += data.length;
receivedFrames.value++;
audioDataReceiving.value = true;
// 每100帧更新一次日志,避免日志过多
if (receivedFrames.value % 100 == 0) {
logger.d('已接收音频数据: ${audioDataSize.value} 字节, ${receivedFrames.value} 帧');
}
});
}
/// 检查蓝牙状态
Future<bool> checkBluetoothStatus() async {
try {
final isEnabled = await jieli.isBluetoothEnabled();
if (!isEnabled) {
logger.d('蓝牙未启用,请求启用蓝牙');
return await jieli.requestBluetoothEnable();
}
return true;
} catch (e) {
logger.e('检查蓝牙状态错误', error: e);
return false;
}
}
/// 开始扫描设备
Future<void> startScan() async {
if (isScanning.value) return;
final bluetoothReady = await checkBluetoothStatus();
if (!bluetoothReady) {
Get.snackbar('蓝牙未启用', '请启用蓝牙后再试');
return;
}
try {
logger.d('开始扫描设备');
isScanning.value = true;
// 清空之前的设备列表
scannedDevices.clear();
// 开始扫描,10秒后自动停止
final success = await jieli.startScan(scanTimeout: 10000);
if (!success) {
logger.e('启动扫描失败');
isScanning.value = false;
Get.snackbar('扫描失败', '启动扫描设备失败,请检查蓝牙权限');
}
// 10秒后自动更新UI状态
Future.delayed(Duration(milliseconds: 10000), () {
isScanning.value = false;
});
} catch (e) {
logger.e('扫描设备错误', error: e);
isScanning.value = false;
Get.snackbar('扫描错误', e.toString());
}
}
/// 停止扫描
Future<void> stopScan() async {
if (!isScanning.value) return;
try {
logger.d('停止扫描');
await jieli.stopScan();
isScanning.value = false;
} catch (e) {
logger.e('停止扫描错误', error: e);
}
}
/// 连接到指定设备
Future<void> connectToDevice(BleDevice device) async {
try {
// 先断开当前连接
if (currentDevice.value != null) {
await disconnectDevice();
}
// 更新UI状态
connectStatus.value = '连接中...';
logger.d('连接设备: ${device.name} (${device.id})');
// 重置音频和唤醒相关的状态
wakeupReceived.value = false;
audioDataSize.value = 0;
receivedFrames.value = 0;
audioDataReceiving.value = false;
// 连接设备
final success = await jieli.connect(device.id);
if (success) {
// 连接成功,更新当前设备
currentDevice.value = device;
deviceInfo.value = '设备名称: ${device.name}\n设备ID: ${device.id}\nRSSI: ${device.rssi} dBm';
logger.d('设备连接成功');
} else {
deviceInfo.value = '连接失败';
logger.d('设备连接失败');
}
} catch (e) {
deviceInfo.value = '连接错误: ${e.toString()}';
logger.e('连接设备错误', error: e);
}
}
/// 断开设备连接
Future<void> disconnectDevice() async {
if (currentDevice.value == null) return;
try {
connectStatus.value = '断开中...';
logger.d('断开设备连接');
final success = await jieli.disconnect();
if (success) {
deviceInfo.value = '未连接设备';
logger.d('设备断开连接成功');
} else {
logger.d('设备断开连接失败');
}
} catch (e) {
logger.e('断开设备错误', error: e);
}
}
/// 发送开始录音命令
Future<void> sendStartRecordingCommand() async {
if (currentDevice.value == null) {
Get.snackbar('操作失败', '未连接设备');
return;
}
try {
logger.d('发送开始录音命令');
final success = await jieli.sendStartRecordingCommand();
if (success) {
Get.snackbar('命令已发送', '已发送开始录音命令');
logger.d('开始录音命令发送成功');
} else {
Get.snackbar('命令发送失败', '发送开始录音命令失败');
logger.d('开始录音命令发送失败');
}
} catch (e) {
logger.e('发送开始录音命令错误', error: e);
Get.snackbar('命令错误', e.toString());
}
}
/// 发送停止录音命令
Future<void> sendStopRecordingCommand() async {
if (currentDevice.value == null) {
Get.snackbar('操作失败', '未连接设备');
return;
}
try {
logger.d('发送停止录音命令');
final success = await jieli.sendStopRecordingCommand();
if (success) {
Get.snackbar('命令已发送', '已发送停止录音命令');
logger.d('停止录音命令发送成功');
} else {
Get.snackbar('命令发送失败', '发送停止录音命令失败');
logger.d('停止录音命令发送失败');
}
} catch (e) {
logger.e('发送停止录音命令错误', error: e);
Get.snackbar('命令错误', e.toString());
}
}
/// 清理资源
void _disposeJieli() {
try {
logger.d('释放Jieli插件资源');
jieli.dispose();
} catch (e) {
logger.e('释放Jieli插件资源错误', error: e);
}
}
}