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
if (index >= 1 && index < m_serviceNames.count())
if (index >= 1 && index <= m_serviceNames.count())
{
// Generate service handler & connect signals/slots
auto serviceUuid = m_controller->services().at(index - 1);
@ -335,6 +335,8 @@ void IO::Drivers::BluetoothLE::selectService(const int index)
&IO::Drivers::BluetoothLE::onCharacteristicChanged);
connect(m_service, &QLowEnergyService::stateChanged, this,
&IO::Drivers::BluetoothLE::onServiceStateChanged);
connect(m_service, &QLowEnergyService::errorOccurred, this,
&IO::Drivers::BluetoothLE::onServiceError);
// clang-format on
if (m_service->state() == QLowEnergyService::RemoteService)
@ -367,8 +369,7 @@ void IO::Drivers::BluetoothLE::configureCharacteristics()
continue;
// Set client/descriptor connection properties
auto descriptor = c.descriptor(
QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration);
auto descriptor = c.clientCharacteristicConfiguration();
if (descriptor.isValid())
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.
*/
@ -448,7 +478,7 @@ void IO::Drivers::BluetoothLE::onDiscoveryError(QBluetoothDeviceDiscoveryAgent::
void IO::Drivers::BluetoothLE::onServiceStateChanged(
QLowEnergyService::ServiceState serviceState)
{
if (serviceState == QLowEnergyService::RemoteService)
if (serviceState == QLowEnergyService::ServiceDiscovered)
configureCharacteristics();
}
@ -459,9 +489,7 @@ void IO::Drivers::BluetoothLE::onCharacteristicChanged(
const QLowEnergyCharacteristic &info, const QByteArray &value)
{
(void)info;
if (!value.isEmpty())
Q_EMIT dataReceived(value);
Q_EMIT dataReceived(value);
}
#ifdef SERIAL_STUDIO_INCLUDE_MOC

View File

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

View File

@ -453,26 +453,34 @@ void IO::Manager::readFrames()
auto fIndex = cursor.indexOf(finish);
auto frame = cursor.left(fIndex);
// Checksum verification & Q_EMIT RX frame
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)
// Parse frame
if (!frame.isEmpty())
{
bytes = prevBytes;
break;
// Checksum verification & Q_EMIT RX frame
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
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;
// Frame empty, wait for more data...
else
bytes = prevBytes;
}
// Remove parsed data from master buffer

View File

@ -41,10 +41,6 @@ JSON::Generator::Generator()
: m_opMode(kAutomatic)
{
// 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,
this, &JSON::Generator::readData);
// clang-format on
@ -218,17 +214,6 @@ void JSON::Generator::writeSettings(const QString &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
* operation mode.
@ -248,16 +233,10 @@ void JSON::Generator::readData(const QByteArray &data)
if (data.isEmpty())
return;
// Initialize status handler
bool ok = false;
// Serial device sends JSON (auto mode)
QJsonObject jsonData;
if (operationMode() == JSON::Generator::kAutomatic)
{
jsonData = QJsonDocument::fromJson(data).object();
ok = !jsonData.isEmpty();
}
// Data is separated and parsed by Serial Studio (manual mode)
else
@ -285,9 +264,10 @@ void JSON::Generator::readData(const QByteArray &data)
if (index <= fields.count())
{
ok = true;
dataset.remove("value");
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
if (ok)
if (!jsonData.isEmpty())
Q_EMIT jsonChanged(jsonData);
}

View File

@ -109,7 +109,6 @@ public Q_SLOTS:
void writeSettings(const QString &path);
private Q_SLOTS:
void reset();
void readData(const QByteArray &data);
private:
@ -118,6 +117,5 @@ private:
QSettings m_settings;
OperationMode m_opMode;
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)
{
qDebug() << sender() << modified << Q_FUNC_INFO;
m_modified = modified;
Q_EMIT modifiedChanged();
}
@ -1483,8 +1481,6 @@ void Project::Model::onJsonLoaded()
*/
void Project::Model::onModelChanged()
{
qDebug() << sender() << Q_FUNC_INFO;
setModified(true);
}
@ -1494,8 +1490,6 @@ void Project::Model::onModelChanged()
*/
void Project::Model::onGroupChanged(const int group)
{
qDebug() << sender() << Q_FUNC_INFO;
(void)group;
setModified(true);
}
@ -1509,8 +1503,6 @@ void Project::Model::onGroupChanged(const int group)
*/
void Project::Model::onDatasetChanged(const int group, const int dataset)
{
qDebug() << sender() << Q_FUNC_INFO;
(void)group;
(void)dataset;
setModified(true);