mirror of
https://github.com/Serial-Studio/Serial-Studio.git
synced 2025-01-31 17:42:55 +08:00
Finish adding BLE support, rewrite JSON parsing code to address #131
This commit is contained in:
parent
aa20ed22e8
commit
17c2c107ce
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user