/* 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); }