Line data Source code
1 : // SPDX-FileCopyrightText: 2022-2023 Paul Colby <git@colby.id.au> 2 : // SPDX-License-Identifier: LGPL-3.0-or-later 3 : 4 : /*! 5 : * \file 6 : * Defines the DeviceInfoService and DeviceInfoServicePrivate classes. 7 : */ 8 : 9 : #include <qtpokit/deviceinfoservice.h> 10 : #include "deviceinfoservice_p.h" 11 : 12 : #include <QtEndian> 13 : 14 : /*! 15 : * \class DeviceInfoService 16 : * 17 : * The DeviceInfoService class accesses the `Device Info` service of Pokit devices. 18 : */ 19 : 20 : /// UUID of the "Device Info" service. 21 : const QBluetoothUuid DeviceInfoService:: 22 : serviceUuid(QBluetoothUuid::ServiceClassUuid::DeviceInformation); 23 : 24 : /// \struct DeviceInfoService::CharacteristicUuids 25 : /// \brief Characteristics available via the `Device Info` service. 26 : 27 : /// UUID of the `Device Info` service's `xxx` characterstic. 28 : const QBluetoothUuid DeviceInfoService::CharacteristicUuids:: 29 : manufacturerName(QBluetoothUuid::CharacteristicType::ManufacturerNameString); 30 : 31 : /// UUID of the `Device Info` service's `xxx` characterstic. 32 : const QBluetoothUuid DeviceInfoService::CharacteristicUuids:: 33 : modelNumber(QBluetoothUuid::CharacteristicType::ModelNumberString); 34 : 35 : /// UUID of the `Device Info` service's `xxx` characterstic. 36 : const QBluetoothUuid DeviceInfoService::CharacteristicUuids:: 37 : hardwareRevision(QBluetoothUuid::CharacteristicType::HardwareRevisionString); 38 : 39 : /// UUID of the `Device Info` service's `xxx` characterstic. 40 : const QBluetoothUuid DeviceInfoService::CharacteristicUuids:: 41 : firmwareRevision(QBluetoothUuid::CharacteristicType::FirmwareRevisionString); 42 : 43 : /// UUID of the `Device Info` service's `xxx` characterstic. 44 : const QBluetoothUuid DeviceInfoService::CharacteristicUuids:: 45 : softwareRevision(QBluetoothUuid::CharacteristicType::SoftwareRevisionString); 46 : 47 : /*! 48 : * Constructs a new Pokit service with \a parent. 49 : */ 50 564 : DeviceInfoService::DeviceInfoService(QLowEnergyController * const controller, QObject * parent) 51 564 : : AbstractPokitService(new DeviceInfoServicePrivate(controller, this), parent) 52 : { 53 : 54 564 : } 55 : 56 : /*! 57 : * \cond internal 58 : * Constructs a new Pokit service with \a parent, and private implementation \a d. 59 : */ 60 0 : DeviceInfoService::DeviceInfoService( 61 0 : DeviceInfoServicePrivate * const d, QObject * const parent) 62 0 : : AbstractPokitService(d, parent) 63 : { 64 : 65 0 : } 66 : /// \endcond 67 : 68 : /*! 69 : * Destroys this DeviceInfoService object. 70 : */ 71 234 : DeviceInfoService::~DeviceInfoService() 72 : { 73 : 74 234 : } 75 : 76 18 : bool DeviceInfoService::readCharacteristics() 77 : { 78 12 : const bool r1 = readFirmwareRevisionCharacteristic(); 79 12 : const bool r2 = readHardwareRevisionCharacteristic(); 80 12 : const bool r3 = readSoftwareRevisionCharacteristic(); 81 12 : const bool r4 = readManufacturerCharacteristics(); 82 12 : const bool r5 = readModelNumberCharacteristic(); 83 18 : return (r1 && r2 && r3 && r4 && r5); 84 : } 85 : 86 : /*! 87 : * Read the `Device Info` service's `Firmware Revision` characteristic. 88 : * 89 : * Returns `true` is the read request is succesfully queued, `false` otherwise (ie if the 90 : * underlying controller it not yet connected to the Pokit device, or the device's services have 91 : * not yet been discovered). 92 : * 93 : * Emits firmwareRevisionRead() if/when the characteristic has been read successfully. 94 : */ 95 30 : bool DeviceInfoService::readFirmwareRevisionCharacteristic() 96 : { 97 : Q_D(DeviceInfoService); 98 36 : return d->readCharacteristic(CharacteristicUuids::firmwareRevision); 99 : } 100 : 101 : /*! 102 : * Read the `Device Info` service's `Hardware Revision` characteristic. 103 : * 104 : * Returns `true` is the read request is succesfully queued, `false` otherwise (ie if the 105 : * underlying controller it not yet connected to the Pokit device, or the device's services have 106 : * not yet been discovered). 107 : * 108 : * Emits hardwareRevisionRead() if/when the characteristic has been read successfully. 109 : */ 110 30 : bool DeviceInfoService::readHardwareRevisionCharacteristic() 111 : { 112 : Q_D(DeviceInfoService); 113 36 : return d->readCharacteristic(CharacteristicUuids::hardwareRevision); 114 : } 115 : 116 : /*! 117 : * Read the `Device Info` service's `Manufacturer Name` characteristic. 118 : * 119 : * Returns `true` is the read request is succesfully queued, `false` otherwise (ie if the 120 : * underlying controller it not yet connected to the Pokit device, or the device's services have 121 : * not yet been discovered). 122 : * 123 : * Emits manufacturerNameRead() if/when the characteristic has been read successfully. 124 : */ 125 30 : bool DeviceInfoService::readManufacturerCharacteristics() 126 : { 127 : Q_D(DeviceInfoService); 128 36 : return d->readCharacteristic(CharacteristicUuids::manufacturerName); 129 : } 130 : 131 : /*! 132 : * Read the `Device Info` service's `Model Number` characteristic. 133 : * 134 : * Returns `true` is the read request is succesfully queued, `false` otherwise (ie if the 135 : * underlying controller it not yet connected to the Pokit device, or the device's services have 136 : * not yet been discovered). 137 : * 138 : * Emits modelNumberRead() if/when the characteristic has been read successfully. 139 : */ 140 30 : bool DeviceInfoService::readModelNumberCharacteristic() 141 : { 142 : Q_D(DeviceInfoService); 143 36 : return d->readCharacteristic(CharacteristicUuids::modelNumber); 144 : } 145 : 146 : /*! 147 : * Read the `Device Info` service's `Software Revision` characteristic. 148 : * 149 : * Returns `true` is the read request is succesfully queued, `false` otherwise (ie if the 150 : * underlying controller it not yet connected to the Pokit device, or the device's services have 151 : * not yet been discovered). 152 : * 153 : * Emits softwareRevisionRead() if/when the characteristic has been read successfully. 154 : */ 155 30 : bool DeviceInfoService::readSoftwareRevisionCharacteristic() 156 : { 157 : Q_D(DeviceInfoService); 158 36 : return d->readCharacteristic(CharacteristicUuids::softwareRevision); 159 : } 160 : 161 : /*! 162 : * Returns the most recent value of the `Device Info` service's `Manufacturer Name` characteristic. 163 : * 164 : * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is 165 : * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a 166 : * null QString is returned. 167 : */ 168 330 : QString DeviceInfoService::manufacturer() const 169 : { 170 : Q_D(const DeviceInfoService); 171 : const QLowEnergyCharacteristic characteristic = 172 330 : d->getCharacteristic(CharacteristicUuids::manufacturerName); 173 660 : return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString(); 174 330 : } 175 : 176 : /*! 177 : * Returns the most recent value of the `Device Info` service's `Model Number` characteristic. 178 : * 179 : * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is 180 : * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a 181 : * null QString is returned. 182 : */ 183 330 : QString DeviceInfoService::modelNumber() const 184 : { 185 : Q_D(const DeviceInfoService); 186 : const QLowEnergyCharacteristic characteristic = 187 330 : d->getCharacteristic(CharacteristicUuids::modelNumber); 188 660 : return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString(); 189 330 : } 190 : 191 : /*! 192 : * Returns the most recent value of the `Device Info` service's `Hardware Revision` characteristic. 193 : * 194 : * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is 195 : * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a 196 : * null QString is returned. 197 : */ 198 330 : QString DeviceInfoService::hardwareRevision() const 199 : { 200 : Q_D(const DeviceInfoService); 201 : const QLowEnergyCharacteristic characteristic = 202 330 : d->getCharacteristic(CharacteristicUuids::hardwareRevision); 203 660 : return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString(); 204 330 : } 205 : 206 : /*! 207 : * Returns the most recent value of the `Device Info` service's `Firmware Revision` characteristic. 208 : * 209 : * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is 210 : * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a 211 : * null QString is returned. 212 : */ 213 330 : QString DeviceInfoService::firmwareRevision() const 214 : { 215 : Q_D(const DeviceInfoService); 216 : const QLowEnergyCharacteristic characteristic = 217 330 : d->getCharacteristic(CharacteristicUuids::firmwareRevision); 218 660 : return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString(); 219 330 : } 220 : 221 : /*! 222 : * Returns the most recent value of the `Device Info` service's `Software Revision` characteristic. 223 : * 224 : * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is 225 : * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a 226 : * null QString is returned. 227 : */ 228 330 : QString DeviceInfoService::softwareRevision() const 229 : { 230 : Q_D(const DeviceInfoService); 231 : const QLowEnergyCharacteristic characteristic = 232 330 : d->getCharacteristic(CharacteristicUuids::softwareRevision); 233 660 : return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString(); 234 330 : } 235 : 236 : /*! 237 : * \fn DeviceInfoService::manufacturerRead 238 : * 239 : * This signal is emitted when the `Manufacturer Name` characteristic has been read successfully. 240 : * 241 : * \see readManufacturerCharacteristic 242 : * \see manufacturer 243 : */ 244 : 245 : /*! 246 : * \fn DeviceInfoService::modelNumberRead 247 : * 248 : * This signal is emitted when the `Model Number` characteristic has been read successfully. 249 : * 250 : * \see readModelNumberCharacteristic 251 : * \see modelNumber 252 : */ 253 : 254 : /*! 255 : * \fn DeviceInfoService::hardwareRevisionRead 256 : * 257 : * This signal is emitted when the `Hardware Revision` characteristic has been read successfully. 258 : * 259 : * \see readHardwareRevisionCharacteristic 260 : * \see hardwareRevision 261 : */ 262 : 263 : /*! 264 : * \fn DeviceInfoService::firmwareRevisionRead 265 : * 266 : * This signal is emitted when the `Firmware Revision` characteristic has been read successfully. 267 : * 268 : * \see readFirmwareRevisionCharacteristic 269 : * \see firmwareRevision 270 : */ 271 : 272 : /*! 273 : * \fn DeviceInfoService::softwareRevisionRead 274 : * 275 : * This signal is emitted when the `Software Revision` characteristic has been read successfully. 276 : * 277 : * \see readSoftwareRevisionCharacteristic 278 : * \see softwareRevision 279 : */ 280 : 281 : /*! 282 : * \cond internal 283 : * \class DeviceInfoServicePrivate 284 : * 285 : * The DeviceInfoServicePrivate class provides private implementation for DeviceInfoService. 286 : */ 287 : 288 : /*! 289 : * \internal 290 : * Constructs a new DeviceInfoServicePrivate object with public implementation \a q. 291 : */ 292 396 : DeviceInfoServicePrivate::DeviceInfoServicePrivate( 293 564 : QLowEnergyController * controller, DeviceInfoService * const q) 294 564 : : AbstractPokitServicePrivate(DeviceInfoService::serviceUuid, controller, q) 295 : { 296 : 297 396 : } 298 : 299 : /*! 300 : * Implements AbstractPokitServicePrivate::characteristicRead to parse \a value, then emit a 301 : * specialised signal, for each supported \a characteristic. 302 : */ 303 18 : void DeviceInfoServicePrivate::characteristicRead(const QLowEnergyCharacteristic &characteristic, 304 : const QByteArray &value) 305 : { 306 18 : AbstractPokitServicePrivate::characteristicRead(characteristic, value); 307 : 308 : Q_Q(DeviceInfoService); 309 18 : if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::manufacturerName) { 310 0 : const QString name = QString::fromUtf8(value); 311 0 : qCDebug(lc).noquote() << tr(R"(Manufacturer name: "%1")").arg(name); 312 0 : emit q->manufacturerRead(name); 313 : return; 314 0 : } 315 : 316 18 : if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::modelNumber) { 317 0 : const QString model = QString::fromUtf8(value); 318 0 : qCDebug(lc).noquote() << tr(R"(Model number: "%1")").arg(model); 319 0 : emit q->modelNumberRead(model); 320 : return; 321 0 : } 322 : 323 18 : if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::hardwareRevision) { 324 0 : const QString revision = QString::fromUtf8(value); 325 0 : qCDebug(lc).noquote() << tr(R"(Hardware revision: "%1")").arg(revision); 326 0 : emit q->hardwareRevisionRead(revision); 327 : return; 328 0 : } 329 : 330 18 : if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::firmwareRevision) { 331 0 : const QString revision = QString::fromUtf8(value); 332 0 : qCDebug(lc).noquote() << tr(R"(Firmware revision: "%1")").arg(revision); 333 0 : emit q->firmwareRevisionRead(revision); 334 : return; 335 0 : } 336 : 337 18 : if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::softwareRevision) { 338 0 : const QString revision = QString::fromUtf8(value); 339 0 : qCDebug(lc).noquote() << tr(R"(Software revision: "%1")").arg(revision); 340 0 : emit q->softwareRevisionRead(revision); 341 : return; 342 0 : } 343 : 344 54 : qCWarning(lc).noquote() << tr("Unknown characteristic read for Device Info service") 345 24 : << serviceUuid << characteristic.name() << characteristic.uuid(); 346 : } 347 : 348 : /// \endcond