devicefinder.cpp 5.5 KB
/* ****************************************************************************
 * Copyright 2019 Open Systems Development BV                                 *
 *                                                                            *
 * Permission is hereby granted, free of charge, to any person obtaining a    *
 * copy of this software and associated documentation files (the "Software"), *
 * to deal in the Software without restriction, including without limitation  *
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
 * and/or sell copies of the Software, and to permit persons to whom the      *
 * Software is furnished to do so, subject to the following conditions:       *
 *                                                                            *
 * The above copyright notice and this permission notice shall be included in *
 * all copies or substantial portions of the Software.                        *
 *                                                                            *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING    *
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER        *
 * DEALINGS IN THE SOFTWARE.                                                  *
 * ***************************************************************************/
// osdev::components::bluetooth
#include "devicefinder.h"
#include "devicehandler.h"
#include "deviceinfo.h"

using namespace osdev::components::bluetooth;

DeviceFinder::DeviceFinder( DeviceHandler *handler, QObject *parent )
    : BluetoothBaseClass( parent )
    , m_pDeviceHandler( handler )
    , m_pDeviceDiscoveryAgent( new QBluetoothDeviceDiscoveryAgent() )
    , m_devices()
{
    //! [devicediscovery-1]
    m_pDeviceDiscoveryAgent->setLowEnergyDiscoveryTimeout( 5000 );

    connect( m_pDeviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &DeviceFinder::slotAddDevice );
    connect( m_pDeviceDiscoveryAgent, static_cast<void (QBluetoothDeviceDiscoveryAgent::*)
             (QBluetoothDeviceDiscoveryAgent::Error)>(&QBluetoothDeviceDiscoveryAgent::error), this, &DeviceFinder::slotScanError );
    connect( m_pDeviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &DeviceFinder::slotScanFinished );
    connect( m_pDeviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::canceled, this, &DeviceFinder::slotScanFinished );

    connect( m_pDeviceHandler, &DeviceHandler::signalReceivedValue, this, &DeviceFinder::signalSendData );
}

DeviceFinder::~DeviceFinder()
{
    qDeleteAll( m_devices );
    m_devices.clear();
}

void DeviceFinder::slotStartSearch()
{
    clearMessages();
    m_pDeviceHandler->setDevice( nullptr );
    qDeleteAll( m_devices );
    m_devices.clear();

    emit signalDevicesChanged();

    m_pDeviceDiscoveryAgent->start( QBluetoothDeviceDiscoveryAgent::LowEnergyMethod );

    emit signalScanningChanged();
    setInfo( tr( "Scanning for devices..." ) );
}

void DeviceFinder::slotAddDevice( const QBluetoothDeviceInfo &device )
{
    // If device is LowEnergy-device and its services contain the one we're looking for, add it to the list.
    if( device.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration )
    {
        qInfo() << device.serviceUuids() << " : Looking for : " << m_pDeviceHandler->requestedServiceUuid();

        m_devices.append( new DeviceInfo( device ) );
        setInfo( tr( "Low Energy Device Found. Scanning for more...." ) );
        emit signalDevicesChanged();
    }
}

void DeviceFinder::slotScanError( QBluetoothDeviceDiscoveryAgent::Error error )
{
    if( error == QBluetoothDeviceDiscoveryAgent::PoweredOffError )
    {
        setError( tr( "The Bluetooth adapter is powered off." ) );
    }
    else if( error == QBluetoothDeviceDiscoveryAgent::InputOutputError )
    {
        setError( tr( "Writing or reading from the device resulted in an error." ) );
    }
    else
    {
        setError( tr( "An unknown error has occured." ) );
    }
}

void DeviceFinder::slotScanFinished()
{
    if( m_devices.isEmpty() )
        setError( tr( "No Low Energy devices found." ) );
    else
        setInfo( tr( "Scanning done." ) );

    emit signalScanningChanged();
    emit signalDevicesChanged();
    emit signalScanFinished();
}

void DeviceFinder::slotConnectToService( const QString &address )
{
    m_pDeviceDiscoveryAgent->stop();

    DeviceInfo *currentDevice = nullptr;
    for( auto entry : qAsConst( m_devices ) )
    {
        if( entry && entry->getAddress() == address )
        {
            currentDevice = entry;
            break;
        }
    }

    if( currentDevice )
        m_pDeviceHandler->setDevice( currentDevice );

    clearMessages();
}

bool DeviceFinder::scanning() const
{
    return m_pDeviceDiscoveryAgent->isActive();
}

QList<DeviceInfo*> DeviceFinder::devices()
{
    return m_devices;
}

QString DeviceFinder::getAddressByName( const QString &name )
{
    if( name.isEmpty() || name.isNull() )
        return QString();

    for( const auto &device : qAsConst( m_devices ) )
    {
        if( device->getName() == name )
            return device->getAddress();
    }

    return QString();
}

void DeviceFinder::slotDisconnect()
{
    m_pDeviceHandler->slotDisconnectService();
}