Removed complexity from program.cs, created classes for rabbitmq management and middleware communication
This commit is contained in:
parent
907f8b66c6
commit
a871693ba8
|
@ -0,0 +1,9 @@
|
|||
namespace InnovEnergy.App.SaliMax.DataTypes;
|
||||
|
||||
public class AlarmOrWarning
|
||||
{
|
||||
public String? Date { get; set; }
|
||||
public String? Time { get; set; }
|
||||
public String? Description { get; set; }
|
||||
public String? CreatedBy { get; set; }
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
using InnovEnergy.App.SaliMax.SystemConfig;
|
||||
|
||||
namespace InnovEnergy.App.SaliMax.MiddlewareClasses;
|
||||
namespace InnovEnergy.App.SaliMax.DataTypes;
|
||||
|
||||
public class Configuration
|
||||
{
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
using InnovEnergy.App.SaliMax.Ess;
|
||||
|
||||
namespace InnovEnergy.App.SaliMax.MiddlewareClasses;
|
||||
namespace InnovEnergy.App.SaliMax.DataTypes;
|
||||
|
||||
public class StatusMessage
|
||||
{
|
|
@ -1,9 +0,0 @@
|
|||
namespace InnovEnergy.App.SaliMax.MiddlewareClasses;
|
||||
|
||||
public class AlarmOrWarning
|
||||
{
|
||||
public String Date { get; set; }
|
||||
public String Time { get; set; }
|
||||
public String Description { get; set; }
|
||||
public String CreatedBy { get; set; }
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using InnovEnergy.App.SaliMax.DataTypes;
|
||||
using InnovEnergy.App.SaliMax.Ess;
|
||||
namespace InnovEnergy.App.SaliMax.MiddlewareClasses;
|
||||
|
||||
public static class MiddlewareAgent
|
||||
{
|
||||
public static UdpClient UdpListener = null!;
|
||||
private static IPAddress? _controllerIpAddress;
|
||||
|
||||
public static void InitializeCommunicationToMiddleware()
|
||||
{
|
||||
_controllerIpAddress = FindVpnIp();
|
||||
if (Equals(IPAddress.None, _controllerIpAddress))
|
||||
{
|
||||
Console.WriteLine("There is no VPN interface, exiting...");
|
||||
}
|
||||
|
||||
const Int32 udpPort = 9000;
|
||||
var endPoint = new IPEndPoint(_controllerIpAddress, udpPort);
|
||||
|
||||
UdpListener = new UdpClient();
|
||||
UdpListener.Client.Blocking = false;
|
||||
UdpListener.Client.Bind(endPoint);
|
||||
}
|
||||
|
||||
private static IPAddress FindVpnIp()
|
||||
{
|
||||
const String interfaceName = "innovenergy";
|
||||
|
||||
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
|
||||
|
||||
foreach (var networkInterface in networkInterfaces)
|
||||
{
|
||||
if (networkInterface.Name == interfaceName)
|
||||
{
|
||||
var ipProps = networkInterface.GetIPProperties();
|
||||
var uniCastIPs = ipProps.UnicastAddresses;
|
||||
var controllerIpAddress = uniCastIPs[0].Address;
|
||||
|
||||
Console.WriteLine("VPN IP is: "+ uniCastIPs[0].Address);
|
||||
return controllerIpAddress;
|
||||
}
|
||||
}
|
||||
|
||||
return IPAddress.None;
|
||||
}
|
||||
|
||||
public static Configuration? SetConfigurationFile()
|
||||
{
|
||||
if (UdpListener.Available > 0)
|
||||
{
|
||||
IPEndPoint? serverEndpoint = null;
|
||||
|
||||
var replyMessage = "ACK";
|
||||
var replyData = Encoding.UTF8.GetBytes(replyMessage);
|
||||
|
||||
var udpMessage = UdpListener.Receive(ref serverEndpoint);
|
||||
var message = Encoding.UTF8.GetString(udpMessage);
|
||||
|
||||
Configuration? config = JsonSerializer.Deserialize<Configuration>(message);
|
||||
|
||||
Console.WriteLine($"Received a configuration message: GridSetPoint is " + config.GridSetPoint + ", MinimumSoC is " + config.MinimumSoC + " and ForceCalibrationCharge is " + config.ForceCalibrationCharge);
|
||||
|
||||
// Send the reply to the sender's endpoint
|
||||
UdpListener.Send(replyData, replyData.Length, serverEndpoint);
|
||||
Console.WriteLine($"Replied to {serverEndpoint}: {replyMessage}");
|
||||
return config;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using InnovEnergy.App.SaliMax.DataTypes;
|
||||
using RabbitMQ.Client;
|
||||
|
||||
namespace InnovEnergy.App.SaliMax.MiddlewareClasses;
|
||||
|
||||
public static class RabbitMqManager
|
||||
{
|
||||
public static ConnectionFactory? Factory ;
|
||||
public static IConnection ? Connection;
|
||||
public static IModel? Channel;
|
||||
|
||||
public static Boolean SubscribeToQueue(StatusMessage currentSalimaxState, String? s3Bucket,String VpnServerIp)
|
||||
{
|
||||
try
|
||||
{
|
||||
//_factory = new ConnectionFactory { HostName = VpnServerIp };
|
||||
|
||||
Factory = new ConnectionFactory
|
||||
{
|
||||
HostName = VpnServerIp,
|
||||
Port = 5672,
|
||||
VirtualHost = "/",
|
||||
UserName = "producer",
|
||||
Password = "b187ceaddb54d5485063ddc1d41af66f",
|
||||
|
||||
};
|
||||
|
||||
Connection = Factory.CreateConnection();
|
||||
Channel = Connection.CreateModel();
|
||||
Channel.QueueDeclare(queue: "statusQueue", durable: true, exclusive: false, autoDelete: false, arguments: null);
|
||||
|
||||
Console.WriteLine("The controller sends its status to the middleware for the first time");
|
||||
if (s3Bucket != null) InformMiddleware(currentSalimaxState);
|
||||
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("An error occurred while connecting to the RabbitMQ queue: " + ex.Message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void InformMiddleware(StatusMessage status)
|
||||
{
|
||||
var message = JsonSerializer.Serialize(status);
|
||||
var body = Encoding.UTF8.GetBytes(message);
|
||||
|
||||
Channel.BasicPublish(exchange: string.Empty,
|
||||
routingKey: "statusQueue",
|
||||
basicProperties: null,
|
||||
body: body);
|
||||
|
||||
Console.WriteLine($"Producer sent message: {message}");
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -4,7 +4,6 @@ using System.Net.NetworkInformation;
|
|||
using System.Net.Sockets;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Threading.Tasks;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using Flurl.Http;
|
||||
using InnovEnergy.App.SaliMax.Devices;
|
||||
|
@ -26,7 +25,7 @@ using InnovEnergy.Lib.Protocols.Modbus.Channels;
|
|||
using InnovEnergy.Lib.Units;
|
||||
using InnovEnergy.Lib.Utils;
|
||||
using System.Text.Json;
|
||||
using RabbitMQ.Client;
|
||||
using InnovEnergy.App.SaliMax.DataTypes;
|
||||
using static System.Double;
|
||||
using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes.SystemConfig;
|
||||
using DeviceState = InnovEnergy.App.SaliMax.Devices.DeviceState;
|
||||
|
@ -52,14 +51,7 @@ internal static class Program
|
|||
private static readonly Channel RelaysChannel ;
|
||||
private static readonly Channel BatteriesChannel ;
|
||||
|
||||
//private const String VpnServerIp = "194.182.190.208";
|
||||
private const String VpnServerIp = "10.2.0.11";
|
||||
|
||||
private static IPAddress? _controllerIpAddress;
|
||||
private static UdpClient _udpListener = null!;
|
||||
private static ConnectionFactory? _factory ;
|
||||
private static IConnection ? _connection;
|
||||
private static IModel? _channel;
|
||||
private static Boolean _subscribedToQueue = false;
|
||||
private static Boolean _subscribeToQueueForTheFirstTime = false;
|
||||
private static SalimaxAlarmState _prevSalimaxState = SalimaxAlarmState.Green;
|
||||
|
@ -95,7 +87,7 @@ internal static class Program
|
|||
{
|
||||
//Do not await
|
||||
HourlyDataAggregationManager();
|
||||
InitializeCommunicationToMiddleware();
|
||||
MiddlewareAgent.InitializeCommunicationToMiddleware();
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
|
@ -109,21 +101,7 @@ internal static class Program
|
|||
}
|
||||
}
|
||||
|
||||
private static void InitializeCommunicationToMiddleware()
|
||||
{
|
||||
_controllerIpAddress = FindVpnIp();
|
||||
if (Equals(IPAddress.None, _controllerIpAddress))
|
||||
{
|
||||
Console.WriteLine("There is no VPN interface, exiting...");
|
||||
}
|
||||
|
||||
const Int32 udpPort = 9000;
|
||||
var endPoint = new IPEndPoint(_controllerIpAddress, udpPort);
|
||||
|
||||
_udpListener = new UdpClient();
|
||||
_udpListener.Client.Blocking = false;
|
||||
_udpListener.Client.Bind(endPoint);
|
||||
}
|
||||
|
||||
private static async Task Run()
|
||||
{
|
||||
|
@ -263,7 +241,7 @@ internal static class Program
|
|||
// ReSharper disable once FunctionNeverReturns
|
||||
}
|
||||
|
||||
private static void SendSalimaxStateAlarm(StatusMessage currentSalimaxState, StatusRecord record)
|
||||
public static void SendSalimaxStateAlarm(StatusMessage currentSalimaxState, StatusRecord record)
|
||||
{
|
||||
var s3Bucket = Config.Load().S3?.Bucket;
|
||||
|
||||
|
@ -274,14 +252,14 @@ internal static class Program
|
|||
if (_subscribeToQueueForTheFirstTime==false)
|
||||
{
|
||||
_subscribeToQueueForTheFirstTime = true;
|
||||
SubscribeToQueue(currentSalimaxState, s3Bucket);
|
||||
_subscribedToQueue = RabbitMqManager.SubscribeToQueue(currentSalimaxState, s3Bucket, VpnServerIp);
|
||||
}
|
||||
//If already subscribed to the queue and the status has been changed, update the queue
|
||||
if (_subscribedToQueue && currentSalimaxState.Status != _prevSalimaxState)
|
||||
{
|
||||
_prevSalimaxState = currentSalimaxState.Status;
|
||||
if (s3Bucket != null)
|
||||
InformMiddleware(currentSalimaxState);
|
||||
RabbitMqManager.InformMiddleware(currentSalimaxState);
|
||||
}
|
||||
else if (_subscribedToQueue && _heartBitInterval>=15)
|
||||
{
|
||||
|
@ -291,97 +269,16 @@ internal static class Program
|
|||
currentSalimaxState.Type = MessageType.Heartbit;
|
||||
|
||||
if (s3Bucket != null)
|
||||
InformMiddleware(currentSalimaxState);
|
||||
RabbitMqManager.InformMiddleware(currentSalimaxState);
|
||||
}
|
||||
|
||||
//If there is an available message from the RabbitMQ Broker, apply the configuration file
|
||||
if (_udpListener.Available > 0)
|
||||
Configuration? config = MiddlewareAgent.SetConfigurationFile();
|
||||
if (config != null)
|
||||
{
|
||||
IPEndPoint? serverEndpoint = null;
|
||||
|
||||
var replyMessage = "ACK";
|
||||
var replyData = Encoding.UTF8.GetBytes(replyMessage);
|
||||
|
||||
var udpMessage = _udpListener.Receive(ref serverEndpoint);
|
||||
var message = Encoding.UTF8.GetString(udpMessage);
|
||||
|
||||
Configuration config = JsonSerializer.Deserialize<Configuration>(message);
|
||||
|
||||
Console.WriteLine($"Received a configuration message: GridSetPoint is "+config.GridSetPoint +", MinimumSoC is "+config.MinimumSoC+ " and ForceCalibrationCharge is "+config.ForceCalibrationCharge);
|
||||
|
||||
// Send the reply to the sender's endpoint
|
||||
_udpListener.Send(replyData, replyData.Length, serverEndpoint);
|
||||
Console.WriteLine($"Replied to {serverEndpoint}: {replyMessage}");
|
||||
|
||||
record.ApplyConfigFile(config);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static void SubscribeToQueue(StatusMessage currentSalimaxState, String? s3Bucket)
|
||||
{
|
||||
try
|
||||
{
|
||||
//_factory = new ConnectionFactory { HostName = VpnServerIp };
|
||||
|
||||
_factory = new ConnectionFactory
|
||||
{
|
||||
HostName = VpnServerIp,
|
||||
Port = 5672,
|
||||
VirtualHost = "/",
|
||||
UserName = "producer",
|
||||
Password = "b187ceaddb54d5485063ddc1d41af66f",
|
||||
|
||||
};
|
||||
|
||||
_connection = _factory.CreateConnection();
|
||||
_channel = _connection.CreateModel();
|
||||
_channel.QueueDeclare(queue: "statusQueue", durable: true, exclusive: false, autoDelete: false, arguments: null);
|
||||
|
||||
Console.WriteLine("The controller sends its status to the middleware for the first time");
|
||||
if (s3Bucket != null) InformMiddleware(currentSalimaxState);
|
||||
|
||||
_subscribedToQueue = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("An error occurred while connecting to the RabbitMQ queue: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static IPAddress FindVpnIp()
|
||||
{
|
||||
const String interfaceName = "innovenergy";
|
||||
|
||||
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
|
||||
|
||||
foreach (var networkInterface in networkInterfaces)
|
||||
{
|
||||
if (networkInterface.Name == interfaceName)
|
||||
{
|
||||
var ipProps = networkInterface.GetIPProperties();
|
||||
var uniCastIPs = ipProps.UnicastAddresses;
|
||||
var controllerIpAddress = uniCastIPs[0].Address;
|
||||
|
||||
Console.WriteLine("VPN IP is: "+ uniCastIPs[0].Address);
|
||||
return controllerIpAddress;
|
||||
}
|
||||
}
|
||||
|
||||
return IPAddress.None;
|
||||
}
|
||||
|
||||
private static void InformMiddleware(StatusMessage status)
|
||||
{
|
||||
var message = JsonSerializer.Serialize(status);
|
||||
var body = Encoding.UTF8.GetBytes(message);
|
||||
|
||||
_channel.BasicPublish(exchange: string.Empty,
|
||||
routingKey: "statusQueue",
|
||||
basicProperties: null,
|
||||
body: body);
|
||||
|
||||
Console.WriteLine($"Producer sent message: {message}");
|
||||
}
|
||||
|
||||
private static StatusMessage GetSalimaxStateAlarm(StatusRecord record)
|
||||
|
@ -774,8 +671,12 @@ internal static class Program
|
|||
//Create a new file to folder "Hourly Aggregated Data and push it to S3"
|
||||
Console.WriteLine("-----------------------------------------------------------------------------------------------------------------");
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Custom method to check if a string is numeric
|
||||
private static bool IsSoc(string value)
|
||||
{
|
||||
|
@ -792,7 +693,7 @@ internal static class Program
|
|||
return value == "/Battery/Dc/Power";
|
||||
}
|
||||
|
||||
private static void ApplyConfigFile(this StatusRecord status, Configuration config)
|
||||
private static void ApplyConfigFile(this StatusRecord status, Configuration? config)
|
||||
{
|
||||
status.Config.MinSoc = config.MinimumSoC;
|
||||
status.Config.GridSetPoint = config.GridSetPoint * 1000; // converted from kW to W
|
||||
|
|
Loading…
Reference in New Issue