merge commit
This commit is contained in:
@@ -68,7 +68,7 @@ public class MainActivity extends FlutterActivity implements INativeNuiCallback
|
|||||||
.setMethodCallHandler((call, result) -> {
|
.setMethodCallHandler((call, result) -> {
|
||||||
Map<String, Object> args = (Map<String, Object>) call.arguments;
|
Map<String, Object> args = (Map<String, Object>) call.arguments;
|
||||||
switch (call.method) {
|
switch (call.method) {
|
||||||
case "start":
|
case "startTts":
|
||||||
Object isChinese = args.get("isChinese");
|
Object isChinese = args.get("isChinese");
|
||||||
if (isChinese == null || isChinese.toString().isBlank()) {
|
if (isChinese == null || isChinese.toString().isBlank()) {
|
||||||
return;
|
return;
|
||||||
@@ -76,17 +76,17 @@ public class MainActivity extends FlutterActivity implements INativeNuiCallback
|
|||||||
boolean isSuccess = startTts(Boolean.parseBoolean(isChinese.toString()));
|
boolean isSuccess = startTts(Boolean.parseBoolean(isChinese.toString()));
|
||||||
result.success(isSuccess);
|
result.success(isSuccess);
|
||||||
break;
|
break;
|
||||||
case "send":
|
case "sendTts":
|
||||||
Object textArg = args.get("text");
|
Object textArg = args.get("text");
|
||||||
if (textArg == null || textArg.toString().isBlank()) {
|
if (textArg == null || textArg.toString().isBlank()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sendTts(textArg.toString());
|
sendTts(textArg.toString());
|
||||||
break;
|
break;
|
||||||
case "complete":
|
case "completeTts":
|
||||||
completeTts();
|
completeTts();
|
||||||
break;
|
break;
|
||||||
case "stop":
|
case "stopTts":
|
||||||
stopTts();
|
stopTts();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -97,10 +97,10 @@ public class MainActivity extends FlutterActivity implements INativeNuiCallback
|
|||||||
asrMethodChannel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), ASR_CHANNEL);
|
asrMethodChannel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), ASR_CHANNEL);
|
||||||
asrMethodChannel.setMethodCallHandler((call, result) -> {
|
asrMethodChannel.setMethodCallHandler((call, result) -> {
|
||||||
switch (call.method) {
|
switch (call.method) {
|
||||||
case "start":
|
case "startAsr":
|
||||||
startAsr();
|
startAsr();
|
||||||
break;
|
break;
|
||||||
case "stop":
|
case "stopAsr":
|
||||||
stopAsr();
|
stopAsr();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class PartScreen extends StatefulWidget {
|
|||||||
class _PartScreenState extends State<PartScreen> {
|
class _PartScreenState extends State<PartScreen> {
|
||||||
final ScrollController _scrollController = ScrollController();
|
final ScrollController _scrollController = ScrollController();
|
||||||
bool _isInitialized = false;
|
bool _isInitialized = false;
|
||||||
|
int _lastMessageCount = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -97,9 +98,13 @@ class _PartScreenState extends State<PartScreen> {
|
|||||||
alignment: Alignment.bottomCenter,
|
alignment: Alignment.bottomCenter,
|
||||||
child: Consumer<MessageService>(
|
child: Consumer<MessageService>(
|
||||||
builder: (context, messageService, child) {
|
builder: (context, messageService, child) {
|
||||||
|
final messageCount = messageService.messages.length;
|
||||||
|
if (messageCount > _lastMessageCount) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
_scrollToBottom();
|
_scrollToBottom();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
_lastMessageCount = messageCount;
|
||||||
return Container(
|
return Container(
|
||||||
width: chatWidth,
|
width: chatWidth,
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ class VehicleCommandService {
|
|||||||
|
|
||||||
Future<VehicleCommandResponse?> getCommandFromText(String text) async {
|
Future<VehicleCommandResponse?> getCommandFromText(String text) async {
|
||||||
try {
|
try {
|
||||||
final uri = Uri.parse(
|
final uri = Uri.parse('http://143.64.185.20:18606/control');
|
||||||
'http://143.64.185.20:18606/control');
|
|
||||||
|
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
uri,
|
uri,
|
||||||
@@ -40,30 +39,23 @@ class VehicleCommandService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行车辆控制命令的方法
|
Future<String> getControlResponse(List<String> successCommandList) async {
|
||||||
Future<bool> executeCommand(VehicleCommand command) async {
|
String reply = "";
|
||||||
try {
|
try {
|
||||||
final uri = Uri.parse('http://143.64.185.20:18607/executeCommand');
|
final uri = Uri.parse('http://143.64.185.20:18606/control_resp');
|
||||||
|
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
uri,
|
uri,
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {'Content-Type': 'application/json'},
|
||||||
body: json.encode({
|
body: json.encode(successCommandList),
|
||||||
'command': command.commandString, // 使用getter转换为字符串
|
|
||||||
'params': command.params,
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
print('命令执行成功: ${command.commandString}');
|
return response.body;
|
||||||
return true;
|
|
||||||
} else {
|
} else {
|
||||||
print('命令执行失败: ${response.statusCode}, ${response.body}');
|
print("请求控制回复失败: ${response.statusCode}");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('命令执行出错: $e');
|
print('请求控制回复异常: $e');
|
||||||
return false;
|
}
|
||||||
}
|
return reply;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,10 @@ class MessageService extends ChangeNotifier {
|
|||||||
_asrChannel.setMethodCallHandler((call) async {
|
_asrChannel.setMethodCallHandler((call) async {
|
||||||
switch (call.method) {
|
switch (call.method) {
|
||||||
case "onAsrResult":
|
case "onAsrResult":
|
||||||
replaceMessage(id: _latestUserMessageId!, text: call.arguments);
|
replaceMessage(
|
||||||
|
id: _latestUserMessageId!,
|
||||||
|
text: call.arguments,
|
||||||
|
status: MessageStatus.normal);
|
||||||
break;
|
break;
|
||||||
case "onAsrStop":
|
case "onAsrStop":
|
||||||
int index = findMessageIndexById(_latestUserMessageId!);
|
int index = findMessageIndexById(_latestUserMessageId!);
|
||||||
@@ -45,8 +48,6 @@ class MessageService extends ChangeNotifier {
|
|||||||
removeMessageById(_latestUserMessageId!);
|
removeMessageById(_latestUserMessageId!);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
replaceMessage(
|
|
||||||
id: _latestUserMessageId!, status: MessageStatus.normal);
|
|
||||||
if (_asrCompleter != null && !_asrCompleter!.isCompleted) {
|
if (_asrCompleter != null && !_asrCompleter!.isCompleted) {
|
||||||
_asrCompleter!.complete(messages.last.text);
|
_asrCompleter!.complete(messages.last.text);
|
||||||
}
|
}
|
||||||
@@ -107,9 +108,8 @@ class MessageService extends ChangeNotifier {
|
|||||||
_latestAssistantMessageId = null;
|
_latestAssistantMessageId = null;
|
||||||
_isReplyAborted = false;
|
_isReplyAborted = false;
|
||||||
changeState(MessageServiceState.recording);
|
changeState(MessageServiceState.recording);
|
||||||
addMessage("", true, MessageStatus.listening);
|
_latestUserMessageId = addMessage("", true, MessageStatus.listening);
|
||||||
_latestUserMessageId = messages.last.id;
|
_asrChannel.invokeMethod("startAsr");
|
||||||
_asrChannel.invokeMethod("start");
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('录音开始出错: $e');
|
print('录音开始出错: $e');
|
||||||
}
|
}
|
||||||
@@ -120,14 +120,16 @@ class MessageService extends ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addMessage(String text, bool isUser, MessageStatus status) {
|
String addMessage(String text, bool isUser, MessageStatus status) {
|
||||||
|
String uuid = Uuid().v1();
|
||||||
_messages.add(ChatMessage(
|
_messages.add(ChatMessage(
|
||||||
id: Uuid().v1(),
|
id: uuid,
|
||||||
text: text,
|
text: text,
|
||||||
isUser: isUser,
|
isUser: isUser,
|
||||||
timestamp: DateTime.now(),
|
timestamp: DateTime.now(),
|
||||||
status: status));
|
status: status));
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> stopAndProcessVoiceInput() async {
|
Future<void> stopAndProcessVoiceInput() async {
|
||||||
@@ -137,7 +139,7 @@ class MessageService extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
changeState(MessageServiceState.recognizing);
|
changeState(MessageServiceState.recognizing);
|
||||||
_asrChannel.invokeMethod("stop");
|
_asrChannel.invokeMethod("stopAsr");
|
||||||
_asrCompleter = Completer<String>();
|
_asrCompleter = Completer<String>();
|
||||||
final recognizedText = await _asrCompleter!.future;
|
final recognizedText = await _asrCompleter!.future;
|
||||||
// final audioData = await _audioService.stopRecording();
|
// final audioData = await _audioService.stopRecording();
|
||||||
@@ -194,8 +196,7 @@ class MessageService extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> reply(String text) async {
|
Future<void> reply(String text) async {
|
||||||
addMessage("", false, MessageStatus.thinking);
|
_latestAssistantMessageId = addMessage("", false, MessageStatus.thinking);
|
||||||
_latestAssistantMessageId = messages.last.id;
|
|
||||||
bool isChinese = CommonUtil.containChinese(text);
|
bool isChinese = CommonUtil.containChinese(text);
|
||||||
try {
|
try {
|
||||||
if (_isReplyAborted) {
|
if (_isReplyAborted) {
|
||||||
@@ -249,9 +250,11 @@ class MessageService extends ChangeNotifier {
|
|||||||
if (!_isReplyAborted) {
|
if (!_isReplyAborted) {
|
||||||
if (await TtsUtil.start(isChinese) == true) {
|
if (await TtsUtil.start(isChinese) == true) {
|
||||||
TtsUtil.send(vehicleCommandResponse.tips!);
|
TtsUtil.send(vehicleCommandResponse.tips!);
|
||||||
|
Future.delayed(const Duration(milliseconds: 300), () => TtsUtil.complete());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool containOpenAC = false;
|
bool containOpenAC = false;
|
||||||
|
List<String> successCommandList = [];
|
||||||
for (var command in vehicleCommandResponse.commands) {
|
for (var command in vehicleCommandResponse.commands) {
|
||||||
if (_isReplyAborted) {
|
if (_isReplyAborted) {
|
||||||
return;
|
return;
|
||||||
@@ -263,11 +266,15 @@ class MessageService extends ChangeNotifier {
|
|||||||
if (command.type == VehicleCommandType.openAC) {
|
if (command.type == VehicleCommandType.openAC) {
|
||||||
containOpenAC = true;
|
containOpenAC = true;
|
||||||
}
|
}
|
||||||
|
bool isSuccess;
|
||||||
if (containOpenAC && command.type == VehicleCommandType.changeACTemp) {
|
if (containOpenAC && command.type == VehicleCommandType.changeACTemp) {
|
||||||
await Future.delayed(const Duration(milliseconds: 2000),
|
isSuccess = await Future.delayed(const Duration(milliseconds: 2000),
|
||||||
() => processCommand(command, isChinese));
|
() => processCommand(command, isChinese));
|
||||||
} else {
|
} else {
|
||||||
await processCommand(command, isChinese);
|
isSuccess = await processCommand(command, isChinese);
|
||||||
|
}
|
||||||
|
if (isSuccess) {
|
||||||
|
successCommandList.add(command.type.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
replaceMessage(
|
replaceMessage(
|
||||||
@@ -275,12 +282,21 @@ class MessageService extends ChangeNotifier {
|
|||||||
text: vehicleCommandResponse.tips!,
|
text: vehicleCommandResponse.tips!,
|
||||||
status: MessageStatus.normal);
|
status: MessageStatus.normal);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
if (_isReplyAborted || successCommandList.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String controlResponse =
|
||||||
|
await _vehicleCommandService.getControlResponse(successCommandList);
|
||||||
|
if (_isReplyAborted || controlResponse.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addMessage(controlResponse, false, MessageStatus.normal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> processCommand(VehicleCommand command, bool isChinese) async {
|
Future<bool> processCommand(VehicleCommand command, bool isChinese) async {
|
||||||
String msg;
|
String msg = "";
|
||||||
MessageStatus status;
|
MessageStatus status = MessageStatus.normal;
|
||||||
final (isSuccess, result) = await CommandService.executeCommand(
|
final (isSuccess, result) = await CommandService.executeCommand(
|
||||||
command.type,
|
command.type,
|
||||||
params: command.params);
|
params: command.params);
|
||||||
@@ -299,20 +315,18 @@ class MessageService extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isSuccess) {
|
if (!isSuccess) {
|
||||||
msg = isChinese
|
|
||||||
? "为您执行\"${command.type.chinese}\"成功"
|
|
||||||
: "Execute \"${command.type.english}\" successful";
|
|
||||||
status = MessageStatus.success;
|
|
||||||
} else {
|
|
||||||
msg = isChinese
|
msg = isChinese
|
||||||
? "很抱歉,\"${command.type.chinese}\"失败"
|
? "很抱歉,\"${command.type.chinese}\"失败"
|
||||||
: "Sorry, execute \"${command.type.english}\" unsuccessfully";
|
: "Sorry, execute \"${command.type.english}\" unsuccessfully";
|
||||||
status = MessageStatus.failure;
|
status = MessageStatus.failure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (msg.isNotEmpty) {
|
||||||
addMessage(msg, false, status);
|
addMessage(msg, false, status);
|
||||||
}
|
}
|
||||||
|
return isSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> answerWrongQuestion(bool isChinese) async {
|
Future<void> answerWrongQuestion(bool isChinese) async {
|
||||||
if (_isReplyAborted) {
|
if (_isReplyAborted) {
|
||||||
|
|||||||
@@ -10,18 +10,18 @@ class TtsUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<bool> start(bool isChinese) async {
|
static Future<bool> start(bool isChinese) async {
|
||||||
return await execute('start', {'isChinese': isChinese});
|
return await execute('startTts', {'isChinese': isChinese});
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> send(String text) async {
|
static Future<void> send(String text) async {
|
||||||
await execute('send', {'text': text});
|
await execute('sendTts', {'text': text});
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> complete() async {
|
static Future<void> complete() async {
|
||||||
await execute('complete');
|
await execute('completeTts');
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> stop() async {
|
static Future<void> stop() async {
|
||||||
await execute('stop');
|
await execute('stopTts');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ class _FloatingIconState extends State<FloatingIcon>
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _showFullScreen() async {
|
void _showFullScreen() async {
|
||||||
|
_hidePartScreen();
|
||||||
await Navigator.of(context).push(
|
await Navigator.of(context).push(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => const FullScreen(),
|
builder: (context) => const FullScreen(),
|
||||||
|
|||||||
Reference in New Issue
Block a user