using System.Globalization; using System.Text; using Newtonsoft.Json; namespace ShellyExporter { public class Metrics { public enum Type { PlugS = 1, Em3 = 2 } public enum Version { Gen1 = 1, Gen2 = 2 } public class Data { public string? Power { get; set; } public string? Overpower { get; set; } public bool? IsValid { get; set; } public string? Timestamp { get; set; } public string? Total { get; set; } public string? Temperature { get; set; } public string? Voltage { get; set; } public string? Current { get; set; } public string? Emeters1Power { get; set; } public string? Emeters1Pf { get; set; } public string? Emeters1Current { get; set; } public string? Emeters1Voltage { get; set; } public bool? Emeters1IsValid { get; set; } public string? Emeters1Total { get; set; } public string? Emeters1TotalReturned { get; set; } public string? Emeters2Power { get; set; } public string? Emeters2Pf { get; set; } public string? Emeters2Current { get; set; } public string? Emeters2Voltage { get; set; } public bool? Emeters2IsValid { get; set; } public string? Emeters2Total { get; set; } public string? Emeters2TotalReturned { get; set; } public string? Emeters3Power { get; set; } public string? Emeters3Pf { get; set; } public string? Emeters3Current { get; set; } public string? Emeters3Voltage { get; set; } public bool? Emeters3IsValid { get; set; } public string? Emeters3Total { get; set; } public string? Emeters3TotalReturned { get; set; } } public static async Task Get(string path, string name, Version shellyVersion, Type type) { var sb = new StringBuilder(); Data data; switch (type) { case Type.PlugS: switch (shellyVersion) { case Version.Gen1: data = await GetPlugSGen1(path); break; case Version.Gen2: data = await GetPlugSGen2(path); break; default: throw new ArgumentOutOfRangeException(nameof(shellyVersion), shellyVersion, null); } break; case Type.Em3: switch (shellyVersion) { case Version.Gen1: data = await Get3EmGen1(path); break; default: throw new ArgumentOutOfRangeException(); } break; default: throw new ArgumentOutOfRangeException(nameof(type), type, null); } if (data.Power != null) sb.AppendLine($"meters_power_wats{{item=\"{name}\"}} {data.Power}"); if (data.Overpower != null) sb.AppendLine($"meters_overpower_wats{{item=\"{name}\"}} " + data.Overpower); if (data.IsValid != null) sb.AppendLine($"meters_is_valid{{item=\"{name}\"}} " + ((bool)data.IsValid ? 1 : 0)); if (data.Timestamp != null) sb.AppendLine($"meters_timestamp{{item=\"{name}\"}} " + data.Timestamp); if (data.Total != null) sb.AppendLine($"meters_power_total{{item=\"{name}\"}} " + data.Total); if (data.Voltage != null) sb.AppendLine($"meters_voltage_V{{item=\"{name}\"}} " + data.Voltage); if (data.Current != null) sb.AppendLine($"meters_current_A{{item=\"{name}\"}} " + data.Current); if (data.Temperature != null) sb.AppendLine($"temperature{{item=\"{name}\"}} " + data.Temperature); if (data.Emeters1Power != null) sb.AppendLine($"emeters_1_power{{item=\"{name}\"}} " + data.Emeters1Power); if (data.Emeters1Pf != null) sb.AppendLine($"emeters_1_pf{{item=\"{name}\"}} " + data.Emeters1Pf); if (data.Emeters1Current != null) sb.AppendLine($"emeters_1_current{{item=\"{name}\"}} " + data.Emeters1Current); if (data.Emeters1Voltage != null) sb.AppendLine($"emeters_1_voltage{{item=\"{name}\"}} " + data.Emeters1Voltage); if (data.Emeters1IsValid != null) sb.AppendLine($"emeters_1_is_valid{{item=\"{name}\"}} " + ((bool)data.Emeters1IsValid ? 1 : 0)); if (data.Emeters1Total != null) sb.AppendLine($"emeters_1_total{{item=\"{name}\"}} " + data.Emeters1Total); if (data.Emeters1TotalReturned != null) sb.AppendLine($"emeters_1_total_returned{{item=\"{name}\"}} " + data.Emeters1TotalReturned); if (data.Emeters2Power != null) sb.AppendLine($"emeters_2_power{{item=\"{name}\"}} " + data.Emeters2Power); if (data.Emeters2Pf != null) sb.AppendLine($"emeters_2_pf{{item=\"{name}\"}} " + data.Emeters2Pf); if (data.Emeters2Current != null) sb.AppendLine($"emeters_2_current{{item=\"{name}\"}} " + data.Emeters2Current); if (data.Emeters2Voltage != null) sb.AppendLine($"emeters_2_voltage{{item=\"{name}\"}} " + data.Emeters2Voltage); if (data.Emeters2IsValid != null) sb.AppendLine($"emeters_2_is_valid{{item=\"{name}\"}} " + ((bool)data.Emeters2IsValid ? 1 : 0)); if (data.Emeters2Total != null) sb.AppendLine($"emeters_2_total{{item=\"{name}\"}} " + data.Emeters2Total); if (data.Emeters2TotalReturned != null) sb.AppendLine($"emeters_2_total_returned{{item=\"{name}\"}} " + data.Emeters2TotalReturned); if (data.Emeters3Power != null) sb.AppendLine($"emeters_3_power{{item=\"{name}\"}} " + data.Emeters3Power); if (data.Emeters3Pf != null) sb.AppendLine($"emeters_3_pf{{item=\"{name}\"}} " + data.Emeters3Pf); if (data.Emeters3Current != null) sb.AppendLine($"emeters_3_current{{item=\"{name}\"}} " + data.Emeters3Current); if (data.Emeters3Voltage != null) sb.AppendLine($"emeters_3_voltage{{item=\"{name}\"}} " + data.Emeters3Voltage); if (data.Emeters3IsValid != null) sb.AppendLine($"emeters_3_is_valid{{item=\"{name}\"}} " + ((bool)data.Emeters3IsValid ? 1 : 0)); if (data.Emeters3Total != null) sb.AppendLine($"emeters_3_total{{item=\"{name}\"}} " + data.Emeters3Total); if (data.Emeters3TotalReturned != null) sb.AppendLine($"emeters_3_total_returned{{item=\"{name}\"}} " + data.Emeters3TotalReturned); return sb; } private static async Task GetPlugSGen1(string path) { var data = new Data(); var client = new HttpClient(); var response = await client.GetStringAsync(path + "/status"); dynamic responseObject = JsonConvert.DeserializeObject(response); if (responseObject == null) return data; if (responseObject.meters != null) { data.Power = responseObject.meters[0].power; data.Overpower = responseObject.meters[0].overpower; data.IsValid = responseObject.meters[0].is_valid; data.Timestamp = responseObject.meters[0].timestamp; data.Total = responseObject.meters[0].total; } if (responseObject.tmp.tC != null) { data.Temperature = responseObject.tmp.tC; } return data; } private static async Task Get3EmGen1(string path) { var data = new Data(); var client = new HttpClient(); var response = await client.GetStringAsync(path + "/status"); dynamic responseObject = JsonConvert.DeserializeObject(response); if (responseObject == null) return data; if (responseObject.total_power != null) { data.Total = responseObject.total_power; } if (responseObject.emeters != null) { data.Emeters1Power = responseObject.emeters[0].power; data.Emeters1Pf = responseObject.emeters[0].pf; data.Emeters1Current = responseObject.emeters[0].current; data.Emeters1Voltage = responseObject.emeters[0].voltage; data.Emeters1IsValid = responseObject.emeters[0].is_valid; data.Emeters1Total = responseObject.emeters[0].total; data.Emeters1TotalReturned = responseObject.emeters[0].total_returned; } if (responseObject.emeters != null) { data.Emeters2Power = responseObject.emeters[1].power; data.Emeters2Pf = responseObject.emeters[1].pf; data.Emeters2Current = responseObject.emeters[1].current; data.Emeters2Voltage = responseObject.emeters[1].voltage; data.Emeters2IsValid = responseObject.emeters[1].is_valid; data.Emeters2Total = responseObject.emeters[1].total; data.Emeters2TotalReturned = responseObject.emeters[1].total_returned; } if (responseObject.emeters != null) { data.Emeters3Power = responseObject.emeters[2].power; data.Emeters3Pf = responseObject.emeters[2].pf; data.Emeters3Current = responseObject.emeters[2].current; data.Emeters3Voltage = responseObject.emeters[2].voltage; data.Emeters3IsValid = responseObject.emeters[2].is_valid; data.Emeters3Total = responseObject.emeters[2].total; data.Emeters3TotalReturned = responseObject.emeters[2].total_returned; } return data; } private static async Task GetPlugSGen2(string path) { var data = new Data(); var client = new HttpClient(); var response = await client.GetStringAsync(path + "/rpc/Switch.GetStatus?id=0"); dynamic responseObject = JsonConvert.DeserializeObject(response); if (responseObject == null) return data; if (responseObject.apower != null) data.Power = responseObject.apower; if (responseObject.current != null) data.Current = responseObject.current; if (responseObject.voltage != null) data.Voltage = responseObject.voltage; if (responseObject.aenergy != null) { if (responseObject.aenergy.total != null) data.Total = (Convert.ToDecimal(responseObject.aenergy.total) * (decimal)60).ToString(CultureInfo.InvariantCulture); if (responseObject.aenergy.minute_ts != null) data.Timestamp = responseObject.aenergy.minute_ts; } if (responseObject.temperature != null && responseObject.temperature.tC != null) data.Temperature = responseObject.temperature.tC; return data; } } }