Files
SatelliteControl/mainwindow.cpp
zhuo.li a0aed8f539 卫星终端控制软件_V1.1.0
1、增加信道/复位等参数配置
2026-01-04 13:49:35 +08:00

2140 lines
92 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QMessageBox>
#include <QChartView>
#include <QValueAxis>
#include <QBarCategoryAxis>
#include <QBarSeries>
#include <QBarSet>
#include <QChart>
#include <QLegend>
#include <QAreaSeries>
#include <QLineSeries>
#include <QPolarChart>
#include <QScatterSeries>
#include <QSplineSeries>
#include <QStackedBarSeries>
#include <QSplitter>
#include <QToolTip>
#include <QtEndian>
#include <QLineEdit>
#include <QRegularExpressionValidator>
#include <QSettings>
#include <QCoreApplication>
#include "msg.h"
qreal get_rand(qreal maxValue) { return rand() * 1.0 / RAND_MAX * maxValue; }
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
setWindowTitle("卫星终端控制软件_V1.1.0");
//创建logger窗口
m_loggerWidget = std::make_shared<LoggerWidget>();//需要在RecordQuery创建前
m_loggerWidget->hide();
connect(&*m_loggerWidget, &LoggerWidget::sendUdpRequest,
this, &MainWindow::handleUdpRequest);
//创建记录查询窗口
m_recordQueryWidget = std::make_shared<RecordQuery>();
m_recordQueryWidget->hide();
//创建参数配置窗口
m_configParamWidget = std::make_shared<ConfigParam>();
m_configParamWidget->hide();
connect(&*m_configParamWidget, &ConfigParam::sendUdpRequest,
this, &MainWindow::handleUdpRequest);
//创建并初始化图表
createBeiDouSignalStrengthChart();
createAzimuthMapChart();
createBeiDouRDSSSignalStrengthChart();
//
QSplitter *splitter = new QSplitter(Qt::Horizontal);
splitter->addWidget(ui->widgetCallAndMessage);
splitter->addWidget(ui->widgetSatelliteStatus);
setCentralWidget(splitter);
ui->lblPosition->clear();
ui->lblZhuanTaiStatus->clear();
ui->lblHydraulicCylinderHeight->clear();
ui->lblAntennaPowerSupply->clear();
ui->lblPhaseLockedLoop->clear();
//获取日志实例
m_logger = spdlog::get("logger");
//初始化其他控件
ui->lblCallDuration->hide();
ui->btnCallReject->hide();
// 禁用控件
ui->btnUHFSimCardStatus->setEnabled(false);
ui->labelUHFSimCardStatus->setEnabled(false);
// 设置透明样式
QString transparentStyle =
"QToolButton:disabled, QLabel:disabled {"
" background: transparent;"
" border: none;"
" color: transparent;"
"}";
ui->btnUHFSimCardStatus->setStyleSheet(transparentStyle);
ui->labelUHFSimCardStatus->setStyleSheet(transparentStyle);
ui->lblLinkStatus->setText("未连接");
ui->lblLinkStatus->setStyleSheet("color: red;"); // 红色
// 初始化UDP连接状态
m_udpConnected = false;
m_versionQuery = false;
m_channelQuery = false;
m_lastUdpDataTime = QDateTime::currentDateTime();
QString exeDir = QCoreApplication::applicationDirPath();
QSettings settings(exeDir + "/app.ini", QSettings::IniFormat);
m_udpIp = settings.value("Config/PeerIP","192.168.2.10").toString();
m_localPort = settings.value("Config/LocalPort",6680).toInt();
m_peerPort = settings.value("Config/PeerPort",6678).toInt();
//创建udp socket
m_udpSocket = std::make_shared<QUdpSocket>();
m_udpServerSocket = std::make_shared<QUdpSocket>();
m_udpServerSocket->bind(m_localPort);
connect(&*m_udpServerSocket, &QUdpSocket::readyRead, this, &MainWindow::readPendingDatagrams);
// 对电话号码添加校验器
// QRegularExpression regExp("[0-9A-Za-z]{1,20}");
// QRegularExpressionValidator *validator = new QRegularExpressionValidator(regExp, this);
// // 获取 QComboBox 的 lineEdit 并设置校验器
// ui->cmbCallNumber->lineEdit()->setValidator(validator);
m_talkingTimer = std::make_shared<QTimer>();
QObject::connect(&*m_talkingTimer, &QTimer::timeout, [this]() {
m_callDuration += 1;
QTime t(0,0,0);
t = t.addSecs(m_callDuration);
ui->lblCallDuration->setText(t.toString("hh:mm:ss"));
});
m_talkingTimer->stop();
m_timer = new QTimer(this);
connect(m_timer, SIGNAL(timeout()), this, SLOT(onTimerTimeout1s()));
m_timer->start(1000);
//3秒定时状态检测
m_status_timer = new QTimer(this);
connect(m_status_timer, SIGNAL(timeout()), this, SLOT(onTimerLinkStatus()));
m_status_timer->start(3000);
//测试
//test();
ui->tabWidget->setCurrentIndex(0); //tab默认显示rdss tab
m_recordQueryWidget->setupNumberCombo(this, ui->cmbCallNumber, NumberKind::Call);
m_recordQueryWidget->setupNumberCombo(this, ui->cmbMessageNumberForUhfAndS, NumberKind::USMsg);
m_recordQueryWidget->setupNumberCombo(this, ui->cmbMessageNumberForBeiDou, NumberKind::BdMsg);
}
MainWindow::~MainWindow() { delete ui; }
void MainWindow::onTimerTimeout1s(){
//模块状态
if(m_uhfModuleStatus == ModuleStatus::kChecking || m_uhfModuleStatus == ModuleStatus::kUpgrading){
if(m_uhfModuleStatusGrayIcon){
ui->btnUHFModuleStatus->setIcon(QIcon(":/rc/res/circle_green.png"));
}else{
ui->btnUHFModuleStatus->setIcon(QIcon(":/rc/res/circle_gray.png"));
}
m_uhfModuleStatusGrayIcon = !m_uhfModuleStatusGrayIcon;
}
if(m_tiantongModuleStatus == ModuleStatus::kChecking|| m_uhfModuleStatus == ModuleStatus::kUpgrading){
if(m_tiantongModuleStatusGrayIcon){
ui->btnSModueStatus->setIcon(QIcon(":/rc/res/circle_green.png"));
}else{
ui->btnSModueStatus->setIcon(QIcon(":/rc/res/circle_gray.png"));
}
m_tiantongModuleStatusGrayIcon = !m_tiantongModuleStatusGrayIcon;
}
if(m_beidouModuleStatus == ModuleStatus::kChecking|| m_uhfModuleStatus == ModuleStatus::kUpgrading){
if(m_beidouModuleStatusGrayIcon){
ui->btnBeiDouModuleStatus->setIcon(QIcon(":/rc/res/circle_green.png"));
}else{
ui->btnBeiDouModuleStatus->setIcon(QIcon(":/rc/res/circle_gray.png"));
}
m_beidouModuleStatusGrayIcon = !m_beidouModuleStatusGrayIcon;
}
//sim卡状态
//if(m_uhfSimCardStatus == SimCardStatus::kChecking){
// if(m_uhfSimCardStatusGrayIcon){
// ui->btnUHFSimCardStatus->setIcon(QIcon(":/rc/res/card_green.png"));
// }else{
// ui->btnUHFSimCardStatus->setIcon(QIcon(":/rc/res/card_gray.png"));
// }
// m_uhfSimCardStatusGrayIcon = !m_uhfSimCardStatusGrayIcon;
//}
if(m_tiantongSimCardStatus == SimCardStatus::kChecking){
if(m_tiantongSimCardStatusGrayIcon){
ui->btnSSimCardStatus->setIcon(QIcon(":/rc/res/card_green.png"));
}else{
ui->btnSSimCardStatus->setIcon(QIcon(":/rc/res/card_gray.png"));
}
m_tiantongSimCardStatusGrayIcon = !m_tiantongSimCardStatusGrayIcon;
}
if(m_beidouSimCardStatus == SimCardStatus::kChecking){
if(m_beidouSimCardStatusGrayIcon){
ui->btnBeiDouSimCardStatus->setIcon(QIcon(":/rc/res/card_green.png"));
}else{
ui->btnBeiDouSimCardStatus->setIcon(QIcon(":/rc/res/card_gray.png"));
}
m_beidouSimCardStatusGrayIcon = !m_beidouSimCardStatusGrayIcon;
}
//m卡状态
if(m_uhfMCardStatus == MCardStatus::kChecking){
if(m_uhfMCardStatusGrayIcon){
ui->btnUHFMCardStatus->setIcon(QIcon(":/rc/res/card_green.png"));
}else{
ui->btnUHFMCardStatus->setIcon(QIcon(":/rc/res/card_gray.png"));
}
m_uhfMCardStatusGrayIcon = !m_uhfMCardStatusGrayIcon;
}
if(m_tiantongMCardStatus == MCardStatus::kChecking){
if(m_tiantongMCardStatusGrayIcon){
ui->btnSMCardStatus->setIcon(QIcon(":/rc/res/card_green.png"));
}else{
ui->btnSMCardStatus->setIcon(QIcon(":/rc/res/card_gray.png"));
}
m_tiantongMCardStatusGrayIcon = !m_tiantongMCardStatusGrayIcon;
}
// 入网状态
if(m_uhfNetworkAccessStatus == NetworkAccessStatus::kConnecting){
if(m_uhfNetworkAccessStatusGrayIcon){
ui->btnUHFNetworkAccessStatus->setIcon(QIcon(":/rc/res/net_in_no_data.png"));
}else{
ui->btnUHFNetworkAccessStatus->setIcon(QIcon(":/rc/res/net_out.png"));
}
m_uhfNetworkAccessStatusGrayIcon = !m_uhfNetworkAccessStatusGrayIcon;
}
if(m_tiantongNetworkAccessStatus == NetworkAccessStatus::kConnecting){
if(m_tiantongNetworkAccessStatusGrayIcon){
ui->btnSNetworkAccessStatus->setIcon(QIcon(":/rc/res/net_in_no_data.png"));
}else{
ui->btnSNetworkAccessStatus->setIcon(QIcon(":/rc/res/net_out.png"));
}
m_tiantongNetworkAccessStatusGrayIcon = !m_tiantongNetworkAccessStatusGrayIcon;
}
// 呼叫状态
CallStatus callStatus;
if(m_uhfCallStatus != CallStatus::kIdle){
callStatus = m_uhfCallStatus;
}else{
callStatus = m_tiantongCallStatus;
}
if(callStatus != CallStatus::kIdle && callStatus != CallStatus::kOnLine){
if(m_callStatusLabelBlack){
ui->lblCallStatus->setStyleSheet("color: green;");
}else{
ui->lblCallStatus->setStyleSheet("color: blue;");
}
m_callStatusLabelBlack = !m_callStatusLabelBlack;
}
}
void MainWindow::onTimerLinkStatus(){
// 计算当前时间与最后收到数据的时间差(秒)
qint64 secondsSinceLastData = m_lastUdpDataTime.secsTo(QDateTime::currentDateTime());
// 如果超过3秒没有收到数据则认为连接断开
if(secondsSinceLastData >= 3) {
m_logger->info("LinkStatus: secondsSinceLastData = {}", secondsSinceLastData);
if(m_udpConnected) {
m_udpConnected = false;
m_versionQuery = false;
m_channelQuery = false;
ui->lblLinkStatus->setText("未连接");
//QMessageBox::information(this, "提示", "连接已断开");
ui->lblLinkStatus->setStyleSheet("color: red;");
m_logger->error("Link is disconnected");
}
} else {
if(!m_udpConnected) {
m_udpConnected = true;
ui->lblLinkStatus->setText("已连接");
ui->lblLinkStatus->setStyleSheet("color: green;");
//QMessageBox::information(this, "提示", "已连接");
m_logger->info("Link is Connected");
}
// 连接成功后,查询设备信息
queryDeviceInfo();
}
}
// 查询设备信息
void MainWindow::queryDeviceInfo()
{
// 如果版本号尚未查询,则发送查询命令
if(!m_versionQuery) {
sendUdpMessage(pack_config_cmd_SoftVersionGet());
}
// 如果信道类型尚未查询,则发送查询命令
if(!m_channelQuery) {
sendUdpMessage(pack_config_cmd_DefaultChannelGet());
}
}
void MainWindow::handleUdpRequest(const QByteArray &message)
{
sendUdpMessage(message); // 调用实际的发送方法
//m_loggerWidget->updateRespStatus(message);
}
//ctrl+l用于打开日志窗口
void MainWindow::keyPressEvent(QKeyEvent* event){
if(event->key() == Qt::Key_L && event->modifiers() & Qt::ControlModifier){
m_loggerWidget->show();
}else{
QWidget::keyPressEvent(event);
}
}
void MainWindow::StartupTalking(){
if(m_talkingTimer->isActive()){
ui->lblCallDuration->show();
return;
}
m_currentTalkingBeginTime = QDateTime::currentDateTime();
m_callDuration = 0;
QTime t(0,0,0);
t = t.addSecs(m_callDuration);
ui->lblCallDuration->setText(t.toString("hh:mm:ss"));
ui->lblCallDuration->show();
m_talkingTimer->start(1000);
}
void MainWindow::ShutdownTalking(){
if(!m_talkingTimer->isActive()){
return;
}
Record r;
r.beginTime = m_currentTalkingBeginTime;
r.channel = m_currentTalkingChan;
r.type = CommType::Call;
r.direction = m_currentTalkingDirection;
r.number = QString::fromStdString(m_currentTalkingNumber);
r.content = "";
r.isUnread = true;
r.callDuration = m_callDuration;
m_recordQueryWidget->InsertRecord(r);
m_talkingTimer->stop();
}
void MainWindow::readPendingDatagrams(){
while (m_udpServerSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(m_udpServerSocket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
// 读取数据报
m_udpServerSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
//m_logger->info("接收到udp消息, 长度 = {}, 数据 = {}",datagram.size(),datagram.toStdString());
m_logger->info("Received a udp message, len = {}, data = {}",datagram.size(),datagram.toHex(' ').toStdString());
processCommand(datagram);
}
}
void MainWindow::test() {
// 随机生成信号能量数据
setSignalStrengthValues(
QStringList{"01", "02", "03", "04", "05", "06", "07", "08", "09"},
QList{get_rand(10.0), get_rand(10.0), get_rand(10.0), get_rand(10.0),
get_rand(10.0), get_rand(10.0), get_rand(50.0), get_rand(33.0), get_rand(27.0)});
// 随机生成方向图数据
QList<QPointF> values;
for (int i = 0; i < 9; i += 1) {
values.append(QPointF(get_rand(360.0), get_rand(360.0)));
}
setAzimuthValues(values);
Record r1;
r1.beginTime = QDateTime::currentDateTime();
r1.channel = Channel::Uhf;
r1.type = CommType::ShortMessage;
r1.direction = CommDirection::Receive;
r1.number = "10001";
r1.content = "地阿斯顿发射点发大水发大水发";
r1.isUnread = true;
r1.callDuration = 0;
Record r2;
r2.beginTime = QDateTime::currentDateTime();
r2.channel = Channel::BeiDou;
r2.type = CommType::ShortMessage;
r2.direction = CommDirection::Send;
r2.number = "10002";
r2.content = "dsfgdsfgsdfgsdfgdfsgdsfgdsfg";
r2.isUnread = false;
r2.callDuration = 0;
Record r3;
r3.beginTime = QDateTime::currentDateTime();
r3.channel = Channel::S;
r3.type = CommType::Call;
r3.direction = CommDirection::Receive;
r3.number = "10003";
r3.content = "fdghfgdhfghdfghdfghdfghf";
r3.isUnread = true;
r3.callDuration = 30;
m_msgList.push_back(r1);
m_msgList.push_back(r2);
m_msgList.push_back(r3);
UpdateMessageList();
m_recordQueryWidget->InsertRecords(m_msgList);
}
void MainWindow::test1(){
// 随机生成信号能量数据
setSignalStrengthValues(
QStringList{"01", "02", "03", "04", "05", "06"},
QList{get_rand(20.0), get_rand(45.0), get_rand(50.0), get_rand(45.0),
get_rand(50.0), get_rand(40.0)});
// 随机生成方向图数据
QList<QPointF> values;
for (int i = 0; i < 6; i += 1) {
values.append(QPointF(get_rand(360.0), get_rand(360.0)));
}
setAzimuthValues(values);
Record r3;
r3.beginTime = QDateTime::currentDateTime();
r3.channel = Channel::S;
r3.type = CommType::ShortMessage;
r3.direction = CommDirection::Receive;
r3.number = "10003";// + QString::number((get_rand(8)));;
r3.content = "fdghfgdhfghdfghdfghdfghf";// + QString::number((get_rand(15)));
r3.isUnread = true;
r3.callDuration = 0;
m_msgList.push_back(r3);
UpdateMessageList();
m_recordQueryWidget->InsertRecord(m_msgList.back());
}
// 槽函数实现
void MainWindow::handleHovered(bool status, int index, QBarSet* barset)
{
if(status && barset && index >=0) {
// 获取实际数值(考虑堆叠结构)
const qreal value = barset->at(index);
// 显示定制化提示框
QToolTip::showText(QCursor::pos(),
QString("数值: %1\n阈值: %2")
.arg(value, 0, 'f', 1) // 保留1位小数
.arg(value < 36 ? "" : ""),
nullptr,
QRect(),
2000); // 显示持续2秒
// 添加高亮效果
//barset->setBorderWidth(2);
//barset->setColor(barset->color().lighter(110)); // 亮度提高10%
} else {
// 恢复原始样式
//if(barset) {
// 获取实际数值(考虑堆叠结构)
// const qreal value = barset->at(index);
//barset->setBorderWidth(1);
//barset->setColor(value < 36 ? QColor("#C0C0C0") : QColor("#0000FF"));
//}
}
}
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
void MainWindow::createBeiDouSignalStrengthChart() {
m_signalStrengthChart = new QChart;
m_signalStrengthChart->setTitle("载噪比");
m_signalStrengthChart->legend()->setVisible(false);
m_signalStrengthChart->legend()->setAlignment(Qt::AlignBottom);
// m_signalStrengthChart->setAnimationOptions(QChart::SeriesAnimations);
m_signalStrengthChartXAxis = new QBarCategoryAxis;
m_signalStrengthChart->addAxis(m_signalStrengthChartXAxis, Qt::AlignBottom);
m_signalStrengthChartYAxis = new QValueAxis;
m_signalStrengthChartYAxis->setRange(0, 50);
m_signalStrengthChart->addAxis(m_signalStrengthChartYAxis, Qt::AlignLeft);
// series->attachAxis(axisY);
// 减小图表边距 - 这是关键设置
m_signalStrengthChart->setMargins(QMargins(0, 0, 0, 0)); // 左上右下全部设为0
QChartView *chartView = new QChartView(m_signalStrengthChart, this);
chartView->setRenderHint(QPainter::Antialiasing);
// 设置ChartView的边距
chartView->setContentsMargins(0, 0, 0, 0);
ui->vboxChannelBeidouSignalStrength->addWidget(chartView);
m_stackedSeries = new QStackedBarSeries;
connect(m_stackedSeries, &QStackedBarSeries::hovered, this, &MainWindow::handleHovered);
}
void MainWindow::setSignalStrengthValues(const QStringList &categories,
const QList<qreal> &yValues) {
// 清空旧数据
m_signalStrengthChart->removeAllSeries();
m_signalStrengthChartXAxis->clear();
// 创建数据集
QBarSet *set0 = new QBarSet("Power");
QBarSet *set1 = new QBarSet("Power2");
//set0->append(yValues);
//set1->append(yValues);
foreach (qreal val, yValues) {
if(val >= 36.0)
{
*set0 << 0;
*set1 << val;
}
else
{
*set0 << val;
*set1 << 0;
}
}
//auto set0 = new QBarSet("Power");
//set0->append(yValues);
// 动态设置柱形颜色
set0->setBrush(QBrush(QColor("#C0C0C0")));
set1->setBrush(QBrush(QColor("#0000FF")));
//for(int i = 0; i < set0->count(); ++i) {
// const qreal value = set0->at(i);
// set0->setBrush(QBrush(value < 36.0 ? QColor("#C0C0C0") : QColor("#0000FF")));
// set0->setPen(QPen(value < 36.0 ? QColor("#606060") : QColor("#0d47a1"), 1));
//}
// 创建柱状序列
//QBarSeries *series = new QBarSeries();
//series->append(set0);
//m_signalStrengthChart->addSeries(series);
// 添加对象追踪防止内存泄漏
//set0->setParent(series); // 建立父子关系
// 创建 QStackedBarSeries 对象, 保留并重用 QStackedBarSeries 对象而非每次新建
//if(m_stackedSeries == nullptr) {
// m_stackedSeries = new QStackedBarSeries();
//}
//->clear();
QStackedBarSeries *series2 = new QStackedBarSeries();
//m_stackedSeries->setBarWidth(0.8); // 设置柱子相对宽度
//m_stackedSeries->setUseOpenGL(true); // 启用GPU加速
series2->append(set0);
series2->append(set1);
// 添加对象追踪防止内存泄漏
set0->setParent(series2); // 建立父子关系
set1->setParent(series2); // 建立父子关系
m_signalStrengthChart->addSeries(series2);
//保留并重用QBarSeries对象而非每次新建
//if(m_series == nullptr) {
// m_series = new QBarSeries();
// m_chart->addSeries(m_series);
//}
//m_series->clear();
// 绑定坐标轴
//series2->attachAxis(m_signalStrengthChartXAxis);
series2->attachAxis(m_signalStrengthChartYAxis);
// 设置X轴标签
m_signalStrengthChartXAxis->append(categories);
// 动态调整Y轴范围
//qreal maxValue = *std::max_element(yValues.begin(), yValues.end());
//m_signalStrengthChartYAxis->setRange(0, maxValue * 1.2); // 留20%余量
// 优化显示效果
series2->setLabelsVisible(false); // 隐藏数值标签
m_signalStrengthChart->legend()->hide(); // 隐藏图例
// 更新卫星数量显示
ui->lblSatelliteCount->setText(QString::asprintf("%d", categories.count()));
}
void MainWindow::createBeiDouRDSSSignalStrengthChart() {
m_RDS1signalStrengthChart = new QChart;
m_RDS1signalStrengthChart->setTitle("载噪比");
m_RDS1signalStrengthChart->legend()->setVisible(false);
m_RDS1signalStrengthChart->legend()->setAlignment(Qt::AlignBottom);
// m_RDS1signalStrengthChart->setAnimationOptions(QChart::SeriesAnimations);
m_RDS1signalStrengthChartXAxis = new QBarCategoryAxis;
m_RDS1signalStrengthChart->addAxis(m_RDS1signalStrengthChartXAxis, Qt::AlignBottom);
m_RDS1signalStrengthChartYAxis = new QValueAxis;
m_RDS1signalStrengthChartYAxis->setRange(0, 50);
m_RDS1signalStrengthChart->addAxis(m_RDS1signalStrengthChartYAxis, Qt::AlignLeft);
// series->attachAxis(axisY);
// 减小图表边距 - 这是关键设置
m_RDS1signalStrengthChart->setMargins(QMargins(0, 0, 0, 0)); // 左上右下全部设为0
QChartView *chartView = new QChartView(m_RDS1signalStrengthChart, this);
chartView->setRenderHint(QPainter::Antialiasing);
// 设置ChartView的边距
chartView->setContentsMargins(0, 0, 0, 0);
ui->vboxChannelBeidouRDS1SignalStrength->addWidget(chartView);
m_RDS2signalStrengthChart = new QChart;
m_RDS2signalStrengthChart->setTitle("载噪比");
m_RDS2signalStrengthChart->legend()->setVisible(false);
m_RDS2signalStrengthChart->legend()->setAlignment(Qt::AlignBottom);
// m_RDS2signalStrengthChart->setAnimationOptions(QChart::SeriesAnimations);
m_RDS2signalStrengthChartXAxis = new QBarCategoryAxis;
m_RDS2signalStrengthChart->addAxis(m_RDS2signalStrengthChartXAxis, Qt::AlignBottom);
m_RDS2signalStrengthChartYAxis = new QValueAxis;
m_RDS2signalStrengthChartYAxis->setRange(0, 50);
m_RDS2signalStrengthChart->addAxis(m_RDS2signalStrengthChartYAxis, Qt::AlignLeft);
// series->attachAxis(axisY);
// 减小图表边距 - 这是关键设置
m_RDS2signalStrengthChart->setMargins(QMargins(0, 0, 0, 0)); // 左上右下全部设为0
QChartView *chartView2 = new QChartView(m_RDS2signalStrengthChart, this);
chartView->setRenderHint(QPainter::Antialiasing);
// 设置ChartView的边距
chartView->setContentsMargins(0, 0, 0, 0);
ui->vboxChannelBeidouRDS2SignalStrength->addWidget(chartView2);
}
void MainWindow::setRDSSSignalStrengthValues(uint8_t type, const QStringList &categories,
const QList<qreal> &yValues) {
if((type != uint8_t(RDSSType::RDSS_S1)) && (type != uint8_t(RDSSType::RDSS_S2))){
m_logger->error("RDSSType: type illegal value, type = {}", type);
return;
}
if(type == uint8_t(RDSSType::RDSS_S1))
{
// 清空旧数据
m_RDS1signalStrengthChart->removeAllSeries();
m_RDS1signalStrengthChartXAxis->clear();
}
else
{
// 清空旧数据
m_RDS2signalStrengthChart->removeAllSeries();
m_RDS2signalStrengthChartXAxis->clear();
}
// 创建数据集
QBarSet *set0 = new QBarSet("Power");
QBarSet *set1 = new QBarSet("Power2");
foreach (qreal val, yValues) {
if(val >= 36.0)
{
*set0 << 0;
*set1 << val;
}
else
{
*set0 << val;
*set1 << 0;
}
}
// 动态设置柱形颜色
set0->setBrush(QBrush(QColor("#C0C0C0")));
set1->setBrush(QBrush(QColor("#0000FF")));
QStackedBarSeries *series2 = new QStackedBarSeries();
series2->append(set0);
series2->append(set1);
// 添加对象追踪防止内存泄漏
set0->setParent(series2); // 建立父子关系
set1->setParent(series2); // 建立父子关系
if(type == uint8_t(RDSSType::RDSS_S1))
{
m_RDS1signalStrengthChart->addSeries(series2);
series2->attachAxis(m_RDS1signalStrengthChartYAxis);
// 设置X轴标签
m_RDS1signalStrengthChartXAxis->append(categories);
// 优化显示效果
series2->setLabelsVisible(false); // 隐藏数值标签
m_RDS1signalStrengthChart->legend()->hide(); // 隐藏图例
// 更新卫星数量显示
ui->rds1SatelliteCount->setText(QString::asprintf("%d", categories.count()));
}
else
{
m_RDS2signalStrengthChart->addSeries(series2);
series2->attachAxis(m_RDS2signalStrengthChartYAxis);
// 设置X轴标签
m_RDS2signalStrengthChartXAxis->append(categories);
// 优化显示效果
series2->setLabelsVisible(false); // 隐藏数值标签
m_RDS2signalStrengthChart->legend()->hide(); // 隐藏图例
// 更新卫星数量显示
ui->rds2SatelliteCount->setText(QString::asprintf("%d", categories.count()));
}
}
void MainWindow::createAzimuthMapChart() {
const qreal angularMin = 0;
const qreal angularMax = 360;
const qreal radialMin = 0;
const qreal radialMax = 90;
m_azimuthChart = new QPolarChart;
//m_azimuthChart->setTitle("");
m_azimuthChart->legend()->setVisible(false);
// 减小图表边距 - 这是关键设置
m_azimuthChart->setMargins(QMargins(0, 0, 0, 0)); // 左上右下全部设为0
auto angularAxis = new QValueAxis;
angularAxis->setTickCount(9);
angularAxis->setLabelFormat("%d");
angularAxis->setShadesVisible(true);
angularAxis->setShadesBrush(QBrush(QColor(249, 249, 255)));
m_azimuthChart->addAxis(angularAxis, QPolarChart::PolarOrientationAngular);
auto radialAxis = new QValueAxis;
radialAxis->setTickCount(7);
radialAxis->setLabelFormat("%d");
m_azimuthChart->addAxis(radialAxis, QPolarChart::PolarOrientationRadial);
radialAxis->setRange(radialMin, radialMax);
angularAxis->setRange(angularMin, angularMax);
QChartView *chartView = new QChartView(m_azimuthChart, this);
chartView->setRenderHint(QPainter::Antialiasing);
// 设置ChartView的边距
chartView->setContentsMargins(0, 0, 0, 0);
ui->vboxAzimuthMap->addWidget(chartView);
}
void MainWindow::setAzimuthValues(const QList<QPointF> &points) {
m_azimuthChart->removeAllSeries();
auto series = new QScatterSeries;
//series->setName("方位");
//series->setMarkerShape(QScatterSeries::MarkerShapeCircle); // 可选:圆形
series->setMarkerSize(10.0);
series->append(points);
m_azimuthChart->addSeries(series);
// 关联到已存在的极坐标轴
for (QAbstractAxis* ax : m_azimuthChart->axes(QPolarChart::PolarOrientationAngular))
series->attachAxis(ax);
for (QAbstractAxis* ax : m_azimuthChart->axes(QPolarChart::PolarOrientationRadial))
series->attachAxis(ax);
}
//--------------------------------------------------------------------------------------
// 消息列表操作
//--------------------------------------------------------------------------------------
void MainWindow::UpdateMessageList() {
ui->tblMessageList->clear();
QStringList column_labels;
column_labels << "读取状态"
<< "开始时间"
<< "信道"
<< "方向"
<< "号码"
<< "消息内容";
// 设置列表行数和列数
int rowCount = std::count_if(m_msgList.begin(),m_msgList.end(),[](const Record& r){ return r.type == CommType::ShortMessage;});
ui->tblMessageList->setRowCount(rowCount); // 设置行数
ui->tblMessageList->setColumnCount(column_labels.size()); // 设置列数
// 设置水平表头
ui->tblMessageList->setHorizontalHeaderLabels(column_labels);
// 设置垂直表头
int column_index = 0;
ui->tblMessageList->setColumnWidth(column_index, 80); // 读取状态
column_index = column_index + 1;
ui->tblMessageList->setColumnWidth(column_index, 180); // 开始时间
column_index = column_index + 1;
ui->tblMessageList->setColumnWidth(column_index, 60); // 信道
column_index = column_index + 1;
ui->tblMessageList->setColumnWidth(column_index, 60); // 方向
column_index = column_index + 1;
ui->tblMessageList->setColumnWidth(column_index, 120); // 号码
column_index = column_index + 1;
ui->tblMessageList->setColumnWidth(column_index, 400); // 消息内容
column_index = column_index + 1;
//插入所有项
m_unReadMsgCount = 0;
int rowIndex = 0;
for (int index = 0; index < m_msgList.size(); index++) {
Record& r = m_msgList[index];
if(r.type == CommType::Call){
continue;
}
int column_index = 0;
// 读取状态
auto item = new QTableWidgetItem(r.isUnread ? "未读" : "已读");
item->setData(Qt::UserRole,index);
item->setTextAlignment(Qt::AlignCenter);
if(r.isUnread){
item->setBackground(Qt::cyan);
++m_unReadMsgCount;
}
ui->tblMessageList->setItem(rowIndex, column_index, item);
column_index = column_index + 1;
// 开始时间
item = new QTableWidgetItem(r.beginTime.toString("yyyy-MM-dd hh:mm:ss"));
item->setTextAlignment(Qt::AlignCenter);
ui->tblMessageList->setItem(rowIndex, column_index, item);
column_index = column_index + 1;
// 信道
item = new QTableWidgetItem(r.channel == Channel::Uhf?"UHF":(r.channel==Channel::S?"S":"北斗"));
item->setTextAlignment(Qt::AlignCenter);
ui->tblMessageList->setItem(rowIndex, column_index, item);
column_index = column_index + 1;
// 方向
item = new QTableWidgetItem(r.direction==CommDirection::Receive?"接收":"发送");
item->setTextAlignment(Qt::AlignCenter);
ui->tblMessageList->setItem(rowIndex, column_index, item);
column_index = column_index + 1;
// 号码
item = new QTableWidgetItem(r.number);
item->setTextAlignment(Qt::AlignCenter);
ui->tblMessageList->setItem(rowIndex, column_index, item);
column_index = column_index + 1;
// 消息内容
item = new QTableWidgetItem(r.content);
item->setToolTip(r.content);
ui->tblMessageList->setItem(rowIndex, column_index, item);
column_index = column_index + 1;
rowIndex++;
}
ui->lblUnreadMessageCount->setText(QString("%1").arg(m_unReadMsgCount));
}
//--------------------------------------------------------------------------------------
// 槽函数
//--------------------------------------------------------------------------------------
bool MainWindow::checkNumber(const QString& number){
if (number.isEmpty()) {
QMessageBox::information(this, "错误", "请输入电话号码");
return false;
}
// 检查号码是否只包含数字 0-9
QRegularExpression digitOnly("^[0-9]*$"); // 正则表达式:只允许数字
if (!digitOnly.match(number).hasMatch()) {
QMessageBox::information(this, "错误", "电话号码只能包含数字0-9");
return false;
}
//检查号码长度
if (number.size() > 20){
QMessageBox::information(this, "错误", "电话号码长度不能超过20");
return false;
}
// TODO: 检查电话号码格式是否满足要求
return true;
}
bool MainWindow::checkMessage(const QString& message){
// 检查消息是否为空
if (message.isEmpty()) {
QMessageBox::information(this, "错误", "请输入要发送的消息");
return false;
}
// 检查消息长度
if (message.length() > 140) {
QMessageBox::information(this, "错误", "消息太长不能超过140个字符");
return false;
}
return true;
}
std::pair<bool,Channel> MainWindow::selectChannel(ChannelType comm_type){
//U无SIM卡状态
bool isUhfChannelOk = (m_uhfModuleStatus == ModuleStatus::kNormal)
&& (m_uhfNetworkAccessStatus == NetworkAccessStatus::kConnectedDataIsActivated || m_uhfNetworkAccessStatus == NetworkAccessStatus::kConnectedDataIsNotActivated);
bool isSChannelOk = (m_tiantongModuleStatus == ModuleStatus::kNormal)
&& (m_tiantongSimCardStatus == SimCardStatus::kExist)
&& (m_tiantongNetworkAccessStatus == NetworkAccessStatus::kConnectedDataIsActivated || m_tiantongNetworkAccessStatus == NetworkAccessStatus::kConnectedDataIsNotActivated);
if(comm_type == ChannelType::ChannelUHF)
{
if(!isUhfChannelOk)
{
QMessageBox::information(this, "提示", "UHF通道不正常, 无法进行通信");
return std::make_pair(false,Channel::Uhf);
}
else
{
return std::make_pair(true,Channel::Uhf);
}
}
else if(comm_type == ChannelType::ChannelS)
{
if(!isSChannelOk)
{
QMessageBox::information(this, "提示", "S通道不正常, 无法进行通信");
return std::make_pair(false,Channel::S);
}
else
{
return std::make_pair(true,Channel::S);
}
}
else if(comm_type == ChannelType::ChannelAuto)
{
if(!isUhfChannelOk && !isSChannelOk){
QMessageBox::information(this, "提示", "UHF和S通道都不正常, 无法进行通信");
return std::make_pair(false,Channel::S);
}
if(isUhfChannelOk && !isSChannelOk){
return std::make_pair(true,Channel::Uhf);
}else if(!isUhfChannelOk && isSChannelOk){
return std::make_pair(true,Channel::S);
}else{
if(m_tiantongSignalStrength >= m_uhfSignalStrength){
return std::make_pair(true,Channel::S);
}else{
return std::make_pair(true,Channel::Uhf);
}
}
}
else
{
QMessageBox::information(this, "提示", "通道错误, 无法进行通信");
return std::make_pair(false,Channel::Uhf);
}
}
void MainWindow::on_btnCallAnswer_clicked() {
if(m_uhfCallStatus == CallStatus::kIdle && m_tiantongCallStatus == CallStatus::kIdle){
// 检查电话号码是否为空
QString number = ui->cmbCallNumber->currentText();
if(!checkNumber(number)){
return;
}
ChannelType commtype;
// 呼叫
if(ui->rdbChannelUHF->isChecked()){
commtype = ChannelType::ChannelUHF;
}else if(ui->rdbChannelS->isChecked()){
commtype = ChannelType::ChannelS;
}else if(ui->rdbChannelAuto->isChecked()){
commtype = ChannelType::ChannelAuto;
}else{
return;
}
std::pair<bool,Channel> r = selectChannel(commtype);
if(!r.first){
return;
}
if (m_recordQueryWidget->saveNumber(NumberKind::Call, number)) {
//QMessageBox::information(this, "提示", "保存成功");
// 触发器已保证只保留最新10条
m_recordQueryWidget->refreshNumberCombo(ui->cmbCallNumber, NumberKind::Call);
}
m_currentTalkingDirection = CommDirection::Send;
if(r.second == Channel::Uhf){
sendUdpMessage(pack_uhf_dial_cmd(number.toStdString()));
}else if(r.second == Channel::S){
sendUdpMessage(pack_tiantong_dial_cmd(number.toStdString()));
}
}else if(m_uhfCallStatus == CallStatus::kCallIsComing){
sendUdpMessage(pack_uhf_answer());
}else if(m_tiantongCallStatus == CallStatus::kCallIsComing){
sendUdpMessage(pack_tiantong_answer());
}
}
void MainWindow::on_btnCallReject_clicked() {
if(m_uhfCallStatus != CallStatus::kIdle){
sendUdpMessage(pack_uhf_hang_up_cmd());
}
if(m_tiantongCallStatus != CallStatus::kIdle){
sendUdpMessage(pack_tiantong_hang_up_cmd());
}
}
void MainWindow::on_btnSendMessageByUhfOrS_clicked() {
QString number = ui->cmbMessageNumberForUhfAndS->currentText();
ChannelType commtype;
if(!checkNumber(number)){
return;
}
QString message = ui->txtMessageContentForUhfAndS->toPlainText();
if(!checkMessage(message)){
return;
}
// 发送信息
if(ui->rdbChannelUHF->isChecked()){
commtype = ChannelType::ChannelUHF;
}else if(ui->rdbChannelS->isChecked()){
commtype = ChannelType::ChannelS;
}else if(ui->rdbChannelAuto->isChecked()){
commtype = ChannelType::ChannelAuto;
}else{
return;
}
std::pair<bool,Channel> r = selectChannel(commtype);
if(!r.first){
return;
}
if (m_recordQueryWidget->saveNumber(NumberKind::USMsg, number)) {
//QMessageBox::information(this, "提示", "保存成功");
// 触发器已保证只保留最新10条
m_recordQueryWidget->refreshNumberCombo(ui->cmbMessageNumberForUhfAndS, NumberKind::USMsg);
}
if(r.second == Channel::Uhf){
sendUdpMessage(pack_uhf_short_message_cmd(number.toStdString(),message.toStdU16String()));
}else if(r.second == Channel::S){
sendUdpMessage(pack_tiantong_short_message_cmd(number.toStdString(),message.toStdU16String()));
}
}
void MainWindow::on_btnSendMessageByBeiDou_clicked()
{
QString number = ui->cmbMessageNumberForBeiDou->currentText();
if(!checkNumber(number)){
return;
}
QString message = ui->txtMessageContentForBeiDou->toPlainText();
if(!checkMessage(message)){
return;
}
if (m_recordQueryWidget->saveNumber(NumberKind::BdMsg, number)) {
//QMessageBox::information(this, "提示", "保存成功");
// 触发器已保证只保留最新10条
m_recordQueryWidget->refreshNumberCombo(ui->cmbMessageNumberForBeiDou, NumberKind::BdMsg);
}
sendUdpMessage(pack_beidou_short_message_cmd(number.toStdString(),message.toStdU16String()));
}
void MainWindow::on_tblMessageList_currentItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous)
{
int currentRow = ui->tblMessageList->currentRow();
if(currentRow == -1){
ui->txtCurrentItemMessageContent->clear();
}else{
int index = ui->tblMessageList->item(currentRow,0)->data(Qt::UserRole).toInt();
ui->txtCurrentItemMessageContent->setText(m_msgList[index].content);
if(m_msgList[index].isUnread){
m_msgList[index].isUnread = false;
ui->tblMessageList->item(currentRow,0)->setText("已读");
ui->tblMessageList->item(currentRow,0)->setBackground(Qt::white);
--m_unReadMsgCount;
ui->lblUnreadMessageCount->setText(QString("%1").arg(m_unReadMsgCount));
}
}
}
void MainWindow::on_btnRecordQuery_clicked() {
m_recordQueryWidget->show();
}
//--------------------------------------------------------------------------------------
// 与底层消息交互
//--------------------------------------------------------------------------------------
bool MainWindow::sendUdpMessage(const QByteArray &udpMessage) {
const QHostAddress address(m_udpIp);
m_logger->info("send a udp message, len = {}, data = {}",udpMessage.size(),udpMessage.toHex(' ').toStdString());
if (m_udpSocket->writeDatagram(udpMessage, address, m_peerPort) !=
udpMessage.size()) {
//m_logger->error("发送udp消息错误");
m_logger->error("An error occurred when sending a udp message");
return false;
}
return true;
}
//--------------------------------------------------------------------------------------
// 处理命令
//--------------------------------------------------------------------------------------
void MainWindow::processCommand(QByteArray& cmd){
if(cmd.size() < 5){
return;
}
if(pack_deslip(cmd) < 0)
{
return;
}
// 更新最后收到数据的时间
m_lastUdpDataTime = QDateTime::currentDateTime();
// 如果当前状态是未连接,立即更新状态
if(!m_udpConnected) {
m_udpConnected = true;
ui->lblLinkStatus->setText("已连接");
ui->lblLinkStatus->setStyleSheet("color: green;");
//QMessageBox::information(this, "提示", "已连接");
m_logger->info("Link is Connected");
}
switch(uint8_t(cmd[COMMAND_TYPE_INDEX])){
case uint8_t(CommandType::kTianTongVoice):
processTianTongVoiceCmd(cmd);
break;
case uint8_t(CommandType::kUhfVoice):
processUhfVoiceCmd(cmd);
break;
case uint8_t(CommandType::kTianTongShortMessage):
processTianTongShortMessageCmd(cmd);
break;
case uint8_t(CommandType::kUhfShortMessage):
processUhfShortMessageCmd(cmd);
break;
case uint8_t(CommandType::kBeiDouShortMessage):
processBeiDouShortMessageCmd(cmd);
break;
case uint8_t(CommandType::kStatusReport):
processStatusReportCmd(cmd);
break;
case uint8_t(CommandType::kSearchSatelliteStatusReport):
processSearchSatelliteStatusReport(cmd);
break;
case uint8_t(CommandType::kSearchZhuanTaiStatusReport):
processZhuanTaiStatusReportCmd(cmd);
break;
case uint8_t(CommandType::kConfigCmdDefaultChannel):
case uint8_t(CommandType::kConfigCmdUDataChannelKeepTime):
case uint8_t(CommandType::kConfigCmdDefaultNumber):
case uint8_t(CommandType::kConfigCmdSoftVersion):
processConfigCmd(cmd);
m_configParamWidget->processConfigCmd(cmd);
break;
case uint8_t(CommandType::kDebugCmd):
processDebugCmd(cmd);
break;
}
}
void MainWindow::processTianTongVoiceCmd(const QByteArray& cmd){
switch(uint8_t(cmd[SUB_COMMAND_TYPE_INDEX])){
case uint8_t(TianTongVoiceSubCommandType::kDial):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//拨号成功
//this->m_logger->info("天通拨号成功, 号码为: {}",ui->cmbCallNumber->currentText().toStdString());
this->m_logger->info("Tiantong: dial was successful, number : {}",ui->cmbCallNumber->currentText().toStdString());
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//拨号失败
//this->m_logger->info("天通拨号失败, 号码为: {}",ui->cmbCallNumber->currentText().toStdString());
this->m_logger->info("The Tiantong: dial was failed, number : {}",ui->cmbCallNumber->currentText().toStdString());
}
break;
case uint8_t(TianTongVoiceSubCommandType::kHangUp):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//挂机成功
//this->m_logger->info("天通挂机成功, 号码为: {}",ui->cmbCallNumber->currentText().toStdString());
this->m_logger->info("Tiantong: hang up was successful, number : {}",ui->cmbCallNumber->currentText().toStdString());
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//挂机失败
//this->m_logger->info("天通挂机失败, 号码为: {}",ui->cmbCallNumber->currentText().toStdString());
this->m_logger->info("The Tiantong: hang up was failed, number : {}",ui->cmbCallNumber->currentText().toStdString());
}
break;
case uint8_t(TianTongVoiceSubCommandType::kAnswer):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//接听成功
//this->m_logger->info("天通接听成功, 号码为: {}",ui->cmbCallNumber->currentText().toStdString());
this->m_logger->info("Tiantong: answer was successful, number : {}",ui->cmbCallNumber->currentText().toStdString());
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//接听失败
//this->m_logger->info("天通接听失败, 号码为: {}",ui->cmbCallNumber->currentText().toStdString());
this->m_logger->info("The Tiantong: answer was failed, number : {}",ui->cmbCallNumber->currentText().toStdString());
}
break;
case uint8_t(TianTongVoiceSubCommandType::kSendKeysWhenOnLine):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//通话中发送按键成功
//this->m_logger->info("天通按键发送成功");
this->m_logger->info("Tiantong: senting keys was successful");
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//通话中发送按键失败
//this->m_logger->info("天通按键发送失败");
this->m_logger->info("The Tiantong: sending keys was successful");
}
break;
}
}
void MainWindow::processUhfVoiceCmd(const QByteArray& cmd){
switch(uint8_t(cmd[SUB_COMMAND_TYPE_INDEX])){
case uint8_t(UhfVoiceSubCommandType::kDial):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//拨号成功
//this->m_logger->info("UHF拨号成功, 号码为: {}",ui->cmbCallNumber->currentText().toStdString());
this->m_logger->info("UHF: dial was successful, number : {}",ui->cmbCallNumber->currentText().toStdString());
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//拨号失败
//this->m_logger->info("UHF拨号失败, 号码为: {}",ui->cmbCallNumber->currentText().toStdString());
this->m_logger->info("UHF: dial was failed, number : {}",ui->cmbCallNumber->currentText().toStdString());
}
break;
case uint8_t(UhfVoiceSubCommandType::kHangUp):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//挂机成功
//this->m_logger->info("UHF挂机成功, 号码为: {}",ui->cmbCallNumber->currentText().toStdString());
this->m_logger->info("UHF: hang up was successful, number : {}",ui->cmbCallNumber->currentText().toStdString());
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//挂机失败
//this->m_logger->info("UHF挂机失败, 号码为: {}",ui->cmbCallNumber->currentText().toStdString());
this->m_logger->info("UHF: hang up was failed, number : {}",ui->cmbCallNumber->currentText().toStdString());
}
break;
case uint8_t(UhfVoiceSubCommandType::kAnswer):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//通话中发送按键成功
//this->m_logger->info("UHF接听成功, 号码为: {}",ui->cmbCallNumber->currentText().toStdString());
this->m_logger->info("UHF: answer was successful, number : {}",ui->cmbCallNumber->currentText().toStdString());
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//通话中发送按键失败
//this->m_logger->info("UHF接听失败, 号码为: {}",ui->cmbCallNumber->currentText().toStdString());
this->m_logger->info("UHF: answer was failed, number : {}",ui->cmbCallNumber->currentText().toStdString());
}
break;
}
}
std::pair<QString,QString> MainWindow::parseReceivedShortMessage(const QByteArray& cmd,Channel chan){
char buffer[21];
memset(buffer,0,21);
memcpy(buffer,cmd.data()+COMMAND_DATA_BEGIN_INDEX,20);
QString number = QString::fromStdString(std::string(buffer));
const char16_t * s = (char16_t*)(cmd.constData() + COMMAND_DATA_BEGIN_INDEX + 20);
size_t len = (cmd.size() - (FRAME_MIN_LEN + 20))/2;
QString message = QString::fromUtf16(s,len);
Record r;
r.beginTime = QDateTime::currentDateTime();
r.channel = chan;
r.type = CommType::ShortMessage;
r.direction = CommDirection::Receive;
r.number = number;
r.content = message;
r.isUnread = true;
r.callDuration = 0;
m_msgList.push_back(r);
UpdateMessageList();
m_recordQueryWidget->InsertRecord(m_msgList.back());
return std::make_pair(number,message);
}
void MainWindow::processTianTongShortMessageCmd(const QByteArray& cmd){
switch(uint8_t(cmd[SUB_COMMAND_TYPE_INDEX])){
case uint8_t(ShortMessageSubCommandType::kSendMessage):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//短消息发送成功
//this->m_logger->info("天通短消息发送成功, 号码为: {}",ui->cmbMessageNumberForUhfAndS->currentText().toStdString());
this->m_logger->info("Tiantong: the message was sent successfully, number: {}",ui->cmbMessageNumberForUhfAndS->currentText().toStdString());
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//短消息发送失败
//this->m_logger->info("天通短消息发送失败, 号码为: {}",ui->cmbMessageNumberForUhfAndS->currentText().toStdString());
this->m_logger->info("Tiantong: short message sending failed, number: {}",ui->cmbMessageNumberForUhfAndS->currentText().toStdString());
}
break;
case uint8_t(ShortMessageSubCommandType::kRecvMessage):
//接收到短消息
if(cmd.size() <= FRAME_MIN_LEN + 20){
this->m_logger->error("接收的天通短消息长度不足, 长度 = {}",cmd.size());
this->m_logger->error("Tiantong: The length of the received short message is insufficient, len = {}",cmd.size());
return;
}
auto r = parseReceivedShortMessage(cmd,Channel::S);
//this->m_logger->info("从天通接收到短消息, 号码为: {}, 消息: {}",r.first.toStdString(),r.second.toStdString());
this->m_logger->info("Tiantong: Received a short message, number: {}, message: {}",r.first.toStdString(),r.second.toStdString());
break;
}
}
void MainWindow::processUhfShortMessageCmd(const QByteArray& cmd){
switch(uint8_t(cmd[SUB_COMMAND_TYPE_INDEX])){
case uint8_t(ShortMessageSubCommandType::kSendMessage):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//短消息发送成功
//this->m_logger->info("UHF短消息发送成功, 号码为: {}",ui->cmbMessageNumberForUhfAndS->currentText().toStdString());
this->m_logger->info("UHF: the message was sent successfully, number: {}",ui->cmbMessageNumberForUhfAndS->currentText().toStdString());
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//短消息发送失败
//this->m_logger->info("UHF短消息发送失败, 号码为: {}",ui->cmbMessageNumberForUhfAndS->currentText().toStdString());
this->m_logger->info("UHF: short message sending failed, number: {}",ui->cmbMessageNumberForUhfAndS->currentText().toStdString());
}
break;
case uint8_t(ShortMessageSubCommandType::kRecvMessage):
//接收到短消息
if(cmd.size() <= FRAME_MIN_LEN + 20){
//this->m_logger->error("接收的UHF短消息长度不足, 长度 = {}",cmd.size());
this->m_logger->error("UHF: The length of the received short message is insufficient, len = {}",cmd.size());
return;
}
auto r = parseReceivedShortMessage(cmd,Channel::Uhf);
//this->m_logger->info("从UHF接收到短消息, 号码为: {}, 消息: {}",r.first.toStdString(),r.second.toStdString());
this->m_logger->info("UHF: Received a short message, number: {}, message: {}",r.first.toStdString(),r.second.toStdString());
break;
}
}
void MainWindow::processBeiDouShortMessageCmd(const QByteArray& cmd){
switch(uint8_t(cmd[SUB_COMMAND_TYPE_INDEX])){
case uint8_t(ShortMessageSubCommandType::kSendMessage):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//短消息发送成功
//this->m_logger->info("北斗短消息发送成功, 号码为: {}",ui->cmbMessageNumberForBeiDou->currentText().toStdString());
this->m_logger->info("BeiDou: the message was sent successfully, number: {}",ui->cmbMessageNumberForBeiDou->currentText().toStdString());
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//短消息发送失败
//this->m_logger->info("北斗短消息发送失败, 号码为: {}",ui->cmbMessageNumberForBeiDou->currentText().toStdString());
this->m_logger->info("BeiDou: the message sending failed, number: {}",ui->cmbMessageNumberForBeiDou->currentText().toStdString());
}
break;
case uint8_t(ShortMessageSubCommandType::kRecvMessage):
//接收到短消息
if(cmd.size() <= FRAME_MIN_LEN + 20){
//this->m_logger->error("接收的北斗短消息长度不足, 长度 = {}",cmd.size());
this->m_logger->error("BeiDou: The length of the received short message is insufficient, len = {}",cmd.size());
return;
}
auto r = parseReceivedShortMessage(cmd,Channel::BeiDou);
//this->m_logger->info("从北斗接收到短消息, 号码为: {}, 消息: {}",r.first.toStdString(),r.second.toStdString());
this->m_logger->info("BeiDou: Received a short message, number: {}, message: {}",r.first.toStdString(),r.second.toStdString());
break;
}
}
void MainWindow::processStatusReportCmd(const QByteArray& cmd){
//QByteArray cmd = cmdinput;
if(cmd.size() != FRAME_LEN_STATUSREPORT){
//cmd.resize(FRAME_LEN_STATUSREPORT);
//m_logger->error("接收的状态包长度错误, 长度 = {}",cmd.size());
m_logger->error("The received status packet length is incorrect, len = {}",cmd.size());
//return;
}
if(uint8_t(cmd[SUB_COMMAND_TYPE_INDEX]) != 0){
return;
}
int data_index = COMMAND_DATA_BEGIN_INDEX;
//uhf状态
uint8_t uhf_module_status = cmd[data_index++];//模块状态
uint8_t uhf_network_access_status = cmd[data_index++];//入网状态
uint8_t uhf_sim_card_status = cmd[data_index++];//sim卡状态
uint8_t uhf_m_card_status = cmd[data_index++];//m卡状态
uint8_t uhf_call_status = cmd[data_index++];//通话状态
uint8_t uhf_satellite_signal_strength = cmd[data_index++];
// 使用 QByteArray 处理
QByteArray uhf_data = QByteArray::fromRawData(cmd.constData() + data_index, 20);
uhf_data.replace('\0', ""); // 移除所有空字符
// 转换为 std::string
std::string uhf_number = uhf_data.toStdString();
data_index += 20;
//天通状态
uint8_t tiantong_module_status = cmd[data_index++];//模块状态
uint8_t tiantong_network_access_status = cmd[data_index++];//入网状态
uint8_t tiantong_sim_card_status = cmd[data_index++];//sim卡状态
uint8_t tiantong_m_card_status = cmd[data_index++];//m卡状态
uint8_t tiantong_call_status = cmd[data_index++];//通话状态
uint8_t tiantong_satellite_signal_strength = cmd[data_index++];
// 使用 QByteArray 处理
QByteArray tiantong_data = QByteArray::fromRawData(cmd.constData() + data_index, 20);
tiantong_data.replace('\0', ""); // 移除所有空字符
// 转换为 std::string
std::string tiantong_number = tiantong_data.toStdString();
data_index += 20;
//北斗状态
uint8_t beidou_module_status = cmd[data_index++];//模块状态
uint8_t beidou_sim_card_status = cmd[data_index++];//sim卡状态
//位置
uint8_t beidou_pos_status = cmd[data_index++];//定位有效标志
int32_t longitude_v = qFromBigEndian<qint32>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 4;
double longitude = longitude_v / 1e6;
int32_t latitude_v = qFromBigEndian<qint32>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 4;
double latitude = latitude_v / 1e6;
int32_t altitude_v = qFromBigEndian<qint32>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 4;
double altitude = altitude_v / 10.0;
//液压缸升降高度状态
int16_t oil_level_position_v = qFromBigEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 2;
//float oil_level_position = oil_level_position_v /1000.0;//米
int16_t oil_level_position = oil_level_position_v;
//自检状态
//天线电源A电压
int16_t antenna_power_supply_a_voltage_v = qFromBigEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 2;
double antenna_power_supply_a_voltage = antenna_power_supply_a_voltage_v / 1000.0;//V
//天线电源A电流
int16_t antenna_power_supply_a_current_v = qFromBigEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 2;
double antenna_power_supply_a_current = antenna_power_supply_a_current_v / 1000.0;//A
//天线电源B电压
int16_t antenna_power_supply_b_voltage_v = qFromBigEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 2;
double antenna_power_supply_b_voltage = antenna_power_supply_b_voltage_v / 1000.0;//V
//天线电源B电流
int16_t antenna_power_supply_b_current_v = qFromBigEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 2;
double antenna_power_supply_b_current = antenna_power_supply_b_current_v / 1000.0;//A
//天线温度
int16_t antenna_temperature_v = qFromBigEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
double antenna_temperature = antenna_temperature_v/100.0;
data_index += 2;
//UHF发送锁相环频综状态
uint8_t phase_locked_loop_send = cmd[data_index++];
//UHF接收锁相环频综状态
uint8_t phase_locked_loop_recv = cmd[data_index++];
//处理模块状态
processUhfModuleStatus(uhf_module_status);
processTianTongModuleStatus(tiantong_module_status);
processBeiDouModuleStatus(beidou_module_status);
//处理入网状态
processUhfNetworkAccessStatus(uhf_network_access_status);
processTianTongNetworkAccessStatus(tiantong_network_access_status);
// 处理sim卡状态
//processUhfSimCardStatus(uhf_sim_card_status);
processTianTongSimCardStatus(tiantong_sim_card_status);
processBeiDouSimCardStatus(beidou_sim_card_status);
// 处理m卡状态
processUhfMCardStatus(uhf_m_card_status);
processTianTongMCardStatus(tiantong_m_card_status);
//处理呼叫状态
processCallStatus(tiantong_call_status,uhf_call_status,tiantong_number,uhf_number);
// 处理信号强度,信号强度范围转换
//m_uhfSignalStrength = uhf_satellite_signal_strength;
// 计算大致区间
if (uhf_satellite_signal_strength == 0) {
m_uhfSignalStrength = 0;
ui->btnUHFSignalStrength->setIcon(QIcon(":/rc/res/signal_0.png"));
} else if (uhf_satellite_signal_strength <= 63) {
m_uhfSignalStrength = 25;
ui->btnUHFSignalStrength->setIcon(QIcon(":/rc/res/signal_1.png"));
} else if (uhf_satellite_signal_strength <= 127) {
m_uhfSignalStrength = 50;
ui->btnUHFSignalStrength->setIcon(QIcon(":/rc/res/signal_2.png"));
} else if (uhf_satellite_signal_strength <= 191) {
m_uhfSignalStrength = 75;
ui->btnUHFSignalStrength->setIcon(QIcon(":/rc/res/signal_3.png"));
} else {
m_uhfSignalStrength = 100;
ui->btnUHFSignalStrength->setIcon(QIcon(":/rc/res/signal_4.png"));
}
ui->btnUHFSignalStrength->setToolTip(QString("%1").arg(uhf_satellite_signal_strength));
//m_tiantongSignalStrength = tiantong_satellite_signal_strength;
if (tiantong_satellite_signal_strength == 0) {
m_tiantongSignalStrength = 0;
ui->btnSSignalStrength->setIcon(QIcon(":/rc/res/signal_0.png"));
} else if (tiantong_satellite_signal_strength >= 1 && tiantong_satellite_signal_strength <= 3) {
m_tiantongSignalStrength = 25;
ui->btnSSignalStrength->setIcon(QIcon(":/rc/res/signal_1.png"));
} else if (tiantong_satellite_signal_strength > 3 && tiantong_satellite_signal_strength <= 6) {
m_tiantongSignalStrength = 50;
ui->btnSSignalStrength->setIcon(QIcon(":/rc/res/signal_2.png"));
} else if (tiantong_satellite_signal_strength > 6 && tiantong_satellite_signal_strength <= 9) {
m_tiantongSignalStrength = 75;
ui->btnSSignalStrength->setIcon(QIcon(":/rc/res/signal_3.png"));
} else if (tiantong_satellite_signal_strength > 10) {
m_tiantongSignalStrength = 100;
ui->btnSSignalStrength->setIcon(QIcon(":/rc/res/signal_4.png"));
}
ui->btnSSignalStrength->setToolTip(QString("%1").arg(tiantong_satellite_signal_strength));
// 处理来电号码,在processCallStatus中处理
//if(!uhf_number.empty()){
// ui->cmbCallNumber->setCurrentText(QString::fromStdString(uhf_number));
//}else{
// ui->cmbCallNumber->setCurrentText(QString::fromStdString(tiantong_number));
//}
// 处理位置
if(beidou_pos_status == 0x01)
{
ui->lblPosition->setText(QString("定位有效, 经度: %1, 纬度: %2, 高度: %3").arg(longitude, 0, 'f', 6).arg(latitude, 0, 'f', 6).arg(altitude, 0, 'f', 1));
}
else
{
ui->lblPosition->setText("定位无效");
}
// 处理液压缸升降高度状态
ui->lblHydraulicCylinderHeight->setText(QString("%1 毫米").arg(oil_level_position));
// 处理自检状态
ui->lblAntennaPowerSupply->setText(QString("电源A电压 %1 V, 电源A电流 %2 A, 电源B电压 %3 V, 电源B电流 %4 A, 温度: %5 ℃")
.arg(antenna_power_supply_a_voltage, 0, 'f', 3).arg(antenna_power_supply_a_current, 0, 'f', 3)
.arg(antenna_power_supply_b_voltage, 0, 'f', 3).arg(antenna_power_supply_b_current, 0, 'f', 3)
.arg(antenna_temperature, 0, 'f', 2));
QString s;
if(phase_locked_loop_send == uint8_t(PhaseLockedLoopStatus::kLocked) || phase_locked_loop_send == uint8_t(PhaseLockedLoopStatus::kUnlocked)){
s = QString("UHF发送锁相环频综 %1 ").arg(phase_locked_loop_send == uint8_t(PhaseLockedLoopStatus::kLocked)?"锁定":"失锁");
}else{
//m_logger->error("UHF发送锁相环频综非法值, phase_locked_loop_send = {}",phase_locked_loop_send);
m_logger->error("UHF: send phase locked loop illegal value, phase_locked_loop_send = {}",phase_locked_loop_send);
}
if(phase_locked_loop_recv == uint8_t(PhaseLockedLoopStatus::kLocked) || phase_locked_loop_recv == uint8_t(PhaseLockedLoopStatus::kUnlocked)){
s += QString("UHF接收锁相环频综 %1").arg(phase_locked_loop_recv == uint8_t(PhaseLockedLoopStatus::kLocked)?"锁定":"失锁");
}else{
//m_logger->error("UHF接收锁相环频综非法值, phase_locked_loop_recv = {}",phase_locked_loop_recv);
m_logger->error("UHF: recv phase locked loop illegal value, phase_locked_loop_recv = {}",phase_locked_loop_send);
}
ui->lblPhaseLockedLoop->setText(s);
}
void MainWindow::processSearchSatelliteStatusReport(const QByteArray& cmd){
int data_index, i;
uint8_t number_of_satellite, number_of_rds1satellite, number_of_rds2satellite;
std::vector<SatelliteStatus> all_satellite_status;
std::vector<RDSSSatelliteStatus> rdss_s1satellite_status, rdss_s2satellite_status;
QList<QString> categories, s1categories, s2categories;
QList<qreal> yValues, s1yValues, s2yValues;
QList<QPointF> azimuth_pitch_values;
switch(uint8_t(cmd[SUB_COMMAND_TYPE_INDEX]))
{
case uint8_t(SearchSatelliteStatusReportSubCommandType::kRnss):
if(cmd.size() < FRAME_MIN_LEN + 1){
//m_logger->error("接收的搜星状态包长度错误, 长度 = {}",cmd.size());
m_logger->error("The received search satellite status packet length is incorrect, len = {}",cmd.size());
return;
}
data_index = COMMAND_DATA_BEGIN_INDEX;
number_of_satellite = cmd[data_index++];//卫星数量
if(cmd.size() < (FRAME_MIN_LEN + 1 + 6* number_of_satellite)){
//m_logger->error("接收的rnss搜星状态包长度错误, 卫星个数 = {}, 长度 = {}",number_of_satellite,cmd.size());
m_logger->error("The received search rnss satellite status packet length is incorrect, satellite_num = {}, len = {}",number_of_satellite,cmd.size());
}
for(i = 0 ; i < number_of_satellite; i++){
SatelliteStatus status;
status.number = cmd[data_index++];//卫星编号
status.locate_flag = cmd[data_index++];//卫星定位标志
status.snr = cmd[data_index++];//卫星信噪比
status.azimuth = qFromBigEndian<quint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));//卫星方位角
data_index += 2;
status.pitch = cmd[data_index++];//卫星俯仰角
all_satellite_status.push_back(status);
}
// 处理卫星状态
for(i = 0 ; i < all_satellite_status.size(); i++){
//categories.push_back(QString("%1").arg(i));
//categories.push_back(QString("%1").arg(all_satellite_status[i].number));
//categories.push_back(QString("%1").arg(all_satellite_status[i].number, 2, 10, QChar('0')));//与下面等效
categories.push_back(QString::asprintf("%02d", all_satellite_status[i].number));
yValues.push_back(all_satellite_status[i].snr);
azimuth_pitch_values.push_back(QPointF(all_satellite_status[i].azimuth,all_satellite_status[i].pitch));
}
// 设置信号能量
setSignalStrengthValues(categories,yValues);
// 设置方位俯仰角
setAzimuthValues(azimuth_pitch_values);
break;
case uint8_t(SearchSatelliteStatusReportSubCommandType::kRdss):
if(cmd.size() < FRAME_MIN_LEN + 2){
//m_logger->error("接收的rdss搜星状态包长度错误, 长度 = {}",cmd.size());
m_logger->error("The received search rdss satellite status packet length is incorrect, len = {}",cmd.size());
return;
}
data_index = COMMAND_DATA_BEGIN_INDEX;
number_of_rds1satellite = cmd[data_index++];//RDSS S1波束数量
number_of_rds2satellite = cmd[data_index+3*number_of_rds1satellite];//RDSS S2波束数量
if(cmd.size() < (FRAME_MIN_LEN + 2 + 3 * (number_of_rds1satellite + number_of_rds2satellite))){
//m_logger->error("接收的rdss搜星状态包长度错误, RDSS S1波束个数 = {}, RDSS S2波束个数 = {}, 长度 = {}",number_of_rds1satellite,number_of_rds1satellite,cmd.size());
m_logger->error("The received search rdss satellite status packet length is incorrect, rds1satellite_num = {}, rds2satellite_num = {}, len = {}",number_of_rds1satellite,number_of_rds2satellite,cmd.size());
}
for(i = 0 ; i < number_of_rds1satellite; i++){
RDSSSatelliteStatus s1status;
s1status.number = cmd[data_index++]; //波束编号
s1status.snr1 = cmd[data_index++]; //波束载噪比1
s1status.snr2 = cmd[data_index++]; //波束载噪比2
rdss_s1satellite_status.push_back(s1status);
}
// 处理卫星状态
for(i = 0 ; i < rdss_s1satellite_status.size(); i++){
//s1categories.push_back(QString("%1").arg(rdss_s1satellite_status[i].number, 2, 10, QChar('0')));//与下面等效
s1categories.push_back(QString::asprintf("%02d", rdss_s1satellite_status[i].number));
s1yValues.push_back(rdss_s1satellite_status[i].snr1); //两个载噪比基本一致
}
// 设置信号能量
setRDSSSignalStrengthValues(uint8_t(RDSSType::RDSS_S1), s1categories, s1yValues);
data_index++; //S2波束锁定数量
for(i = 0 ; i < number_of_rds2satellite; i++){
RDSSSatelliteStatus s2status;
s2status.number = cmd[data_index++]; //波束编号
s2status.snr1 = cmd[data_index++]; //波束载噪比1
s2status.snr2 = cmd[data_index++]; //波束载噪比2
rdss_s2satellite_status.push_back(s2status);
}
// 处理卫星状态
for(i = 0 ; i < rdss_s2satellite_status.size(); i++){
//s2categories.push_back(QString("%1").arg(rdss_s2satellite_status[i].number, 2, 10, QChar('0')));//与下面等效
s2categories.push_back(QString::asprintf("%02d", rdss_s2satellite_status[i].number));
s2yValues.push_back(rdss_s2satellite_status[i].snr1); //两个载噪比基本一致
}
setRDSSSignalStrengthValues(uint8_t(RDSSType::RDSS_S2), s2categories, s2yValues);
break;
default:
m_logger->error("SearchSatelliteStatusReportSubCommandType is incorrect, type = 0x{:02X}", cmd[SUB_COMMAND_TYPE_INDEX] & 0xFF);
break;
}
}
void MainWindow::processZhuanTaiStatusReportCmd(const QByteArray& cmd){
if(cmd.size() != FRAME_LEN_ZHUANTAISTATUSREPORT){
//m_logger->error("接收的转台状态包长度错误, 长度 = {}",cmd.size());
m_logger->error("The received zhuantai status packet length is incorrect, len = {}",cmd.size());
return;
}
int data_index = COMMAND_DATA_BEGIN_INDEX;
//通信状态
uint8_t commu_state = cmd[data_index++];
//定位状态
uint8_t locate_state = cmd[data_index++];
//避免出现符号扩展问题,使用如下方式,不能使用 ((uint16_t)cmd[data_index] << 8) | cmd[data_index+1];
uint16_t az_angle = qFromBigEndian<quint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 2;
//避免出现符号扩展问题
uint16_t el_angle = qFromBigEndian<quint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 2;
QString s;
if(commu_state == uint8_t(PhaseLockedLoopStatus::kLocked) || commu_state == uint8_t(PhaseLockedLoopStatus::kUnlocked)){
s = QString("通信状态: %1, ").arg(commu_state == uint8_t(PhaseLockedLoopStatus::kLocked)?"正常":"异常");
}else{
s = QString("通信状态: 未知 ");
}
if(commu_state == uint8_t(PhaseLockedLoopStatus::kLocked))
{
if(locate_state == uint8_t(PhaseLockedLoopStatus::kLocked) || locate_state == uint8_t(PhaseLockedLoopStatus::kUnlocked)){
s += QString("定位状态: %1, ").arg(locate_state == uint8_t(PhaseLockedLoopStatus::kLocked)?"锁定":"未锁定");
}else{
s += QString("定位状态: 未知, ");
}
s += QString("方位角: %1, ").arg((double)az_angle/100, 0, 'f', 2);
s += QString("俯仰角: %1 ").arg((double)el_angle/100, 0, 'f', 2);
}
ui->lblZhuanTaiStatus->setText(s);
}
void MainWindow::processConfigCmd(const QByteArray& cmd){
switch(uint8_t(cmd[COMMAND_TYPE_INDEX])){
case uint8_t(CommandType::kConfigCmdDefaultChannel):
if(cmd[SUB_COMMAND_TYPE_INDEX] == uint8_t(ConfigCommandType::kGetType))
{
int data_index = COMMAND_DATA_BEGIN_INDEX;
uint8_t channelType = cmd[data_index++];//信道类型
switch(channelType)
{
case uint8_t(ChannelType::ChannelS):
ui->rdbChannelS->setChecked(true);
break;
case uint8_t(ChannelType::ChannelUHF):
ui->rdbChannelUHF->setChecked(true);
break;
case uint8_t(ChannelType::ChannelAuto):
ui->rdbChannelAuto->setChecked(true);
break;
}
m_channelQuery = true;
}
else if(cmd[SUB_COMMAND_TYPE_INDEX] == uint8_t(ConfigCommandType::kSetType))
{
if(cmd[COMMAND_DATA_BEGIN_INDEX] == uint8_t(VoiceAndShortMessageReponse::kSucess)){//设置成功
QMessageBox::information(this, "提示", "默认信道设置成功");
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == uint8_t(VoiceAndShortMessageReponse::kFailure)){//设置失败
QMessageBox::information(this, "提示", "默认信道设置失败");
}
sendUdpMessage(pack_config_cmd_DefaultChannelGet()); //查询一次
}
break;
case uint8_t(CommandType::kConfigCmdSoftVersion):
if(cmd[SUB_COMMAND_TYPE_INDEX] == uint8_t(ConfigCommandType::kGetType))
{
int data_index = COMMAND_DATA_BEGIN_INDEX;
// U号码,使用 QByteArray 处理
QByteArray softversion_data = QByteArray::fromRawData(cmd.constData() + data_index, 32);
softversion_data.replace('\0', ""); // 移除所有空字符
// 转换为 std::string
std::string softversion = softversion_data.toStdString();
ui->lblSoftVersion->setText(QString::fromStdString(softversion));
m_versionQuery = true;
}
break;
case uint8_t(CommandType::kConfigCmdSoftReset):
if(cmd[SUB_COMMAND_TYPE_INDEX] == uint8_t(ConfigCommandType::kSetType))
{
if(cmd[COMMAND_DATA_BEGIN_INDEX] == uint8_t(VoiceAndShortMessageReponse::kSucess)){//设置成功
QMessageBox::information(this, "提示", "软件复位成功");
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == uint8_t(VoiceAndShortMessageReponse::kFailure)){//设置失败
QMessageBox::information(this, "提示", "软件复位失败");
}
}
break;
case uint8_t(CommandType::kConfigCmdSDataSwitch):
if(cmd[SUB_COMMAND_TYPE_INDEX] == uint8_t(ConfigCommandType::kSetType))
{
if(cmd[COMMAND_DATA_BEGIN_INDEX] == uint8_t(VoiceAndShortMessageReponse::kSucess)){//设置成功
QMessageBox::information(this, "提示", "S数据开关设置成功");
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == uint8_t(VoiceAndShortMessageReponse::kFailure)){//设置失败
QMessageBox::information(this, "提示", "S数据开关设置失败");
}
}
break;
default:
break;
}
}
void MainWindow::processDebugCmd(const QByteArray& cmd){
switch(uint8_t(cmd[SUB_COMMAND_TYPE_INDEX])){
case uint8_t(DebugCommandType::kUCattierType):
case uint8_t(DebugCommandType::kURate):
case uint8_t(DebugCommandType::kSFreq):
case uint8_t(DebugCommandType::kSRate):
case uint8_t(DebugCommandType::kPASwitch):
case uint8_t(DebugCommandType::kZTCtrl):
if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kSucess)){//设置成功
//this->m_logger->info("设置成功");
m_loggerWidget->updateRespStatus("设置成功");
}else if(cmd[COMMAND_DATA_BEGIN_INDEX] == int(VoiceAndShortMessageReponse::kFailure)){//设置失败
//this->m_logger->info("设置失败");
m_loggerWidget->updateRespStatus("设置失败");
}
break;
case uint8_t(DebugCommandType::kCmdCtrl):
int data_index = COMMAND_DATA_BEGIN_INDEX;
std::string resp = std::string((cmd.data()+data_index), (cmd.length() - 5)); //去除信息长度2/命令1/命令子类型1/校验1
m_loggerWidget->updateRespStatus(resp.c_str());
break;
}
}
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
// 处理模块状态
void MainWindow::processUhfModuleStatus(uint8_t status){
if(status != uint8_t(ModuleStatus::kChecking) && status != uint8_t(ModuleStatus::kNormal)
&& status != uint8_t(ModuleStatus::kFault) && status != uint8_t(ModuleStatus::kUpgrading)){
//m_logger->error("UHF模块状态非法值, status = {}",status);
m_logger->error("UHF: module status illegal value, status = {}",status);
return;
}
m_uhfModuleStatus = ModuleStatus(status);
switch(m_uhfModuleStatus){
case ModuleStatus::kChecking:
ui->btnUHFModuleStatus->setToolTip("检测中");
break;
case ModuleStatus::kNormal:
ui->btnUHFModuleStatus->setIcon(QIcon(":/rc/res/module_ok.png"));
ui->btnUHFModuleStatus->setToolTip("正常");
break;
case ModuleStatus::kFault:
ui->btnUHFModuleStatus->setIcon(QIcon(":/rc/res/module_error.png"));
ui->btnUHFModuleStatus->setToolTip("故障");
break;
case ModuleStatus::kUpgrading:
ui->btnUHFModuleStatus->setIcon(QIcon(":/rc/res/module_update.png"));
ui->btnUHFModuleStatus->setToolTip("升级中");
break;
}
}
void MainWindow::processTianTongModuleStatus(uint8_t status){
if(status != uint8_t(ModuleStatus::kChecking) && status != uint8_t(ModuleStatus::kNormal)
&& status != uint8_t(ModuleStatus::kFault) && status != uint8_t(ModuleStatus::kUpgrading)){
//m_logger->error("天通模块状态非法值, status = {}",status);
m_logger->error("Tiantong: module status illegal value, status = {}",status);
return;
}
m_tiantongModuleStatus = ModuleStatus(status);
switch(m_tiantongModuleStatus){
case ModuleStatus::kChecking:
ui->btnSModueStatus->setToolTip("检测中");
break;
case ModuleStatus::kNormal:
ui->btnSModueStatus->setIcon(QIcon(":/rc/res/module_ok.png"));
ui->btnSModueStatus->setToolTip("正常");
break;
case ModuleStatus::kFault:
ui->btnSModueStatus->setIcon(QIcon(":/rc/res/module_error.png"));
ui->btnSModueStatus->setToolTip("故障");
break;
case ModuleStatus::kUpgrading:
ui->btnSModueStatus->setIcon(QIcon(":/rc/res/module_update.png"));
ui->btnSModueStatus->setToolTip("升级中");
break;
}
}
void MainWindow::processBeiDouModuleStatus(uint8_t status){
if(status != uint8_t(ModuleStatus::kChecking) && status != uint8_t(ModuleStatus::kNormal)
&& status != uint8_t(ModuleStatus::kFault) && status != uint8_t(ModuleStatus::kUpgrading)){
//m_logger->error("北斗模块状态非法值, status = {}",status);
m_logger->error("BeiDou: module status status illegal value, status = {}",status);
return;
}
m_beidouModuleStatus = ModuleStatus(status);
switch(m_beidouModuleStatus){
case ModuleStatus::kChecking:
ui->btnBeiDouModuleStatus->setToolTip("检测中");
break;
case ModuleStatus::kNormal:
ui->btnBeiDouModuleStatus->setIcon(QIcon(":/rc/res/module_ok.png"));
ui->btnBeiDouModuleStatus->setToolTip("正常");
break;
case ModuleStatus::kFault:
ui->btnBeiDouModuleStatus->setIcon(QIcon(":/rc/res/module_error.png"));
ui->btnBeiDouModuleStatus->setToolTip("故障");
break;
case ModuleStatus::kUpgrading:
ui->btnBeiDouModuleStatus->setIcon(QIcon(":/rc/res/module_update.png"));
ui->btnBeiDouModuleStatus->setToolTip("升级中");
break;
}
}
// 处理SIM卡状态
void MainWindow::processUhfSimCardStatus(uint8_t status){
if(status != uint8_t(SimCardStatus::kChecking) && status != uint8_t(SimCardStatus::kExist)
&& status != uint8_t(SimCardStatus::kNotExist)){
//m_logger->error("UHF SIM卡状态非法值, status = {}",status);
m_logger->error("UHF: sim card status illegal value, status = {}",status);
return;
}
m_uhfSimCardStatus = SimCardStatus(status);
switch(m_uhfSimCardStatus){
case SimCardStatus::kChecking:
ui->btnUHFSimCardStatus->setToolTip("正在检测");
break;
case SimCardStatus::kExist:
ui->btnUHFSimCardStatus->setIcon(QIcon(":/rc/res/sim_card_exist.png"));
ui->btnUHFSimCardStatus->setToolTip("存在");
break;
case SimCardStatus::kNotExist:
ui->btnUHFSimCardStatus->setIcon(QIcon(":/rc/res/sim_card_not_exist.png"));
ui->btnUHFSimCardStatus->setToolTip("不存在");
break;
}
}
void MainWindow::processTianTongSimCardStatus(uint8_t status){
if(status != uint8_t(SimCardStatus::kChecking) && status != uint8_t(SimCardStatus::kExist)
&& status != uint8_t(SimCardStatus::kNotExist)){
//m_logger->error("TianTong SIM卡状态非法值, status = {}",status);
m_logger->error("Tiantong: sim card status illegal value, status = {}",status);
return;
}
m_tiantongSimCardStatus = SimCardStatus(status);
switch(m_tiantongSimCardStatus){
case SimCardStatus::kChecking:
ui->btnSSimCardStatus->setToolTip("正在检测");
break;
case SimCardStatus::kExist:
ui->btnSSimCardStatus->setIcon(QIcon(":/rc/res/sim_card_exist.png"));
ui->btnSSimCardStatus->setToolTip("存在");
break;
case SimCardStatus::kNotExist:
ui->btnSSimCardStatus->setIcon(QIcon(":/rc/res/sim_card_not_exist.png"));
ui->btnSSimCardStatus->setToolTip("不存在");
break;
}
}
void MainWindow::processBeiDouSimCardStatus(uint8_t status){
if(status != uint8_t(SimCardStatus::kChecking) && status != uint8_t(SimCardStatus::kExist)
&& status != uint8_t(SimCardStatus::kNotExist)){
//m_logger->error("北斗 SIM卡状态非法值, status = {}",status);
m_logger->error("BeiDou: sim card status illegal value, status = {}",status);
return;
}
m_beidouSimCardStatus = SimCardStatus(status);
switch(m_beidouSimCardStatus){
case SimCardStatus::kChecking:
ui->btnBeiDouSimCardStatus->setToolTip("正在检测");
break;
case SimCardStatus::kExist:
ui->btnBeiDouSimCardStatus->setIcon(QIcon(":/rc/res/sim_card_exist.png"));
ui->btnBeiDouSimCardStatus->setToolTip("存在");
break;
case SimCardStatus::kNotExist:
ui->btnBeiDouSimCardStatus->setIcon(QIcon(":/rc/res/sim_card_not_exist.png"));
ui->btnBeiDouSimCardStatus->setToolTip("不存在");
break;
}
}
// 处理M卡状态
void MainWindow::processUhfMCardStatus(uint8_t status){
if(status != uint8_t(MCardStatus::kChecking) && status != uint8_t(MCardStatus::kExistNotEncryted)
&& status != uint8_t(MCardStatus::kExistEncryted)&& status != uint8_t(MCardStatus::kNotExist)){
//m_logger->error("UHF M卡状态非法值, status = {}",status);
m_logger->error("UHF: m card status illegal value, status = {}",status);
return;
}
m_uhfMCardStatus = MCardStatus(status);
switch(m_uhfMCardStatus){
case MCardStatus::kChecking:
ui->btnUHFMCardStatus->setToolTip("正在检测");
break;
case MCardStatus::kExistNotEncryted:
ui->btnUHFMCardStatus->setIcon(QIcon(":/rc/res/m_card_no_stick.png"));
ui->btnUHFMCardStatus->setToolTip("存在未注密");
break;
case MCardStatus::kExistEncryted:
ui->btnUHFMCardStatus->setIcon(QIcon(":/rc/res/m_card_stick.png"));
ui->btnUHFMCardStatus->setToolTip("存在已注密");
break;
case MCardStatus::kNotExist:
ui->btnUHFMCardStatus->setIcon(QIcon(":/rc/res/m_card_not_exist.png"));
ui->btnUHFMCardStatus->setToolTip("不存在");
break;
}
}
void MainWindow::processTianTongMCardStatus(uint8_t status){
if(status != uint8_t(MCardStatus::kChecking) && status != uint8_t(MCardStatus::kExistNotEncryted)
&& status != uint8_t(MCardStatus::kExistEncryted)&& status != uint8_t(MCardStatus::kNotExist)){
//m_logger->error("天通M卡状态非法值, status = {}",status);
m_logger->error("Tiantong: m card status illegal value, status = {}",status);
return;
}
m_tiantongMCardStatus = MCardStatus(status);
switch(m_tiantongMCardStatus){
case MCardStatus::kChecking:
ui->btnSMCardStatus->setToolTip("正在检测");
break;
case MCardStatus::kExistNotEncryted:
ui->btnSMCardStatus->setIcon(QIcon(":/rc/res/m_card_no_stick.png"));
ui->btnSMCardStatus->setToolTip("存在未注密");
break;
case MCardStatus::kExistEncryted:
ui->btnSMCardStatus->setIcon(QIcon(":/rc/res/m_card_stick.png"));
ui->btnSMCardStatus->setToolTip("存在已注密");
break;
case MCardStatus::kNotExist:
ui->btnSMCardStatus->setIcon(QIcon(":/rc/res/m_card_not_exist.png"));
ui->btnSMCardStatus->setToolTip("不存在");
break;
}
}
// 处理网络访问状态
void MainWindow::processUhfNetworkAccessStatus(uint8_t status){
if(status != uint8_t(NetworkAccessStatus::kNotConnected)
&& status != uint8_t(NetworkAccessStatus::kConnecting)
&& status != uint8_t(NetworkAccessStatus::kConnectedDataIsNotActivated)
&& status != uint8_t(NetworkAccessStatus::kConnectedDataIsActivated)){
//m_logger->error("uhf 入网状态非法值, status = {}",status);
m_logger->error("UHF: network access status illegal value, status = {}",status);
}
m_uhfNetworkAccessStatus = NetworkAccessStatus(status);
switch(m_uhfNetworkAccessStatus){
case NetworkAccessStatus::kNotConnected:
ui->btnUHFNetworkAccessStatus->setIcon(QIcon(":/rc/res/net_out.png"));
ui->btnUHFNetworkAccessStatus->setToolTip("未入网");
break;
case NetworkAccessStatus::kConnecting:
ui->btnUHFNetworkAccessStatus->setToolTip("正在入网");
break;
case NetworkAccessStatus::kConnectedDataIsNotActivated:
ui->btnUHFNetworkAccessStatus->setIcon(QIcon(":/rc/res/net_in_no_data.png"));
ui->btnUHFNetworkAccessStatus->setToolTip("已入网, 数据未激活");
break;
case NetworkAccessStatus::kConnectedDataIsActivated:
ui->btnUHFNetworkAccessStatus->setIcon(QIcon(":/rc/res/net_in_data.png"));
ui->btnUHFNetworkAccessStatus->setToolTip("已入网, 数据已激活");
break;
}
}
void MainWindow::processTianTongNetworkAccessStatus(uint8_t status){
if(status == uint8_t(NetworkAccessStatus::kNotConnected)
&& status == uint8_t(NetworkAccessStatus::kConnecting)
&& status == uint8_t(NetworkAccessStatus::kConnectedDataIsNotActivated)
&& status == uint8_t(NetworkAccessStatus::kConnectedDataIsActivated)){
//m_logger->error("天通入网状态非法值, status = {}",status);
m_logger->error("Tiantong: network access status illegal value, status = {}",status);
}
m_tiantongNetworkAccessStatus = NetworkAccessStatus(status);
switch(m_tiantongNetworkAccessStatus){
case NetworkAccessStatus::kNotConnected:
ui->btnSNetworkAccessStatus->setIcon(QIcon(":/rc/res/net_out.png"));
ui->btnSNetworkAccessStatus->setToolTip("未入网");
break;
case NetworkAccessStatus::kConnecting:
// ui->btnSNetworkAccessStatus->setIcon(QIcon(":/rc/res/net_out.png"));
ui->btnSNetworkAccessStatus->setToolTip("正在入网");
break;
case NetworkAccessStatus::kConnectedDataIsNotActivated:
ui->btnSNetworkAccessStatus->setIcon(QIcon(":/rc/res/net_in_no_data.png"));
ui->btnSNetworkAccessStatus->setToolTip("已入网, 数据未激活");
break;
case NetworkAccessStatus::kConnectedDataIsActivated:
ui->btnSNetworkAccessStatus->setIcon(QIcon(":/rc/res/net_in_data.png"));
ui->btnSNetworkAccessStatus->setToolTip("已入网, 数据已激活");
break;
}
}
// 处理呼叫状态
void MainWindow::processCallStatus(uint8_t tiantong_call_status,uint8_t uhf_call_status,const std::string& tiantong_number,const std::string& uhf_number){
if(tiantong_call_status != uint8_t(CallStatus::kIdle) && tiantong_call_status != uint8_t(CallStatus::kDialing)
&& tiantong_call_status != uint8_t(CallStatus::kPeerRingTheBell) && tiantong_call_status != uint8_t(CallStatus::kOnLine)
&& tiantong_call_status != uint8_t(CallStatus::kCallIsComing)){
return;
}
if(uhf_call_status != uint8_t(CallStatus::kIdle) && uhf_call_status != uint8_t(CallStatus::kDialing)
&& uhf_call_status != uint8_t(CallStatus::kPeerRingTheBell) && uhf_call_status != uint8_t(CallStatus::kOnLine)
&& uhf_call_status != uint8_t(CallStatus::kCallIsComing)){
return;
}
m_tiantongCallStatus = CallStatus(tiantong_call_status);
m_uhfCallStatus = CallStatus(uhf_call_status);
CallStatus status;
static uint8_t lastStatus = 0xFF;
Channel chan;
if(m_tiantongCallStatus != CallStatus::kIdle){
status = m_tiantongCallStatus;
chan = Channel::S;
}else{
status = m_uhfCallStatus;
chan = Channel::Uhf;
}
switch(status){
case CallStatus::kIdle://空闲
//挂断电话
ui->cmbCallNumber->setEnabled(true);
ui->btnCallAnswer->show();
ui->btnCallReject->hide();
ui->lblCallStatus->setText("空闲");
ui->lblCallStatus->setStyleSheet("color: black;");
m_callStatusLabelBlack = true;
ShutdownTalking();
ui->lblCallDuration->hide();
ui->lblCallDuration->setText(""); //清空
break;
case CallStatus::kDialing://拨号中
//拨号中
ui->cmbCallNumber->setEnabled(false);
ui->btnCallAnswer->hide();
ui->btnCallReject->show();
ui->lblCallStatus->setText("拨号中...");
ui->lblCallDuration->hide();
ui->lblCallDuration->setText(""); //清空
break;
case CallStatus::kPeerRingTheBell://对方振铃
//对方振铃中
ui->cmbCallNumber->setEnabled(false);
ui->btnCallAnswer->hide();
ui->btnCallReject->show();
ui->lblCallStatus->setText("对方振铃...");
ui->lblCallDuration->hide();
ui->lblCallDuration->setText(""); //清空
break;
case CallStatus::kOnLine://通话中
if(lastStatus == (uint8_t)CallStatus::kIdle)//避免从'空闲'直接变成'通话中'
{
m_logger->error("CallStatus is Err, lastStatus = {}, currentStatus = {}", lastStatus, (uint8_t)status);
return;
}
//通话中
if(chan == Channel::S){
m_currentTalkingNumber = tiantong_number;
ui->cmbCallNumber->setCurrentText(QString::fromStdString(tiantong_number));
}else{
m_currentTalkingNumber = uhf_number;
ui->cmbCallNumber->setCurrentText(QString::fromStdString(uhf_number));
}
m_currentTalkingChan = chan;
ui->cmbCallNumber->setEnabled(false);
ui->btnCallAnswer->hide();
ui->btnCallReject->show();
ui->lblCallStatus->setText("通话中...");
ui->lblCallStatus->setStyleSheet("color: green;");
m_callStatusLabelBlack = false;
StartupTalking();
break;
case CallStatus::kCallIsComing://来电中
//有来电
ui->cmbCallNumber->setEnabled(false);
if(chan == Channel::S){
m_currentTalkingNumber = tiantong_number;
ui->cmbCallNumber->setCurrentText(QString::fromStdString(tiantong_number));
}else{
m_currentTalkingNumber = uhf_number;
ui->cmbCallNumber->setCurrentText(QString::fromStdString(uhf_number));
}
m_currentTalkingDirection = CommDirection::Receive;
ui->btnCallAnswer->show();
ui->btnCallReject->show();
ui->lblCallStatus->setText("来电中...");
ui->lblCallDuration->hide();
ui->lblCallDuration->setText(""); //清空
break;
}
lastStatus = (uint8_t)status;
}
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
void MainWindow::on_btnConfigParam_clicked()
{
m_configParamWidget->show();
}
void MainWindow::on_rdbChannelS_clicked()
{
sendUdpMessage(pack_config_cmd_DefaultChannelSet(uint8_t(ChannelType::ChannelS)));
}
void MainWindow::on_rdbChannelUHF_clicked()
{
sendUdpMessage(pack_config_cmd_DefaultChannelSet(uint8_t(ChannelType::ChannelUHF)));
}
void MainWindow::on_rdbChannelAuto_clicked()
{
sendUdpMessage(pack_config_cmd_DefaultChannelSet(uint8_t(ChannelType::ChannelAuto)));
}
void MainWindow::on_sDataSwitch_checkStateChanged(const Qt::CheckState &arg1)
{
uint8_t onoff = 0;
if(arg1 == Qt::CheckState::Checked)
{
onoff = 1;
}
sendUdpMessage(pack_config_cmd_SDataSwitchSet(onoff));
}
void MainWindow::on_btnSoftReset_clicked()
{
// 1. 弹出确认对话框(按钮显示中文“确定/取消”)
QMessageBox msgBox(this);
msgBox.setWindowTitle("确认操作");
msgBox.setText("您确定要软件复位吗?");
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
// 通过 button() 获取按钮指针再 setText不使用 setButtonText
msgBox.button(QMessageBox::Yes)->setText("确定");
msgBox.button(QMessageBox::No)->setText("取消");
if (msgBox.exec() != QMessageBox::Yes) {
return;
}
sendUdpMessage(pack_config_cmd_SoftResetSet());
}