summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
Diffstat (limited to 'daemon')
-rw-r--r--daemon/CMakeLists.txt12
-rw-r--r--daemon/logger.cpp105
-rw-r--r--daemon/logger.h47
-rw-r--r--daemon/sensorPlugins/heartrateSensor.cpp64
-rw-r--r--daemon/sensorPlugins/heartrateSensor.h45
-rw-r--r--daemon/sensorPlugins/stepCounter.cpp71
-rw-r--r--daemon/sensorPlugins/stepCounter.h43
-rw-r--r--daemon/sensorlogd.cpp34
8 files changed, 421 insertions, 0 deletions
diff --git a/daemon/CMakeLists.txt b/daemon/CMakeLists.txt
new file mode 100644
index 0000000..7d38132
--- /dev/null
+++ b/daemon/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_executable(healthd
+ sensorlogd.cpp
+ logger.cpp
+ logger.h
+ sensorPlugins/stepCounter.cpp
+ sensorPlugins/stepCounter.h
+ sensorPlugins/heartrateSensor.cpp
+ sensorPlugins/heartrateSensor.h
+)
+set_target_properties(healthd PROPERTIES AUTOMOC ON)
+#add_compile_definitions(Q_DECLARE_PRIVATE_SUPPORTS_UNIQUE_PTR=${Q_DECLARE_PRIVATE_SUPPORTS_UNIQUE_PTR})
+target_link_libraries(healthd PRIVATE Qt5::Core Qt5::DBus Qt5::Qml Qt5::Positioning Qt5::Sensors)
diff --git a/daemon/logger.cpp b/daemon/logger.cpp
new file mode 100644
index 0000000..93f764f
--- /dev/null
+++ b/daemon/logger.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2023 Arseniy Movshev <dodoradio@outlook.com>
+ * This file is part of sensorlogd, a sensor logger for the AsteroidOS smartwatch OS.
+ *
+ * sensorlogd is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ * sensorlogd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+
+#include <QSettings>
+#include <QDBusInterface>
+#include <QDBusConnection>
+#include <QDateTime>
+#include <QFile>
+#include <QTextStream>
+#include <QStandardPaths>
+#include <QTimer>
+#include <QDebug>
+
+#include "logger.h"
+
+#include "sensorPlugins/stepCounter.h"
+#include "sensorPlugins/heartrateSensor.h"
+
+Logger::Logger(QObject *parent) :
+ QObject(parent){
+ m_iface = new QDBusInterface("com.nokia.mce","/com/nokia/mce/signal", "com.nokia.mce.signal", QDBusConnection::systemBus());
+ QSettings settings;
+
+//intialise HRM
+ if (heartrateSensorEnabled) { //add check for HRM
+ m_heartrateSensor = new HeartrateSensorPlugin(this,settings.value("stepsInterval",600000).toInt());
+ }
+
+//initialise step counter
+ if (stepCounterEnabled) { //add check for step sensor
+ m_stepCounter = new StepCounterPlugin(this,settings.value("stepsInterval",600000).toInt());
+ }
+
+ if(!m_iface->isValid()) {
+ qDebug() << "interface is not valid";
+ qDebug() << m_iface->lastError();
+ }
+ if(connect(m_iface, SIGNAL(display_status_ind(QString)), this, SLOT(displayOn(QString)))) { //this fires when the display turns on
+ qDebug() << "healthd connected display_status signal to slot";
+ }
+ qDebug() << "healthd sensors logger initialised";
+}
+
+void Logger::displayOn(QString displayState) {
+ if (displayState == "off")
+ return;
+ qDebug() << "display on detected";
+ uint currTime = QDateTime::currentMSecsSinceEpoch();
+
+ if (heartrateSensorEnabled) {
+ m_heartrateSensor->timeUpdate();
+ }
+
+ if (stepCounterEnabled) {
+ m_stepCounter->timeUpdate();
+ }
+}
+
+void fileAddRecord(QString sensorPrefix, QString logdata, QDateTime recordTime) { //adds a record to today's log file for the given sensor
+ qDebug() << fileNameForDate(recordTime.date(), sensorPrefix);
+ QFile file(fileNameForDate(recordTime.date(), sensorPrefix));
+ if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
+ qDebug() << "failed to open file";
+ return;
+ }
+ file.seek(file.size());
+ QTextStream out(&file);
+ out << QString::number(recordTime.currentSecsSinceEpoch()) + ":" + logdata + "\n";
+ file.close();
+}
+bool dayFileExists(QString sensorPrefix, QDateTime dateTime) {
+ return QFile::exists(fileNameForDate(dateTime.date(), sensorPrefix));
+}
+
+QStringList fileGetPrevRecord(QString sensorPrefix, QDateTime recordTime) {
+ qDebug() << fileNameForDate(recordTime.date(), sensorPrefix);
+ QFile file(fileNameForDate(recordTime.date(), sensorPrefix));
+ if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
+ qDebug() << "failed to open file";
+ return {0,0};
+ }
+ QTextStream inStream(&file);
+ QString line;
+ int i;
+ while(!inStream.atEnd())
+ {
+ line = inStream.readLine();
+ qDebug() << line;
+ i++;
+ }
+ file.close();
+ return line.split(":");
+}
+
+QString fileNameForDate(QDate date, QString prefix) {
+ return QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + "/asteroid-healthloggerd/" + prefix + "/" + date.toString("yyyy-MM-dd.log");
+}
diff --git a/daemon/logger.h b/daemon/logger.h
new file mode 100644
index 0000000..14d097f
--- /dev/null
+++ b/daemon/logger.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 Arseniy Movshev <dodoradio@outlook.com>
+ * This file is part of sensorlogd, a sensor logger for the AsteroidOS smartwatch OS.
+ *
+ * sensorlogd is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ * sensorlogd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef LOGGER_H
+#define LOGGER_H
+
+#include <QObject>
+#include <QDateTime>
+#include <QDate>
+#include <QDBusInterface>
+#include <QTimer>
+#include <QString>
+
+#include "sensorPlugins/stepCounter.h"
+#include "sensorPlugins/heartrateSensor.h"
+
+class Logger : public QObject
+{
+ Q_OBJECT
+public:
+ explicit Logger(QObject *parent = 0);
+ virtual ~Logger() {};
+
+private slots:
+ void displayOn(QString displayState);
+
+private:
+ QDBusInterface *m_iface;
+ bool heartrateSensorEnabled = true;
+ HeartrateSensorPlugin *m_heartrateSensor;
+ bool stepCounterEnabled = true;
+ StepCounterPlugin *m_stepCounter;
+
+};
+ void fileAddRecord(QString sensorPrefix, QString logdata, QDateTime recordTime = QDateTime::currentDateTime()); //adds a record to today's log file for the given sensor
+ bool dayFileExists(QString sensorPrefix, QDateTime date = QDateTime::currentDateTime()); //check if today has a log file for the given sensor
+ QStringList fileGetPrevRecord(QString sensorPrefix, QDateTime recordTime = QDateTime::currentDateTime()); //works backwards to find the last record in today's file before the given time - returns nothing if no file is found.
+ QString fileNameForDate(QDate date, QString prefix);
+
+#endif // LOGGER_H
diff --git a/daemon/sensorPlugins/heartrateSensor.cpp b/daemon/sensorPlugins/heartrateSensor.cpp
new file mode 100644
index 0000000..cf3bfb4
--- /dev/null
+++ b/daemon/sensorPlugins/heartrateSensor.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 Arseniy Movshev <dodoradio@outlook.com>
+ * This file is part of sensorlogd, a sensor logger for the AsteroidOS smartwatch OS.
+ *
+ * sensorlogd is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ * sensorlogd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+
+#include <QDateTime>
+#include <QTimer>
+#include <QtSensors/QHrmSensor>
+#include <QDebug>
+#include <QString>
+
+#include "../logger.h"
+
+#include "heartrateSensor.h"
+
+HeartrateSensorPlugin::HeartrateSensorPlugin(QObject *parent, int initInterval) :
+ QObject(parent){
+ interval = initInterval;
+
+ hrmSensor = new QHrmSensor(this);
+ connect(hrmSensor,SIGNAL(readingChanged()),this,SLOT(finishRecording()));
+
+ qDebug() << "heartrate sensor is enabled. interval is (ms) " << interval;
+ recordIntervalTimer = new QTimer(this);
+ connect(recordIntervalTimer,SIGNAL(timeout()),this,SLOT(triggerRecording()));
+ recordIntervalTimer->setSingleShot(true);
+ recordIntervalTimer->start(interval);
+ lastRecordTime = QDateTime::currentDateTime();
+}
+
+void HeartrateSensorPlugin::timeUpdate() {
+ uint elapsed = QDateTime::currentMSecsSinceEpoch() - lastRecordTime.toMSecsSinceEpoch();
+ qDebug() << "time until next steps recording" << recordIntervalTimer->remainingTime() << " elapsed = " << elapsed << " lastRecordTime " << lastRecordTime.toMSecsSinceEpoch();
+ if (elapsed > interval) { //if too much time has passed, reset the timer and record
+ triggerRecording();
+ lastRecordTime = QDateTime::currentDateTime();
+ } else { //otherwise, restart the timer and compensate for time spent in suspend
+ recordIntervalTimer->start(interval - elapsed);
+ }
+}
+
+void HeartrateSensorPlugin::triggerRecording() {
+ qDebug() << "heartrate interval recording";
+ recordIntervalTimer->start(interval);
+ hrmSensor->start();
+}
+
+void HeartrateSensorPlugin::finishRecording() {
+ qDebug() << "bpm update received";
+ int bpm = hrmSensor->reading()->bpm();
+ qDebug() << QDateTime::currentDateTime().toString("hh:mm:ss") << " : " << bpm << hrmSensor->status() << hrmSensor->isActive();
+ if ((bpm == 0) || (hrmSensor->status() < 3)) {
+ qDebug() << "hrm sensor accuracy insufficient. waiting.";
+ return;
+ }
+ fileAddRecord(sensorPathPrefix,QString::number(bpm));
+ hrmSensor->stop();
+}
diff --git a/daemon/sensorPlugins/heartrateSensor.h b/daemon/sensorPlugins/heartrateSensor.h
new file mode 100644
index 0000000..7788d7e
--- /dev/null
+++ b/daemon/sensorPlugins/heartrateSensor.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 Arseniy Movshev <dodoradio@outlook.com>
+ * This file is part of sensorlogd, a sensor logger for the AsteroidOS smartwatch OS.
+ *
+ * sensorlogd is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ * sensorlogd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef HEARTRATESENSOR_H
+#define HEARTRATESENSOR_H
+
+#include <QObject>
+#include <QDateTime>
+#include <QDBusInterface>
+#include <QTimer>
+
+#include <QtSensors/QHrmSensor>
+
+class HeartrateSensorPlugin : public QObject
+{
+ Q_OBJECT
+public:
+ explicit HeartrateSensorPlugin(QObject *parent = 0, int initInterval = 600000);
+ virtual ~HeartrateSensorPlugin() {};
+
+ void timeUpdate();
+
+public slots:
+ void triggerRecording();
+
+private slots:
+ void finishRecording();
+
+private:
+ QDateTime lastRecordTime;
+ int interval;
+ QTimer *recordIntervalTimer;
+ QHrmSensor *hrmSensor;
+
+ const QString sensorPathPrefix = "heartrateMonitor";
+};
+
+#endif // HEARTRATESENSOR_H
diff --git a/daemon/sensorPlugins/stepCounter.cpp b/daemon/sensorPlugins/stepCounter.cpp
new file mode 100644
index 0000000..8bfed03
--- /dev/null
+++ b/daemon/sensorPlugins/stepCounter.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2023 Arseniy Movshev <dodoradio@outlook.com>
+ * This file is part of sensorlogd, a sensor logger for the AsteroidOS smartwatch OS.
+ *
+ * sensorlogd is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ * sensorlogd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <QDateTime>
+#include <QTimer>
+#include <QtSensors/QStepCounterSensor>
+#include <QDebug>
+#include <QString>
+
+#include "../logger.h"
+
+#include "stepCounter.h"
+
+StepCounterPlugin::StepCounterPlugin(QObject *parent, int initInterval) :
+ QObject(parent){
+ interval = initInterval;
+
+ stepcounterSensor = new QStepCounterSensor(this);
+ stepcounterSensor->start();
+
+ qDebug() << "step counter sensor is enabled. interval is (ms) " << interval;
+ recordIntervalTimer = new QTimer(this);
+ connect(recordIntervalTimer,SIGNAL(timeout()),this,SLOT(triggerRecording()));
+ recordIntervalTimer->setSingleShot(true);
+ recordIntervalTimer->start(interval);
+
+ QDateTime currDateTime = QDateTime::currentDateTime();
+
+ if (dayFileExists(sensorPathPrefix)) {
+ QStringList lastLineData = fileGetPrevRecord(sensorPathPrefix);
+ lastRecordTime = QDateTime::fromSecsSinceEpoch(lastLineData[0].toInt());
+ if (stepcounterSensor->reading()->steps() == 0) {
+ stepsOffset = -(lastLineData[1].toInt());
+ } else {
+
+ }
+ } else {
+ //if it's a new day, we 'reset' the counter. this is crude - we should really check for a boot here, since certain machines have capability of counting steps when powered down.
+ stepsOffset = stepcounterSensor->reading()->steps();
+ }
+}
+
+void StepCounterPlugin::timeUpdate() {
+ QDateTime currDateTime = QDateTime::currentDateTime();
+ if (lastRecordTime.date() < currDateTime.date()) {
+ stepsOffset = stepcounterSensor->reading()->steps(); //this 'resets' the reading whenever the screen is first turned on after midnight. this means that, in the morning, the step count will always be zero, but steps taken just before midnight are still counted and not discarded.
+ }
+ uint elapsed = currDateTime.toMSecsSinceEpoch() - lastRecordTime.toMSecsSinceEpoch();
+ qDebug() << "time until next steps recording" << recordIntervalTimer->remainingTime() << " elapsed = " << elapsed << " lastRecordTime " << lastRecordTime.toMSecsSinceEpoch();
+ if (elapsed > interval) { //if too much time has passed, reset the timer and record
+ triggerRecording();
+ lastRecordTime = QDateTime::currentDateTime();
+ } else { //otherwise, restart the timer and compensate for time spent in suspend
+ recordIntervalTimer->start(interval - elapsed);
+ }
+}
+
+void StepCounterPlugin::triggerRecording() {
+ qDebug() << "stepcounter interval recording";
+ int steps = stepcounterSensor->reading()->steps();
+ qDebug() << QDateTime::currentDateTime().toString("hh:mm:ss") << " : " << steps << stepcounterSensor->isActive();
+ //we probably ought to do some error checking here
+ fileAddRecord(sensorPathPrefix,QString::number(steps - stepsOffset));
+}
diff --git a/daemon/sensorPlugins/stepCounter.h b/daemon/sensorPlugins/stepCounter.h
new file mode 100644
index 0000000..a221561
--- /dev/null
+++ b/daemon/sensorPlugins/stepCounter.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 Arseniy Movshev <dodoradio@outlook.com>
+ * This file is part of sensorlogd, a sensor logger for the AsteroidOS smartwatch OS.
+ *
+ * sensorlogd is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ * sensorlogd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef STEPCOUNTER_H
+#define STEPCOUNTER_H
+
+#include <QObject>
+#include <QDateTime>
+#include <QDBusInterface>
+#include <QTimer>
+
+#include <QtSensors/QStepCounterSensor>
+
+class StepCounterPlugin : public QObject
+{
+ Q_OBJECT
+public:
+ explicit StepCounterPlugin(QObject *parent = 0, int initInterval = 600000);
+ virtual ~StepCounterPlugin() {};
+
+ void timeUpdate();
+
+public slots:
+ void triggerRecording();
+
+private:
+ QDateTime lastRecordTime;
+ int interval;
+ QTimer *recordIntervalTimer;
+ QStepCounterSensor *stepcounterSensor;
+ int stepsOffset; //this is subtracted from the raw sensor value to compensate for daily step resets and boot offsets.
+
+ const QString sensorPathPrefix = "stepCounter";
+};
+
+#endif // STEPCOUNTER_H
diff --git a/daemon/sensorlogd.cpp b/daemon/sensorlogd.cpp
new file mode 100644
index 0000000..8b7395a
--- /dev/null
+++ b/daemon/sensorlogd.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 Arseniy Movshev <dodoradio@outlook.com>
+ * This file is part of sensorlogd, a sensor logger for the AsteroidOS smartwatch OS.
+ *
+ * sensorlogd is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ * sensorlogd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <QCoreApplication>
+#include <QDBusConnection>
+#include <QDebug>
+#include "logger.h"
+
+int main(int argc, char **argv)
+{
+ QCoreApplication qcoreapp(argc, argv);
+ if (!QDBusConnection::systemBus().isConnected()) {
+ fprintf(stderr, "Cannot connect to the D-Bus system bus.\n");
+ return 3;
+ }
+ if (!QDBusConnection::sessionBus().isConnected()) {
+ fprintf(stderr, "Cannot connect to the D-Bus session bus.\n");
+ return 2;
+ }
+ Logger sensorsLogger;
+ QCoreApplication::setOrganizationName("asteroid");
+ QCoreApplication::setOrganizationDomain("asteroidos.org");
+ QCoreApplication::setApplicationName("healthd");
+ qDebug() << "healthd started";
+ qcoreapp.exec();
+ return 0;
+}