/* Copyright (C) 2020 - 2024, Thornwave Labs Inc
* Written by Razvan Turiac <razvan.turiac@thornwave.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the “Software”), to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
* Attribution shall be given to Thornwave Labs Inc. and shall be made visible to the final user.
*
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <model.h>
#include <filesystem>
#include <iostream>
#include <fstream>
#include <string>
Model::Model(): mMainWindow(nullptr)
{
mHomePath.AssignDir(wxStandardPaths::Get().GetUserConfigDir());
#if defined(_MSC_VER)
mHomePath.AppendDir(wxT("pmon"));
#elif defined (__GNUC__)
mHomePath.AppendDir(wxT(".pmon"));
#endif
mHomePath.Mkdir();
loadCloudDevices();
}
void Model::setDevice(uint64_t serial)
{
wxString str;
str.Printf(wxT("%" PRIx64), serial);
mLogFilesPath = mHomePath;
mLogFilesPath.AppendDir(str);
mLogFilesPath.Mkdir();
}
void Model::clearDevice(void)
{
mLogFilesPath.Clear();
}
void Model::addCloudDevice(const Powermon::DeviceIdentifier &id)
{
auto it = std::find(cloudDeviceList.begin(), cloudDeviceList.end(), id);
if (it != cloudDeviceList.end())
*it = id;
else
cloudDeviceList.push_back(id);
saveCloudDevices();
if (mMainWindow)
mMainWindow->UpdateCloudDeviceList();
}
void Model::loadCloudDevices(void)
{
wxFileName fname = mHomePath;
fname.SetFullName(wxT("cloud_devices.cfg"));
wxTextFile file;
if (!file.Open(fname.GetFullPath()))
return;
for (wxString line = file.GetFirstLine(); !file.Eof(); line = file.GetNextLine())
{
if (line.Length())
{
Powermon::DeviceIdentifier id;
if (id.fromURL(line.c_str()))
cloudDeviceList.push_back(id);
}
}
file.Close();
}
void Model::saveCloudDevices(void)
{
wxFileName fname = mHomePath;
fname.SetFullName(wxT("cloud_devices.cfg"));
wxTextFile file;
const wxString path = fname.GetFullPath();
if (!file.Open(path))
if (!file.Create(path))
return;
file.Clear();
for (auto& id : cloudDeviceList)
{
const wxString line = id.toURL();
file.AddLine(line);
}
file.Write();
file.Close();
}
void Model::loadLogData(std::vector<PowermonLogFile::Sample> &samples)
{
samples.clear();
if (mLogFilesPath.IsOk())
{
std::vector<uint32_t> log_files;
wxDir dir;
if (!dir.Open(mLogFilesPath.GetFullPath()))
return;
wxString fname;
bool result = dir.GetFirst(&fname, wxT("*.log"), wxDIR_FILES);
while (result)
{
if (fname.GetChar(0) != 'r')
continue;
fname.Remove(0, 1);
if (fname.Right(4) != wxT(".log"))
continue;
fname.RemoveLast(4);
if (fname.Length() != 8)
continue;
char* endptr;
uint32_t id = strtoul(fname.c_str(), &endptr, 16);
if (*endptr != 0)
continue;
log_files.push_back(id);
result = dir.GetNext(&fname);
}
std::sort(log_files.begin(), log_files.end());
for(const uint32_t id: log_files)
{
wxFile file;
if (!file.Open(getLogFileName(id).GetFullPath(), wxFile::read))
continue;
const wxFileOffset fsize = file.Length();
if (fsize == wxInvalidOffset)
{
file.Close();
continue;
}
std::vector<char> buffer(fsize);
const ssize_t result = file.Read(buffer.data(), fsize);
if (result == fsize)
PowermonLogFile::decode(buffer, samples);
file.Close();
}
}
}
void Model::deleteLogData(void)
{
if (mLogFilesPath.IsOk())
mLogFilesPath.Rmdir(wxPATH_RMDIR_RECURSIVE);
}