File indexing completed on 2024-06-09 05:46:35
0001 /* 0002 * Copyright 2019 Eike Hein <hein@kde.org> 0003 * 0004 * This library is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU Lesser General Public 0006 * License as published by the Free Software Foundation; either 0007 * version 2.1 of the License, or (at your option) version 3, or any 0008 * later version accepted by the membership of KDE e.V. (or its 0009 * successor approved by the membership of KDE e.V.), which shall 0010 * act as a proxy defined in Section 6 of version 3 of the license. 0011 * 0012 * This library is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 * Lesser General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU Lesser General Public 0018 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 0019 */ 0020 0021 #include "parrotplugin.h" 0022 #include "debug.h" 0023 #include "parrotprotocol.h" 0024 #include "parrotvehicle.h" 0025 0026 #include <KLocalizedString> 0027 #include <KPluginFactory> 0028 0029 #include <QJsonDocument> 0030 0031 #ifndef Q_OS_ANDROID 0032 #include <kdnssd_version.h> 0033 #if KDNSSD_VERSION >= QT_VERSION_CHECK(5, 84, 0) 0034 #include <KDNSSD/RemoteService> 0035 #include <KDNSSD/ServiceBrowser> 0036 #else 0037 #include <DNSSD/RemoteService> 0038 #include <DNSSD/ServiceBrowser> 0039 #endif 0040 #else 0041 #include "QtZeroConf/qzeroconf.h" 0042 #include "QtZeroConf/qzeroconfservice.h" 0043 #endif 0044 0045 ParrotPlugin::ParrotPlugin(QObject *parent, const QVariantList & /* args */) 0046 : Kirogi::VehicleSupportPlugin(parent) 0047 #ifndef Q_OS_ANDROID 0048 , m_bebop2Browser(nullptr) 0049 , m_anafiBrowser(nullptr) 0050 #endif 0051 { 0052 qCDebug(KIROGI_VEHICLESUPPORT_PARROT) << "Parrot Vehicle Support Plugin initializing ..."; 0053 0054 qRegisterMetaType<Parrot::Command>("Parrot::Command"); 0055 qRegisterMetaType<ParrotCommand>(); 0056 0057 class AbstractMDNSService 0058 { 0059 public: 0060 #ifndef Q_OS_ANDROID 0061 AbstractMDNSService(KDNSSD::RemoteService::Ptr service) 0062 { 0063 name = service->serviceName(); 0064 host = service->hostName(); 0065 port = service->port(); 0066 0067 if (!service->textData().isEmpty()) { 0068 data = QJsonDocument::fromJson(service->textData().firstKey().toUtf8()); 0069 } 0070 } 0071 #else 0072 AbstractMDNSService(QZeroConfService service) 0073 { 0074 name = service->name(); 0075 host = service->host(); 0076 port = service->port(); 0077 0078 if (!service->txt().isEmpty()) { 0079 data = QJsonDocument::fromJson(service->txt().firstKey()); 0080 } 0081 } 0082 #endif 0083 0084 QString name; 0085 QString host; 0086 uint port; 0087 QJsonDocument data; 0088 }; 0089 0090 auto serviceAdded = [this](AbstractMDNSService *service, ParrotVehicle::Type type) { 0091 if (!m_vehicles.contains(service->name)) { 0092 QString productSerial; 0093 0094 if (!service->data.isNull() || !service->data.isObject()) { 0095 productSerial = service->data.object().value(QStringLiteral("device_id")).toString(); 0096 } else { 0097 qCWarning(KIROGI_VEHICLESUPPORT_PARROT) << "mDNS service has no text data. We will be unable to decode the product serial."; 0098 } 0099 0100 if (productSerial.isEmpty()) { 0101 qCWarning(KIROGI_VEHICLESUPPORT_PARROT) << "Unable to decode product serial from mDNS service text data."; 0102 } 0103 0104 qCDebug(KIROGI_VEHICLESUPPORT_PARROT) << "Discovered new vehicle at:" << QString("%1:%2.").arg(service->name, QString::number(service->port)); 0105 0106 ParrotVehicle *vehicle = new ParrotVehicle(type, service->host, service->port, productSerial, this); 0107 m_vehicles.insert(service->name, vehicle); 0108 emit vehicleAdded(vehicle); 0109 0110 vehicle->connectToVehicle(); 0111 } else { 0112 qCWarning(KIROGI_VEHICLESUPPORT_PARROT) << "Already have a vehicle for:" << service->name; 0113 } 0114 }; 0115 0116 auto serviceRemoved = [this](AbstractMDNSService *service) { 0117 qCDebug(KIROGI_VEHICLESUPPORT_PARROT) << "Removing vehicle at" << QString("%1:%2.").arg(service->host, QString::number(service->port)); 0118 0119 Kirogi::AbstractVehicle *vehicle = m_vehicles.value(service->name); 0120 0121 m_vehicles.remove(service->name); 0122 emit vehicleRemoved(vehicle); 0123 0124 delete vehicle; 0125 }; 0126 0127 #ifndef Q_OS_ANDROID 0128 m_bebop2Browser = new KDNSSD::ServiceBrowser(QStringLiteral("_arsdk-090c._udp"), true); 0129 m_anafiBrowser = new KDNSSD::ServiceBrowser(QStringLiteral("_arsdk-0914._udp"), true); 0130 0131 if (m_bebop2Browser->isAvailable() != KDNSSD::ServiceBrowser::Working) { 0132 qCWarning(KIROGI_VEHICLESUPPORT_PARROT) << "KDNSSD mDNS browsing (Bebop 2) unavailable:" << m_bebop2Browser->isAvailable(); 0133 } 0134 0135 if (m_anafiBrowser->isAvailable() != KDNSSD::ServiceBrowser::Working) { 0136 qCWarning(KIROGI_VEHICLESUPPORT_PARROT) << "KDNSSD mDNS browsing (Anafi) unavailable:" << m_anafiBrowser->isAvailable(); 0137 } 0138 0139 QObject::connect(m_bebop2Browser, &KDNSSD::ServiceBrowser::serviceAdded, this, [serviceAdded](KDNSSD::RemoteService::Ptr service) { 0140 serviceAdded(new AbstractMDNSService(service), ParrotVehicle::Bebop2); 0141 }); 0142 QObject::connect(m_bebop2Browser, &KDNSSD::ServiceBrowser::serviceRemoved, this, [serviceRemoved](KDNSSD::RemoteService::Ptr service) { 0143 serviceRemoved(new AbstractMDNSService(service)); 0144 }); 0145 QObject::connect(m_anafiBrowser, &KDNSSD::ServiceBrowser::serviceAdded, this, [serviceAdded](KDNSSD::RemoteService::Ptr service) { 0146 serviceAdded(new AbstractMDNSService(service), ParrotVehicle::Anafi); 0147 }); 0148 QObject::connect(m_anafiBrowser, &KDNSSD::ServiceBrowser::serviceRemoved, this, [serviceRemoved](KDNSSD::RemoteService::Ptr service) { 0149 serviceRemoved(new AbstractMDNSService(service)); 0150 }); 0151 0152 m_bebop2Browser->startBrowse(); 0153 m_anafiBrowser->startBrowse(); 0154 #else 0155 QZeroConf *bebop2Browser = new QZeroConf(this); 0156 QZeroConf *anafiBrowser = new QZeroConf(this); 0157 0158 QObject::connect(bebop2Browser, &QZeroConf::serviceAdded, this, [serviceAdded](QZeroConfService service) { 0159 serviceAdded(new AbstractMDNSService(service), ParrotVehicle::Bebop2); 0160 }); 0161 QObject::connect(bebop2Browser, &QZeroConf::serviceRemoved, this, [serviceRemoved](QZeroConfService service) { 0162 serviceRemoved(new AbstractMDNSService(service)); 0163 }); 0164 QObject::connect(bebop2Browser, &QZeroConf::error, this, [](QZeroConf::error_t error) { 0165 qCWarning(KIROGI_VEHICLESUPPORT_PARROT) << "QZeroConf mDNS browsing (Bebop 2) error:" << error; 0166 }); 0167 QObject::connect(anafiBrowser, &QZeroConf::serviceAdded, this, [serviceAdded](QZeroConfService service) { 0168 serviceAdded(new AbstractMDNSService(service), ParrotVehicle::Anafi); 0169 }); 0170 QObject::connect(anafiBrowser, &QZeroConf::serviceRemoved, this, [serviceRemoved](QZeroConfService service) { 0171 serviceRemoved(new AbstractMDNSService(service)); 0172 }); 0173 QObject::connect(anafiBrowser, &QZeroConf::error, this, [](QZeroConf::error_t error) { 0174 qCWarning(KIROGI_VEHICLESUPPORT_PARROT) << "QZeroConf mDNS browsing (Anafi) error:" << error; 0175 }); 0176 0177 bebop2Browser->startBrowser(QStringLiteral("_arsdk-090c._udp")); 0178 anafiBrowser->startBrowser(QStringLiteral("_arsdk-0914._udp")); 0179 #endif 0180 } 0181 0182 ParrotPlugin::~ParrotPlugin() 0183 { 0184 #ifndef Q_OS_ANDROID 0185 delete m_bebop2Browser; 0186 delete m_anafiBrowser; 0187 #endif 0188 0189 qCDebug(KIROGI_VEHICLESUPPORT_PARROT) << "Parrot Vehicle Support Plugin unloaded."; 0190 } 0191 0192 QList<Kirogi::AbstractVehicle *> ParrotPlugin::vehicles() const 0193 { 0194 return m_vehicles.values(); 0195 } 0196 0197 K_PLUGIN_CLASS_WITH_JSON(ParrotPlugin, "kirogiparrotplugin.json") 0198 0199 #include "parrotplugin.moc"