机器状态 优化
This commit is contained in:
@@ -39,7 +39,7 @@ class AuthCubit extends Cubit<AuthState> {
|
||||
if (user != null) {
|
||||
// 1. 建立 TCP 连接 (远程控制)
|
||||
tcp.connect(host: TCPConsts.TCP_IP, port: TCPConsts.TCP_PORT);
|
||||
await _authTcpDatasource.sendAuthPacket();//包括发送认证包和获取列表和切换函数
|
||||
//await _authTcpDatasource.sendAuthPacket();//包括发送认证包和获取列表和切换函数
|
||||
// 2. 同步全局 App 状态
|
||||
appCubit.setAuth(user);
|
||||
// 3. 进入已登录状态
|
||||
|
||||
@@ -9,8 +9,8 @@ import '../../../../core/di/injection.dart';
|
||||
import '../../../../core/network/net_message_dispatcher.dart';
|
||||
import '../../../../core/network/protocol_decoder.dart';
|
||||
import '../../../devices/presentation/bloc/devices_cubit.dart';
|
||||
import '../../../devices/presentation/bloc/device_status_bloc.dart'; // 👈 新增导入
|
||||
import '../../../devices/presentation/bloc/device_status_state.dart'; // 👈 新增导入
|
||||
import '../../../devices/presentation/bloc/device_status_bloc.dart';
|
||||
import '../../../devices/presentation/bloc/device_status_state.dart';
|
||||
|
||||
class RunningStatusPage extends StatefulWidget {
|
||||
const RunningStatusPage({super.key});
|
||||
@@ -20,18 +20,33 @@ class RunningStatusPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _RunningStatusPageState extends State<RunningStatusPage> {
|
||||
// 视图切换状态
|
||||
bool _isCardView = true;
|
||||
|
||||
// 解析定位质量数值为文字描述
|
||||
String _parseLocationQuality(int locationValue) {
|
||||
switch (locationValue) {
|
||||
case 0:
|
||||
return '无效';
|
||||
case 1:
|
||||
return 'GPS 单点定位';
|
||||
case 2:
|
||||
return 'DGPS 伪距差分或 SBAS';
|
||||
case 4:
|
||||
return 'RTK 固定解';
|
||||
case 5:
|
||||
return 'RTK 浮点解';
|
||||
default:
|
||||
return '未知($locationValue)'; // 处理未定义的数值,避免显示空值
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final deviceState = context.read<DevicesCubit>().state;
|
||||
final currentDevice = deviceState.selectedDevice;
|
||||
|
||||
if (currentDevice == null) {
|
||||
return const Scaffold(
|
||||
body: Center(child: Text("加载中...")),
|
||||
);
|
||||
return const Scaffold(body: Center(child: Text("加载中...")));
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
@@ -39,7 +54,6 @@ class _RunningStatusPageState extends State<RunningStatusPage> {
|
||||
body: CustomScrollView(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
slivers: [
|
||||
// 1. 顶部导航栏
|
||||
SliverAppBar(
|
||||
backgroundColor: const Color(0xFF1677FF),
|
||||
pinned: true,
|
||||
@@ -55,21 +69,21 @@ class _RunningStatusPageState extends State<RunningStatusPage> {
|
||||
),
|
||||
),
|
||||
|
||||
// 2. 状态信息行(动态更新)- 使用 BlocBuilder 监听
|
||||
BlocBuilder<DeviceStatusBloc, DeviceStatusState>(
|
||||
builder: (context, state) {
|
||||
String yaw = '--';
|
||||
String qual = '--';
|
||||
String satelliteCnt = '--';
|
||||
String headingStatus = "--";
|
||||
|
||||
if (state is DeviceStatusUpdated) {
|
||||
yaw = state.status.yaw.toStringAsFixed(2);
|
||||
qual = state.status.qual.toString();
|
||||
headingStatus = state.status.headingStatus == 0 ? '未初始化' : '已初始化';
|
||||
qual = _parseLocationQuality(state.status.qual);
|
||||
qual = int.parse(state.status.qual.toString());
|
||||
satelliteCnt = state.status.satelliteCnt.toString();
|
||||
} else if (state is DeviceStatusError) {
|
||||
yaw = '错误';
|
||||
qual = '-';
|
||||
satelliteCnt = '-';
|
||||
headingStatus = '-';
|
||||
}
|
||||
|
||||
return SliverToBoxAdapter(
|
||||
@@ -79,7 +93,7 @@ class _RunningStatusPageState extends State<RunningStatusPage> {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text("航向角状态:$yaw°", style: const TextStyle(fontSize: 14)),
|
||||
Text("航向角状态:$headingStatus", style: const TextStyle(fontSize: 14)),
|
||||
Text("定位质量:$qual", style: const TextStyle(fontSize: 14)),
|
||||
Text("卫星数:$satelliteCnt", style: const TextStyle(fontSize: 14)),
|
||||
],
|
||||
@@ -89,7 +103,6 @@ class _RunningStatusPageState extends State<RunningStatusPage> {
|
||||
},
|
||||
),
|
||||
|
||||
// 3. 选项卡 + 刷新按钮
|
||||
SliverToBoxAdapter(
|
||||
child: Container(
|
||||
color: Colors.white,
|
||||
@@ -98,7 +111,6 @@ class _RunningStatusPageState extends State<RunningStatusPage> {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
// 切换选项卡
|
||||
Row(
|
||||
children: [
|
||||
GestureDetector(
|
||||
@@ -112,7 +124,6 @@ class _RunningStatusPageState extends State<RunningStatusPage> {
|
||||
),
|
||||
],
|
||||
),
|
||||
// 刷新按钮
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF1677FF),
|
||||
@@ -128,16 +139,12 @@ class _RunningStatusPageState extends State<RunningStatusPage> {
|
||||
),
|
||||
),
|
||||
|
||||
// 4. 内容区域 - 使用 BlocBuilder 监听
|
||||
SliverFillRemaining(
|
||||
child: BlocBuilder<DeviceStatusBloc, DeviceStatusState>(
|
||||
builder: (context, state) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
|
||||
child: _isCardView ? _buildCardContentView(state) : _buildChartContentView(),
|
||||
);
|
||||
},
|
||||
@@ -153,7 +160,7 @@ class _RunningStatusPageState extends State<RunningStatusPage> {
|
||||
title,
|
||||
style: TextStyle(
|
||||
color: isActive ? const Color(0xFF1677FF) : const Color(0xFF666666),
|
||||
fontSize: 16,
|
||||
fontSize: 18,
|
||||
fontWeight: isActive ? FontWeight.bold : FontWeight.normal,
|
||||
decoration: isActive ? TextDecoration.underline : null,
|
||||
decorationColor: const Color(0xFF1677FF),
|
||||
@@ -162,90 +169,123 @@ class _RunningStatusPageState extends State<RunningStatusPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCardItem(String title, String value) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(title, style: const TextStyle(fontSize: 16, color: Color(0xFF333333))),
|
||||
Text(value, style: const TextStyle(fontSize: 16, color: Color(0xFF666666))),
|
||||
],
|
||||
// 电机参数表格
|
||||
Widget _buildMotorTable(DeviceStatusUpdated state) {
|
||||
final status = state.status;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 12),
|
||||
child: Text("电机参数", style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
|
||||
),
|
||||
Table(
|
||||
border: TableBorder.all(color: const Color(0xFFE5E5E5)),
|
||||
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
||||
children: [
|
||||
TableRow(
|
||||
decoration: const BoxDecoration(color: Color(0xFFF5F5F5)),
|
||||
children: [const SizedBox(), _buildTableCell("左轮", isHeader: true), _buildTableCell("右轮", isHeader: true)],
|
||||
),
|
||||
TableRow(
|
||||
children: [
|
||||
_buildTableCell("目标速度\n(rpm)"),
|
||||
_buildTableCell(status.leftTargetSpeed.toStringAsFixed(2)),
|
||||
_buildTableCell(status.rightTargetSpeed.toStringAsFixed(2)),
|
||||
],
|
||||
),
|
||||
TableRow(
|
||||
children: [
|
||||
_buildTableCell("测量速度\n(rpm)"),
|
||||
_buildTableCell(status.leftTargetSpeed.toStringAsFixed(2)),
|
||||
_buildTableCell(status.rightTargetSpeed.toStringAsFixed(2)),
|
||||
//_buildTableCell(status.leftMeasuredSpeed.toStringAsFixed(2)),
|
||||
//_buildTableCell(status.rightMeasuredSpeed.toStringAsFixed(2)),
|
||||
],
|
||||
),
|
||||
TableRow(
|
||||
children: [
|
||||
_buildTableCell("电流(A)"),
|
||||
_buildTableCell(status.leftCurrent.toStringAsFixed(2)),
|
||||
_buildTableCell(status.rightCurrent.toStringAsFixed(2)),
|
||||
],
|
||||
),
|
||||
TableRow(
|
||||
children: [
|
||||
_buildTableCell("电机温度(°C)"),
|
||||
_buildTableCell(status.leftMotorTemp.toStringAsFixed(2)),
|
||||
_buildTableCell(status.rightMotorTemp.toStringAsFixed(2)),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// 其他参数表格
|
||||
Widget _buildOtherParamsTable(DeviceStatusUpdated state) {
|
||||
final status = state.status;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 12),
|
||||
child: Text("其他参数", style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
|
||||
),
|
||||
Table(
|
||||
border: TableBorder.all(color: const Color(0xFFE5E5E5)),
|
||||
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
||||
children: [
|
||||
TableRow(
|
||||
decoration: const BoxDecoration(color: Color(0xFFF5F5F5)),
|
||||
children: [_buildTableCell("名称", isHeader: true), _buildTableCell("数值", isHeader: true)],
|
||||
),
|
||||
TableRow(children: [_buildTableCell("俯仰角(°)"), _buildTableCell(status.pitch.toStringAsFixed(2))]),
|
||||
TableRow(children: [_buildTableCell("翻滚角(°)"), _buildTableCell(status.roll.toStringAsFixed(2))]),
|
||||
TableRow(children: [_buildTableCell("航向角(°)"), _buildTableCell(status.yaw.toStringAsFixed(2))]),
|
||||
TableRow(children: [_buildTableCell("电量(%)"), _buildTableCell(status.battery)]),
|
||||
TableRow(children: [_buildTableCell("芯片温度(°C)"), _buildTableCell(status.chipTemp.toStringAsFixed(2))]),
|
||||
TableRow(children: [_buildTableCell("割刀速度(rpm)"), _buildTableCell(status.knifeCuttingSpeed)]),
|
||||
TableRow(children: [_buildTableCell("纬度(°)"), _buildTableCell(status.latitude.toStringAsFixed(6))]),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTableCell(String text, {bool isHeader = false}) {
|
||||
return TableCell(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8),
|
||||
child: Text(
|
||||
text,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: isHeader ? const Color(0xFF333333) : const Color(0xFF666666),
|
||||
fontWeight: isHeader ? FontWeight.bold : FontWeight.normal,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Widget _buildCardContentView(DeviceStatusState state) {
|
||||
// 从 Bloc 状态中提取数据
|
||||
String voltage = '--';
|
||||
String leftSpeed = '--';
|
||||
String rightSpeed = '--';
|
||||
String yaw = '--';
|
||||
String pitch = '--';
|
||||
String roll = '--';
|
||||
String satelliteCnt = '--';
|
||||
String qual = '--';
|
||||
String latitude = '--';
|
||||
String longitude = '--';
|
||||
String timeStamp = '--';
|
||||
String knifeCuttingSpeed = '--';
|
||||
String controlMode = '--';
|
||||
String workingArea = '--';
|
||||
String battery = '--';
|
||||
String obstacleFlag = '--';
|
||||
|
||||
if (state is DeviceStatusUpdated) {
|
||||
final status = state.status;
|
||||
voltage = status.voltage.toStringAsFixed(2);
|
||||
leftSpeed = status.leftTargetSpeed.toStringAsFixed(2);
|
||||
rightSpeed = status.rightTargetSpeed.toStringAsFixed(2);
|
||||
yaw = status.yaw.toStringAsFixed(2);
|
||||
pitch = status.pitch.toStringAsFixed(2);
|
||||
roll = status.roll.toStringAsFixed(2);
|
||||
satelliteCnt = status.satelliteCnt.toString();
|
||||
qual = status.qual.toString();
|
||||
latitude = status.latitude.toStringAsFixed(8);
|
||||
longitude = status.longitude.toStringAsFixed(8);
|
||||
timeStamp = '${status.latitude} ${status.longitude}';
|
||||
knifeCuttingSpeed = status.knifeCuttingSpeed;
|
||||
controlMode = status.controlMode;
|
||||
workingArea = status.workingArea;
|
||||
battery = status.battery;
|
||||
obstacleFlag = status.obstacleFlag;
|
||||
return SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(children: [_buildMotorTable(state), const SizedBox(height: 20), _buildOtherParamsTable(state)]),
|
||||
);
|
||||
} else if (state is DeviceStatusError) {
|
||||
voltage = '错误';
|
||||
return const Center(
|
||||
child: Text("数据加载失败", style: TextStyle(color: Colors.red, fontSize: 16)),
|
||||
);
|
||||
} else {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(20.0),child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text("设备实时状态", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 16),
|
||||
_buildCardItem("电压", "$voltage V"),
|
||||
_buildCardItem("左轮速度", "$leftSpeed rpm"),
|
||||
_buildCardItem( "右轮速度", "$rightSpeed rpm"),
|
||||
_buildCardItem( "航向角", "$yaw°"),
|
||||
_buildCardItem( "俯仰角", "$pitch°"),
|
||||
_buildCardItem( "翻滚角", "$roll°"),
|
||||
_buildCardItem( "卫星数", satelliteCnt),
|
||||
_buildCardItem( "定位质量", qual),
|
||||
_buildCardItem( "纬度", latitude),
|
||||
_buildCardItem( "经度", longitude),
|
||||
/* //_buildCardItem( "时间戳", timeStamp),*/
|
||||
_buildCardItem( "割刀速度", "$knifeCuttingSpeed rpm"),
|
||||
_buildCardItem( "控制模式", controlMode),
|
||||
_buildCardItem( "作业面积", "$workingArea m²"),
|
||||
_buildCardItem( "电量", "$battery%"),
|
||||
_buildCardItem( "障碍物标志", obstacleFlag),
|
||||
],
|
||||
),
|
||||
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildChartContentView() {
|
||||
@@ -266,13 +306,11 @@ class _RunningStatusPageState extends State<RunningStatusPage> {
|
||||
final currentDevice = deviceState.selectedDevice;
|
||||
|
||||
if (currentDevice != null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text("数据刷新成功!"), duration: Duration(seconds: 1)),
|
||||
);
|
||||
// 这里可以触发 Bloc 事件来刷新数据
|
||||
// context.read<DeviceStatusBloc>().add(RefreshDeviceStatus(deviceId: currentDevice.id));
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("数据刷新成功!"), duration: Duration(seconds: 1)));
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text("暂无设备,无法刷新"), duration: Duration(seconds: 1)),
|
||||
);
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("暂无设备,无法刷新"), duration: Duration(seconds: 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user