增加通讯协议
This commit is contained in:
+142
-68
@@ -4,7 +4,7 @@
|
||||
#include "datacard.h"
|
||||
#include "ledindicator.h"
|
||||
#include "paramcontrol.h"
|
||||
#include "udpcommunication.h"
|
||||
#include "car.h"
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
@@ -19,7 +19,7 @@ DebugMaintainPage::DebugMaintainPage(AppContext* ctx, QWidget* parent)
|
||||
root->setSpacing(0);
|
||||
|
||||
m_titleBar = new TitleBar(ctx, this);
|
||||
m_titleBar->setTitle("洗消调试");
|
||||
m_titleBar->setTitle("调试维护");
|
||||
root->addWidget(m_titleBar);
|
||||
|
||||
// 警告横幅(常显红闪)
|
||||
@@ -34,35 +34,38 @@ DebugMaintainPage::DebugMaintainPage(AppContext* ctx, QWidget* parent)
|
||||
// 左球阀控制区
|
||||
QWidget* left = new QWidget(this);
|
||||
QVBoxLayout* leftLay = new QVBoxLayout(left);
|
||||
leftLay->setContentsMargins(0, 0, 0, 0);
|
||||
leftLay->setSpacing(16);
|
||||
leftLay->setContentsMargins(20, 10, 10, 10);
|
||||
leftLay->setSpacing(60);
|
||||
leftLay->addWidget(makeValveGroup(1));
|
||||
leftLay->addWidget(makeValveGroup(2));
|
||||
leftLay->addStretch(1);
|
||||
left->setFixedWidth(300);
|
||||
main->addWidget(left);
|
||||
|
||||
// 中央卡片区
|
||||
// 中央卡片区(左右两列:左列 底盘/机械臂/气体检测仪 纵向排列,右列 洗消参数)
|
||||
QWidget* center = new QWidget(this);
|
||||
QVBoxLayout* centerLay = new QVBoxLayout(center);
|
||||
QHBoxLayout* centerLay = new QHBoxLayout(center);
|
||||
centerLay->setContentsMargins(0, 0, 0, 0);
|
||||
centerLay->setSpacing(10);
|
||||
centerLay->setSpacing(28); // 与 main 的列间距一致
|
||||
|
||||
QHBoxLayout* miniRow = new QHBoxLayout();
|
||||
miniRow->setSpacing(10);
|
||||
m_chassisCard = new DataCard("底盘", center);
|
||||
QWidget* centerLeft = new QWidget(center);
|
||||
QVBoxLayout* centerLeftLay = new QVBoxLayout(centerLeft);
|
||||
centerLeftLay->setContentsMargins(0, 0, 0, 0);
|
||||
centerLeftLay->setSpacing(10);
|
||||
|
||||
m_chassisCard = new DataCard("底盘", centerLeft);
|
||||
m_chassisCard->addField("电量", "85%");
|
||||
m_chassisCard->addField("电压", "360V");
|
||||
m_armCard = new DataCard("机械臂", center);
|
||||
m_armCard = new DataCard("机械臂", centerLeft);
|
||||
m_armCard->addField("末端位置", "XYZ");
|
||||
m_armCard->addField("姿态", "RX/RY/RZ");
|
||||
m_gasCard = new DataCard("气体检测仪", center);
|
||||
m_gasCard = new DataCard("气体检测仪", centerLeft);
|
||||
m_gasCard->addField("主机状态", "待机");
|
||||
m_gasCard->addField("浓度", "0 ppb");
|
||||
miniRow->addWidget(m_chassisCard, 1);
|
||||
miniRow->addWidget(m_armCard, 1);
|
||||
miniRow->addWidget(m_gasCard, 1);
|
||||
centerLay->addLayout(miniRow, 1);
|
||||
centerLeftLay->addWidget(m_chassisCard, 1);
|
||||
centerLeftLay->addWidget(m_armCard, 1);
|
||||
centerLeftLay->addWidget(m_gasCard, 1);
|
||||
centerLay->addWidget(centerLeft, 1);
|
||||
|
||||
m_washCard = new DataCard("洗消参数", center);
|
||||
m_washCard->addField("洗消模式", "--");
|
||||
@@ -79,11 +82,11 @@ DebugMaintainPage::DebugMaintainPage(AppContext* ctx, QWidget* parent)
|
||||
// 右泵控制区
|
||||
QWidget* right = new QWidget(this);
|
||||
QVBoxLayout* rightLay = new QVBoxLayout(right);
|
||||
rightLay->setContentsMargins(0, 0, 0, 0);
|
||||
rightLay->setSpacing(8);
|
||||
rightLay->addWidget(makePumpGroup("air", "空压机"));
|
||||
rightLay->addWidget(makePumpGroup("plunger", "柱塞泵"));
|
||||
rightLay->addWidget(makePumpGroup("leaf", "叶片泵"));
|
||||
rightLay->setContentsMargins(10, 10,20,10);
|
||||
rightLay->setSpacing(40);
|
||||
rightLay->addWidget(makePumpGroup("air", "空压机(rpm)"), 0, Qt::AlignHCenter);
|
||||
rightLay->addWidget(makePumpGroup("plunger", "柱塞泵(rpm)"), 0, Qt::AlignHCenter);
|
||||
rightLay->addWidget(makePumpGroup("leaf", "叶片泵(rpm)"), 0, Qt::AlignHCenter);
|
||||
rightLay->addStretch(1);
|
||||
right->setFixedWidth(420);
|
||||
main->addWidget(right);
|
||||
@@ -92,28 +95,56 @@ DebugMaintainPage::DebugMaintainPage(AppContext* ctx, QWidget* parent)
|
||||
|
||||
// 底部指示灯条
|
||||
QWidget* bottom = new QWidget(this);
|
||||
bottom->setObjectName("DebugBottom");
|
||||
bottom->setFixedHeight(94);
|
||||
bottom->setStyleSheet(QString("background-color:%1;border-top:1px solid %2;")
|
||||
// 用 #DebugBottom 限定选择器:不带选择器的样式表会连子控件一起套上边框和底色
|
||||
bottom->setStyleSheet(QString("QWidget#DebugBottom{background-color:%1;border-top:1px solid %2;}")
|
||||
.arg(C::PANEL, C::BORDER));
|
||||
QHBoxLayout* bottomLay = new QHBoxLayout(bottom);
|
||||
bottomLay->setContentsMargins(36, 0, 24, 0);
|
||||
// 左起 364 = 36(页面边距) + 300(球阀列) + 28(列间距),与中央“底盘”列左边缘对齐
|
||||
bottomLay->setContentsMargins(364, 0, 24, 0);
|
||||
bottomLay->setSpacing(48);
|
||||
m_ledPlunger = new LedIndicator("柱塞泵", bottom);
|
||||
m_ledAir = new LedIndicator("空压机", bottom);
|
||||
m_ledLeaf = new LedIndicator("叶片泵", bottom);
|
||||
m_ledLevel = new LedIndicator("液位低", bottom);
|
||||
bottomLay->addWidget(m_ledPlunger);
|
||||
bottomLay->addWidget(m_ledAir);
|
||||
bottomLay->addWidget(m_ledLeaf);
|
||||
bottomLay->addWidget(m_ledLevel);
|
||||
auto makeLed = [&](const QString& text) {
|
||||
LedIndicator* led = new LedIndicator(text, bottom);
|
||||
led->setTextPixelSize(40); // 字号与卡片标题一致
|
||||
led->setDotAfterText(true); // 圆点画在文字后面
|
||||
bottomLay->addWidget(led);
|
||||
return led;
|
||||
};
|
||||
m_ledPlunger = makeLed("柱塞泵");
|
||||
m_ledAir = makeLed("空压机");
|
||||
m_ledLeaf = makeLed("叶片泵");
|
||||
m_ledLevel = makeLed("液位低");
|
||||
bottomLay->addStretch(1);
|
||||
QPushButton* back = button("返回", "", bottom);
|
||||
back->setFixedSize(144, 76);
|
||||
back->setFixedSize(160, 76);
|
||||
back->setStyleSheet(cancelButtonStyle(40)); // 选中(悬停/按下/焦点)红底白字
|
||||
connect(back, &QPushButton::clicked, this, [this]() { emit navigate(PageJob); });
|
||||
bottomLay->addWidget(back);
|
||||
root->addWidget(bottom);
|
||||
|
||||
connect(ctx->comm(), &UdpCommunication::telemetryUpdated, this, &DebugMaintainPage::refresh);
|
||||
connect(ctx->comm(), &CarCommunication::telemetryUpdated, this, [this]() {
|
||||
m_telemetrySeen = true; // 遥测一到,球阀到位灯改由 refresh() 接管
|
||||
refresh();
|
||||
});
|
||||
|
||||
// Tab 顺序(循环):返回 → D1控制 → D2控制 → 各泵(转速输入 → 启动 → 停止) → 回到返回。
|
||||
// 这些按钮在控件级样式表里写了 :checked,而控件级样式表的优先级高于全局
|
||||
// QPushButton:focus,默认焦点链下容易看起来“停不上去”,故显式排一遍保证都能停住
|
||||
QWidget* tabChain[] = {
|
||||
m_valve1Btn, m_valve2Btn,
|
||||
m_airRpm->editor(), m_airStart, m_airStop,
|
||||
m_plungerRpm->editor(), m_plungerStart, m_plungerStop,
|
||||
m_leafRpm->editor(), m_leafStart, m_leafStop,
|
||||
};
|
||||
QWidget* prev = back;
|
||||
for (QWidget* w : tabChain) {
|
||||
if (!w) continue;
|
||||
QWidget::setTabOrder(prev, w);
|
||||
prev = w;
|
||||
}
|
||||
QWidget::setTabOrder(prev, back); // 回到起点,形成循环
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
@@ -127,26 +158,36 @@ QWidget* DebugMaintainPage::makeValveGroup(int valve)
|
||||
lay->setContentsMargins(12, 12, 12, 12);
|
||||
lay->setSpacing(8);
|
||||
|
||||
QLabel* title = label(QString("D%1 球阀").arg(valve), 20, C::TEXT, true, grp);
|
||||
QLabel* title = label(QString("D%1 球阀").arg(valve), 30, C::TEXT, true, grp);
|
||||
lay->addWidget(title);
|
||||
|
||||
// 控制开/关(toggle)
|
||||
QPushButton* ctrl = button(QString("D%1 控制:关闭").arg(valve), "", grp);
|
||||
// 控制开/关(toggle):文字固定,底色表示状态——未选中=关闭(红)、选中=开启(绿)
|
||||
QPushButton* ctrl = button(QString("D%1 控制").arg(valve), "", grp);
|
||||
ctrl->setCheckable(true);
|
||||
ctrl->setFixedHeight(64);
|
||||
connect(ctrl, &QPushButton::toggled, this, [this, valve, ctrl](bool on) {
|
||||
ctrl->setText(QString("D%1 控制:%2").arg(valve).arg(on ? "开启" : "关闭"));
|
||||
ctrl->setFixedSize(180, 64); // 窄按钮,与泵组的“上电”一致
|
||||
// 控件级样式表优先级高于全局 QSS,故 :focus 也在这里补,否则 Tab 选中看不出变化
|
||||
ctrl->setStyleSheet(QString("QPushButton{background-color:%1;color:#FFFFFF;border:none;}"
|
||||
"QPushButton:checked{background-color:%2;color:#FFFFFF;border:none;}"
|
||||
"QPushButton:focus{border:4px solid #8ABFFF;}")
|
||||
.arg(C::DANGER).arg(C::SUCCESS));
|
||||
connect(ctrl, &QPushButton::toggled, this, [this, valve](bool on) {
|
||||
ctx()->comm()->sendBallValve(valve, on);
|
||||
});
|
||||
lay->addWidget(ctrl);
|
||||
lay->addWidget(ctrl, 0, Qt::AlignHCenter);
|
||||
|
||||
// 开启到位 / 关闭到位
|
||||
LedIndicator* open = new LedIndicator("开启到位", grp);
|
||||
open->setState(LedIndicator::Off);
|
||||
LedIndicator* close = new LedIndicator("关闭到位", grp);
|
||||
// 开启到位 / 关闭到位(同一行,居中)。未收到车端遥测时保持缺省显示
|
||||
// (开启绿 / 关闭红),首次收到遥测后由 refresh() 按实际到位状态刷新
|
||||
LedIndicator* open = new LedIndicator("开启", grp);
|
||||
open->setState(LedIndicator::Green);
|
||||
LedIndicator* close = new LedIndicator("关闭", grp);
|
||||
close->setState(LedIndicator::Red);
|
||||
lay->addWidget(open);
|
||||
lay->addWidget(close);
|
||||
QHBoxLayout* ioRow = new QHBoxLayout();
|
||||
ioRow->setSpacing(10);
|
||||
ioRow->addStretch(1);
|
||||
ioRow->addWidget(open);
|
||||
ioRow->addWidget(close);
|
||||
ioRow->addStretch(1);
|
||||
lay->addLayout(ioRow);
|
||||
|
||||
// 故障提示
|
||||
QLabel* fault = label("", 16, C::DANGER, true, grp);
|
||||
@@ -175,29 +216,60 @@ QWidget* DebugMaintainPage::makePumpGroup(const QString& pump, const QString& na
|
||||
grp->setProperty("card", true);
|
||||
grp->setStyleSheet(QString("QWidget[card=\"true\"]{background-color:%1;border:2px solid %2;border-radius:12px;}")
|
||||
.arg(C::PANEL, C::BORDER));
|
||||
// 不设固定宽度:卡片按内容自适应(由最宽的“空压机(rpm)”标签决定)。
|
||||
// 固定宽度一旦小于布局最小宽度,标签会被压到小于文字宽度而裁字
|
||||
QVBoxLayout* lay = new QVBoxLayout(grp);
|
||||
lay->setContentsMargins(12, 8, 12, 8);
|
||||
lay->setSpacing(4);
|
||||
lay->setContentsMargins(30, 8, 20, 8);
|
||||
lay->setSpacing(10);
|
||||
|
||||
ParamControl* rpm = new ParamControl(name + "转速", "rpm", 10, 0, 2000, false, false, grp);
|
||||
// 上限按协议各泵量程:空压机 AirComp_Spd 0-3000、柱塞泵 PlungerPump_Spd 0-1450、
|
||||
// 叶片泵 VanePump__Spd 0-2000 rpm。每档 = 显示精度的最小单位,转速是整数显示故为 1 rpm
|
||||
const int rpmMax = (pump == "air") ? 3000 : (pump == "plunger") ? 1450 : 2000;
|
||||
ParamControl* rpm = new ParamControl(name, "", 1, 0, rpmMax, false, false, grp);
|
||||
rpm->setCentered(true);
|
||||
rpm->setValue(200);
|
||||
connect(rpm, &ParamControl::valueChanged, this, [this, pump](double v) {
|
||||
ctx()->comm()->sendPumpRpm(pump, static_cast<int>(v));
|
||||
});
|
||||
|
||||
lay->addWidget(rpm);
|
||||
|
||||
QPushButton* power = button("上电", "", grp);
|
||||
power->setCheckable(true);
|
||||
power->setFixedHeight(56);
|
||||
connect(power, &QPushButton::toggled, this, [this, pump, power](bool on) {
|
||||
power->setText(on ? "上电中" : "上电");
|
||||
ctx()->comm()->sendPumpPower(pump, on);
|
||||
// 启动 / 停止:互斥,选中态对应当前泵状态(绿=运行、红=停止)。
|
||||
// 控件级样式表优先级高于全局 QSS,故 :focus 也在这里补,否则 Tab 选中看不出变化
|
||||
QPushButton* start = button("启动", "", grp);
|
||||
start->setCheckable(true);
|
||||
start->setFixedSize(120, 60);
|
||||
start->setStyleSheet(QString("QPushButton:checked{background-color:%1;color:#FFFFFF;border:none;}"
|
||||
"QPushButton:focus{border:4px solid #8ABFFF;}")
|
||||
.arg(C::SUCCESS));
|
||||
QPushButton* stop = button("停止", "", grp);
|
||||
stop->setCheckable(true);
|
||||
stop->setFixedSize(120, 60);
|
||||
stop->setStyleSheet(QString("QPushButton:checked{background-color:%1;color:#FFFFFF;border:none;}"
|
||||
"QPushButton:focus{border:4px solid #8ABFFF;}")
|
||||
.arg(C::DANGER));
|
||||
|
||||
connect(start, &QPushButton::clicked, this, [this, pump, start, stop]() {
|
||||
start->setChecked(true);
|
||||
stop->setChecked(false);
|
||||
ctx()->comm()->sendPumpPower(pump, true);
|
||||
});
|
||||
lay->addWidget(power);
|
||||
connect(stop, &QPushButton::clicked, this, [this, pump, start, stop]() {
|
||||
stop->setChecked(true);
|
||||
start->setChecked(false);
|
||||
ctx()->comm()->sendPumpPower(pump, false);
|
||||
});
|
||||
QHBoxLayout* pwrRow = new QHBoxLayout();
|
||||
pwrRow->setSpacing(12);
|
||||
pwrRow->addStretch(1);
|
||||
pwrRow->addWidget(start);
|
||||
pwrRow->addWidget(stop);
|
||||
pwrRow->addStretch(1);
|
||||
lay->addLayout(pwrRow);
|
||||
|
||||
if (pump == "air") { m_airRpm = rpm; m_airPower = power; }
|
||||
else if (pump == "plunger") { m_plungerRpm = rpm; m_plungerPower = power; }
|
||||
else { m_leafRpm = rpm; m_leafPower = power; }
|
||||
if (pump == "air") { m_airRpm = rpm; m_airStart = start; m_airStop = stop; }
|
||||
else if (pump == "plunger") { m_plungerRpm = rpm; m_plungerStart = start; m_plungerStop = stop; }
|
||||
else { m_leafRpm = rpm; m_leafStart = start; m_leafStop = stop; }
|
||||
return grp;
|
||||
}
|
||||
|
||||
@@ -220,11 +292,13 @@ void DebugMaintainPage::refresh()
|
||||
m_washCard->setField(5, t.pumpFaults.value(0));
|
||||
m_washCard->setField(6, t.pumpFaults.value(0));
|
||||
|
||||
// 球阀到位反馈
|
||||
m_v1Open->setState(t.d1open ? LedIndicator::Green : LedIndicator::Off);
|
||||
m_v1Close->setState(t.d1close ? LedIndicator::Red : LedIndicator::Off);
|
||||
m_v2Open->setState(t.d2open ? LedIndicator::Green : LedIndicator::Off);
|
||||
m_v2Close->setState(t.d2close ? LedIndicator::Red : LedIndicator::Off);
|
||||
// 球阀到位反馈:未收到过车端遥测时不动,保留构造时的缺省显示(开启绿 / 关闭红)
|
||||
if (m_telemetrySeen) {
|
||||
m_v1Open->setState(t.d1open ? LedIndicator::Green : LedIndicator::Off);
|
||||
m_v1Close->setState(t.d1close ? LedIndicator::Red : LedIndicator::Off);
|
||||
m_v2Open->setState(t.d2open ? LedIndicator::Green : LedIndicator::Off);
|
||||
m_v2Close->setState(t.d2close ? LedIndicator::Red : LedIndicator::Off);
|
||||
}
|
||||
|
||||
// 球阀故障提示
|
||||
bool v1Fault = t.valveFault.contains("D1");
|
||||
@@ -234,10 +308,10 @@ void DebugMaintainPage::refresh()
|
||||
if (v2Fault) { m_valveFault2->setText(t.valveFault); m_valveFault2->show(); startBlink(m_valveFault2, "blink"); }
|
||||
else { stopBlink(m_valveFault2, "blink"); m_valveFault2->hide(); }
|
||||
|
||||
// 泵上电状态同步
|
||||
if (m_airPower) m_airPower->setChecked(t.air);
|
||||
if (m_plungerPower) m_plungerPower->setChecked(t.plunger);
|
||||
if (m_leafPower) m_leafPower->setChecked(t.leaf);
|
||||
// 泵启停状态同步(互斥组内先置“启动”再置“停止”,两者互补,结果总是一选中一未选)
|
||||
if (m_airStart) { m_airStart->setChecked(t.air); m_airStop->setChecked(!t.air); }
|
||||
if (m_plungerStart){ m_plungerStart->setChecked(t.plunger); m_plungerStop->setChecked(!t.plunger); }
|
||||
if (m_leafStart) { m_leafStart->setChecked(t.leaf); m_leafStop->setChecked(!t.leaf); }
|
||||
|
||||
// 底部指示灯
|
||||
m_ledPlunger->setState(t.plunger ? LedIndicator::Green : LedIndicator::Off);
|
||||
|
||||
Reference in New Issue
Block a user