feat: 新增ai_chat_core,将core 和 widget 分离(未完成)
迁移了 models enums, utils, http 封装,还有一些extensions;service 只迁移了 sse service
This commit is contained in:
@@ -16,14 +16,7 @@ export 'services/message_service.dart';
|
||||
export 'services/command_service.dart';
|
||||
|
||||
// types && enums && models
|
||||
export 'models/vehicle_cmd.dart';
|
||||
export 'models/vehicle_cmd_response.dart';
|
||||
export 'models/chat_message.dart';
|
||||
export 'models/vehicle_status_info.dart';
|
||||
|
||||
export 'enums/vehicle_command_type.dart';
|
||||
export 'enums/message_status.dart';
|
||||
export 'enums/message_service_state.dart';
|
||||
export 'package:ai_chat_core/ai_chat_core.dart';
|
||||
|
||||
// utils
|
||||
export 'utils/assets_util.dart';
|
||||
@@ -1,5 +1,3 @@
|
||||
import '../enums/vehicle_command_type.dart';
|
||||
import '../services/command_service.dart';
|
||||
import 'easy_bloc.dart';
|
||||
import 'command_state.dart';
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import '../enums/vehicle_command_type.dart';
|
||||
|
||||
// AI Chat Command States
|
||||
import 'package:ai_chat_core/ai_chat_core.dart';
|
||||
|
||||
enum AIChatCommandStatus {
|
||||
idle,
|
||||
executing,
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
enum MessageServiceState {
|
||||
idle,
|
||||
recording,
|
||||
recognizing,
|
||||
replying,
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
enum MessageStatus {
|
||||
normal('普通消息', 'Normal'),
|
||||
listening('聆听中', 'Listening'),
|
||||
recognizing('识别中', 'Recognizing'),
|
||||
thinking('思考中', 'Thinking'),
|
||||
completed('完成回答', 'Completed'),
|
||||
executing('执行中', 'Executing'),
|
||||
success('执行成功', 'Success'),
|
||||
failure('执行失败', 'Failure'),
|
||||
aborted('已中止', 'Aborted');
|
||||
|
||||
const MessageStatus(this.chinese, this.english);
|
||||
|
||||
final String chinese;
|
||||
final String english;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
enum VehicleCommandType {
|
||||
unknown('未知', 'unknown'),
|
||||
lock('上锁车门', 'lock'),
|
||||
unlock('解锁车门', 'unlock'),
|
||||
openWindow('打开车窗', 'open window'),
|
||||
closeWindow('关闭车窗', 'close window'),
|
||||
appointAC('预约空调', 'appoint AC'),
|
||||
openAC('打开空调', 'open AC'),
|
||||
closeAC('关闭空调', 'close AC'),
|
||||
changeACTemp('修改空调温度', 'change AC temperature'),
|
||||
coolSharply('极速降温', 'cool sharply'),
|
||||
prepareCar('一键备车', 'prepare car'),
|
||||
meltSnow('一键融雪', 'melt snow'),
|
||||
openTrunk('打开后备箱', 'open trunk'),
|
||||
closeTrunk('关闭后备箱', 'close trunk'),
|
||||
honk('鸣笛', 'honk'),
|
||||
locateCar('定位车辆', 'locate car'),
|
||||
openWheelHeat('开启方向盘加热', 'open wheel heat'),
|
||||
closeWheelHeat('关闭方向盘加热', 'close wheel heat'),
|
||||
openMainSeatHeat('开启主座椅加热', 'open main seat heat'),
|
||||
closeMainSeatHeat('关闭主座椅加热', 'close main seat heat'),
|
||||
openMinorSeatHeat('开启副座椅加热', 'open minor seat heat'),
|
||||
closeMinorSeatHeat('关闭副座椅加热', 'close minor seat heat');
|
||||
|
||||
const VehicleCommandType(this.chinese, this.english);
|
||||
|
||||
final String chinese;
|
||||
final String english;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:ai_chat_core/ai_chat_core.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_vosk_wakeword/flutter_vosk_wakeword.dart';
|
||||
@@ -10,7 +11,6 @@ import 'package:porcupine_flutter/porcupine_manager.dart';
|
||||
|
||||
import 'bloc/ai_chat_cubit.dart';
|
||||
import 'bloc/command_state.dart';
|
||||
import 'models/vehicle_cmd.dart';
|
||||
|
||||
/// 车辆命令处理器抽象类
|
||||
abstract class VehicleCommandHandler {
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import '../enums/message_status.dart';
|
||||
|
||||
class ChatMessage {
|
||||
final String id;
|
||||
final String text;
|
||||
final bool isUser;
|
||||
final DateTime timestamp;
|
||||
MessageStatus status;
|
||||
|
||||
ChatMessage({
|
||||
required this.id,
|
||||
required this.text,
|
||||
required this.isUser,
|
||||
required this.timestamp,
|
||||
this.status = MessageStatus.normal,
|
||||
});
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
import '../enums/vehicle_command_type.dart';
|
||||
|
||||
/// 车辆控制命令类
|
||||
class VehicleCommand {
|
||||
final VehicleCommandType type;
|
||||
final Map<String, dynamic>? params;
|
||||
final String error;
|
||||
late String commandId;
|
||||
|
||||
VehicleCommand({required this.type, this.params, this.error = ''}) {
|
||||
commandId = DateTime.now().millisecondsSinceEpoch.toString();
|
||||
}
|
||||
|
||||
// 从字符串创建命令(用于从API响应解析)
|
||||
factory VehicleCommand.fromString(
|
||||
String commandStr, Map<String, dynamic>? params, String error) {
|
||||
// 将字符串转换为枚举值
|
||||
VehicleCommandType type;
|
||||
try {
|
||||
type = VehicleCommandType.values.firstWhere(
|
||||
(e) => e.name == commandStr,
|
||||
orElse: () => VehicleCommandType.unknown,
|
||||
);
|
||||
} catch (e) {
|
||||
print('Error parsing command string: $e');
|
||||
// 默认为搜车指令,或者你可以选择抛出异常
|
||||
type = VehicleCommandType.unknown;
|
||||
}
|
||||
|
||||
return VehicleCommand(type: type, params: params, error: error);
|
||||
}
|
||||
|
||||
// 将命令转换为字符串(用于API请求)
|
||||
String get commandString => type.name;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'VehicleCommand(command: ${type.name}, params: $params)';
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import 'package:ai_chat_assistant/models/vehicle_cmd.dart';
|
||||
|
||||
class VehicleCommandResponse {
|
||||
final String? tips;
|
||||
final List<VehicleCommand> commands;
|
||||
|
||||
VehicleCommandResponse({
|
||||
this.tips,
|
||||
required this.commands,
|
||||
});
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
class VehicleStatusInfo {
|
||||
/// 对应车架号
|
||||
String vin = "";
|
||||
|
||||
/// 剩余里程
|
||||
double remainingMileage = 0;
|
||||
|
||||
/// 空调开关状态 开启true,false关闭
|
||||
bool acState = false;
|
||||
|
||||
/// 空调温度 未拿到、不支持都返回0;原始值
|
||||
double acTemp = 0;
|
||||
|
||||
/// AC开关 true打开,false关闭
|
||||
bool acSwitch = false;
|
||||
|
||||
/// 左前锁状态 true解锁,false闭锁
|
||||
bool leftFrontLockState = false;
|
||||
|
||||
/// 右前锁状态 true解锁,false闭锁
|
||||
bool rightFrontLockState = false;
|
||||
|
||||
/// 左后锁状态 true解锁,false闭锁
|
||||
bool leftRearLockState = false;
|
||||
|
||||
/// 右后锁状态 true解锁,false闭锁
|
||||
bool rightRearLockState = false;
|
||||
|
||||
/// 左前门状态 true打开,false关闭
|
||||
bool leftFrontDoorState = false;
|
||||
|
||||
/// 右前门状态 true打开,false关闭
|
||||
bool rightFrontDoorState = false;
|
||||
|
||||
/// 左后门状态 true打开,false关闭
|
||||
bool leftRearDoorState = false;
|
||||
|
||||
/// 右后门状态 true打开,false关闭
|
||||
bool rightRearDoorState = false;
|
||||
|
||||
/// 左前窗状态 true打开,false关闭
|
||||
bool leftFrontWindowState = false;
|
||||
|
||||
/// 右前窗状态 true打开,false关闭
|
||||
bool rightFrontWindowState = false;
|
||||
|
||||
/// 左后窗状态 true打开,false关闭
|
||||
bool leftRearWindowState = false;
|
||||
|
||||
/// 右后窗状态 true打开,false关闭
|
||||
bool rightRearWindowState = false;
|
||||
|
||||
/// 后备箱状态 true打开,false关闭
|
||||
bool trunkState = false;
|
||||
|
||||
/// 电量百分比
|
||||
int soc = 0;
|
||||
|
||||
/// 车内温度
|
||||
double temperatureInside = 0;
|
||||
|
||||
/// 方向盘加热状态 false:未加热 true:加热中
|
||||
bool wheelHeat = false;
|
||||
|
||||
/// 主座椅加热状态 false:未加热 true:加热中
|
||||
bool mainSeatHeat = false;
|
||||
|
||||
/// 副座椅加热档位 false:未加热 true:加热中
|
||||
bool minorSeatHeat = false;
|
||||
|
||||
/// 是否行驶中,仅用于车控前置条件判断
|
||||
bool isDriving = false;
|
||||
|
||||
/// 会员是否过期 true过期,false不过期
|
||||
bool vipExpired = false;
|
||||
|
||||
/// 会员有效期,时间戳,单位毫秒
|
||||
int vipTime = 0;
|
||||
|
||||
/// 距离过期还剩多少天
|
||||
int vipRemainCount = 0;
|
||||
|
||||
/// 车况更新时间 ms
|
||||
int statusUpdateTime = 0;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'IGKVehicleStatusInfo{vin:$vin, LockState:($leftFrontLockState,$rightFrontLockState,$leftRearLockState,$rightRearLockState), DoorState:($leftFrontDoorState,$rightFrontDoorState,$leftRearDoorState,$rightRearDoorState), WindowState: ($leftFrontWindowState,$rightFrontWindowState,$leftRearWindowState,$rightRearWindowState), trunkState: $trunkState, soc: $soc, remainingMileage: $remainingMileage, acState: $acState, acTemp: $acTemp, acSwitch:$acSwitch, isDriving:$isDriving, vipExpired: $vipExpired, vipTime: $vipTime, vipRemainCount: $vipRemainCount}';
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:ai_chat_assistant/models/chat_message.dart';
|
||||
import 'package:ai_chat_core/ai_chat_core.dart';
|
||||
import 'package:t_basic_intl/intl.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../enums/message_status.dart';
|
||||
import '../widgets/chat_box.dart';
|
||||
import '../widgets/gradient_background.dart';
|
||||
import '../services/message_service.dart';
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:ai_chat_assistant/utils/tts_util.dart';
|
||||
import '../utils/tts_util.dart';
|
||||
|
||||
import '../utils/common_util.dart';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import '../enums/vehicle_command_type.dart';
|
||||
import '../models/vehicle_status_info.dart';
|
||||
import 'package:ai_chat_core/ai_chat_core.dart';
|
||||
|
||||
|
||||
/// 命令处理回调函数定义
|
||||
typedef CommandCallback = Future<(bool, Map<String, dynamic>? params)> Function(
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import 'dart:convert';
|
||||
import 'package:ai_chat_core/ai_chat_core.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import '../models/vehicle_cmd.dart';
|
||||
import '../models/vehicle_cmd_response.dart';
|
||||
import 'vehicle_state_service.dart';
|
||||
|
||||
/// 车辆命令服务 - 负责与后端交互以获取和处理车辆控制命令
|
||||
class VehicleCommandService {
|
||||
|
||||
@@ -8,14 +8,17 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
import '../services/chat_sse_service.dart';
|
||||
import '../services/chat_sse_service.dart' as Service;
|
||||
import '../services/classification_service.dart';
|
||||
import '../services/control_recognition_service.dart';
|
||||
// import '../services/audio_recorder_service.dart';
|
||||
// import '../services/voice_recognition_service.dart';
|
||||
import 'command_service.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
|
||||
import 'platform_tts_service.dart';
|
||||
|
||||
const aliSdkChannelName = 'com.example.ai_chat_assistant/ali_sdk';
|
||||
|
||||
// 用单例的模式创建
|
||||
class MessageService extends ChangeNotifier {
|
||||
static const MethodChannel _asrChannel = MethodChannel('com.example.ai_chat_assistant/ali_sdk');
|
||||
@@ -77,7 +80,9 @@ class MessageService extends ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
final ChatSseService _chatSseService = ChatSseService();
|
||||
// final ChatSseService _chatSseService = ChatSseService(PlatformTtsService(aliSdkChannelName));
|
||||
final Service.ChatSseService _chatSseService = Service.ChatSseService();
|
||||
|
||||
// final LocalTtsService _ttsService = LocalTtsService();
|
||||
// final AudioRecorderService _audioService = AudioRecorderService();
|
||||
// final VoiceRecognitionService _recognitionService = VoiceRecognitionService();
|
||||
|
||||
36
lib/services/platform_tts_service.dart
Normal file
36
lib/services/platform_tts_service.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
import 'package:ai_chat_core/ai_chat_core.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
/// TtsService 的平台特定实现,通过 MethodChannel 调用原生代码
|
||||
class PlatformTtsService implements TtsService {
|
||||
@override
|
||||
final String channelName;
|
||||
|
||||
final MethodChannel _channel;
|
||||
|
||||
PlatformTtsService(this.channelName): _channel = MethodChannel(channelName);
|
||||
|
||||
Future<T?> _execute<T>(String method, [Map<Object, Object>? arguments]) {
|
||||
return _channel.invokeMethod(method, arguments);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> start(bool isChinese) async {
|
||||
return await _execute('startTts', {'isChinese': isChinese}) ?? false;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> send(String text) async {
|
||||
await _execute('sendTts', {'text': text});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> complete() async {
|
||||
await _execute('completeTts');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stop() async {
|
||||
await _execute('stopTts');
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import 'package:ai_chat_assistant/utils/common_util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_tts/flutter_tts.dart';
|
||||
|
||||
@Deprecated('Use TtsService interface and its implementations instead')
|
||||
class LocalTtsService {
|
||||
final FlutterTts _flutterTts = FlutterTts();
|
||||
bool _isPlaying = false;
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:http/http.dart' as http;
|
||||
import 'dart:convert';
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
|
||||
@Deprecated('VoiceRecognitionService is deprecated, please use the new implementation if available.')
|
||||
class VoiceRecognitionService {
|
||||
Future<String?> recognizeSpeech(List<int> audioBytes,
|
||||
{String lang = 'cn'}) async {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:ai_chat_core/ai_chat_core.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../models/chat_message.dart';
|
||||
import 'chat_bubble.dart';
|
||||
|
||||
class ChatBox extends StatelessWidget {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import 'package:ai_chat_assistant/utils/common_util.dart';
|
||||
import 'package:ai_chat_assistant/widgets/rotating_image.dart';
|
||||
import 'package:ai_chat_core/ai_chat_core.dart';
|
||||
import 'package:t_basic_intl/intl.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_markdown_plus/flutter_markdown_plus.dart';
|
||||
import '../enums/message_status.dart';
|
||||
import '../models/chat_message.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../services/message_service.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
Reference in New Issue
Block a user