File indexing completed on 2024-04-28 15:17:52

0001 /*
0002  * BluezQt - Asynchronous Bluez wrapper library
0003  *
0004  * SPDX-FileCopyrightText: 2021 Ivan Podkurkov <podkiva2@gmail.com>
0005  *
0006  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007  */
0008 
0009 #include "gattserviceremote_p.h"
0010 #include "gattserviceremote.h"
0011 #include "gattcharacteristicremote_p.h"
0012 #include "gattcharacteristicremote.h"
0013 #include "device_p.h"
0014 #include "device.h"
0015 #include "adapter.h"
0016 #include "input.h"
0017 #include "input_p.h"
0018 #include "mediaplayer.h"
0019 #include "mediaplayer_p.h"
0020 #include "utils.h"
0021 #include "macros.h"
0022 
0023 namespace BluezQt
0024 {
0025 
0026 GattServiceRemotePrivate::GattServiceRemotePrivate(const QString &path, const QVariantMap &properties, const DevicePtr &device)
0027     : QObject()
0028     , m_dbusProperties(nullptr)
0029     , m_primary(false)
0030     , m_device(device)
0031     , m_handle(0)
0032 {
0033     m_bluezGattService = new BluezGattService(Strings::orgBluez(), path, DBusConnection::orgBluez(), this);
0034 
0035     init(properties);
0036 }
0037 
0038 void GattServiceRemotePrivate::init(const QVariantMap &properties)
0039 {
0040     m_dbusProperties = new DBusProperties(Strings::orgBluez(), m_bluezGattService->path(),
0041                                           DBusConnection::orgBluez(), this);
0042 
0043     // Init properties    
0044     m_uuid = properties.value(QStringLiteral("UUID")).toString();
0045     m_primary = properties.value(QStringLiteral("Primary")).toBool();
0046     m_includes = properties.value(QStringLiteral("Includes")).value<QList<QDBusObjectPath>>();
0047     m_handle = static_cast<quint16>(properties.value(QStringLiteral("Handle")).toUInt());
0048 
0049 }
0050 
0051 void GattServiceRemotePrivate::interfacesAdded(const QString &path, const QVariantMapMap &interfaces)
0052 {
0053     bool changed = false;
0054     QVariantMapMap::const_iterator it;
0055 
0056     for (it = interfaces.constBegin(); it != interfaces.constEnd(); ++it) {
0057         if (it.key() == Strings::orgBluezGattCharacteristic1()) {
0058             addGattCharacteristic(path,it.value());
0059             changed = true;
0060         }
0061     }
0062 
0063     for (auto& ch: m_characteristics) {
0064         if (path.startsWith(ch->ubi())) {
0065             ch->d->interfacesAdded(path, interfaces);
0066             changed = true;
0067         }
0068     }
0069 
0070     if (changed) {
0071         Q_EMIT q.lock().data()->serviceChanged(q.toStrongRef());
0072     }
0073 }
0074 
0075 void GattServiceRemotePrivate::interfacesRemoved(const QString &path, const QStringList &interfaces)
0076 {
0077     Q_UNUSED(path)
0078     bool changed = false;
0079 
0080     for (auto& interface : interfaces) {
0081         if (interface == Strings::orgBluezGattCharacteristic1()) {
0082             removeGattCharacteristic(path);
0083             changed = true;
0084         }
0085     }
0086 
0087     for (auto& ch: m_characteristics) {
0088         if (path.startsWith(ch->ubi())) {
0089             ch->d->interfacesRemoved(path, interfaces);
0090             changed = true;
0091         }
0092     }
0093 
0094     if (changed) {
0095         Q_EMIT q.lock().data()->serviceChanged(q.toStrongRef());
0096     }
0097 }
0098 
0099 void GattServiceRemotePrivate::addGattCharacteristic(const QString &gattCharacteristicPath, const QVariantMap &properties)
0100 {
0101     // Check if we have the right path
0102     if (m_bluezGattService->path() != properties.value(QStringLiteral("Service")).value<QDBusObjectPath>().path()) {
0103         return;
0104     }
0105 
0106     GattServiceRemotePtr service = GattServiceRemotePtr(this->q);
0107 
0108     if (!service) {
0109         return;
0110     }
0111 
0112     GattCharacteristicRemotePtr gattCharacteristic = GattCharacteristicRemotePtr(new GattCharacteristicRemote(gattCharacteristicPath, properties, service));
0113     gattCharacteristic->d->q = gattCharacteristic.toWeakRef();
0114     m_characteristics.append(gattCharacteristic);
0115 
0116     Q_EMIT service->gattCharacteristicAdded(gattCharacteristic);
0117     Q_EMIT service->characteristicsChanged(m_characteristics);
0118 
0119     // Connections
0120     connect(gattCharacteristic.data(),&GattCharacteristicRemote::characteristicChanged,q.lock().data(),&GattServiceRemote::gattCharacteristicChanged);
0121 }
0122 
0123 void GattServiceRemotePrivate::removeGattCharacteristic(const QString &gattCharacteristicPath)
0124 {
0125     GattServiceRemotePtr service = GattServiceRemotePtr(this->q);
0126 
0127     if (!service) {
0128         return;
0129     }
0130 
0131     GattCharacteristicRemotePtr gattCharacteristic = nullptr;
0132     for (int i=0; i < service->characteristics().size(); ++i) {
0133         if (service->characteristics().at(i)->ubi() == gattCharacteristicPath) {
0134             gattCharacteristic = service->characteristics().at(i);
0135         }
0136     }
0137 
0138     if (gattCharacteristic == nullptr) {
0139         return;
0140     }
0141 
0142     m_characteristics.removeOne(gattCharacteristic);
0143 
0144     Q_EMIT service->gattCharacteristicRemoved(gattCharacteristic);
0145     Q_EMIT service->characteristicsChanged(m_characteristics);
0146 
0147     // Connections
0148     disconnect(gattCharacteristic.data(),&GattCharacteristicRemote::characteristicChanged,q.lock().data(),&GattServiceRemote::gattCharacteristicChanged);
0149 }
0150 
0151 QDBusPendingReply<> GattServiceRemotePrivate::setDBusProperty(const QString &name, const QVariant &value)
0152 {
0153     return m_dbusProperties->Set(Strings::orgBluezGattService1(), name, QDBusVariant(value));
0154 }
0155 
0156 void GattServiceRemotePrivate::propertiesChanged(const QString &path, const QString &interface, const QVariantMap &changed, const QStringList &invalidated)
0157 {
0158     if (interface == Strings::orgBluezGattCharacteristic1() || interface == Strings::orgBluezGattDescriptor1()) {
0159         for (GattCharacteristicRemotePtr characteristic : m_characteristics) {
0160             if (path.startsWith(characteristic->ubi())) {
0161                 characteristic->d->propertiesChanged(path, interface, changed, invalidated);
0162                 return;
0163             }
0164         }
0165     } else if (interface != Strings::orgBluezGattService1()) {
0166         return;
0167     }
0168 
0169     QVariantMap::const_iterator i;
0170     for (i = changed.constBegin(); i != changed.constEnd(); ++i) {
0171         const QVariant &value = i.value();
0172         const QString &property = i.key();
0173 
0174         if (property == QLatin1String("UUID")) {
0175             PROPERTY_CHANGED(m_uuid, toString, uuidChanged);
0176         } else if (property == QLatin1String("Primary")) {
0177             PROPERTY_CHANGED(m_primary, toBool, primaryChanged);
0178         } else if (property == QLatin1String("Includes")) {
0179             PROPERTY_CHANGED2(m_includes, value.value<QList<QDBusObjectPath>>(), includesChanged);
0180         } else if (property == QLatin1String("Handle")) {
0181             PROPERTY_CHANGED2(m_handle, value.value<quint16>(), handleChanged);
0182         }
0183     }
0184 
0185     for (auto& property : invalidated) {
0186         if (property == QLatin1String("UUID")) {
0187             PROPERTY_INVALIDATED(m_uuid, QString(), uuidChanged);
0188         } else if (property == QLatin1String("Primary")) {
0189             PROPERTY_INVALIDATED(m_primary, false, primaryChanged);
0190         } else if (property == QLatin1String("Includes")) {
0191             PROPERTY_INVALIDATED(m_includes, QList<QDBusObjectPath>(), includesChanged);
0192         } else if (property == QLatin1String("Handle")) {
0193             PROPERTY_INVALIDATED(m_handle, quint16(), handleChanged);
0194         }
0195     }
0196 
0197     q.lock().data()->serviceChanged(q.toStrongRef());
0198 }
0199 
0200 } // namespace BluezQt
0201 
0202 #include "moc_gattserviceremote_p.cpp"