Changeset b14a522 in subsurface


Ignore:
Timestamp:
Jun 11, 2017, 1:55:41 PM (2 weeks ago)
Author:
Dirk Hohndel <dirk@…>
Branches:
master
Children:
49cbfdd7
Parents:
3b993fba
git-author:
Dirk Hohndel <dirk@…> (06/05/17 19:41:57)
git-committer:
Dirk Hohndel <dirk@…> (06/11/17 13:55:41)
Message:

QML UI: move BT handling into core code

This shouldn't be part of the UI (qmlmanager), but part of our
overall handling of dive computers and BT devices.

Signed-off-by: Dirk Hohndel <dirk@…>

Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • core/CMakeLists.txt

    rdec47e1 rb14a522  
    2727# compile the core library, in C.
    2828set(SUBSURFACE_CORE_LIB_SRCS
     29        btdiscovery.cpp
    2930        cochran.c
    3031        datatrak.c
  • core/downloadfromdcthread.cpp

    re7cd1785 rb14a522  
    100100}
    101101
     102DCDeviceData *DCDeviceData::m_instance = NULL;
     103
    102104DCDeviceData::DCDeviceData(QObject *parent) : QObject(parent)
    103105{
     106        if (m_instance) {
     107                qDebug() << "already have an instance of DCDevieData";
     108                return;
     109        }
     110        m_instance = this;
    104111        memset(&data, 0, sizeof(data));
    105112        data.trip = nullptr;
     
    109116}
    110117
     118DCDeviceData *DCDeviceData::instance()
     119{
     120        if (!m_instance)
     121                m_instance = new DCDeviceData();
     122        return m_instance;
     123}
     124
     125QStringList DCDeviceData::getProductListFromVendor(const QString &vendor)
     126{
     127        return productList[vendor];
     128}
     129
    111130DCDeviceData * DownloadThread::data()
    112131{
     
    223242        return &data;
    224243}
     244
     245int DCDeviceData::getDetectedVendorIndex()
     246{
     247#if defined(BT_SUPPORT)
     248        QList<btVendorProduct> btDCs = BTDiscovery::instance()->getBtDcs();
     249        if (!btDCs.isEmpty()) {
     250                qDebug() << "getVendorIdx" << btDCs.first().vendorIdx;
     251                return btDCs.first().vendorIdx;
     252        }
     253#endif
     254        return -1;
     255}
     256
     257int DCDeviceData::getDetectedProductIndex()
     258{
     259#if defined(BT_SUPPORT)
     260        QList<btVendorProduct> btDCs = BTDiscovery::instance()->getBtDcs();
     261        if (!btDCs.isEmpty()) {
     262                qDebug() << "getProductIdx" << btDCs.first().productIdx;
     263                return btDCs.first().productIdx;
     264        }
     265#endif
     266        return -1;
     267}
     268
     269QString DCDeviceData::getDetectedDeviceAddress()
     270{
     271#if BT_SUPPORT
     272        QList<btVendorProduct> btDCs = BTDiscovery::instance()->getBtDcs();
     273        if (!btDCs.isEmpty()) {
     274                QString btAddr = btDCs.first().btdi.address().toString();
     275                qDebug() << "getBtAddress" << btAddr;
     276                return btAddr;
     277        }
     278        return QString();
     279#endif
     280}
  • core/downloadfromdcthread.h

    ra568562 rb14a522  
    55#include <QMap>
    66#include <QHash>
     7#include <QLoggingCategory>
    78
    89#include "dive.h"
    910#include "libdivecomputer.h"
     11#include "core/btdiscovery.h"
    1012
    1113/* Helper object for access of Device Data in QML */
     
    2628public:
    2729        DCDeviceData(QObject *parent = nullptr);
     30        static DCDeviceData *instance();
    2831
    2932        QString vendor() const;
     
    4245        device_data_t* internalData();
    4346
     47        Q_INVOKABLE QStringList getProductListFromVendor(const QString& vendor);
     48        Q_INVOKABLE int getDetectedVendorIndex();
     49        Q_INVOKABLE int getDetectedProductIndex();
     50        Q_INVOKABLE QString getDetectedDeviceAddress();
     51
    4452public slots:
    4553        void setVendor(const QString& vendor);
     
    5462        void setSaveLog(bool saveLog);
    5563private:
     64        static DCDeviceData *m_instance;
    5665        device_data_t data;
    5766};
     
    6574        void run() override;
    6675
    67         DCDeviceData *data();
     76        Q_INVOKABLE DCDeviceData *data();
    6877        QString error;
    6978
  • mobile-widgets/qml/DownloadFromDiveComputer.qml

    r8faf33e rb14a522  
    5858                                Layout.fillWidth: true
    5959                                model: vendorList
    60                                 currentIndex: manager.getVendorIndex()
     60                                currentIndex: downloadThread.data().getDetectedVendorIndex()
    6161                                onCurrentTextChanged: {
    62                                         comboProduct.model = manager.getDCListFromVendor(comboVendor.currentText)
    63                                         if (currentIndex == manager.getVendorIndex())
    64                                                 comboProduct.currentIndex = manager.getProductIndex()
     62                                        comboProduct.model = downloadThread.data().getProductListFromVendor(comboVendor.currentText)
     63                                        if (currentIndex == downloadThread.data().getDetectedVendorIndex())
     64                                                comboProduct.currentIndex = downloadThread.data().getDetectedProductIndex()
    6565                                }
    6666                        }
     
    7575                        CheckBox {
    7676                                id: isBluetooth
    77                                 checked: manager.getVendorIndex() != -1
     77                                checked: downloadThread.data().getDetectedVendorIndex() != -1
    7878                        }
    7979                }
  • mobile-widgets/qmlmanager.cpp

    r3b993fba rb14a522  
    9595{
    9696#if defined(BT_SUPPORT)
    97         if (localBtDevice.isValid() &&
    98             localBtDevice.hostMode() == QBluetoothLocalDevice::HostConnectable) {
    99                 btPairedDevices.clear();
    100                 QString localDeviceName = "localDevice " + localBtDevice.name() + " is valid, starting discovery";
    101                 appendTextToLog(localDeviceName.toUtf8().data());
    102 #if defined(Q_OS_LINUX)
    103                 discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
    104                 connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &QMLManager::btDeviceDiscovered);
    105                 discoveryAgent->start();
    106 #endif
    107 #if defined(Q_OS_ANDROID)
    108                 getBluetoothDevices();
    109 #endif
    110                 for (int i = 0; i < btPairedDevices.length(); i++) {
    111                         qDebug() << "Paired =" << btPairedDevices[i].name << btPairedDevices[i].address.toString();
    112                 }
    113 #if defined(Q_OS_LINUX)
    114                 discoveryAgent->stop();
    115 #endif
    116         } else {
    117                 appendTextToLog("localBtDevice isn't valid");
    118         }
     97        // ensure that we start the BTDiscovery - this should be triggered by the export of the class
     98        // to QML, but that doesn't seem to always work
     99        BTDiscovery *btDiscovery = BTDiscovery::instance();
    119100#endif
    120101        m_instance = this;
     
    216197        parse_file(filename);
    217198        process_dives(true, false);
    218 }
    219 
    220 #if defined(BT_SUPPORT)
    221 
    222 extern void addBtUuid(QBluetoothUuid uuid);
    223 
    224 void QMLManager::btDeviceDiscovered(const QBluetoothDeviceInfo &device)
    225 {
    226         btPairedDevice this_d;
    227         this_d.address = device.address();
    228         this_d.name = device.name();
    229         btPairedDevices.append(this_d);
    230 
    231         QString newDevice = device.name();
    232 
    233         // all the HW OSTC BT computers show up as "OSTC" + some other text, depending on model
    234         if (newDevice.startsWith("OSTC"))
    235                 newDevice = "OSTC 3";
    236         QList<QBluetoothUuid> serviceUuids = device.serviceUuids();
    237         foreach (QBluetoothUuid id, serviceUuids) {
    238                 addBtUuid(id);
    239                 qDebug() << id.toByteArray();
    240         }
    241         appendTextToLog("Found new device " + newDevice + " (" + device.address().toString() + ")");
    242         QString vendor, product;
    243         foreach (vendor, productList.keys()) {
    244                 if (productList[vendor].contains(newDevice)) {
    245                         appendTextToLog("this could be a " + vendor + " " +
    246                                         (newDevice == "OSTC 3" ? "OSTC family" : newDevice));
    247                         struct btVendorProduct btVP;
    248                         btVP.btdi = device;
    249                         btVP.vendorIdx = vendorList.indexOf(vendor);
    250                         btVP.productIdx = productList[vendor].indexOf(newDevice);
    251                         qDebug() << "adding new btDCs entry" << newDevice << btVP.vendorIdx << btVP.productIdx;
    252                         btDCs << btVP;
    253                 }
    254         }
    255 }
    256 #endif
    257 
    258 int QMLManager::getVendorIndex()
    259 {
    260 #if defined(BT_SUPPORT)
    261         if (!btDCs.isEmpty()) {
    262                 qDebug() << "getVendorIdx" << btDCs.first().vendorIdx;
    263                 return btDCs.first().vendorIdx;
    264         }
    265 #endif
    266         return -1;
    267 }
    268 
    269 int QMLManager::getProductIndex()
    270 {
    271 #if defined(BT_SUPPORT)
    272         if (!btDCs.isEmpty()) {
    273                 qDebug() << "getProductIdx" << btDCs.first().productIdx;
    274                 return btDCs.first().productIdx;
    275         }
    276 #endif
    277         return -1;
    278 }
    279 
    280 QString QMLManager::getBtAddress()
    281 {
    282 #if BT_SUPPORT
    283         if (!btDCs.isEmpty()) {
    284                 QString btAddr = btDCs.first().btdi.address().toString();
    285                 qDebug() << "getBtAddress" << btAddr;
    286                 return btAddr;
    287         }
    288         return QString();
    289 #endif
    290199}
    291200
     
    16121521        emit showPinChanged();
    16131522}
    1614 
    1615 QStringList QMLManager::getDCListFromVendor(const QString& vendor)
    1616 {
    1617         return productList[vendor];
    1618 }
    1619 
    1620 // Android: As Qt is not able to pull the pairing data from a device, i
    1621 // a lengthy discovery process is needed to see what devices are paired. On
    1622 // https://forum.qt.io/topic/46075/solved-bluetooth-list-paired-devices
    1623 // user s.frings74 does, however, present a solution to this using JNI.
    1624 // Currently, this code is taken "as is".
    1625 
    1626 void QMLManager::getBluetoothDevices()
    1627 {
    1628 #if defined(Q_OS_ANDROID) && defined(BT_SUPPORT)
    1629         struct QMLManager::btPairedDevice result;
    1630         // Query via Android Java API.
    1631 
    1632         // returns a BluetoothAdapter
    1633         QAndroidJniObject adapter=QAndroidJniObject::callStaticObjectMethod("android/bluetooth/BluetoothAdapter","getDefaultAdapter","()Landroid/bluetooth/BluetoothAdapter;");
    1634         if (checkException("BluetoothAdapter.getDefaultAdapter()", &adapter)) {
    1635                 return;
    1636         }
    1637         // returns a Set<BluetoothDevice>
    1638         QAndroidJniObject pairedDevicesSet=adapter.callObjectMethod("getBondedDevices","()Ljava/util/Set;");
    1639         if (checkException("BluetoothAdapter.getBondedDevices()", &pairedDevicesSet)) {
    1640                 return;
    1641         }
    1642         jint size=pairedDevicesSet.callMethod<jint>("size");
    1643         checkException("Set<BluetoothDevice>.size()", &pairedDevicesSet);
    1644         if (size > 0) {
    1645                 // returns an Iterator<BluetoothDevice>
    1646                 QAndroidJniObject iterator=pairedDevicesSet.callObjectMethod("iterator","()Ljava/util/Iterator;");
    1647                 if (checkException("Set<BluetoothDevice>.iterator()", &iterator)) {
    1648                         return;
    1649                 }
    1650                 for (int i = 0; i < size; i++) {
    1651                         // returns a BluetoothDevice
    1652                         QAndroidJniObject dev=iterator.callObjectMethod("next","()Ljava/lang/Object;");
    1653                         if (checkException("Iterator<BluetoothDevice>.next()", &dev)) {
    1654                                 continue;
    1655                 }
    1656 
    1657                 result.address = QBluetoothAddress(dev.callObjectMethod("getAddress","()Ljava/lang/String;").toString());
    1658                 result.name = dev.callObjectMethod("getName", "()Ljava/lang/String;").toString();
    1659 
    1660                 btPairedDevices.append(result);
    1661         }
    1662 }
    1663 #endif
    1664 }
    1665 
    1666 #if defined(Q_OS_ANDROID)
    1667 bool QMLManager::checkException(const char* method, const QAndroidJniObject *obj)
    1668 {
    1669         static QAndroidJniEnvironment env;
    1670         bool result = false;
    1671 
    1672         if (env->ExceptionCheck()) {
    1673                 qCritical("Exception in %s", method);
    1674                 env->ExceptionDescribe();
    1675                 env->ExceptionClear();
    1676                 result=true;
    1677         }
    1678         if (!(obj == NULL || obj->isValid())) {
    1679                 qCritical("Invalid object returned by %s", method);
    1680         result=true;
    1681         }
    1682         return result;
    1683 }
    1684 #endif
  • mobile-widgets/qmlmanager.h

    rdbd1d1f4 rb14a522  
    1717#endif
    1818
     19#include "core/btdiscovery.h"
    1920#include "core/gpslocation.h"
    2021#include "qt-models/divelistmodel.h"
     
    122123        bool showPin() const;
    123124        void setShowPin(bool enable);
    124         Q_INVOKABLE QStringList getDCListFromVendor(const QString& vendor);
    125         Q_INVOKABLE int getVendorIndex();
    126         Q_INVOKABLE int getProductIndex();
    127         Q_INVOKABLE QString getBtAddress();
    128 #if defined(BT_SUPPORT)
    129         struct btPairedDevice {
    130                 QBluetoothAddress address;
    131                 QString name;
    132         };
    133         void btDeviceDiscovered(const QBluetoothDeviceInfo &device);
    134         void getBluetoothDevices();
    135 #endif
    136125
    137126public slots:
     
    217206        bool m_showPin;
    218207
    219 #if defined(Q_OS_ANDROID)
    220         bool checkException(const char* method, const QAndroidJniObject* obj);
    221 #endif
    222 
    223 #if defined(BT_SUPPORT)
    224         QList<struct btPairedDevice> btPairedDevices;
    225         QBluetoothLocalDevice localBtDevice;
    226         QBluetoothDeviceDiscoveryAgent *discoveryAgent;
    227         struct btVendorProduct {
    228                 QBluetoothDeviceInfo btdi;
    229                 int vendorIdx;
    230                 int productIdx;
    231         };
    232         QList<struct btVendorProduct> btDCs;
    233 #endif
    234 
    235208signals:
    236209        void cloudUserNameChanged();
Note: See TracChangeset for help on using the changeset viewer.