inital commit
This commit is contained in:
commit
fe71d498b5
7
CMakeLists.txt
Normal file
7
CMakeLists.txt
Normal 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
112
main.cpp
Normal 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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user