From 2199f43400d36fd522b81f14d44470ae203974bf Mon Sep 17 00:00:00 2001 From: Noe Date: Wed, 8 Nov 2023 11:59:15 +0100 Subject: [PATCH 1/3] Integrate middleware code inside backend --- csharp/App/Backend/Backend.csproj | 8 + csharp/App/Backend/Controller.cs | 126 ++++++++++ .../App/Backend/DataTypes/Methods/ExoCmd.cs | 8 +- csharp/App/Backend/Program.cs | 6 +- .../Backend/Websockets/InstallationInfo.cs | 7 + .../App/Backend/Websockets/StatusMessage.cs | 6 + .../Backend/Websockets/WebsockerManager.cs | 238 ++++++++++++++++++ csharp/App/BmsTunnel/Program.cs | 4 +- csharp/App/Middleware/Program.cs | 4 +- csharp/App/Middleware/RabbitMQConsumer.cs | 118 ++++----- .../src/Resources/axiosConfig.tsx | 6 +- .../src/content/dashboards/Tree/treeView.tsx | 5 +- 12 files changed, 463 insertions(+), 73 deletions(-) create mode 100644 csharp/App/Backend/Websockets/InstallationInfo.cs create mode 100644 csharp/App/Backend/Websockets/StatusMessage.cs create mode 100644 csharp/App/Backend/Websockets/WebsockerManager.cs diff --git a/csharp/App/Backend/Backend.csproj b/csharp/App/Backend/Backend.csproj index bbbac1191..0e70bb5dd 100644 --- a/csharp/App/Backend/Backend.csproj +++ b/csharp/App/Backend/Backend.csproj @@ -23,6 +23,7 @@ + @@ -51,4 +52,11 @@ + + + + ..\..\..\..\..\..\.nuget\packages\rabbitmq.client\6.6.0\lib\netstandard2.0\RabbitMQ.Client.dll + + + diff --git a/csharp/App/Backend/Controller.cs b/csharp/App/Backend/Controller.cs index 524cad118..e76f2d71d 100644 --- a/csharp/App/Backend/Controller.cs +++ b/csharp/App/Backend/Controller.cs @@ -1,7 +1,12 @@ +using System.Net; +using System.Net.WebSockets; +using System.Text; +using System.Text.Json; using InnovEnergy.App.Backend.Database; using InnovEnergy.App.Backend.DataTypes; using InnovEnergy.App.Backend.DataTypes.Methods; using InnovEnergy.App.Backend.Relations; +using InnovEnergy.App.Backend.Websockets; using InnovEnergy.Lib.Utils; using Microsoft.AspNetCore.Mvc; @@ -9,10 +14,12 @@ namespace InnovEnergy.App.Backend; using Token = String; + [Controller] [Route("api/")] public class Controller : ControllerBase { + [HttpPost(nameof(Login))] public ActionResult Login(String username, String? password) { @@ -47,6 +54,125 @@ public class Controller : ControllerBase : Unauthorized(); } + [HttpGet(nameof(CreateWebSocket))] + public async Task CreateWebSocket(Token authToken) + { + var session = Db.GetSession(authToken)?.User; + + if (session is null) + { + HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized; + HttpContext.Abort(); + return; + } + + if (!HttpContext.WebSockets.IsWebSocketRequest) + { + HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized; + HttpContext.Abort(); + return; + } + + var webSocketContext = await HttpContext.WebSockets.AcceptWebSocketAsync(); + var webSocket = webSocketContext; + + //Handle the WebSocket connection + //WebsocketManager.HandleWebSocketConnection(webSocket) + + var buffer = new byte[4096]; + try + { + while (webSocket.State == WebSocketState.Open) + { + //Listen for incoming messages on this WebSocket + var result = await webSocket.ReceiveAsync(buffer, CancellationToken.None); + Console.WriteLine("Received a new message from websocket"); + if (result.MessageType != WebSocketMessageType.Text) + continue; + + var message = Encoding.UTF8.GetString(buffer, 0, result.Count); + var installationIds = JsonSerializer.Deserialize(message); + + lock (WebsocketManager.InstallationConnections) + { + //Each front-end will send the list of the installations it wants to access + //If this is a new key (installation id), initialize the list for this key and then add the websocket object for this client + //Then, report the status of each requested installation to the front-end that created the websocket connection + if (installationIds != null) + foreach (var installationId in installationIds) + { + if (!WebsocketManager.InstallationConnections.ContainsKey(installationId)) + { + Console.WriteLine("Create new empty list for installation id " + installationId); + WebsocketManager.InstallationConnections[installationId] = new InstallationInfo + { + Status = -2 + }; + } + + WebsocketManager.InstallationConnections[installationId].Connections.Add(webSocket); + + var jsonObject = new + { + id = installationId, + status = WebsocketManager.InstallationConnections[installationId].Status + }; + + var jsonString = JsonSerializer.Serialize(jsonObject); + var dataToSend = Encoding.UTF8.GetBytes(jsonString); + + + webSocket.SendAsync(dataToSend, + WebSocketMessageType.Text, + true, // Indicates that this is the end of the message + CancellationToken.None + ); + } + + Console.WriteLine("Printing installation connection list"); + Console.WriteLine("----------------------------------------------"); + foreach (var installationConnection in WebsocketManager.InstallationConnections) + { + Console.WriteLine("Installation ID: " + installationConnection.Key + " Number of Connections: " + installationConnection.Value.Connections.Count); + } + Console.WriteLine("----------------------------------------------"); + } + } + + lock (WebsocketManager.InstallationConnections) + { + //When the front-end terminates the connection, the following code will be executed + Console.WriteLine("The connection has been terminated"); + foreach (var installationConnection in WebsocketManager.InstallationConnections) + { + if (installationConnection.Value.Connections.Contains(webSocket)) + { + installationConnection.Value.Connections.Remove(webSocket); + } + } + } + + await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Connection closed by server", CancellationToken.None); + lock (WebsocketManager.InstallationConnections) + { + //Print the installationConnections dictionary after deleting a websocket + Console.WriteLine("Print the installation connections list after deleting a websocket"); + Console.WriteLine("----------------------------------------------"); + foreach (var installationConnection in WebsocketManager.InstallationConnections) + { + Console.WriteLine("Installation ID: " + installationConnection.Key + " Number of Connections: " + installationConnection.Value.Connections.Count); + } + + Console.WriteLine("----------------------------------------------"); + } + } + catch (Exception ex) + { + Console.WriteLine("WebSocket error: " + ex.Message); + } + + + } [HttpGet(nameof(GetUserById))] public ActionResult GetUserById(Int64 id, Token authToken) diff --git a/csharp/App/Backend/DataTypes/Methods/ExoCmd.cs b/csharp/App/Backend/DataTypes/Methods/ExoCmd.cs index b28f64142..8f2836cd5 100644 --- a/csharp/App/Backend/DataTypes/Methods/ExoCmd.cs +++ b/csharp/App/Backend/DataTypes/Methods/ExoCmd.cs @@ -44,7 +44,7 @@ public static class ExoCmd messageToSign += time; - Console.WriteLine("Message to sign:\n" + messageToSign); + //Console.WriteLine("Message to sign:\n" + messageToSign); var hmac = HmacSha256Digest(messageToSign, Secret); @@ -108,7 +108,7 @@ public static class ExoCmd if (response.StatusCode != HttpStatusCode.OK){ Console.WriteLine("Fuck"); } - Console.WriteLine($"Created Key for {installation.Name}"); + //Console.WriteLine($"Created Key for {installation.Name}"); var responseString = await response.Content.ReadAsStringAsync(); var responseJson = JsonNode.Parse(responseString) ; @@ -155,7 +155,7 @@ public static class ExoCmd var response = await client.PostAsync(url, content); var responseString = await response.Content.ReadAsStringAsync(); - Console.WriteLine(responseString); + //Console.WriteLine(responseString); //Put Role ID into database var id = JsonNode.Parse(responseString)!["reference"]!["id"]!.GetValue(); @@ -232,7 +232,7 @@ public static class ExoCmd var response = await client.PostAsync(url, content); var responseString = await response.Content.ReadAsStringAsync(); - Console.WriteLine(responseString); + //Console.WriteLine(responseString); //Put Role ID into database var id = JsonNode.Parse(responseString)!["reference"]!["id"]!.GetValue(); diff --git a/csharp/App/Backend/Program.cs b/csharp/App/Backend/Program.cs index 455a9ba8b..09ebc3c0a 100644 --- a/csharp/App/Backend/Program.cs +++ b/csharp/App/Backend/Program.cs @@ -1,5 +1,6 @@ using Hellang.Middleware.ProblemDetails; using InnovEnergy.App.Backend.Database; +using InnovEnergy.App.Backend.Websockets; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.Mvc; using Microsoft.OpenApi.Models; @@ -14,6 +15,8 @@ public static class Program //Db.CreateFakeRelations(); Db.Init(); var builder = WebApplication.CreateBuilder(args); + + WebsocketManager.InformInstallationsToSubscribeToRabbitMq(); builder.Services.AddControllers(); builder.Services.AddProblemDetails(setup => @@ -46,8 +49,9 @@ public static class Program await next(context); }); + - + app.UseWebSockets(); app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto diff --git a/csharp/App/Backend/Websockets/InstallationInfo.cs b/csharp/App/Backend/Websockets/InstallationInfo.cs new file mode 100644 index 000000000..770a6698c --- /dev/null +++ b/csharp/App/Backend/Websockets/InstallationInfo.cs @@ -0,0 +1,7 @@ +using System.Net.WebSockets; + +public class InstallationInfo +{ + public int Status { get; set; } + public List Connections { get; } = new List(); +} \ No newline at end of file diff --git a/csharp/App/Backend/Websockets/StatusMessage.cs b/csharp/App/Backend/Websockets/StatusMessage.cs new file mode 100644 index 000000000..074ac71b0 --- /dev/null +++ b/csharp/App/Backend/Websockets/StatusMessage.cs @@ -0,0 +1,6 @@ + +public class StatusMessage +{ + public required int InstallationId { get; init; } + public required int Status { get; init; } +} \ No newline at end of file diff --git a/csharp/App/Backend/Websockets/WebsockerManager.cs b/csharp/App/Backend/Websockets/WebsockerManager.cs new file mode 100644 index 000000000..37e5d4e85 --- /dev/null +++ b/csharp/App/Backend/Websockets/WebsockerManager.cs @@ -0,0 +1,238 @@ +using System.Diagnostics.CodeAnalysis; +using System.Net; +using System.Net.Sockets; +using System.Net.WebSockets; +using System.Text; +using System.Text.Json; +using RabbitMQ.Client; +using RabbitMQ.Client.Events; + +namespace InnovEnergy.App.Backend.Websockets; + +public static class WebsocketManager +{ + public static readonly Dictionary InstallationConnections = new Dictionary(); + private static ConnectionFactory _factory = null!; + private static IConnection _connection = null!; + private static IModel _channel = null!; + + public static void InformInstallationsToSubscribeToRabbitMq() + { + var installationsIds = new List { 1 }; + var installationIps = new List { "10.2.3.115" }; + var maxRetransmissions = 2; + + StartRabbitMqConsumer(); + + UdpClient udpClient = new UdpClient(); + udpClient.Client.ReceiveTimeout = 2000; + int port = 9000; + //Send a message to each installation and tell it to subscribe to the queue + for (int i = 0; i < installationsIds.Count; i++) + { + using (udpClient) + { + //Try at most MAX_RETRANSMISSIONS times to reach an installation. + for (int j = 0; j < maxRetransmissions; j++) + { + string message = "This is a message from RabbitMQ server, you can subscribe to the RabbitMQ queue"; + byte[] data = Encoding.UTF8.GetBytes(message); + udpClient.Send(data, data.Length, installationIps[i], port); + + Console.WriteLine($"Sent UDP message to {installationIps[i]}:{port}: {message}"); + IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(installationIps[i]), port); + + try + { + byte[] replyData = udpClient.Receive(ref remoteEndPoint); + string replyMessage = Encoding.UTF8.GetString(replyData); + Console.WriteLine("Received "+replyMessage +" from installation " + installationsIds[i]); + break; + } + catch (SocketException ex) + { + if (ex.SocketErrorCode == SocketError.TimedOut) + { + Console.WriteLine("Timed out waiting for a response. Retry..."); + } + else + { + Console.WriteLine("Error: " + ex.Message); + } + } + } + } + } + } + + public static void StartRabbitMqConsumer() + { + //string vpnServerIp = "194.182.190.208"; + string vpnServerIp = "127.0.0.1"; + _factory = new ConnectionFactory { HostName = vpnServerIp}; + _connection = _factory.CreateConnection(); + _channel = _connection.CreateModel(); + Console.WriteLine("Middleware subscribed to RabbitMQ queue, ready for receiving messages"); + _channel.QueueDeclare(queue: "statusQueue", durable: false, exclusive: false, autoDelete: false, arguments: null); + + var consumer = new EventingBasicConsumer(_channel); + consumer.Received += (_, ea) => CallbackReceiveMessageFromQueue(ea); + _channel.BasicConsume(queue: "statusQueue", autoAck: true, consumer: consumer); + } + + [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "")] + private static void CallbackReceiveMessageFromQueue(BasicDeliverEventArgs ea) + { + var body = ea.Body.ToArray(); + var message = Encoding.UTF8.GetString(body); + StatusMessage? receivedStatusMessage = JsonSerializer.Deserialize(message); + + lock (InstallationConnections) + { + // Process the received message + if (receivedStatusMessage != null) + { + Console.WriteLine("Received a message from installation: " + receivedStatusMessage.InstallationId + " and status is: " + receivedStatusMessage.Status); + Console.WriteLine("----------------------------------------------"); + Console.WriteLine("Update installation connection table"); + var installationId = receivedStatusMessage.InstallationId; + + if (!InstallationConnections.ContainsKey(installationId)) + { + Console.WriteLine("Create new empty list for installation: " + installationId); + InstallationConnections[installationId] = new InstallationInfo + { + Status = receivedStatusMessage.Status + }; + } + + Console.WriteLine("----------------------------------------------"); + + foreach (var installationConnection in InstallationConnections) + { + if (installationConnection.Key == installationId && installationConnection.Value.Connections.Count > 0) + { + Console.WriteLine("Update all the connected websockets for installation " + installationId); + installationConnection.Value.Status = receivedStatusMessage.Status; + + var jsonObject = new + { + id = installationId, + status = receivedStatusMessage.Status + }; + + string jsonString = JsonSerializer.Serialize(jsonObject); + byte[] dataToSend = Encoding.UTF8.GetBytes(jsonString); + + foreach (var connection in installationConnection.Value.Connections) + { + connection.SendAsync( + new ArraySegment(dataToSend, 0, dataToSend.Length), + WebSocketMessageType.Text, + true, // Indicates that this is the end of the message + CancellationToken.None + ); + } + } + } + } + } + } + + [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "")] + public static async Task HandleWebSocketConnection(WebSocket currentWebSocket) + { + var buffer = new byte[4096]; + try + { + while (currentWebSocket.State == WebSocketState.Open) + { + //Listen for incoming messages on this WebSocket + var result = await currentWebSocket.ReceiveAsync(buffer, CancellationToken.None); + Console.WriteLine("Received a new message from websocket"); + if (result.MessageType != WebSocketMessageType.Text) + continue; + + var message = Encoding.UTF8.GetString(buffer, 0, result.Count); + var installationIds = JsonSerializer.Deserialize(message); + + lock (InstallationConnections) + { + //Each front-end will send the list of the installations it wants to access + //If this is a new key (installation id), initialize the list for this key and then add the websocket object for this client + //Then, report the status of each requested installation to the front-end that created the websocket connection + if (installationIds != null) + foreach (var installationId in installationIds) + { + if (!InstallationConnections.ContainsKey(installationId)) + { + Console.WriteLine("Create new empty list for installation id " + installationId); + InstallationConnections[installationId] = new InstallationInfo + { + Status = -2 + }; + } + + InstallationConnections[installationId].Connections.Add(currentWebSocket); + + var jsonObject = new + { + id = installationId, + status = InstallationConnections[installationId].Status + }; + + var jsonString = JsonSerializer.Serialize(jsonObject); + var dataToSend = Encoding.UTF8.GetBytes(jsonString); + + + currentWebSocket.SendAsync(dataToSend, + WebSocketMessageType.Text, + true, // Indicates that this is the end of the message + CancellationToken.None + ); + } + + Console.WriteLine("Printing installation connection list"); + Console.WriteLine("----------------------------------------------"); + foreach (var installationConnection in InstallationConnections) + { + Console.WriteLine("Installation ID: " + installationConnection.Key + " Number of Connections: " + installationConnection.Value.Connections.Count); + } + Console.WriteLine("----------------------------------------------"); + } + } + + lock (InstallationConnections) + { + //When the front-end terminates the connection, the following code will be executed + Console.WriteLine("The connection has been terminated"); + foreach (var installationConnection in InstallationConnections) + { + if (installationConnection.Value.Connections.Contains(currentWebSocket)) + { + installationConnection.Value.Connections.Remove(currentWebSocket); + } + } + } + + await currentWebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Connection closed by server", CancellationToken.None); + lock (InstallationConnections) + { + //Print the installationConnections dictionary after deleting a websocket + Console.WriteLine("Print the installation connections list after deleting a websocket"); + Console.WriteLine("----------------------------------------------"); + foreach (var installationConnection in InstallationConnections) + { + Console.WriteLine("Installation ID: " + installationConnection.Key + " Number of Connections: " + installationConnection.Value.Connections.Count); + } + + Console.WriteLine("----------------------------------------------"); + } + } + catch (Exception ex) + { + Console.WriteLine("WebSocket error: " + ex.Message); + } + } + +} \ No newline at end of file diff --git a/csharp/App/BmsTunnel/Program.cs b/csharp/App/BmsTunnel/Program.cs index eb23e57d8..b9968d63e 100644 --- a/csharp/App/BmsTunnel/Program.cs +++ b/csharp/App/BmsTunnel/Program.cs @@ -25,11 +25,11 @@ public static class Program ExplainNode(); ExplainExit(); - Console.WriteLine(""); + //Console.WriteLine(""); while (true) { - Console.WriteLine(""); + //Console.WriteLine(""); Console.Write($"node{tunnel.Node}> "); var cmd = Console.ReadLine()?.ToUpper().Trim(); diff --git a/csharp/App/Middleware/Program.cs b/csharp/App/Middleware/Program.cs index 65bf0efb9..7a5bd0ed4 100644 --- a/csharp/App/Middleware/Program.cs +++ b/csharp/App/Middleware/Program.cs @@ -4,6 +4,7 @@ using System.Net; using System.Net.Sockets; using System.Net.WebSockets; using System.Text; +using InnovEnergy.Lib.Utils; internal class Program { @@ -16,6 +17,7 @@ internal class Program var installationsIds = new List {1}; var installationIps = new List {"10.2.3.115"}; var MAX_RETRANSMISSIONS = 2; + RabbitMqConsumer.StartRabbitMqConsumer(installationConnections,SharedDataLock); UdpClient udpClient = new UdpClient(); @@ -58,8 +60,6 @@ internal class Program } } - Console.WriteLine("WebSocket server is running. Press Enter to exit."); - Console.WriteLine("WebSocket server is running. Press Enter to exit."); await WebSocketListener.StartServerAsync(installationConnections,SharedDataLock); } diff --git a/csharp/App/Middleware/RabbitMQConsumer.cs b/csharp/App/Middleware/RabbitMQConsumer.cs index 90967731e..688f202b9 100644 --- a/csharp/App/Middleware/RabbitMQConsumer.cs +++ b/csharp/App/Middleware/RabbitMQConsumer.cs @@ -15,72 +15,74 @@ public static class RabbitMqConsumer public static void StartRabbitMqConsumer(Dictionary installationConnections, Object sharedDataLock) { string vpnServerIp = "194.182.190.208"; - _factory = new ConnectionFactory { HostName = vpnServerIp }; + _factory = new ConnectionFactory { HostName = "localhost" }; _connection = _factory.CreateConnection(); _channel = _connection.CreateModel(); Console.WriteLine("Middleware subscribed to RabbitMQ queue, ready for receiving messages"); _channel.QueueDeclare(queue: "statusQueue", durable: false, exclusive: false, autoDelete: false, arguments: null); var consumer = new EventingBasicConsumer(_channel); - consumer.Received += (model, ea) => - { - var body = ea.Body.ToArray(); - var message = Encoding.UTF8.GetString(body); - StatusMessage? receivedStatusMessage = JsonSerializer.Deserialize(message); - - lock (sharedDataLock) - { - // Process the received message - if (receivedStatusMessage != null) - { - Console.WriteLine("Received a message from installation: " + receivedStatusMessage.InstallationId + " and status is: " + receivedStatusMessage.Status); - Console.WriteLine("----------------------------------------------"); - Console.WriteLine("Update installation connection table"); - var installationId = receivedStatusMessage.InstallationId; - - if (!installationConnections.ContainsKey(installationId)) - { - Console.WriteLine("Create new empty list for installation: " + installationId); - installationConnections[installationId] = new InstallationInfo - { - Status = receivedStatusMessage.Status - }; - } - - Console.WriteLine("----------------------------------------------"); - - foreach (var installationConnection in installationConnections) - { - if (installationConnection.Key == installationId && installationConnection.Value.Connections.Count > 0) - { - Console.WriteLine("Update all the connected websockets for installation " + installationId); - installationConnection.Value.Status = receivedStatusMessage.Status; - - var jsonObject = new - { - id = installationId, - status = receivedStatusMessage.Status - }; - - string jsonString = JsonSerializer.Serialize(jsonObject); - byte[] dataToSend = Encoding.UTF8.GetBytes(jsonString); - - foreach (var connection in installationConnection.Value.Connections) - { - connection.SendAsync( - new ArraySegment(dataToSend, 0, dataToSend.Length), - WebSocketMessageType.Text, - true, // Indicates that this is the end of the message - CancellationToken.None - ); - } - } - } - } - } - }; + consumer.Received += (_, ea) => Callback(installationConnections, sharedDataLock, ea); _channel.BasicConsume(queue: "statusQueue", autoAck: true, consumer: consumer); } + + private static void Callback(Dictionary installationConnections, Object sharedDataLock, BasicDeliverEventArgs ea) + { + var body = ea.Body.ToArray(); + var message = Encoding.UTF8.GetString(body); + StatusMessage? receivedStatusMessage = JsonSerializer.Deserialize(message); + + lock (sharedDataLock) + { + // Process the received message + if (receivedStatusMessage != null) + { + Console.WriteLine("Received a message from installation: " + receivedStatusMessage.InstallationId + " and status is: " + receivedStatusMessage.Status); + Console.WriteLine("----------------------------------------------"); + Console.WriteLine("Update installation connection table"); + var installationId = receivedStatusMessage.InstallationId; + + if (!installationConnections.ContainsKey(installationId)) + { + Console.WriteLine("Create new empty list for installation: " + installationId); + installationConnections[installationId] = new InstallationInfo + { + Status = receivedStatusMessage.Status + }; + } + + Console.WriteLine("----------------------------------------------"); + + foreach (var installationConnection in installationConnections) + { + if (installationConnection.Key == installationId && installationConnection.Value.Connections.Count > 0) + { + Console.WriteLine("Update all the connected websockets for installation " + installationId); + installationConnection.Value.Status = receivedStatusMessage.Status; + + var jsonObject = new + { + id = installationId, + status = receivedStatusMessage.Status + }; + + string jsonString = JsonSerializer.Serialize(jsonObject); + byte[] dataToSend = Encoding.UTF8.GetBytes(jsonString); + + foreach (var connection in installationConnection.Value.Connections) + { + connection.SendAsync( + new ArraySegment(dataToSend, 0, dataToSend.Length), + WebSocketMessageType.Text, + true, // Indicates that this is the end of the message + CancellationToken.None + ); + } + } + } + } + } + } } \ No newline at end of file diff --git a/typescript/frontend-marios2/src/Resources/axiosConfig.tsx b/typescript/frontend-marios2/src/Resources/axiosConfig.tsx index 84da2b64f..6069ad19f 100644 --- a/typescript/frontend-marios2/src/Resources/axiosConfig.tsx +++ b/typescript/frontend-marios2/src/Resources/axiosConfig.tsx @@ -1,11 +1,13 @@ import axios from 'axios'; export const axiosConfigWithoutToken = axios.create({ - baseURL: 'https://monitor.innov.energy/api' + //baseURL: 'https://monitor.innov.energy/api' + baseURL: 'http://127.0.0.1:7087/api' }); const axiosConfig = axios.create({ - baseURL: 'https://monitor.innov.energy/api' + //baseURL: 'https://monitor.innov.energy/api' + baseURL: 'http://127.0.0.1:7087/api' }); axiosConfig.defaults.params = {}; diff --git a/typescript/frontend-marios2/src/content/dashboards/Tree/treeView.tsx b/typescript/frontend-marios2/src/content/dashboards/Tree/treeView.tsx index 1626d2530..82e8c737d 100644 --- a/typescript/frontend-marios2/src/content/dashboards/Tree/treeView.tsx +++ b/typescript/frontend-marios2/src/content/dashboards/Tree/treeView.tsx @@ -1,7 +1,6 @@ import { Box, Grid, useTheme } from '@mui/material'; import InstallationTree from './InstallationTree'; import InstallationsContextProvider from 'src/contexts/InstallationsContextProvider'; -import LogContextProvider from '../../../contexts/LogContextProvider'; function TreeView() { const theme = useTheme(); @@ -10,9 +9,7 @@ function TreeView() { - - - + From 704c1910dbe07fb68a186069474f048ff41539ea Mon Sep 17 00:00:00 2001 From: Noe Date: Wed, 8 Nov 2023 12:07:49 +0100 Subject: [PATCH 2/3] Update VPN IPs --- csharp/App/Backend/Controller.cs | 96 +------------------ .../Backend/Websockets/WebsockerManager.cs | 4 +- 2 files changed, 3 insertions(+), 97 deletions(-) diff --git a/csharp/App/Backend/Controller.cs b/csharp/App/Backend/Controller.cs index e76f2d71d..ee4d50ba1 100644 --- a/csharp/App/Backend/Controller.cs +++ b/csharp/App/Backend/Controller.cs @@ -77,101 +77,7 @@ public class Controller : ControllerBase var webSocket = webSocketContext; //Handle the WebSocket connection - //WebsocketManager.HandleWebSocketConnection(webSocket) - - var buffer = new byte[4096]; - try - { - while (webSocket.State == WebSocketState.Open) - { - //Listen for incoming messages on this WebSocket - var result = await webSocket.ReceiveAsync(buffer, CancellationToken.None); - Console.WriteLine("Received a new message from websocket"); - if (result.MessageType != WebSocketMessageType.Text) - continue; - - var message = Encoding.UTF8.GetString(buffer, 0, result.Count); - var installationIds = JsonSerializer.Deserialize(message); - - lock (WebsocketManager.InstallationConnections) - { - //Each front-end will send the list of the installations it wants to access - //If this is a new key (installation id), initialize the list for this key and then add the websocket object for this client - //Then, report the status of each requested installation to the front-end that created the websocket connection - if (installationIds != null) - foreach (var installationId in installationIds) - { - if (!WebsocketManager.InstallationConnections.ContainsKey(installationId)) - { - Console.WriteLine("Create new empty list for installation id " + installationId); - WebsocketManager.InstallationConnections[installationId] = new InstallationInfo - { - Status = -2 - }; - } - - WebsocketManager.InstallationConnections[installationId].Connections.Add(webSocket); - - var jsonObject = new - { - id = installationId, - status = WebsocketManager.InstallationConnections[installationId].Status - }; - - var jsonString = JsonSerializer.Serialize(jsonObject); - var dataToSend = Encoding.UTF8.GetBytes(jsonString); - - - webSocket.SendAsync(dataToSend, - WebSocketMessageType.Text, - true, // Indicates that this is the end of the message - CancellationToken.None - ); - } - - Console.WriteLine("Printing installation connection list"); - Console.WriteLine("----------------------------------------------"); - foreach (var installationConnection in WebsocketManager.InstallationConnections) - { - Console.WriteLine("Installation ID: " + installationConnection.Key + " Number of Connections: " + installationConnection.Value.Connections.Count); - } - Console.WriteLine("----------------------------------------------"); - } - } - - lock (WebsocketManager.InstallationConnections) - { - //When the front-end terminates the connection, the following code will be executed - Console.WriteLine("The connection has been terminated"); - foreach (var installationConnection in WebsocketManager.InstallationConnections) - { - if (installationConnection.Value.Connections.Contains(webSocket)) - { - installationConnection.Value.Connections.Remove(webSocket); - } - } - } - - await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Connection closed by server", CancellationToken.None); - lock (WebsocketManager.InstallationConnections) - { - //Print the installationConnections dictionary after deleting a websocket - Console.WriteLine("Print the installation connections list after deleting a websocket"); - Console.WriteLine("----------------------------------------------"); - foreach (var installationConnection in WebsocketManager.InstallationConnections) - { - Console.WriteLine("Installation ID: " + installationConnection.Key + " Number of Connections: " + installationConnection.Value.Connections.Count); - } - - Console.WriteLine("----------------------------------------------"); - } - } - catch (Exception ex) - { - Console.WriteLine("WebSocket error: " + ex.Message); - } - - + await WebsocketManager.HandleWebSocketConnection(webSocket); } [HttpGet(nameof(GetUserById))] diff --git a/csharp/App/Backend/Websockets/WebsockerManager.cs b/csharp/App/Backend/Websockets/WebsockerManager.cs index 37e5d4e85..591bb1abf 100644 --- a/csharp/App/Backend/Websockets/WebsockerManager.cs +++ b/csharp/App/Backend/Websockets/WebsockerManager.cs @@ -67,8 +67,8 @@ public static class WebsocketManager public static void StartRabbitMqConsumer() { - //string vpnServerIp = "194.182.190.208"; - string vpnServerIp = "127.0.0.1"; + string vpnServerIp = "194.182.190.208"; + //string vpnServerIp = "127.0.0.1"; _factory = new ConnectionFactory { HostName = vpnServerIp}; _connection = _factory.CreateConnection(); _channel = _connection.CreateModel(); From 4878e7bcae835ee686794c9be28735afab2777c9 Mon Sep 17 00:00:00 2001 From: atef Date: Fri, 10 Nov 2023 11:02:47 +0100 Subject: [PATCH 3/3] Add a readme file for the config.json --- csharp/App/SaliMax/resources/ConfigReadme.txt | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 csharp/App/SaliMax/resources/ConfigReadme.txt diff --git a/csharp/App/SaliMax/resources/ConfigReadme.txt b/csharp/App/SaliMax/resources/ConfigReadme.txt new file mode 100644 index 000000000..a47ab3469 --- /dev/null +++ b/csharp/App/SaliMax/resources/ConfigReadme.txt @@ -0,0 +1,110 @@ +"MinSoc": Number, 0 - 100 this is the minimum State of Charge that the batteries must not go below, + "ForceCalibrationCharge": Boolean (true or false), A flag to force a calibration charge, + "DisplayIndividualBatteries": Boolean (true or false), To display the indvidual batteries + "PConstant": Number 0 - 1, P value of our controller. + "GridSetPoint": Number in Watts, The set point of our controller. + "BatterySelfDischargePower": Number, 200, this a physical measurement of the self discharging power. + "HoldSocZone": Number, 1, This is magic number for the soft landing factor. + "IslandMode": { // Dc Link Voltage in Island mode + "AcDc": { + "MaxDcLinkVoltage": Number, 810, Max Dc Link Voltage, + "MinDcLinkVoltage": Number, 690, Min Dc Link Voltage, + "ReferenceDcLinkVoltage": Number, 750, Reference Dc Link + }, + "DcDc": { + "LowerDcLinkVoltage": Number, 50, Lower Dc Link Window , + "ReferenceDcLinkVoltage": 750, reference Dc Link + "UpperDcLinkVoltage": Number, 50, Upper Dc Link Window , + } + }, + "GridTie": {// Dc Link Voltage in GrieTie mode + "AcDc": { + "MaxDcLinkVoltage":Number, 780, Max Dc Link Voltage, + "MinDcLinkVoltage": Number, 690, Min Dc Link Voltage, + "ReferenceDcLinkVoltage": Number, 750, Reference Dc Link + }, + "DcDc": { + "LowerDcLinkVoltage": Number, 20, Lower Dc Link Window , + "ReferenceDcLinkVoltage": 750, reference Dc Link + "UpperDcLinkVoltage": Number, 20, Upper Dc Link Window , + } + }, + "MaxBatteryChargingCurrent":Number, 0 - 210, Max Charging current by DcDc + "MaxBatteryDischargingCurrent":Number, 0 - 210, Max Discharging current by DcDc + "MaxDcPower": Number, 0 - 10000, Max Power exported/imported by DcDc (10000 is the maximum) + "MaxChargeBatteryVoltage": Number, 57, Max Charging battery Voltage + "MinDischargeBatteryVoltage": Number, 0, Min Charging Battery Voltage + "Devices": { This is All Salimax devices (including offline ones) + "RelaysIp": { + "DeviceState": 1, // 0: is not present, 1: Present and Can be mesured, 2: Present but must be computed/calculted + "Host": "10.0.1.1", // Ip @ of the device in the local network + "Port": 502 // port + }, + "GridMeterIp": { + "DeviceState": 1, + "Host": "10.0.4.1", + "Port": 502 + }, + "PvOnAcGrid": { + "DeviceState": 0, // If a device is not present + "Host": "false", // this is not important + "Port": 0 // this is not important + }, + "LoadOnAcGrid": { + "DeviceState": 2, // this is a computed device + "Host": "true", + "Port": 0 + }, + "PvOnAcIsland": { + "DeviceState": 0, + "Host": "false", + "Port": 0 + }, + "IslandBusLoadMeterIp": { + "DeviceState": 1, + "Host": "10.0.4.2", + "Port": 502 + }, + "TruConvertAcIp": { + "DeviceState": 1, + "Host": "10.0.2.1", + "Port": 502 + }, + "PvOnDc": { + "DeviceState": 1, + "Host": "10.0.5.1", + "Port": 502 + }, + "LoadOnDc": { + "DeviceState": 0, + "Host": "false", + "Port": 0 + }, + "TruConvertDcIp": { + "DeviceState": 1, + "Host": "10.0.3.1", + "Port": 502 + }, + "BatteryIp": { + "DeviceState": 1, + "Host": "localhost", + "Port": 6855 + }, + "BatteryNodes": [ // this is a list of battery nodes + 2, + 3, + 4, + 5, + 6 + ] + }, + "S3": { // this is parameters of S3 Buckets and co + "Bucket": "8-3e5b3069-214a-43ee-8d85-57d72000c19d", + "Region": "sos-ch-dk-2", + "Provider": "exo.io", + "Key": "EXO502627299197f83e8b090f63", + "Secret": "jUNYJL6B23WjndJnJlgJj4rc1i7uh981u5Aba5xdA5s", + "ContentType": "text/plain; charset=utf-8", + "Host": "8-3e5b3069-214a-43ee-8d85-57d72000c19d.sos-ch-dk-2.exo.io", + "Url": "https://8-3e5b3069-214a-43ee-8d85-57d72000c19d.sos-ch-dk-2.exo.io" + }