diff --git a/AppSettings.json b/AppSettings.json index 16def4c..46dbaf2 100644 --- a/AppSettings.json +++ b/AppSettings.json @@ -3,5 +3,6 @@ "AccountsUri": "https://smartpaymapi.ovoenergy.com/first-login/api/bootstrap/v2/", "MonthlyUri": "https://smartpaymapi.ovoenergy.com/usage/api/monthly/{0}?date={1}", "DailyUri": "https://smartpaymapi.ovoenergy.com/usage/api/daily/{0}?date={1}", - "HalfHourlyUri": "https://smartpaymapi.ovoenergy.com/usage/api/half-hourly/{0}?date={1}" + "HalfHourlyUri": "https://smartpaymapi.ovoenergy.com/usage/api/half-hourly/{0}?date={1}", + "DumpData": "false" } \ No newline at end of file diff --git a/Assets/FolderPermissions.png b/Assets/FolderPermissions.png new file mode 100644 index 0000000..cb9ab2a Binary files /dev/null and b/Assets/FolderPermissions.png differ diff --git a/Helpers/ConfigHelper.cs b/Helpers/ConfigHelper.cs new file mode 100644 index 0000000..e7442d2 --- /dev/null +++ b/Helpers/ConfigHelper.cs @@ -0,0 +1,31 @@ +using Microsoft.Extensions.Configuration; +using System; + +namespace OvoData.Helpers; + +public static class ConfigHelper +{ + public static bool GetBoolean(IConfigurationRoot config, string key, bool defaultValue) + { + var result = defaultValue; + + if (config != null) + { + try + { + var value = config[key]; + if (bool.TryParse(value, out result)) + { + return result; + } + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + } + + return result; + } +} \ No newline at end of file diff --git a/Helpers/HttpHelper.cs b/Helpers/HttpHelper.cs index 63f98df..2899cad 100644 --- a/Helpers/HttpHelper.cs +++ b/Helpers/HttpHelper.cs @@ -83,6 +83,10 @@ public static MonthlyResponse GetMonthlyUsage(IConfigurationRoot config, string if (response.IsSuccessStatusCode) { var content = response.Content.ReadAsStringAsync().Result; + if (ConfigHelper.GetBoolean(config, "DumpData", false)) + { + Logger.DumpJson($"{nameof(GetMonthlyUsage)}-{year}", content); + } result = JsonSerializer.Deserialize(content, _options); } } @@ -109,6 +113,10 @@ public static DailyResponse GetDailyUsage(IConfigurationRoot config, string acco if (response.IsSuccessStatusCode) { var content = response.Content.ReadAsStringAsync().Result; + if (ConfigHelper.GetBoolean(config, "DumpData", false)) + { + Logger.DumpJson($"{nameof(GetDailyUsage)}-{year}-{month:D2}", content); + } result = JsonSerializer.Deserialize(content, _options); } } @@ -135,6 +143,10 @@ public static HalfHourlyResponse GetHalfHourlyUsage(IConfigurationRoot config, s if (response.IsSuccessStatusCode) { var content = response.Content.ReadAsStringAsync().Result; + if (ConfigHelper.GetBoolean(config, "DumpData", false)) + { + Logger.DumpJson($"{nameof(GetHalfHourlyUsage)}-{year}-{month:D2}-{day:D2}", content); + } result = JsonSerializer.Deserialize(content, _options); } } diff --git a/Helpers/Logger.cs b/Helpers/Logger.cs index c4817eb..e0cdeaf 100644 --- a/Helpers/Logger.cs +++ b/Helpers/Logger.cs @@ -31,4 +31,18 @@ private static string GetFileName() return fileName; } + + public static void DumpJson(string responseType, string json) + { + var folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), Constants.ApplicationName); + + if (!Directory.Exists(Path.Combine(folder, "Dump"))) + { + Directory.CreateDirectory(Path.Combine(folder, "Dump")); + } + + var fileName = Path.Combine(folder, "Dump", $"{DateTime.Now:yyyy-MM-dd HH-mm-ss.fff} {responseType}.json"); + + File.WriteAllText(fileName, json); + } } \ No newline at end of file diff --git a/Helpers/SqliteHelper.cs b/Helpers/SqliteHelper.cs index b9148b7..505542b 100644 --- a/Helpers/SqliteHelper.cs +++ b/Helpers/SqliteHelper.cs @@ -109,9 +109,11 @@ public void UpsertMonthly(string fuelType, List items) { var stringBuilder = new StringBuilder(); + double.TryParse(item.Cost.Amount, out var safeCost); + stringBuilder.AppendLine($"INSERT INTO Monthly{fuelType}"); stringBuilder.AppendLine("VALUES"); - stringBuilder.AppendLine($"('{item.Year}-{item.Month:D2}', '{item.Mpxn}', {item.Consumption}, {item.Cost.Amount})"); + stringBuilder.AppendLine($"('{item.Year}-{item.Month:D2}', '{item.Mpxn}', {item.Consumption}, {safeCost})"); stringBuilder.AppendLine("ON CONFLICT (Month)"); stringBuilder.AppendLine("DO UPDATE SET Mxpn = excluded.Mxpn, Consumption = excluded.Consumption, Cost = excluded.Cost"); @@ -191,9 +193,11 @@ public void UpsertDaily(string fuelType, List items) var day = item.Interval.Start.ToString("yyyy-MM-dd"); + double.TryParse(item.Cost.Amount, out var safeCost); + stringBuilder.AppendLine($"INSERT INTO Daily{fuelType}"); stringBuilder.AppendLine("VALUES"); - stringBuilder.AppendLine($"('{day}', {item.Consumption}, {item.Cost.Amount}, {item.Rates.Standing}, {item.Rates.AnyTime}, {item.Rates.Peak}, {item.Rates.OffPeak}, {item.HasHhData})"); + stringBuilder.AppendLine($"('{day}', {item.Consumption}, {safeCost}, {item.Rates.Standing}, {item.Rates.AnyTime}, {item.Rates.Peak}, {item.Rates.OffPeak}, {item.HasHhData})"); stringBuilder.AppendLine("ON CONFLICT (Day)"); stringBuilder.AppendLine("DO UPDATE SET Consumption = excluded.Consumption, Cost = excluded.Cost, Standing = excluded.Standing, AnyTime = excluded.AnyTime, Peak = excluded.Peak, OffPeak = excluded.OffPeak, HasHhData = excluded.HasHhData"); diff --git a/Models/OvoApi/AccountsResponse.cs b/Models/OvoApi/AccountsResponse.cs index 869f4d5..9cc0eed 100644 --- a/Models/OvoApi/AccountsResponse.cs +++ b/Models/OvoApi/AccountsResponse.cs @@ -4,7 +4,7 @@ namespace OvoData.Models.OvoApi; public class AccountsResponse { - public string CustomerId { get; set; } + public string CustomerId { get; set; } = string.Empty; public bool IsFirstLogin { get; set; } - public List AccountIds { get; set; } + public List AccountIds { get; set; } = new(); } \ No newline at end of file diff --git a/Models/OvoApi/Cost.cs b/Models/OvoApi/Cost.cs index cb78a84..734ab08 100644 --- a/Models/OvoApi/Cost.cs +++ b/Models/OvoApi/Cost.cs @@ -2,6 +2,6 @@ public class Cost { - public string CurrencyUnit { get; set; } - public string Amount { get; set; } + public string CurrencyUnit { get; set; } = string.Empty; + public string Amount { get; set; } = string.Empty; } \ No newline at end of file diff --git a/Models/OvoApi/DailyDataItem.cs b/Models/OvoApi/DailyDataItem.cs index 310302f..ef012ab 100644 --- a/Models/OvoApi/DailyDataItem.cs +++ b/Models/OvoApi/DailyDataItem.cs @@ -5,8 +5,8 @@ public class DailyDataItem public bool HasHhData { get; set; } public double Consumption { get; set; } - public Interval Interval { get; set; } + public Interval Interval { get; set; } = new(); - public Cost Cost { get; set; } - public Rates Rates { get; set; } + public Cost Cost { get; set; } = new(); + public Rates Rates { get; set; } = new(); } \ No newline at end of file diff --git a/Models/OvoApi/HalfHourlyDataItem.cs b/Models/OvoApi/HalfHourlyDataItem.cs index e85d499..afa16d2 100644 --- a/Models/OvoApi/HalfHourlyDataItem.cs +++ b/Models/OvoApi/HalfHourlyDataItem.cs @@ -3,6 +3,6 @@ public class HalfHourlyDataItem { public double Consumption { get; set; } - public Interval Interval { get; set; } - public string Unit { get; set; } + public Interval Interval { get; set; } = new(); + public string Unit { get; set; } = string.Empty; } \ No newline at end of file diff --git a/Models/OvoApi/LoginRequest.cs b/Models/OvoApi/LoginRequest.cs index 0db9499..ca1e6df 100644 --- a/Models/OvoApi/LoginRequest.cs +++ b/Models/OvoApi/LoginRequest.cs @@ -2,7 +2,7 @@ public class LoginRequest { - public string Username { get; set; } - public string Password { get; set; } + public string Username { get; set; } = string.Empty; + public string Password { get; set; } = string.Empty; public bool RememberMe { get; set; } } \ No newline at end of file diff --git a/Models/OvoApi/MonthlyDataItem.cs b/Models/OvoApi/MonthlyDataItem.cs index 2d5276b..4aa03a3 100644 --- a/Models/OvoApi/MonthlyDataItem.cs +++ b/Models/OvoApi/MonthlyDataItem.cs @@ -2,9 +2,9 @@ public class MonthlyDataItem { - public string Mpxn { get; set; } + public string Mpxn { get; set; } = string.Empty; public int Month { get; set; } public int Year { get; set; } public double Consumption { get; set; } - public Cost Cost { get; set; } + public Cost Cost { get; set; } = new(); } \ No newline at end of file diff --git a/OvoData.csproj b/OvoData.csproj index be62c58..56e128f 100644 --- a/OvoData.csproj +++ b/OvoData.csproj @@ -8,8 +8,8 @@ win-x64 en-US;en Ovo.ico - 1.0.2 - 1.0.2.2 + 1.0.3 + 1.0.3.3 @@ -33,12 +33,12 @@ - - + + - + \ No newline at end of file diff --git a/README.md b/README.md index 10fd386..cd5ec8c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,12 @@ Get your energy usage data from OVO via it's API. +There have been reports that some Windows 11 users require this to be run elevated (as admin). +This is probably due to permissions to the folder C:\ProgramData. + +If this affects you please create the above folder and assign "Full control" to the Users Group + + + If you like my work, please consider donating at https://www.buymeacoffee.com/mikewilliamsuk