Code
·
110 lines
·
3703 bytes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110using GoodWe;
if (args.Length == 0)
{
Console.WriteLine("Usage: GoodWe.Console <inverter-ip> [udp|tcp] [family]");
Console.WriteLine(" family: ET (default), ES, DT");
Console.WriteLine();
Console.WriteLine("Example: GoodWe.Console 192.168.1.100");
Console.WriteLine(" GoodWe.Console 192.168.1.100 udp DT");
Console.WriteLine(" GoodWe.Console 192.168.1.100 tcp ET");
return 1;
}
string host = args[0];
string transport = args.Length > 1 ? args[1].ToLower() : "udp";
string family = args.Length > 2 ? args[2] : "Unknown";
Console.WriteLine($"Connecting to {host} ({transport.ToUpper()}{(family != null ? $" / {family}" : "")}) ...");
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
try
{
bool tcp = transport == "tcp";
await using var inverter = await GoodWeClient.ConnectAsync(host,
tcp: tcp, family: Enum.Parse<FamilyEnum>(family!), ct: cts.Token);
if (inverter == null)
return 1;
// ── Device info ────────────────────────────────────────────────────────
Console.WriteLine();
PrintHeader("Device Info");
PrintRow("Model", inverter.ModelName);
PrintRow("Serial", inverter.SerialNumber);
PrintRow("Rated Power", $"{inverter.RatedPower} W");
PrintRow("Firmware", inverter.Firmware);
PrintRow("ARM Firmware", inverter.ArmFirmware);
// ── Runtime data ───────────────────────────────────────────────────────
Console.WriteLine();
PrintHeader("Runtime Data");
var data = await inverter.ReadRuntimeDataAsync(cts.Token);
PrintAllData(data);
// ── Settings ───────────────────────────────────────────────────────────
Console.WriteLine();
PrintHeader("Settings");
var opMode = await inverter.GetOperationModeAsync(cts.Token);
PrintRow("Operation Mode", opMode.ToString());
var dictSettings = await inverter.ReadSettingsDataAsync(CancellationToken.None);
PrintRow("Grid Export Limit", $"{dictSettings["grid_export_limit"]}");
PrintRow("Grid Export Limit Value", $"{dictSettings["grid_export_limit_value"]} %");
Console.WriteLine();
Console.WriteLine("Press any key to exit...");
Console.ReadKey(intercept: true);
return 0;
}
catch (MaxRetriesException)
{
Console.Error.WriteLine($"Error: no response from {host} after retries. Check IP and network.");
return 2;
}
catch (InverterError ex)
{
Console.Error.WriteLine($"Inverter error: {ex.Message}");
return 3;
}
catch (OperationCanceledException)
{
Console.Error.WriteLine("Timed out.");
return 4;
}
// ── helpers ──────────────────────────────────────────────────────────────────
static void PrintHeader(string title)
{
Console.WriteLine($"=== {title} ===");
}
static void PrintRow(string label, string? value)
{
Console.WriteLine($" {label,-30}: {value ?? "n/a"}");
}
static void PrintAllData(Dictionary<string, object?> data)
{
// Separate into measurements (have numeric/typed values) and labels/codes
// Sort by key so output is predictable
foreach (var kv in data.OrderBy(k => k.Key))
{
if (kv.Value is null) continue;
string display = kv.Value switch
{
double d => $"{d:F2}",
float f => $"{f:F2}",
DateTime dt => dt.ToString("yyyy-MM-dd HH:mm:ss"),
_ => kv.Value.ToString() ?? ""
};
Console.WriteLine($" {kv.Key,-35}: {display}");
}
}