mirror of
https://github.com/Serial-Studio/Serial-Studio.git
synced 2025-01-15 05:22:53 +08:00
Clean up JSON::Generator
This commit is contained in:
parent
b8263646a2
commit
735ec2e868
@ -65,8 +65,28 @@ DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050F00
|
||||
CONFIG += c++11
|
||||
CONFIG += silent
|
||||
|
||||
*g++*: {
|
||||
QMAKE_CXXFLAGS_RELEASE -= -O1
|
||||
QMAKE_CXXFLAGS_RELEASE -= -O2
|
||||
QMAKE_CXXFLAGS_RELEASE *= -O3
|
||||
QMAKE_CXXFLAGS_RELEASE *= -Ofast
|
||||
QMAKE_CXXFLAGS_RELEASE *= -flto
|
||||
}
|
||||
|
||||
*clang*: {
|
||||
QMAKE_CXXFLAGS_RELEASE -= -O1
|
||||
QMAKE_CXXFLAGS_RELEASE -= -O2
|
||||
QMAKE_CXXFLAGS_RELEASE *= -O3
|
||||
QMAKE_CXXFLAGS_RELEASE *= -Ofast
|
||||
QMAKE_CXXFLAGS_RELEASE *= -flto
|
||||
}
|
||||
|
||||
*msvc*: {
|
||||
QMAKE_CXXFLAGS *= -MP
|
||||
QMAKE_CXXFLAGS_RELEASE -= /O
|
||||
QMAKE_CXXFLAGS_RELEASE *= /O2
|
||||
QMAKE_CXXFLAGS_RELEASE *= /GL
|
||||
|
||||
INCLUDEPATH += $$OUT_PWD
|
||||
INCLUDEPATH += $$OUT_PWD/debug
|
||||
INCLUDEPATH += $$OUT_PWD/release
|
||||
|
@ -110,7 +110,6 @@ Item {
|
||||
property alias endSequence: settings.endSequence
|
||||
property alias startSequence: settings.startSequence
|
||||
property alias separatorSequence: settings.separatorSequence
|
||||
property alias multithreadedFrameProcessing: settings.multithreadedFrameProcessing
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -37,7 +37,6 @@ Control {
|
||||
property alias startSequence: _startSequence.text
|
||||
property alias windowShadows: _windowShadows.checked
|
||||
property alias separatorSequence: _separatorSequence.text
|
||||
property alias multithreadedFrameProcessing: _multithreadedFrameProcessing.checked
|
||||
|
||||
//
|
||||
// Layout
|
||||
@ -152,22 +151,6 @@ Control {
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Multi-threaded frame processing
|
||||
//
|
||||
Label {
|
||||
text: qsTr("Multithreaded frame parsing") + ": "
|
||||
} Switch {
|
||||
id: _multithreadedFrameProcessing
|
||||
Layout.leftMargin: -app.spacing
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
checked: Cpp_JSON_Generator.processFramesInSeparateThread
|
||||
onCheckedChanged: {
|
||||
if (checked != Cpp_JSON_Generator.processFramesInSeparateThread)
|
||||
Cpp_JSON_Generator.processFramesInSeparateThread = checked
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Window shadows
|
||||
//
|
||||
|
@ -39,13 +39,15 @@
|
||||
JSON::Generator::Generator()
|
||||
: m_frameCount(0)
|
||||
, m_opMode(kAutomatic)
|
||||
, m_processInSeparateThread(false)
|
||||
{
|
||||
const auto io = &IO::Manager::instance();
|
||||
const auto cp = &CSV::Player::instance();
|
||||
connect(cp, SIGNAL(openChanged()), this, SLOT(reset()));
|
||||
connect(io, SIGNAL(deviceChanged()), this, SLOT(reset()));
|
||||
connect(io, SIGNAL(frameReceived(QByteArray)), this, SLOT(readData(QByteArray)));
|
||||
// clang-format off
|
||||
connect(&CSV::Player::instance(), &CSV::Player::openChanged,
|
||||
this, &JSON::Generator::reset);
|
||||
connect(&IO::Manager::instance(), &IO::Manager::deviceChanged,
|
||||
this, &JSON::Generator::reset);
|
||||
connect(&IO::Manager::instance(), &IO::Manager::frameReceived,
|
||||
this, &JSON::Generator::readData);
|
||||
// clang-format on
|
||||
|
||||
readSettings();
|
||||
}
|
||||
@ -103,14 +105,6 @@ JSON::Generator::OperationMode JSON::Generator::operationMode() const
|
||||
return m_opMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns @c true if JSON frames shall be generated in a separate thread
|
||||
*/
|
||||
bool JSON::Generator::processFramesInSeparateThread() const
|
||||
{
|
||||
return m_processInSeparateThread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file dialog & lets the user select the JSON file map
|
||||
*/
|
||||
@ -203,15 +197,6 @@ void JSON::Generator::setOperationMode(const JSON::Generator::OperationMode &mod
|
||||
Q_EMIT operationModeChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables multi-threaded frame processing
|
||||
*/
|
||||
void JSON::Generator::setProcessFramesInSeparateThread(const bool threaded)
|
||||
{
|
||||
m_processInSeparateThread = threaded;
|
||||
Q_EMIT processFramesInSeparateThreadChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the last saved JSON map file (if any)
|
||||
*/
|
||||
@ -222,25 +207,6 @@ void JSON::Generator::readSettings()
|
||||
loadJsonMap(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the rest of the application that a new JSON frame has been received. The JFI
|
||||
* also contains RX date/time and frame number.
|
||||
*
|
||||
* Read the "FrameInfo.h" file for more information.
|
||||
*/
|
||||
void JSON::Generator::loadJFI(const JFI_Object &info)
|
||||
{
|
||||
const bool csvOpen = CSV::Player::instance().isOpen();
|
||||
const bool devOpen = IO::Manager::instance().connected();
|
||||
const bool mqttSub = MQTT::Client::instance().isSubscribed();
|
||||
|
||||
if (csvOpen || devOpen || mqttSub)
|
||||
Q_EMIT jsonChanged(info);
|
||||
|
||||
else
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the location of the last valid JSON map file that was opened (if any)
|
||||
*/
|
||||
@ -249,16 +215,6 @@ void JSON::Generator::writeSettings(const QString &path)
|
||||
m_settings.setValue("json_map_location", path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new JFI event with the given @a JSON document and increment the frame count
|
||||
*/
|
||||
void JSON::Generator::loadJSON(const QJsonDocument &json)
|
||||
{
|
||||
m_frameCount++;
|
||||
auto jfi = JFI_CreateNew(m_frameCount, QDateTime::currentDateTime(), json);
|
||||
loadJFI(jfi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all the statistics related to the current device and the JSON map file
|
||||
*/
|
||||
@ -289,29 +245,7 @@ void JSON::Generator::readData(const QByteArray &data)
|
||||
|
||||
// Increment received frames and process frame
|
||||
m_frameCount++;
|
||||
|
||||
// Create new worker thread to read JSON data
|
||||
if (processFramesInSeparateThread())
|
||||
{
|
||||
// clang-format off
|
||||
QThread *thread = new QThread;
|
||||
Worker *worker = new Worker(data,
|
||||
m_frameCount,
|
||||
QDateTime::currentDateTime());
|
||||
worker->moveToThread(thread);
|
||||
// clang-format on
|
||||
|
||||
connect(thread, SIGNAL(started()), worker, SLOT(process()));
|
||||
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
|
||||
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
|
||||
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
|
||||
connect(worker, &JSON::Worker::jsonReady, this, &JSON::Generator::loadJFI);
|
||||
thread->start();
|
||||
}
|
||||
|
||||
// Process frames in main thread
|
||||
else
|
||||
processFrame(data, m_frameCount, QDateTime::currentDateTime());
|
||||
processFrame(data, m_frameCount, QDateTime::currentDateTime());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -321,6 +255,10 @@ void JSON::Generator::readData(const QByteArray &data)
|
||||
void JSON::Generator::processFrame(const QByteArray &data, const quint64 frame,
|
||||
const QDateTime &time)
|
||||
{
|
||||
//
|
||||
// TODO: Re-write this function because it leaks memory
|
||||
//
|
||||
|
||||
// Serial device sends JSON (auto mode)
|
||||
if (operationMode() == JSON::Generator::kAutomatic)
|
||||
m_jfi.jsonDocument = QJsonDocument::fromJson(data, &m_error);
|
||||
@ -387,97 +325,6 @@ void JSON::Generator::processFrame(const QByteArray &data, const quint64 frame,
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// JSON worker object (executed for each frame on a new thread)
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructor function, stores received frame data & the date/time that the frame data
|
||||
* was received.
|
||||
*/
|
||||
JSON::Worker::Worker(const QByteArray &data, const quint64 frame, const QDateTime &time)
|
||||
: m_time(time)
|
||||
, m_data(data)
|
||||
, m_frame(frame)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the frame & inserts its values on the JSON map, and/or extracts the JSON frame
|
||||
* directly from the serial data.
|
||||
*/
|
||||
void JSON::Worker::process()
|
||||
{
|
||||
// Init variables
|
||||
QJsonParseError error;
|
||||
QJsonDocument document;
|
||||
|
||||
// Serial device sends JSON (auto mode)
|
||||
if (Generator::instance().operationMode() == Generator::kAutomatic)
|
||||
document = QJsonDocument::fromJson(m_data, &error);
|
||||
|
||||
// We need to use a map file, check if its loaded & replace values into map
|
||||
else
|
||||
{
|
||||
// Empty JSON map data
|
||||
if (Generator::instance().jsonMapData().isEmpty())
|
||||
return;
|
||||
|
||||
// Separate incoming data & add it to the JSON map
|
||||
auto json = Generator::instance().jsonMapData();
|
||||
const auto sepr = IO::Manager::instance().separatorSequence();
|
||||
const auto list = QString::fromUtf8(m_data).split(sepr);
|
||||
for (int i = 0; i < list.count(); ++i)
|
||||
json.replace(QString("\"%%1\"").arg(i + 1), "\"" + list.at(i) + "\"");
|
||||
|
||||
// Create json document
|
||||
const auto jsonData = json.toUtf8();
|
||||
const auto jsonDocument = QJsonDocument::fromJson(jsonData, &error);
|
||||
|
||||
// Calculate dynamically generated values
|
||||
auto root = jsonDocument.object();
|
||||
auto groups = JFI_Value(root, "groups", "g").toArray();
|
||||
for (int i = 0; i < groups.count(); ++i)
|
||||
{
|
||||
// Get group
|
||||
auto group = groups.at(i).toObject();
|
||||
|
||||
// Evaluate each dataset of the current group
|
||||
auto datasets = JFI_Value(group, "datasets", "d").toArray();
|
||||
for (int j = 0; j < datasets.count(); ++j)
|
||||
{
|
||||
auto dataset = datasets.at(j).toObject();
|
||||
auto value = JFI_Value(dataset, "value", "v").toString();
|
||||
dataset.remove("v");
|
||||
dataset.remove("value");
|
||||
dataset.insert("value", value);
|
||||
datasets.replace(j, dataset);
|
||||
}
|
||||
|
||||
// Replace group datasets
|
||||
group.remove("d");
|
||||
group.remove("datasets");
|
||||
group.insert("datasets", datasets);
|
||||
groups.replace(i, group);
|
||||
}
|
||||
|
||||
// Replace root document group objects
|
||||
root.remove("g");
|
||||
root.remove("groups");
|
||||
root.insert("groups", groups);
|
||||
|
||||
// Create JSON document
|
||||
document = QJsonDocument(root);
|
||||
}
|
||||
|
||||
// No parse error, update UI & reset error counter
|
||||
if (error.error == QJsonParseError::NoError)
|
||||
Q_EMIT jsonReady(JFI_CreateNew(m_frame, m_time, document));
|
||||
|
||||
// Delete object
|
||||
Q_EMIT finished();
|
||||
}
|
||||
|
||||
#ifdef SERIAL_STUDIO_INCLUDE_MOC
|
||||
# include "moc_Generator.cpp"
|
||||
#endif
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include <QFile>
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <QSettings>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonValue>
|
||||
@ -36,33 +35,6 @@
|
||||
|
||||
namespace JSON
|
||||
{
|
||||
/**
|
||||
* Generates a JSON document by combining the JSON map file and the received
|
||||
* data from the microcontroller device.
|
||||
*
|
||||
* This code is executed on another thread in order to avoid blocking the
|
||||
* user interface.
|
||||
*/
|
||||
class Worker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_SIGNALS:
|
||||
void finished();
|
||||
void jsonReady(const JFI_Object &info);
|
||||
|
||||
public:
|
||||
Worker(const QByteArray &data, const quint64 frame, const QDateTime &time);
|
||||
|
||||
public Q_SLOTS:
|
||||
void process();
|
||||
|
||||
private:
|
||||
QDateTime m_time;
|
||||
QByteArray m_data;
|
||||
quint64 m_frame;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The Generator class
|
||||
*
|
||||
@ -99,17 +71,12 @@ class Generator : public QObject
|
||||
READ operationMode
|
||||
WRITE setOperationMode
|
||||
NOTIFY operationModeChanged)
|
||||
Q_PROPERTY(bool processFramesInSeparateThread
|
||||
READ processFramesInSeparateThread
|
||||
WRITE setProcessFramesInSeparateThread
|
||||
NOTIFY processFramesInSeparateThreadChanged)
|
||||
// clang-format on
|
||||
|
||||
Q_SIGNALS:
|
||||
void jsonFileMapChanged();
|
||||
void operationModeChanged();
|
||||
void jsonChanged(const JFI_Object &info);
|
||||
void processFramesInSeparateThreadChanged();
|
||||
|
||||
private:
|
||||
explicit Generator();
|
||||
@ -132,19 +99,15 @@ public:
|
||||
QString jsonMapFilename() const;
|
||||
QString jsonMapFilepath() const;
|
||||
OperationMode operationMode() const;
|
||||
bool processFramesInSeparateThread() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void loadJsonMap();
|
||||
void loadJsonMap(const QString &path);
|
||||
void setProcessFramesInSeparateThread(const bool threaded);
|
||||
void setOperationMode(const JSON::Generator::OperationMode &mode);
|
||||
|
||||
public Q_SLOTS:
|
||||
void readSettings();
|
||||
void loadJFI(const JFI_Object &object);
|
||||
void writeSettings(const QString &path);
|
||||
void loadJSON(const QJsonDocument &json);
|
||||
|
||||
private Q_SLOTS:
|
||||
void reset();
|
||||
@ -159,6 +122,5 @@ private:
|
||||
QString m_jsonMapData;
|
||||
OperationMode m_opMode;
|
||||
QJsonParseError m_error;
|
||||
bool m_processInSeparateThread;
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user