diff --git a/csharp/App/Backend/Backend.csproj b/csharp/App/Backend/Backend.csproj index 71cefbddc..fc491daee 100644 --- a/csharp/App/Backend/Backend.csproj +++ b/csharp/App/Backend/Backend.csproj @@ -34,6 +34,7 @@ + diff --git a/csharp/App/Backend/DataTypes/Installation.cs b/csharp/App/Backend/DataTypes/Installation.cs index 067da8cba..b0c2c0b33 100644 --- a/csharp/App/Backend/DataTypes/Installation.cs +++ b/csharp/App/Backend/DataTypes/Installation.cs @@ -10,7 +10,7 @@ public class Installation : TreeNode // TODO: make relation //public IReadOnlyList OrderNumbers { get; set; } = Array.Empty(); - public String OrderNumbers { get; set; } = ""; + public String? OrderNumbers { get; set; } = ""; public Double Lat { get; set; } public Double Long { get; set; } diff --git a/csharp/App/Backend/DataTypes/Methods/ExoCmd.cs b/csharp/App/Backend/DataTypes/Methods/ExoCmd.cs index 4f935e17b..129f500da 100644 --- a/csharp/App/Backend/DataTypes/Methods/ExoCmd.cs +++ b/csharp/App/Backend/DataTypes/Methods/ExoCmd.cs @@ -1,71 +1,63 @@ -using CliWrap; -using CliWrap.Buffered; -using InnovEnergy.Lib.Utils; +using System.Text.Json; +using InnovEnergy.Lib.S3Utils; +using InnovEnergy.Lib.S3Utils.DataTypes; +using System.Diagnostics.CodeAnalysis; namespace InnovEnergy.App.Backend.DataTypes.Methods; public static class ExoCmd { - private static readonly Command Exo = Cli.Wrap("exo"); - private const String ConfigFile = "./exoscale.toml"; - + [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "")] + private static readonly S3Credentials? S3Creds = JsonSerializer.Deserialize("./exoscaleS3.json"); + public static async Task<(String key, String secret)> CreateReadKey(this Installation installation) { - //if (installation.Id != 1) return "help"; //Todo remove me I am for debugging + var iamService = new S3Region(installation.Region, S3Creds!).GetIamClient(); + if (!await Iam.UserExists(iamService, $"READ{installation.BucketName()}")) + { + + var readOnlyPolicy = $"{installation.BucketName()}"; // TODO make me + await Iam.CreateUserAsync(iamService, $"READ{installation.BucketName()}"); + await Iam.PutUserPolicyAsync(iamService, $"READ{installation.BucketName()}", $"READ{installation.BucketName()}",readOnlyPolicy); + } + + var keySecret = await Iam.CreateAccessKeyAsync(iamService, $"READ{installation.BucketName()}"); - - var preParse = await Exo - .WithArguments("iam access-key create " + installation.BucketName() - + " --operation get-sos-object" - + " --resource sos/bucket:" + installation.BucketName() - + " -C " + ConfigFile - + " -O text") - .ExecuteBufferedAsync(); + return (keySecret.AccessKeyId, keySecret.SecretAccessKey); + } + + public static async Task RevokeReadKey(this Installation installation) + { + var iamService = new S3Region(installation.Region, S3Creds!).GetIamClient(); + if (!await Iam.UserExists(iamService, $"READ{installation.BucketName()}")) + { + return true; + } - var key = preParse.StandardOutput.Split("\t")[2]; - var secret = preParse.StandardOutput.Split("\t")[3]; - - return (key, secret); - - //return $"{key};{secret}"; + return await Iam.RevokeAccessKey(iamService, $"READ{installation.BucketName()}"); } public static async Task<(String key, String secret)> CreateWriteKey(this Installation installation) { - //if (installation.Id != 1) return "help"; //Todo remove me I am for debugging + var iamService = new S3Region(installation.Region, S3Creds!).GetIamClient(); + if (!await Iam.UserExists(iamService, $"READWRITE{installation.BucketName()}")) + { + var readWritePolicy = $"{installation.BucketName()}"; // TODO make me + await Iam.CreateUserAsync(iamService, $"READWRITE{installation.BucketName()}"); + await Iam.PutUserPolicyAsync(iamService, $"READWRITE{installation.BucketName()}", $"READWRITE{installation.BucketName()}",readWritePolicy); + } + + var keySecret = await Iam.CreateAccessKeyAsync(iamService, $"READWRITE{installation.BucketName()}"); - - var preParse = await Exo - .WithArguments("iam access-key create " + installation.BucketName() - + " --resource sos/bucket:" + installation.BucketName() - + " -C " + ConfigFile - + " -O text") - .ExecuteBufferedAsync(); - - var key = preParse.StandardOutput.Split("\t")[2]; - var secret = preParse.StandardOutput.Split("\t")[3]; - - return (key, secret); - - //return $"{key};{secret}"; + return (keySecret.AccessKeyId, keySecret.SecretAccessKey); } - - public static async Task RevokeReadKey(this Installation installation) + + + public static async Task CreateBucket(this Installation installation) { - try - { - await Exo - .WithArguments("iam access-key revoke " + installation.S3Key + " -f " + " -C " + ConfigFile) - .WithValidation(CommandResultValidation.None) - .ExecuteAsync(); - } - catch - { - // TODO - ("Failed to revoke key for installation " + installation.Name).WriteLine(); - } + var s3Region = new S3Region(installation.Region, S3Creds!); + return await s3Region.PutBucket(installation.BucketName()) != null; } - } \ No newline at end of file diff --git a/csharp/App/Backend/DataTypes/Methods/Installation.cs b/csharp/App/Backend/DataTypes/Methods/Installation.cs index 7f3ffd55e..420b905b4 100644 --- a/csharp/App/Backend/DataTypes/Methods/Installation.cs +++ b/csharp/App/Backend/DataTypes/Methods/Installation.cs @@ -1,4 +1,5 @@ using InnovEnergy.App.Backend.Database; +using InnovEnergy.Lib.S3Utils; using InnovEnergy.Lib.Utils; namespace InnovEnergy.App.Backend.DataTypes.Methods; @@ -31,27 +32,12 @@ public static class InstallationMethods return Db.Update(installation); } - - public static Task CreateBucket(this Installation installation) - { - // TODO - throw new NotImplementedException(); - - // return S3Access - // .Admin - // .CreateBucket(installation.BucketName()); - } - public static Task DeleteBucket(this Installation installation) + public static async Task DeleteBucket(this Installation installation) { - // TODO - - throw new NotImplementedException(); - - // return S3Access - // .ReadWrite - // .DeleteBucket(installation.BucketName()); + // TODO We dont do this here + return true; } public static IEnumerable UsersWithAccess(this Installation installation) @@ -138,7 +124,7 @@ public static class InstallationMethods public static Installation FillOrderNumbers(this Installation installation) { - installation.OrderNumbers = installation.GetOrderNumbers(); + installation.OrderNumbers = installation.GetOrderNumbers().ToString(); return installation; } diff --git a/csharp/App/Backend/DataTypes/Methods/Session.cs b/csharp/App/Backend/DataTypes/Methods/Session.cs index 488465263..1376342ac 100644 --- a/csharp/App/Backend/DataTypes/Methods/Session.cs +++ b/csharp/App/Backend/DataTypes/Methods/Session.cs @@ -87,7 +87,7 @@ public static class SessionMethods && user.HasWriteAccess && user.HasAccessToParentOf(installation) && Db.Create(installation) // TODO: these two in a transaction - && installation.SetOrderNumbers() + // && installation.SetOrderNumbers() && Db.Create(new InstallationAccess { UserId = user.Id, InstallationId = installation.Id }) && await installation.CreateBucket() && await installation.RenewS3Credentials(); // generation of access _after_ generation of @@ -101,7 +101,7 @@ public static class SessionMethods var user = session?.User; var original = Db.GetInstallationById(installation?.Id); - var originalOrderNumbers = original!.GetOrderNumbers(); + var originalOrderNumbers = original.OrderNumbers; if (!Equals(originalOrderNumbers, installation?.OrderNumbers)) { diff --git a/csharp/App/Backend/DataTypes/Methods/exoscale.toml b/csharp/App/Backend/DataTypes/Methods/exoscale.toml deleted file mode 100644 index 58336b073..000000000 --- a/csharp/App/Backend/DataTypes/Methods/exoscale.toml +++ /dev/null @@ -1,10 +0,0 @@ -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/DataTypes/Methods/exoscaleS3.json b/csharp/App/Backend/DataTypes/Methods/exoscaleS3.json new file mode 100644 index 000000000..15df82368 --- /dev/null +++ b/csharp/App/Backend/DataTypes/Methods/exoscaleS3.json @@ -0,0 +1,4 @@ +{ + "Key": "EXOf67c5b528282988503ddab12", + "Secret": "KBFh5HvoSQcTtGYcWSm4Qn4m-WFutKe89UqsOdOL-ts" +} \ No newline at end of file diff --git a/csharp/App/Backend/Properties/launchSettings.json b/csharp/App/Backend/Properties/launchSettings.json index c1c45c271..3bef649bb 100644 --- a/csharp/App/Backend/Properties/launchSettings.json +++ b/csharp/App/Backend/Properties/launchSettings.json @@ -9,7 +9,8 @@ "launchUrl": "swagger", "applicationUrl": "https://localhost:7087", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Development", + "HOME":"~/backend" } } } diff --git a/csharp/App/Backend/S3/S3Access.cs b/csharp/App/Backend/S3/S3Access.cs deleted file mode 100644 index c71a3d317..000000000 --- a/csharp/App/Backend/S3/S3Access.cs +++ /dev/null @@ -1,20 +0,0 @@ -// using System.Diagnostics.CodeAnalysis; -// using static System.IO.File; -// using static System.Text.Json.JsonSerializer; -// -// namespace InnovEnergy.App.Backend.S3; -// -// [SuppressMessage("Trimming", "IL2026:Members annotated with \'RequiresUnreferencedCodeAttribute\' require dynamic access otherwise can break functionality when trimming application code")] -// public static class S3Access -// { -// public static S3Cmd ReadOnly => ParseJsonFile("./Resources/s3ReadOnlyKey.json")!; -// -// private static T? ParseJsonFile(String file) -// { -// var fileStream = OpenRead(file); -// return Deserialize(fileStream); -// } -// -// public static S3Cmd ReadWrite => Deserialize(OpenRead("./Resources/s3ReadWriteKey.json"))!; -// public static S3Cmd Admin => Deserialize(OpenRead("./Resources/s3AdminKey.json"))!; -// } \ No newline at end of file diff --git a/csharp/App/Backend/S3/S3Cmd.cs b/csharp/App/Backend/S3/S3Cmd.cs deleted file mode 100644 index 5869d4232..000000000 --- a/csharp/App/Backend/S3/S3Cmd.cs +++ /dev/null @@ -1,90 +0,0 @@ -// using System.Diagnostics.CodeAnalysis; -// using CliWrap; -// using CliWrap.Buffered; -// using InnovEnergy.Lib.Utils; -// -// #pragma warning disable CS8618 -// -// namespace InnovEnergy.App.Backend.S3; -// -// [SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Global")] -// public class S3Cmd -// { -// private static readonly Command Python = Cli.Wrap("python3"); -// -// private const String S3CmdPath = "Resources/s3cmd.py"; -// private const String S3Prefix = "s3://"; -// -// public String Key { get; init; } -// public String Secret { get; init; } -// public String Region { get; init; } = "sos-ch-dk-2.exo.io"; -// -// [Obsolete("Only to be used by Json-Deserializer")] public S3Cmd() -// {} -// -// public async Task CreateBucket(String bucketName) -// { -// const String cors = "./Resources/CORS"; -// -// var makeBucket = await Run(bucketName, "mb"); -// -// if (makeBucket.ExitCode != 0) -// return false; -// -// var setCors = await Run(bucketName, "setcors", cors); -// -// return setCors.ExitCode == 0; -// } -// -// public async Task ListFilesInBucket(String bucketName) -// { -// var result = await Run(bucketName, "ls"); -// return result.StandardOutput; -// } -// -// public async Task?> GetFileLines(String bucketName, String filename) -// { -// try -// { -// await Run(bucketName + "/" + filename, "get", "--force"); -// } -// catch -// { -// return null; -// } -// -// var lines = File.ReadAllLines($"./{filename}"); -// File.Delete(filename); -// return lines; -// } -// -// public async Task DeleteBucket(String bucketName) -// { -// var result = await Run(bucketName, "rb"); -// return result.ExitCode == 0; -// } -// -// private Task Run(String s3Path, String operation, params String[] optionalArgs) -// { -// var credentials = new[] -// { -// S3CmdPath, -// "--access_key", Key, -// "--secret_key", Secret, -// "--host" , Region -// }; -// -// var args = credentials -// .Append(operation) -// .Concat(optionalArgs) -// .Append(s3Path.EnsureStartsWith(S3Prefix)); -// -// var withArguments = Python -// .WithArguments(args); -// -// return withArguments -// .WithValidation(CommandResultValidation.None) -// .ExecuteBufferedAsync(); -// } -// -// } \ No newline at end of file diff --git a/csharp/App/Backend/S3/exoscale.toml b/csharp/App/Backend/S3/exoscale.toml deleted file mode 100644 index 58336b073..000000000 --- a/csharp/App/Backend/S3/exoscale.toml +++ /dev/null @@ -1,10 +0,0 @@ -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/S3Explorer/Program.cs b/csharp/App/S3Explorer/Program.cs index 95413a4d7..e00a2df02 100644 --- a/csharp/App/S3Explorer/Program.cs +++ b/csharp/App/S3Explorer/Program.cs @@ -4,6 +4,7 @@ using Amazon.S3.Model; using InnovEnergy.Lib.S3Utils; using InnovEnergy.Lib.S3Utils.DataTypes; using InnovEnergy.Lib.Utils; +using S3Cfg = InnovEnergy.Lib.S3Utils.S3Cfg; namespace InnovEnergy.App.S3Explorer; diff --git a/csharp/App/VrmGrabber/Controller.cs b/csharp/App/VrmGrabber/Controller.cs index 461f9a1d6..d2012c8a9 100644 --- a/csharp/App/VrmGrabber/Controller.cs +++ b/csharp/App/VrmGrabber/Controller.cs @@ -191,17 +191,19 @@ th { /* header cell */ for (var batteryId = 3; batteryId < Int64.Parse(numberOfBatteries) + 2; batteryId++) { localCommand = localCommand.Append( - $" && sleep 3m && /opt/innovenergy/scripts/upload-bms-firmware {batteryTtyName} {batteryId} /opt/innovenergy/{FirmwareVersion}.bin"); + $" && sleep 3m && /opt/innovenergy/scripts/upload-bms-firmware {batteryTtyName} {batteryId} /opt/innovenergy/bms-firmware/{FirmwareVersion}.bin"); } #pragma warning disable CS4014 Db.ExecuteBufferedAsyncCommandOnIp(installationIp, localCommand) - .ContinueWith(t => + .ContinueWith(async t => { if (t.Status == TaskStatus.RanToCompletion) { installation.BatteryUpdateStatus = "Complete"; Db.Update(installation: installation); - UpdateVrmTagsToNewFirmware(installationIp); + var vrmInst = await FindVrmInstallationByIp(installation.Ip!); + await UpdateVrmTagsToNewFirmware(installationIp); + await Db.UpdateAlarms(vrmInst); } else { @@ -236,8 +238,8 @@ th { /* header cell */ private static async Task SendNewBatteryFirmware(String installationIp) { await Cli.Wrap("rsync") - .WithArguments($@"-r {FirmwareVersion}.bin") - .AppendArgument($@"root@{installationIp}:/opt/innovenergy/bms-firmware/{FirmwareVersion}.bin") + .WithArguments($@"-r --relative bms-firmware/{FirmwareVersion}.bin") + .AppendArgument($@"root@{installationIp}:/opt/innovenergy") .ExecuteAsync(); } // [HttpGet(nameof(GetInstallation))] diff --git a/csharp/App/VrmGrabber/Database/Db.cs b/csharp/App/VrmGrabber/Database/Db.cs index 79599c9dc..f0adf3cda 100644 --- a/csharp/App/VrmGrabber/Database/Db.cs +++ b/csharp/App/VrmGrabber/Database/Db.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using System.IO.Enumeration; using System.Runtime.InteropServices; using System.Text.Json.Nodes; using System.Web; @@ -80,9 +81,10 @@ public static partial class Db foreach (var installation in installations) { Console.WriteLine(installation.Name); - sd_notify(0, "WATCHDOG=1"); + sd_notify(0, "WATCHDOG=1"); var details = await GetInstallationDetails(installation); - await updateAlarms(installation); + // Thread.Sleep(1000); + await UpdateAlarms(installation); var ip = Ip(details); var updatedInstallation = new Installation( installation.Name, @@ -113,23 +115,21 @@ public static partial class Db } } - [RequiresUnreferencedCode("Calls System.Text.Json.JsonSerializer.SerializeToElement(TValue, JsonSerializerOptions)")] - private static async Task updateAlarms(VrmInstallation installation) + [RequiresUnreferencedCode( + "Calls System.Text.Json.JsonSerializer.SerializeToElement(TValue, JsonSerializerOptions)")] + public static async Task UpdateAlarms(VrmInstallation installation) { // installation.GetDevices().batteryMonitor.setTemperatureAlarms(245,250,315,313); - var alarmJson = Deserialize(""" - { - "AlarmEnabled": 1, - "NotifyAfterSeconds": 60, - "highAlarm": 315, - "highAlarmHysteresis": 313, - "lowAlarm": 245, - "lowAlarmHysteresis": 250 - } - """)!; + var alarmJson = JsonNode.Parse(File.ReadAllText("./alarm.json"))!.AsObject(); var tags = await installation.GetTags(); if (tags.Contains("FM-AF09")) + { + // Console.WriteLine(installation.IdSite.ToString()); + // await installation.GetAlarms(); return await installation.SetAlarms(alarmJson); + + } + return true; } diff --git a/csharp/App/VrmGrabber/alarm.json b/csharp/App/VrmGrabber/alarm.json new file mode 100644 index 000000000..a99f75c16 --- /dev/null +++ b/csharp/App/VrmGrabber/alarm.json @@ -0,0 +1,10 @@ +{ + "idDataAttribute":115, + "instance":1, + "lowAlarm":245, + "lowAlarmHysteresis":250, + "highAlarm":315, + "highAlarmHysteresis":313, + "AlarmEnabled":1, + "NotifyAfterSeconds":60, + "meta_info": {"icon":"device-battery-monitor","name":"Battery Monitor [1]","idDeviceType":2,"dataAttribute":"Battery temperature"}} diff --git a/csharp/App/VrmGrabber/db.sqlite b/csharp/App/VrmGrabber/db.sqlite index 81843140c..4847f0a8b 100644 Binary files a/csharp/App/VrmGrabber/db.sqlite and b/csharp/App/VrmGrabber/db.sqlite differ diff --git a/csharp/Lib/S3Utils/DataTypes/S3Cfg.cs b/csharp/Lib/S3Utils/DataTypes/S3Cfg.cs index 4f5ce85ab..cb362c413 100644 --- a/csharp/Lib/S3Utils/DataTypes/S3Cfg.cs +++ b/csharp/Lib/S3Utils/DataTypes/S3Cfg.cs @@ -57,7 +57,7 @@ public static class S3Cfg Secret: cfg["secret_key"] ); - return new S3Region(Name: cfg["host_base"], Credentials: credentials); + return new S3Region(cfg["host_base"], credentials); } catch { diff --git a/csharp/Lib/S3Utils/DataTypes/S3Region.cs b/csharp/Lib/S3Utils/DataTypes/S3Region.cs index 2e507dfaf..034b0b87a 100644 --- a/csharp/Lib/S3Utils/DataTypes/S3Region.cs +++ b/csharp/Lib/S3Utils/DataTypes/S3Region.cs @@ -1,7 +1,13 @@ namespace InnovEnergy.Lib.S3Utils.DataTypes; public record S3Region -( - String Name, - S3Credentials Credentials -); +{ + public S3Region(String name, S3Credentials creds) + { + Name = name; + Credentials = creds; + } + public String Name { get; init; } + public S3Credentials Credentials { get; init; } + +} diff --git a/csharp/Lib/S3Utils/Iam.cs b/csharp/Lib/S3Utils/Iam.cs index 7a55c3158..d43c0979f 100644 --- a/csharp/Lib/S3Utils/Iam.cs +++ b/csharp/Lib/S3Utils/Iam.cs @@ -1,5 +1,7 @@ using System.Collections.Concurrent; +using System.Net; using Amazon.IdentityManagement; +using Amazon.IdentityManagement.Model; using Amazon.Runtime; using InnovEnergy.Lib.S3Utils.DataTypes; using InnovEnergy.Lib.Utils; @@ -10,7 +12,9 @@ public static class Iam { // TODO + + private static readonly ConcurrentDictionary AimClientCache = new(); public static AmazonIdentityManagementServiceClient GetIamClient(this S3Url url ) => url.Bucket.GetIamClient(); @@ -23,10 +27,48 @@ public static class Iam private static AmazonIdentityManagementServiceClient CreateIamClient(S3Region region) => new ( credentials: new BasicAWSCredentials(region.Credentials.Key, region.Credentials.Secret), - clientConfig: new() { ServiceURL = StringUtils.EnsureStartsWith(region.Name, "https://") } + clientConfig: new() { ServiceURL = region.Name.EnsureStartsWith("https://") } ); + public static async Task CreateUserAsync(AmazonIdentityManagementServiceClient iamService,String userName) + { + var response = await iamService.CreateUserAsync(new CreateUserRequest { UserName = userName }); + return response.User; + } - + public static async Task PutUserPolicyAsync(AmazonIdentityManagementServiceClient iamService, String userName, String policyName, String policyDocument) + { + var request = new PutUserPolicyRequest() + { + UserName = userName, + PolicyName = policyName, + PolicyDocument = policyDocument + }; + + var response = await iamService.PutUserPolicyAsync(request); + return response.HttpStatusCode == System.Net.HttpStatusCode.OK; + } + public static async Task CreateAccessKeyAsync(AmazonIdentityManagementServiceClient iamService, String userName) + { + var response = await iamService.CreateAccessKeyAsync(new CreateAccessKeyRequest + { + UserName = userName, + }); + + return response.AccessKey; + + } + + public static async Task UserExists(AmazonIdentityManagementServiceClient iamService, String userName) + { + var response = await iamService.GetUserAsync(new GetUserRequest { UserName = userName }); + return response.HttpStatusCode == HttpStatusCode.OK; + } + + public static async Task RevokeAccessKey(AmazonIdentityManagementServiceClient iamService, String userName) + { + var response = await iamService.DeleteAccessKeyAsync(new DeleteAccessKeyRequest{ AccessKeyId = userName }); + return response.HttpStatusCode == HttpStatusCode.OK; + } } \ No newline at end of file diff --git a/csharp/Lib/S3Utils/S3.cs b/csharp/Lib/S3Utils/S3.cs index 345d41ce5..b80458e82 100644 --- a/csharp/Lib/S3Utils/S3.cs +++ b/csharp/Lib/S3Utils/S3.cs @@ -15,13 +15,6 @@ public static class S3 { private static readonly ConcurrentDictionary S3ClientCache = new(); - // QOL method - public static S3Region Region(this S3Credentials credentials, String name) => new - ( - Name: name, - Credentials: credentials - ); - // QOL method public static S3Bucket Bucket(this S3Region region, String name) => new ( @@ -179,7 +172,7 @@ public static class S3 credentials: new BasicAWSCredentials(region.Credentials.Key, region.Credentials.Secret), clientConfig: new() { - ServiceURL = StringUtils.EnsureStartsWith(region.Name, "https://"), + ServiceURL = region.Name.EnsureStartsWith("https://"), ForcePathStyle = true, } ); diff --git a/csharp/Lib/S3Utils/S3Cfg.cs b/csharp/Lib/S3Utils/S3Cfg.cs index 2f9f9a328..a55209247 100644 --- a/csharp/Lib/S3Utils/S3Cfg.cs +++ b/csharp/Lib/S3Utils/S3Cfg.cs @@ -58,7 +58,7 @@ public static class S3Cfg Secret: cfg["secret_key"] ); - return new S3Region(Name: cfg["host_base"], Credentials: credentials); + return new S3Region(cfg["host_base"], credentials); } catch { diff --git a/csharp/Lib/S3Utils/S3Utils.csproj b/csharp/Lib/S3Utils/S3Utils.csproj index e672ba589..a161ec092 100644 --- a/csharp/Lib/S3Utils/S3Utils.csproj +++ b/csharp/Lib/S3Utils/S3Utils.csproj @@ -16,18 +16,4 @@ - - - - - - - - - - - - - - diff --git a/csharp/Lib/Victron/VictronVRM/FlurlExtensions.cs b/csharp/Lib/Victron/VictronVRM/FlurlExtensions.cs index dbd443571..47be48176 100644 --- a/csharp/Lib/Victron/VictronVRM/FlurlExtensions.cs +++ b/csharp/Lib/Victron/VictronVRM/FlurlExtensions.cs @@ -2,6 +2,7 @@ using System.Net; using System.Text.Json.Nodes; using Flurl.Http; using Flurl.Http.Content; +using InnovEnergy.Lib.Utils; using static System.Net.Http.HttpMethod; namespace InnovEnergy.Lib.Victron.VictronVRM; @@ -20,6 +21,12 @@ public static class FlurlExtensions var stream = await TryRequest(request, Post, content).ReceiveStream(); return JsonNode.Parse(stream)!; } + + public static async Task TryPutJson(this IFlurlRequest request, JsonObject? content = null) + { + var stream = await TryRequest(request, Put, content).ReceiveStream(); + return JsonNode.Parse(stream)!; + } private static async Task TryRequest(this IFlurlRequest request, HttpMethod verb, JsonObject? data = null) { diff --git a/csharp/Lib/Victron/VictronVRM/Installation.Alarms.cs b/csharp/Lib/Victron/VictronVRM/Installation.Alarms.cs index 38c54ac20..016da8ff0 100644 --- a/csharp/Lib/Victron/VictronVRM/Installation.Alarms.cs +++ b/csharp/Lib/Victron/VictronVRM/Installation.Alarms.cs @@ -1,5 +1,6 @@ using System.Text.Json; using System.Text.Json.Nodes; +using Flurl.Http; namespace InnovEnergy.Lib.Victron.VictronVRM; @@ -10,21 +11,23 @@ public readonly partial record struct Installation public async Task> GetAlarms() { var reply = await VrmAccount.AlarmsRequest(IdSite).TryGetJson(); + // Console.WriteLine("Got"); var vrmReply = new Reply(reply); + Console.WriteLine(vrmReply.ToString()); if (!vrmReply.Success) throw new Exception(nameof(GetAlarms) + " failed"); - + Console.WriteLine(vrmReply.Alarms); return vrmReply.Alarms; } public async Task SetAlarms(JsonObject tags) { - var reply = await VrmAccount.AlarmsRequest(IdSite).TryPostJson(tags); + var reply = await VrmAccount.AlarmsRequest(IdSite).TryPutJson(tags); var vrmReply = new Reply(reply); + // Console.WriteLine(vrmReply.Success.ToString()); if (!vrmReply.Success) throw new Exception(nameof(SetAlarms) + " failed"); - return vrmReply.Success; } } \ No newline at end of file diff --git a/csharp/Lib/Victron/VictronVRM/Reply.cs b/csharp/Lib/Victron/VictronVRM/Reply.cs index af91e9b3d..35b5190ed 100644 --- a/csharp/Lib/Victron/VictronVRM/Reply.cs +++ b/csharp/Lib/Victron/VictronVRM/Reply.cs @@ -9,7 +9,7 @@ public readonly record struct Reply(JsonNode Json) public Boolean Success => Json.TryGetBoolean("success") is not null or true; public IReadOnlyList Tags => Json.GetArray("tags"); - public IReadOnlyList Alarms => Json.GetArray("alarms"); + public IReadOnlyList Alarms => Json.GetArray("alarms"); public JsonArray Records => Json.GetArray("records"); public IReadOnlyList Devices => Json["records"]!