Fixed a bug that stopped the updating of installations

This commit is contained in:
Kim 2023-05-25 09:18:41 +02:00
parent 5eb373b78e
commit c969b72a82
2 changed files with 71 additions and 29 deletions

View File

@ -1,16 +1,15 @@
using System.Data.Common;
using System.IdentityModel.Tokens.Jwt;
using System.Web;
using CliWrap;
using CliWrap.Buffered;
using HandlebarsDotNet;
using InnovEnergy.App.RemoteSupportConsole;
using InnovEnergy.App.VrmGrabber.Database;
using InnovEnergy.Lib.Utils;
using Microsoft.AspNetCore.Mvc;
using FILE=System.IO.File;
using VrmInstallation = InnovEnergy.Lib.Victron.VictronVRM.Installation;
namespace InnovEnergy.App.VrmGrabber;
public record Install(
public record InstallationToHtmlInterface(
String Name,
String Ip,
Int64 Vrm,
@ -26,12 +25,17 @@ public record Install(
[Controller]
public class Controller : ControllerBase
{
//Todo automatically grab newest version?
private const String FirmwareVersion = "VERSION";
[HttpGet]
[Route("/")]
[Produces("text/html")]
public ActionResult Index()
{
String source = @"<head>
const String source = @"<head>
<style>
tbody {
background-color: #e4f0f5;
@ -84,8 +88,9 @@ public class Controller : ControllerBase
</table>
<div id='managerTable'>";
String partialSource =
@"<tr><td>{{Name}}</td>
const String partialSource = @"<tr><td>{{Name}}</td>
<td><a target='_blank' href=http://{{Ip}}>{{online}} {{Ip}}</a></td>
<td><a target='_blank' href=https://vrm.victronenergy.com/installation/{{Vrm}}/dashboard>VRM</a></td>
<td><a target='_blank' href='https://salidomo.innovenergy.ch/d/ENkNRQXmk/installation?refresh=5s&orgId=1&var-Installation={{EscapedName}}&kiosk=tv'>Grafana</a></td>
@ -94,11 +99,11 @@ public class Controller : ControllerBase
<td>{{Serial}}</td>
<td>{{NumBatteries}}</td>
<td>{{BatteryVersion}}</td>
<td><a target='_blank' href=http://{{serverIp}}/UpdateBatteryFirmware/{{Ip}}>⬆️{{firmwareVersion}}</a></td>
</tr>";
var instList = Db.Installations.ToList();
if (instList.Count == 0) return new ContentResult
var installationsInDb = Db.Installations.ToList();
if (installationsInDb.Count == 0) return new ContentResult
{
ContentType = "text/html",
Content = "<p>Please wait page is still loading</p>"
@ -106,7 +111,7 @@ public class Controller : ControllerBase
Handlebars.RegisterTemplate("installations", partialSource);
var template = Handlebars.Compile(source);
var insts = instList.Select(i => new Install(
var installsForHtml = installationsInDb.Select(i => new InstallationToHtmlInterface(
i.Name,
i.Ip,
i.Vrm,
@ -120,7 +125,9 @@ public class Controller : ControllerBase
var data = new
{
inst = insts
inst = installsForHtml,
serverIp = "10.2.0.1",
firmwareVersion = FirmwareVersion
};
var result = template(data);
@ -132,6 +139,32 @@ public class Controller : ControllerBase
};
}
[HttpGet(nameof(UpdateBatteryFirmware))]
public async Task<ActionResult> UpdateBatteryFirmware(String installationIp, Int64 numOfBatteries)
{
//We need the DeviceName of the battery (ttyUSB?)
var pathToBattery = await Db.ExecuteBufferedAsyncCommandOnIp(installationIp, "dbus-send --system --dest=com.victronenergy.system --type=method_call --print-reply /ServiceMapping/com_victronenergy_battery_1 com.victronenergy.BusItem.GetText");
if (pathToBattery == "Failed") return new BadRequestResult();
SendNewBatteryFirmware(installationIp);
for (var batteryId = 0; batteryId < numOfBatteries; batteryId++)
{
var updateCommand = await Db.ExecuteBufferedAsyncCommandOnIp(installationIp, $"/opt/innovenergy/scripts/upload-bms-firmware {pathToBattery} {batteryId} /opt/innovenergy/bms-firmware/{FirmwareVersion}.bin");
if (updateCommand == "Failed") return new BadRequestResult();
}
return new AcceptedResult();
}
private void SendNewBatteryFirmware(String installationIp)
{
Cli.Wrap("scp")
.WithArguments($@"{FirmwareVersion}.bin")
.AppendArgument($@"root@{installationIp}:/opt/innovenergy/bms-firmware/{FirmwareVersion}.bin")
.WithValidation(CommandResultValidation.None).ExecuteBufferedAsync();
}
// [HttpGet(nameof(GetInstallation))]
// [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
// public Object GetInstallation(UInt64 serialNumber)

View File

@ -1,5 +1,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
using System.Web;
using CliWrap;
using CliWrap.Buffered;
@ -33,7 +35,7 @@ public static partial class Db
public static Dictionary<Installation, InstallationDetails> InstallationsAndDetails;
internal const String DbPath = "./db.sqlite";
private const String DbPath = "./db.sqlite";
private static SQLiteConnection Connection { get; } = new SQLiteConnection(DbPath);
@ -54,10 +56,10 @@ public static partial class Db
public static async Task UpdateDetailsAndInstallations()
{
while (true)
{
do {
await UpdateInstallationsAndDetailsFromVrm(0);
}
while (true) ;
}
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
@ -70,7 +72,7 @@ public static partial class Db
var installations = await user.GetInstallations();
// var returnDictionary = new Dictionary<VrmInstallation, InstallationDetails>();
foreach (var installation in installations.Take(70)) //TODO REMOVE TAKE
foreach (var installation in installations) //TODO REMOVE TAKE
{
Console.WriteLine(installation.Name);
var details = await GetInstallationDetails(installation);
@ -85,8 +87,8 @@ public static partial class Db
ip[1],
details.Details.Last().Json["timestamp"].ToString(),
Serialize(details.Details),
await NumberOfBatteries(ip[0]),
await BatteryFirmwareVersion(ip[0]));
await NumberOfBatteries(ip[0], ip[1]),
await BatteryFirmwareVersion(ip[0], ip[1]));
if (GetInstallationByIdentifier(installation.Identifier) == null)
{
@ -99,34 +101,41 @@ public static partial class Db
}
}
private static async Task<String> BatteryFirmwareVersion(String? ip)
private static async Task<String> BatteryFirmwareVersion(String? ip, String? online)
{
if (ip is null or "Unknown") return "Unknown";
if (ip is null or "Unknown" || online == "❌") return "Unknown";
var pathToBattery = await ExecuteBufferedAsyncCommandOnIp(ip, "dbus-send --system --dest=com.victronenergy.system --type=method_call --print-reply /ServiceMapping/com_victronenergy_battery_1 com.victronenergy.BusItem.GetText");
if (pathToBattery.StartsWith("Error")) return "Unknown";
var command = $"dbus-send --system --dest={pathToBattery} --type=method_call --print-reply /FirmwareVersion com.victronenergy.BusItem.GetText";
return await ExecuteBufferedAsyncCommandOnIp(ip, command); //todo fill me
return await ExecuteBufferedAsyncCommandOnIp(ip, command);
}
private static async Task<Int64> NumberOfBatteries(String? ip)
private static async Task<Int64> NumberOfBatteries(String? ip, String? online)
{
if (ip is null or "Unknown") return 0;
if (ip is null or "Unknown" || online == "❌") return 0;
var pathToBattery = await ExecuteBufferedAsyncCommandOnIp(ip, "dbus-send --system --dest=com.victronenergy.system --type=method_call --print-reply /ServiceMapping/com_victronenergy_battery_1 com.victronenergy.BusItem.GetText");
if (pathToBattery.StartsWith("Error")) return 0;
var cmd = await ExecuteBufferedAsyncCommandOnIp(ip,$"dbus-send --system --dest={pathToBattery} --type=method_call --print-reply /NbOfBatteries com.victronenergy.BusItem.GetText" );
return cmd == "Unknown" ? 0 : Int64.Parse(cmd); //No Batteries can be found
return cmd == "Failed" ? 0 : Int64.Parse(cmd); //No Batteries can be found
}
private static async Task<String> ExecuteBufferedAsyncCommandOnIp(String? ip, String command)
public static async Task<String> ExecuteBufferedAsyncCommandOnIp(String? ip, String command)
{
if (ip is null or "Unknown") return "Unknown";
if (ip is null or "Unknown") return "Failed";
var cmd = await Cli.Wrap("ssh")
.WithArguments($@"root@{ip}")
.AppendArgument("-o StrictHostKeyChecking=accept-new")
.AppendArgument(command)
.WithValidation(CommandResultValidation.None).ExecuteBufferedAsync();
return cmd.StandardOutput.Split('"')[1];
return cmd.ExitCode == 0 ? cmd.StandardOutput.Split('"')[1] : cmd.StandardError;
}
private static String?[] Ip(InstallationDetails details)