Update libreria x Shelly

This commit is contained in:
Samuele Locatelli
2025-08-07 08:35:34 +02:00
parent 6531d13e67
commit 302f1b1035
12 changed files with 328 additions and 131 deletions
+18 -8
View File
@@ -83,7 +83,7 @@ namespace EgwProxy.Shelly.Test
catch catch
{ } { }
// setup devAddr // setup devAddr
Shelly1PmOptions options = new Shelly1PmOptions() ShellyOptions options = new ShellyOptions()
{ {
DefaultTimeout = TimeSpan.FromSeconds(testConf.tOutSec), DefaultTimeout = TimeSpan.FromSeconds(testConf.tOutSec),
ServerUri = new Uri($"http://{testConf.devAddr}/rpc") ServerUri = new Uri($"http://{testConf.devAddr}/rpc")
@@ -124,7 +124,7 @@ namespace EgwProxy.Shelly.Test
switch (item.action) switch (item.action)
{ {
case stepType.getFullStatus: case stepType.getFullStatus:
var respFull = Task.Run(() => shelly1PM.GetStatus(CancellationToken.None)).Result; var respFull = Task.Run(() => shelly1PM.GetStatus(CancellationToken.None)).Result;
if (respFull.IsSuccess) if (respFull.IsSuccess)
{ {
string serValFull = JsonConvert.SerializeObject(respFull.Value, Formatting.Indented); string serValFull = JsonConvert.SerializeObject(respFull.Value, Formatting.Indented);
@@ -132,11 +132,21 @@ namespace EgwProxy.Shelly.Test
} }
break; break;
case stepType.getSwitchStatus: case stepType.getSwitchStatus:
var respSwitch = Task.Run(() => shellyPro3.GetEmStatus(CancellationToken.None)).Result; var respEmDto = Task.Run(() => shellyPro3.GetEmStatus(CancellationToken.None, 0)).Result;
if (respSwitch.IsSuccess) if (respEmDto.IsSuccess)
{ {
string serValSwitch = JsonConvert.SerializeObject(respSwitch.Value, Formatting.Indented); string serValSwitch = JsonConvert.SerializeObject(respEmDto.Value, Formatting.Indented);
esitoStep = respSwitch.IsSuccess ? serValSwitch : "Errore in GetEmStatus"; 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; break;
default: default:
@@ -169,10 +179,10 @@ namespace EgwProxy.Shelly.Test
// registro ed eseguo chiamata in modalità sincrona // registro ed eseguo chiamata in modalità sincrona
sw.Restart(); sw.Restart();
var response = Task.Run(() => shellyClient.GetStatus(CancellationToken.None)).Result; var response = Task.Run(() => shellyClient.GetStatus(CancellationToken.None)).Result;
sw.Stop();
if (response.IsSuccess) if (response.IsSuccess)
{ {
string serVal = JsonConvert.SerializeObject(response.Value, Formatting.Indented); string serVal = JsonConvert.SerializeObject(response.Value, Formatting.Indented);
sw.Stop();
writeResult(response.IsSuccess, serVal); writeResult(response.IsSuccess, serVal);
} }
} }
@@ -197,10 +207,10 @@ namespace EgwProxy.Shelly.Test
// registro ed eseguo chiamata in modalità sincrona // registro ed eseguo chiamata in modalità sincrona
sw.Restart(); sw.Restart();
var response = Task.Run(() => shellyClient.GetStatus(CancellationToken.None)).Result; var response = Task.Run(() => shellyClient.GetStatus(CancellationToken.None)).Result;
sw.Stop();
if (response.IsSuccess) if (response.IsSuccess)
{ {
string serVal = JsonConvert.SerializeObject(response.Value, Formatting.Indented); string serVal = JsonConvert.SerializeObject(response.Value, Formatting.Indented);
sw.Stop();
writeResult(response.IsSuccess, serVal); writeResult(response.IsSuccess, serVal);
} }
} }
+1 -1
View File
@@ -10,7 +10,7 @@ namespace EgwProxy.Shelly.Clients
{ {
public class Shelly1PmClient : ShellyClientBase, IShelly1Pm public class Shelly1PmClient : ShellyClientBase, IShelly1Pm
{ {
public Shelly1PmClient(HttpClient httpClient, Shelly1PmOptions shellyOptions) : base(httpClient, shellyOptions) public Shelly1PmClient(HttpClient httpClient, ShellyOptions shellyOptions) : base(httpClient, shellyOptions)
{ {
} }
+15 -5
View File
@@ -14,7 +14,7 @@ namespace EgwProxy.Shelly.Clients
{ {
public class ShellyPro3EmClient : ShellyClientBase, IShellyPro3Em 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<ShellyGen2StatusDto>(requestMessage, cancellationToken, timeout); return await ExecuteRequestAsync<ShellyGen2StatusDto>(requestMessage, cancellationToken, timeout);
} }
public async Task<ShellyResult<EnergyDto>> GetEmStatus(CancellationToken cancellationToken, TimeSpan? timeout = null) public async Task<ShellyResult<EMDto>> 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); var requestMessage = new HttpRequestMessage(HttpMethod.Get, endpoint);
return await ExecuteRequestAsync<EnergyDto>(requestMessage, cancellationToken, timeout); return await ExecuteRequestAsync<EMDto>(requestMessage, cancellationToken, timeout);
}
public async Task<ShellyResult<EMDataDto>> 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<EMDataDto>(requestMessage, cancellationToken, timeout);
} }
#if false #if false
@@ -46,7 +53,10 @@ namespace EgwProxy.Shelly.Clients
var readAsStringAsync = await response.Content.ReadAsStringAsync(); var readAsStringAsync = await response.Content.ReadAsStringAsync();
var settings = new JsonSerializerSettings var settings = new JsonSerializerSettings
{ {
Converters = new List<JsonConverter> { new EnergyDtoConverter() } Converters = new List<JsonConverter> {
new EMDtoConverter(),
new EMDataDtoConverter()
}
}; };
var shelly1Status = JsonConvert.DeserializeObject<T>(readAsStringAsync, settings); var shelly1Status = JsonConvert.DeserializeObject<T>(readAsStringAsync, settings);
return ShellyResult<T>.Success(shelly1Status, readAsStringAsync); return ShellyResult<T>.Success(shelly1Status, readAsStringAsync);
@@ -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<EMDataDto>
{
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<List<string>>() ?? new List<string>()
};
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);
}
}
}
@@ -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<EMDto>
{
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<double?>() ?? 0,
TotalCurrent = (double)obj["total_current"],
TotalActivePower = (double)obj["total_act_power"],
TotalApparentPower = (double)obj["total_aprt_power"],
UserCalibratedPhase = obj["user_calibrated_phase"]?.ToObject<List<string>>() ?? new List<string>(),
Errors = obj["errors"]?.ToObject<List<string>>() ?? new List<string>()
};
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);
}
}
}
@@ -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<EnergyDto>
{
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<double?>() ?? 0,
TotalCurrent = (double)obj["total_current"],
TotalActivePower = (double)obj["total_act_power"],
TotalApparentPower = (double)obj["total_aprt_power"],
UserCalibratedPhase = obj["user_calibrated_phase"]?.ToObject<List<double>>() ?? new List<double>()
};
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");
}
}
}
+40
View File
@@ -0,0 +1,40 @@
using EgwProxy.Shelly.Converters;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace EgwProxy.Shelly.DTO.Gen2
{
/// <summary>
/// EnergyMeterData Info DTO (Total Counters)
/// </summary>
//[JsonConverter(typeof(EMDataDtoConverter))]
public class EMDataDto
{
public int Id { get; set; }
/// <summary>
/// Phase A data
/// </summary>
public EnergyDto TotalPhaseA { get; set; } = new EnergyDto();
/// <summary>
/// Phase B data
/// </summary>
public EnergyDto TotalPhaseB { get; set; } = new EnergyDto();
/// <summary>
/// Phase C data
/// </summary>
public EnergyDto TotalPhaseC { get; set; } = new EnergyDto();
/// <summary>
/// AllPhase data
/// </summary>
public EnergyDto TotalAll { get; set; } = new EnergyDto();
/// <summary>
/// Calibrazione fasi manuale
/// </summary>
[JsonProperty("errors")]
public List<string> Errors { get; set; } = new List<string>();
}
}
+65
View File
@@ -0,0 +1,65 @@
using EgwProxy.Shelly.Converters;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace EgwProxy.Shelly.DTO.Gen2
{
/// <summary>
/// EnergyMeter Info DTO (Realtime Data)
/// </summary>
//[JsonConverter(typeof(EMDtoConverter))]
public class EMDto
{
public int Id { get; set; }
/// <summary>
/// Phase A data
/// </summary>
public PhaseDataDto PhaseA { get; set; } = new PhaseDataDto();
/// <summary>
/// Phase B data
/// </summary>
public PhaseDataDto PhaseB { get; set; } = new PhaseDataDto();
/// <summary>
/// Phase C data
/// </summary>
public PhaseDataDto PhaseC { get; set; } = new PhaseDataDto();
/// <summary>
/// Corrente Neutro
/// </summary>
[JsonProperty("n_current")]
public double NeutralCurrent { get; set; } = 0;
/// <summary>
/// Corrente Totale
/// </summary>
[JsonProperty("total_current")]
public double TotalCurrent { get; set; } = 0;
/// <summary>
/// Corrente Totale Attiva
/// </summary>
[JsonProperty("total_act_power")]
public double TotalActivePower { get; set; } = 0;
/// <summary>
/// Corrente Totale Apparente
/// </summary>
[JsonProperty("total_aprt_power")]
public double TotalApparentPower { get; set; } = 0;
/// <summary>
/// Calibrazione fasi manuale
/// </summary>
[JsonProperty("user_calibrated_phase")]
public List<string> UserCalibratedPhase { get; set; } = new List<string>();
/// <summary>
/// Calibrazione fasi manuale
/// </summary>
[JsonProperty("errors")]
public List<string> Errors { get; set; } = new List<string>();
}
}
+10 -46
View File
@@ -1,57 +1,21 @@
using Newtonsoft.Json; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EgwProxy.Shelly.DTO.Gen2 namespace EgwProxy.Shelly.DTO.Gen2
{ {
/// <summary>
/// Energy Info
/// </summary>
public class EnergyDto public class EnergyDto
{ {
/// <summary>
public int Id { get; set; } /// Energia Attiva (Wh)
/// </summary>
public double ActEnergy { get; set; } = 0;
/// <summary> /// <summary>
/// Phase A data /// Energia Ritornata (Wh)
/// </summary> /// </summary>
public PhaseDataDto PhaseA { get; set; } = new PhaseDataDto(); public double RetEnergy { get; set; } = 0;
/// <summary>
/// Phase B data
/// </summary>
public PhaseDataDto PhaseB { get; set; } = new PhaseDataDto();
/// <summary>
/// Phase C data
/// </summary>
public PhaseDataDto PhaseC { get; set; } = new PhaseDataDto();
/// <summary>
/// Corrente Neutro
/// </summary>
[JsonProperty("n_current")]
public double NeutralCurrent { get; set; } = 0;
/// <summary>
/// Corrente Totale
/// </summary>
[JsonProperty("total_current")]
public double TotalCurrent { get; set; } = 0;
/// <summary>
/// Corrente Totale Attiva
/// </summary>
[JsonProperty("total_act_power")]
public double TotalActivePower { get; set; } = 0;
/// <summary>
/// Corrente Totale Apparente
/// </summary>
[JsonProperty("total_aprt_power")]
public double TotalApparentPower { get; set; } = 0;
/// <summary>
/// Calibrazione fasi manuale
/// </summary>
[JsonProperty("user_calibrated_phase")]
public List<double> UserCalibratedPhase { get; set; } = new List<double>();
} }
} }
+1 -1
View File
@@ -26,7 +26,7 @@ namespace EgwProxy.Shelly.DTO
/// EnergyMonitor 0 data /// EnergyMonitor 0 data
/// </summary> /// </summary>
[JsonProperty("em:0")] [JsonProperty("em:0")]
public EnergyDto EmData { get; set; } public EMDto EmData { get; set; }
/// <summary> /// <summary>
/// MQTT queue state /// MQTT queue state
+5 -2
View File
@@ -88,9 +88,12 @@
<Compile Include="Clients\ShellyPro3EmClient.cs" /> <Compile Include="Clients\ShellyPro3EmClient.cs" />
<Compile Include="Clients\Shelly1PmClient.cs" /> <Compile Include="Clients\Shelly1PmClient.cs" />
<Compile Include="Clients\ShellyClientBase.cs" /> <Compile Include="Clients\ShellyClientBase.cs" />
<Compile Include="Converters\EnergyDtoConverter.cs" /> <Compile Include="Converters\EMDataDtoConverter.cs" />
<Compile Include="Converters\EMDtoConverter.cs" />
<Compile Include="DTO\BaseServiceDto.cs" /> <Compile Include="DTO\BaseServiceDto.cs" />
<Compile Include="DTO\CloudDto.cs" /> <Compile Include="DTO\CloudDto.cs" />
<Compile Include="DTO\Gen2\EMDataDto.cs" />
<Compile Include="DTO\Gen2\EMDto.cs" />
<Compile Include="DTO\Gen2\EnergyDto.cs" /> <Compile Include="DTO\Gen2\EnergyDto.cs" />
<Compile Include="DTO\Gen2\PhaseDataDto.cs" /> <Compile Include="DTO\Gen2\PhaseDataDto.cs" />
<Compile Include="DTO\Shelly1PmStatusDto.cs" /> <Compile Include="DTO\Shelly1PmStatusDto.cs" />
@@ -106,7 +109,7 @@
<Compile Include="Options\IShellyAuthOptions.cs" /> <Compile Include="Options\IShellyAuthOptions.cs" />
<Compile Include="Options\IShellyCommonOptions.cs" /> <Compile Include="Options\IShellyCommonOptions.cs" />
<Compile Include="Options\Shelly1Options.cs" /> <Compile Include="Options\Shelly1Options.cs" />
<Compile Include="Options\Shelly1PmOptions.cs" /> <Compile Include="Options\ShellyOptions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ShellyResult.cs" /> <Compile Include="ShellyResult.cs" />
</ItemGroup> </ItemGroup>
@@ -6,14 +6,14 @@ using System.Threading.Tasks;
namespace EgwProxy.Shelly.Options namespace EgwProxy.Shelly.Options
{ {
public class Shelly1PmOptions : IShellyCommonOptions public class ShellyOptions : IShellyCommonOptions
{ {
public Uri ServerUri { get; set; } public Uri ServerUri { get; set; }
public TimeSpan? DefaultTimeout { get; set; } public TimeSpan? DefaultTimeout { get; set; }
public string UserName { get; set; } public string UserName { get; set; }
public string Password { get; set; } public string Password { get; set; }
public Shelly1PmOptions() public ShellyOptions()
{ {
DefaultTimeout = null; DefaultTimeout = null;
} }