using System.Diagnostics.CodeAnalysis; using System.Reactive.Concurrency; using System.Reactive.Linq; using System.Reactive.Threading.Tasks; using CliWrap; using CliWrap.Buffered; using InnovEnergy.App.RemoteSupportConsole; using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Victron.VictronVRM; using SQLite; using static System.Text.Json.JsonSerializer; using Installation = InnovEnergy.App.VrmGrabber.DataTypes.Installation; namespace InnovEnergy.App.VrmGrabber.Database; public class InstallationDetails { public InstallationDetails(String ip, IReadOnlyList details) { Details = details; Ip = ip; } public IReadOnlyList? Details { get; set; } public String Ip { get; set; } } public static partial class Db { internal const String DbPath = "./db.sqlite"; public static Dictionary InstallationsAndDetails; private static SQLiteConnection Connection { get; } = new SQLiteConnection(DbPath); public static TableQuery Installations => Connection.Table(); public static void Init() { // used to force static constructor } static Db() { // on startup create/migrate tables Connection.RunInTransaction(() => { // Connection.CreateTable(); });// on startup create/migrate tables InstallationsAndDetails = new Dictionary(); Observable.Interval(TimeSpan.FromMinutes(5)) //Repeat(0) .ObserveOn(TaskPoolScheduler.Default) .SubscribeOn(TaskPoolScheduler.Default) .StartWith(0) // Do it right away (on startup) .Select(UpdateInstallationsAndDetailsFromVrm) // .Select(t => t.ToObservable()) // .Concat() .Subscribe(d => InstallationsAndDetails = d, exception => exception.WriteLine()); } [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "")] private static Dictionary UpdateInstallationsAndDetailsFromVrm(Int64 _) { var fileContent = File.ReadAllTextAsync("./token.json").Result; var acc = Deserialize(fileContent); var user = VrmAccount.Token(acc.idUser, acc.token); var installations = user.GetInstallations().Result; return installations.Take(30) .Do(i=>i.Name.WriteLine()) .ToDictionary(i => i, GetInstallationDetails); } private static InstallationDetails GetInstallationDetails(Lib.Victron.VictronVRM.Installation i) { // Thread.Sleep(3000); IReadOnlyList details; try { details = i.GetDetails().Result; var ip = VpnInfo.LookUpIp(i.Identifier, details.MachineSerial()).Result ?? "Unknown"; if(ip != "Unknown") UpdateInstallationName(i, ip); return new InstallationDetails(ip,details); } catch (Exception e) { Console.WriteLine(e); } return new InstallationDetails("Unkown", Array.Empty()); } private static async Task UpdateInstallationName(Lib.Victron.VictronVRM.Installation installation, String ip) { var command = Cli.Wrap("ssh") .WithArguments($@"root@{ip}") .AppendArgument("-o StrictHostKeyChecking=accept-new") .AppendArgument($"echo '{installation.Name}' > /data/innovenergy/openvpn/installation-name"); Console.WriteLine(command.ToString()); var x = await command .WithValidation(CommandResultValidation.None).ExecuteBufferedAsync(); if (x.ExitCode != 0) { Console.WriteLine(x.StandardError); Console.WriteLine("Renaming did not work"); } } } public class AccToken { public UInt64 idUser { get; init;} public String token { get; init;} }