Innovenergy_trunk/csharp/app/API/VrmLink.cs

146 lines
4.4 KiB
C#

using System.Text.RegularExpressions;
using InnovEnergy.API.DataModel;
using InnovEnergy.Lib.Utils;
using InnovEnergy.Lib.Victron.VictronVRM;
namespace InnovEnergy.API;
public class VrmLink : IDisposable
{
private static readonly Regex RxSerial = new Regex(@"\s*\(\s*20\d\d-\d\d\d\d\d(\.\d)?\s*\)\s*", RegexOptions.Compiled | RegexOptions.Singleline);
private Vrm Vrm { get; }
private VrmLink(Vrm vrm)
{
Vrm = vrm;
}
public static async Task<VrmLink> Login()
{
const String vrmUser = "victron@innov.energy";
const String vrmPwd = "NnoVctr201002";
var vrm = await Vrm.Login(vrmUser, vrmPwd);
return new VrmLink(vrm);
}
public async Task SyncWithVrm(Data data)
{
var installationDetails = Vrm.GetInstallationDetailsAsync();
// var vpnIpLookup = Vpn.CreateVpnIpLookup();
// var vpnOnlineLookup = Vpn.CreateVpnOnlineLookup();
var vpnIpLookup = (String s) => "127.0.0.1";
var vpnOnlineLookup = (String s) => true;
var vrmInstallationsById = data
.Root
.DescendantInstallations()
.Where(d => (d.Element as VrmInstallation)?.UniqueId != null)
.ToDictionary(d => d.Element.CastTo<VrmInstallation>().UniqueId!);
List<User> DeleteExistingInstallation(InstallationDetails details)
{
vrmInstallationsById.TryGetValue(details.Identifier, out var existing);
if (existing is null)
return new List<User>();
// if it already exists, delete it, but keep its users
var installation = existing.Installation()!;
var users = installation.Users;
installation.Users = new List<User>();
existing.Delete();
return users;
}
// SYNC
await foreach (var i in installationDetails)
{
if (!i.IsActive) continue;
var (name, path, ieSerial) = ParseVrmName(i);
var users = DeleteExistingInstallation(i);
var installation = new VrmInstallation
{
Name = name,
Users = users,
IeSerial = ieSerial,
VrmId = i.IdSite,
UniqueId = i.Identifier,
FirmwareVersion = i.FirmwareVersion,
SystemType = i.SystemType,
MachineSerial = i.MachineSerial,
MachineName = i.MachineName, // type: VenusGx, CCGX, etc.
Tags = i.Tags,
VpnIp = vpnIpLookup(i.MachineSerial),
Online = vpnOnlineLookup(i.MachineSerial),
};
if (i.MachineName is not null)
await Vrm.AddTags(i.IdSite, i.MachineName);
var folder = data.GetOrCreateFolder(path);
folder.Add(installation);
}
// SORT
foreach (var folder in data.Root.DescendantFolders().Select(d => d.Element).OfType<Folder>())
{
folder.Folders.Sort();
folder.Installations.Sort();
folder.Users.Sort();
var grouped = folder.Installations.OfType<VrmInstallation>().GroupBy(i=>i.Name);
foreach (var g in grouped.Where(g => g.Count() > 1))
foreach (var (vrmInstallation, n) in g.OrderBy(i => i.UniqueId).Select((i, n) => (i, n)))
{
vrmInstallation.Name += $" ({n + 1})";
}
foreach (var installation in folder.Installations)
installation.Users.Sort();
}
}
private static (String name, IReadOnlyList<String> path, String? serial) ParseVrmName(InstallationDetails installationDetails)
{
var fullName = installationDetails.Name;
var match = RxSerial.Match(fullName); // extract IeSerial from _entire_ fullname
var serial = match.Success
? match.Value
: null;
fullName = RxSerial.Replace(fullName, "");
var split = fullName.Split('|', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
var path = split.Length > 1
? split.Skip(1).Reverse().ToArray(split.Length - 1)
: new[] { "ie" };
var name = split.Length >= 1
? split[0]
: installationDetails.Identifier;
return (name, path, serial);
}
public void Dispose() => Vrm.Dispose();
}