forked from xin/TowerOptoSifAndSpectral
机载第一版
This commit is contained in:
28
othersoft/GPSLog/project/CMakeLists.txt
Normal file
28
othersoft/GPSLog/project/CMakeLists.txt
Normal 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)
|
||||
36
othersoft/GPSLog/src/DataLogger.cpp
Normal file
36
othersoft/GPSLog/src/DataLogger.cpp
Normal 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();
|
||||
}
|
||||
25
othersoft/GPSLog/src/DataLogger.h
Normal file
25
othersoft/GPSLog/src/DataLogger.h
Normal 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
|
||||
105
othersoft/GPSLog/src/GPSDataParser.cpp
Normal file
105
othersoft/GPSLog/src/GPSDataParser.cpp
Normal 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;
|
||||
}
|
||||
36
othersoft/GPSLog/src/GPSDataParser.h
Normal file
36
othersoft/GPSLog/src/GPSDataParser.h
Normal 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
|
||||
94
othersoft/GPSLog/src/Logger/Logger.h
Normal file
94
othersoft/GPSLog/src/Logger/Logger.h
Normal 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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
58
othersoft/GPSLog/src/SerialPortReader.cpp
Normal file
58
othersoft/GPSLog/src/SerialPortReader.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
35
othersoft/GPSLog/src/SerialPortReader.h
Normal file
35
othersoft/GPSLog/src/SerialPortReader.h
Normal 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
|
||||
62
othersoft/GPSLog/src/main.cpp
Normal file
62
othersoft/GPSLog/src/main.cpp
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user