feat(device): 实现下位机 JSON 协议(data model 对齐)
按 docs/下位机交互数据模型.md 重构串口协议层: 协议层 - 新增 DeviceMessage 模型,对应 message_id/type/ack/need_ack/data - 新增 JsonProtocolService,4 字节大端长度前缀 + UTF-8 JSON 帧 - 删除原二进制协议(serial_protocol.dart) 服务层 - 新增 DeviceMessageService,集中收发并按 type 分发 - 重写 SerialRunner 为 JsonSerialRunner,使用 create_task/control 消息 数据模型 - DeviceState 增加 doorStatus/lightStatus/taskStatus/lastInfoAt - 新增 DeviceInfoNotifier 订阅 device_info 上行 - 灯光按钮接通 light_control 消息 测试 - 新增 device_protocol_test.dart(14 用例) - 修复 models_test.dart 残留的 Step mixSpeed/blowSpeed 错误
This commit is contained in:
@@ -1,30 +1,28 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../../../core/localization/app_localizations.dart';
|
||||
import '../../../core/theme/app_theme.dart';
|
||||
import '../../../shared/widgets/status_indicator.dart';
|
||||
import '../../device/providers/device_info_provider.dart';
|
||||
|
||||
/// 状态栏组件 - 明亮工业风格
|
||||
/// 显示设备名称、实时时钟、系统状态、照明控制、瓷套棒状态
|
||||
class StatusBar extends StatefulWidget {
|
||||
/// 显示设备名称、实时时钟、系统状态、照明控制
|
||||
class StatusBar extends ConsumerStatefulWidget {
|
||||
final bool isRunning;
|
||||
final bool lightOn;
|
||||
final VoidCallback? onLightToggle;
|
||||
final bool ceramicSleeveInstalled;
|
||||
|
||||
const StatusBar({
|
||||
super.key,
|
||||
this.isRunning = false,
|
||||
this.lightOn = false,
|
||||
this.onLightToggle,
|
||||
this.ceramicSleeveInstalled = false,
|
||||
});
|
||||
|
||||
@override
|
||||
State<StatusBar> createState() => _StatusBarState();
|
||||
ConsumerState<StatusBar> createState() => _StatusBarState();
|
||||
}
|
||||
|
||||
class _StatusBarState extends State<StatusBar> {
|
||||
class _StatusBarState extends ConsumerState<StatusBar> {
|
||||
String _currentTime = '';
|
||||
Timer? _timer;
|
||||
|
||||
@@ -51,9 +49,15 @@ class _StatusBarState extends State<StatusBar> {
|
||||
|
||||
String _twoDigits(int n) => n.toString().padLeft(2, '0');
|
||||
|
||||
Future<void> _onLightTap() async {
|
||||
widget.onLightToggle?.call();
|
||||
await ref.read(deviceInfoProvider.notifier).toggleLight();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = AppLocalizations.of(context);
|
||||
final deviceInfo = ref.watch(deviceInfoProvider);
|
||||
|
||||
return Container(
|
||||
height: 56,
|
||||
@@ -86,9 +90,10 @@ class _StatusBarState extends State<StatusBar> {
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
_LightToggleButton(isOn: widget.lightOn, onTap: widget.onLightToggle),
|
||||
const SizedBox(width: 16),
|
||||
_CeramicSleeveStatus(installed: widget.ceramicSleeveInstalled),
|
||||
_LightToggleButton(
|
||||
isOn: deviceInfo.lightingOn,
|
||||
onTap: _onLightTap,
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
StatusIndicator(
|
||||
text: widget.isRunning
|
||||
@@ -114,36 +119,6 @@ class _StatusBarState extends State<StatusBar> {
|
||||
}
|
||||
}
|
||||
|
||||
class _CeramicSleeveStatus extends StatelessWidget {
|
||||
final bool installed;
|
||||
const _CeramicSleeveStatus({required this.installed});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
width: 8,
|
||||
height: 8,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: installed ? Colors.greenAccent : Colors.redAccent,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
installed ? '瓷套棒: 已安装' : '瓷套棒: 未安装',
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: 0.9),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _LightToggleButton extends StatelessWidget {
|
||||
final bool isOn;
|
||||
final VoidCallback? onTap;
|
||||
|
||||
Reference in New Issue
Block a user