113 lines
3.2 KiB
C#
113 lines
3.2 KiB
C#
using CliWrap;
|
|
using CliWrap.Buffered;
|
|
using InnovEnergy.Lib.Utils;
|
|
using static InnovEnergy.BmsTunnel.CliPrograms;
|
|
|
|
namespace InnovEnergy.BmsTunnel;
|
|
|
|
using Nodes = IReadOnlyList<Byte>;
|
|
|
|
public readonly struct BatteryConnection
|
|
{
|
|
public String Tty { get; }
|
|
public Nodes Nodes { get; }
|
|
|
|
private BatteryConnection(String tty, Nodes nodes)
|
|
{
|
|
Tty = tty;
|
|
Nodes = nodes;
|
|
}
|
|
|
|
private BatteryConnection(String tty, params Byte[] nodes) : this(tty, (Nodes) nodes)
|
|
{
|
|
}
|
|
|
|
|
|
public static async Task<BatteryConnection?> Connect(SshHost? host = null)
|
|
{
|
|
Console.WriteLine("searching battery connection...");
|
|
|
|
return await GetConnectionFromDBus(host)
|
|
?? await GetConnectionFromDevTty(host);
|
|
}
|
|
|
|
private static async Task<BatteryConnection?> GetConnectionFromDevTty(SshHost? host)
|
|
{
|
|
var fs = FileSystem.OnHost(host);
|
|
|
|
var ttys = await fs.GetFiles("/dev", FileType.CharacterDevice);
|
|
|
|
var candidateTtys = ttys
|
|
.Where(f => f.StartsWith("ttyUSB"))
|
|
.Select(t => t.Split("/").LastOrDefault())
|
|
.NotNull()
|
|
.ToList();
|
|
|
|
if (!candidateTtys.Any())
|
|
{
|
|
Console.WriteLine("no USB converter cable attached!");
|
|
return null;
|
|
}
|
|
|
|
var userSelectedTty = "Select TTY:".ChooseFrom(candidateTtys);
|
|
|
|
return userSelectedTty != null
|
|
? new BatteryConnection(userSelectedTty)
|
|
: null;
|
|
}
|
|
|
|
private static async Task<BatteryConnection?> GetConnectionFromDBus(SshHost? host)
|
|
{
|
|
var tty = await LsDBus
|
|
.OnHost(host)
|
|
.ExecuteBufferedAsync()
|
|
.Select(ParseBatteryTty);
|
|
|
|
if (tty == null)
|
|
return null;
|
|
|
|
Console.WriteLine("found battery on DBus");
|
|
|
|
var availableNodes = await GetNodes(tty, host);
|
|
return new BatteryConnection(tty, availableNodes);
|
|
}
|
|
|
|
private static CommandTask<Nodes> GetNodes(String tty, SshHost? host = null)
|
|
{
|
|
const String defaultArgs = "--system --print-reply --type=method_call / com.victronenergy.BusItem.GetValue";
|
|
|
|
return DBusSend
|
|
.OnHost(host)
|
|
.AppendArgument($"--dest=com.victronenergy.battery.{tty}")
|
|
.AppendArgument(defaultArgs)
|
|
.ExecuteBufferedAsync()
|
|
.Select(ParseBatteryNodes);
|
|
}
|
|
|
|
private static Nodes ParseBatteryNodes(BufferedCommandResult result)
|
|
{
|
|
return result
|
|
.StandardOutput
|
|
.Split(Environment.NewLine)
|
|
.Where(l => l.Contains("_Battery/"))
|
|
.Select(l => l.Split('/')[1])
|
|
.Where(n => Byte.TryParse(n, out _))
|
|
.Select(Byte.Parse)
|
|
.Distinct()
|
|
.OrderBy(n => n)
|
|
.ToList();
|
|
}
|
|
|
|
private static String? ParseBatteryTty(BufferedCommandResult result)
|
|
{
|
|
return result
|
|
.StandardOutput
|
|
.Split(Environment.NewLine)
|
|
.Where(l => l.Contains("com.victronenergy.battery."))
|
|
.SelectMany(l => l.Split('.'))
|
|
.LastOrDefault();
|
|
}
|
|
|
|
}
|
|
|