diff --git a/csharp/App/Backend/Controller.cs b/csharp/App/Backend/Controller.cs index 6adc74a2f..188bfcc92 100644 --- a/csharp/App/Backend/Controller.cs +++ b/csharp/App/Backend/Controller.cs @@ -254,7 +254,7 @@ public class Controller : ControllerBase [HttpPost(nameof(CreateUser))] public ActionResult CreateUser(User newUser, Token authToken) { - return Db.GetSession(authToken).Create(newUser) + return Db.GetSession(authToken).Create(newUser) ? newUser.HidePassword() : Unauthorized() ; } diff --git a/csharp/App/Backend/DataTypes/Methods/ExoCmd.cs b/csharp/App/Backend/DataTypes/Methods/ExoCmd.cs index f4569d54b..4f935e17b 100644 --- a/csharp/App/Backend/DataTypes/Methods/ExoCmd.cs +++ b/csharp/App/Backend/DataTypes/Methods/ExoCmd.cs @@ -58,6 +58,7 @@ public static class ExoCmd { await Exo .WithArguments("iam access-key revoke " + installation.S3Key + " -f " + " -C " + ConfigFile) + .WithValidation(CommandResultValidation.None) .ExecuteAsync(); } catch diff --git a/csharp/App/Backend/DataTypes/Methods/Installation.cs b/csharp/App/Backend/DataTypes/Methods/Installation.cs index aaca63b3f..3ec874011 100644 --- a/csharp/App/Backend/DataTypes/Methods/Installation.cs +++ b/csharp/App/Backend/DataTypes/Methods/Installation.cs @@ -7,7 +7,7 @@ namespace InnovEnergy.App.Backend.DataTypes.Methods; public static class InstallationMethods { - private const String BucketNameSalt = "3e5b3069-214a-43ee-8d85-57d72000c10d"; + private const String BucketNameSalt = "3e5b3069-214a-43ee-8d85-57d72000c19d"; public static String BucketName(this Installation installation) { diff --git a/csharp/App/Backend/DataTypes/Methods/Session.cs b/csharp/App/Backend/DataTypes/Methods/Session.cs index 2c259ffc9..52683e16f 100644 --- a/csharp/App/Backend/DataTypes/Methods/Session.cs +++ b/csharp/App/Backend/DataTypes/Methods/Session.cs @@ -86,12 +86,14 @@ public static class SessionMethods return user is not null && installation is not null && user.HasWriteAccess - && user.HasAccessTo(installation.Parent()) + && user.HasAccessToParentOf(installation) && Db.Create(installation) // TODO: these two in a transaction && Db.Create(new InstallationAccess { UserId = user.Id, InstallationId = installation.Id }) && await installation.CreateBucket() && await installation.RenewS3Credentials(); // generation of access _after_ generation of - // bucket to prevent "zombie" access-rights. + // bucket to prevent "zombie" access-rights. + // This might fuck us over if the creation of access rights fails, + // as bucket-names are unique and bound to the installation id... -K } public static Boolean Update(this Session? session, Installation? installation) @@ -155,10 +157,12 @@ public static class SessionMethods && sessionUser.HasWriteAccess && newUser .WithParent(sessionUser) - .Do(() => newUser.Password = newUser.SaltAndHashPassword(newUser.Password)) .Do(() => newUser.MustResetPassword = true) - .Apply(Db.Create) - && Mailer.Mailer.SendVerificationMessage(newUser); + .Do(() => newUser.Password = newUser.SaltAndHashPassword(newUser.Password)) + .Apply(Db.Create); + // && Mailer.Mailer.SendVerificationMessage(newUser); + + // .Do(() => newUser.Password = newUser.SaltAndHashPassword(newUser.Password)) //Send Email to new user to verify email and set password diff --git a/csharp/App/Backend/DataTypes/Methods/exoscale.toml b/csharp/App/Backend/DataTypes/Methods/exoscale.toml new file mode 100644 index 000000000..58336b073 --- /dev/null +++ b/csharp/App/Backend/DataTypes/Methods/exoscale.toml @@ -0,0 +1,10 @@ +defaultaccount = "Kim" + +[[accounts]] + account = "innovenergy-ag" + defaultZone = "ch-dk-2" + endpoint = "https://api.exoscale.com/v1" + environment = "" + key = "EXOf67c5b528282988503ddab12" + name = "Kim" + secret = "KBFh5HvoSQcTtGYcWSm4Qn4m-WFutKe89UqsOdOL-ts" diff --git a/csharp/App/Backend/Database/Db.cs b/csharp/App/Backend/Database/Db.cs index 95b3e4aa7..45d6e4097 100644 --- a/csharp/App/Backend/Database/Db.cs +++ b/csharp/App/Backend/Database/Db.cs @@ -24,7 +24,7 @@ public static partial class Db { var latestDb = new DirectoryInfo(@"DbBackups").GetFiles() .OrderBy(f => f.LastWriteTime) - .First().Name; + .Last().Name; var fileConnection = new SQLiteConnection("DbBackups/"+latestDb); @@ -129,7 +129,7 @@ public static partial class Db Connection.CreateTable(); }); - Observable.Interval(TimeSpan.FromDays(0.5)) + Observable.Interval(TimeSpan.FromHours(0.5)) .StartWith(0) // Do it right away (on startup) .ObserveOn(TaskPoolScheduler.Default) .SubscribeOn(TaskPoolScheduler.Default) @@ -182,8 +182,7 @@ public static partial class Db var installationsToUpdate = Installations .Select(i => i) - .Where(i => bucketList.StandardOutput.Contains("\"" + i.BucketName())).ToList() - ; + .Where(i => bucketList.StandardOutput.Contains("\"" + i.BucketName() + "\"")).ToList(); foreach (var installation in installationsToUpdate) { diff --git a/csharp/App/Backend/S3/S3Cmd.cs b/csharp/App/Backend/S3/S3Cmd.cs index 4a077a9f7..e5783f833 100644 --- a/csharp/App/Backend/S3/S3Cmd.cs +++ b/csharp/App/Backend/S3/S3Cmd.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using System.Drawing; using CliWrap; using CliWrap.Buffered; using InnovEnergy.Lib.Utils; @@ -14,7 +15,8 @@ public class S3Cmd private const String S3Prefix = "s3://"; public String Key { get; init;} - public String Secret { get; init;} + public String Secret { get; init;} + public String Region { get; init; } = "sos-ch-dk-2.exo.io"; // private String?[] DefaultArgs { get; } @@ -79,6 +81,7 @@ public class S3Cmd S3CmdPath, "--access_key", Key, "--secret_key", Secret, + "--host", Region }; var args = credentials diff --git a/csharp/App/VrmGrabber/Controller.cs b/csharp/App/VrmGrabber/Controller.cs index dba20c829..b907339e8 100644 --- a/csharp/App/VrmGrabber/Controller.cs +++ b/csharp/App/VrmGrabber/Controller.cs @@ -21,9 +21,10 @@ public record InstallationToHtmlInterface( String LastSeen, String NumBatteries, String BatteryVersion, + String BatteryUpdateStatus, String ServerIp = "10.2.0.1", //TODO MAKE ME DYNAMIC String FirmwareVersion = "AF09" //Todo automatically grab newest version? -); + ); [Controller] public class Controller : ControllerBase @@ -95,7 +96,7 @@ th { /* header cell */ - + @@ -105,6 +106,7 @@ th { /* header cell */ + {{#inst}} {{> installations}} @@ -124,7 +126,8 @@ th { /* header cell */ - + + "; var installationsInDb = Db.Installations.OrderBy(i => i.Name, StringComparer.OrdinalIgnoreCase).ToList(); @@ -146,7 +149,8 @@ th { /* header cell */ i.Online, DateTimeOffset.FromUnixTimeSeconds(Convert.ToInt64(i.LastSeen)).ToString(), i.NumberOfBatteries, - i.BatteryFirmwareVersion)); + i.BatteryFirmwareVersion, + i.BatteryUpdateStatus)); var data = new { @@ -179,21 +183,36 @@ th { /* header cell */ } if (split[1] == "Failed" || split2[0] == "Error") return "Update failed"; - await UpdateVrmTagsToNewFirmware(installationIp); + - SendNewBatteryFirmware(installationIp); - - for (var batteryId = 2; batteryId <= Int64.Parse(numberOfBatteries) + 1; batteryId++) + await SendNewBatteryFirmware(installationIp); + var batteryTtyName = split[1].Split(".").Last(); + var localCommand = $"/opt/innovenergy/scripts/upload-bms-firmware {batteryTtyName} 2 /opt/innovenergy/{FirmwareVersion}.bin"; + var installation = Db.Installations.First(installation => installation.Ip == installationIp); + installation.BatteryUpdateStatus = "Running"; + Db.Update(installation: installation); + for (var batteryId = 3; batteryId < Int64.Parse(numberOfBatteries) + 2; batteryId++) { - var batteryTtyName = split[1].Split(".").Last(); - var localCommand = $"/opt/innovenergy/scripts/upload-bms-firmware {batteryTtyName} {batteryId} /opt/innovenergy/bms-firmware/{FirmwareVersion}.bin"; - - #pragma warning disable CS4014 - Db.ExecuteBufferedAsyncCommandOnIp(installationIp, localCommand); - #pragma warning restore CS4014 - - // Console.WriteLine(remoteUpdateCommandResult); + localCommand = localCommand.Append( + $" && /opt/innovenergy/scripts/upload-bms-firmware {batteryTtyName} {batteryId} /opt/innovenergy/{FirmwareVersion}.bin"); } + #pragma warning disable CS4014 + Db.ExecuteBufferedAsyncCommandOnIp(installationIp, localCommand) + .ContinueWith(t => + { + if (t.Status == TaskStatus.RanToCompletion) + { + installation.BatteryUpdateStatus = "Complete"; + Db.Update(installation: installation); + UpdateVrmTagsToNewFirmware(installationIp); + } + else + { + installation.BatteryUpdateStatus = "Failed"; + Db.Update(installation: installation); + } + }); + #pragma warning restore CS4014 return "Battery update is successfully initiated, it will take around 15 minutes to complete! You can close this page now."; } @@ -217,12 +236,12 @@ th { /* header cell */ return await vrmAccount.GetInstallation(installationId!); } - private static void SendNewBatteryFirmware(String installationIp) + private static async Task SendNewBatteryFirmware(String installationIp) { - Cli.Wrap("scp") + await Cli.Wrap("scp") .WithArguments($@"{FirmwareVersion}.bin") - .AppendArgument($@"root@{installationIp}:/opt/innovenergy/bms-firmware/{FirmwareVersion}.bin") - .WithValidation(CommandResultValidation.None).ExecuteBufferedAsync(); + .AppendArgument($@"root@{installationIp}:/opt/innovenergy/{FirmwareVersion}.bin") + .ExecuteAsync(); } // [HttpGet(nameof(GetInstallation))] // [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "")] diff --git a/csharp/App/VrmGrabber/DataTypes/Installation.cs b/csharp/App/VrmGrabber/DataTypes/Installation.cs index 977ce1d59..ff2bd2d24 100644 --- a/csharp/App/VrmGrabber/DataTypes/Installation.cs +++ b/csharp/App/VrmGrabber/DataTypes/Installation.cs @@ -6,7 +6,7 @@ namespace InnovEnergy.App.VrmGrabber.DataTypes; public class Installation { - public Installation(String? argName, String? argIp, Int64 argVrm, String? argIdentifier, String? serial, String? urlEncode, String? online, String? lastSeen, String details, String numberOfBatteries, String batteryFirmwareVersion) + public Installation(String? argName, String? argIp, Int64 argVrm, String? argIdentifier, String? serial, String? urlEncode, String? online, String? lastSeen, String details, String numberOfBatteries, String batteryFirmwareVersion, String? batteryUpdateStatus) { Name = argName; Ip = argIp; @@ -19,6 +19,7 @@ public class Installation Details = details; NumberOfBatteries = numberOfBatteries; BatteryFirmwareVersion = batteryFirmwareVersion; + BatteryUpdateStatus = batteryUpdateStatus; } public Installation() @@ -37,6 +38,7 @@ public class Installation public String? LastSeen { get; set;} public String? NumberOfBatteries { get; set;} public String? BatteryFirmwareVersion { get; set;} + public String? BatteryUpdateStatus { get; set;} public String? Details { get; set; } //JSON } \ No newline at end of file diff --git a/csharp/App/VrmGrabber/Database/Db.cs b/csharp/App/VrmGrabber/Database/Db.cs index 0684c8d09..b454a1d8f 100644 --- a/csharp/App/VrmGrabber/Database/Db.cs +++ b/csharp/App/VrmGrabber/Database/Db.cs @@ -74,7 +74,7 @@ public static partial class Db var readOnlyInstallations = await user.GetInstallations(); var installations = readOnlyInstallations.ToList(); - installations.Shuffle(); + installations.Shuffle(); // This foreach (var installation in installations) { @@ -88,12 +88,14 @@ public static partial class Db (Int64)installation.IdSite, installation.Identifier, details.Details.MachineSerial() ?? "Unknown", - HttpUtility.UrlEncode(installation.Name), + HttpUtility.UrlEncode(installation.Name), ip[1], details.Details.Last().Json["timestamp"].ToString(), Serialize(details.Details), await NumberOfBatteries(ip[0], ip[1]), - await BatteryFirmwareVersion(ip[0], ip[1])); + await BatteryFirmwareVersion(ip[0], ip[1]), + "No updates" + ); if (ip[0] != "Unknown") await UpdateInstallationName(installation, ip[0]); diff --git a/csharp/App/VrmGrabber/db.sqlite b/csharp/App/VrmGrabber/db.sqlite index 60a55002e..85bb6b269 100644 Binary files a/csharp/App/VrmGrabber/db.sqlite and b/csharp/App/VrmGrabber/db.sqlite differ diff --git a/typescript/Frontend/src/config/axiosConfig.tsx b/typescript/Frontend/src/config/axiosConfig.tsx index 95616e2e0..8d9277190 100644 --- a/typescript/Frontend/src/config/axiosConfig.tsx +++ b/typescript/Frontend/src/config/axiosConfig.tsx @@ -1,11 +1,11 @@ import axios from "axios"; export const axiosConfigWithoutToken = axios.create({ - baseURL: "https://monitor.innov.energy/api", + baseURL: "http://localhost:5000/api", }); const axiosConfig = axios.create({ - baseURL: "https://monitor.innov.energy/api", + baseURL: "http://localhost:5000/api", }); axiosConfig.defaults.params = {};
NameName This site is updated once per day! Gui VRM Grafana#Batteries Firmware-Version UpdateLast Update Status
{{Serial}} {{NumBatteries}} {{BatteryVersion}}⬆️{{FirmwareVersion}}⬆️{{FirmwareVersion}}{{BatteryUpdateStatus}}