Files
adas-core/adas-core.module.Relays/Devices/KMTronicV2Relay.cs
T

187 lines
5.8 KiB
C#

using System.Net;
using System.Xml;
using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;
using adas_core.module.Relays.Models;
using adas_core.module.Relays.Utils;
using Serilog;
namespace adas_core.module.Relays.Devices;
public class KmTronicV2Relay : RelayDevice
{
public KmTronicV2Relay(Relay relay, RelaySettings relaySettings) : base(relay, relaySettings)
{
CheckDevice();
}
public sealed override bool CheckDevice()
{
CheckStatus();
var result = GetStatusRelay(1);
return result != RelayEnum.Status.Unknown;
}
public override void CheckStatus()
{
try
{
var httpResponse = SendRequest("status.xml", HttpMethod.Get);
if (httpResponse.StatusCode.Equals(HttpStatusCode.OK))
{
var responseContent = httpResponse.Content;
var responseString = responseContent.ReadAsStringAsync().Result;
if (!string.IsNullOrEmpty(responseString))
{
var response = new XmlDocument();
response.LoadXml(responseString);
foreach (XmlNode node in response.SelectNodes("//response")!)
foreach (XmlNode childNode in node.ChildNodes)
{
if (!childNode.Name.StartsWith("relay") || string.IsNullOrEmpty(childNode.InnerText)) continue;
var id = int.Parse(childNode.Name[5..]);
if (id <= 0 || id > Relay.Total) continue;
var value = int.Parse(childNode.InnerText);
var relayStatus = value.Equals(0) ? RelayEnum.Status.Off :
value.Equals(1) ? RelayEnum.Status.On : RelayEnum.Status.Unknown;
Tuple.Create(Relay.Ip, Relay.Port, id);
SetStatusRelay(id, relayStatus);
}
}
Log.Debug(responseContent.ReadAsStringAsync().Result);
}
else
{
Log.Debug("Status code = " + httpResponse.StatusCode);
}
}
catch (Exception ex)
{
Log.Error(ex.ToString());
Enumerable.Range(1, Relay.Total).ToList().ForEach(outletId =>
{
SetStatusRelay(outletId, RelayEnum.Status.Unknown);
});
}
}
public override bool GetStatusRelay()
{
return GetStatusRelay(1) == RelayEnum.Status.On;
}
public override Task<bool> GetStatusRelayAsync()
{
var result = GetStatusRelay();
return Task.FromResult(result);
}
public override void PowerOnRelay(int outletId)
{
PowerRelay(outletId, RelayEnum.Status.On);
}
public override void PowerOffRelay(int outletId)
{
PowerRelay(outletId, RelayEnum.Status.Off);
}
private Uri GetUri(string path, string? query = null)
{
var uriBuilder = new UriBuilder
{ Scheme = "http", Host = Relay.Ip, Port = Relay.Port, Path = path };
if (!string.IsNullOrEmpty(query)) uriBuilder.Query = query;
return uriBuilder.Uri;
}
private HttpRequestMessage GetRequest(string path, HttpMethod method, string? query = null)
{
var uri = GetUri(path, query);
var request = new HttpRequestMessage
{
RequestUri = uri,
Method = method
};
if (!string.IsNullOrEmpty(Relay.Username) && !string.IsNullOrEmpty(Relay.Password))
HttpUtils.AddBasicAuth(Relay.Username, Relay.Password, request.Headers);
return request;
}
private HttpResponseMessage SendRequest(string path, HttpMethod method, string? query = null)
{
using var client = new HttpClient();
client.Timeout = TimeSpan.FromSeconds(15);
try
{
return client.Send(GetRequest(path, method, query));
}
catch (Exception e)
{
Log.Warning("Error sending request to kmtronic ip {IP} port {Port}: {Message}", Relay.Ip,
Relay.Port, e.Message);
return new HttpResponseMessage(HttpStatusCode.Gone);
}
}
private void PowerRelay(int outletId, RelayEnum.Status toState, bool checkStatus = true)
{
if (Relay.Mode == RelayEnum.Mode.OpenedOffClosedOn)
toState = toState == RelayEnum.Status.Off ? RelayEnum.Status.On : RelayEnum.Status.Off;
var status = GetStatusRelay(outletId);
if (status == toState) return;
//No entiendo esto así, siempre enciende/apaga el mismo uriBuilder.Query = $"relay={outlet.outlet}";
//me quedo con el nombre y solo con el número del rele que es la llamada que el hace realmente desde la web
//No uso una regex porque es mucho más lento
try
{
SendRequest("relays.cgi", HttpMethod.Post, $"relay={outletId}");
}
catch (Exception ex)
{
Log.Debug(ex.Message);
}
finally
{
if (checkStatus) CheckStatus();
}
}
public override void PowerOnAll()
{
PowerAll(RelayEnum.Status.On);
}
public override void PowerOffAll()
{
PowerAll(RelayEnum.Status.Off);
}
private void PowerAll(RelayEnum.Status toState)
{
Enumerable.Range(1, Relay.Total).ToList().ForEach(outletId => { PowerRelay(outletId, toState, false); });
CheckStatus();
}
public override void Reboot()
{
PowerOffAll();
if (Relay.RebootDelay is > 0) Thread.Sleep(Relay.RebootDelay!.Value);
PowerOnAll();
}
public override void RebootOutlet(int outletId)
{
PowerOffRelay(outletId);
Thread.Sleep(30000);
PowerOnRelay(outletId);
}
}