Innovenergy_trunk/csharp/App/VrmGrabber/Database/Db.cs

210 lines
6.6 KiB
C#
Raw Normal View History

2023-04-27 14:59:45 +00:00
using System.Diagnostics.CodeAnalysis;
using System.Web;
2023-05-11 13:41:41 +00:00
using CliWrap;
using CliWrap.Buffered;
using InnovEnergy.App.RemoteSupportConsole;
2023-04-27 14:59:45 +00:00
using InnovEnergy.Lib.Utils;
using InnovEnergy.Lib.Victron.VictronVRM;
using SQLite;
2023-05-04 15:22:58 +00:00
using static System.Text.Json.JsonSerializer;
using Installation = InnovEnergy.App.VrmGrabber.DataTypes.Installation;
using VrmInstallation = InnovEnergy.Lib.Victron.VictronVRM.Installation;
using FILE=System.IO.File;
2023-04-27 14:59:45 +00:00
2023-05-04 15:22:58 +00:00
namespace InnovEnergy.App.VrmGrabber.Database;
2023-04-27 14:59:45 +00:00
public class InstallationDetails
{
public InstallationDetails(String? ip, IReadOnlyList<Detail> details)
{
Details = details;
Ip = ip;
}
public IReadOnlyList<Detail>? Details { get; set; }
public String? Ip { get; set; }
}
2023-04-27 14:59:45 +00:00
public static partial class Db
2023-04-27 14:59:45 +00:00
{
public static Dictionary<Installation, InstallationDetails> InstallationsAndDetails;
internal const String DbPath = "./db.sqlite";
private static SQLiteConnection Connection { get; } = new SQLiteConnection(DbPath);
public static TableQuery<Installation> Installations => Connection.Table<Installation>();
public static void Init()
{
// used to force static constructor
}
static Db()
{
// on startup create/migrate tables
Connection.RunInTransaction(() => { Connection.CreateTable<Installation>(); });
}
2023-04-27 14:59:45 +00:00
public static async Task UpdateDetailsAndInstallations()
2023-04-27 14:59:45 +00:00
{
while (true)
{
await UpdateInstallationsAndDetailsFromVrm(0);
}
2023-04-27 14:59:45 +00:00
}
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
private static async Task UpdateInstallationsAndDetailsFromVrm(Int32 _)
2023-04-27 14:59:45 +00:00
{
var fileContent = await File.ReadAllTextAsync("./token.json");
var acc = Deserialize<AccToken>(fileContent);
var user = VrmAccount.Token(acc!.idUser, acc.token);
var installations = await user.GetInstallations();
// var returnDictionary = new Dictionary<VrmInstallation, InstallationDetails>();
foreach (var installation in installations.Take(20)) //TODO REMOVE TAKE
{
Console.WriteLine(installation.Name);
var details = await GetInstallationDetails(installation);
var ip = Ip(details);
var updatedInstallation = new Installation(
installation.Name,
ip[0],
(Int64)installation.IdSite,
installation.Identifier,
details.Details.MachineSerial() ?? "Unknown",
HttpUtility.UrlEncode(installation.Name),
ip[1],
details.Details.Last().Json["timestamp"].ToString(),
Serialize(details.Details));
if (GetInstallationByIdentifier(installation.Identifier) == null)
{
Create(updatedInstallation);
}
else
{
Update(updatedInstallation);
}
}
}
private static String?[] Ip(InstallationDetails details)
{
var online = "❌";
var lookup = details.Ip;
if (lookup == "Unknown")
{
var serial = details.Details.MachineSerial() ?? "Unknown";
if (serial != "Unknown" && FILE.Exists($@"/etc/openvpn/server/Salino/ccd/{serial}"))
lookup = FILE.ReadAllText($@"/etc/openvpn/server/Salino/ccd/{serial}").Split(' ')[1];
}
else
{
online = "✅";
}
return new[] { lookup, online };
2023-05-11 13:41:41 +00:00
}
private static async Task<InstallationDetails> GetInstallationDetails(VrmInstallation i)
2023-05-11 13:41:41 +00:00
{
await Task.Delay(1000);
2023-05-11 13:41:41 +00:00
try
{
var details = await i.GetDetails();
var ip = await VpnInfo.LookUpIp(i.Identifier, details.MachineSerial()) ?? "Unknown";
if (ip != "Unknown")
await UpdateInstallationName(i, ip);
return new InstallationDetails(ip, details);
2023-05-11 13:41:41 +00:00
}
catch (Exception e)
{
Console.WriteLine(e);
}
return new InstallationDetails("Unknown", Array.Empty<Detail>());
2023-05-11 13:41:41 +00:00
}
private static async Task UpdateInstallationName(VrmInstallation installation, String? ip)
2023-05-11 13:41:41 +00:00
{
var oldNameInFileRequest = await Cli.Wrap("ssh")
2023-05-11 13:41:41 +00:00
.WithArguments($@"root@{ip}")
.AppendArgument("-o StrictHostKeyChecking=accept-new")
.AppendArgument("cat /data/innovenergy/openvpn/installation-name")
2023-05-11 13:41:41 +00:00
.WithValidation(CommandResultValidation.None).ExecuteBufferedAsync();
var oldNameInFileWithoutNewLine = oldNameInFileRequest.StandardOutput.TrimEnd();
if (oldNameInFileRequest.ExitCode == 0 && oldNameInFileWithoutNewLine != installation.Name)
{
var overwriteNameCommand = Cli.Wrap("ssh")
.WithArguments($@"root@{ip}")
.AppendArgument($"echo '{installation.Name}' > /data/innovenergy/openvpn/installation-name");
var overwriteNameResponse = await overwriteNameCommand
.WithValidation(CommandResultValidation.None).ExecuteBufferedAsync();
if (overwriteNameResponse.ExitCode != 0)
{
Console.WriteLine(overwriteNameResponse.StandardError);
Console.WriteLine("Renaming did not work");
}
else
{
var rebootAfterRename = await Cli.Wrap("ssh")
.WithArguments($@"root@{ip}")
.AppendArgument("reboot")
.WithValidation(CommandResultValidation.None).ExecuteBufferedAsync();
if (rebootAfterRename.ExitCode != 0)
{
Console.WriteLine(overwriteNameResponse.StandardError);
Console.WriteLine("Rebooting did not work");
}
else
{
Console.WriteLine($"Renamed and rebooted {installation.Name}");
}
}
2023-05-11 13:41:41 +00:00
}
2023-04-27 14:59:45 +00:00
}
private static Boolean RunTransaction(Func<Boolean> func)
{
var savepoint = Connection.SaveTransactionPoint();
var success = false;
try
{
success = func();
}
finally
{
if (success)
Connection.Release(savepoint);
else
Connection.RollbackTo(savepoint);
}
return success;
}
2023-04-27 14:59:45 +00:00
}
public class AccToken
{
public UInt64 idUser { get; init;}
public String token { get; init;}
}