442 lines
13 KiB
Dart
Raw 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 '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) {
// 预加载图片数据
Uint8List imageData = Uint8List.fromList(event.tvList);
// 更新状态
state.listData.value = imageData;
}
});
}
/// 收到UDP发送的状态
StreamSubscription? _getUDPStatusRefreshUIEvent;
void _getUDPStatusRefreshUIAction() {
_getUDPStatusRefreshUIEvent =
eventBus.on<GetUDPStatusRefreshUI>().listen((event) {
state.udpStatus.value = event.udpStatus;
if (state.udpStatus.value == 8) {
// 接听成功了,然后刷新界面的时间 60秒以后自动挂断
state.oneMinuteTimeTimer =
Timer.periodic(const Duration(seconds: 1), (Timer t) async {
state.oneMinuteTime.value++;
// Get.log('state.oneMinuteTime.value:${state.oneMinuteTime.value}');
if (state.oneMinuteTime.value >= 60) {
// 超过60秒了
state.oneMinuteTimeTimer.cancel();
state.oneMinuteTime.value = 0;
// 挂断
UDPSenderManage.sendMainProtocol(
command: 150,
commandTypeIsCalling: 1,
subCommand: 30,
lockID: state.getLockName.value,
lockIP: UDPManage().host,
userMobile: await state.userMobile,
userMobileIP: await state.userMobileIP,
endData: []);
CallTalk().stopPcmSound();
// 关闭当前界面
Get.back();
}
});
}
});
}
//查询监视状态
udpQueryMonitoringStatusAction() async {
UDPSenderManage.sendMainProtocol(
command: 152,
commandTypeIsCalling: 1,
subCommand: 20,
lockID: state.getLockName.value,
lockIP: UDPManage().host,
userMobile: await state.userMobile,
userMobileIP: await state.userMobileIP,
endData: []);
}
/// 监视
udpMonitorAction() async {
UDPSenderManage.sendMainProtocol(
command: 152,
commandTypeIsCalling: 1,
subCommand: 1,
lockID: state.getLockName.value,
lockIP: UDPManage().host,
userMobile: await state.userMobile,
userMobileIP: await state.userMobileIP,
endData: []);
// print('得到lockName------${state.getLockName.value}');
}
/// 接听
udpAnswerAction() async {
UDPSenderManage.sendMainProtocol(
command: 150,
commandTypeIsCalling: 1,
subCommand: 6,
lockID: UDPManage().lockId,
lockIP: UDPManage().host,
userMobile: await state.userMobile,
userMobileIP: await state.userMobileIP,
endData: []);
}
/// 挂断
udpHangUpAction() async {
UDPSenderManage.sendMainProtocol(
command: 152,
commandTypeIsCalling: 1,
subCommand: 30,
lockID: UDPManage().lockId,
lockIP: UDPManage().host,
userMobile: await state.userMobile,
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.userMobile,
userMobileIP: await state.userMobileIP,
endData: list);
Get.back();
}
Future<void> _readG711Data() async {
String filePath = 'assets/s10-g711.bin';
List<int> audioData = await G711().readAssetFile(filePath);
// Get.log('发送读取711文件数据为:$audioData');// 数据为:$audioData
// return;
// print('发送读取711文件数据长度为:${audioData.length}');// 数据为:$audioData
if (audioData.isNotEmpty) {
// 在这里处理你的音频数据
// pcmBytes = G711().convertList(audioData);
// print('发送转换pcmBytes数据长度为:${pcmBytes.length}');
int start = 0;
int length = 320;
while (start < audioData.length) {
// await Future.delayed(const Duration(milliseconds: 50));
int end = (start + length > audioData.length)
? audioData.length
: start + length;
List<int> sublist = audioData.sublist(start, end);
sendRecordData({
"bytes": sublist,
// "udpSendDataFrameNumber": 0,
"lockID": UDPManage().lockId,
"lockIP": UDPManage().host,
"userMobile": await state.userMobile,
"userMobileIP": await state.userMobileIP,
});
print(sublist);
start += length;
}
print('G711数据发送完成');
} else {
print('Failed to read audio data.');
}
}
Future<void> startProcessing() async {
frameListener(List<int> frame) async {
// Get.log('Get data.length:${frame.length} Received data:$frame');
for (int i = 0; i < frame.length; i++) {
frame[i] = linearToULaw(frame[i]);
}
// Get.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.userMobile,
"userMobileIP": await state.userMobileIP,
});
}
errorListener(VoiceProcessorException error) {
print("VoiceProcessorException: $error");
}
;
state.voiceProcessor?.addFrameListener(frameListener);
state.voiceProcessor?.addErrorListener(errorListener);
try {
if (await state.voiceProcessor?.hasRecordAudioPermission() ?? false) {
await state.voiceProcessor?.start(320, 8000);
bool? isRecording = await state.voiceProcessor?.isRecording();
} else {}
} on PlatformException catch (ex) {
Get.log("PlatformException: $ex");
} finally {}
}
Future<void> stopProcessing() async {
try {
await state.voiceProcessor?.stop();
} on PlatformException catch (ex) {
Get.log("PlatformException: $ex");
} finally {}
}
void onError(Object e) {
print(e);
}
sendRecordData(Map<String, dynamic> args) async {
List<int> bytes = args["bytes"];
// int udpSendDataFrameNumber = args["udpSendDataFrameNumber"];
String? lockID = args["lockID"];
String? lockIP = args["lockIP"];
String? userMobile = args["userMobile"];
String? userMobileIP = args["userMobileIP"];
// int length = 320; // 每个子List的长度
// List<int> list = state.listAudioData.value.sublist(0, 320);
// for (int i = 0; i < bytes.length; i += length) {
// int end = (i + length < bytes.length) ? i + length : bytes.length;
// bytes.sublist(i, end);
// // _sendRecordData(bytes.sublist(i, end));
// // // 刚进来是接听状态,然后改为长按对讲
// }
// while(list.isNotEmpty) {
state.udpSendDataFrameNumber++;
if (state.udpSendDataFrameNumber >= 65536) state.udpSendDataFrameNumber = 1;
// 57
List<int> topBytes = [];
// var cID = "XXXCID";
// List<int> cIDData = utf8.encode(cID!);
// topBytes.addAll(cIDData);
// // topBytes = getFixedLengthList(cIDData, 20 - cIDData.length);
// for (int i = 0; i < 6 - cIDData.length; i++) {
// topBytes.add(0);
// }
//
// // 命令
// topBytes.add(150);
//
// // 命令类型
// topBytes.add(1);
//
// // 子命令
// topBytes.add(8);
//
// // lockID
// List<int> lockIDData = utf8.encode(lockID!);
// topBytes.addAll(lockIDData);
// // topBytes = getFixedLengthList(lockIDData, 20 - lockIDData.length);
// for (int i = 0; i < 20 - lockIDData.length; i++) {
// topBytes.add(0);
// }
//
// // lockIP
// var lockIPList = lockIP!.split(".");
// lockIPList.forEach((element) {
// topBytes.add(int.parse(element));
// });
//
// // userMobile
// List<int> userMobileData = utf8.encode(userMobile!);
// topBytes.addAll(userMobileData);
// // topBytes = getFixedLengthList(topBytes, 20 - userMobileData.length);
// for (int i = 0; i < 20 - userMobileData.length; i++) {
// topBytes.add(0);
// }
//
// // userMobileIP
// var userMobileIPList = userMobileIP!.split(".");
// userMobileIPList.forEach((element) {
// topBytes.add(int.parse(element));
// });
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);
print(
"udpSendDataFrameNumber:${state.udpSendDataFrameNumber} topBytes[63]:${topBytes[6]} topBytes[64]:${topBytes[7]}");
topBytes.addAll(bytes);
Get.log("setVoiceBytes:$topBytes");
UDPSenderManage.sendMainProtocol(
command: 150,
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) {
List<int> table = [
0xFF,
0x1FF,
0x3FF,
0x7FF,
0xFFF,
0x1FFF,
0x3FFF,
0x7FFF
];
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);
double dbfs = 20 * log(rms / 32767.0) / log(10);
double normalizedValue = (dbfs + 50) / 50;
return normalizedValue.clamp(0.0, 1.0);
}
Future<bool> getPermissionStatus() async {
Permission permission = Permission.microphone;
//granted 通过denied 被拒绝permanentlyDenied 拒绝且不在提示
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 {
PermissionStatus status = await permission.request();
if (status.isPermanentlyDenied) {
openAppSettings();
}
}
@override
void onReady() {
// TODO: implement onReady
super.onReady();
print("onReady()");
_getTVDataRefreshUIAction();
_getUDPStatusRefreshUIAction();
initRecorder();
}
@override
void onInit() {
// TODO: implement onInit
super.onInit();
}
@override
void onClose() {
// TODO: implement onClose
print("锁详情界面销毁了");
_getTVDataRefreshUIEvent!.cancel();
_getUDPStatusRefreshUIEvent!.cancel();
if (state.oneMinuteTimeTimer != null) {
state.oneMinuteTimeTimer.cancel();
}
stopProcessing();
state.listData.value = Uint8List(0);
if (state.realTimePicTimer != null) {
state.realTimePicTimer.cancel();
}
}
}