inital commit

This commit is contained in:
uvos 2024-05-23 17:31:21 +02:00
commit fe71d498b5
2 changed files with 119 additions and 0 deletions

7
CMakeLists.txt Normal file
View File

@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.20)
project(infinilog LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
add_executable(${PROJECT_NAME} main.cpp)

112
main.cpp Normal file
View File

@ -0,0 +1,112 @@
#include <iostream>
#include <fstream>
#include <cstdint>
#include <vector>
#include <filesystem>
#include <ctime>
#include <algorithm>
static constexpr uint8_t magic[] = {0xf6, 0x76, 0xd8, 0x09};
struct __attribute__((packed)) Frame {
uint64_t time;
uint32_t steps;
uint8_t batteryPercent;
uint8_t heartRate;
uint8_t pad[2];
};
bool arrayeq(const uint8_t* a, const uint8_t* b, size_t len)
{
for(size_t i = 0; i < len; ++i)
{
if(a[i] != b[i])
return false;
}
return true;
}
std::vector<Frame> readFile(const std::filesystem::path& path)
{
std::ifstream file;
file.open(path, std::ios_base::binary | std::ios_base::in);
if(!file.is_open())
{
std::cout<<"could not open "<<path<<'\n';
return {};
}
uint8_t magicRef[4];
file.read(reinterpret_cast<char*>(&magicRef), 4);
if(!arrayeq(magic, magicRef, 4))
{
std::cout<<path<<" is not a valid infitime log file\n";
return {};
}
uint8_t versionMajor;
uint8_t versionMinor;
file.read(reinterpret_cast<char*>(&versionMajor), 1);
file.read(reinterpret_cast<char*>(&versionMinor), 1);
if(versionMajor > 1 || file.bad())
{
std::cout<<path<<" is a file of version "<<versionMajor<<'.'<<versionMinor<<" this application supports only versions 1.x and below\n";
return {};
}
uint16_t size;
file.read(reinterpret_cast<char*>(&size), sizeof(size));
if(sizeof(Frame) != size)
{
std::cout<<path<<" contains frames of an unexpected size\n";
return {};
}
uint32_t length;
file.read(reinterpret_cast<char*>(&length), sizeof(length));
std::vector<Frame> frames;
frames.reserve(length);
for(size_t i = 0; i < length && !file.bad(); ++i)
{
Frame frame = {};
file.read(reinterpret_cast<char*>(&frame), sizeof(frame));
if(frame.time != 0)
frames.push_back(frame);
}
std::sort(frames.begin(), frames.end(), [](const Frame& a, const Frame& b){return a.time < b.time;});
return frames;
}
int main(int argc, char** argv)
{
if(argc < 2)
{
std::cout<<"Usage: "<<(argc > 0 ? argv[0] : "infinilog")<<" [LOG_FILE]\n";
return 1;
}
std::vector<Frame> frames = readFile(argv[1]);
if(frames.empty())
return 1;
std::cout<<"timestamp, steps, battery percent, heart rate\n";
for(auto& frame : frames) {
std::time_t time = frame.time;
std::tm* ptm = std::localtime(&time);
char timeBuffer[32];
std::strftime(timeBuffer, 32, "%a, %d.%m.%Y %H:%M:%S", ptm);
std::cout<<timeBuffer<<", "<<frame.steps<<", "<<static_cast<int>(frame.batteryPercent)<<", "<<static_cast<int>(frame.heartRate)<<'\n';
}
return 0;
}