dodana podpora za temperaturni senzor addon, pm1
dodan nlog pinganje devicov
This commit is contained in:
30
ShellyExporter/Classes/Pm1GetStatusResponse.cs
Normal file
30
ShellyExporter/Classes/Pm1GetStatusResponse.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace ShellyExporter.Classes
|
||||||
|
{
|
||||||
|
internal class Pm1GetStatusResponse
|
||||||
|
{
|
||||||
|
public class Energy
|
||||||
|
{
|
||||||
|
[JsonProperty("total")]
|
||||||
|
internal string? Total { get; set; }
|
||||||
|
[JsonProperty("minute_ts")]
|
||||||
|
internal string? MinuteTimeStamp { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonProperty("id")]
|
||||||
|
internal string? Id { get; set; }
|
||||||
|
[JsonProperty("voltage")]
|
||||||
|
internal string? Voltage { get; set; }
|
||||||
|
[JsonProperty("current")]
|
||||||
|
internal string? Current { get; set; }
|
||||||
|
[JsonProperty("apower")]
|
||||||
|
internal string? Apower { get; set; }
|
||||||
|
[JsonProperty("freq")]
|
||||||
|
internal string? Freq { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("aenergy")]
|
||||||
|
internal Energy? Aenergy { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
16
ShellyExporter/Classes/TemperatureGetStatusResponse.cs
Normal file
16
ShellyExporter/Classes/TemperatureGetStatusResponse.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace ShellyExporter.Classes
|
||||||
|
{
|
||||||
|
internal class TemperatureGetStatusResponse
|
||||||
|
{
|
||||||
|
[JsonProperty("id")]
|
||||||
|
internal string? Id { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("tC")]
|
||||||
|
internal string? TemperatureC { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("tF")]
|
||||||
|
internal string? TemperatureF { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,22 +1,30 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Net.NetworkInformation;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using NLog;
|
||||||
|
|
||||||
namespace ShellyExporter
|
namespace ShellyExporter
|
||||||
{
|
{
|
||||||
public class Metrics
|
public class Metrics
|
||||||
{
|
{
|
||||||
|
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
public enum Type
|
public enum Type
|
||||||
{
|
{
|
||||||
PlugS = 1,
|
PlugS = 1,
|
||||||
Em3 = 2
|
Em3 = 2,
|
||||||
|
TemperatureAddon = 3,
|
||||||
|
Pm1 = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Version
|
public enum Version
|
||||||
{
|
{
|
||||||
Gen1 = 1,
|
Gen1 = 1,
|
||||||
Gen2 = 2
|
Gen2 = 2,
|
||||||
|
Gen3 = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Data
|
public class Data
|
||||||
{
|
{
|
||||||
public string? Power { get; set; }
|
public string? Power { get; set; }
|
||||||
@@ -54,41 +62,97 @@ namespace ShellyExporter
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<StringBuilder> Get(string path, string name, Version shellyVersion, Type type)
|
public static async Task<StringBuilder> Get(string ip, string name, Version shellyVersion, Type type, string id)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
var online = true;
|
||||||
Data data;
|
var error = false;
|
||||||
switch (type)
|
try
|
||||||
{
|
{
|
||||||
case Type.PlugS:
|
using var pinger = new Ping();
|
||||||
switch (shellyVersion)
|
var reply = pinger.Send(ip, TimeSpan.FromSeconds(2), null, null);
|
||||||
{
|
if (reply.Status != IPStatus.Success)
|
||||||
case Version.Gen1:
|
{
|
||||||
data = await GetPlugSGen1(path);
|
Logger.Error($"PingDevice:Status {reply.Status}");
|
||||||
break;
|
online = false;
|
||||||
case Version.Gen2:
|
}
|
||||||
data = await GetPlugSGen2(path);
|
}
|
||||||
break;
|
catch (PingException e)
|
||||||
default:
|
{
|
||||||
throw new ArgumentOutOfRangeException(nameof(shellyVersion), shellyVersion, null);
|
Logger.Error(e, "PingDevice");
|
||||||
}
|
online = false;
|
||||||
break;
|
error = true;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var path = $"http://{ip}";
|
||||||
|
|
||||||
|
Data data = null;
|
||||||
|
if (online)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
case Type.TemperatureAddon:
|
||||||
|
switch (shellyVersion)
|
||||||
|
{
|
||||||
|
case Version.Gen2:
|
||||||
|
data = await GetTemperatureAddonGen2(path, id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Type.Pm1:
|
||||||
|
switch (shellyVersion)
|
||||||
|
{
|
||||||
|
case Version.Gen3:
|
||||||
|
data = await GetPm1Gen3(path);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(type), type, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.Error(e, "GetDataFromDevice");
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine($"device_online{{item=\"{name}\"}} {(online ? 1 : 0)}");
|
||||||
|
sb.AppendLine($"device_error_retrieving_data{{item=\"{name}\"}} {(error ? 1 : 0)}");
|
||||||
|
if (!online || error)
|
||||||
|
return sb;
|
||||||
|
|
||||||
|
//Prestavljeno na sestevek vseh faz
|
||||||
if (data.Power != null)
|
if (data.Power != null)
|
||||||
sb.AppendLine($"meters_power_wats{{item=\"{name}\"}} {data.Power}");
|
sb.AppendLine($"meters_power_wats{{item=\"{name}\"}} {data.Power}");
|
||||||
if (data.Overpower != null)
|
if (data.Overpower != null)
|
||||||
@@ -151,6 +215,18 @@ namespace ShellyExporter
|
|||||||
if (data.Emeters3TotalReturned != null)
|
if (data.Emeters3TotalReturned != null)
|
||||||
sb.AppendLine($"emeters_3_total_returned{{item=\"{name}\"}} " + data.Emeters3TotalReturned);
|
sb.AppendLine($"emeters_3_total_returned{{item=\"{name}\"}} " + data.Emeters3TotalReturned);
|
||||||
|
|
||||||
|
//Ce gre za 3PM
|
||||||
|
if (data.Power != null
|
||||||
|
&& data is { Emeters1Power: not null, Emeters2Power: not null, Emeters3Power: not null })
|
||||||
|
{
|
||||||
|
var emetersPowerTotal = 0d;
|
||||||
|
double.TryParse(data.Emeters1Power, CultureInfo.InvariantCulture, out var emeters1Power);
|
||||||
|
double.TryParse(data.Emeters2Power, CultureInfo.InvariantCulture, out var emeters2Power);
|
||||||
|
double.TryParse(data.Emeters3Power, CultureInfo.InvariantCulture, out var emeters3Power);
|
||||||
|
|
||||||
|
sb.AppendLine($"meters_power_wats{{item=\"{name}\"}} {(emeters1Power + emeters2Power + emeters3Power)}");
|
||||||
|
}
|
||||||
|
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,5 +345,54 @@ namespace ShellyExporter
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async Task<Data> GetTemperatureAddonGen2(string path, string id)
|
||||||
|
{
|
||||||
|
var data = new Data();
|
||||||
|
var client = new HttpClient();
|
||||||
|
var response = await client.GetStringAsync(path + $"/rpc/Temperature.GetStatus?id={id}");
|
||||||
|
|
||||||
|
var responseObject = JsonConvert.DeserializeObject<Classes.TemperatureGetStatusResponse>(response);
|
||||||
|
|
||||||
|
if (responseObject == null)
|
||||||
|
return data;
|
||||||
|
|
||||||
|
if (responseObject.TemperatureC != null)
|
||||||
|
data.Temperature = responseObject.TemperatureC;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<Data> GetPm1Gen3(string path)
|
||||||
|
{
|
||||||
|
var data = new Data();
|
||||||
|
var client = new HttpClient();
|
||||||
|
var response = await client.GetStringAsync(path + "/rpc/PM1.GetStatus?id=0");
|
||||||
|
|
||||||
|
var responseObject = JsonConvert.DeserializeObject<Classes.Pm1GetStatusResponse>(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.MinuteTimeStamp!= null)
|
||||||
|
data.Timestamp = responseObject.Aenergy.MinuteTimeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc.RazorPages;
|
|||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using ShellyExporter;
|
using ShellyExporter;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
using NLog.Web;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
@@ -19,6 +20,12 @@ if (!builder.Environment.IsDevelopment())
|
|||||||
builder.WebHost.UseUrls(builder.Configuration["Kst:Url"]);
|
builder.WebHost.UseUrls(builder.Configuration["Kst:Url"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Nlog
|
||||||
|
builder.Logging.ClearProviders();
|
||||||
|
builder.Logging.SetMinimumLevel(LogLevel.Trace);
|
||||||
|
builder.Host.UseNLog();
|
||||||
|
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
@@ -39,10 +46,15 @@ app.Map("/metrics", () =>
|
|||||||
|
|
||||||
foreach (var host in builder.Configuration.GetSection("Hosts").GetChildren())
|
foreach (var host in builder.Configuration.GetSection("Hosts").GetChildren())
|
||||||
{
|
{
|
||||||
sb.Append(Metrics.Get($"http://{host["ip"]}",
|
var id = "0";
|
||||||
|
if (host["id"] != "")
|
||||||
|
id = host["id"];
|
||||||
|
|
||||||
|
sb.Append(Metrics.Get(host["ip"],
|
||||||
host.Path.Replace("Hosts:", ""),
|
host.Path.Replace("Hosts:", ""),
|
||||||
(Metrics.Version)Convert.ToInt16(host["version"]),
|
(Metrics.Version)Convert.ToInt16(host["version"]),
|
||||||
(Metrics.Type)Convert.ToInt16(host["type"])).Result);
|
(Metrics.Type)Convert.ToInt16(host["type"]),
|
||||||
|
id).Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
|
|||||||
@@ -10,9 +10,11 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" />
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
<PackageReference Include="NLog" Version="5.3.4" />
|
||||||
|
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.15" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -24,6 +24,23 @@
|
|||||||
"ip": "192.168.1.64",
|
"ip": "192.168.1.64",
|
||||||
"type": 2,
|
"type": 2,
|
||||||
"version": 1
|
"version": 1
|
||||||
|
},
|
||||||
|
"temperatura-zunaj": {
|
||||||
|
"ip": "192.168.1.75",
|
||||||
|
"type": 3,
|
||||||
|
"version": 2,
|
||||||
|
"id": "100"
|
||||||
|
},
|
||||||
|
"temperatura-notraj": {
|
||||||
|
"ip": "192.168.1.75",
|
||||||
|
"type": 3,
|
||||||
|
"version": 2,
|
||||||
|
"id": "101"
|
||||||
|
},
|
||||||
|
"tv-dnevna": {
|
||||||
|
"ip": "192.168.1.67",
|
||||||
|
"type": 4,
|
||||||
|
"version": 3
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
21
ShellyExporter/nlog.config
Normal file
21
ShellyExporter/nlog.config
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
|
||||||
|
<extensions>
|
||||||
|
<add assembly="NLog.Web.AspNetCore"/>
|
||||||
|
</extensions>
|
||||||
|
|
||||||
|
|
||||||
|
<targets>
|
||||||
|
<target name="logFile" xsi:type="File"
|
||||||
|
layout="${level} ${date:format=dd.MM.yyyy HH\:mm\:ss} ${logger} ${message} ${exception:format=ToString}"
|
||||||
|
fileName="ShellyExporter.log" />
|
||||||
|
<target xsi:type="Console" name="console" layout="${longdate} ${uppercase:${level}} ${message}" />
|
||||||
|
</targets>
|
||||||
|
|
||||||
|
<rules>
|
||||||
|
<logger name="*" minlevel="Warn" writeTo="logFile" />
|
||||||
|
<logger name="*" minlevel="Warn" writeTo="console" />
|
||||||
|
</rules>
|
||||||
|
|
||||||
|
</nlog>
|
||||||
Reference in New Issue
Block a user