diff options
Diffstat (limited to 'src/metawatchbletransport.cpp')
-rw-r--r-- | src/metawatchbletransport.cpp | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/metawatchbletransport.cpp b/src/metawatchbletransport.cpp new file mode 100644 index 0000000..56039d3 --- /dev/null +++ b/src/metawatchbletransport.cpp @@ -0,0 +1,141 @@ +#include "metawatchbletransport.h" + +const GatoUUID MetaWatchBLETransport::ServiceUuid(quint16(0x8880)); +const GatoUUID MetaWatchBLETransport::InputCharacteristicUuid(quint16(0x8882)); +const GatoUUID MetaWatchBLETransport::OutputCharacteristicUuid(quint16(0x8881)); + +MetaWatchBLETransport::MetaWatchBLETransport(GatoPeripheral *peripheral, QObject *parent) : + MetaWatchTransport(parent), _dev(peripheral) +{ + connect(_dev, SIGNAL(connected()), SLOT(handleDeviceConnected())); + connect(_dev, SIGNAL(disconnected()), SLOT(handleDeviceDisconnected())); + connect(_dev, SIGNAL(servicesDiscovered()), SLOT(handleDeviceServices())); + connect(_dev, SIGNAL(characteristicsDiscovered(GatoService)), + SLOT(handleDeviceCharacteristics(GatoService))); + connect(_dev, SIGNAL(valueUpdated(GatoCharacteristic,QByteArray)), + SLOT(handleDeviceUpdate(GatoCharacteristic,QByteArray))); +} + +MetaWatchBLETransport::~MetaWatchBLETransport() +{ + disconnectDevice(); +} + +void MetaWatchBLETransport::sendMessage(quint8 type, quint8 options, const QByteArray &payload) +{ + QByteArray packet = encode(type, options, payload); + qDebug() << "Send:" << packet.toHex(); + _dev->writeValue(_out, packet); +} + +void MetaWatchBLETransport::connectDevice() +{ + qDebug() << "Trying to connect to" << _dev->address(); + _dev->connectPeripheral(); +} + +void MetaWatchBLETransport::disconnectDevice() +{ + _dev->disconnectPeripheral(); +} + +QByteArray MetaWatchBLETransport::encode(quint8 type, quint8 options, const QByteArray &payload) +{ + QByteArray packet; + + quint8 message_size = 6 + payload.size(); + packet.reserve(message_size); + + packet.append(0x01); + packet.append(message_size); + packet.append(type); + packet.append(options); + + packet.append(payload); + packet.append("\0\0", 2); // Empty CRC is OK for BLE + + return packet; +} + +bool MetaWatchBLETransport::decode(const QByteArray &packet, quint8 *type, quint8 *options, QByteArray *payload) +{ + if (packet.size() < 6) { + qWarning() << "Message too short"; + } + + if (packet.at(0) != 0x1) { + qWarning() << "Invalid packet header"; + return false; + } + + quint8 message_size = packet[1]; + if (message_size < 6 || message_size > 32 || message_size != packet.size()) { + qWarning() << "Invalid message size:" << message_size; + } + + *type = packet[2]; + *options = packet[3]; + + *payload = packet.mid(4, message_size - 6); + + // Ignore CRC on BLE: it's set to 0 by firmware. + + return true; +} + +void MetaWatchBLETransport::handleDeviceConnected() +{ + qDebug() << "MW connected"; + if (_dev->services().isEmpty()) { + qDebug() << "Trying to discover services"; + QList<GatoUUID> interesting_services; + interesting_services << ServiceUuid; + _dev->discoverServices(); + } +} + +void MetaWatchBLETransport::handleDeviceDisconnected() +{ + qDebug() << "MW disconnected"; + emit disconnected(); +} + +void MetaWatchBLETransport::handleDeviceServices() +{ + QList<GatoService> services = _dev->services(); + qDebug() << "Got" << services.size() << "services"; + foreach (const GatoService &s, services) { + if (s.uuid() == ServiceUuid) { + _dev->discoverCharacteristics(s); + } + } +} + +void MetaWatchBLETransport::handleDeviceCharacteristics(const GatoService &service) +{ + qDebug() << "Got characteristic"; + foreach (const GatoCharacteristic &c, service.characteristics()) { + if (c.uuid() == InputCharacteristicUuid) { + _in = c; + _dev->setNotification(_in, true); + } else if (c.uuid() == OutputCharacteristicUuid) { + _out = c; + } + if (!_in.isNull() && !_out.isNull()) { + emit connected(); + } + } +} + +void MetaWatchBLETransport::handleDeviceUpdate(const GatoCharacteristic &characteristic, const QByteArray &value) +{ + qDebug() << "Recv:" << value.toHex(); + quint8 type, options; + QByteArray payload; + + if (decode(value, &type, &options, &payload)) { + emit messageReceived(type, options, payload); + } else { + qWarning() << "Failed to decode message from metawatch:" << value.toHex(); + } +} |