app-starlock/lib/main/lockDetail/realTimePicture/realTimePicture_logic.dart

324 lines
9.0 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 'dart:async';
import 'dart:math';
import 'package:flutter/services.dart';
import 'package:flutter_voice_processor/flutter_voice_processor.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:star_lock/talk/call/callTalk.dart';
import '../../../../talk/call/g711.dart';
import '../../../../talk/udp/udp_manage.dart';
import '../../../../talk/udp/udp_senderManage.dart';
import '../../../../tools/baseGetXController.dart';
import '../../../../tools/eventBusEventManage.dart';
import '../../../app_settings/app_settings.dart';
import 'realTimePicture_state.dart';
class RealTimePictureLogic extends BaseGetXController {
final RealTimePictureState state = RealTimePictureState();
/// 初始化发送声音
initRecorder() {
state.voiceProcessor = VoiceProcessor.instance;
}
/// 收到视频流数据
StreamSubscription? _getTVDataRefreshUIEvent;
void _getTVDataRefreshUIAction() {
// 蓝牙协议通知传输跟蓝牙之外的数据传输类不一样 eventBus
_getTVDataRefreshUIEvent =
eventBus.on<GetTVDataRefreshUI>().listen((event) {
if (event.tvList.isNotEmpty) {
// 预加载图片数据
final Uint8List imageData = Uint8List.fromList(event.tvList);
// 更新状态
state.listData.value = imageData;
}
});
}
/// 收到UDP发送的状态
StreamSubscription? _getUDPStatusRefreshUIEvent;
void _getUDPStatusRefreshUIAction() {
_getUDPStatusRefreshUIEvent =
eventBus.on<GetUDPStatusMonitorUI>().listen((event) {
state.udpStatus.value = event.udpStatus;
});
}
/// 监视
udpMonitorAction() async {
UDPSenderManage.sendMainProtocol(
command: 152,
commandTypeIsCalling: 1,
subCommand: 1,
lockID: state.getLockName.value,
lockIP: UDPManage().host,
userMobile: await state.userUid,
userMobileIP: await state.userMobileIP,
endData: []);
}
/// 挂断
udpHangUpAction() async {
UDPSenderManage.sendMainProtocol(
command: 152,
commandTypeIsCalling: 1,
subCommand: 30,
lockID: UDPManage().lockId,
lockIP: UDPManage().host,
userMobile: await state.userUid,
userMobileIP: await state.userMobileIP,
endData: []);
}
/// 开门
udpOpenDoorAction(List<int> list) async {
UDPSenderManage.sendMainProtocol(
command: 152,
commandTypeIsCalling: 1,
subCommand: 10,
lockID: UDPManage().lockId,
lockIP: UDPManage().host,
userMobile: await state.userUid,
userMobileIP: await state.userMobileIP,
endData: list);
Get.back();
}
Future<void> _readG711Data() async {
final String filePath = 'assets/s10-g711.bin';
final List<int> audioData = await G711().readAssetFile(filePath);
// AppLog.log('发送读取711文件数据为:$audioData');// 数据为:$audioData
// return;
// AppLog.log('发送读取711文件数据长度为:${audioData.length}');// 数据为:$audioData
if (audioData.isNotEmpty) {
// 在这里处理你的音频数据
// pcmBytes = G711().convertList(audioData);
// AppLog.log('发送转换pcmBytes数据长度为:${pcmBytes.length}');
int start = 0;
final int length = 320;
while (start < audioData.length) {
// await Future.delayed(const Duration(milliseconds: 50));
final int end = (start + length > audioData.length)
? audioData.length
: start + length;
final List<int> sublist = audioData.sublist(start, end);
sendRecordData({
'bytes': sublist,
// "udpSendDataFrameNumber": 0,
'lockID': UDPManage().lockId,
'lockIP': UDPManage().host,
'userMobile': await state.userUid,
'userMobileIP': await state.userMobileIP,
});
AppLog.log(sublist.toString());
start += length;
}
AppLog.log('G711数据发送完成');
} else {
AppLog.log('Failed to read audio data.');
}
}
Future<void> startProcessing() async {
frameListener(List<int> frame) async {
// AppLog.log('Get data.length:${frame.length} Received data:$frame');
for (int i = 0; i < frame.length; i++) {
frame[i] = linearToULaw(frame[i]);
}
// AppLog.log('change Get data.length:${frame.length} change Received data:$frame');
await Future.delayed(const Duration(milliseconds: 50));
sendRecordData({
'bytes': frame,
// "udpSendDataFrameNumber": 0,
'lockID': UDPManage().lockId,
'lockIP': UDPManage().host,
'userMobile': await state.userUid,
'userMobileIP': await state.userMobileIP,
});
}
errorListener(VoiceProcessorException error) {
AppLog.log('VoiceProcessorException: $error');
}
state.voiceProcessor?.addFrameListener(frameListener);
state.voiceProcessor?.addErrorListener(errorListener);
try {
if (await state.voiceProcessor?.hasRecordAudioPermission() ?? false) {
await state.voiceProcessor?.start(320, 8000);
final bool? isRecording = await state.voiceProcessor?.isRecording();
} else {}
} on PlatformException catch (ex) {
AppLog.log('PlatformException: $ex');
} finally {}
}
Future<void> stopProcessing() async {
try {
await state.voiceProcessor?.stop();
} on PlatformException catch (ex) {
AppLog.log('PlatformException: $ex');
} finally {}
}
void onError(Object e) {
AppLog.log(e.toString());
}
sendRecordData(Map<String, dynamic> args) async {
final List<int> bytes = args['bytes'];
// int udpSendDataFrameNumber = args["udpSendDataFrameNumber"];
final String? lockID = args['lockID'];
final String? lockIP = args['lockIP'];
final String? userMobile = args['userMobile'];
final String? userMobileIP = args['userMobileIP'];
state.udpSendDataFrameNumber++;
if (state.udpSendDataFrameNumber >= 65536) state.udpSendDataFrameNumber = 1;
// 57
final List<int> topBytes = [];
topBytes.addAll([
1, 1, 1, 1, // 时间戳
1, 0, // 音频
1, 0, // 帧序号
64, 0, 0, 0, // 帧长度
1, 0, // 总包数
1, 0, // 当前包号
64, 1, // 数据长度
176, 4, // 保留
]);
topBytes[6] = state.udpSendDataFrameNumber & 0x000000FF;
topBytes[7] = (state.udpSendDataFrameNumber & 0x0000FF00) >> 8;
topBytes.addAll(bytes);
AppLog.log('setVoiceBytes:$topBytes');
UDPSenderManage.sendMainProtocol(
command: 152,
commandTypeIsCalling: 1,
subCommand: 8,
lockID: lockID,
lockIP: lockIP,
userMobile: userMobile,
userMobileIP: userMobileIP,
endData: topBytes);
// UDPManage().sendData(topBytes);
}
// 拿到的音频转化成pcm
int linearToULaw(int pcmVal) {
int mask;
int seg;
int uval;
if (pcmVal < 0) {
pcmVal = 0x84 - pcmVal;
mask = 0x7F;
} else {
pcmVal += 0x84;
mask = 0xFF;
}
seg = search(pcmVal);
if (seg >= 8) {
return 0x7F ^ mask;
} else {
uval = seg << 4;
uval |= (pcmVal >> (seg + 3)) & 0xF;
return uval ^ mask;
}
}
int search(int val) {
final List<int> table = [
0xFF,
0x1FF,
0x3FF,
0x7FF,
0xFFF,
0x1FFF,
0x3FFF,
0x7FFF
];
final int size = 8;
for (int i = 0; i < size; i++) {
if (val <= table[i]) {
return i;
}
}
return size;
}
double _calculateVolumeLevel(List<int> frame) {
double rms = 0.0;
for (int sample in frame) {
rms += pow(sample, 2);
}
rms = sqrt(rms / frame.length);
final double dbfs = 20 * log(rms / 32767.0) / log(10);
final double normalizedValue = (dbfs + 50) / 50;
return normalizedValue.clamp(0.0, 1.0);
}
Future<bool> getPermissionStatus() async {
final Permission permission = Permission.microphone;
//granted 通过denied 被拒绝permanentlyDenied 拒绝且不在提示
final PermissionStatus status = await permission.status;
if (status.isGranted) {
return true;
} else if (status.isDenied) {
requestPermission(permission);
} else if (status.isPermanentlyDenied) {
openAppSettings();
} else if (status.isRestricted) {
requestPermission(permission);
} else {}
return false;
}
///申请权限
void requestPermission(Permission permission) async {
final PermissionStatus status = await permission.request();
if (status.isPermanentlyDenied) {
openAppSettings();
}
}
@override
void onReady() {
super.onReady();
_getTVDataRefreshUIAction();
_getUDPStatusRefreshUIAction();
initRecorder();
}
@override
void onInit() {
super.onInit();
}
@override
void onClose() {
CallTalk().finishAVData();
_getTVDataRefreshUIEvent!.cancel();
_getUDPStatusRefreshUIEvent!.cancel();
if (state.oneMinuteTimeTimer != null) {
state.oneMinuteTimeTimer.cancel();
}
stopProcessing();
state.listData.value = Uint8List(0);
}
}