1、修正SLIP帧解析

2、增加定位有效标志
3、其他
This commit is contained in:
lz
2025-09-01 14:17:12 +08:00
parent 1d5c55ae6a
commit ee2aef296d
6 changed files with 185 additions and 56 deletions

View File

@@ -1,4 +1,4 @@
[Config]
PeerIP = "127.0.0.1"
LocalPort = 8000
PeerPort = 8080
PeerIP = "192.168.2.10"
LocalPort = 6680
PeerPort = 6678

View File

@@ -1,4 +1,4 @@
[Config]
PeerIP = "127.0.0.1"
LocalPort = 8000
PeerPort = 8080
PeerIP = "192.168.2.10"
LocalPort = 6680
PeerPort = 6678

View File

@@ -66,9 +66,9 @@ MainWindow::MainWindow(QWidget *parent)
QString exeDir = QCoreApplication::applicationDirPath();
QSettings settings(exeDir + "/app.ini", QSettings::IniFormat);
m_udpIp = settings.value("Config/PeerIP","127.0.0.1").toString();
m_localPort = settings.value("Config/LocalPort",8000).toInt();
m_peerPort = settings.value("Config/PeerPort",8080).toInt();
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>();
@@ -772,10 +772,16 @@ bool MainWindow::sendUdpMessage(const QByteArray &udpMessage) {
//--------------------------------------------------------------------------------------
// 处理命令
//--------------------------------------------------------------------------------------
void MainWindow::processCommand(const QByteArray& cmd){
void MainWindow::processCommand(QByteArray& cmd){
if(cmd.size() < 5){
return;
}
if(pack_deslip(cmd) < 0)
{
return;
}
switch(uint8_t(cmd[COMMAND_TYPE_INDEX])){
case uint8_t(CommandType::kTianTongVoice):
processTianTongVoiceCmd(cmd);
@@ -971,10 +977,12 @@ void MainWindow::processBeiDouShortMessageCmd(const QByteArray& cmd){
}
}
void MainWindow::processStatusReportCmd(const QByteArray& cmd){
if(cmd.size() != FRAME_MIN_LEN + 26 + 26 + 2 + 26){
//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;
//return;
}
if(uint8_t(cmd[SUB_COMMAND_TYPE_INDEX]) != 0){
return;
@@ -1003,39 +1011,41 @@ void MainWindow::processStatusReportCmd(const QByteArray& cmd){
uint8_t beidou_module_status = cmd[data_index++];//模块状态
uint8_t beidou_sim_card_status = cmd[data_index++];//sim卡状态
//位置
int32_t longitude_v = qFromLittleEndian<qint32>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
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;
float longitude = longitude_v / 1e6;
int32_t latitude_v = qFromLittleEndian<qint32>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
double longitude = longitude_v / 1e6;
int32_t latitude_v = qFromBigEndian<qint32>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 4;
float latitude = latitude_v / 1e6;
int32_t altitude_v = qFromLittleEndian<qint32>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
double latitude = latitude_v / 1e6;
int32_t altitude_v = qFromBigEndian<qint32>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 4;
float altitude = altitude_v / 10.0;
double altitude = altitude_v / 10.0;
//液压缸升降高度状态
int16_t oil_level_position_v = qFromLittleEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
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;//米
//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 = qFromLittleEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
int16_t antenna_power_supply_a_voltage_v = qFromBigEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 2;
float antenna_power_supply_a_voltage = antenna_power_supply_a_voltage_v / 1000.0;//V
double antenna_power_supply_a_voltage = antenna_power_supply_a_voltage_v / 1000.0;//V
//天线电源A电流
int16_t antenna_power_supply_a_current_v = qFromLittleEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
int16_t antenna_power_supply_a_current_v = qFromBigEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 2;
float antenna_power_supply_a_current = antenna_power_supply_a_current_v / 1000.0;//A
double antenna_power_supply_a_current = antenna_power_supply_a_current_v / 1000.0;//A
//天线电源B电压
int16_t antenna_power_supply_b_voltage_v = qFromLittleEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
int16_t antenna_power_supply_b_voltage_v = qFromBigEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 2;
float antenna_power_supply_b_voltage = antenna_power_supply_b_voltage_v / 1000.0;//V
double antenna_power_supply_b_voltage = antenna_power_supply_b_voltage_v / 1000.0;//V
//天线电源B电流
int16_t antenna_power_supply_b_current_v = qFromLittleEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
int16_t antenna_power_supply_b_current_v = qFromBigEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
data_index += 2;
float antenna_power_supply_b_current = antenna_power_supply_b_current_v / 1000.0;//A
double antenna_power_supply_b_current = antenna_power_supply_b_current_v / 1000.0;//A
//天线温度
int16_t antenna_temperature_v = qFromLittleEndian<qint16>(reinterpret_cast<const uchar*>(cmd.constData()+data_index));
float antenna_temperature = antenna_temperature_v/100.0;
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++];
@@ -1063,30 +1073,37 @@ void MainWindow::processStatusReportCmd(const QByteArray& cmd){
m_tiantongSignalStrength = tiantong_satellite_signal_strength;
ui->progressChannelUHFSignalStrength->setValue(m_uhfSignalStrength);
ui->progressChannelSSignalStrength->setValue(m_tiantongSignalStrength);
// 处理来电号码
if(!uhf_number.empty()){
ui->cmbCallNumber->setCurrentText(QString::fromStdString(uhf_number));
}else{
ui->cmbCallNumber->setCurrentText(QString::fromStdString(tiantong_number));
}
// 处理来电号码,在processCallStatus中处理
//if(!uhf_number.empty()){
// ui->cmbCallNumber->setCurrentText(QString::fromStdString(uhf_number));
//}else{
// ui->cmbCallNumber->setCurrentText(QString::fromStdString(tiantong_number));
//}
// 处理位置
ui->lblPosition->setText(QString(" 经度: %1, 纬度: %2, 高度, %3").arg(longitude).arg(latitude).arg(altitude));
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->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).arg(antenna_power_supply_a_current)
.arg(antenna_power_supply_b_voltage).arg(antenna_power_supply_b_current)
.arg(antenna_temperature));
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)?"锁定":"失锁");
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)?"锁定":"失锁");
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);
@@ -1419,7 +1436,7 @@ void MainWindow::processCallStatus(uint8_t tiantong_call_status,uint8_t uhf_call
ui->cmbCallNumber->setEnabled(true);
ui->btnCallAnswer->show();
ui->btnCallReject->hide();
ui->lblCallStatus->setText("空闲中...");
ui->lblCallStatus->setText("空闲");
ui->lblCallStatus->setStyleSheet("color: black;");
m_callStatusLabelBlack = true;
ui->lblCallDuration->hide();

View File

@@ -71,7 +71,7 @@ private:
//-------------------------------------------------
bool sendUdpMessage(const QByteArray &udpMessage);
bool sendShortMessage(const QString &number,const QString& message);
void processCommand(const QByteArray& cmd);
void processCommand(QByteArray& cmd);
void processTianTongVoiceCmd(const QByteArray& cmd);
void processUhfVoiceCmd(const QByteArray& cmd);
void processTianTongShortMessageCmd(const QByteArray& cmd);

122
msg.cpp
View File

@@ -6,7 +6,41 @@ void pack_len(QByteArray& cmd,uint16_t len){
memcpy(&cmd[0],reinterpret_cast<const char*>(&v),2);
}
void calc_checksum(QByteArray&cmd){
#if 0
// 初始化校验和
char checksum = 0;
// 检查字节数组长度
if (cmd.size() < 2) {
return;
}
// 创建临时数组(排除最后一个字节)
QByteArray tempArray = cmd.mid(0, cmd.size() - 1);
// 使用foreach遍历计算除最后一个字节之外的字节
foreach (const char byte, tempArray) {
checksum ^= byte;
}
// 将校验和存储到数组末尾
cmd[cmd.size() - 1] = checksum;
#endif
// 如果字节数组太小不足2字节无法计算校验和
if (cmd.size() < 2) {
return;
}
// 初始化校验和为0 (0x00)
char checksum = 0;
// 计算校验和(排除最后一个字节)
// 从索引0开始到倒数第二个字节 (size()-2)
for (int i = 0; i < (cmd.size() - 1); i++) {
checksum ^= cmd[i]; // 逐字节异或
}
// 将校验和存储到最后一个字节
cmd[cmd.size() - 1] = checksum;
}
QByteArray pack_tiantong_dial_cmd(const std::string& number){
assert(number.size() <= 20);
@@ -16,7 +50,7 @@ QByteArray pack_tiantong_dial_cmd(const std::string& number){
cmd[SUB_COMMAND_TYPE_INDEX] = uint8_t(TianTongVoiceSubCommandType::kDial);
memcpy(&cmd[COMMAND_DATA_BEGIN_INDEX],number.c_str(),number.size());
calc_checksum(cmd);
return cmd;
return pack_slip(cmd);
}
QByteArray pack_tiantong_hang_up_cmd(){
QByteArray cmd(FRAME_MIN_LEN, '\0');
@@ -24,7 +58,7 @@ QByteArray pack_tiantong_hang_up_cmd(){
cmd[COMMAND_TYPE_INDEX] = uint8_t(CommandType::kTianTongVoice);
cmd[SUB_COMMAND_TYPE_INDEX] = uint8_t(TianTongVoiceSubCommandType::kHangUp);
calc_checksum(cmd);
return cmd;
return pack_slip(cmd);
}
QByteArray pack_tiantong_answer(){
QByteArray cmd(FRAME_MIN_LEN, '\0');
@@ -32,7 +66,7 @@ QByteArray pack_tiantong_answer(){
cmd[COMMAND_TYPE_INDEX] = uint8_t(CommandType::kTianTongVoice);
cmd[SUB_COMMAND_TYPE_INDEX] = uint8_t(TianTongVoiceSubCommandType::kAnswer);
calc_checksum(cmd);
return cmd;
return pack_slip(cmd);
}
QByteArray pack_tiantong_send_keys_when_on_line_cmd(const std::string& keys){
assert(keys.size() <= 12);
@@ -42,7 +76,7 @@ QByteArray pack_tiantong_send_keys_when_on_line_cmd(const std::string& keys){
cmd[SUB_COMMAND_TYPE_INDEX] = uint8_t(TianTongVoiceSubCommandType::kSendKeysWhenOnLine);
memcpy(&cmd[COMMAND_DATA_BEGIN_INDEX],keys.c_str(),keys.size());
calc_checksum(cmd);
return cmd;
return pack_slip(cmd);
}
QByteArray pack_uhf_dial_cmd(const std::string& number){
@@ -53,7 +87,7 @@ QByteArray pack_uhf_dial_cmd(const std::string& number){
cmd[SUB_COMMAND_TYPE_INDEX] = uint8_t(UhfVoiceSubCommandType::kDial);
memcpy(&cmd[COMMAND_DATA_BEGIN_INDEX],number.c_str(),number.size());
calc_checksum(cmd);
return cmd;
return pack_slip(cmd);
}
QByteArray pack_uhf_hang_up_cmd(){
QByteArray cmd(FRAME_MIN_LEN, '\0');
@@ -61,7 +95,7 @@ QByteArray pack_uhf_hang_up_cmd(){
cmd[COMMAND_TYPE_INDEX] = uint8_t(CommandType::kUhfVoice);
cmd[SUB_COMMAND_TYPE_INDEX] = uint8_t(UhfVoiceSubCommandType::kHangUp);
calc_checksum(cmd);
return cmd;
return pack_slip(cmd);
}
QByteArray pack_uhf_answer(){
QByteArray cmd(FRAME_MIN_LEN, '\0');
@@ -69,7 +103,7 @@ QByteArray pack_uhf_answer(){
cmd[COMMAND_TYPE_INDEX] = uint8_t(CommandType::kUhfVoice);
cmd[SUB_COMMAND_TYPE_INDEX] = uint8_t(UhfVoiceSubCommandType::kAnswer);
calc_checksum(cmd);
return cmd;
return pack_slip(cmd);
}
QByteArray pack_short_message_cmd(CommandType cmd_type,const std::string& number, const std::u16string& message){
@@ -81,7 +115,79 @@ QByteArray pack_short_message_cmd(CommandType cmd_type,const std::string& number
memcpy(&cmd[COMMAND_DATA_BEGIN_INDEX],number.c_str(),number.size());
memcpy(&cmd[COMMAND_DATA_BEGIN_INDEX+20],message.c_str(),message.size()*sizeof(char16_t));
calc_checksum(cmd);
return cmd;
return pack_slip(cmd);
}
QByteArray pack_slip(QByteArray &message){
// 创建临时数组,最多数据内容*2+加帧头尾
QByteArray tempArray((message.size()*2 + 2), '\0');
int index = 0;
tempArray[index++] = FRAME_SLIP_C0;
for(int i = 0; i < message.size(); i++)
{
if(static_cast<uint8_t>(message[i]) == FRAME_SLIP_C0)
{
tempArray[index++] = FRAME_SLIP_DB;
tempArray[index++] = FRAME_SLIP_DC;
}
else if(static_cast<uint8_t>(message[i]) == FRAME_SLIP_DB)
{
tempArray[index++] = FRAME_SLIP_DB;
tempArray[index++] = FRAME_SLIP_DD;
}
else
{
tempArray[index++] = message[i];
}
}
tempArray[index++] = FRAME_SLIP_C0;
return tempArray.mid(0, index);
}
int pack_deslip(QByteArray &message){
int i = 0;
int index = 0;
unsigned char crc = 0;
if((static_cast<uint8_t>(message[0]) != 0xC0) || (static_cast<uint8_t>(message[message.size() - 1]) != 0xC0))
{
return -1;
}
//去掉头和尾
for(i = 1; i < (message.size() - 1); i++)
{
if ((static_cast<uint8_t>(message[i]) == FRAME_SLIP_DB) && (static_cast<uint8_t>(message[i + 1]) == FRAME_SLIP_DC))
{
message[index] = FRAME_SLIP_C0;
i++;
}
else if ((static_cast<uint8_t>(message[i]) == FRAME_SLIP_DB) && (static_cast<uint8_t>(message[i + 1]) == FRAME_SLIP_DD))
{
message[index] = FRAME_SLIP_DB;
i++;
}
else
{
message[index] = message[i];
}
index++;
}
crc = message[index - 1];
QByteArray tempArray = message.mid(0, index);
calc_checksum(tempArray);
if(crc != static_cast<uint8_t>(tempArray[index - 1]))//crc校验出错
{
return -1;
}
message.resize(index); //保留校验字节
return index;
}
QByteArray pack_tiantong_short_message_cmd(const std::string& number, const std::u16string& message){

10
msg.h
View File

@@ -5,10 +5,15 @@
#include <string>
#include <QByteArray>
#define FRAME_SLIP_C0 0xC0
#define FRAME_SLIP_DB 0xDB
#define FRAME_SLIP_DC 0xDC
#define FRAME_SLIP_DD 0xDD
#define COMMAND_TYPE_INDEX 2
#define SUB_COMMAND_TYPE_INDEX 3
#define COMMAND_DATA_BEGIN_INDEX 4
#define FRAME_MIN_LEN 5
#define FRAME_LEN_STATUSREPORT (FRAME_MIN_LEN + 81)
enum class CommandType : uint8_t{
kTianTongVoice = 0xA0,
@@ -89,7 +94,7 @@ struct SatelliteStatus{
uint16_t azimuth;
uint8_t pitch;
};
void calc_checksum(QByteArray&cmd);
QByteArray pack_tiantong_dial_cmd(const std::string& number);
QByteArray pack_tiantong_hang_up_cmd();
QByteArray pack_tiantong_answer();
@@ -98,7 +103,8 @@ QByteArray pack_tiantong_send_keys_when_on_line_cmd(const std::string& keys);
QByteArray pack_uhf_dial_cmd(const std::string& number);
QByteArray pack_uhf_hang_up_cmd();
QByteArray pack_uhf_answer();
QByteArray pack_slip(QByteArray &message);
int pack_deslip(QByteArray &message);
QByteArray pack_tiantong_short_message_cmd(const std::string& number,const std::u16string& message);
QByteArray pack_uhf_short_message_cmd(const std::string& number, const std::u16string& message);
QByteArray pack_beidou_short_message_cmd(const std::string& number, const std::u16string& message);