diff --git a/EgwProxy.Shelly.Test/Program.cs b/EgwProxy.Shelly.Test/Program.cs index a179125..3e74d6c 100644 --- a/EgwProxy.Shelly.Test/Program.cs +++ b/EgwProxy.Shelly.Test/Program.cs @@ -83,7 +83,7 @@ namespace EgwProxy.Shelly.Test catch { } // setup devAddr - Shelly1PmOptions options = new Shelly1PmOptions() + ShellyOptions options = new ShellyOptions() { DefaultTimeout = TimeSpan.FromSeconds(testConf.tOutSec), ServerUri = new Uri($"http://{testConf.devAddr}/rpc") @@ -124,7 +124,7 @@ namespace EgwProxy.Shelly.Test switch (item.action) { case stepType.getFullStatus: - var respFull = Task.Run(() => shelly1PM.GetStatus(CancellationToken.None)).Result; + var respFull = Task.Run(() => shelly1PM.GetStatus(CancellationToken.None)).Result; if (respFull.IsSuccess) { string serValFull = JsonConvert.SerializeObject(respFull.Value, Formatting.Indented); @@ -132,11 +132,21 @@ namespace EgwProxy.Shelly.Test } break; case stepType.getSwitchStatus: - var respSwitch = Task.Run(() => shellyPro3.GetEmStatus(CancellationToken.None)).Result; - if (respSwitch.IsSuccess) + var respEmDto = Task.Run(() => shellyPro3.GetEmStatus(CancellationToken.None, 0)).Result; + if (respEmDto.IsSuccess) { - string serValSwitch = JsonConvert.SerializeObject(respSwitch.Value, Formatting.Indented); - esitoStep = respSwitch.IsSuccess ? serValSwitch : "Errore in GetEmStatus"; + string serValSwitch = JsonConvert.SerializeObject(respEmDto.Value, Formatting.Indented); + esitoStep = respEmDto.IsSuccess ? serValSwitch : "Errore in GetEmStatus"; + } + + // registro ed eseguo chiamata in modalità sincrona + sw.Restart(); + var respEmDataDto = Task.Run(() => shellyPro3.GetEmDataStatus(CancellationToken.None, 0)).Result; + if (respEmDataDto.IsSuccess) + { + string serVal = JsonConvert.SerializeObject(respEmDataDto.Value, Formatting.Indented); + sw.Stop(); + writeResult(respEmDataDto.IsSuccess, serVal); } break; default: @@ -169,10 +179,10 @@ namespace EgwProxy.Shelly.Test // registro ed eseguo chiamata in modalità sincrona sw.Restart(); var response = Task.Run(() => shellyClient.GetStatus(CancellationToken.None)).Result; + sw.Stop(); if (response.IsSuccess) { string serVal = JsonConvert.SerializeObject(response.Value, Formatting.Indented); - sw.Stop(); writeResult(response.IsSuccess, serVal); } } @@ -197,10 +207,10 @@ namespace EgwProxy.Shelly.Test // registro ed eseguo chiamata in modalità sincrona sw.Restart(); var response = Task.Run(() => shellyClient.GetStatus(CancellationToken.None)).Result; + sw.Stop(); if (response.IsSuccess) { string serVal = JsonConvert.SerializeObject(response.Value, Formatting.Indented); - sw.Stop(); writeResult(response.IsSuccess, serVal); } } diff --git a/EgwProxy.Shelly/Clients/Shelly1PmClient.cs b/EgwProxy.Shelly/Clients/Shelly1PmClient.cs index 269c4e8..a3673b4 100644 --- a/EgwProxy.Shelly/Clients/Shelly1PmClient.cs +++ b/EgwProxy.Shelly/Clients/Shelly1PmClient.cs @@ -10,7 +10,7 @@ namespace EgwProxy.Shelly.Clients { public class Shelly1PmClient : ShellyClientBase, IShelly1Pm { - public Shelly1PmClient(HttpClient httpClient, Shelly1PmOptions shellyOptions) : base(httpClient, shellyOptions) + public Shelly1PmClient(HttpClient httpClient, ShellyOptions shellyOptions) : base(httpClient, shellyOptions) { } diff --git a/EgwProxy.Shelly/Clients/ShellyPro3EmClient.cs b/EgwProxy.Shelly/Clients/ShellyPro3EmClient.cs index ef53785..1cb4779 100644 --- a/EgwProxy.Shelly/Clients/ShellyPro3EmClient.cs +++ b/EgwProxy.Shelly/Clients/ShellyPro3EmClient.cs @@ -14,7 +14,7 @@ namespace EgwProxy.Shelly.Clients { public class ShellyPro3EmClient : ShellyClientBase, IShellyPro3Em { - public ShellyPro3EmClient(HttpClient httpClient, Shelly1PmOptions shellyOptions) : base(httpClient, shellyOptions) + public ShellyPro3EmClient(HttpClient httpClient, ShellyOptions shellyOptions) : base(httpClient, shellyOptions) { } @@ -25,11 +25,18 @@ namespace EgwProxy.Shelly.Clients return await ExecuteRequestAsync(requestMessage, cancellationToken, timeout); } - public async Task> GetEmStatus(CancellationToken cancellationToken, TimeSpan? timeout = null) + public async Task> GetEmStatus(CancellationToken cancellationToken, int id, TimeSpan? timeout = null) { - var endpoint = ServerUri.AppendPathSegment("EM.GetStatus?id=0"); + var endpoint = ServerUri.AppendPathSegment("EM.GetStatus").AppendQueryParam("id", id); var requestMessage = new HttpRequestMessage(HttpMethod.Get, endpoint); - return await ExecuteRequestAsync(requestMessage, cancellationToken, timeout); + return await ExecuteRequestAsync(requestMessage, cancellationToken, timeout); + } + + public async Task> GetEmDataStatus(CancellationToken cancellationToken, int id, TimeSpan? timeout = null) + { + var endpoint = ServerUri.AppendPathSegment("EMData.GetStatus").AppendQueryParam("id", id); + var requestMessage = new HttpRequestMessage(HttpMethod.Get, endpoint); + return await ExecuteRequestAsync(requestMessage, cancellationToken, timeout); } #if false @@ -46,7 +53,10 @@ namespace EgwProxy.Shelly.Clients var readAsStringAsync = await response.Content.ReadAsStringAsync(); var settings = new JsonSerializerSettings { - Converters = new List { new EnergyDtoConverter() } + Converters = new List { + new EMDtoConverter(), + new EMDataDtoConverter() + } }; var shelly1Status = JsonConvert.DeserializeObject(readAsStringAsync, settings); return ShellyResult.Success(shelly1Status, readAsStringAsync); diff --git a/EgwProxy.Shelly/Converters/EMDataDtoConverter.cs b/EgwProxy.Shelly/Converters/EMDataDtoConverter.cs new file mode 100644 index 0000000..90e77c4 --- /dev/null +++ b/EgwProxy.Shelly/Converters/EMDataDtoConverter.cs @@ -0,0 +1,71 @@ +using EgwProxy.Shelly.DTO.Gen2; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EgwProxy.Shelly.Converters +{ + public class EMDataDtoConverter : JsonConverter + { + public override EMDataDto ReadJson(JsonReader reader, Type objectType, EMDataDto existingValue, bool hasExistingValue, JsonSerializer serializer) + { + JObject obj = JObject.Load(reader); + var dto = new EMDataDto + { + Id = (int)obj["id"], + Errors = obj["errors"]?.ToObject>() ?? new List() + }; + + dto.TotalPhaseA = new EnergyDto + { + ActEnergy = (double)obj["a_total_act_energy"], + RetEnergy = (double)obj["a_total_act_ret_energy"] + }; + + dto.TotalPhaseB = new EnergyDto + { + ActEnergy = (double)obj["b_total_act_energy"], + RetEnergy = (double)obj["b_total_act_ret_energy"] + }; + + dto.TotalPhaseC = new EnergyDto + { + ActEnergy = (double)obj["c_total_act_energy"], + RetEnergy = (double)obj["c_total_act_ret_energy"] + }; + + dto.TotalAll = new EnergyDto + { + ActEnergy = (double)obj["total_act"], + RetEnergy = (double)obj["total_act_ret"] + }; + + return dto; + } + + public override void WriteJson(JsonWriter writer, EMDataDto value, JsonSerializer serializer) + { + var obj = new JObject + { + ["id"] = value.Id, + ["a_total_act_energy"] = value.TotalPhaseA.ActEnergy, + ["a_total_act_ret_energy"] = value.TotalPhaseA.RetEnergy, + ["b_total_act_energy"] = value.TotalPhaseB.ActEnergy, + ["b_total_act_ret_energy"] = value.TotalPhaseB.RetEnergy, + ["c_total_act_energy"] = value.TotalPhaseC.ActEnergy, + ["c_total_act_ret_energy"] = value.TotalPhaseC.RetEnergy, + ["total_act"] = value.TotalAll.ActEnergy, + ["total_act_ret"] = value.TotalAll.RetEnergy, + ["errors"] = JArray.FromObject(value.Errors) + }; + + obj.WriteTo(writer); + } + + } + +} diff --git a/EgwProxy.Shelly/Converters/EMDtoConverter.cs b/EgwProxy.Shelly/Converters/EMDtoConverter.cs new file mode 100644 index 0000000..50b8cff --- /dev/null +++ b/EgwProxy.Shelly/Converters/EMDtoConverter.cs @@ -0,0 +1,100 @@ +using EgwProxy.Shelly.DTO.Gen2; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EgwProxy.Shelly.Converters +{ + public class EMDtoConverter : JsonConverter + { + public override EMDto ReadJson(JsonReader reader, Type objectType, EMDto existingValue, bool hasExistingValue, JsonSerializer serializer) + { + JObject obj = JObject.Load(reader); + var dto = new EMDto + { + Id = (int)obj["id"], + NeutralCurrent = obj["n_current"]?.ToObject() ?? 0, + TotalCurrent = (double)obj["total_current"], + TotalActivePower = (double)obj["total_act_power"], + TotalApparentPower = (double)obj["total_aprt_power"], + UserCalibratedPhase = obj["user_calibrated_phase"]?.ToObject>() ?? new List(), + Errors = obj["errors"]?.ToObject>() ?? new List() + }; + + dto.PhaseA = new PhaseDataDto + { + Current = (double)obj["a_current"], + Voltage = (double)obj["a_voltage"], + ActivePower = (double)obj["a_act_power"], + ApparentPower = (double)obj["a_aprt_power"], + PowerFactor = (double)obj["a_pf"], + Frequency = (double)obj["a_freq"] + }; + + dto.PhaseB = new PhaseDataDto + { + Current = (double)obj["b_current"], + Voltage = (double)obj["b_voltage"], + ActivePower = (double)obj["b_act_power"], + ApparentPower = (double)obj["b_aprt_power"], + PowerFactor = (double)obj["b_pf"], + Frequency = (double)obj["b_freq"] + }; + + dto.PhaseC = new PhaseDataDto + { + Current = (double)obj["c_current"], + Voltage = (double)obj["c_voltage"], + ActivePower = (double)obj["c_act_power"], + ApparentPower = (double)obj["c_aprt_power"], + PowerFactor = (double)obj["c_pf"], + Frequency = (double)obj["c_freq"] + }; + + return dto; + } + + public override void WriteJson(JsonWriter writer, EMDto value, JsonSerializer serializer) + { + var obj = new JObject + { + ["id"] = value.Id, + ["a_current"] = value.PhaseA.Current, + ["a_voltage"] = value.PhaseA.Voltage, + ["a_act_power"] = value.PhaseA.ActivePower, + ["a_aprt_power"] = value.PhaseA.ApparentPower, + ["a_pf"] = value.PhaseA.PowerFactor, + ["a_freq"] = value.PhaseA.Frequency, + + ["b_current"] = value.PhaseB.Current, + ["b_voltage"] = value.PhaseB.Voltage, + ["b_act_power"] = value.PhaseB.ActivePower, + ["b_aprt_power"] = value.PhaseB.ApparentPower, + ["b_pf"] = value.PhaseB.PowerFactor, + ["b_freq"] = value.PhaseB.Frequency, + + ["c_current"] = value.PhaseC.Current, + ["c_voltage"] = value.PhaseC.Voltage, + ["c_act_power"] = value.PhaseC.ActivePower, + ["c_aprt_power"] = value.PhaseC.ApparentPower, + ["c_pf"] = value.PhaseC.PowerFactor, + ["c_freq"] = value.PhaseC.Frequency, + + ["n_current"] = value.NeutralCurrent, + ["total_current"] = value.TotalCurrent, + ["total_act_power"] = value.TotalActivePower, + ["total_aprt_power"] = value.TotalApparentPower, + ["user_calibrated_phase"] = JArray.FromObject(value.UserCalibratedPhase), + ["errors"] = JArray.FromObject(value.Errors) + }; + + obj.WriteTo(writer); + } + + } + +} diff --git a/EgwProxy.Shelly/Converters/EnergyDtoConverter.cs b/EgwProxy.Shelly/Converters/EnergyDtoConverter.cs deleted file mode 100644 index 81de237..0000000 --- a/EgwProxy.Shelly/Converters/EnergyDtoConverter.cs +++ /dev/null @@ -1,66 +0,0 @@ -using EgwProxy.Shelly.DTO.Gen2; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace EgwProxy.Shelly.Converters -{ - public class EnergyDtoConverter : JsonConverter - { - public override EnergyDto ReadJson(JsonReader reader, Type objectType, EnergyDto existingValue, bool hasExistingValue, JsonSerializer serializer) - { - JObject obj = JObject.Load(reader); - var dto = new EnergyDto - { - Id = (int)obj["id"], - NeutralCurrent = obj["n_current"]?.ToObject() ?? 0, - TotalCurrent = (double)obj["total_current"], - TotalActivePower = (double)obj["total_act_power"], - TotalApparentPower = (double)obj["total_aprt_power"], - UserCalibratedPhase = obj["user_calibrated_phase"]?.ToObject>() ?? new List() - }; - - dto.PhaseA = new PhaseDataDto - { - Current = (double)obj["a_current"], - Voltage = (double)obj["a_voltage"], - ActivePower = (double)obj["a_act_power"], - ApparentPower = (double)obj["a_aprt_power"], - PowerFactor = (double)obj["a_pf"], - Frequency = (double)obj["a_freq"] - }; - - dto.PhaseB = new PhaseDataDto - { - Current = (double)obj["b_current"], - Voltage = (double)obj["b_voltage"], - ActivePower = (double)obj["b_act_power"], - ApparentPower = (double)obj["b_aprt_power"], - PowerFactor = (double)obj["b_pf"], - Frequency = (double)obj["b_freq"] - }; - - dto.PhaseC = new PhaseDataDto - { - Current = (double)obj["c_current"], - Voltage = (double)obj["c_voltage"], - ActivePower = (double)obj["c_act_power"], - ApparentPower = (double)obj["c_aprt_power"], - PowerFactor = (double)obj["c_pf"], - Frequency = (double)obj["c_freq"] - }; - - return dto; - } - - public override void WriteJson(JsonWriter writer, EnergyDto value, JsonSerializer serializer) - { - throw new NotImplementedException("Serialization not implemented"); - } - } - -} diff --git a/EgwProxy.Shelly/DTO/Gen2/EMDataDto.cs b/EgwProxy.Shelly/DTO/Gen2/EMDataDto.cs new file mode 100644 index 0000000..20b5b5c --- /dev/null +++ b/EgwProxy.Shelly/DTO/Gen2/EMDataDto.cs @@ -0,0 +1,40 @@ +using EgwProxy.Shelly.Converters; +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace EgwProxy.Shelly.DTO.Gen2 +{ + /// + /// EnergyMeterData Info DTO (Total Counters) + /// + //[JsonConverter(typeof(EMDataDtoConverter))] + public class EMDataDto + { + + public int Id { get; set; } + + /// + /// Phase A data + /// + public EnergyDto TotalPhaseA { get; set; } = new EnergyDto(); + /// + /// Phase B data + /// + public EnergyDto TotalPhaseB { get; set; } = new EnergyDto(); + /// + /// Phase C data + /// + public EnergyDto TotalPhaseC { get; set; } = new EnergyDto(); + + /// + /// AllPhase data + /// + public EnergyDto TotalAll { get; set; } = new EnergyDto(); + + /// + /// Calibrazione fasi manuale + /// + [JsonProperty("errors")] + public List Errors { get; set; } = new List(); + } +} diff --git a/EgwProxy.Shelly/DTO/Gen2/EMDto.cs b/EgwProxy.Shelly/DTO/Gen2/EMDto.cs new file mode 100644 index 0000000..b8cd584 --- /dev/null +++ b/EgwProxy.Shelly/DTO/Gen2/EMDto.cs @@ -0,0 +1,65 @@ +using EgwProxy.Shelly.Converters; +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace EgwProxy.Shelly.DTO.Gen2 +{ + /// + /// EnergyMeter Info DTO (Realtime Data) + /// + //[JsonConverter(typeof(EMDtoConverter))] + public class EMDto + { + + public int Id { get; set; } + + /// + /// Phase A data + /// + public PhaseDataDto PhaseA { get; set; } = new PhaseDataDto(); + /// + /// Phase B data + /// + public PhaseDataDto PhaseB { get; set; } = new PhaseDataDto(); + /// + /// Phase C data + /// + public PhaseDataDto PhaseC { get; set; } = new PhaseDataDto(); + + /// + /// Corrente Neutro + /// + [JsonProperty("n_current")] + public double NeutralCurrent { get; set; } = 0; + + /// + /// Corrente Totale + /// + [JsonProperty("total_current")] + public double TotalCurrent { get; set; } = 0; + + /// + /// Corrente Totale Attiva + /// + [JsonProperty("total_act_power")] + public double TotalActivePower { get; set; } = 0; + + /// + /// Corrente Totale Apparente + /// + [JsonProperty("total_aprt_power")] + public double TotalApparentPower { get; set; } = 0; + + /// + /// Calibrazione fasi manuale + /// + [JsonProperty("user_calibrated_phase")] + public List UserCalibratedPhase { get; set; } = new List(); + + /// + /// Calibrazione fasi manuale + /// + [JsonProperty("errors")] + public List Errors { get; set; } = new List(); + } +} diff --git a/EgwProxy.Shelly/DTO/Gen2/EnergyDto.cs b/EgwProxy.Shelly/DTO/Gen2/EnergyDto.cs index d0348e5..f9ff484 100644 --- a/EgwProxy.Shelly/DTO/Gen2/EnergyDto.cs +++ b/EgwProxy.Shelly/DTO/Gen2/EnergyDto.cs @@ -1,57 +1,21 @@ -using Newtonsoft.Json; +using System; using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; namespace EgwProxy.Shelly.DTO.Gen2 { - /// - /// Energy Info - /// public class EnergyDto { - - public int Id { get; set; } + /// + /// Energia Attiva (Wh) + /// + public double ActEnergy { get; set; } = 0; /// - /// Phase A data + /// Energia Ritornata (Wh) /// - public PhaseDataDto PhaseA { get; set; } = new PhaseDataDto(); - /// - /// Phase B data - /// - public PhaseDataDto PhaseB { get; set; } = new PhaseDataDto(); - /// - /// Phase C data - /// - public PhaseDataDto PhaseC { get; set; } = new PhaseDataDto(); - - /// - /// Corrente Neutro - /// - [JsonProperty("n_current")] - public double NeutralCurrent { get; set; } = 0; - - /// - /// Corrente Totale - /// - [JsonProperty("total_current")] - public double TotalCurrent { get; set; } = 0; - - /// - /// Corrente Totale Attiva - /// - [JsonProperty("total_act_power")] - public double TotalActivePower { get; set; } = 0; - - /// - /// Corrente Totale Apparente - /// - [JsonProperty("total_aprt_power")] - public double TotalApparentPower { get; set; } = 0; - - /// - /// Calibrazione fasi manuale - /// - [JsonProperty("user_calibrated_phase")] - public List UserCalibratedPhase { get; set; } = new List(); + public double RetEnergy { get; set; } = 0; } } diff --git a/EgwProxy.Shelly/DTO/ShellyGen2StatusDto.cs b/EgwProxy.Shelly/DTO/ShellyGen2StatusDto.cs index be02120..048081e 100644 --- a/EgwProxy.Shelly/DTO/ShellyGen2StatusDto.cs +++ b/EgwProxy.Shelly/DTO/ShellyGen2StatusDto.cs @@ -26,7 +26,7 @@ namespace EgwProxy.Shelly.DTO /// EnergyMonitor 0 data /// [JsonProperty("em:0")] - public EnergyDto EmData { get; set; } + public EMDto EmData { get; set; } /// /// MQTT queue state diff --git a/EgwProxy.Shelly/EgwProxy.Shelly.csproj b/EgwProxy.Shelly/EgwProxy.Shelly.csproj index 60fff12..22709c5 100644 --- a/EgwProxy.Shelly/EgwProxy.Shelly.csproj +++ b/EgwProxy.Shelly/EgwProxy.Shelly.csproj @@ -88,9 +88,12 @@ - + + + + @@ -106,7 +109,7 @@ - + diff --git a/EgwProxy.Shelly/Options/Shelly1PmOptions.cs b/EgwProxy.Shelly/Options/ShellyOptions.cs similarity index 81% rename from EgwProxy.Shelly/Options/Shelly1PmOptions.cs rename to EgwProxy.Shelly/Options/ShellyOptions.cs index 41c0141..5cfb15d 100644 --- a/EgwProxy.Shelly/Options/Shelly1PmOptions.cs +++ b/EgwProxy.Shelly/Options/ShellyOptions.cs @@ -6,14 +6,14 @@ using System.Threading.Tasks; namespace EgwProxy.Shelly.Options { - public class Shelly1PmOptions : IShellyCommonOptions + public class ShellyOptions : IShellyCommonOptions { public Uri ServerUri { get; set; } public TimeSpan? DefaultTimeout { get; set; } public string UserName { get; set; } public string Password { get; set; } - public Shelly1PmOptions() + public ShellyOptions() { DefaultTimeout = null; }