Report serial port errors for #233

This commit is contained in:
Alex Spataru 2024-11-27 10:09:15 -05:00
parent 5a6ea37e32
commit 61c0758fad
3 changed files with 88 additions and 37 deletions

View File

@ -325,7 +325,6 @@ Rectangle {
icon.source: checked ? "qrc:/rcc/icons/toolbar/connect.svg" : icon.source: checked ? "qrc:/rcc/icons/toolbar/connect.svg" :
"qrc:/rcc/icons/toolbar/disconnect.svg" "qrc:/rcc/icons/toolbar/disconnect.svg"
// //
// Connect/disconnect device when button is clicked // Connect/disconnect device when button is clicked
// //

View File

@ -41,6 +41,9 @@ IO::Drivers::Serial::Serial()
, m_lastSerialDeviceIndex(0) , m_lastSerialDeviceIndex(0)
, m_portIndex(0) , m_portIndex(0)
{ {
// Populate error list
populateErrors();
// Read settings // Read settings
readSettings(); readSettings();
@ -55,6 +58,10 @@ IO::Drivers::Serial::Serial()
// Update connect button status when user selects a serial device // Update connect button status when user selects a serial device
connect(this, &IO::Drivers::Serial::portIndexChanged, this, connect(this, &IO::Drivers::Serial::portIndexChanged, this,
&IO::Drivers::Serial::configurationChanged); &IO::Drivers::Serial::configurationChanged);
// Update error list when language is changed
connect(this, &IO::Drivers::Serial::languageChanged, this,
&IO::Drivers::Serial::populateErrors);
} }
/** /**
@ -177,8 +184,19 @@ bool IO::Drivers::Serial::open(const QIODevice::OpenMode mode)
m_lastSerialDeviceIndex = m_portIndex; m_lastSerialDeviceIndex = m_portIndex;
Q_EMIT portIndexChanged(); Q_EMIT portIndexChanged();
// Create new serial port handler // Get port name from device list
m_port = new QSerialPort(ports.at(portId)); const auto name = ports.at(portId);
// Create new serial port handler for native serial ports
if (m_deviceNames.contains(name))
{
const auto handler = validPorts().at(portId - 1);
m_port = new QSerialPort(handler);
}
// Create a new serial port handler for user-specified serial ports
else if (m_customDevices.contains(name))
m_port = new QSerialPort(name);
// Configure serial port // Configure serial port
port()->setParity(parity()); port()->setParity(parity());
@ -196,7 +214,6 @@ bool IO::Drivers::Serial::open(const QIODevice::OpenMode mode)
{ {
connect(port(), &QIODevice::readyRead, this, connect(port(), &QIODevice::readyRead, this,
&IO::Drivers::Serial::onReadyRead); &IO::Drivers::Serial::onReadyRead);
port()->setDataTerminalReady(dtrEnabled()); port()->setDataTerminalReady(dtrEnabled());
return true; return true;
} }
@ -218,17 +235,6 @@ bool IO::Drivers::Serial::open(const QIODevice::OpenMode mode)
// Driver specifics // Driver specifics
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/**
* Returns the name of the current serial port device
*/
QString IO::Drivers::Serial::portName() const
{
if (port())
return port()->portName();
return tr("No Device");
}
/** /**
* Returns the pointer to the current serial port handler * Returns the pointer to the current serial port handler
*/ */
@ -309,8 +315,8 @@ quint8 IO::Drivers::Serial::flowControlIndex() const
*/ */
QStringList IO::Drivers::Serial::portList() const QStringList IO::Drivers::Serial::portList() const
{ {
if (m_portList.count() > 0) if (m_deviceNames.count() > 0)
return m_portList + m_customDevices; return m_deviceNames + m_customDevices;
else else
return QStringList{tr("Select Port")}; return QStringList{tr("Select Port")};
@ -456,6 +462,7 @@ void IO::Drivers::Serial::setupExternalConnections()
// Build serial devices list and refresh it every second // Build serial devices list and refresh it every second
connect(&Misc::TimerEvents::instance(), &Misc::TimerEvents::timeout1Hz, this, connect(&Misc::TimerEvents::instance(), &Misc::TimerEvents::timeout1Hz, this,
&IO::Drivers::Serial::refreshSerialDevices); &IO::Drivers::Serial::refreshSerialDevices);
// Update lists when language changes // Update lists when language changes
connect(&Misc::Translator::instance(), &Misc::Translator::languageChanged, connect(&Misc::Translator::instance(), &Misc::Translator::languageChanged,
this, &IO::Drivers::Serial::languageChanged); this, &IO::Drivers::Serial::languageChanged);
@ -516,21 +523,33 @@ void IO::Drivers::Serial::setPortIndex(const quint8 portIndex)
Q_EMIT portIndexChanged(); Q_EMIT portIndexChanged();
} }
/**
* @brief Registers a custom serial device.
*
* This function allows the registration of a custom serial device by verifying
* the validity of the provided path and ensuring it is not already registered.
* If the path is valid and not yet registered, it is added to the list of
* custom devices.
*
* @param device The file path of the device to register.
*/
void IO::Drivers::Serial::registerDevice(const QString &device) void IO::Drivers::Serial::registerDevice(const QString &device)
{ {
QFile path(device); const auto trimmedPath = device.simplified();
QFile path(trimmedPath);
if (path.exists()) if (path.exists())
{ {
if (!m_customDevices.contains(device)) if (!m_customDevices.contains(trimmedPath))
{ {
m_customDevices.append(device); m_customDevices.append(trimmedPath);
refreshSerialDevices(); Q_EMIT availablePortsChanged();
} }
} }
else else
Misc::Utilities::showMessageBox( Misc::Utilities::showMessageBox(
tr("\"%1\" is not a valid path").arg(device), tr("\"%1\" is not a valid path").arg(trimmedPath),
tr("Please type another path to register a custom serial device")); tr("Please type another path to register a custom serial device"));
} }
@ -718,25 +737,28 @@ void IO::Drivers::Serial::refreshSerialDevices()
{ {
// Create device list, starting with dummy header // Create device list, starting with dummy header
// (for a more friendly UI when no devices are attached) // (for a more friendly UI when no devices are attached)
QStringList ports; QStringList names;
ports.append(tr("Select Port")); QStringList locations;
locations.append("/dev/null");
names.append(tr("Select Port"));
// Search for available ports and add them to the lsit // Search for available ports and add them to the lsit
auto validPortList = validPorts(); auto validPortList = validPorts();
Q_FOREACH (QSerialPortInfo info, validPortList) Q_FOREACH (QSerialPortInfo info, validPortList)
{ {
#ifdef Q_OS_WIN if (!info.isNull())
ports.append(info.portName()); {
#else names.append(info.portName());
ports.append(info.systemLocation()); locations.append(info.systemLocation());
#endif }
} }
// Update list only if necessary // Update list only if necessary
if (portList() != ports) if (m_deviceNames != names)
{ {
// Update list // Update list
m_portList = ports; m_deviceNames = names;
m_deviceLocations = locations;
// Update current port index // Update current port index
bool indexChanged = false; bool indexChanged = false;
@ -784,8 +806,13 @@ void IO::Drivers::Serial::refreshSerialDevices()
void IO::Drivers::Serial::handleError(QSerialPort::SerialPortError error) void IO::Drivers::Serial::handleError(QSerialPort::SerialPortError error)
{ {
if (error != QSerialPort::NoError) if (error != QSerialPort::NoError)
{
Misc::Utilities::showMessageBox(tr("Critical serial port error"),
m_errorDescriptions[error]);
Manager::instance().disconnectDevice(); Manager::instance().disconnectDevice();
} }
}
/** /**
* Reads all the data from the serial port. * Reads all the data from the serial port.
@ -872,6 +899,31 @@ void IO::Drivers::Serial::writeSettings()
m_settings.setValue(QStringLiteral("IO_DataSource_Serial__BaudRates"), list); m_settings.setValue(QStringLiteral("IO_DataSource_Serial__BaudRates"), list);
} }
/**
* @brief Populates the error descriptions for the serial port driver.
*
* This function initializes a mapping of QSerialPort error codes to their
* corresponding human-readable descriptions. These descriptions provide
* detailed context and, where applicable, suggestions for resolving the error.
*/
void IO::Drivers::Serial::populateErrors()
{
// clang-format off
m_errorDescriptions.clear();
m_errorDescriptions.insert(QSerialPort::NoError, tr("No error occurred."));
m_errorDescriptions.insert(QSerialPort::DeviceNotFoundError, tr("The specified device could not be found. Please check the connection and try again."));
m_errorDescriptions.insert(QSerialPort::PermissionError, tr("Permission denied. Ensure the application has the necessary access rights to the device."));
m_errorDescriptions.insert(QSerialPort::OpenError, tr("Failed to open the device. It may already be in use or unavailable."));
m_errorDescriptions.insert(QSerialPort::WriteError, tr("An error occurred while writing data to the device."));
m_errorDescriptions.insert(QSerialPort::ReadError, tr("An error occurred while reading data from the device."));
m_errorDescriptions.insert(QSerialPort::ResourceError, tr("A critical resource error occurred. The device may have been disconnected or is no longer accessible."));
m_errorDescriptions.insert(QSerialPort::UnsupportedOperationError, tr("The requested operation is not supported on this device."));
m_errorDescriptions.insert(QSerialPort::UnknownError, tr("An unknown error occurred. Please check the device and try again."));
m_errorDescriptions.insert(QSerialPort::TimeoutError, tr("The operation timed out. The device may not be responding."));
m_errorDescriptions.insert(QSerialPort::NotOpenError, tr("The device is not open. Please open the device before attempting this operation."));
// clang-format on
}
/** /**
* Returns a list with all the valid serial port objects * Returns a list with all the valid serial port objects
*/ */

View File

@ -44,9 +44,6 @@ class Serial : public HAL_Driver
{ {
// clang-format off // clang-format off
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString portName
READ portName
NOTIFY portChanged)
Q_PROPERTY(bool autoReconnect Q_PROPERTY(bool autoReconnect
READ autoReconnect READ autoReconnect
WRITE setAutoReconnect WRITE setAutoReconnect
@ -136,7 +133,6 @@ public:
[[nodiscard]] quint64 write(const QByteArray &data) override; [[nodiscard]] quint64 write(const QByteArray &data) override;
[[nodiscard]] bool open(const QIODevice::OpenMode mode) override; [[nodiscard]] bool open(const QIODevice::OpenMode mode) override;
[[nodiscard]] QString portName() const;
[[nodiscard]] QSerialPort *port() const; [[nodiscard]] QSerialPort *port() const;
[[nodiscard]] bool autoReconnect() const; [[nodiscard]] bool autoReconnect() const;
@ -180,6 +176,7 @@ private slots:
void onReadyRead(); void onReadyRead();
void readSettings(); void readSettings();
void writeSettings(); void writeSettings();
void populateErrors();
void refreshSerialDevices(); void refreshSerialDevices();
void handleError(QSerialPort::SerialPortError error); void handleError(QSerialPort::SerialPortError error);
@ -206,9 +203,12 @@ private:
quint8 m_stopBitsIndex; quint8 m_stopBitsIndex;
quint8 m_flowControlIndex; quint8 m_flowControlIndex;
QStringList m_portList; QStringList m_deviceNames;
QStringList m_baudRateList;
QStringList m_customDevices; QStringList m_customDevices;
QStringList m_deviceLocations;
QStringList m_baudRateList;
QMap<QSerialPort::SerialPortError, QString> m_errorDescriptions;
}; };
} // namespace Drivers } // namespace Drivers
} // namespace IO } // namespace IO