Improve behavior on connection loss

master
Michael Zanetti 2019-10-16 00:03:31 +02:00
parent 4fe6a91771
commit 796a27e0ff
2 changed files with 48 additions and 23 deletions

View File

@ -86,6 +86,27 @@ EqivaBluetooth::EqivaBluetooth(BluetoothLowEnergyManager *bluetoothManager, cons
m_refreshTimer.setInterval(5000);
m_refreshTimer.setSingleShot(true);
connect(&m_refreshTimer, &QTimer::timeout, this, &EqivaBluetooth::sendDate);
m_reconnectTimer.setSingleShot(true);
connect(&m_reconnectTimer, &QTimer::timeout, this, [this](){
qCDebug(dcEQ3()) << m_name << "Trying to reconnect";
m_reconnectAttempt++;
m_bluetoothDevice->connectDevice();
});
m_commandTimeout.setInterval(3000);
m_commandTimeout.setSingleShot(true);
connect(&m_commandTimeout, &QTimer::timeout, this, [this](){
// Put current command back to the queue as it didn't succeed
qCWarning(dcEQ3()) << m_name << "Command timed out:" << m_currentCommand.id << m_currentCommand.name << "Putting command back to queue";
m_commandQueue.prepend(m_currentCommand);
m_currentCommand = Command();
// and reset the connection
if (m_bluetoothDevice->connected()) {
m_bluetoothDevice->disconnectDevice();
}
});
}
EqivaBluetooth::~EqivaBluetooth()
@ -208,24 +229,19 @@ bool EqivaBluetooth::batteryCritical() const
void EqivaBluetooth::controllerStateChanged(const QLowEnergyController::ControllerState &state)
{
qCDebug(dcEQ3()) << m_name << "Bluetooth device state changed:" << state;
if (state == QLowEnergyController::ConnectingState) {
// Make sure the reconnect timer is stopped when we're starting a new attempt
m_reconnectTimer.stop();
return;
}
if (state == QLowEnergyController::UnconnectedState) {
int delay = qMin(m_reconnectAttempt, 30);
qWarning(dcEQ3()) << m_name << "Eqiva device disconnected. Reconnecting in" << delay << "sec";
m_available = false;
emit availableChanged();
if (m_currentCommand.id != -1) {
qCDebug(dcEQ3()) << m_name << "Putting command" << m_currentCommand.id << m_currentCommand.name << "back to queue";
m_commandQueue.prepend(m_currentCommand);
m_currentCommand = Command();
}
QTimer::singleShot(delay * 1000, this, [this](){
qCDebug(dcEQ3()) << m_name << "Trying to reconnect";
m_reconnectAttempt++;
m_bluetoothDevice->connectDevice();
});
m_reconnectTimer.start(delay * 1000);
}
if (state != QLowEnergyController::DiscoveredState) {
@ -293,7 +309,10 @@ void EqivaBluetooth::controllerStateChanged(const QLowEnergyController::Controll
});
connect(m_eqivaService, &QLowEnergyService::characteristicWritten, this, [this](const QLowEnergyCharacteristic &info, const QByteArray &value){
qCDebug(dcEQ3()) << m_name << "Characteristic written:" << info.name() << info.uuid() << value.toHex();
Q_UNUSED(info) // We're only writing one...
Q_UNUSED(value)
qCDebug(dcEQ3()) << m_name << "Command sent:" << m_currentCommand.id << m_currentCommand.name;
m_commandTimeout.stop();
emit commandResult(m_currentCommand.id, true);
m_currentCommand.id = -1;
processCommandQueue();
@ -333,14 +352,19 @@ void EqivaBluetooth::serviceStateChanged(QLowEnergyService::ServiceState newStat
// Enable notifications
QLowEnergyCharacteristic characteristic = m_eqivaService->characteristic(notificationCharacteristicUuid);
QLowEnergyDescriptor notificationDescriptor = characteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
m_eqivaService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0000"));
// m_eqivaService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0000"));
m_eqivaService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
}
void EqivaBluetooth::characteristicChanged(const QLowEnergyCharacteristic &info, const QByteArray &value)
{
qCDebug(dcEQ3()) << m_name << "Notification received" << info.uuid() << value.toHex();
// qCDebug(dcEQ3()) << m_name << "Notification received" << info.uuid() << value.toHex();
if (info.uuid() != notificationCharacteristicUuid) {
qCWarning(dcEQ3()) << m_name << "Received a notification from a characteristic we did't expect:" << info.uuid() << value.toHex();
return;
}
m_refreshTimer.start();
QByteArray data(value);
@ -442,20 +466,18 @@ void EqivaBluetooth::sendDate()
stream << static_cast<quint8>(now.time().second());
// Example: 03130117172315 -> 03YYMMDDHHMMSS
qCDebug(dcEQ3()) << m_name << "Updating date on device...";
// qCDebug(dcEQ3()) << m_name << "Updating date on device...";
enqueue("SetDate", data);
}
int EqivaBluetooth::enqueue(const QString &name, const QByteArray &data)
{
static int nextId = 0;
Command cmd;
cmd.name = name;
cmd.id = nextId++;
cmd.id = m_nextCommandId++;
cmd.data = data;
m_commandQueue.append(cmd);
qCDebug(dcEQ3()) << m_name << "Enqueued command" << cmd.name << "Command queue length:" << m_commandQueue.length();
// qCDebug(dcEQ3()) << m_name << "Enqueued command" << cmd.name << "Command queue length:" << m_commandQueue.length();
processCommandQueue();
return cmd.id;
}
@ -468,7 +490,7 @@ void EqivaBluetooth::processCommandQueue()
}
if (m_commandQueue.isEmpty()) {
qCDebug(dcEQ3()) << m_name << "Command queue is empty. Nothing to do...";
// qCDebug(dcEQ3()) << m_name << "Command queue is empty. Nothing to do...";
return;
}
@ -479,6 +501,7 @@ void EqivaBluetooth::processCommandQueue()
}
m_currentCommand = m_commandQueue.takeFirst();
m_commandTimeout.start();
qCDebug(dcEQ3()) << m_name << "Sending command" << m_currentCommand.id << m_currentCommand.name << m_currentCommand.data.toHex();
writeCharacteristic(commandCharacteristicUuid, m_currentCommand.data);
}

View File

@ -87,17 +87,19 @@ private:
quint8 m_valveOpen = 0;
bool m_batteryCritical = false;
QTimer m_reconnectTimer;
int m_reconnectAttempt = 0;
struct Command {
QString name; // For debug prints
QByteArray data;
int id = -1;
qint32 id = -1;
};
QList<Command> m_commandQueue;
Command m_currentCommand;
QTimer m_commandTimeout;
int m_nextCommandId = 0;
quint16 m_nextCommandId = 0;
};
class EqivaBluetoothDiscovery: public QObject