Skip to content

Commit

Permalink
Merge pull request #9 from miikasda/extra_info
Browse files Browse the repository at this point in the history
Add support for reading voltage and movement counter
  • Loading branch information
miikasda authored Jul 16, 2024
2 parents 7e770dd + 452b4c3 commit deae5d5
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 8 deletions.
6 changes: 5 additions & 1 deletion qml/pages/GetDataPage.qml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
Skruuvi - Reader for Ruuvi sensors
Copyright (C) 2023 Miika Malin
Copyright (C) 2023-2024 Miika Malin
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -262,6 +262,10 @@ Page {
loadingScreen.text = "Connected, fetching data"
} else if (data[0] === "data_received_amount") {
loadingScreen.text = "Connected, received " + data[1] + " readings"
} else if (data[0] === "extra_data") {
// Update voltage and movement counter
db.setVoltage(selectedDevice.deviceAddress, data[1])
db.setMovement(selectedDevice.deviceAddress, data[2])
} else if (data[0] === "failed") {
loadingScreen.running = false;
failureOverlay.visible = true;
Expand Down
83 changes: 82 additions & 1 deletion qml/pages/SelectDevicePage.qml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
Skruuvi - Reader for Ruuvi sensors
Copyright (C) 2023 Miika Malin
Copyright (C) 2023-2024 Miika Malin
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -112,6 +112,8 @@ Page {
deviceModel.append({
deviceName: device.deviceName,
deviceAddress: device.deviceAddress,
deviceVoltage: device.deviceVoltage,
deviceMovement: device.deviceMovement,
showBluetoothIcon: false
});
}
Expand Down Expand Up @@ -164,6 +166,7 @@ Page {
}

Image {
id: btIcon
source: "image://theme/icon-s-bluetooth"
width: Theme.iconSizeSmall
height: Theme.iconSizeSmall
Expand All @@ -175,6 +178,32 @@ Page {
}
}

Image {
id: batteryIcon
source: "image://theme/icon-m-battery"
width: Theme.iconSizeSmall
height: Theme.iconSizeSmall
anchors {
left: topLabel.right
leftMargin: Theme.paddingMedium
verticalCenter: parent.verticalCenter
verticalCenterOffset: -topLabel.height / 2
}
}

Image {
id: movementIcon
source: "image://theme/icon-s-sync"
width: Theme.iconSizeSmall
height: Theme.iconSizeSmall
anchors {
left: voltageLabel.right
leftMargin: Theme.paddingMedium
verticalCenter: parent.verticalCenter
verticalCenterOffset: -topLabel.height / 2
}
}

Label {
id: topLabel
text: model.deviceName
Expand All @@ -185,6 +214,25 @@ Page {
}

Label {
id: voltageLabel
text: model.deviceVoltage + " V"
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -topLabel.height / 2
anchors.left: batteryIcon.right
anchors.leftMargin: Theme.paddingSmall
}

Label {
id: movementLabel
text: model.deviceMovement + " Moves"
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -topLabel.height / 2
anchors.left: movementIcon.right
anchors.leftMargin: Theme.paddingSmall
}

Label {
id: bottomLabel
anchors.top: topLabel.bottom
text: model.deviceAddress
font.pixelSize: Theme.fontSizeSmall
Expand Down Expand Up @@ -301,6 +349,37 @@ Page {
}
}

Connections {
target: db
onVoltageUpdated: {
// Find the device with the matching mac address in the model
var deviceFound = false;
for (var i = 0; i < deviceModel.count; i++) {
var device = deviceModel.get(i);
if (device.deviceAddress === mac) {
deviceFound = true;
// Update the voltage for the matched device
deviceModel.setProperty(i, "deviceVoltage", voltage.toString());
console.log("Voltage updated for " + mac);
break;
}
}
}
onMovementUpdated: {
var deviceFound = false;
for (var i = 0; i < deviceModel.count; i++) {
var device = deviceModel.get(i);
if (device.deviceAddress === mac) {
deviceFound = true;
// Update the movement for the matched device
deviceModel.setProperty(i, "deviceMovement", movement.toString());
console.log("Movement updated for " + mac);
break;
}
}
}
}

Connections {
target: ld
onDeviceFound: {
Expand All @@ -320,6 +399,8 @@ Page {
deviceModel.append({
deviceName: deviceName,
deviceAddress: deviceAddress,
deviceVoltage: "NA",
deviceMovement: "NA",
showBluetoothIcon: true
});
}
Expand Down
19 changes: 16 additions & 3 deletions qml/pages/ruuvi_read.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
License:
Skruuvi - Reader for Ruuvi sensors
Copyright (C) 2023 Miika Malin
Copyright (C) 2023-2024 Miika Malin
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -43,8 +43,9 @@
# Charasteristic UUIDS
UART_RX_CHAR_UUID = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
UART_TX_CHAR_UUID = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
# Magic value for log read
LOG_READ = 0x11
# Magic values
LOG_READ = 0x11 # Log read command
ADV_DATA = 0x05 # Header information for advertisement data


class RuuviTagReader:
Expand Down Expand Up @@ -97,6 +98,18 @@ def handle_rx(self, _, data):
"data_received_amount",
self.data_received_amount
])
elif data[0] == ADV_DATA:
if len(data) != 18:
print("Wrong advertisement data size", flush=True)
else:
print("Advertisement data received", flush=True)
dat = struct.unpack('>BhHHhhhHBH', data)
voltage = ((dat[7] >> 5) + 1600) / 1000
movement_counter = dat[8]
pyotherside.send([
"extra_data",
round(voltage, 2), movement_counter
])

async def read_log_data(self):
print(f"Searching for Ruuvi {self.device_address}", flush=True)
Expand Down
55 changes: 53 additions & 2 deletions src/database.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
Skruuvi - Reader for Ruuvi sensors
Copyright (C) 2023 Miika Malin
Copyright (C) 2023-2024 Miika Malin
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -77,6 +77,10 @@ database::database(QObject* parent) : QObject(parent) {
"FOREIGN KEY (device) REFERENCES devices(mac))";
executeQuery(createAirPressureTableQuery);

// Colums added after initial release needs to be appended
checkAndAddColumn("devices", "voltage", "REAL");
checkAndAddColumn("devices", "movement", "INT");

}

void database::executeQuery(const QString& queryStr) {
Expand All @@ -86,6 +90,49 @@ void database::executeQuery(const QString& queryStr) {
}
}

void database::checkAndAddColumn(const QString &tableName, const QString &columnName, const QString &columnType) {
QSqlQuery query(db);
query.exec("PRAGMA table_info(" + tableName + ")");
bool columnExists = false;
while (query.next()) {
if (query.value(1).toString() == columnName) {
columnExists = true;
break;
}
}
if (!columnExists) {
qDebug() << "Adding column " << columnName << " to table " << tableName;
QString alterTableQuery = "ALTER TABLE " + tableName + " ADD COLUMN " + columnName + " " + columnType;
executeQuery(alterTableQuery);
}
}

void database::setVoltage(const QString &mac, double voltage) {
QSqlQuery query(db);
query.prepare("UPDATE devices SET voltage = :voltage WHERE mac = :mac");
query.bindValue(":voltage", voltage);
query.bindValue(":mac", mac);

if (!query.exec()) {
qDebug() << "Error setting voltage:" << query.lastError().text();
} else {
emit voltageUpdated(mac, voltage); // Emit the new voltage reading
}
}

void database::setMovement(const QString &mac, int movement) {
QSqlQuery query(db);
query.prepare("UPDATE devices SET movement = :movement WHERE mac = :mac");
query.bindValue(":movement", movement);
query.bindValue(":mac", mac);

if (!query.exec()) {
qDebug() << "Error setting movement:" << query.lastError().text();
} else {
emit movementUpdated(mac, movement); // Emit the new movement reading
}
}

void database::inputRawData(QString deviceAddress, QString deviceName, const QVariantList& data) {
// Create a QThread to run the function in a separate thread
QThread* thread = new QThread(this);
Expand Down Expand Up @@ -141,16 +188,20 @@ QVariantList database::getDevices()
{
QVariantList devices;

QString selectQuery = "SELECT mac, name FROM devices";
QString selectQuery = "SELECT mac, name, voltage, movement FROM devices";
QSqlQuery query(db);
if (query.exec(selectQuery)) {
while (query.next()) {
QString mac = query.value(0).toString();
QString name = query.value(1).toString();
QString voltage = query.value("voltage").isNull() ? "NA" : QString::number(query.value("voltage").toDouble());
QString movement = query.value("movement").isNull() ? "NA" : QString::number(query.value("movement").toInt());

QVariantMap device;
device["deviceName"] = name;
device["deviceAddress"] = mac;
device["deviceVoltage"] = voltage;
device["deviceMovement"] = movement;

devices.append(device);
}
Expand Down
7 changes: 6 additions & 1 deletion src/database.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
Skruuvi - Reader for Ruuvi sensors
Copyright (C) 2023 Miika Malin
Copyright (C) 2023-2024 Miika Malin
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -37,12 +37,17 @@ class database : public QObject {
Q_INVOKABLE void renameDevice(const QString deviceAddress, const QString newDeviceName);
Q_INVOKABLE void removeDevice(const QString deviceAddress);
Q_INVOKABLE QString exportCSV(const QString deviceAddress, const QString deviceName, int startTime, int endTime);
Q_INVOKABLE void setVoltage(const QString &mac, double voltage);
Q_INVOKABLE void setMovement(const QString &mac, int movement);

private:
QSqlDatabase db;
void checkAndAddColumn(const QString &tableName, const QString &columnName, const QString &columnType);

signals:
void inputFinished();
void voltageUpdated(const QString &mac, double voltage);
void movementUpdated(const QString &mac, int movement);
};

#endif // DATABASE_H

0 comments on commit deae5d5

Please sign in to comment.