Newer
Older
powermon_manager_sw / gui / model.cpp
@Razvan Turiac Razvan Turiac on 8 Jul 4 KB Initial import
/* 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);
}