diff --git a/BBPebbleLib/Pebble.cpp b/BBPebbleLib/Pebble.cpp index c3026ea..e43cbc9 100644 --- a/BBPebbleLib/Pebble.cpp +++ b/BBPebbleLib/Pebble.cpp @@ -5,6 +5,8 @@ * Author: James */ +#include + #include "Pebble.h" const quint8 Pebble::PEBBLE_CLIENT_VERSION = 2; @@ -38,31 +40,48 @@ void Pebble::onDisconnect() void Pebble::onDataReceived(QBluetoothSocket &bt_socket) { - QDataStream in(&bt_socket); - - if (this->payloadSize == 0) { - if (bt_socket.bytesAvailable() < (int)2*sizeof(quint16)) { + static const int header_length = (int)2*sizeof(quint16); + + while (bt_socket.bytesAvailable() >= header_length) { + // Take a look at the header, but do not remove it from the socket input buffer. + // We will only remove it once we're sure the entire packet is in the buffer. + uchar header[header_length]; + bt_socket.peek(reinterpret_cast(header), header_length); + + quint16 message_length = qFromBigEndian(&header[0]); + quint16 endpoint = qFromBigEndian(&header[2]); + + // Sanity checks on the message_length + if (message_length == 0) { + qDebug() << "received empty message"; + bt_socket.read(header_length); // skip this header + continue; // check if there are additional headers. + } else if (message_length > 8 * 1024) { + // Protocol does not allow messages more than 8K long, seemingly. + qDebug() << "received message size too long: " << message_length; + bt_socket.readAll(); // drop entire input buffer return; } - in >> this->payloadSize; - in >> this->endPoint; - } - if(bt_socket.bytesAvailable() < this->payloadSize){ - return; - } - char buffer[this->payloadSize]; - in.readRawData(buffer, this->payloadSize); - QByteArray payload(buffer); + // Now wait for the entire message + if (bt_socket.bytesAvailable() < header_length + message_length) { + qDebug() << "incomplete msg body in read buffer"; + return; // try again once more data comes in + } - qDebug() << "Received data. Endpoint : " << endPoint << " Payload Size : " << payloadSize << " HEX : " << payload.toHex() << "STR : " << QString(payload); + // We can now safely remove the header from the input buffer, + // as we know the entire message is in the input buffer. + bt_socket.read(header_length); - emit onDataReadFinished(endPoint, payload); + // Now read the rest of the message + QByteArray data = bt_socket.read(message_length); - this->payloadSize = 0; - this->endPoint = 0; + qDebug() << "<<<< received data. Endpoint : " << endpoint << " Payload Size : " << data.size() << " HEX : " << data.toHex() << "STR : " << QString(data); + + emit onDataReadFinished(endpoint, data); - onDataReceived(bt_socket); + onDataReceived(bt_socket); + } } void Pebble::onDataReadFinished(quint16 endPoint, const QByteArray &payload){ @@ -88,6 +107,9 @@ void Pebble::sendDataToPebble(quint16 endPoint, const QByteArray &payload) const in << (quint16)endPoint; finalData.append(payload); in.setByteOrder(QDataStream::BigEndian); + + qDebug() << ">>>> sent data. Endpoint : " << endPoint << " Payload Size : " << payload.size() << " HEX : " << payload.toHex() << "STR : " << QString(payload); + this->bt_device->sendData(finalData); } diff --git a/README.md b/README.md index 33d4c3a..9c438d3 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,12 @@ I am expecting (hopefully) to not be the only one to contribute to this project * Get information of an application * Displaying Weather on a watchface * Much much much more + +### Related Work +Thanks to all the other projects which achieved communication with the Pebble watch and inspired/helped this project, namely: +* https://github.com/smokku/pebble +* https://github.com/Hexxeh/libpebble +* https://github.com/pebble/libpebble2 +* https://github.com/Keboo/PebbleSharp +* https://github.com/DouweM/pebblewatch +* https://github.com/barometz/flint