Removed complexity from program.cs, created classes for rabbitmq management and middleware communication

This commit is contained in:
Noe 2023-12-13 11:12:43 +01:00
parent 907f8b66c6
commit a871693ba8
7 changed files with 166 additions and 127 deletions

View File

@ -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; }
}

View File

@ -1,6 +1,6 @@
using InnovEnergy.App.SaliMax.SystemConfig; using InnovEnergy.App.SaliMax.SystemConfig;
namespace InnovEnergy.App.SaliMax.MiddlewareClasses; namespace InnovEnergy.App.SaliMax.DataTypes;
public class Configuration public class Configuration
{ {

View File

@ -1,7 +1,6 @@
using InnovEnergy.App.SaliMax.Ess; using InnovEnergy.App.SaliMax.Ess;
namespace InnovEnergy.App.SaliMax.MiddlewareClasses; namespace InnovEnergy.App.SaliMax.DataTypes;
public class StatusMessage public class StatusMessage
{ {

View File

@ -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; }
}

View File

@ -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;
}
}

View File

@ -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}");
}
}

View File

@ -4,7 +4,6 @@ using System.Net.NetworkInformation;
using System.Net.Sockets; using System.Net.Sockets;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Reactive.Threading.Tasks; using System.Reactive.Threading.Tasks;
using System.Security.Cryptography.X509Certificates;
using System.Text; using System.Text;
using Flurl.Http; using Flurl.Http;
using InnovEnergy.App.SaliMax.Devices; using InnovEnergy.App.SaliMax.Devices;
@ -26,7 +25,7 @@ using InnovEnergy.Lib.Protocols.Modbus.Channels;
using InnovEnergy.Lib.Units; using InnovEnergy.Lib.Units;
using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Utils;
using System.Text.Json; using System.Text.Json;
using RabbitMQ.Client; using InnovEnergy.App.SaliMax.DataTypes;
using static System.Double; using static System.Double;
using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes.SystemConfig; using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes.SystemConfig;
using DeviceState = InnovEnergy.App.SaliMax.Devices.DeviceState; using DeviceState = InnovEnergy.App.SaliMax.Devices.DeviceState;
@ -52,14 +51,7 @@ internal static class Program
private static readonly Channel RelaysChannel ; private static readonly Channel RelaysChannel ;
private static readonly Channel BatteriesChannel ; private static readonly Channel BatteriesChannel ;
//private const String VpnServerIp = "194.182.190.208";
private const String VpnServerIp = "10.2.0.11"; 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 _subscribedToQueue = false;
private static Boolean _subscribeToQueueForTheFirstTime = false; private static Boolean _subscribeToQueueForTheFirstTime = false;
private static SalimaxAlarmState _prevSalimaxState = SalimaxAlarmState.Green; private static SalimaxAlarmState _prevSalimaxState = SalimaxAlarmState.Green;
@ -95,7 +87,7 @@ internal static class Program
{ {
//Do not await //Do not await
HourlyDataAggregationManager(); HourlyDataAggregationManager();
InitializeCommunicationToMiddleware(); MiddlewareAgent.InitializeCommunicationToMiddleware();
while (true) while (true)
{ {
try 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() private static async Task Run()
{ {
@ -262,8 +240,8 @@ internal static class Program
// ReSharper disable once FunctionNeverReturns // 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; var s3Bucket = Config.Load().S3?.Bucket;
@ -274,14 +252,14 @@ internal static class Program
if (_subscribeToQueueForTheFirstTime==false) if (_subscribeToQueueForTheFirstTime==false)
{ {
_subscribeToQueueForTheFirstTime = true; _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 already subscribed to the queue and the status has been changed, update the queue
if (_subscribedToQueue && currentSalimaxState.Status != _prevSalimaxState) if (_subscribedToQueue && currentSalimaxState.Status != _prevSalimaxState)
{ {
_prevSalimaxState = currentSalimaxState.Status; _prevSalimaxState = currentSalimaxState.Status;
if (s3Bucket != null) if (s3Bucket != null)
InformMiddleware(currentSalimaxState); RabbitMqManager.InformMiddleware(currentSalimaxState);
} }
else if (_subscribedToQueue && _heartBitInterval>=15) else if (_subscribedToQueue && _heartBitInterval>=15)
{ {
@ -291,97 +269,16 @@ internal static class Program
currentSalimaxState.Type = MessageType.Heartbit; currentSalimaxState.Type = MessageType.Heartbit;
if (s3Bucket != null) if (s3Bucket != null)
InformMiddleware(currentSalimaxState); RabbitMqManager.InformMiddleware(currentSalimaxState);
} }
//If there is an available message from the RabbitMQ Broker, apply the configuration file //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); 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) 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" //Create a new file to folder "Hourly Aggregated Data and push it to S3"
Console.WriteLine("-----------------------------------------------------------------------------------------------------------------"); Console.WriteLine("-----------------------------------------------------------------------------------------------------------------");
} }
// Custom method to check if a string is numeric // Custom method to check if a string is numeric
private static bool IsSoc(string value) private static bool IsSoc(string value)
{ {
@ -792,7 +693,7 @@ internal static class Program
return value == "/Battery/Dc/Power"; 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.MinSoc = config.MinimumSoC;
status.Config.GridSetPoint = config.GridSetPoint * 1000; // converted from kW to W status.Config.GridSetPoint = config.GridSetPoint * 1000; // converted from kW to W