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.App.RemoteSupportConsole; public static class VrmConnection { public static async Task Open(Installation installation, IReadOnlyList 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 OpenProxy(String rsHost, String rsPort) { "contacting Victron remote support host at ".Write(); rsHost.Write(Cyan); " ... ".Write(); var stdIn = new Subject(); var stdInPipe = stdIn .Select(l => l + "\n") .Select(Encoding.UTF8.GetBytes) .AsPipeSource(); var stdOut = Ssh .Command(rsHost, "ccgxsupport", "22") .WithStandardInputPipe(stdInPipe) .Observe() .OfType() .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 Log(this IObservable 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