Skip to content

Commit

Permalink
Introduce BodyMeasures as generalization of current Withings Data
Browse files Browse the repository at this point in the history
... body measures are weight/height data as provided by multiple fitness platform (one of the being the already support Withings platform)
... all access to Weight from external platforms is done through the body measures model - not direct use of Withings any more
... not all platform deliver all measures - but (hopefully) all are providing "weight in kg" as a minimum data

General Download Dialog for Body Measures
... allowing to select the source and the daterange for which data is downloaded (e.g. only the new data since last available measure)
... Support existing Withings Download
... Support new Today's Plan as data source (which is able to receive measures from other sits - e.g. Garmin Connect)
... Support CSV files as data source

Store Body Measures Data in one fix file under /activities (not in /cache like Withings) (so that e.g. backup works like before).

What's open:

... CSV File Import (Info Message on missing feature)
... Test of "old" Withings Download API (since I can't do this)
  • Loading branch information
Joern-R committed Mar 18, 2017
1 parent 643a273 commit c6c2121
Show file tree
Hide file tree
Showing 18 changed files with 982 additions and 164 deletions.
123 changes: 123 additions & 0 deletions src/Cloud/BodyMeasures.cpp
@@ -0,0 +1,123 @@
/*
* Copyright (c) 2015 Joern Rischmueller (joern.rm@gmail.com)
*
* 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 the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program 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, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "BodyMeasures.h"

#include <QList>
#include <QMessageBox>
#include <QTextStream>

#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>

bool
BodyMeasureParser::serialize(QString filename, QList<BodyMeasure> &data) {

// open file - truncate contents
QFile file(filename);
if (!file.open(QFile::WriteOnly)) {
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Critical);
msgBox.setText(QObject::tr("Problem Saving Body Measures"));
msgBox.setInformativeText(QObject::tr("File: %1 cannot be opened for 'Writing'. Please check file properties.").arg(filename));
msgBox.exec();
return false;
};
file.resize(0);
QTextStream out(&file);
out.setCodec("UTF-8");

QJsonArray measures;
for (int i = 0; i < data.count(); i++) {
BodyMeasure m = data.at(i);
QJsonObject measure;
measure.insert("when", m.when.toSecsSinceEpoch());
measure.insert("comment", m.comment);
measure.insert("weightkg", m.weightkg);
measure.insert("fatkg", m.fatkg);
measure.insert("boneskg", m.boneskg);
measure.insert("musclekg", m.musclekg);
measure.insert("leankg", m.leankg);
measure.insert("fatpercent", m.fatpercent);
measures.append(measure);
}

QJsonObject jsonObject;
// add a version in case of format changes
jsonObject.insert("version", 1);
jsonObject.insert("measures", QJsonValue(measures));

QJsonDocument json;
json.setObject(jsonObject);

out << json.toJson();
out.flush();
file.close();
return true;

}


bool
BodyMeasureParser::unserialize(QFile &file, QList<BodyMeasure> &data) {

// open file - truncate contents
if (!file.open(QFile::ReadOnly)) {
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Critical);
msgBox.setText(QObject::tr("Problem Reading Body Measures"));
msgBox.setInformativeText(QObject::tr("File: %1 cannot be opened for 'Reading'. Please check file properties.").arg(file.fileName()));
msgBox.exec();
return false;
};
QByteArray jsonFileContent = file.readAll();
file.close();

QJsonParseError parseError;
QJsonDocument document = QJsonDocument::fromJson(jsonFileContent, &parseError);

if (parseError.error != QJsonParseError::NoError || document.isEmpty() || document.isNull()) {
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Critical);
msgBox.setText(QObject::tr("Problem Parsing Body Measures"));
msgBox.setInformativeText(QObject::tr("File: %1 is not a proper JSON file. Parsing error: %2").arg(file.fileName()).arg(parseError.errorString()));
msgBox.exec();
return false;
}

data.clear();
QJsonObject object = document.object();
QJsonArray measures = object["measures"].toArray();
for (int i = 0; i < measures.count(); i++) {
QJsonObject measure = measures.at(i).toObject();
BodyMeasure m;
m.when = QDateTime::fromSecsSinceEpoch(measure["when"].toDouble());
m.comment = measure["comment"].toString();
m.weightkg = measure["weightkg"].toDouble();
m.fatkg = measure["fatkg"].toDouble();
m.boneskg = measure["boneskg"].toDouble();
m.musclekg = measure["musclekg"].toDouble();
m.leankg = measure["leankg"].toDouble();
m.fatpercent = measure["fatpercent"].toDouble();
data.append(m);
}

return true;
}

66 changes: 66 additions & 0 deletions src/Cloud/BodyMeasures.h
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2015 Joern Rischmueller (joern.rm@gmail.com)
*
* 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 the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program 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, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef _Gc_BodyMeasures_h
#define _Gc_BodyMeasures_h

#include "Context.h"

#include <QString>
#include <QStringList>
#include <QDateTime>

#define BODY_WEIGHT_KG 0
#define BODY_WEIGHT_FAT_KG 1
#define BODY_WEIGHT_MUSCLE_KG 2
#define BODY_WEIGHT_BONES_KG 3
#define BODY_WEIGHT_LEAN_KG 4
#define BODY_WEIGHT_FAT_PERCENT 5

class BodyMeasure {

public:
BodyMeasure() : when(QDateTime()), comment(""), weightkg(0), fatkg(0), musclekg(0), boneskg(0), leankg(0), fatpercent(0) {}

// depending on datasource not all fields may be filled with actual values

QDateTime when; // when was this reading taken
QString comment; // user commentary regarding this measurement

double weightkg, // weight in Kilograms
fatkg, // fat in Kilograms
musclekg, // muscles in Kilograms
boneskg, // bones in Kilograms
leankg, // lean mass in Kilograms
fatpercent; // body fat as a percentage of weight

// used by qSort()
bool operator< (BodyMeasure right) const {
return (when < right.when);
}
};

class BodyMeasureParser {

public:
static bool serialize(QString, QList<BodyMeasure> &);
static bool unserialize(QFile &, QList<BodyMeasure> &);
};


#endif

0 comments on commit c6c2121

Please sign in to comment.