128 lines
4.9 KiB
C#
128 lines
4.9 KiB
C#
|
using System.Reactive.Linq;
|
||
|
using System.Reactive.Subjects;
|
||
|
using System.Text;
|
||
|
using CliWrap.EventStream;
|
||
|
using InnovEnergy.Lib.Utils;
|
||
|
using InnovEnergy.Lib.Victron.VictronVRM;
|
||
|
using static System.ConsoleColor;
|
||
|
using static System.StringSplitOptions;
|
||
|
|
||
|
namespace InnovEnergy.RemoteSupportConsole;
|
||
|
|
||
|
public static class VrmConnection
|
||
|
{
|
||
|
public static async Task<Int32> Open(Installation installation, IReadOnlyList<Detail> details)
|
||
|
{
|
||
|
var rsHost = details.RemoteSupportIp();
|
||
|
var rsPort = details.RemoteSupportPort();
|
||
|
|
||
|
"starting remote support connection with ".Write();
|
||
|
installation.Name.WriteLine(Green);
|
||
|
|
||
|
using var proxy = await OpenProxy(rsHost!, rsPort!);
|
||
|
|
||
|
"initiating SSH connection\n".WriteLine();
|
||
|
|
||
|
return await Ssh.Interactive(proxy.Host, installation.Name, proxy.User, proxy.Port);
|
||
|
|
||
|
}
|
||
|
|
||
|
private static async Task<VrmProxy> OpenProxy(String rsHost, String rsPort)
|
||
|
{
|
||
|
"contacting Victron remote support host at ".Write();
|
||
|
rsHost.Write(Cyan);
|
||
|
" ... ".Write();
|
||
|
|
||
|
var stdIn = new Subject<String>();
|
||
|
|
||
|
var stdInPipe = stdIn
|
||
|
.Select(l => l + "\n")
|
||
|
.Select(Encoding.UTF8.GetBytes)
|
||
|
.AsPipeSource();
|
||
|
|
||
|
var stdOut = Ssh
|
||
|
.Command(rsHost, "ccgxsupport", "22")
|
||
|
.WithStandardInputPipe(stdInPipe)
|
||
|
.Observe()
|
||
|
.OfType<StandardOutputCommandEvent>()
|
||
|
.Select(e => e.Text)
|
||
|
.Replay();
|
||
|
|
||
|
var connection = stdOut.Connect();
|
||
|
|
||
|
await stdOut.FirstAsync(l => l.StartsWith("Full readline support"));
|
||
|
|
||
|
"ok".WriteLine();
|
||
|
"requesting tunnel through port ".Write();
|
||
|
rsPort.Write(Cyan);
|
||
|
" ... ".Write();
|
||
|
|
||
|
stdIn.OnNext($"proxyport {rsPort}");
|
||
|
|
||
|
var connectMsg = await stdOut.FirstAsync(l => l.StartsWith("You can now connect"));
|
||
|
|
||
|
"ok".WriteLine();
|
||
|
|
||
|
var portUserHost = connectMsg.Split(" ", RemoveEmptyEntries);
|
||
|
var userHost = portUserHost[^1].Split("@");
|
||
|
var user = userHost[0];
|
||
|
var host = userHost[1];
|
||
|
var port = portUserHost[^2];
|
||
|
|
||
|
return new VrmProxy(connection, user, host, port);
|
||
|
}
|
||
|
|
||
|
public static IObservable<CommandEvent> Log(this IObservable<CommandEvent> es)
|
||
|
{
|
||
|
return es.Do(e => Console.WriteLine(Log(e)));
|
||
|
}
|
||
|
|
||
|
private static String Log(CommandEvent e) => e switch
|
||
|
{
|
||
|
StandardOutputCommandEvent so => "=> " + so.Text,
|
||
|
StandardErrorCommandEvent se => "!! " + se.Text,
|
||
|
StartedCommandEvent => "START",
|
||
|
ExitedCommandEvent => "EXIT",
|
||
|
_ => "UNKNOWN MESSAGE: " + e.GetType().Name
|
||
|
};
|
||
|
}
|
||
|
|
||
|
|
||
|
// ReSharper disable CommentTypo
|
||
|
|
||
|
// $ ssh ccgxsupport@3.72.120.57
|
||
|
// Welcome to the Victron remote support tunnel creator.
|
||
|
//
|
||
|
// You will given a one-time tunnel. SSH authentication to
|
||
|
// the Color Control is done with your SSH public key.
|
||
|
//
|
||
|
// *****************************************************************************
|
||
|
// * IMPORTANT NOTE: *
|
||
|
// * *
|
||
|
// * There are now multiple SSH support hosts. Logging in directly *
|
||
|
// * is not officially supported behavior, because you may end up on the wrong *
|
||
|
// * server. A script called 'rs' to use the new format '1.2.3.4;45630' is *
|
||
|
// * available. Ask your Victron contact to supply you with it. *
|
||
|
// *****************************************************************************
|
||
|
//
|
||
|
// The proxy opened up to the CCGX will be restricted to your IP: 145.40.192.17
|
||
|
//
|
||
|
// Commands are:
|
||
|
// proxyport [port] - take color control [port] and temporarily make it available to the outside.
|
||
|
// iptoport [ip] - show the ports being listened on by that IP. Note, you do need to know
|
||
|
// which server the device is connected to. Currently, possibilites are:
|
||
|
// - 84.22.108.49 (EU)
|
||
|
// - 84.22.107.120 (EU)
|
||
|
// - 3.69.217.175 (EU)
|
||
|
// - 3.72.120.57 (EU)
|
||
|
// - 3.25.10.245 (AUS Sydney)
|
||
|
// - 35.165.124.40 (USA West)
|
||
|
// - 13.244.154.199 (South Africa)
|
||
|
// - 13.246.113.18 (South Africa)
|
||
|
// A good start would be the last known, as seen on the diagnostics page.
|
||
|
// exit - exits the shell and all tunnels you set up
|
||
|
//
|
||
|
// Full readline support (command history and editing) is available.
|
||
|
//
|
||
|
// proxyport 24337
|
||
|
// You can now connect to the CCGX with: ssh -o 'UserKnownHostsFile=/dev/null' -o 'StrictHostKeyChecking=no' -o 'ServerAliveInterval=60' -p 4001 root@3.72.120.57
|