Add new schema support to solar-server

This commit is contained in:
2022-09-14 19:40:58 +02:00
parent aeedd58bf0
commit ba6ed5da1a

View File

@@ -2,6 +2,7 @@
#include <cmath> #include <cmath>
#include <iomanip> #include <iomanip>
#include <solar/server/database/connection.hpp> #include <solar/server/database/connection.hpp>
#include <spdlog/spdlog.h>
#include <sstream> #include <sstream>
#include <vector> #include <vector>
@@ -26,30 +27,42 @@ namespace Database
} }
public: public:
bool AddRecord(long const epoch, char const * watt, char const * kwh) bool AddRecord(long const epoch, char const * currentWatts, double const kwh)
{ {
++insertions; ++insertions;
jsonStream << "{\"time\":" << epoch << ",\"watt\":" << watt << ",\"kwh\":" << kwh << "},"; jsonStream << "{\"time\":" << epoch << ",\"currentWatts\":" << currentWatts << ",\"kwh\":" << kwh << "},";
return true; return true;
} }
bool AddRecord(char const * timeUtc, char const * watt, char const * kwh) bool AddRecord(long const epoch, char const * currentWatts, char const * totalWatts)
{
auto const totalWattsInt = std::atoi(totalWatts);
auto const kwh = static_cast<double>(totalWattsInt) / 1000;
return AddRecord(epoch, currentWatts, kwh);
}
bool AddRecord(char const * timeUtc, char const * currentWatts, char const * totalWatts)
{ {
auto const timeInSeconds = Util::ToSecondsFromTimeString(timeUtc); auto const timeInSeconds = Util::ToSecondsFromTimeString(timeUtc);
if(timeInSeconds < 0) if(timeInSeconds < 0)
{ {
std::printf("AddRecord: cannot parse %s to hours, minutes and seconds\n", timeUtc); spdlog::error("AddRecord: cannot parse {0} to hours, minutes and seconds", timeUtc);
return false; return false;
} }
return AddRecord(timeInSeconds + dateEpoch, watt, kwh); return AddRecord(timeInSeconds + dateEpoch, currentWatts, totalWatts);
} }
bool bool AddRecord(
AddRecord(unsigned const year, unsigned const month, unsigned const day, char const * watt, char const * kwh) unsigned const year,
unsigned const month,
unsigned const day,
char const * currentWatts,
char const * totalWatts)
{ {
return AddRecord(Util::GetEpoch(year, month, day), watt, kwh); return AddRecord(Util::GetEpoch(year, month, day), currentWatts, totalWatts);
} }
// Returns the records added thus far as JSON array and resets // Returns the records added thus far as JSON array and resets
@@ -80,7 +93,7 @@ namespace Database
// TimeUtc, Watt and KilowattHour // TimeUtc, Watt and KilowattHour
if(argc != 3) if(argc != 3)
{ {
std::printf("DetailedCallback: unexpected number of arguments %i\n", argc); spdlog::error("DetailedCallback: unexpected number of arguments {0}", argc);
return -1; return -1;
} }
@@ -93,7 +106,7 @@ namespace Database
std::string Connection::GetEntireDay(Util::Date const & date) std::string Connection::GetEntireDay(Util::Date const & date)
{ {
std::stringstream queryStream; std::stringstream queryStream;
queryStream << "SELECT TimeUtc, Watts, KilowattHour FROM SolarPanelOutput WHERE Date = " << '\'' queryStream << "SELECT TimeUtc, CurrentWatts, TotalWatts FROM ZeverLogs WHERE Date = " << '\''
<< date.ToISOString() << '\'' << " ORDER BY TimeUtc ASC;"; << date.ToISOString() << '\'' << " ORDER BY TimeUtc ASC;";
JsonResult result(date.ToEpoch()); JsonResult result(date.ToEpoch());
@@ -101,7 +114,7 @@ namespace Database
= sqlite3_exec(connectionPtr, queryStream.str().c_str(), DetailedCallback, &result, nullptr); = sqlite3_exec(connectionPtr, queryStream.str().c_str(), DetailedCallback, &result, nullptr);
if(sqlResult) if(sqlResult)
{ {
std::printf("GetEntireDay: SQLite error code %i, returning empty JSON array.\n", sqlResult); spdlog::error("GetEntireDay: SQLite error code {0}, returning empty JSON array", sqlResult);
return "[]"; return "[]";
} }
@@ -113,7 +126,7 @@ namespace Database
// Date and KilowattHour // Date and KilowattHour
if(argc != 2) if(argc != 2)
{ {
std::printf("SummaryCallback: unexpected number of arguments %i\n", argc); spdlog::error("SummaryCallback: unexpected number of arguments {0}", argc);
return -1; return -1;
} }
@@ -127,7 +140,7 @@ namespace Database
std::string Connection::GetSummarizedPerDayRecords(Util::Date const & startDate, Util::Date const & endDate) std::string Connection::GetSummarizedPerDayRecords(Util::Date const & startDate, Util::Date const & endDate)
{ {
std::stringstream queryStream; std::stringstream queryStream;
queryStream << "SELECT Date, KilowattHour FROM SolarPanelSummary" queryStream << "SELECT Date, TotalWatts FROM ZeverSummary"
<< " WHERE Date >= '" << startDate.ToISOString() << '\'' << " AND Date <= '" << " WHERE Date >= '" << startDate.ToISOString() << '\'' << " AND Date <= '"
<< endDate.ToISOString() << '\'' << " ORDER BY Date;"; << endDate.ToISOString() << '\'' << " ORDER BY Date;";
@@ -136,7 +149,7 @@ namespace Database
= sqlite3_exec(connectionPtr, queryStream.str().c_str(), SummaryCallback, &result, nullptr); = sqlite3_exec(connectionPtr, queryStream.str().c_str(), SummaryCallback, &result, nullptr);
if(sqlResult) if(sqlResult)
{ {
std::printf("GetSummarizedPerDayRecords: SQLite error code %i, returning empty JSON array.\n", sqlResult); spdlog::error("GetSummarizedPerDayRecords: SQLite error code {0}, returning empty JSON array", sqlResult);
return "[]"; return "[]";
} }
@@ -146,10 +159,10 @@ namespace Database
struct YearResult struct YearResult
{ {
int year; int year;
std::array<double, 12> monthValues; std::array<int, 12> monthValues;
// month is in range 1 to 12 // month is in range 1 to 12
void AddMonthValue(int month, double value) { monthValues[month - 1] += value; } void AddMonthValue(int month, int value) { monthValues[month - 1] += value; }
YearResult(int _year) : year(_year), monthValues() { } YearResult(int _year) : year(_year), monthValues() { }
}; };
@@ -159,23 +172,23 @@ namespace Database
// Date and KilowattHour // Date and KilowattHour
if(argc != 2) if(argc != 2)
{ {
std::printf("MonthSummaryCallback: unexpected number of arguments %i\n", argc); spdlog::error("MonthSummaryCallback: unexpected number of arguments {0}", argc);
return -1; return -1;
} }
Util::Date recordDate; Util::Date recordDate;
if(!recordDate.TryParse(argv[0])) if(!recordDate.TryParse(argv[0]))
{ {
std::printf("MonthSummaryCallback: error parsing date %s\n", argv[0]); spdlog::error("MonthSummaryCallback: error parsing date {0}", argv[0]);
return -1; return -1;
} }
std::vector<YearResult> & yearResults = *reinterpret_cast<std::vector<YearResult> *>(data); std::vector<YearResult> & yearResults = *reinterpret_cast<std::vector<YearResult> *>(data);
double const kwh = std::atof(argv[1]); auto const totalWatts = std::atoi(argv[1]);
if(std::isnan(kwh) || kwh < 0.0) if(std::isnan(totalWatts) || totalWatts < 0)
{ {
// This value makes no sense, ignore it // This value makes no sense, ignore it
std::printf("MonthSummaryCallback: ignoring bogus value for year month %s\n", argv[1]); spdlog::warn("MonthSummaryCallback: ignoring bogus value for year month {0}", argv[1]);
return 0; return 0;
} }
@@ -183,19 +196,19 @@ namespace Database
{ {
if(yearResults[i].year == recordDate.Year()) if(yearResults[i].year == recordDate.Year())
{ {
yearResults[i].AddMonthValue(recordDate.Month(), kwh); yearResults[i].AddMonthValue(recordDate.Month(), totalWatts);
return 0; return 0;
} }
if(yearResults[i].year > recordDate.Year()) if(yearResults[i].year > recordDate.Year())
{ {
yearResults.insert(yearResults.begin() + i, YearResult(recordDate.Year())); yearResults.insert(yearResults.begin() + i, YearResult(recordDate.Year()));
yearResults[i].AddMonthValue(recordDate.Month(), kwh); yearResults[i].AddMonthValue(recordDate.Month(), totalWatts);
return 0; return 0;
} }
} }
yearResults.push_back(YearResult(recordDate.Year())); yearResults.push_back(YearResult(recordDate.Year()));
yearResults[yearResults.size() - 1].AddMonthValue(recordDate.Month(), kwh); yearResults[yearResults.size() - 1].AddMonthValue(recordDate.Month(), totalWatts);
return 0; return 0;
} }
@@ -203,7 +216,7 @@ namespace Database
std::string Connection::GetSummarizedPerMonthRecords(Util::Date const & startDate, Util::Date const & endDate) std::string Connection::GetSummarizedPerMonthRecords(Util::Date const & startDate, Util::Date const & endDate)
{ {
std::stringstream queryStream; std::stringstream queryStream;
queryStream << "SELECT Date, KilowattHour FROM SolarPanelSummary" queryStream << "SELECT Date, TotalWatts FROM ZeverSummary"
<< " WHERE Date >= '" << startDate.ToISOString() << '\'' << " AND Date <= '" << " WHERE Date >= '" << startDate.ToISOString() << '\'' << " AND Date <= '"
<< endDate.ToISOString() << "';"; << endDate.ToISOString() << "';";
@@ -212,8 +225,8 @@ namespace Database
= sqlite3_exec(connectionPtr, queryStream.str().c_str(), MonthSummaryCallback, &yearResults, nullptr); = sqlite3_exec(connectionPtr, queryStream.str().c_str(), MonthSummaryCallback, &yearResults, nullptr);
if(sqlResult || yearResults.size() == 0) if(sqlResult || yearResults.size() == 0)
{ {
std::printf( spdlog::error(
"GetSummarizedPerMonthRecords: SQLite return code %i and %lu years retrieved, returning empty JSON array.\n", "GetSummarizedPerMonthRecords: SQLite return code {0} and {0} years retrieved, returning empty JSON array",
sqlResult, sqlResult,
yearResults.size()); yearResults.size());
return "[]"; return "[]";
@@ -231,8 +244,8 @@ namespace Database
} }
auto const epoch = Util::GetEpoch(year, month + 1, 1); auto const epoch = Util::GetEpoch(year, month + 1, 1);
auto const kwh = yearResults[i].monthValues[month]; auto const totalWatts = yearResults[i].monthValues[month];
result.AddRecord(epoch, "0", std::to_string(kwh).c_str()); result.AddRecord(epoch, "0", totalWatts);
} }
} }