LCOV - code coverage report
Current view: top level - src/cli - devicecommand.cpp (source / functions) Hit Total Coverage
Project: Dokit Lines: 42 60 70.0 %
Version: Functions: 9 10 90.0 %

          Line data    Source code
       1             : // SPDX-FileCopyrightText: 2022-2023 Paul Colby <git@colby.id.au>
       2             : // SPDX-License-Identifier: LGPL-3.0-or-later
       3             : 
       4             : #include "devicecommand.h"
       5             : 
       6             : #include <qtpokit/abstractpokitservice.h>
       7             : #include <qtpokit/pokitdevice.h>
       8             : #include <qtpokit/pokitdiscoveryagent.h>
       9             : 
      10             : /*!
      11             :  * \class DeviceCommand
      12             :  *
      13             :  * The AbstractCommand class extends AbstractCommand to add a PokitDevice instance.
      14             :  */
      15             : 
      16             : /*!
      17             :  * Construct a new DeviceCommand object with \a parent.
      18             :  */
      19        6486 : DeviceCommand::DeviceCommand(QObject * const parent) : AbstractCommand(parent)
      20             : {
      21             : 
      22        6486 : }
      23             : 
      24             : /*!
      25             :  * Begins scanning for the Pokit device.
      26             :  */
      27          36 : bool DeviceCommand::start()
      28             : {
      29          72 :     qCInfo(lc).noquote() << ((deviceToScanFor.isNull())
      30          64 :         ? tr("Looking for first available Pokit device...")
      31          76 :         : tr("Looking for device \"%1\"...").arg(deviceToScanFor));
      32          36 :     discoveryAgent->start();
      33          36 :     return true;
      34             : }
      35             : 
      36             : /*!
      37             :  * Disconnects the underlying Pokit device, and sets \a exitCode to be return to the OS once the
      38             :  * disconnection has taken place.
      39             :  */
      40         474 : void DeviceCommand::disconnect(int exitCode)
      41             : {
      42         474 :     qCDebug(lc).noquote() << tr("Disconnecting Pokit device...");
      43             :     Q_ASSERT(device);
      44             :     Q_ASSERT(device->controller());
      45         474 :     exitCodeOnDisconnect = exitCode;
      46         474 :     device->controller()->disconnectFromDevice();
      47         474 : }
      48             : 
      49             : /*!
      50             :  * \fn virtual AbstractPokitService * DeviceCommand::getService() = 0
      51             :  *
      52             :  * Returns a Pokit service object for the derived command class. This will be called by
      53             :  * deviceDiscovered() when the requested Pokit device has been found, after which
      54             :  * deviceDiscovered() will connect the returned service's common signals, and kick off the
      55             :  * device's connection process.
      56             :  */
      57             : 
      58             : /*!
      59             :  * Handles controller error events. This base implementation simply logs \a error and then exits
      60             :  * with `EXIT_FAILURE`. Derived classes may override this slot to implement their own error
      61             :  * handing if desired.
      62             :  */
      63          36 : void DeviceCommand::controllerError(QLowEnergyController::Error error)
      64             : {
      65         108 :     qCWarning(lc).noquote() << tr("Bluetooth controller error:") << error;
      66          36 :     QCoreApplication::exit(EXIT_FAILURE);
      67          36 : }
      68             : 
      69             : /*!
      70             :  * Handles devics disconnection events. This base implementation simply logs and exits the
      71             :  * application (via QCoreApplication::exit) with the current exitCodeOnDisconnect value, which is
      72             :  * initialise to `EXIT_FAILURE` in the constructor, but should be set to `EXIT_SUCESS` if/when
      73             :  * the derived command class has completed its actions and requested the disconnection (as opposed
      74             :  * to a spontaneous disconnection on error).
      75             :  */
      76          18 : void DeviceCommand::deviceDisconnected()
      77             : {
      78          18 :     qCDebug(lc).noquote() << tr("Pokit device disconnected. Exiting with code %1.")
      79           0 :         .arg(exitCodeOnDisconnect);
      80          18 :     QCoreApplication::exit(exitCodeOnDisconnect);
      81          18 : }
      82             : 
      83             : /*!
      84             :  * Handles service error events. This base implementation simply logs \a error and then exits
      85             :  * with `EXIT_FAILURE`. Derived classes may override this slot to implement their own error
      86             :  * handing if desired.
      87             :  *
      88             :  * \note As this base class does not construct services (derived classed do), its up to the derived
      89             :  * classed to connect this slot to the relevant service's error signal if desired.
      90             :  */
      91          36 : void DeviceCommand::serviceError(const QLowEnergyService::ServiceError error)
      92             : {
      93         108 :     qCWarning(lc).noquote() << tr("Bluetooth service error:") << error;
      94          36 :     QCoreApplication::exit(EXIT_FAILURE);
      95          36 : }
      96             : 
      97             : /*!
      98             :  * Handles service detail discovery events. This base implementation simply logs the event, and
      99             :  * nothing more. Derived classes may (usually do) override this slot to provide their own processing
     100             :  * when a services details have been discovered.
     101             :  */
     102         348 : void DeviceCommand::serviceDetailsDiscovered()
     103             : {
     104         348 :     qCDebug(lc).noquote() << tr("Service details discovered.");
     105         348 : }
     106             : 
     107             : /*!
     108             :  * Checks if \a info is the device (if any) we're looking for, and if so, create a contoller and
     109             :  * service, and begins connecting to the device.
     110             :  */
     111          18 : void DeviceCommand::deviceDiscovered(const QBluetoothDeviceInfo &info)
     112             : {
     113          18 :     if (device) {
     114           0 :         qCDebug(lc).noquote() << tr("Ignoring additional Pokit device \"%1\" (%2) at (%3).")
     115           0 :             .arg(info.name(), info.deviceUuid().toString(), info.address().toString());
     116           0 :         return;
     117             :     }
     118             : 
     119          54 :     if ((deviceToScanFor.isEmpty()) || (deviceToScanFor == info.name()) ||
     120          72 :         ((!info.address().isNull()) && (info.address() == QBluetoothAddress(deviceToScanFor))) ||
     121          36 :         ((!info.deviceUuid().isNull()) && (info.deviceUuid() == QBluetoothUuid(deviceToScanFor))))
     122             :     {
     123           0 :         qCDebug(lc).noquote() << tr("Found Pokit device \"%1\" (%2) at (%3).")
     124           0 :             .arg(info.name(), info.deviceUuid().toString(), info.address().toString());
     125           0 :         discoveryAgent->stop();
     126             : 
     127           0 :         device = new PokitDevice(info, this);
     128           0 :         connect(device->controller(), &QLowEnergyController::disconnected,
     129             :                 this, &DeviceCommand::deviceDisconnected);
     130           0 :         connect(device->controller(),
     131             :             #if (QT_VERSION < QT_VERSION_CHECK(6, 2, 0))
     132             :             QOverload<QLowEnergyController::Error>::of(&QLowEnergyController::error),
     133             :             #else
     134             :             &QLowEnergyController::errorOccurred,
     135             :             #endif
     136             :             this, &DeviceCommand::controllerError, Qt::QueuedConnection);
     137             : 
     138           0 :         const AbstractPokitService * const service = getService();
     139             : 
     140             :         Q_ASSERT(service);
     141           0 :         connect(service, &AbstractPokitService::serviceDetailsDiscovered,
     142             :                 this, &DeviceCommand::serviceDetailsDiscovered);
     143           0 :         connect(service, &AbstractPokitService::serviceErrorOccurred,
     144             :                 this, &DeviceCommand::serviceError);
     145             : 
     146           0 :         qCDebug(lc).noquote() << tr("Connecting to Pokit device \"%1\" (%2) at (%3).")
     147           0 :             .arg(info.name(), info.deviceUuid().toString(), info.address().toString());
     148           0 :         device->controller()->connectToDevice();
     149           0 :         return;
     150             :     }
     151             : 
     152          18 :     qCDebug(lc).noquote() << tr("Ignoring non-matching Pokit device \"%1\" (%2) at (%3).")
     153           0 :         .arg(info.name(), info.deviceUuid().toString(), info.address().toString());
     154           3 :     return;
     155             : }
     156             : 
     157             : /*!
     158             :  * Checks that the requested device was discovered, and if not, reports and error and exits.
     159             :  */
     160          36 : void DeviceCommand::deviceDiscoveryFinished()
     161             : {
     162          36 :     if (!device) {
     163          72 :         qCWarning(lc).noquote() << ((deviceToScanFor.isNull())
     164          64 :             ? tr("Failed to find any Pokit device.")
     165          76 :             : tr("Failed to find device \"%1\".").arg(deviceToScanFor));
     166          36 :         QCoreApplication::exit(EXIT_FAILURE);
     167             :     }
     168          36 : }

Generated by: LCOV version 1.14