diff --git a/backend/Api/AMQPReciever/AMQPReciever.cs b/backend/Api/AMQPReciever/AMQPReciever.cs index 0b6cf56..0d76072 100644 --- a/backend/Api/AMQPReciever/AMQPReciever.cs +++ b/backend/Api/AMQPReciever/AMQPReciever.cs @@ -28,13 +28,16 @@ namespace Api.AMQPReciever factory.HostName = _configuration["AMQP:host"]; factory.Port = Convert.ToInt32(_configuration["AMQP:port"]); + // Connecting to our rabbitmq and after that it create's a channel where you can connect to a queue using var conn = await factory.CreateConnectionAsync(); Console.WriteLine("AMQPClien connected"); using var channel = await conn.CreateChannelAsync(); + // Here we connect to the queue through the channel that got created earlier await channel.QueueDeclareAsync(queue: queue, durable: false, exclusive: false, autoDelete: false); Console.WriteLine($"{queue} connected"); + // Everytime a message is recieved from the queue it goes into this consumer.ReceivedAsync var consumer = new AsyncEventingBasicConsumer(channel); consumer.ReceivedAsync += (model, ea) => { @@ -44,15 +47,18 @@ namespace Api.AMQPReciever var messageReceive = JsonSerializer.Deserialize<MQTTMessageReceive>(message); - if (messageReceive == null || messageReceive.temperature == 0 || messageReceive.device_id == null || messageReceive.timestamp == 0) + // Checks if the message has the data we need + if (messageReceive == null || messageReceive.device_id == null || messageReceive.timestamp == 0) { return Task.CompletedTask; } + // Convert to the model we use in the database and gets the device from the database that is used for getting the current set temphigh and templow TemperatureLogs newLog = new TemperatureLogs(); string refernceId = messageReceive.device_id; var device = _dbAccess.ReadDevice(refernceId); + // Checks if the device exist if it doesn't it throws the data away if (device == null) { return Task.CompletedTask; } newLog.Temperature = messageReceive.temperature; @@ -60,11 +66,13 @@ namespace Api.AMQPReciever newLog.TempHigh = device.TempHigh; newLog.TempLow = device.TempLow; + // Send the data to dbaccess to be saved _dbAccess.CreateLog(newLog, refernceId); return Task.CompletedTask; }; + // Consumes the data in the queue await channel.BasicConsumeAsync(queue, true, consumer); Console.WriteLine("Press enter to exit."); diff --git a/backend/Api/DBAccess/DBAccess.cs b/backend/Api/DBAccess/DBAccess.cs index ad83328..8ced21d 100644 --- a/backend/Api/DBAccess/DBAccess.cs +++ b/backend/Api/DBAccess/DBAccess.cs @@ -18,6 +18,11 @@ namespace Api.DBAccess _context = context; } + /// <summary> + /// Creates a user using entityframework core + /// </summary> + /// <param name="user">Need the entire user obj</param> + /// <returns>returns the true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns> public async Task<IActionResult> CreateUser(User user) { var users = await _context.Users.ToListAsync(); @@ -43,6 +48,11 @@ namespace Api.DBAccess return new ConflictObjectResult(new { message = "Could not save to databse" }); } + /// <summary> + /// Returns a user that matches either the email or username + /// </summary> + /// <param name="login">Has a username or email and a password here the password is not used</param> + /// <returns>(user) that matches the login</returns> public async Task<User> Login(Login login) { User user = new User(); @@ -59,11 +69,18 @@ namespace Api.DBAccess return user; } + // Returns a user according to userID public async Task<User> ReadUser(int userId) { return await _context.Users.FirstOrDefaultAsync(u => u.Id == userId); } + /// <summary> + /// Updates the user in the database + /// </summary> + /// <param name="user">Contains the updated user info</param> + /// <param name="userId">Has the id for the user that is to be updated</param> + /// <returns>returns the updated user in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns> public async Task<IActionResult> UpdateUser(User user, int userId) { var profile = await _context.Users.FirstOrDefaultAsync(u => u.Id == userId); @@ -97,6 +114,11 @@ namespace Api.DBAccess return new ConflictObjectResult(new { message = "Could not save to database" }); } + /// <summary> + /// Deletes a user from the database + /// </summary> + /// <param name="userId">The Id of the user that is to be deleted</param> + /// <returns>returns the true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns> public async Task<IActionResult> DeleteUser(int userId) { var user = await _context.Users.Include(u => u.Devices).FirstOrDefaultAsync(u => u.Id == userId); @@ -120,6 +142,7 @@ namespace Api.DBAccess return new ConflictObjectResult(new { message = "Invalid user" }); } + // Returns devices according to userID public async Task<List<Device>> ReadDevices(int userId) { var user = await _context.Users.Include(u => u.Devices).FirstOrDefaultAsync(u => u.Id == userId); @@ -131,6 +154,12 @@ namespace Api.DBAccess return devices; } + /// <summary> + /// Creates a user using entityframework core + /// </summary> + /// <param name="device">The device that is going to be created</param> + /// <param name="userId">The user that owns the device</param> + /// <returns>returns the true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns> public async Task<IActionResult> CreateDevice(Device device, int userId) { var user = await _context.Users.Include(u => u.Devices).FirstOrDefaultAsync(u => u.Id == userId); @@ -147,17 +176,25 @@ namespace Api.DBAccess return new ConflictObjectResult(new { message = "Could not save to database" }); } - + + // Returns a device according to userID public async Task<Device> ReadDevice(int deviceId) { return await _context.Devices.FirstOrDefaultAsync(d => d.Id == deviceId); } + // Returns a device according to userID public Device ReadDevice(string refenreId) { return _context.Devices.FirstOrDefault(d => d.ReferenceId == refenreId); } + /// <summary> + /// Updates a device in the database + /// </summary> + /// <param name="device">Contains the updated device info</param> + /// <param name="deviceId">Has the id for the device that is to be updated</param> + /// <returns>returns the updated device in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns> public async Task<IActionResult> UpdateDevice(Device device, int deviceId) { var device1 = await _context.Devices.FirstOrDefaultAsync(u => u.Id == deviceId); @@ -179,6 +216,11 @@ namespace Api.DBAccess return new ConflictObjectResult(new { message = "Could not save to database" }); } + /// <summary> + /// Returns the logs from the device + /// </summary> + /// <param name="deviceId">Has the id for the device that the los belong too</param> + /// <returns></returns> public async Task<List<TemperatureLogs>> ReadLogs(int deviceId) { var device = await _context.Devices.Include(d => d.Logs).FirstOrDefaultAsync(d => d.Id == deviceId); @@ -190,6 +232,11 @@ namespace Api.DBAccess return logs; } + /// <summary> + /// Creates a new log + /// </summary> + /// <param name="temperatureLogs">the new log</param> + /// <param name="referenceId">the referenceId that belongs too the device that recoded the log</param> public async void CreateLog(TemperatureLogs temperatureLogs, string referenceId) { var device = await _context.Devices.Include(d => d.Logs).FirstOrDefaultAsync(d => d.ReferenceId == referenceId); @@ -202,6 +249,7 @@ namespace Api.DBAccess await _context.SaveChangesAsync(); } + // Does a health check on the database access public async Task<bool> Test() { return _context.Database.CanConnect(); diff --git a/backend/Api/MQTTReciever/MQTTReciever.cs b/backend/Api/MQTTReciever/MQTTReciever.cs index aa0931d..8c72341 100644 --- a/backend/Api/MQTTReciever/MQTTReciever.cs +++ b/backend/Api/MQTTReciever/MQTTReciever.cs @@ -26,12 +26,14 @@ namespace Api.MQTTReciever using (mqttClient = mqttFactory.CreateMqttClient()) { + // Entering our values for conecting to MQTT var mqttClientOptions = new MqttClientOptionsBuilder() .WithTcpServer($"{_configuration["MQTT:host"]}", Convert.ToInt32(_configuration["MQTT:port"])) .WithCredentials($"{_configuration["MQTT:username"]}", $"{_configuration["MQTT:password"]}") .WithCleanSession() .Build(); + // Everytime a message is recieved from the queue it goes into this mqttClient.ApplicationMessageReceivedAsync // Setup message handling before connecting so that queued messages // are also handled properly. When there is no event handler attached all // received messages get lost. @@ -41,35 +43,38 @@ namespace Api.MQTTReciever string sensorData = Encoding.UTF8.GetString(e.ApplicationMessage.Payload); - var mqttMessageReceive = JsonSerializer.Deserialize<MQTTMessageReceive>(sensorData); + var messageReceive = JsonSerializer.Deserialize<MQTTMessageReceive>(sensorData); - if (mqttMessageReceive == null || mqttMessageReceive.temperature == 0 || mqttMessageReceive.device_id == null || mqttMessageReceive.timestamp == 0) + // Checks if the message has the data we need + if (messageReceive == null || messageReceive.device_id == null || messageReceive.timestamp == 0) { return Task.CompletedTask; } + // Convert to the model we use in the database and gets the device from the database that is used for getting the current set temphigh and templow TemperatureLogs newLog = new TemperatureLogs(); - string refernceId = mqttMessageReceive.device_id; + string refernceId = messageReceive.device_id; var device = _dbAccess.ReadDevice(refernceId); + // Checks if the device exist if it doesn't it throws the data away if (device == null) { return Task.CompletedTask; } - newLog.Temperature = mqttMessageReceive.temperature; - newLog.Date = DateTimeOffset.FromUnixTimeSeconds(mqttMessageReceive.timestamp).DateTime; + newLog.Temperature = messageReceive.temperature; + newLog.Date = DateTimeOffset.FromUnixTimeSeconds(messageReceive.timestamp).DateTime; newLog.TempHigh = device.TempHigh; newLog.TempLow = device.TempLow; + // Send the data to dbaccess to be saved _dbAccess.CreateLog(newLog, refernceId); return Task.CompletedTask; }; - + // Starts the connection to rabbitmq await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None); Console.WriteLine("mqttClient"); - //var mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder().WithTopicTemplate(topic).Build(); - + // Subscribes to our topic await mqttClient.SubscribeAsync("temperature"); Console.WriteLine("MQTT client subscribed to topic."); diff --git a/backend/Api/Program.cs b/backend/Api/Program.cs index 2cd40db..8ab6897 100644 --- a/backend/Api/Program.cs +++ b/backend/Api/Program.cs @@ -12,7 +12,7 @@ class Program public static void Main(string[] args) { var app = CreateWebHostBuilder(args).Build(); - + string rabbitMQ = "AMQP"; // This value has to be either "AMQP" or "MQTT" RunMigrations(app); @@ -24,11 +24,17 @@ class Program var configuration = services.GetRequiredService<IConfiguration>(); var dbAccess = services.GetRequiredService<DbAccess>(); - //AMQPReciever amqp = new AMQPReciever(configuration, dbAccess); - //amqp.Handle_Received_Application_Message().Wait(); - - MQTTReciever mqtt = new MQTTReciever(configuration, dbAccess); - mqtt.Handle_Received_Application_Message().Wait(); + // Choose to either connect AMQP or MQTT + if (rabbitMQ == "AMQP") + { + AMQPReciever amqp = new AMQPReciever(configuration, dbAccess); + amqp.Handle_Received_Application_Message().Wait(); + } + else if (rabbitMQ == "MQTT") + { + MQTTReciever mqtt = new MQTTReciever(configuration, dbAccess); + mqtt.Handle_Received_Application_Message().Wait(); + } } }); diff --git a/backend/ConsoleApp1/ConsoleApp1.csproj b/backend/ConsoleApp1/ConsoleApp1.csproj deleted file mode 100644 index 7dfb515..0000000 --- a/backend/ConsoleApp1/ConsoleApp1.csproj +++ /dev/null @@ -1,14 +0,0 @@ -<Project Sdk="Microsoft.NET.Sdk"> - - <PropertyGroup> - <OutputType>Exe</OutputType> - <TargetFramework>net8.0</TargetFramework> - <ImplicitUsings>enable</ImplicitUsings> - <Nullable>enable</Nullable> - </PropertyGroup> - - <ItemGroup> - <PackageReference Include="RabbitMQ.Client" Version="7.1.2" /> - </ItemGroup> - -</Project> diff --git a/backend/ConsoleApp1/ConsoleApp1.sln b/backend/ConsoleApp1/ConsoleApp1.sln deleted file mode 100644 index b1ff789..0000000 --- a/backend/ConsoleApp1/ConsoleApp1.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.9.34607.119 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp1", "ConsoleApp1.csproj", "{0BC93CF2-F92D-4DD6-83BE-A985CBB74960}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {0BC93CF2-F92D-4DD6-83BE-A985CBB74960}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0BC93CF2-F92D-4DD6-83BE-A985CBB74960}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0BC93CF2-F92D-4DD6-83BE-A985CBB74960}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0BC93CF2-F92D-4DD6-83BE-A985CBB74960}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {55EE0E94-4585-4E79-AC67-4B0E809E99AB} - EndGlobalSection -EndGlobal diff --git a/backend/ConsoleApp1/Program.cs b/backend/ConsoleApp1/Program.cs deleted file mode 100644 index a5e0e23..0000000 --- a/backend/ConsoleApp1/Program.cs +++ /dev/null @@ -1,52 +0,0 @@ -using RabbitMQ.Client; -using RabbitMQ.Client.Events; -using System.Text; - - -var factory = new ConnectionFactory(); -var queue = "test"; - - -factory.UserName = "h5"; -factory.Password = "Merc1234"; -factory.HostName = "10.135.51.116"; -factory.Port = 5672; - -using var conn = await factory.CreateConnectionAsync(); -Console.WriteLine("AMQPClien connected"); -using var channel = await conn.CreateChannelAsync(); - -await channel.QueueDeclareAsync(queue: queue, durable: false, exclusive: false, autoDelete: false); -Console.WriteLine($"{queue} connected"); - -var consumer = new AsyncEventingBasicConsumer(channel); -consumer.ReceivedAsync += (model, ea) => -{ - Console.WriteLine("Received application message."); - var body = ea.Body.ToArray(); - var message = Encoding.UTF8.GetString(body); - Console.WriteLine(message); - - return Task.CompletedTask; -}; - -await channel.BasicConsumeAsync(queue, true, consumer); - - -const string message = "Hello World!"; -var body = Encoding.UTF8.GetBytes(message); -await channel.BasicPublishAsync(exchange: string.Empty, routingKey: queue, body: body); -Console.WriteLine(" Press enter to continue."); -Console.ReadLine(); -await channel.BasicPublishAsync(exchange: string.Empty, routingKey: queue, body: body); -Console.WriteLine(" Press enter to continue."); -Console.ReadLine(); -await channel.BasicPublishAsync(exchange: string.Empty, routingKey: queue, body: body); -Console.WriteLine(" Press enter to continue."); -Console.ReadLine(); -await channel.BasicPublishAsync(exchange: string.Empty, routingKey: queue, body: body); -Console.WriteLine(" Press enter to continue."); -Console.ReadLine(); -await channel.BasicPublishAsync(exchange: string.Empty, routingKey: queue, body: body); -Console.WriteLine(" Press enter to exit."); -Console.ReadLine(); \ No newline at end of file