File indexing completed on 2024-12-08 12:15:33

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 "gattcharacteristicremote_p.h"
0010 #include "gattcharacteristicremote.h"
0011 #include "gattdescriptorremote.h"
0012 #include "gattdescriptorremote_p.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 GattCharacteristicRemotePrivate::GattCharacteristicRemotePrivate(const QString &path, const QVariantMap &properties, const GattServiceRemotePtr &service)
0027     : QObject()
0028     , m_dbusProperties(nullptr)
0029     , m_writeAcquired(false)
0030     , m_notifyAcquired(false)
0031     , m_notifying(false)
0032     , m_handle()
0033     , m_MTU()
0034     , m_service(service)
0035 {
0036     m_bluezGattCharacteristic = new BluezGattCharacteristic(Strings::orgBluez(), path, DBusConnection::orgBluez(), this);
0037 
0038     init(properties);
0039 }
0040 
0041 void GattCharacteristicRemotePrivate::init(const QVariantMap &properties)
0042 {
0043     m_dbusProperties = new DBusProperties(Strings::orgBluez(), m_bluezGattCharacteristic->path(),
0044                                           DBusConnection::orgBluez(), this);
0045 
0046     // Init properties
0047     m_uuid = properties.value(QStringLiteral("UUID")).toString();
0048     m_value = properties.value(QStringLiteral("Value")).toByteArray();
0049     m_writeAcquired = properties.value(QStringLiteral("WriteAcquired")).toBool();
0050     m_notifyAcquired = properties.value(QStringLiteral("NotifyAcquired")).toBool();
0051     m_notifying = properties.value(QStringLiteral("Notifying")).toBool();
0052     m_flags = properties.value(QStringLiteral("Flags")).toStringList();
0053     m_handle = properties.value(QStringLiteral("Handle")).value<quint16>();
0054     m_MTU = properties.value(QStringLiteral("MTU")).value<quint16>();
0055 }
0056 
0057 void GattCharacteristicRemotePrivate::interfacesAdded(const QString &path, const QVariantMapMap &interfaces)
0058 {
0059     bool changed = false;
0060     QVariantMapMap::const_iterator it;
0061 
0062     for (it = interfaces.constBegin(); it != interfaces.constEnd(); ++it) {
0063         if (it.key() == Strings::orgBluezGattDescriptor1()) {
0064             addGattDescriptor(path,it.value());
0065             changed = true;
0066         }
0067     }
0068 
0069     if (changed) {
0070         Q_EMIT q.lock().data()->characteristicChanged(q.toStrongRef());
0071     }
0072 }
0073 
0074 void GattCharacteristicRemotePrivate::interfacesRemoved(const QString &path, const QStringList &interfaces)
0075 {
0076     Q_UNUSED(path)
0077     bool changed = false;
0078 
0079     for (auto& interface : interfaces) {
0080         if (interface == Strings::orgBluezGattDescriptor1()) {
0081             removeGattDescriptor(path);
0082             changed = true;
0083         }
0084     }
0085 
0086     if (changed) {        
0087         Q_EMIT q.lock().data()->characteristicChanged(q.toStrongRef());
0088     }
0089 }
0090 
0091 void GattCharacteristicRemotePrivate::addGattDescriptor(const QString &gattDescriptorPath, const QVariantMap &properties)
0092 {
0093     // Check if we have the right path
0094     if (m_bluezGattCharacteristic->path() != properties.value(QStringLiteral("Characteristic")).value<QDBusObjectPath>().path()) {
0095         return;
0096     }
0097 
0098     GattCharacteristicRemotePtr characteristic = GattCharacteristicRemotePtr(this->q);
0099 
0100     if (!characteristic) {
0101         return;
0102     }
0103 
0104     GattDescriptorRemotePtr gattDescriptor = GattDescriptorRemotePtr(new GattDescriptorRemote(gattDescriptorPath, properties, characteristic));
0105     gattDescriptor->d->q = gattDescriptor.toWeakRef();
0106     m_descriptors.append(gattDescriptor);
0107 
0108     Q_EMIT characteristic->gattDescriptorAdded(gattDescriptor);
0109     Q_EMIT characteristic->descriptorsChanged(m_descriptors);
0110 
0111     // Connections    
0112     connect(gattDescriptor.data(),&GattDescriptorRemote::descriptorChanged,q.lock().data(),&GattCharacteristicRemote::gattDescriptorChanged);
0113 }
0114 
0115 void GattCharacteristicRemotePrivate::removeGattDescriptor(const QString &gattDescriptorPath)
0116 {
0117     GattCharacteristicRemotePtr characteristic = GattCharacteristicRemotePtr(this->q);
0118 
0119     if (!characteristic) {
0120         return;
0121     }
0122 
0123     GattDescriptorRemotePtr gattDescriptor = nullptr;
0124     for (int i=0; i < characteristic->descriptors().size(); ++i) {
0125         if (characteristic->descriptors().at(i)->ubi() == gattDescriptorPath) {
0126             gattDescriptor = characteristic->descriptors().at(i);
0127         }
0128     }
0129 
0130     if (gattDescriptor == nullptr) {
0131         return;
0132     }
0133 
0134     m_descriptors.removeOne(gattDescriptor);
0135 
0136     Q_EMIT characteristic->gattDescriptorRemoved(gattDescriptor);
0137     Q_EMIT characteristic->descriptorsChanged(m_descriptors);
0138 
0139     // Connections    
0140     disconnect(gattDescriptor.data(),&GattDescriptorRemote::descriptorChanged,q.lock().data(),&GattCharacteristicRemote::gattDescriptorChanged);
0141 }
0142 
0143 QDBusPendingReply<> GattCharacteristicRemotePrivate::setDBusProperty(const QString &name, const QVariant &value)
0144 {
0145     return m_dbusProperties->Set(Strings::orgBluezGattCharacteristic1(), name, QDBusVariant(value));
0146 }
0147 
0148 void GattCharacteristicRemotePrivate::propertiesChanged(const QString &path, const QString &interface, const QVariantMap &changed, const QStringList &invalidated)
0149 {
0150     Q_UNUSED(path)
0151 
0152     if (interface == Strings::orgBluezGattDescriptor1()) {
0153         for (GattDescriptorRemotePtr descriptor : m_descriptors) {
0154             if (path.startsWith(descriptor->ubi())) {
0155                 descriptor->d->propertiesChanged(path, interface, changed, invalidated);
0156                 return;
0157             }
0158         }
0159     } else if (interface != Strings::orgBluezGattCharacteristic1()) {
0160         return;
0161     }
0162 
0163     QVariantMap::const_iterator i;
0164     for (i = changed.constBegin(); i != changed.constEnd(); ++i) {
0165         const QVariant &value = i.value();
0166         const QString &property = i.key();
0167 
0168         if (property == QLatin1String("UUID")) {
0169             PROPERTY_CHANGED(m_uuid, toString, uuidChanged);
0170         } else if (property == QLatin1String("Value")) {
0171             PROPERTY_CHANGED(m_value, toByteArray, valueChanged);
0172         } else if (property == QLatin1String("WriteAcquired")) {
0173             PROPERTY_CHANGED(m_writeAcquired, toBool, writeAcquiredChanged);
0174         } else if (property == QLatin1String("NotifyAcquired")) {
0175             PROPERTY_CHANGED(m_writeAcquired, toBool, writeAcquiredChanged);
0176         } else if (property == QLatin1String("Notifying")) {
0177             PROPERTY_CHANGED(m_notifying, toBool, notifyingChanged);
0178         } else if (property == QLatin1String("Flags")) {
0179             PROPERTY_CHANGED2(m_flags, value.toStringList(), flagsChanged);
0180         } else if (property == QLatin1String("Handle")) {
0181             PROPERTY_CHANGED2(m_handle, value.value<quint16>(), handleChanged);
0182         } else if (property == QLatin1String("MTU")) {
0183             PROPERTY_CHANGED2(m_MTU, value.value<quint16>(), MTUChanged);
0184         }
0185     }
0186 
0187     for (auto& property : invalidated) {
0188         if (property == QLatin1String("UUID")) {
0189             PROPERTY_INVALIDATED(m_uuid, QString(), uuidChanged);
0190         } else if (property == QLatin1String("Value")) {
0191             PROPERTY_INVALIDATED(m_value, QByteArray(), valueChanged);
0192         } else if (property == QLatin1String("WriteAcquired")) {
0193             PROPERTY_INVALIDATED(m_writeAcquired, false, writeAcquiredChanged);
0194         } else if (property == QLatin1String("NotifyAcquired")) {
0195             PROPERTY_INVALIDATED(m_writeAcquired, false, writeAcquiredChanged);
0196         } else if (property == QLatin1String("Notifying")) {
0197             PROPERTY_INVALIDATED(m_notifying, false, notifyingChanged);
0198         } else if (property == QLatin1String("Flags")) {
0199             PROPERTY_INVALIDATED(m_flags, QStringList(), flagsChanged);
0200         } else if (property == QLatin1String("Handle")) {
0201             PROPERTY_INVALIDATED(m_handle, quint16(), handleChanged);
0202         } else if (property == QLatin1String("MTU")) {
0203             PROPERTY_INVALIDATED(m_MTU, quint16(), MTUChanged);
0204         }
0205     }
0206 
0207     q.lock().data()->characteristicChanged(q.toStrongRef());
0208 }
0209 
0210 } // namespace BluezQt
0211 
0212 #include "moc_gattcharacteristicremote_p.cpp"