机载第一版

This commit is contained in:
xin
2025-11-19 15:11:44 +08:00
parent 612bf24b15
commit e8db9aa9fe
32 changed files with 766 additions and 75 deletions

View File

@ -0,0 +1,28 @@
cmake_minimum_required(VERSION 3.5)
project(GPSLog)
set(CMAKE_CXX_STANDARD 11)
# Qt 5.12 需要手动指定 Qt 模块
set(QT_MODULES Core SerialPort)
find_package(Qt5 COMPONENTS ${QT_MODULES} REQUIRED)
include_directories(${Qt5Core_INCLUDE_DIRS} ${Qt5SerialPort_INCLUDE_DIRS})
include_directories("../src/Logger")
# Source files
file(GLOB SOURCES "../src/*.cpp" "../src/*.h")
# Tell CMake to run moc when necessary
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
message(STATUS "SOURCES: ${SOURCES}")
add_executable(GPSLog ${SOURCES})
qt5_use_modules(GPSLog Core SerialPort)
target_link_libraries(GPSLog Qt5::Core Qt5::SerialPort)

View File

@ -0,0 +1,36 @@
#include "DataLogger.h"
#include <QDebug>
DataLogger::DataLogger(const QString &filePath, QObject *parent)
: QObject(parent),
m_filePath(filePath),
m_file(filePath)
{
m_stream.setDevice(&m_file);
}
bool DataLogger::openFile()
{
if (m_file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
qDebug() << "Data log file opened: " << m_filePath;
return true;
} else {
qDebug() << "Failed to open data log file: " << m_filePath << ", error: " << m_file.errorString();
return false;
}
}
void DataLogger::closeFile()
{
if (m_file.isOpen()) {
m_stream.flush();
m_file.close();
qDebug() << "Data log file closed: " << m_filePath;
}
}
void DataLogger::logData(const QString &computerTime, const QString &gpsTime, double latitude, double longitude, double altitude)
{
m_stream << computerTime << "," << gpsTime << "," << latitude << "," << longitude << "," << altitude << "\n";
m_stream.flush();
}

View File

@ -0,0 +1,25 @@
#ifndef DATALOGGER_H
#define DATALOGGER_H
#include <QObject>
#include <QString>
#include <QFile>
#include <QTextStream>
class DataLogger : public QObject
{
Q_OBJECT
public:
explicit DataLogger(const QString &filePath, QObject *parent = nullptr);
bool openFile();
void closeFile();
void logData(const QString &computerTime, const QString &gpsTime, double latitude, double longitude, double altitude);
private:
QString m_filePath;
QFile m_file;
QTextStream m_stream;
};
#endif // DATALOGGER_H

View File

@ -0,0 +1,105 @@
#include "GPSDataParser.h"
#include <QDebug>
#include <QStringList>
#include <QString>
#include <QByteArray>
GPSDataParser::GPSDataParser(QObject *parent)
: QObject(parent),
m_latitude(0.0),
m_longitude(0.0),
m_altitude(0.0)
{
}
long timeshasrecive=0;
float alttiude_last=0.0;
void GPSDataParser::parse(const QByteArray &nmeaData)
{
if (timeshasrecive>=2000)timeshasrecive=0;
timeshasrecive++;
if (timeshasrecive<10)
qDebug() << "Received NMEA data: " << nmeaData;
QString nmeaString = QString::fromUtf8(nmeaData);
QStringList nmeaParts = nmeaString.split(",");
// if (nmeaParts.size() < 11) {
// qDebug() << "Invalid NMEA data: " << nmeaString;
// return;
// }
// Parse GPGGA sentence
// qDebug() << " first " << nmeaParts[0];
if (nmeaParts[0] == "$GPGGA"|| nmeaParts[0] == "$GNGGA") {
// qDebug() << " GGA data: " << nmeaString;
if (nmeaParts.size() < 10) {
qDebug() << "Invalid GGA data: " << nmeaString;
return;
}
QString utcTime = nmeaParts[1];
bool ok;
double latitudeDegrees = nmeaParts[2].toDouble(&ok);
if (!ok) return;
char latitudeDirection = nmeaParts[3].at(0).toLatin1();
double longitudeDegrees = nmeaParts[4].toDouble(&ok);
if (!ok) return;
char longitudeDirection = nmeaParts[5].at(0).toLatin1();
double altitude = nmeaParts[9].toDouble(&ok);
if (!ok) return;
double latitude = convertToDecimalDegrees(latitudeDegrees, latitudeDirection);
double longitude = convertToDecimalDegrees(longitudeDegrees, longitudeDirection);
//emit dataParsed(utcTime, latitude, longitude, altitude);
alttiude_last=altitude;
} else if (nmeaParts[0] == "$GPRMC"|| nmeaParts[0] == "$GNRMC") {
// qDebug() << "valid RMC data: " << nmeaString;
if (nmeaParts.size() < 7) {
qDebug() << "Invalid RMC data: " << nmeaString;
return;
}
QString utcTime = nmeaParts[1];
char status = nmeaParts[2].at(0).toLatin1();
if (status == 'A') {
bool ok;
double latitudeDegrees = nmeaParts[3].toDouble(&ok);
if (!ok) return;
char latitudeDirection = nmeaParts[4].at(0).toLatin1();
double longitudeDegrees = nmeaParts[5].toDouble(&ok);
if (!ok) return;
char longitudeDirection = nmeaParts[6].at(0).toLatin1();
double latitude = convertToDecimalDegrees(latitudeDegrees, latitudeDirection);
double longitude = convertToDecimalDegrees(longitudeDegrees, longitudeDirection);
double altitude = 0.0; // RMC doesn't have altitude
emit dataParsed(utcTime, latitude, longitude, alttiude_last);
// // 输出utc lat long alt
// qDebug()<< "RMC Parsed Data - UTC Time:" << utcTime
// << "Latitude:" << latitude
// << "Longitude:" << longitude
// << "Altitude:" << altitude;
system("gpio mode 13 out");
}
} else {
// qDebug() << "other NMEA data: " << nmeaString;
}
}
double GPSDataParser::convertToDecimalDegrees(double degreesMinutes, char direction)
{
double degrees = int(degreesMinutes / 100);
double minutes = degreesMinutes - (degrees * 100);
double decimalDegrees = degrees + (minutes / 60);
if (direction == 'S' || direction == 'W') {
decimalDegrees *= -1;
}
return decimalDegrees;
}

View File

@ -0,0 +1,36 @@
#ifndef GPSDATAPARSER_H
#define GPSDATAPARSER_H
#include <QObject>
#include <QString>
#include <QByteArray>
class GPSDataParser : public QObject
{
Q_OBJECT
public:
explicit GPSDataParser(QObject *parent = nullptr);
void parse(const QByteArray &nmeaData);
signals:
void dataParsed(const QString &gpsTime, double latitude, double longitude, double altitude);
private:
double convertToDecimalDegrees(double degreesMinutes, char direction);
private:
QString m_utcTime;
double m_latitude;
double m_longitude;
double m_altitude;
public:
inline QString getUTCTime() const { return m_utcTime; }
inline double getLatitude() const { return m_latitude; }
inline double getLongitude() const { return m_longitude; }
inline double getAltitude() const { return m_altitude; }
};
#endif // GPSDATAPARSER_H

View File

@ -0,0 +1,94 @@
//
// Created by xin on 2021/8/17.
//edit by zz.
//fixed code page problem;added a new initialize function; --20211101
#pragma once
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include "qmutex.h"
#include "QtMsgHandler"
#include <iostream>
#include <QDir>
namespace QT_LOG
{
static int m_LogLevel = 1;
static QString m_LogFile = QString("%1_GPS.log").arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmss"));
QMutex m_LogMutex;
void customMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
if (type < m_LogLevel)
{
return;
}
QString log_info;
switch (type)
{
case QtDebugMsg:
log_info = QString("%1:%2").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"),msg);
break;
case QtWarningMsg:
log_info = QString("%1[Warning]:%2").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"),msg);
break;
case QtCriticalMsg:
log_info = QString("%1[Critical]:%2").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"),msg);
break;
case QtFatalMsg:
log_info = QString("%1[Fatal]:%2").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"),msg);
abort();
}
m_LogMutex.lock();
QFile outFile(m_LogFile);
outFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text);
QTextStream ts(&outFile);
ts << log_info << endl;
std::cout<<log_info.toStdString()<<std::endl;
outFile.close();
m_LogMutex.unlock();
}
void logInit(QString logFile = "",int logLevel = 0)
{
#ifndef _Debug
if ((logLevel < 0) || (logLevel > 3))
{
m_LogLevel = 1;
}
else
{
m_LogLevel = logLevel;
}
if (!logFile.isEmpty())
{
m_LogFile = logFile+"/"+m_LogFile;
}
qInstallMessageHandler(customMessageHandler);
//qInstallMsgHandler(customMessageHandler);
#endif
}
//added by IRIS_ZZ initialize from main
void InitLogger(QString qstrDir)
{
QDir qdLogFolder;
qdLogFolder.mkdir(qstrDir);
qDebug() << QT_LOG::m_LogFile;
QT_LOG::logInit(qstrDir);
}
};

View File

@ -0,0 +1,58 @@
#include "SerialPortReader.h"
SerialPortReader::SerialPortReader(const QString &portName, int baudRate, QObject *parent)
: QObject(parent),
m_portName(portName),
m_baudRate(baudRate),
m_serialPort(new QSerialPort(this))
{
m_serialPort->setPortName(m_portName);
m_serialPort->setBaudRate(115200);
connect(m_serialPort, &QSerialPort::readyRead, this, &SerialPortReader::readData);
}
SerialPortReader::~SerialPortReader()
{
closePort();
}
bool SerialPortReader::openPort()
{
if (m_serialPort->open(QIODevice::ReadOnly)) {
qDebug() << "Serial port opened: " << m_portName;
return true;
} else {
qDebug() << "Failed to open serial port: " << m_portName << ", error: " << m_serialPort->errorString();
return false;
}
}
void SerialPortReader::closePort()
{
if (m_serialPort->isOpen()) {
m_serialPort->close();
qDebug() << "Serial port closed: " << m_portName;
}
}
void SerialPortReader::start()
{
if (!openPort()) {
return;
}
}
void SerialPortReader::readData()
{
QByteArray newData = m_serialPort->readAll();
m_buffer.append(newData);
int nmeaEndIndex = m_buffer.indexOf("\r\n");
while (nmeaEndIndex != -1) {
QByteArray nmeaData = m_buffer.left(nmeaEndIndex);
m_buffer.remove(0, nmeaEndIndex + 2);
nmeaEndIndex = m_buffer.indexOf("\r\n");
emit dataReceived(nmeaData);
}
}

View File

@ -0,0 +1,35 @@
#ifndef SERIALPORTREADER_H
#define SERIALPORTREADER_H
#include <QObject>
#include <QThread>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>
class SerialPortReader : public QObject
{
Q_OBJECT
public:
explicit SerialPortReader(const QString &portName, int baudRate, QObject *parent = nullptr);
~SerialPortReader();
bool openPort();
void closePort();
void start();
signals:
void dataReceived(const QByteArray &data);
private slots:
void readData();
private:
QString m_portName;
int m_baudRate;
QSerialPort *m_serialPort;
QByteArray m_buffer;
};
#endif // SERIALPORTREADER_H

View File

@ -0,0 +1,62 @@
#include <QCoreApplication>
#include <QDateTime>
#include <QDebug>
#include <QSerialPort>
#include <QSerialPortInfo>
#include "SerialPortReader.h"
#include "GPSDataParser.h"
#include "DataLogger.h"
#include "Logger/Logger.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
system("gpio mode 13 input");
QT_LOG::InitLogger("/home/data/Log/");
// 1. 查找可用的串口
QString serialPortName;
const auto serialPortInfos = QSerialPortInfo::availablePorts();
if (!serialPortInfos.isEmpty()) {
for (const QSerialPortInfo &serialPortInfo : serialPortInfos) {
qDebug() << "Available serial port: " << serialPortInfo.portName();
}
// 默认使用第一个串口
serialPortName = serialPortInfos.first().portName();
} else {
qDebug() << "No serial port found.";
return 1;
}
// 3. 创建 SerialPortReader, GPSDataParser, DataLogger
SerialPortReader serialPortReader("/dev/ttyS2", 115200);
GPSDataParser gpsDataParser;
QDateTime datenow=QDateTime::currentDateTime();
QString fileparenth=QString("/home/data/GPS_Data/%1").arg(datenow.toString("yyyyMMdd"));
QString command=QString("mkdir -p %1").arg(fileparenth);
system(command.toStdString().c_str());
QString filePath = fileparenth+QString("/%1_gps.csv").arg( datenow.toString("yyyyMMdd_HHmmss"));
DataLogger dataLogger(filePath);
if (!dataLogger.openFile()) {
return 1;
}
// 4. 连接信号和槽
QObject::connect(&serialPortReader, &SerialPortReader::dataReceived, &gpsDataParser, &GPSDataParser::parse);
QObject::connect(&gpsDataParser, &GPSDataParser::dataParsed, [&](const QString &gpsTime, double latitude, double longitude, double altitude) {
QString computerTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
dataLogger.logData(computerTime, gpsTime, latitude, longitude, altitude);
});
// 5. 启动串口读取
serialPortReader.start();
// 6. 启动应用程序事件循环
int result = a.exec();
// 7. 关闭文件
dataLogger.closeFile();
return result;
}