remove API
This commit is contained in:
parent
cec22d07d8
commit
384d7c9596
|
@ -1,32 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="../InnovEnergy.app.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<RootNamespace>InnovEnergy.API</RootNamespace>
|
||||
<StartupObject>InnovEnergy.API.Program</StartupObject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../lib/Utils/Utils.csproj" />
|
||||
<ProjectReference Include="../../lib/VictronVRM/VictronVRM.csproj" />
|
||||
<ProjectReference Include="../../lib/WebServer/WebServer.csproj" />
|
||||
<ProjectReference Include="../OpenVpnCertificatesServer/OpenVpnCertificatesServer.csproj" />
|
||||
<ProjectReference Include="../../lib/Victron/VictronVRM/VictronVRM.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="sqlite-net-pcl" Version="1.8.116" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<!-- <Target Name="sass" BeforeTargets="PreBuildEvent">-->
|
||||
<!-- <Exec Command="find $(MSBuildProjectDirectory) -name '*.scss' | sed 's//.scss$//' | xargs -I{} $(MSBuildProjectDirectory)/../../tools/sass --embed-source-map {}.scss {}.css" />-->
|
||||
<!-- </Target>-->
|
||||
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
using Flurl;
|
||||
using InnovEnergy.API.DataModel;
|
||||
|
||||
namespace InnovEnergy.API;
|
||||
|
||||
public static class Api
|
||||
{
|
||||
public static Result CreateUser(QueryParamCollection queryParams, LoginState loginState)
|
||||
{
|
||||
var parentPath = queryParams.FirstOrDefault("path") as String;
|
||||
var userName = queryParams.FirstOrDefault("userName") as String;
|
||||
var userType = queryParams.FirstOrDefault("userType") as String;
|
||||
|
||||
if (userName != null && Program.Data.Root.FindDescendantUser(userName) != null)
|
||||
return Result.Failure("there is already another user with that name");
|
||||
|
||||
return loginState.CreateUser(parentPath, userName, userType);
|
||||
}
|
||||
|
||||
public static Result EditUser(QueryParamCollection queryParams, LoginState loginState)
|
||||
{
|
||||
var userPath = queryParams.FirstOrDefault("path") as String;
|
||||
var userType = queryParams.FirstOrDefault("userType") as String;
|
||||
|
||||
return loginState.EditUser(userPath, userType);
|
||||
}
|
||||
|
||||
public static Result RenameInstallation(QueryParamCollection queryParams, LoginState loginState)
|
||||
{
|
||||
var userPath = queryParams.FirstOrDefault("path") as String;
|
||||
var userType = queryParams.FirstOrDefault("name") as String;
|
||||
|
||||
return loginState.RenameInstallation(userPath, userType);
|
||||
}
|
||||
|
||||
|
||||
public static Result DeleteFolder(QueryParamCollection queryParams, LoginState loginState)
|
||||
{
|
||||
var path = queryParams.FirstOrDefault("path") as String;
|
||||
|
||||
return loginState.DeleteFolder(path);
|
||||
}
|
||||
|
||||
public static Result DeleteInstallation(QueryParamCollection queryParams, LoginState loginState)
|
||||
{
|
||||
var path = queryParams.FirstOrDefault("path") as String;
|
||||
|
||||
return loginState.DeleteInstallation(path);
|
||||
}
|
||||
|
||||
|
||||
public static Result DeleteUser(QueryParamCollection queryParams, LoginState loginState)
|
||||
{
|
||||
var path = queryParams.FirstOrDefault("path") as String;
|
||||
|
||||
return loginState.DeleteUser(path);
|
||||
}
|
||||
|
||||
// public static Result Rename(QueryParamCollection queryParams, LoginState loginState)
|
||||
// {
|
||||
// var path = queryParams.FirstOrDefault("path") as String;
|
||||
// var name = queryParams.FirstOrDefault("name") as String;
|
||||
//
|
||||
// return loginState.Delete(path);
|
||||
// }
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public static class DataExtensions
|
||||
{
|
||||
public static Folder GetOrCreateFolder(this Data data, IEnumerable<String> path)
|
||||
{
|
||||
var parent = data.Root;
|
||||
var stack = new Stack<String>(path.Reverse());
|
||||
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var childFolderName = stack.Pop();
|
||||
|
||||
var childFolder = parent.Folders.FirstOrDefault(f => f.Name == childFolderName);
|
||||
|
||||
if (childFolder is null)
|
||||
{
|
||||
childFolder = new Folder { Name = childFolderName };
|
||||
parent.Add(childFolder);
|
||||
}
|
||||
|
||||
parent = childFolder;
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
using InnovEnergy.Lib.Utils;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public partial record Data
|
||||
{
|
||||
private static readonly JsonSerializerSettings PersistenceJsonSettings = new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
NullValueHandling = NullValueHandling.Include,
|
||||
ContractResolver = new CamelCasePropertyNamesContractResolver(),
|
||||
TypeNameHandling = TypeNameHandling.Auto
|
||||
};
|
||||
|
||||
public static readonly JsonSerializerSettings WireFormatJsonSettings = new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
ContractResolver = new CamelCasePropertyNamesContractResolver(),
|
||||
TypeNameHandling = TypeNameHandling.None
|
||||
};
|
||||
|
||||
public static Data Load() => GetLastVersion().Apply(Load);
|
||||
public static String LoadJson() => GetLastVersion().Apply(LoadJson);
|
||||
|
||||
public static Data Load(Int32 sequenceNb)
|
||||
{
|
||||
var json = LoadJson(sequenceNb);
|
||||
return JsonConvert.DeserializeObject<Data>(json, PersistenceJsonSettings)!;
|
||||
}
|
||||
|
||||
public static String LoadJson(Int32 sequenceNb)
|
||||
{
|
||||
var jsonFile = System.IO.Path.Combine(Program.RootDir, sequenceNb + ".json");
|
||||
|
||||
Console.WriteLine($"loaded {jsonFile}");
|
||||
|
||||
return jsonFile.Apply(File.ReadAllText);
|
||||
}
|
||||
|
||||
public void Save(String editAction, String user)
|
||||
{
|
||||
var version = Edit.Version + 1;
|
||||
|
||||
Edit = new Edit(editAction, user, version);
|
||||
|
||||
var path = System.IO.Path.Combine(Program.RootDir, version + ".json");
|
||||
var json = SerializeJson();
|
||||
|
||||
File.WriteAllText(path, json);
|
||||
}
|
||||
|
||||
public String SerializeJson()
|
||||
{
|
||||
return JsonConvert.SerializeObject(this, PersistenceJsonSettings);
|
||||
}
|
||||
|
||||
private static String Base64Hash(DataElement element)
|
||||
{
|
||||
return element
|
||||
.GetHashCode()
|
||||
.Apply(BitConverter.GetBytes)
|
||||
.Apply(Convert.ToBase64String)
|
||||
.Apply(TrimEq);
|
||||
}
|
||||
|
||||
private static String TrimEq(String h) => h.TrimEnd('=');
|
||||
|
||||
private static Int32 GetLastVersion()
|
||||
{
|
||||
return Directory
|
||||
.EnumerateFiles(Program.RootDir, "*.json")
|
||||
.Select(System.IO.Path.GetFileNameWithoutExtension)
|
||||
.Where(f => f!.All(Char.IsDigit))
|
||||
.OrderBy(f => f)
|
||||
.Last()
|
||||
.Apply(Int32.Parse!);
|
||||
}
|
||||
|
||||
//public override String ToString() => JsonConvert.SerializeObject(this, WireFormatJsonSettings);
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public partial record Data
|
||||
{
|
||||
public Edit Edit { get; set; }
|
||||
public Folder Root { get; set; } = null!;
|
||||
|
||||
public Data(Folder root, Edit edit)
|
||||
{
|
||||
Root = root;
|
||||
Edit = edit;
|
||||
}
|
||||
|
||||
public static Data Origin
|
||||
{
|
||||
get
|
||||
{
|
||||
var root = new Folder { Name = "All Installations" };
|
||||
var admin = new User { Name = "admin", UserType = UserType.Admin };
|
||||
root.Add(admin);
|
||||
|
||||
return new Data(root, new Edit("ORIGIN", admin.Name, 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// https://vrmapi.victronenergy.com/v2/users/55450/addsite
|
||||
// {"installation_identifier":"ertertertertertert","description":"___TEST"}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public static class DataElementExtensions
|
||||
{
|
||||
public static IEnumerable<DataElement> GetChildren(this DataElement de)
|
||||
{
|
||||
return de switch
|
||||
{
|
||||
Folder f => f.Folders.Concat<DataElement>(f.Installations).Concat(f.Users),
|
||||
Installation i => i.Users,
|
||||
_ => Enumerable.Empty<DataElement>()
|
||||
};
|
||||
}
|
||||
|
||||
public static Path RelativePath(this DataElement root) => new Path(null, root);
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public abstract record DataElement : IComparable<DataElement>
|
||||
{
|
||||
[JsonProperty(Order = Int32.MinValue + 0)] public String Name { get; set; } = "<no name>";
|
||||
[JsonProperty(Order = Int32.MinValue + 1)] public String Type { get; set; }
|
||||
|
||||
protected DataElement()
|
||||
{
|
||||
Type = GetType().Name;
|
||||
}
|
||||
|
||||
public override String ToString() => $"{Type.ToLower()} '{Name}'";
|
||||
|
||||
public Int32 CompareTo(DataElement? other)
|
||||
{
|
||||
if (ReferenceEquals(this, other)) return 0;
|
||||
if (ReferenceEquals(null, other)) return 1;
|
||||
|
||||
return String.Compare(Name, other.Name, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
using System.Globalization;
|
||||
|
||||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public record Edit
|
||||
{
|
||||
private static readonly String DateTimePattern = CultureInfo.CurrentCulture.DateTimeFormat.UniversalSortableDateTimePattern;
|
||||
|
||||
public String Action { get; set; } = "";
|
||||
public String User { get; set; } = "";
|
||||
public String TimeStamp { get; set; } = "";
|
||||
public Int32 Version { get; set; }
|
||||
|
||||
public Edit(String action, String user, Int32 version)
|
||||
{
|
||||
Action = action;
|
||||
User = user;
|
||||
Version = version;
|
||||
TimeStamp = DateTime.Now.ToString(DateTimePattern);
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using InnovEnergy.Lib.Utils;
|
||||
|
||||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public partial record Folder
|
||||
{
|
||||
public virtual Boolean Equals(Folder? other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
|
||||
return base.Equals(other) &&
|
||||
Folders.SequenceEqual(other.Folders) &&
|
||||
Installations.SequenceEqual(other.Installations);
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")]
|
||||
public override Int32 GetHashCode() => HashCode.Combine(base.GetHashCode(),
|
||||
Folders.SequenceHash(),
|
||||
Installations.SequenceHash());
|
||||
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public static class FolderExtensions
|
||||
{
|
||||
public static IEnumerable<Path> DescendantUserParents(this Folder folder)
|
||||
{
|
||||
foreach (var path in folder.GetDescendantFolders())
|
||||
{
|
||||
yield return path;
|
||||
|
||||
var f = path.Folder()!;
|
||||
|
||||
foreach (var installation in f.Installations)
|
||||
yield return new Path(path, installation);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<Path> DescendantFolders(this Folder folder) => folder.GetDescendantFolders();
|
||||
|
||||
public static IEnumerable<Path> DescendantInstallations(this Folder folder)
|
||||
{
|
||||
return from path in folder.DescendantFolders()
|
||||
let f = path.Element as Folder
|
||||
from installation in f.Installations
|
||||
select new Path(path, installation);
|
||||
}
|
||||
|
||||
|
||||
public static IEnumerable<Path> DescendantUsers(this Folder folder)
|
||||
{
|
||||
IEnumerable<User> GetUsers(Folder f) => f
|
||||
.Installations
|
||||
.SelectMany(i => i.Users)
|
||||
.Concat(f.Users);
|
||||
|
||||
return from path in folder.DescendantFolders()
|
||||
from user in GetUsers(path.Folder())
|
||||
select new Path(path, user);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static Path? FindDescendantUser(this Folder folder, String userName)
|
||||
{
|
||||
return folder
|
||||
.DescendantUsers()
|
||||
.FirstOrDefault(f => f.Element.Name == userName);
|
||||
}
|
||||
|
||||
|
||||
private static IEnumerable<Path> GetDescendantFolders(this Folder folder, Path? parent = null)
|
||||
{
|
||||
var path = new Path(parent, folder);
|
||||
|
||||
yield return path;
|
||||
|
||||
var descendantFolders = from f in folder.Folders
|
||||
from descendant in f.GetDescendantFolders(path)
|
||||
select descendant;
|
||||
|
||||
foreach (var descendant in descendantFolders)
|
||||
yield return descendant;
|
||||
}
|
||||
|
||||
public static Boolean Remove(this Folder folder, Installation installation)
|
||||
{
|
||||
return folder.Installations.Remove(installation);
|
||||
}
|
||||
|
||||
public static void Add(this Folder folder, Installation installation)
|
||||
{
|
||||
folder.Installations.Add(installation);
|
||||
}
|
||||
|
||||
public static Boolean Remove(this Folder folder, Folder child)
|
||||
{
|
||||
return folder.Folders.Remove(child);
|
||||
}
|
||||
|
||||
public static void Add(this Folder folder, Folder child)
|
||||
{
|
||||
folder.Folders.Add(child);
|
||||
}
|
||||
|
||||
|
||||
public static VrmInstallation GetOrCreateVrmInstallation(this Folder folder, String uniqueId)
|
||||
{
|
||||
var vrmInstallation = folder
|
||||
.Installations
|
||||
.OfType<VrmInstallation>()
|
||||
.FirstOrDefault(i => i.UniqueId == uniqueId);
|
||||
|
||||
if (vrmInstallation is not null)
|
||||
return vrmInstallation; // installation exist, return it
|
||||
|
||||
vrmInstallation = new VrmInstallation();
|
||||
folder.Installations.Add(vrmInstallation);
|
||||
|
||||
return vrmInstallation;
|
||||
}
|
||||
|
||||
public static Boolean IsEmpty(this Folder folder) => !folder.Folders.Any() && !folder.Installations.Any();
|
||||
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public partial record Folder : UserParent
|
||||
{
|
||||
public List<Folder> Folders { get; set; } = new List<Folder>();
|
||||
public List<Installation> Installations { get; set; } = new List<Installation>();
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using InnovEnergy.Lib.Utils;
|
||||
|
||||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public abstract partial record Installation
|
||||
{
|
||||
public virtual Boolean Equals(Installation? other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
|
||||
return base.Equals(other) &&
|
||||
VpnIp == other.VpnIp &&
|
||||
IeSerial == other.IeSerial &&
|
||||
Tags.SequenceEqual(other.Tags);
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")]
|
||||
public override Int32 GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(base.GetHashCode(), VpnIp, IeSerial, Tags.SequenceHash());
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public abstract partial record Installation : UserParent
|
||||
{
|
||||
public String? VpnIp { get; set; }
|
||||
public String? IeSerial { get; set; }
|
||||
public IReadOnlyList<String> Tags { get; set; } = Array.Empty<String>();
|
||||
}
|
|
@ -1,159 +0,0 @@
|
|||
using static InnovEnergy.API.Result;
|
||||
|
||||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public static class PathExtensions
|
||||
{
|
||||
public static Boolean IsRoot(this Path path) => path.Parent is null;
|
||||
|
||||
public static Installation? Installation(this Path? path) => path?.Element as Installation;
|
||||
public static Folder? Folder (this Path? path) => path?.Element as Folder;
|
||||
public static User? User (this Path? path) => path?.Element as User;
|
||||
public static UserParent? UserParent (this Path? path) => path?.Element as UserParent;
|
||||
|
||||
public static Boolean IsInstallation(this Path? path) => path?.Element is Installation;
|
||||
public static Boolean IsFolder (this Path? path) => path?.Element is Folder;
|
||||
public static Boolean IsUser (this Path? path) => path?.Element is User;
|
||||
|
||||
public static Boolean Exists(this Path? path) => path?.Element is not null;
|
||||
|
||||
public static IEnumerable<Path> Children(this Path? path) => from child in path?.Element.GetChildren()
|
||||
select new Path(path, child);
|
||||
|
||||
|
||||
public static Result MoveTo(this Path sourcePath, Path targetPath)
|
||||
{
|
||||
var add = targetPath.AddChild(sourcePath.Element);
|
||||
|
||||
if (add.Succeeded)
|
||||
{
|
||||
var delete = sourcePath.Delete();
|
||||
|
||||
if (delete.Succeeded)
|
||||
return Success($"moved {sourcePath} to {targetPath}");
|
||||
|
||||
var revert = targetPath.Delete();
|
||||
if (revert.Failed)
|
||||
throw new Exception($"failed to move {sourcePath} to {targetPath}");
|
||||
}
|
||||
|
||||
return Failure($"failed to move {sourcePath} to {targetPath}");
|
||||
}
|
||||
|
||||
public static Result Delete(this Path path)
|
||||
{
|
||||
var child = path.Element;
|
||||
var parent = path.Parent?.Element;
|
||||
|
||||
if (parent is Folder folder)
|
||||
{
|
||||
if (child is Folder f)
|
||||
{
|
||||
if (!f.IsEmpty())
|
||||
return Failure($"Cannot delete folder '{f.Name}'.\nFolder is not empty.");
|
||||
|
||||
if (folder.Remove(f))
|
||||
return Success($"Deleted folder {path}");
|
||||
}
|
||||
if (child is User u)
|
||||
{
|
||||
if (folder.Remove(u))
|
||||
return Success($"Deleted user {path}");
|
||||
}
|
||||
if (child is Installation i)
|
||||
{
|
||||
if (!i.IsEmpty())
|
||||
return Failure($"Cannot delete installation '{i.Name}'.\nInstallation has active users.");
|
||||
|
||||
if (folder.Remove(i))
|
||||
return Success($"deleted installation {path}");
|
||||
}
|
||||
}
|
||||
else if (parent is Installation installation && child is User user)
|
||||
{
|
||||
installation.Remove(user);
|
||||
return Success($"deleted user {path}");
|
||||
}
|
||||
|
||||
return Failure($"cannot delete {path}");
|
||||
}
|
||||
|
||||
public static Result AddChild(this Path path, DataElement child)
|
||||
{
|
||||
var parent = path.Element;
|
||||
|
||||
if (parent.GetChildren().Any(c => c.Name == child.Name))
|
||||
return Failure($"{path} already has an element with name {child.Name}");
|
||||
|
||||
if (parent is Folder folder)
|
||||
{
|
||||
if (child is Folder f)
|
||||
{
|
||||
folder.Add(f);
|
||||
return Success($"added folder {child.Name} to folder {path}");
|
||||
}
|
||||
if (child is User u)
|
||||
{
|
||||
folder.Add(u);
|
||||
return Success($"added user {child.Name} to folder {path}");
|
||||
}
|
||||
if (child is Installation i)
|
||||
{
|
||||
folder.Add(i);
|
||||
return Success($"added installation {child.Name} to folder {path}");
|
||||
}
|
||||
}
|
||||
else if (parent is Installation installation && child is User user)
|
||||
{
|
||||
installation.Add(user);
|
||||
return Success($"added user {child.Name} to installation {path}");
|
||||
}
|
||||
|
||||
return Failure($"cannot add {child} to {path}");
|
||||
}
|
||||
|
||||
|
||||
public static Path? GetDescendant(this Path path, params String[] stringPath)
|
||||
{
|
||||
return path.GetDescendant((IEnumerable<String>)stringPath);
|
||||
}
|
||||
|
||||
public static Path? GetDescendant(this Path path, IEnumerable<String> stringPath)
|
||||
{
|
||||
foreach (var childName in stringPath)
|
||||
{
|
||||
var child = path
|
||||
.Element
|
||||
.GetChildren()
|
||||
.SingleOrDefault(c => c.Name == childName);
|
||||
|
||||
if (child is null) return null;
|
||||
|
||||
path = new Path(path, child);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
// public static Path? GetDescendant(this Path path, String stringPath)
|
||||
// {
|
||||
// while (!stringPath.IsNullOrWhiteSpace())
|
||||
// {
|
||||
// var childName = stringPath.UntilFirst('|');
|
||||
//
|
||||
// var child = path
|
||||
// .Head
|
||||
// .GetChildren()
|
||||
// .SingleOrDefault(c => c.Name == childName);
|
||||
//
|
||||
// if (child is null) return null;
|
||||
//
|
||||
// stringPath = stringPath.AfterFirst('|');
|
||||
// path = new Path(path, child);
|
||||
// }
|
||||
//
|
||||
// return path;
|
||||
// }
|
||||
|
||||
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public record Path(Path? Parent, DataElement Element)
|
||||
{
|
||||
public override String ToString()
|
||||
{
|
||||
var path = Element.Name;
|
||||
var parent = Parent;
|
||||
|
||||
while (parent is not null)
|
||||
{
|
||||
path = parent.Element.Name + "|" + path;
|
||||
parent = parent.Parent;
|
||||
}
|
||||
|
||||
return $"|{path}";
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public static class UserExtensions
|
||||
{
|
||||
public static Boolean CanEditUsers(this User user) => user.UserType == UserType.Admin;
|
||||
public static Boolean CanEditFolders(this User user) => user.UserType != UserType.Viewer;
|
||||
public static Boolean CanEditInstallations(this User user) => user.UserType != UserType.Viewer;
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public record User : DataElement
|
||||
{
|
||||
public UserType UserType { get;set; }
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
using InnovEnergy.Lib.Utils;
|
||||
|
||||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public abstract partial record UserParent
|
||||
{
|
||||
public virtual Boolean Equals(UserParent? other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
|
||||
return base.Equals(other) && Users.SequenceEqual(other.Users);
|
||||
}
|
||||
|
||||
public override Int32 GetHashCode()
|
||||
{
|
||||
// ReSharper disable once NonReadonlyMemberInGetHashCode
|
||||
return HashCode.Combine(base.GetHashCode(), Users.SequenceHash());
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public static class UserParentExtensions
|
||||
{
|
||||
public static Boolean Remove(this UserParent parent, User user)
|
||||
{
|
||||
return parent.Users.Remove(user);
|
||||
}
|
||||
|
||||
public static void Add(this UserParent parent, User user)
|
||||
{
|
||||
parent.Users.Add(user);
|
||||
}
|
||||
|
||||
public static Boolean IsEmpty(this UserParent parent)
|
||||
{
|
||||
return !parent.Users.Any();
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public abstract partial record UserParent : DataElement
|
||||
{
|
||||
public List<User> Users { get; set; } = new List<User>();
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum UserType
|
||||
{
|
||||
Unknown ,
|
||||
Viewer ,
|
||||
Editor ,
|
||||
Admin
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
namespace InnovEnergy.API.DataModel;
|
||||
|
||||
public record VrmInstallation : Installation
|
||||
{
|
||||
public String? UniqueId { get; set; }
|
||||
public UInt64 VrmId { get; set; }
|
||||
public String? MachineSerial { get; set; }
|
||||
public String? SystemType { get; set; }
|
||||
public String? FirmwareVersion { get; set; }
|
||||
public Boolean? Online { get; set; }
|
||||
public String? MachineName { get; set; }
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
namespace InnovEnergy.API;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public const String Installation = ".inst";
|
||||
public const String Folder = ".folder";
|
||||
public const String Viewer = ".viewer";
|
||||
public const String Admin = ".admin";
|
||||
public const String Editor = ".editor";
|
||||
|
||||
|
||||
public static Boolean IsInstallation(this String path) => path.EndsWith(Installation);
|
||||
public static Boolean IsFolder (this String path) => path.EndsWith(Folder);
|
||||
public static Boolean IsViewer (this String path) => path.EndsWith(Viewer);
|
||||
public static Boolean IsEditor (this String path) => path.EndsWith(Editor);
|
||||
public static Boolean IsAdmin (this String path) => path.EndsWith(Admin);
|
||||
public static Boolean IsUser (this String path) => path.IsViewer() || path.IsEditor() || path.IsAdmin();
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
namespace InnovEnergy.API;
|
||||
|
||||
public enum InstallationType
|
||||
{
|
||||
InnovEnergy,
|
||||
Victron,
|
||||
}
|
|
@ -1,259 +0,0 @@
|
|||
using InnovEnergy.API.DataModel;
|
||||
using static InnovEnergy.API.Result;
|
||||
using Path = InnovEnergy.API.DataModel.Path;
|
||||
|
||||
namespace InnovEnergy.API;
|
||||
|
||||
public static class LoginStateExtensions
|
||||
{
|
||||
// TODO: sync VRM
|
||||
|
||||
public static Boolean CanEdit(this LoginState uc, Path path) => uc.CanEdit(path.Element);
|
||||
|
||||
public static Boolean CanEdit(this LoginState uc, DataElement de)
|
||||
{
|
||||
var user = uc.LoginUser;
|
||||
|
||||
return de is Folder && user.CanEditFolders() ||
|
||||
de is User && user.CanEditUsers() ||
|
||||
de is Installation && user.CanEditInstallations();
|
||||
}
|
||||
|
||||
public static Result Move(this LoginState ctx, String sourcePath, String targetPath)
|
||||
{
|
||||
var source = ctx.ParsePath(sourcePath);
|
||||
|
||||
if (source is null)
|
||||
return Failure($"cannot find {sourcePath}");
|
||||
|
||||
if (!ctx.CanEdit(source))
|
||||
return Failure($"operation not allowed for {ctx.LoginUser}");
|
||||
|
||||
var target = ctx.ParsePath(targetPath);
|
||||
|
||||
if (target is null)
|
||||
return Failure($"cannot find folder {targetPath}");
|
||||
|
||||
return source.MoveTo(target);
|
||||
}
|
||||
|
||||
|
||||
public static Result DeleteInstallation(this LoginState ctx, String? pathToDelete)
|
||||
{
|
||||
var path = ctx.ParsePath(pathToDelete);
|
||||
|
||||
if (path?.Installation() is null)
|
||||
return Failure($"cannot find {pathToDelete}");
|
||||
|
||||
if (!ctx.CanEdit(path))
|
||||
return Failure($"operation not allowed for {ctx.LoginUser}");
|
||||
|
||||
return path.Delete();
|
||||
}
|
||||
|
||||
public static Result RenameInstallation(this LoginState ctx, String? installationPath, String? newName)
|
||||
{
|
||||
var path = ctx.ParsePath(installationPath);
|
||||
|
||||
var installation = path?.Installation();
|
||||
|
||||
if (path is null || installation is null)
|
||||
return Failure($"cannot find {installationPath}");
|
||||
|
||||
if (newName is null)
|
||||
return Failure("no name supplied");
|
||||
|
||||
if (!ctx.CanEdit(path))
|
||||
return Failure($"operation not allowed for {ctx.LoginUser}");
|
||||
|
||||
|
||||
installation.Name = newName;
|
||||
|
||||
return path.Delete();
|
||||
}
|
||||
|
||||
|
||||
public static Result DeleteFolder(this LoginState ctx, String? pathToDelete)
|
||||
{
|
||||
var path = ctx.ParsePath(pathToDelete);
|
||||
|
||||
if (path?.Folder() is null)
|
||||
return Failure($"cannot find {pathToDelete}");
|
||||
|
||||
if (!ctx.CanEdit(path))
|
||||
return Failure($"operation not allowed for {ctx.LoginUser}");
|
||||
|
||||
return path.Delete();
|
||||
}
|
||||
|
||||
public static Result DeleteUser(this LoginState ctx, String? pathToDelete)
|
||||
{
|
||||
var path = ctx.ParsePath(pathToDelete);
|
||||
|
||||
if (path?.User() is null)
|
||||
return Failure($"cannot find {pathToDelete}");
|
||||
|
||||
if (!ctx.CanEdit(path))
|
||||
return Failure($"operation not allowed for {ctx.LoginUser}");
|
||||
|
||||
return path.Delete();
|
||||
}
|
||||
|
||||
public static Result Rename(this LoginState ctx, String pathToRename, String newName)
|
||||
{
|
||||
var path = ctx.ParsePath(pathToRename);
|
||||
|
||||
if (path is null)
|
||||
return Failure($"cannot find {pathToRename}");
|
||||
|
||||
if (!ctx.CanEdit(path) || path.IsUser())
|
||||
return Failure("operation not permitted");
|
||||
|
||||
if (String.IsNullOrWhiteSpace(newName))
|
||||
return Failure($"{newName} is not a valid name");
|
||||
|
||||
path.Element.Name = newName;
|
||||
return Success($"renamed {pathToRename} to {newName}");
|
||||
}
|
||||
|
||||
// TODO: prevent folder cycles!
|
||||
|
||||
// public Result AddNewFolder(String parentFolderPath, String folderName)
|
||||
// {
|
||||
// if (!User.CanEditFolders())
|
||||
// return Failure($"operation not allowed for {User}");
|
||||
//
|
||||
// var parent = ParsePath(parentFolderPath);
|
||||
//
|
||||
// if (parent is null)
|
||||
// return Failure($"cannot find folder {parentFolderPath}");
|
||||
//
|
||||
// return parent.AddChild(new Folder { Name = folderName });
|
||||
// }
|
||||
|
||||
// TODO: VRM
|
||||
// public Result AddNewInstallation(Int32 parentFolderId, String installationName)
|
||||
// {
|
||||
// if (!User.CanEditInstallations())
|
||||
// throw new ApiException($"operation not allowed for {User}");
|
||||
//
|
||||
// var parentPath = HomeFolder.FindDescendantFolder(parentFolderId);
|
||||
// var parentFolder = parentPath?.Folder();
|
||||
//
|
||||
// if (parentFolder is null)
|
||||
// return new Failure($"cannot find folder {parentFolderId}");
|
||||
//
|
||||
// var newInstallation = new Installation { Name = installationName };
|
||||
// parentFolder.Add(newInstallation);
|
||||
//
|
||||
// return new Success($"added new {newInstallation} to {parentPath}");
|
||||
// }
|
||||
|
||||
|
||||
public static Result CreateUser(this LoginState loginState, String? parentPath, String? userName, String? userType)
|
||||
{
|
||||
const String allowedSpecialChars = "_-.@";
|
||||
|
||||
if (!loginState.LoginUser.CanEditUsers())
|
||||
return Failure($"operation not allowed for {loginState.LoginUser}");
|
||||
|
||||
if (userName is null || userName.Length < 3)
|
||||
return Failure("username must consist of at least 3 characters");
|
||||
|
||||
if (!userName.All(c => Char.IsLetter(c) || Char.IsDigit(c) || allowedSpecialChars.Contains(c)))
|
||||
{
|
||||
return Failure("Illegal character in username.\n" +
|
||||
"The username can contain letters, digits and the following the following characters:\n" +
|
||||
allowedSpecialChars);
|
||||
}
|
||||
|
||||
var path = loginState.ParsePath(parentPath);
|
||||
|
||||
if (path is null)
|
||||
return Failure($"cannot find parent {parentPath}");
|
||||
|
||||
var type = ParseUserType(userType);
|
||||
|
||||
if (type == UserType.Unknown)
|
||||
return Failure($"unknown user type {type}");
|
||||
|
||||
var newUser = new User
|
||||
{
|
||||
Name = userName,
|
||||
UserType = type
|
||||
};
|
||||
|
||||
return path.AddChild(newUser);
|
||||
}
|
||||
|
||||
public static Result EditUser(this LoginState loginState, String? userPath, String? userType)
|
||||
{
|
||||
if (!loginState.LoginUser.CanEditUsers())
|
||||
return Failure($"operation not permitted for {loginState.LoginUser}");
|
||||
|
||||
var user = loginState.ParsePath(userPath).User();
|
||||
|
||||
if (user == loginState.LoginUser)
|
||||
return Failure($"operation not permitted for {loginState.LoginUser}");
|
||||
|
||||
if (user is null)
|
||||
return Failure($"cannot find user {userPath}");
|
||||
|
||||
var oldType = user.UserType;
|
||||
|
||||
var newType = ParseUserType(userType);
|
||||
|
||||
if (newType == UserType.Unknown)
|
||||
return Failure($"unknown user type {newType}");
|
||||
|
||||
user.UserType = newType;
|
||||
|
||||
return Success($"Changed user type of user {userPath} from {oldType} to {newType}");
|
||||
}
|
||||
|
||||
private static UserType ParseUserType(String? userType)
|
||||
{
|
||||
return userType switch
|
||||
{
|
||||
"Viewer" => UserType.Viewer,
|
||||
"Editor" => UserType.Editor,
|
||||
"Admin" => UserType.Admin,
|
||||
_ => UserType.Unknown
|
||||
};
|
||||
}
|
||||
|
||||
// public Result ChangeUserType(Int32 userId, UserType userType)
|
||||
// {
|
||||
// if (!User.CanEditUsers() || userId == User.Id)
|
||||
// return Failure($"operation not allowed for {User}");
|
||||
//
|
||||
// var userToEdit = HomeFolder.FindDescendantUser(userId)?.User();
|
||||
//
|
||||
// if (userToEdit is null)
|
||||
// return Failure($"cannot find user {userId}");
|
||||
//
|
||||
// var oldUserType = userToEdit.UserType;
|
||||
// userToEdit.UserType = userType;
|
||||
//
|
||||
// return Success($"changed type of user {userToEdit} from {oldUserType} to {userType}");
|
||||
// }
|
||||
|
||||
|
||||
private static Path? ParsePath(this LoginState uc, String? path)
|
||||
{
|
||||
if (path == null)
|
||||
return null;
|
||||
|
||||
var splitPath = path
|
||||
.Split("|", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
||||
.Skip(1);
|
||||
|
||||
return uc
|
||||
.HomeFolder
|
||||
.RelativePath()
|
||||
.GetDescendant(splitPath);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
using InnovEnergy.API.DataModel;
|
||||
|
||||
namespace InnovEnergy.API;
|
||||
|
||||
public class LoginState
|
||||
{
|
||||
public static readonly Random Rng = new Random();
|
||||
|
||||
public User LoginUser { get; }
|
||||
public Folder HomeFolder { get; }
|
||||
public String Token { get; }
|
||||
|
||||
public String? Error { get; set; }
|
||||
public Int32 DataVersion { get; set; }
|
||||
|
||||
public LoginState(User loginUser, Folder homeFolder, Int32 dataVersion)
|
||||
{
|
||||
LoginUser = loginUser;
|
||||
HomeFolder = homeFolder;
|
||||
DataVersion = dataVersion;
|
||||
Token = GenerateToken();
|
||||
}
|
||||
|
||||
private static String GenerateToken()
|
||||
{
|
||||
var buffer = new Byte[16];
|
||||
Rng.NextBytes(buffer);
|
||||
return Convert.ToBase64String(buffer);
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using static System.Runtime.CompilerServices.MethodImplOptions;
|
||||
|
||||
namespace InnovEnergy.API;
|
||||
|
||||
public static class PathExtensions
|
||||
{
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static String GetFileNameWithoutExtension(this String path) => Path.GetFileNameWithoutExtension(path);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static String GetFileName(this String path) => Path.GetFileName(path);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static String GetExtension(this String path) => Path.GetExtension(path);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static IEnumerable<String> GetDirectories(this String path) => Directory.EnumerateDirectories(path);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static IEnumerable<String> GetFiles(this String path) => Directory.EnumerateFiles(path);
|
||||
|
||||
|
||||
}
|
|
@ -1,202 +0,0 @@
|
|||
using Flurl;
|
||||
using InnovEnergy.API.DataModel;
|
||||
using InnovEnergy.Lib.WebServer;
|
||||
using InnovEnergy.Lib.Utils;
|
||||
using Newtonsoft.Json;
|
||||
using static System.Text.Encoding;
|
||||
using static InnovEnergy.Lib.WebServer.Default;
|
||||
|
||||
namespace InnovEnergy.API;
|
||||
|
||||
public static class Program
|
||||
{
|
||||
public static String RootDir { get; private set; } = "/home/eef/sync/work/Code/innovenergy/server/WebMonitoring/src";
|
||||
|
||||
public static Data Data { get; set; }
|
||||
|
||||
public static Dictionary<String, LoginState> LoggedInUsers { get; } = new Dictionary<String, LoginState>();
|
||||
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
RootDir = args.FirstOrDefault() ?? RootDir;
|
||||
|
||||
Console.WriteLine("start");
|
||||
|
||||
#pragma warning disable 4014
|
||||
SyncWithVrm();
|
||||
#pragma warning restore 4014
|
||||
|
||||
Data = Data.Load();
|
||||
WebServer.ServeOnLocalHost(8080, Serve);
|
||||
|
||||
Console.WriteLine("stop");
|
||||
}
|
||||
|
||||
private static async Task SyncWithVrm()
|
||||
{
|
||||
Console.WriteLine("Starting VRM sync");
|
||||
|
||||
var vrmLink = await VrmLink.Login();
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = Data.Load();
|
||||
var json = data.SerializeJson();
|
||||
await vrmLink.SyncWithVrm(data);
|
||||
|
||||
var changed = json != data.SerializeJson();
|
||||
|
||||
if (changed)
|
||||
{
|
||||
data.Save("Synced from VRM", "system");
|
||||
var edit = data.Edit;
|
||||
Console.WriteLine($"{edit.TimeStamp} [{edit.Version}] {edit.Action}");
|
||||
Data = data;
|
||||
}
|
||||
|
||||
await Task.Delay(TimeSpan.FromMinutes(10));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Failed to sync with VRM:\n" + e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static HttpResponse Serve(HttpRequest request)
|
||||
{
|
||||
var pathSegments = request.Url.PathSegments;
|
||||
|
||||
var p0 = pathSegments.ElementAtOrDefault(0);
|
||||
|
||||
Console.WriteLine(p0);
|
||||
|
||||
return p0 switch
|
||||
{
|
||||
"api" => ServeApi(request),
|
||||
_ => ServeAssets(request)
|
||||
};
|
||||
}
|
||||
|
||||
private static HttpResponse Login(QueryParamCollection query)
|
||||
{
|
||||
var userName = query.FirstOrDefault("username") as String;
|
||||
var password = query.FirstOrDefault("password") as String;
|
||||
|
||||
// TODO: password check
|
||||
|
||||
if (String.IsNullOrEmpty(userName))
|
||||
return HttpForbidden;
|
||||
|
||||
var userPath = Data.Root.FindDescendantUser(userName);
|
||||
var user = userPath?.User();
|
||||
var homeFolder = userPath?.Parent.Folder();
|
||||
|
||||
if (user is null || homeFolder is null)
|
||||
return HttpForbidden;
|
||||
|
||||
var loginState = new LoginState(user, homeFolder, Data.Edit.Version);
|
||||
|
||||
LoggedInUsers[loginState.Token] = loginState; // TODO: remove stale tokens
|
||||
|
||||
return CreateJsonResponse(loginState);
|
||||
}
|
||||
|
||||
|
||||
private static HttpResponse ServeApi(HttpRequest request)
|
||||
{
|
||||
var url = request.Url;
|
||||
var query = url.QueryParams;
|
||||
var action = query.FirstOrDefault("action") as String;
|
||||
|
||||
Console.WriteLine(action);
|
||||
|
||||
if (action == "login")
|
||||
return Login(query);
|
||||
|
||||
if (query.FirstOrDefault("token") is not String token ||
|
||||
!LoggedInUsers.TryGetValue(token, out var loginState))
|
||||
return HttpForbidden;
|
||||
|
||||
var result = action switch
|
||||
{
|
||||
"createUser" => Api.CreateUser(query, loginState),
|
||||
"editUser" => Api.EditUser(query, loginState),
|
||||
"renameInstallation" => Api.RenameInstallation(query, loginState),
|
||||
|
||||
// "deleteUser" => Api.DeleteUser(query, loginState),
|
||||
// "deleteFolder" => Api.DeleteFolder(query, loginState),
|
||||
// "deleteInstallation" => Api.DeleteInstallation(query, loginState),
|
||||
//"rename" => Api.Delete(query, loginState),
|
||||
|
||||
_ => Result.Failure("unsupported api call")
|
||||
};
|
||||
|
||||
|
||||
|
||||
return result
|
||||
.WriteToDisk(loginState.LoginUser)
|
||||
.CreateResponse(loginState);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private static HttpResponse ServeAssets(HttpRequest request)
|
||||
{
|
||||
var localPath = RootDir + request.Url.Path;
|
||||
|
||||
if (request.Url.PathSegments.Count == 0)
|
||||
localPath = RootDir + "/index.html";
|
||||
|
||||
Console.WriteLine(request.Url + " => " + localPath + " | " + InferContentType.FromExtension(localPath));
|
||||
|
||||
if (!File.Exists(localPath))
|
||||
{
|
||||
Console.WriteLine("404");
|
||||
return HttpNotFound;
|
||||
}
|
||||
|
||||
return new HttpResponse
|
||||
{
|
||||
Content = File.ReadAllBytes(localPath), // TODO: cache?
|
||||
ContentType = InferContentType.FromExtension(localPath)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private static Result WriteToDisk(this Result result, User loggedInUser)
|
||||
{
|
||||
if (result.Succeeded)
|
||||
{
|
||||
Data.Save(result.Message, loggedInUser.Name);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static HttpResponse CreateResponse(this Result result, LoginState loginState)
|
||||
{
|
||||
loginState.DataVersion = Data.Edit.Version; // important!
|
||||
loginState.Error = result.Succeeded ? null : result.Message;
|
||||
|
||||
return CreateJsonResponse(loginState);
|
||||
}
|
||||
|
||||
private static HttpResponse CreateJsonResponse<T>(T payload)
|
||||
{
|
||||
var json = JsonConvert.SerializeObject(payload, Data.WireFormatJsonSettings);
|
||||
|
||||
return new HttpResponse
|
||||
{
|
||||
Content = json.Apply(UTF8.GetBytes),
|
||||
ContentType = ContentType.ApplicationJson,
|
||||
Headers = new[] { new HttpHeader("Access-Control-Allow-Origin", "*") }
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
namespace InnovEnergy.API;
|
||||
|
||||
public class Result
|
||||
{
|
||||
public String Message { get; }
|
||||
public Boolean Succeeded { get; }
|
||||
public Boolean Failed => !Succeeded;
|
||||
|
||||
public static Result Success(String message = "") => new Result(message, succeeded: true);
|
||||
public static Result Failure(String message = "") => new Result(message, succeeded: false);
|
||||
|
||||
private Result(String message, Boolean succeeded)
|
||||
{
|
||||
Message = message;
|
||||
Succeeded = succeeded;
|
||||
}
|
||||
}
|
|
@ -1,146 +0,0 @@
|
|||
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();
|
||||
}
|
Binary file not shown.
|
@ -1,468 +0,0 @@
|
|||
{
|
||||
"runtimeTarget": {
|
||||
"name": ".NETCoreApp,Version=v6.0",
|
||||
"signature": ""
|
||||
},
|
||||
"compilationOptions": {},
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v6.0": {
|
||||
"API/1.0.0": {
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "13.0.1",
|
||||
"OpenVpnCertificatesServer": "1.0.0",
|
||||
"Utils": "1.0.0",
|
||||
"VictronVRM": "1.0.0",
|
||||
"WebServer": "1.0.0",
|
||||
"sqlite-net-pcl": "1.8.116"
|
||||
},
|
||||
"runtime": {
|
||||
"API.dll": {}
|
||||
}
|
||||
},
|
||||
"BouncyCastle/1.8.9": {
|
||||
"runtime": {
|
||||
"lib/BouncyCastle.Crypto.dll": {
|
||||
"assemblyVersion": "1.8.9.0",
|
||||
"fileVersion": "1.8.20343.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CliWrap/3.3.1": {
|
||||
"runtime": {
|
||||
"lib/netcoreapp3.0/CliWrap.dll": {
|
||||
"assemblyVersion": "3.3.1.0",
|
||||
"fileVersion": "3.3.1.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Flurl/3.0.4": {
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/Flurl.dll": {
|
||||
"assemblyVersion": "3.0.4.0",
|
||||
"fileVersion": "3.0.4.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Flurl.Http/3.2.2": {
|
||||
"dependencies": {
|
||||
"Flurl": "3.0.4",
|
||||
"Newtonsoft.Json": "13.0.1",
|
||||
"System.Text.Encoding.CodePages": "4.5.1"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/Flurl.Http.dll": {
|
||||
"assemblyVersion": "3.2.2.0",
|
||||
"fileVersion": "3.2.2.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.NETCore.Platforms/2.1.2": {},
|
||||
"Newtonsoft.Json/13.0.1": {
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/Newtonsoft.Json.dll": {
|
||||
"assemblyVersion": "13.0.0.0",
|
||||
"fileVersion": "13.0.1.25517"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SharpZipLib/1.3.3": {
|
||||
"runtime": {
|
||||
"lib/netstandard2.1/ICSharpCode.SharpZipLib.dll": {
|
||||
"assemblyVersion": "1.3.3.11",
|
||||
"fileVersion": "1.3.3.11"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sqlite-net-pcl/1.8.116": {
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.bundle_green": "2.0.4"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/SQLite-net.dll": {
|
||||
"assemblyVersion": "1.8.116.0",
|
||||
"fileVersion": "1.8.116.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SQLitePCLRaw.bundle_green/2.0.4": {
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.0.4",
|
||||
"SQLitePCLRaw.lib.e_sqlite3": "2.0.4",
|
||||
"SQLitePCLRaw.provider.dynamic_cdecl": "2.0.4"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netcoreapp3.1/SQLitePCLRaw.batteries_v2.dll": {
|
||||
"assemblyVersion": "2.0.4.976",
|
||||
"fileVersion": "2.0.4.976"
|
||||
},
|
||||
"lib/netcoreapp3.1/SQLitePCLRaw.nativelibrary.dll": {
|
||||
"assemblyVersion": "2.0.4.976",
|
||||
"fileVersion": "2.0.4.976"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SQLitePCLRaw.core/2.0.4": {
|
||||
"dependencies": {
|
||||
"System.Memory": "4.5.3"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/SQLitePCLRaw.core.dll": {
|
||||
"assemblyVersion": "2.0.4.976",
|
||||
"fileVersion": "2.0.4.976"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SQLitePCLRaw.lib.e_sqlite3/2.0.4": {
|
||||
"runtimeTargets": {
|
||||
"runtimes/alpine-x64/native/libe_sqlite3.so": {
|
||||
"rid": "alpine-x64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-arm/native/libe_sqlite3.so": {
|
||||
"rid": "linux-arm",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-arm64/native/libe_sqlite3.so": {
|
||||
"rid": "linux-arm64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-armel/native/libe_sqlite3.so": {
|
||||
"rid": "linux-armel",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-mips64/native/libe_sqlite3.so": {
|
||||
"rid": "linux-mips64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-musl-x64/native/libe_sqlite3.so": {
|
||||
"rid": "linux-musl-x64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-x64/native/libe_sqlite3.so": {
|
||||
"rid": "linux-x64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/linux-x86/native/libe_sqlite3.so": {
|
||||
"rid": "linux-x86",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/osx-x64/native/libe_sqlite3.dylib": {
|
||||
"rid": "osx-x64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/win-arm/native/e_sqlite3.dll": {
|
||||
"rid": "win-arm",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/win-arm64/native/e_sqlite3.dll": {
|
||||
"rid": "win-arm64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/win-x64/native/e_sqlite3.dll": {
|
||||
"rid": "win-x64",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
},
|
||||
"runtimes/win-x86/native/e_sqlite3.dll": {
|
||||
"rid": "win-x86",
|
||||
"assetType": "native",
|
||||
"fileVersion": "0.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SQLitePCLRaw.provider.dynamic_cdecl/2.0.4": {
|
||||
"dependencies": {
|
||||
"SQLitePCLRaw.core": "2.0.4"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/SQLitePCLRaw.provider.dynamic_cdecl.dll": {
|
||||
"assemblyVersion": "2.0.4.976",
|
||||
"fileVersion": "2.0.4.976"
|
||||
}
|
||||
}
|
||||
},
|
||||
"System.Memory/4.5.3": {},
|
||||
"System.Reactive/5.0.0": {
|
||||
"runtime": {
|
||||
"lib/net5.0/System.Reactive.dll": {
|
||||
"assemblyVersion": "5.0.0.0",
|
||||
"fileVersion": "5.0.0.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"System.Reactive.Linq/5.0.0": {
|
||||
"dependencies": {
|
||||
"System.Reactive": "5.0.0",
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/System.Reactive.Linq.dll": {
|
||||
"assemblyVersion": "3.0.6000.0",
|
||||
"fileVersion": "0.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe/6.0.0": {},
|
||||
"System.Text.Encoding.CodePages/4.5.1": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "2.1.2",
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Text.Encodings.Web/6.0.0": {
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Text.Json/6.0.2": {
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0",
|
||||
"System.Text.Encodings.Web": "6.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net6.0/System.Text.Json.dll": {
|
||||
"assemblyVersion": "6.0.0.0",
|
||||
"fileVersion": "6.0.222.6406"
|
||||
}
|
||||
}
|
||||
},
|
||||
"System.Threading.Tasks.Extensions/4.5.4": {},
|
||||
"OpenVpnCertificatesServer/1.0.0": {
|
||||
"dependencies": {
|
||||
"BouncyCastle": "1.8.9",
|
||||
"Flurl.Http": "3.2.2",
|
||||
"SharpZipLib": "1.3.3",
|
||||
"Utils": "1.0.0",
|
||||
"VictronVRM": "1.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"OpenVpnCertificatesServer.dll": {}
|
||||
}
|
||||
},
|
||||
"SysTools/1.0.0": {
|
||||
"dependencies": {
|
||||
"System.Reactive.Linq": "5.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"SysTools.dll": {}
|
||||
}
|
||||
},
|
||||
"Utils/1.0.0": {
|
||||
"dependencies": {
|
||||
"CliWrap": "3.3.1",
|
||||
"System.Reactive.Linq": "5.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"Utils.dll": {}
|
||||
}
|
||||
},
|
||||
"VictronVRM/1.0.0": {
|
||||
"dependencies": {
|
||||
"Flurl.Http": "3.2.2",
|
||||
"Newtonsoft.Json": "13.0.1",
|
||||
"SysTools": "1.0.0",
|
||||
"System.Reactive.Linq": "5.0.0",
|
||||
"System.Text.Json": "6.0.2",
|
||||
"Utils": "1.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"VictronVRM.dll": {}
|
||||
}
|
||||
},
|
||||
"WebServer/1.0.0": {
|
||||
"dependencies": {
|
||||
"Flurl": "3.0.4",
|
||||
"Flurl.Http": "3.2.2",
|
||||
"System.Reactive.Linq": "5.0.0",
|
||||
"Utils": "1.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"WebServer.dll": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"API/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"BouncyCastle/1.8.9": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-axnBgvdD5n+FnEG6efk/tfKuMFru7R/EoISH9zjh319yb3HD24TEHSAbNN/lTRT2ulOGRxDgOsCjkuk08iwWPg==",
|
||||
"path": "bouncycastle/1.8.9",
|
||||
"hashPath": "bouncycastle.1.8.9.nupkg.sha512"
|
||||
},
|
||||
"CliWrap/3.3.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-yFJBBbDCSJ9ZgllaJub07K04EYf54V4jZ2Cm6Sg3KrGfiy27J4ed/os7UqqN7SXoIVL5ru442nPXe0sbsx2wVg==",
|
||||
"path": "cliwrap/3.3.1",
|
||||
"hashPath": "cliwrap.3.3.1.nupkg.sha512"
|
||||
},
|
||||
"Flurl/3.0.4": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-2bgCzOs3TGwRkfcijCiH+7o9Pz4pyVnt4yyLX2vD3wlMSekpmGhqe2zA4988qSMmPa6AqeekX13CY4FvsjsDJQ==",
|
||||
"path": "flurl/3.0.4",
|
||||
"hashPath": "flurl.3.0.4.nupkg.sha512"
|
||||
},
|
||||
"Flurl.Http/3.2.2": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-zVen69D8Qr1uZN4ua0ZnOMuDZol66w04AnwOSCyE5Kqy5GGbAtk0m7bKXaU+FJJ9R7ByVIKAG/kpGbGMGdt2/Q==",
|
||||
"path": "flurl.http/3.2.2",
|
||||
"hashPath": "flurl.http.3.2.2.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.NETCore.Platforms/2.1.2": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-mOJy3M0UN+LUG21dLGMxaWZEP6xYpQEpLuvuEQBaownaX4YuhH6NmNUlN9si+vNkAS6dwJ//N1O4DmLf2CikVg==",
|
||||
"path": "microsoft.netcore.platforms/2.1.2",
|
||||
"hashPath": "microsoft.netcore.platforms.2.1.2.nupkg.sha512"
|
||||
},
|
||||
"Newtonsoft.Json/13.0.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
|
||||
"path": "newtonsoft.json/13.0.1",
|
||||
"hashPath": "newtonsoft.json.13.0.1.nupkg.sha512"
|
||||
},
|
||||
"SharpZipLib/1.3.3": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-N8+hwhsKZm25tDJfWpBSW7EGhH/R7EMuiX+KJ4C4u+fCWVc1lJ5zg1u3S1RPPVYgTqhx/C3hxrqUpi6RwK5+Tg==",
|
||||
"path": "sharpziplib/1.3.3",
|
||||
"hashPath": "sharpziplib.1.3.3.nupkg.sha512"
|
||||
},
|
||||
"sqlite-net-pcl/1.8.116": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-W0NuwAOVVAR9LP4eZwNBIrim1p3EN7t8iNfSHXEhtzKAd4YyItekoQ8NyWYs4faVSrN2KZr/P5u4hycCjKKexg==",
|
||||
"path": "sqlite-net-pcl/1.8.116",
|
||||
"hashPath": "sqlite-net-pcl.1.8.116.nupkg.sha512"
|
||||
},
|
||||
"SQLitePCLRaw.bundle_green/2.0.4": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-ubFgOHDmtTcq2LU7Ss10yHnFVMm2rFVr65Ggi+Mh514KjGx4pal98P2zSvZtWf3wbtJw6G1InBgeozBtnpEfKQ==",
|
||||
"path": "sqlitepclraw.bundle_green/2.0.4",
|
||||
"hashPath": "sqlitepclraw.bundle_green.2.0.4.nupkg.sha512"
|
||||
},
|
||||
"SQLitePCLRaw.core/2.0.4": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-4XlDZpDAsboMD6qZQcz9AaKblKDUTVHF+8f3lvbP7QjoqSRr2Xc0Lm34IK2pjRIYnyFLhI3yOJ5YWfOiCid2yg==",
|
||||
"path": "sqlitepclraw.core/2.0.4",
|
||||
"hashPath": "sqlitepclraw.core.2.0.4.nupkg.sha512"
|
||||
},
|
||||
"SQLitePCLRaw.lib.e_sqlite3/2.0.4": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-oetvmtDZOE4Nnrtxd8Trapl9geBiu0rDCUXff46qGYjnUwzaU1mZ3OHnfR402tl32rx8gBWg3n5OBRaPJRbsGw==",
|
||||
"path": "sqlitepclraw.lib.e_sqlite3/2.0.4",
|
||||
"hashPath": "sqlitepclraw.lib.e_sqlite3.2.0.4.nupkg.sha512"
|
||||
},
|
||||
"SQLitePCLRaw.provider.dynamic_cdecl/2.0.4": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-AY6+vv/4ji1mCkLrS6HP/88rHT9YFKRyg3LUj8RyIk6imJMUFdQDiP8rK8gq0a/0FbqspLjK1t7rtKcr7FXRYA==",
|
||||
"path": "sqlitepclraw.provider.dynamic_cdecl/2.0.4",
|
||||
"hashPath": "sqlitepclraw.provider.dynamic_cdecl.2.0.4.nupkg.sha512"
|
||||
},
|
||||
"System.Memory/4.5.3": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA==",
|
||||
"path": "system.memory/4.5.3",
|
||||
"hashPath": "system.memory.4.5.3.nupkg.sha512"
|
||||
},
|
||||
"System.Reactive/5.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==",
|
||||
"path": "system.reactive/5.0.0",
|
||||
"hashPath": "system.reactive.5.0.0.nupkg.sha512"
|
||||
},
|
||||
"System.Reactive.Linq/5.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-IB4/qlV4T1WhZvM11RVoFUSZXPow9VWVeQ1uDkSKgz6bAO+gCf65H/vjrYlwyXmojSSxvfHndF9qdH43P/IuAw==",
|
||||
"path": "system.reactive.linq/5.0.0",
|
||||
"hashPath": "system.reactive.linq.5.0.0.nupkg.sha512"
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe/6.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==",
|
||||
"path": "system.runtime.compilerservices.unsafe/6.0.0",
|
||||
"hashPath": "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512"
|
||||
},
|
||||
"System.Text.Encoding.CodePages/4.5.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==",
|
||||
"path": "system.text.encoding.codepages/4.5.1",
|
||||
"hashPath": "system.text.encoding.codepages.4.5.1.nupkg.sha512"
|
||||
},
|
||||
"System.Text.Encodings.Web/6.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==",
|
||||
"path": "system.text.encodings.web/6.0.0",
|
||||
"hashPath": "system.text.encodings.web.6.0.0.nupkg.sha512"
|
||||
},
|
||||
"System.Text.Json/6.0.2": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-0nE2gwXLn3PTBOPwORLqwuYvWB+Beomt9ZBX+6LmogMNKUvfD1SoDb/ycB1vBntT94rGaB/SvxEyeLu14H6aEg==",
|
||||
"path": "system.text.json/6.0.2",
|
||||
"hashPath": "system.text.json.6.0.2.nupkg.sha512"
|
||||
},
|
||||
"System.Threading.Tasks.Extensions/4.5.4": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==",
|
||||
"path": "system.threading.tasks.extensions/4.5.4",
|
||||
"hashPath": "system.threading.tasks.extensions.4.5.4.nupkg.sha512"
|
||||
},
|
||||
"OpenVpnCertificatesServer/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"SysTools/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Utils/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"VictronVRM/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"WebServer/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"runtimeOptions": {
|
||||
"tfm": "net6.0",
|
||||
"framework": {
|
||||
"name": "Microsoft.NETCore.App",
|
||||
"version": "6.0.0"
|
||||
},
|
||||
"configProperties": {
|
||||
"System.Globalization.Invariant": true,
|
||||
"System.Globalization.PredefinedCulturesOnly": true
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,272 +0,0 @@
|
|||
{
|
||||
"runtimeTarget": {
|
||||
"name": ".NETCoreApp,Version=v6.0",
|
||||
"signature": ""
|
||||
},
|
||||
"compilationOptions": {},
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v6.0": {
|
||||
"OpenVpnCertificatesServer/1.0.0": {
|
||||
"dependencies": {
|
||||
"BouncyCastle": "1.8.9",
|
||||
"Flurl.Http": "3.2.2",
|
||||
"SharpZipLib": "1.3.3",
|
||||
"Utils": "1.0.0",
|
||||
"VictronVRM": "1.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"OpenVpnCertificatesServer.dll": {}
|
||||
}
|
||||
},
|
||||
"BouncyCastle/1.8.9": {
|
||||
"runtime": {
|
||||
"lib/BouncyCastle.Crypto.dll": {
|
||||
"assemblyVersion": "1.8.9.0",
|
||||
"fileVersion": "1.8.20343.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CliWrap/3.3.1": {
|
||||
"runtime": {
|
||||
"lib/netcoreapp3.0/CliWrap.dll": {
|
||||
"assemblyVersion": "3.3.1.0",
|
||||
"fileVersion": "3.3.1.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Flurl/3.0.4": {
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/Flurl.dll": {
|
||||
"assemblyVersion": "3.0.4.0",
|
||||
"fileVersion": "3.0.4.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Flurl.Http/3.2.2": {
|
||||
"dependencies": {
|
||||
"Flurl": "3.0.4",
|
||||
"Newtonsoft.Json": "12.0.3",
|
||||
"System.Text.Encoding.CodePages": "4.5.1"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/Flurl.Http.dll": {
|
||||
"assemblyVersion": "3.2.2.0",
|
||||
"fileVersion": "3.2.2.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.NETCore.Platforms/2.1.2": {},
|
||||
"Newtonsoft.Json/12.0.3": {
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/Newtonsoft.Json.dll": {
|
||||
"assemblyVersion": "12.0.0.0",
|
||||
"fileVersion": "12.0.3.23909"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SharpZipLib/1.3.3": {
|
||||
"runtime": {
|
||||
"lib/netstandard2.1/ICSharpCode.SharpZipLib.dll": {
|
||||
"assemblyVersion": "1.3.3.11",
|
||||
"fileVersion": "1.3.3.11"
|
||||
}
|
||||
}
|
||||
},
|
||||
"System.Reactive/5.0.0": {
|
||||
"runtime": {
|
||||
"lib/net5.0/System.Reactive.dll": {
|
||||
"assemblyVersion": "5.0.0.0",
|
||||
"fileVersion": "5.0.0.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"System.Reactive.Linq/5.0.0": {
|
||||
"dependencies": {
|
||||
"System.Reactive": "5.0.0",
|
||||
"System.Threading.Tasks.Extensions": "4.5.4"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/System.Reactive.Linq.dll": {
|
||||
"assemblyVersion": "3.0.6000.0",
|
||||
"fileVersion": "0.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe/6.0.0": {},
|
||||
"System.Text.Encoding.CodePages/4.5.1": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "2.1.2",
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Text.Encodings.Web/6.0.0": {
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||
}
|
||||
},
|
||||
"System.Text.Json/6.0.2": {
|
||||
"dependencies": {
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0",
|
||||
"System.Text.Encodings.Web": "6.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net6.0/System.Text.Json.dll": {
|
||||
"assemblyVersion": "6.0.0.0",
|
||||
"fileVersion": "6.0.222.6406"
|
||||
}
|
||||
}
|
||||
},
|
||||
"System.Threading.Tasks.Extensions/4.5.4": {},
|
||||
"SysTools/1.0.0": {
|
||||
"dependencies": {
|
||||
"System.Reactive.Linq": "5.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"SysTools.dll": {}
|
||||
}
|
||||
},
|
||||
"Utils/1.0.0": {
|
||||
"dependencies": {
|
||||
"CliWrap": "3.3.1",
|
||||
"System.Reactive.Linq": "5.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"Utils.dll": {}
|
||||
}
|
||||
},
|
||||
"VictronVRM/1.0.0": {
|
||||
"dependencies": {
|
||||
"Flurl.Http": "3.2.2",
|
||||
"Newtonsoft.Json": "12.0.3",
|
||||
"SysTools": "1.0.0",
|
||||
"System.Reactive.Linq": "5.0.0",
|
||||
"System.Text.Json": "6.0.2",
|
||||
"Utils": "1.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"VictronVRM.dll": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"OpenVpnCertificatesServer/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"BouncyCastle/1.8.9": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-axnBgvdD5n+FnEG6efk/tfKuMFru7R/EoISH9zjh319yb3HD24TEHSAbNN/lTRT2ulOGRxDgOsCjkuk08iwWPg==",
|
||||
"path": "bouncycastle/1.8.9",
|
||||
"hashPath": "bouncycastle.1.8.9.nupkg.sha512"
|
||||
},
|
||||
"CliWrap/3.3.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-yFJBBbDCSJ9ZgllaJub07K04EYf54V4jZ2Cm6Sg3KrGfiy27J4ed/os7UqqN7SXoIVL5ru442nPXe0sbsx2wVg==",
|
||||
"path": "cliwrap/3.3.1",
|
||||
"hashPath": "cliwrap.3.3.1.nupkg.sha512"
|
||||
},
|
||||
"Flurl/3.0.4": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-2bgCzOs3TGwRkfcijCiH+7o9Pz4pyVnt4yyLX2vD3wlMSekpmGhqe2zA4988qSMmPa6AqeekX13CY4FvsjsDJQ==",
|
||||
"path": "flurl/3.0.4",
|
||||
"hashPath": "flurl.3.0.4.nupkg.sha512"
|
||||
},
|
||||
"Flurl.Http/3.2.2": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-zVen69D8Qr1uZN4ua0ZnOMuDZol66w04AnwOSCyE5Kqy5GGbAtk0m7bKXaU+FJJ9R7ByVIKAG/kpGbGMGdt2/Q==",
|
||||
"path": "flurl.http/3.2.2",
|
||||
"hashPath": "flurl.http.3.2.2.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.NETCore.Platforms/2.1.2": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-mOJy3M0UN+LUG21dLGMxaWZEP6xYpQEpLuvuEQBaownaX4YuhH6NmNUlN9si+vNkAS6dwJ//N1O4DmLf2CikVg==",
|
||||
"path": "microsoft.netcore.platforms/2.1.2",
|
||||
"hashPath": "microsoft.netcore.platforms.2.1.2.nupkg.sha512"
|
||||
},
|
||||
"Newtonsoft.Json/12.0.3": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-6mgjfnRB4jKMlzHSl+VD+oUc1IebOZabkbyWj2RiTgWwYPPuaK1H97G1sHqGwPlS5npiF5Q0OrxN1wni2n5QWg==",
|
||||
"path": "newtonsoft.json/12.0.3",
|
||||
"hashPath": "newtonsoft.json.12.0.3.nupkg.sha512"
|
||||
},
|
||||
"SharpZipLib/1.3.3": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-N8+hwhsKZm25tDJfWpBSW7EGhH/R7EMuiX+KJ4C4u+fCWVc1lJ5zg1u3S1RPPVYgTqhx/C3hxrqUpi6RwK5+Tg==",
|
||||
"path": "sharpziplib/1.3.3",
|
||||
"hashPath": "sharpziplib.1.3.3.nupkg.sha512"
|
||||
},
|
||||
"System.Reactive/5.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==",
|
||||
"path": "system.reactive/5.0.0",
|
||||
"hashPath": "system.reactive.5.0.0.nupkg.sha512"
|
||||
},
|
||||
"System.Reactive.Linq/5.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-IB4/qlV4T1WhZvM11RVoFUSZXPow9VWVeQ1uDkSKgz6bAO+gCf65H/vjrYlwyXmojSSxvfHndF9qdH43P/IuAw==",
|
||||
"path": "system.reactive.linq/5.0.0",
|
||||
"hashPath": "system.reactive.linq.5.0.0.nupkg.sha512"
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe/6.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==",
|
||||
"path": "system.runtime.compilerservices.unsafe/6.0.0",
|
||||
"hashPath": "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512"
|
||||
},
|
||||
"System.Text.Encoding.CodePages/4.5.1": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==",
|
||||
"path": "system.text.encoding.codepages/4.5.1",
|
||||
"hashPath": "system.text.encoding.codepages.4.5.1.nupkg.sha512"
|
||||
},
|
||||
"System.Text.Encodings.Web/6.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==",
|
||||
"path": "system.text.encodings.web/6.0.0",
|
||||
"hashPath": "system.text.encodings.web.6.0.0.nupkg.sha512"
|
||||
},
|
||||
"System.Text.Json/6.0.2": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-0nE2gwXLn3PTBOPwORLqwuYvWB+Beomt9ZBX+6LmogMNKUvfD1SoDb/ycB1vBntT94rGaB/SvxEyeLu14H6aEg==",
|
||||
"path": "system.text.json/6.0.2",
|
||||
"hashPath": "system.text.json.6.0.2.nupkg.sha512"
|
||||
},
|
||||
"System.Threading.Tasks.Extensions/4.5.4": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==",
|
||||
"path": "system.threading.tasks.extensions/4.5.4",
|
||||
"hashPath": "system.threading.tasks.extensions.4.5.4.nupkg.sha512"
|
||||
},
|
||||
"SysTools/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Utils/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"VictronVRM/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"runtimeOptions": {
|
||||
"tfm": "net6.0",
|
||||
"framework": {
|
||||
"name": "Microsoft.NETCore.App",
|
||||
"version": "6.0.0"
|
||||
},
|
||||
"configProperties": {
|
||||
"System.Globalization.Invariant": true,
|
||||
"System.Globalization.PredefinedCulturesOnly": true
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,11 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# stop on errors
|
||||
set -e
|
||||
|
||||
printf "\n################################### publish ###################################\n\n"
|
||||
dotnet publish API.csproj -c Release -r linux-x64
|
||||
|
||||
printf "\n################################### sync ###################################\n\n"
|
||||
rsync -av bin/Release/netcoreapp5.0/linux-x64/publish/ ig@salidomo.innovenergy.ch:/home/ig/api
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
|
|
@ -1,4 +0,0 @@
|
|||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
|
|
@ -1,23 +0,0 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: System.Reflection.AssemblyMetadata("IsTrimmable", "True")]
|
||||
[assembly: System.Reflection.AssemblyCompanyAttribute("InnovEnergy")]
|
||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("API")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("API")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
// Generated by the MSBuild WriteCodeFragment class.
|
||||
|
|
@ -1 +0,0 @@
|
|||
b5bcdcd7d18bd3a9ee59e18ad3d0832e4b2db0fa
|
|
@ -1,8 +0,0 @@
|
|||
// <auto-generated/>
|
||||
global using global::System;
|
||||
global using global::System.Collections.Generic;
|
||||
global using global::System.IO;
|
||||
global using global::System.Linq;
|
||||
global using global::System.Net.Http;
|
||||
global using global::System.Threading;
|
||||
global using global::System.Threading.Tasks;
|
|
@ -1 +0,0 @@
|
|||
26c942d0f9a2a9c4f1830357e31a4e7567969887
|
|
@ -1,56 +0,0 @@
|
|||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/OpenVpnCertificatesServer.deps.json
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/OpenVpnCertificatesServer.runtimeconfig.json
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/OpenVpnCertificatesServer
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/API
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/API.deps.json
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/API.runtimeconfig.json
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/API.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/ref/API.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/API.pdb
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/BouncyCastle.Crypto.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/CliWrap.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/Flurl.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/Flurl.Http.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/Newtonsoft.Json.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/ICSharpCode.SharpZipLib.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/SQLite-net.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/SQLitePCLRaw.batteries_v2.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/SQLitePCLRaw.nativelibrary.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/SQLitePCLRaw.core.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/SQLitePCLRaw.provider.dynamic_cdecl.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/System.Reactive.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/System.Reactive.Linq.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/System.Text.Json.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/runtimes/alpine-x64/native/libe_sqlite3.so
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/runtimes/linux-arm/native/libe_sqlite3.so
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/runtimes/linux-arm64/native/libe_sqlite3.so
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/runtimes/linux-armel/native/libe_sqlite3.so
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/runtimes/linux-mips64/native/libe_sqlite3.so
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/runtimes/linux-musl-x64/native/libe_sqlite3.so
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/runtimes/linux-x64/native/libe_sqlite3.so
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/runtimes/linux-x86/native/libe_sqlite3.so
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/runtimes/osx-x64/native/libe_sqlite3.dylib
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/runtimes/win-arm/native/e_sqlite3.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/runtimes/win-arm64/native/e_sqlite3.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/runtimes/win-x64/native/e_sqlite3.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/runtimes/win-x86/native/e_sqlite3.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/OpenVpnCertificatesServer.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/SysTools.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/Utils.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/VictronVRM.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/WebServer.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/Utils.pdb
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/VictronVRM.pdb
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/WebServer.pdb
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/OpenVpnCertificatesServer.pdb
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/bin/Debug/net6.0/SysTools.pdb
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/obj/Debug/net6.0/API.csproj.AssemblyReference.cache
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/obj/Debug/net6.0/API.GeneratedMSBuildEditorConfig.editorconfig
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/obj/Debug/net6.0/API.AssemblyInfoInputs.cache
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/obj/Debug/net6.0/API.AssemblyInfo.cs
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/obj/Debug/net6.0/API.csproj.CoreCompileInputs.cache
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/obj/Debug/net6.0/API.csproj.CopyComplete
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/obj/Debug/net6.0/API.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/obj/Debug/net6.0/ref/API.dll
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/obj/Debug/net6.0/API.pdb
|
||||
/home/kim/code/innovenergy/new/csharp/app/API/obj/Debug/net6.0/API.genruntimeconfig.cache
|
Binary file not shown.
|
@ -1 +0,0 @@
|
|||
bfb409d9f9fd81349684431d00d084f9c26aa8cf
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue