146 lines
4.4 KiB
C#
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();
|
|
} |