feat: 新增ai_chat_core,将core 和 widget 分离(未完成)

迁移了 models enums, utils, http 封装,还有一些extensions;service 只迁移了 sse service
This commit is contained in:
2025-09-29 18:33:46 +08:00
parent ba73d6d780
commit a7ed838c92
40 changed files with 933 additions and 38 deletions

View File

@@ -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';

View File

@@ -1,5 +1,3 @@
import '../enums/vehicle_command_type.dart';
import '../services/command_service.dart';
import 'easy_bloc.dart';
import 'command_state.dart';

View File

@@ -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,

View File

@@ -1,6 +0,0 @@
enum MessageServiceState {
idle,
recording,
recognizing,
replying,
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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 {

View File

@@ -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,
});
}

View File

@@ -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)';
}
}

View File

@@ -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,
});
}

View File

@@ -1,90 +0,0 @@
class VehicleStatusInfo {
/// 对应车架号
String vin = "";
/// 剩余里程
double remainingMileage = 0;
/// 空调开关状态 开启truefalse关闭
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}';
}
}

View File

@@ -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';

View File

@@ -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';

View File

@@ -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(

View File

@@ -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 {

View File

@@ -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();

View 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');
}
}

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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';