Checking for loops in foldertree, getting only unique children now.

Small Stability changes to VrmGrabber
This commit is contained in:
Kim 2023-09-18 13:21:39 +02:00
parent 731587ac77
commit b727ef765a
8 changed files with 162 additions and 10 deletions

View File

@ -31,13 +31,22 @@ public static class FolderMethods
.NotNull(); .NotNull();
} }
public static IEnumerable<Folder> ChildFolders(this Folder parent) private static IEnumerable<Folder> ChildFolders(this Folder parent)
{ {
// Unsafe can give back loops
return Db return Db
.Folders .Folders
.Where(f => f.ParentId == parent.Id); .Where(f => f.ParentId == parent.Id);
} }
public static IEnumerable<Folder> UniqueChildFolders(this Folder parent)
{
var set = new HashSet<Folder>(Db.Folders, EqualityComparer<Folder>.Default);
return ChildFolders(parent).Where(set.Add);
}
public static IEnumerable<Installation> ChildInstallations(this Folder parent) public static IEnumerable<Installation> ChildInstallations(this Folder parent)
{ {
return Db return Db
@ -48,14 +57,14 @@ public static class FolderMethods
public static IEnumerable<Folder> DescendantFolders(this Folder parent) public static IEnumerable<Folder> DescendantFolders(this Folder parent)
{ {
return parent return parent
.TraverseDepthFirstPreOrder(ChildFolders) .TraverseDepthFirstPreOrder(UniqueChildFolders)
.Skip(1); // skip self .Skip(1); // skip self
} }
public static IEnumerable<Folder> DescendantFoldersAndSelf(this Folder parent) public static IEnumerable<Folder> DescendantFoldersAndSelf(this Folder parent)
{ {
return parent return parent
.TraverseDepthFirstPreOrder(ChildFolders); .TraverseDepthFirstPreOrder(UniqueChildFolders);
} }
public static Boolean IsDescendantOf(this Folder folder, Folder ancestor) public static Boolean IsDescendantOf(this Folder folder, Folder ancestor)
{ {

View File

@ -138,7 +138,7 @@ public static class InstallationMethods
public static String GetOrderNumbers(this Installation installation) public static String GetOrderNumbers(this Installation installation)
{ {
return string.Join(", ", Db.OrderNumber2Installation return String.Join(", ", Db.OrderNumber2Installation
.Where(i => i.InstallationId == installation.Id) .Where(i => i.InstallationId == installation.Id)
.Select(i => i.OrderNumber) .Select(i => i.OrderNumber)
.ToReadOnlyList()); .ToReadOnlyList());

View File

@ -13,10 +13,10 @@ public static class UserMethods
{ {
public static IEnumerable<Installation> AccessibleInstallations(this User user) public static IEnumerable<Installation> AccessibleInstallations(this User user)
{ {
var direct = user.DirectlyAccessibleInstallations(); var direct = user.DirectlyAccessibleInstallations().ToList();
var fromFolders = user var fromFolders = user
.AccessibleFolders() .AccessibleFolders()
.SelectMany(u => u.ChildInstallations()); .SelectMany(u => u.ChildInstallations()).ToList();
return direct return direct
.Concat(fromFolders) .Concat(fromFolders)
@ -35,7 +35,7 @@ public static class UserMethods
{ {
var folders = user.AccessibleFolders() as IEnumerable<TreeNode>; var folders = user.AccessibleFolders() as IEnumerable<TreeNode>;
// user.AccessibleInstallations().ForEach(i => i.FillOrderNumbers()); user.AccessibleInstallations().ForEach(i => i.FillOrderNumbers());
var installations = user.AccessibleInstallations(); var installations = user.AccessibleInstallations();
return folders.Concat(installations); return folders.Concat(installations);

View File

@ -0,0 +1,25 @@
using System.Diagnostics.CodeAnalysis;
namespace InnovEnergy.App.Backend.DataTypes;
public abstract partial class TreeNode
{
private sealed class IdEqualityComparer : IEqualityComparer<TreeNode>
{
public Boolean Equals(TreeNode x, TreeNode y)
{
if (ReferenceEquals(x, y)) return true;
if (ReferenceEquals(x, null)) return false;
if (ReferenceEquals(y, null)) return false;
if (x.GetType() != y.GetType()) return false;
return x.Id == y.Id;
}
public Int32 GetHashCode(TreeNode obj)
{
return obj.Id.GetHashCode();
}
}
public static IEqualityComparer<TreeNode> IdComparer { get; } = new IdEqualityComparer();
}

View File

@ -195,7 +195,7 @@ th { /* header cell */
for (var batteryId = 3; batteryId < Int64.Parse(numberOfBatteries) + 2; batteryId++) for (var batteryId = 3; batteryId < Int64.Parse(numberOfBatteries) + 2; batteryId++)
{ {
localCommand = localCommand.Append( localCommand = localCommand.Append(
$" && /opt/innovenergy/scripts/upload-bms-firmware {batteryTtyName} {batteryId} /opt/innovenergy/{FirmwareVersion}.bin"); $" && sleep 3m && /opt/innovenergy/scripts/upload-bms-firmware {batteryTtyName} {batteryId} /opt/innovenergy/{FirmwareVersion}.bin");
} }
#pragma warning disable CS4014 #pragma warning disable CS4014
Db.ExecuteBufferedAsyncCommandOnIp(installationIp, localCommand) Db.ExecuteBufferedAsyncCommandOnIp(installationIp, localCommand)

View File

@ -153,7 +153,7 @@ public static partial class Db
var command = $"dbus-send --system --dest={pathToBattery.Split('"')[1]} --type=method_call --print-reply /FirmwareVersion com.victronenergy.BusItem.GetText"; var command = $"dbus-send --system --dest={pathToBattery.Split('"')[1]} --type=method_call --print-reply /FirmwareVersion com.victronenergy.BusItem.GetText";
var returnString = await ExecuteBufferedAsyncCommandOnIp(ip, command); var returnString = await ExecuteBufferedAsyncCommandOnIp(ip, command);
var returnStringShortened = returnString.Split('"')[1]; var returnStringShortened = returnString.Split('"')[1];
return returnStringShortened.Length > 5 ? "Unknown" : returnStringShortened; return returnStringShortened.Length > 10 ? "Unknown" : returnStringShortened;
} }
private static async Task<String> NumberOfBatteries(String? ip, String? online) private static async Task<String> NumberOfBatteries(String? ip, String? online)

View File

@ -0,0 +1,116 @@
using System.Diagnostics.CodeAnalysis;
namespace InnovEnergy.Lib.Utils;
public static class GraphTraversal
{
public static IEnumerable<T> TraverseDepthFirstPreOrder<T>(T root,
Func<T, IEnumerable<T>> getChildren,
IEqualityComparer<T>? comparer = null)
{
return Traverse(root, TreeTraversal.TraverseDepthFirstPreOrder, getChildren, comparer);
}
public static IEnumerable<T> TraverseDepthFirstPostOrder<T>(T root,
Func<T, IEnumerable<T>> getChildren,
IEqualityComparer<T>? comparer = null)
{
return Traverse(root, TreeTraversal.TraverseDepthFirstPostOrder, getChildren, comparer);
}
public static IEnumerable<T> TraverseBreadthFirst<T>(T root,
Func<T, IEnumerable<T>> getChildren,
IEqualityComparer<T>? comparer = null)
{
return Traverse(root, TreeTraversal.TraverseBreadthFirst, getChildren, comparer);
}
public static IEnumerable<T> TraverseDepthFirstPreOrder<T>(IEnumerable<T> sources,
Func<T, IEnumerable<T>> getChildren,
IEqualityComparer<T>? comparer = null)
{
return Traverse(sources, TreeTraversal.TraverseDepthFirstPreOrder, getChildren, comparer);
}
public static IEnumerable<T> TraverseDepthFirstPostOrder<T>(IEnumerable<T> sources,
Func<T, IEnumerable<T>> getChildren,
IEqualityComparer<T>? comparer = null)
{
return Traverse(sources, TreeTraversal.TraverseDepthFirstPostOrder, getChildren, comparer);
}
public static IEnumerable<T> TraverseBreadthFirst<T>(IEnumerable<T> sources,
Func<T, IEnumerable<T>> getChildren,
IEqualityComparer<T>? comparer = null)
{
return Traverse(sources, TreeTraversal.TraverseBreadthFirst, getChildren, comparer);
}
private static IEnumerable<T> Traverse<T>(T root,
Func<T , Func<T, IEnumerable<T>>,IEnumerable<T>> traversor,
Func<T, IEnumerable<T>> getChildren,
IEqualityComparer<T>? comparer = null)
{
var getUniqueChildren = GetUniqueChildren(getChildren, root, comparer);
return traversor(root, getUniqueChildren);
}
[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
private static IEnumerable<T> Traverse<T>(IEnumerable<T> sources,
Func<T , Func<T, IEnumerable<T>>,IEnumerable<T>> traversor,
Func<T, IEnumerable<T>> getChildren,
IEqualityComparer<T>? comparer = null)
{
var set = new HashSet<T>(sources, comparer ?? EqualityComparer<T>.Default);
IEnumerable<T> GetUniqueChildren(T n) => getChildren(n).Where(set.Add);
return from s in sources
from e in traversor(s, GetUniqueChildren)
select e;
}
// TODO: IEqualityComparer
public static IEnumerable<(T source, T target)> Edges<T>(T node, Func<T, IEnumerable<T>> getChildren)
{
return Edges(node.AsSingleEnumerable(), getChildren);
}
// TODO: IEqualityComparer
public static IEnumerable<(T source, T target)> Edges<T>(IEnumerable<T> sources,
Func<T, IEnumerable<T>> getChildren)
{
var hs = new HashSet<(T source, T target)>();
IEnumerable<(T source, T target)> GetChildEdges((T source, T target) edge)
{
return getChildren(edge.target)
.Select(c => (edge.target, c))
.Where(hs!.Add);
}
return from src in sources.Select(s => (s, s))
from e in TreeTraversal.TraverseDepthFirstPreOrder(src, GetChildEdges).Skip(1)
select e;
}
private static Func<T, IEnumerable<T>> GetUniqueChildren<T>(Func<T, IEnumerable<T>> getChildren,
T root,
IEqualityComparer<T>? comparer)
{
return GetUniqueChildren(getChildren, root.AsSingleEnumerable(), comparer);
}
private static Func<T, IEnumerable<T>> GetUniqueChildren<T>(Func<T, IEnumerable<T>> getChildren,
IEnumerable<T> sources,
IEqualityComparer<T>? comparer)
{
var set = new HashSet<T>(sources, comparer ?? EqualityComparer<T>.Default);
return n => getChildren(n).Where(set.Add);
}
}

View File

@ -1,3 +1,5 @@
using InnovEnergy.Lib.Utils.Reflection;
namespace InnovEnergy.Lib.Utils; namespace InnovEnergy.Lib.Utils;
public static class TreeTraversal public static class TreeTraversal
@ -77,7 +79,7 @@ public static class TreeTraversal
var stack = new Stack<IEnumerator<T>>(); var stack = new Stack<IEnumerator<T>>();
var it = root.AsSingleEnumerator(); var it = root.AsSingleEnumerator();
it.MoveNext(); it.MoveNext();
while (true) while (true)
{ {
//////// going down //////// //////// going down ////////