Finish adding BLE support, rewrite JSON parsing code to address #131

This commit is contained in:
Alex Spataru 2023-01-22 05:40:45 -06:00
parent aa20ed22e8
commit 17c2c107ce
6 changed files with 64 additions and 57 deletions

View File

@ -321,7 +321,7 @@ void IO::Drivers::BluetoothLE::selectService(const int index)
} }
// Ensure that index is valid // Ensure that index is valid
if (index >= 1 && index < m_serviceNames.count()) if (index >= 1 && index <= m_serviceNames.count())
{ {
// Generate service handler & connect signals/slots // Generate service handler & connect signals/slots
auto serviceUuid = m_controller->services().at(index - 1); auto serviceUuid = m_controller->services().at(index - 1);
@ -335,6 +335,8 @@ void IO::Drivers::BluetoothLE::selectService(const int index)
&IO::Drivers::BluetoothLE::onCharacteristicChanged); &IO::Drivers::BluetoothLE::onCharacteristicChanged);
connect(m_service, &QLowEnergyService::stateChanged, this, connect(m_service, &QLowEnergyService::stateChanged, this,
&IO::Drivers::BluetoothLE::onServiceStateChanged); &IO::Drivers::BluetoothLE::onServiceStateChanged);
connect(m_service, &QLowEnergyService::errorOccurred, this,
&IO::Drivers::BluetoothLE::onServiceError);
// clang-format on // clang-format on
if (m_service->state() == QLowEnergyService::RemoteService) if (m_service->state() == QLowEnergyService::RemoteService)
@ -367,8 +369,7 @@ void IO::Drivers::BluetoothLE::configureCharacteristics()
continue; continue;
// Set client/descriptor connection properties // Set client/descriptor connection properties
auto descriptor = c.descriptor( auto descriptor = c.clientCharacteristicConfiguration();
QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration);
if (descriptor.isValid()) if (descriptor.isValid())
m_service->writeDescriptor(descriptor, QByteArray::fromHex("0100")); m_service->writeDescriptor(descriptor, QByteArray::fromHex("0100"));
} }
@ -415,6 +416,35 @@ void IO::Drivers::BluetoothLE::onDeviceDiscovered(const QBluetoothDeviceInfo &de
} }
} }
/**
* Notifies any service error that occurs
*/
void IO::Drivers::BluetoothLE::onServiceError(
QLowEnergyService::ServiceError serviceError)
{
switch (serviceError)
{
case QLowEnergyService::OperationError:
Q_EMIT error(tr("Operation error"));
break;
case QLowEnergyService::CharacteristicWriteError:
Q_EMIT error(tr("Characteristic write error"));
break;
case QLowEnergyService::DescriptorWriteError:
Q_EMIT error(tr("Descriptor write error"));
break;
case QLowEnergyService::UnknownError:
Q_EMIT error(tr("Unknown error"));
break;
case QLowEnergyService::CharacteristicReadError:
Q_EMIT error(tr("Characteristic read error"));
break;
case QLowEnergyService::DescriptorReadError:
Q_EMIT error(tr("Descriptor read error"));
break;
}
}
/** /**
* Notifies the user of any errors detected in the Bluetooth adapter of the computer. * Notifies the user of any errors detected in the Bluetooth adapter of the computer.
*/ */
@ -448,7 +478,7 @@ void IO::Drivers::BluetoothLE::onDiscoveryError(QBluetoothDeviceDiscoveryAgent::
void IO::Drivers::BluetoothLE::onServiceStateChanged( void IO::Drivers::BluetoothLE::onServiceStateChanged(
QLowEnergyService::ServiceState serviceState) QLowEnergyService::ServiceState serviceState)
{ {
if (serviceState == QLowEnergyService::RemoteService) if (serviceState == QLowEnergyService::ServiceDiscovered)
configureCharacteristics(); configureCharacteristics();
} }
@ -459,9 +489,7 @@ void IO::Drivers::BluetoothLE::onCharacteristicChanged(
const QLowEnergyCharacteristic &info, const QByteArray &value) const QLowEnergyCharacteristic &info, const QByteArray &value)
{ {
(void)info; (void)info;
Q_EMIT dataReceived(value);
if (!value.isEmpty())
Q_EMIT dataReceived(value);
} }
#ifdef SERIAL_STUDIO_INCLUDE_MOC #ifdef SERIAL_STUDIO_INCLUDE_MOC

View File

@ -106,6 +106,7 @@ private Q_SLOTS:
void configureCharacteristics(); void configureCharacteristics();
void onServiceDiscoveryFinished(); void onServiceDiscoveryFinished();
void onDeviceDiscovered(const QBluetoothDeviceInfo &device); void onDeviceDiscovered(const QBluetoothDeviceInfo &device);
void onServiceError(QLowEnergyService::ServiceError serviceError);
void onDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error error); void onDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error error);
void onServiceStateChanged(QLowEnergyService::ServiceState serviceState); void onServiceStateChanged(QLowEnergyService::ServiceState serviceState);
void onCharacteristicChanged(const QLowEnergyCharacteristic &info, void onCharacteristicChanged(const QLowEnergyCharacteristic &info,

View File

@ -453,26 +453,34 @@ void IO::Manager::readFrames()
auto fIndex = cursor.indexOf(finish); auto fIndex = cursor.indexOf(finish);
auto frame = cursor.left(fIndex); auto frame = cursor.left(fIndex);
// Checksum verification & Q_EMIT RX frame // Parse frame
int chop = 0; if (!frame.isEmpty())
auto result = integrityChecks(frame, cursor, &chop);
if (result == ValidationStatus::FrameOk)
Q_EMIT frameReceived(frame);
// Checksum data incomplete, try next time...
else if (result == ValidationStatus::ChecksumIncomplete)
{ {
bytes = prevBytes; // Checksum verification & Q_EMIT RX frame
break; int chop = 0;
auto result = integrityChecks(frame, cursor, &chop);
if (result == ValidationStatus::FrameOk)
Q_EMIT frameReceived(frame);
// Checksum data incomplete, try next time...
else if (result == ValidationStatus::ChecksumIncomplete)
{
bytes = prevBytes;
break;
}
// Remove the data including the finish sequence from the master buffer
cursor = cursor.mid(fIndex + chop, -1);
bytes += fIndex + chop;
// Frame read successfully, save the number of bytes to chop.
// This is used to manage frames with incomplete checksums
prevBytes = bytes;
} }
// Remove the data including the finish sequence from the master buffer // Frame empty, wait for more data...
cursor = cursor.mid(fIndex + chop, -1); else
bytes += fIndex + chop; bytes = prevBytes;
// Frame read successfully, save the number of bytes to chop.
// This is used to manage frames with incomplete checksums
prevBytes = bytes;
} }
// Remove parsed data from master buffer // Remove parsed data from master buffer

View File

@ -41,10 +41,6 @@ JSON::Generator::Generator()
: m_opMode(kAutomatic) : m_opMode(kAutomatic)
{ {
// clang-format off // clang-format off
connect(&CSV::Player::instance(), &CSV::Player::openChanged,
this, &JSON::Generator::reset);
connect(&IO::Manager::instance(), &IO::Manager::driverChanged,
this, &JSON::Generator::reset);
connect(&IO::Manager::instance(), &IO::Manager::frameReceived, connect(&IO::Manager::instance(), &IO::Manager::frameReceived,
this, &JSON::Generator::readData); this, &JSON::Generator::readData);
// clang-format on // clang-format on
@ -218,17 +214,6 @@ void JSON::Generator::writeSettings(const QString &path)
m_settings.setValue("json_map_location", path); m_settings.setValue("json_map_location", path);
} }
/**
* Resets all the statistics related to the current device and the JSON map file
*/
void JSON::Generator::reset()
{
m_json = QJsonObject();
m_latestValidValues.clear();
Q_EMIT jsonChanged(m_json);
}
/** /**
* Tries to parse the given data as a JSON document according to the selected * Tries to parse the given data as a JSON document according to the selected
* operation mode. * operation mode.
@ -248,16 +233,10 @@ void JSON::Generator::readData(const QByteArray &data)
if (data.isEmpty()) if (data.isEmpty())
return; return;
// Initialize status handler
bool ok = false;
// Serial device sends JSON (auto mode) // Serial device sends JSON (auto mode)
QJsonObject jsonData; QJsonObject jsonData;
if (operationMode() == JSON::Generator::kAutomatic) if (operationMode() == JSON::Generator::kAutomatic)
{
jsonData = QJsonDocument::fromJson(data).object(); jsonData = QJsonDocument::fromJson(data).object();
ok = !jsonData.isEmpty();
}
// Data is separated and parsed by Serial Studio (manual mode) // Data is separated and parsed by Serial Studio (manual mode)
else else
@ -285,9 +264,10 @@ void JSON::Generator::readData(const QByteArray &data)
if (index <= fields.count()) if (index <= fields.count())
{ {
ok = true;
dataset.remove("value"); dataset.remove("value");
dataset.insert("value", QJsonValue(fields.at(index - 1))); dataset.insert("value", QJsonValue(fields.at(index - 1)));
datasets.removeAt(j);
datasets.insert(j, dataset);
} }
} }
@ -306,7 +286,7 @@ void JSON::Generator::readData(const QByteArray &data)
} }
// Update UI // Update UI
if (ok) if (!jsonData.isEmpty())
Q_EMIT jsonChanged(jsonData); Q_EMIT jsonChanged(jsonData);
} }

View File

@ -109,7 +109,6 @@ public Q_SLOTS:
void writeSettings(const QString &path); void writeSettings(const QString &path);
private Q_SLOTS: private Q_SLOTS:
void reset();
void readData(const QByteArray &data); void readData(const QByteArray &data);
private: private:
@ -118,6 +117,5 @@ private:
QSettings m_settings; QSettings m_settings;
OperationMode m_opMode; OperationMode m_opMode;
QJsonParseError m_error; QJsonParseError m_error;
QStringList m_latestValidValues;
}; };
} }

View File

@ -1461,8 +1461,6 @@ void Project::Model::setDatasetFFTSamples(const int group, const int dataset,
*/ */
void Project::Model::setModified(const bool modified) void Project::Model::setModified(const bool modified)
{ {
qDebug() << sender() << modified << Q_FUNC_INFO;
m_modified = modified; m_modified = modified;
Q_EMIT modifiedChanged(); Q_EMIT modifiedChanged();
} }
@ -1483,8 +1481,6 @@ void Project::Model::onJsonLoaded()
*/ */
void Project::Model::onModelChanged() void Project::Model::onModelChanged()
{ {
qDebug() << sender() << Q_FUNC_INFO;
setModified(true); setModified(true);
} }
@ -1494,8 +1490,6 @@ void Project::Model::onModelChanged()
*/ */
void Project::Model::onGroupChanged(const int group) void Project::Model::onGroupChanged(const int group)
{ {
qDebug() << sender() << Q_FUNC_INFO;
(void)group; (void)group;
setModified(true); setModified(true);
} }
@ -1509,8 +1503,6 @@ void Project::Model::onGroupChanged(const int group)
*/ */
void Project::Model::onDatasetChanged(const int group, const int dataset) void Project::Model::onDatasetChanged(const int group, const int dataset)
{ {
qDebug() << sender() << Q_FUNC_INFO;
(void)group; (void)group;
(void)dataset; (void)dataset;
setModified(true); setModified(true);