Added mqtt camera handler
This commit is contained in:
136
UCS_Status_Monitor.UnitTest/MQTT_Test.cs
Normal file
136
UCS_Status_Monitor.UnitTest/MQTT_Test.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace UCS_Status_Monitor.UnitTest
|
||||
{
|
||||
[TestClass]
|
||||
public class MQTT_Test
|
||||
{
|
||||
private static readonly Dictionary<string, string> inMemorySettings = new()
|
||||
{
|
||||
{ "Database", "UCSStatusMonitorTestDB.db" },
|
||||
{ "SectionName:SomeKey", "SectionValue" },
|
||||
};
|
||||
private readonly IConfiguration configuration = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(inMemorySettings)
|
||||
.Build();
|
||||
|
||||
//[TestMethod]
|
||||
//public void ConnectionstatesPacketTest()
|
||||
//{
|
||||
// ILogger<TelemetryService> logger = Mock.Of<ILogger<TelemetryService>>();
|
||||
// ITelegramBotService telegrambot = Mock.Of<ITelegramBotService>();
|
||||
// TelemetryService telemetryWorker = new(logger, configuration, telegrambot);
|
||||
|
||||
// Models.TelemetryPacket telemetryPacket = new()
|
||||
// {
|
||||
// ComputerName = "PXX - UCS99",
|
||||
// };
|
||||
|
||||
// //list == null
|
||||
// telemetryWorker.ProcessPacket(telemetryPacket);
|
||||
// Assert.AreEqual(1, telemetryWorker.SystemCount());
|
||||
// Assert.AreEqual(0, telemetryWorker.DeviceCount());
|
||||
|
||||
// //empty list
|
||||
// telemetryPacket.Connectionstates = new List<Models.ConnectionState>();
|
||||
// telemetryWorker.ProcessPacket(telemetryPacket);
|
||||
// Assert.AreEqual(0, telemetryWorker.DeviceCount("PXX - UCS99"));
|
||||
|
||||
// //list with empty device
|
||||
// telemetryPacket.Connectionstates.Add(new Models.ConnectionState() { });
|
||||
// telemetryWorker.ProcessPacket(telemetryPacket);
|
||||
// Assert.AreEqual(0, telemetryWorker.DeviceCount("PXX - UCS99"));
|
||||
|
||||
// //only ID
|
||||
// telemetryPacket.Connectionstates.Add(new Models.ConnectionState() { ID = "DX" });
|
||||
// telemetryWorker.ProcessPacket(telemetryPacket);
|
||||
// Assert.AreEqual(1, telemetryWorker.DeviceCount("PXX - UCS99"));
|
||||
|
||||
// telemetryPacket.Connectionstates.Add(new Models.ConnectionState() { ID = "D1", Name = "DienstIngang", State = true, LastStateChange = DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss") });
|
||||
// telemetryWorker.ProcessPacket(telemetryPacket);
|
||||
// Assert.AreEqual(2, telemetryWorker.DeviceCount("PXX - UCS99"));
|
||||
|
||||
// telemetryPacket.Connectionstates.Add(new Models.ConnectionState() { ID = "D2", Name = "AchterIngang", State = true, LastStateChange = DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss") });
|
||||
// telemetryWorker.ProcessPacket(telemetryPacket);
|
||||
// Assert.AreEqual(3, telemetryWorker.DeviceCount("PXX - UCS99"));
|
||||
|
||||
// //Bestaat all
|
||||
// telemetryPacket.Connectionstates.Add(new Models.ConnectionState() { ID = "D2", Name = "AchterIngang", State = true, LastStateChange = DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss") });
|
||||
// telemetryWorker.ProcessPacket(telemetryPacket);
|
||||
// Assert.AreEqual(3, telemetryWorker.DeviceCount("PXX - UCS99"));
|
||||
//}
|
||||
|
||||
[TestMethod]
|
||||
public void Parse_Teltonika_Json()
|
||||
{
|
||||
string json = "";
|
||||
var message = TeltonikaMessage.Deserialize(json);
|
||||
Assert.IsNull(message);
|
||||
|
||||
json = "lufhy2q9478ry78aq39 f3g789fy egy 3ghuieg heasuhg egh eisulgh uielg hsalgire";
|
||||
message = TeltonikaMessage.Deserialize(json);
|
||||
Assert.IsNull(message);
|
||||
|
||||
json = "[\"Temp\":\"360\",\"Uptime\":\"100680\",\"ThisMonthRX\":\"631408118\",\"ThisMonthTX\":\"967449262\",\"RSSI\":\"-62\",\"LastMonthRX\":\"63108118\",\"LastMonthTX\":\"94926132\",\"WanIp\":\"178,224,157,191\"]";
|
||||
message = TeltonikaMessage.Deserialize(json);
|
||||
Assert.IsNotNull(message);
|
||||
Assert.IsInstanceOfType(message, typeof(TeltonikaMessage));
|
||||
|
||||
//Temp
|
||||
Assert.AreEqual(36.0, message.TempValue());
|
||||
Assert.AreEqual("36℃", message.Temp);
|
||||
//Uptime
|
||||
var uptime = TimeSpan.FromSeconds(100680);
|
||||
Assert.AreEqual(uptime, message.UptimeValue());
|
||||
Assert.AreEqual("1 days 3 hours 58 min 0 sec", message.Uptime);
|
||||
//ThisMonthRX
|
||||
Assert.AreEqual((UInt32)631408118, message.ThisMonthRX);
|
||||
//ThisMonthTX
|
||||
Assert.AreEqual((UInt32)967449262, message.ThisMonthTX);
|
||||
//LastMonthRX
|
||||
Assert.AreEqual((UInt32)63108118, message.LastMonthRX);
|
||||
//LastMonthTX
|
||||
Assert.AreEqual((UInt32)94926132, message.LastMonthTX);
|
||||
//RSSI
|
||||
Assert.AreEqual(-62, message.RSSI);
|
||||
//WanIp
|
||||
Assert.AreEqual("178.224.157.191", message.WanIp);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Parse_AxisCam_Json()
|
||||
{
|
||||
string json = "";
|
||||
var message = AxisCamMessage.Deserialize(json);
|
||||
Assert.IsNull(message);
|
||||
|
||||
json = "lufhy2q9478ry78aq39 f3g789fy egy 3ghuieg heasuhg egh eisulgh uielg hsalgire";
|
||||
message = AxisCamMessage.Deserialize(json);
|
||||
Assert.IsNull(message);
|
||||
|
||||
json = "{ \"serialNumber\": \"B8A44F4A646C\",\"timestamp\": \"2022-07-26T08:33:59.336107Z\",\"connected\": true,\"description\": \"Connected\"}";
|
||||
message = AxisCamMessage.Deserialize(json);
|
||||
Assert.IsNotNull(message);
|
||||
Assert.IsInstanceOfType(message, typeof(AxisCamMessage));
|
||||
|
||||
//SerialNumber
|
||||
Assert.AreEqual("B8A44F4A646C", message.SerialNumber);
|
||||
//Timestamp
|
||||
Assert.AreEqual("26-7-2022 08:33:59", message.Timestamp.ToString());
|
||||
//Connected
|
||||
Assert.AreEqual(true, message.Connected);
|
||||
//Description
|
||||
Assert.AreEqual("Connected", message.Description);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -464,5 +464,51 @@ namespace UCS_Status_Monitor.Controllers
|
||||
|
||||
return View(sensors.ToList());
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
public ActionResult Cameras()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
public async Task<JsonResult> GetCamerasTable()
|
||||
{
|
||||
using var dbContext = new MonitorDbContext(_configuration);
|
||||
List<CameraTableModel> camsList = await dbContext.AxisCams
|
||||
.OrderByDescending(o => o.Device)
|
||||
.Select(a => new CameraTableModel
|
||||
{
|
||||
//LastMessageTime = Helpers.Html.FormatDateTime(a.LastMessageTime),
|
||||
TableColor = a.TableColor(),
|
||||
Device = a.Device,
|
||||
Location = a.Location,
|
||||
SerialNumber = a.SerialNumber,
|
||||
Timestamp = a.Timestamp,
|
||||
Connected = a.Connected,
|
||||
Description = a.Description
|
||||
}).ToListAsync();
|
||||
return Json(camsList);
|
||||
|
||||
|
||||
|
||||
//List<Router> routers = await dbContext.Routers
|
||||
// //.Include(d => d.Devices)
|
||||
// .OrderByDescending(o => o.Location)
|
||||
// .ToListAsync();
|
||||
// //.Select(a => new HomeTableModel
|
||||
// //{
|
||||
// // //ComputerName = a.ComputerName,
|
||||
// // ComputerName = a.ComputerNameWithError(),
|
||||
// // ConfigFileName = a.ConfigFileName,
|
||||
// // Uptime = a.Uptime,
|
||||
// // LastMessageTime = Helpers.Html.FormatDateTime(a.LastMessageTime),
|
||||
// // TableColor = a.TableColor(),
|
||||
// //}).ToListAsync();
|
||||
|
||||
//return Json(routers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@ namespace UCS_Status_Monitor.Database
|
||||
public DbSet<Models.Logging> Loggings { get; set; }
|
||||
public DbSet<Models.EventLogError> Errors { get; set; }
|
||||
public DbSet<Models.Sensor> Sensors { get; set; }
|
||||
public DbSet<Models.Router> Routers { get; set; }
|
||||
public DbSet<Models.AxisCam> AxisCams { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
@@ -42,6 +44,8 @@ namespace UCS_Status_Monitor.Database
|
||||
modelBuilder.Entity<Models.Logging>().ToTable("Loggings");
|
||||
modelBuilder.Entity<Models.EventLogError>().ToTable("Errors");
|
||||
modelBuilder.Entity<Models.Sensor>().ToTable("Sensors");
|
||||
modelBuilder.Entity<Models.Router>().ToTable("Routers");
|
||||
modelBuilder.Entity<Models.AxisCam>().ToTable("AxisCams");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
48
UCS_Status_Monitor/MQTT/AxisCamMessage.cs
Normal file
48
UCS_Status_Monitor/MQTT/AxisCamMessage.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace UCS_Status_Monitor
|
||||
{
|
||||
public class AxisCamMessage
|
||||
{
|
||||
//{
|
||||
// "serialNumber": "B8A44F4A646C",
|
||||
// "timestamp": "2022-07-26T08:33:59.336107Z",
|
||||
// "connected": true,
|
||||
// "description": "Connected"
|
||||
//}
|
||||
|
||||
public static AxisCamMessage Deserialize(string json)
|
||||
{
|
||||
try
|
||||
{
|
||||
return JsonSerializer.Deserialize<AxisCamMessage>(json, new JsonSerializerOptions()
|
||||
{
|
||||
NumberHandling = JsonNumberHandling.AllowReadingFromString
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonPropertyName("serialNumber")]
|
||||
public string SerialNumber { get; set; }
|
||||
|
||||
[JsonPropertyName("timestamp")]
|
||||
public DateTime Timestamp { get; set; }
|
||||
|
||||
[JsonPropertyName("connected")]
|
||||
public bool Connected { get; set; }
|
||||
|
||||
[JsonPropertyName("description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
//public override string ToString()
|
||||
//{
|
||||
// return $"serialNumber: {SerialNumber}{Environment.NewLine}timestamp: {Timestamp}{Environment.NewLine}connected: {Connected}{Environment.NewLine}description: {Description}{Environment.NewLine}";
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -2,19 +2,21 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MQTTnet;
|
||||
using MQTTnet.Client.Connecting;
|
||||
using MQTTnet.Client.Disconnecting;
|
||||
using MQTTnet.Client.Options;
|
||||
using MQTTnet.Client;
|
||||
using MQTTnet.Extensions.ManagedClient;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using UCS_Status_Monitor.Database;
|
||||
|
||||
namespace UCS_Status_Monitor
|
||||
{
|
||||
@@ -42,196 +44,179 @@ namespace UCS_Status_Monitor
|
||||
//private readonly X509Certificate clientCert = new X509Certificate2("Certs\\server.crt", "Certs\\server.key");
|
||||
private readonly X509Certificate clientCert = new X509Certificate2("Certs\\server.pfx", "12345");
|
||||
|
||||
//private IManagedMqttClient managedMqttClient;
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
var options = new ManagedMqttClientOptionsBuilder()
|
||||
.WithAutoReconnectDelay(TimeSpan.FromSeconds(5))
|
||||
.WithClientOptions(new MqttClientOptionsBuilder()
|
||||
.WithClientId(_mqttconfig.ClientID)
|
||||
.WithTcpServer(_mqttconfig.BrokerAddress, _mqttconfig.BrokerPort)
|
||||
.WithCredentials(_mqttconfig.Username, _mqttconfig.Password)
|
||||
//.WithProtocolVersion(MQTTnet.Formatter.MqttProtocolVersion.V500)
|
||||
.WithTls(new MqttClientOptionsBuilderTlsParameters
|
||||
{
|
||||
UseTls = true,
|
||||
SslProtocol = System.Security.Authentication.SslProtocols.Tls12,
|
||||
var mqttFactory = new MqttFactory();
|
||||
using (var managedMqttClient = mqttFactory.CreateManagedMqttClient())
|
||||
{
|
||||
var managedMqttClientOptions = new ManagedMqttClientOptionsBuilder()
|
||||
.WithClientOptions(new MqttClientOptionsBuilder()
|
||||
.WithClientId(_mqttconfig.ClientID)
|
||||
.WithTcpServer(_mqttconfig.BrokerAddress, _mqttconfig.BrokerPort)
|
||||
.WithCredentials(_mqttconfig.Username, _mqttconfig.Password)
|
||||
//.WithProtocolVersion(MQTTnet.Formatter.MqttProtocolVersion.V500)
|
||||
.WithTls(new MqttClientOptionsBuilderTlsParameters
|
||||
{
|
||||
UseTls = true,
|
||||
SslProtocol = System.Security.Authentication.SslProtocols.Tls12,
|
||||
|
||||
CertificateValidationHandler = (certContext) =>
|
||||
{
|
||||
X509Chain chain = new X509Chain();
|
||||
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
|
||||
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
|
||||
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
|
||||
chain.ChainPolicy.VerificationTime = DateTime.Now;
|
||||
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 0);
|
||||
chain.ChainPolicy.CustomTrustStore.Add(caCrt);
|
||||
chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
|
||||
CertificateValidationHandler = (certContext) =>
|
||||
{
|
||||
X509Chain chain = new X509Chain();
|
||||
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
|
||||
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
|
||||
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
|
||||
chain.ChainPolicy.VerificationTime = DateTime.Now;
|
||||
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 0);
|
||||
chain.ChainPolicy.CustomTrustStore.Add(caCrt);
|
||||
chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
|
||||
|
||||
// convert provided X509Certificate to X509Certificate2
|
||||
var x5092 = new X509Certificate2(certContext.Certificate);
|
||||
return chain.Build(x5092);
|
||||
},
|
||||
Certificates = new List<X509Certificate>()
|
||||
// convert provided X509Certificate to X509Certificate2
|
||||
var x5092 = new X509Certificate2(certContext.Certificate);
|
||||
return chain.Build(x5092);
|
||||
},
|
||||
Certificates = new List<X509Certificate>()
|
||||
{
|
||||
clientCert
|
||||
}
|
||||
})
|
||||
.WithCleanSession()
|
||||
.Build())
|
||||
.Build();
|
||||
|
||||
IManagedMqttClient mqttClient = new MqttFactory().CreateManagedMqttClient();
|
||||
|
||||
//mqttClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(OnConnected);
|
||||
mqttClient.ConnectingFailedHandler = new ConnectingFailedHandlerDelegate(OnConnectingFailed);
|
||||
//mqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(OnDisconnected);
|
||||
|
||||
mqttClient.UseApplicationMessageReceivedHandler(async e =>
|
||||
{
|
||||
await MessageReceived(e);
|
||||
});
|
||||
await mqttClient.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("#").Build());
|
||||
|
||||
|
||||
|
||||
|
||||
await mqttClient.StartAsync(options);
|
||||
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
var message = new MqttApplicationMessageBuilder()
|
||||
.WithTopic("MQTTNet/Test")
|
||||
.WithPayload("{\"Message\":\"Hello world\"}")
|
||||
.WithExactlyOnceQoS()
|
||||
.WithRetainFlag()
|
||||
})
|
||||
.WithCleanSession()
|
||||
.Build())
|
||||
.Build();
|
||||
|
||||
await mqttClient.PublishAsync(message, stoppingToken);
|
||||
managedMqttClient.ConnectingFailedAsync += OnConnectingFailed;
|
||||
managedMqttClient.ApplicationMessageReceivedAsync += OnApplicationMessageReceived;
|
||||
|
||||
//await mqttClient.PublishAsync("Topic", "Hello");
|
||||
await managedMqttClient.SubscribeAsync("#");
|
||||
await managedMqttClient.StartAsync(managedMqttClientOptions);
|
||||
|
||||
//SpinWait.SpinUntil(() => managedMqttClient.PendingApplicationMessagesCount == 0, 10000);
|
||||
//Debug.WriteLine($"Pending messages = {managedMqttClient.PendingApplicationMessagesCount}");
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
// var message = new MqttApplicationMessageBuilder()
|
||||
// .WithTopic("MQTTNet/Test")
|
||||
// .WithPayload("{\"Message\":\"Hello world\"}")
|
||||
// .WithRetainFlag()
|
||||
// .Build();
|
||||
|
||||
// await mqttClient.EnqueueAsync(message);
|
||||
|
||||
// //SpinWait.SpinUntil(() => managedMqttClient.PendingApplicationMessagesCount == 0, 10000);
|
||||
// //Debug.WriteLine($"Pending messages = {managedMqttClient.PendingApplicationMessagesCount}");
|
||||
|
||||
|
||||
Debug.WriteLine($"Pending messages = {mqttClient.PendingApplicationMessagesCount}");
|
||||
// Debug.WriteLine($"Pending messages = {mqttClient.PendingApplicationMessagesCount}");
|
||||
|
||||
await Task.Delay(30000, stoppingToken);
|
||||
await Task.Delay(30000, stoppingToken);
|
||||
}
|
||||
}
|
||||
mqttClient.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine(ex.ToString());
|
||||
_logger.LogError(ex, "Setting up mqttclient failed");
|
||||
//throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//static void OnConnected(MqttClientConnectedEventArgs obj)
|
||||
//{
|
||||
// Debug.WriteLine("Successfully connected.");
|
||||
//}
|
||||
|
||||
private void OnConnectingFailed(ManagedProcessFailedEventArgs obj)
|
||||
private async Task<Task> OnConnectingFailed(ConnectingFailedEventArgs args)
|
||||
{
|
||||
Debug.WriteLine("Couldn't connect to broker." + obj.Exception.Message);
|
||||
_logger.LogError(obj.Exception, "Connect to broker failed.");
|
||||
|
||||
Debug.WriteLine("Couldn't connect to broker." + args.Exception.Message);
|
||||
_logger.LogError(args.Exception, "Connect to broker failed.");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
//static void OnDisconnected(MqttClientDisconnectedEventArgs obj)
|
||||
//{
|
||||
// Debug.WriteLine("Successfully disconnected. " + obj.Exception.Message);
|
||||
//}
|
||||
private async Task<Task> OnApplicationMessageProcessed(ApplicationMessageProcessedEventArgs args)
|
||||
{
|
||||
Debug.WriteLine("OnApplicationMessageProcessed");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task MessageReceived(MqttApplicationMessageReceivedEventArgs args)
|
||||
private async Task<Task> OnApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs args)
|
||||
{
|
||||
//Debug.WriteLine("### RECEIVED APPLICATION MESSAGE ###");
|
||||
//Debug.WriteLine($"+ Topic = {args.ApplicationMessage.Topic}");
|
||||
//Debug.WriteLine($"+ Payload = {Encoding.UTF8.GetString(args.ApplicationMessage.Payload)}");
|
||||
//Debug.WriteLine($"+ QoS = {args.ApplicationMessage.QualityOfServiceLevel}");
|
||||
//Debug.WriteLine($"+ Retain = {args.ApplicationMessage.Retain}");
|
||||
//Debug.WriteLine("----------------");
|
||||
//Debug.WriteLine("-------------------------------");
|
||||
|
||||
MqttMessage mqttMessage = new MqttMessage(args.ApplicationMessage.Topic, Encoding.UTF8.GetString(args.ApplicationMessage.Payload));
|
||||
var parts = args.ApplicationMessage.Topic.Split('/');
|
||||
string location = parts[0];
|
||||
string device = parts[1];
|
||||
|
||||
//Debug.WriteLine($"Topic = {mqttMessage.Topic}");
|
||||
Debug.WriteLine($"Location = {mqttMessage.Location}");
|
||||
Debug.WriteLine($"Device = {mqttMessage.Device}");
|
||||
Debug.WriteLine($"JSON = {mqttMessage.Json}");
|
||||
foreach (var item in mqttMessage.JsonValues)
|
||||
{
|
||||
Debug.WriteLine($"+ {item.Key} - {item.Value}");
|
||||
if (device.Contains("ROUT"))
|
||||
{
|
||||
TeltonikaMessage teltonikaMessage = TeltonikaMessage.Deserialize(Encoding.UTF8.GetString(args.ApplicationMessage.Payload));
|
||||
if (teltonikaMessage == null)
|
||||
{
|
||||
_logger.LogError($"Teltonika Mqtt error - {args.ApplicationMessage.Payload}");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
using var dbContext = new MonitorDbContext(_configuration);
|
||||
Models.Router router = new()
|
||||
{
|
||||
Location = location,
|
||||
Device = device,
|
||||
Temperature = teltonikaMessage.TempValue(),
|
||||
Uptime = teltonikaMessage.UptimeValue(),
|
||||
ThisMonthRX = teltonikaMessage.ThisMonthRX,
|
||||
ThisMonthTX = teltonikaMessage.ThisMonthTX,
|
||||
LastMonthRX = teltonikaMessage.LastMonthRX,
|
||||
LastMonthTX = teltonikaMessage.LastMonthTX,
|
||||
RSSI = teltonikaMessage.RSSI,
|
||||
WanIp = teltonikaMessage.WanIp
|
||||
};
|
||||
dbContext.Routers.Add(router);
|
||||
await dbContext.SaveChangesAsync();
|
||||
|
||||
await _telegramBot.Send($"RX:{teltonikaMessage.ThisMonthRX / 1000000}MB TX:{teltonikaMessage.ThisMonthTX / 1000000}MB");
|
||||
}
|
||||
Debug.WriteLine("--------------------------");
|
||||
|
||||
//if (args.ApplicationMessage.Topic == "5688HT002/S12ROUT01")
|
||||
//{
|
||||
// //Debug.WriteLine("Router message");
|
||||
// TeltronikaRouterMessage(Encoding.UTF8.GetString(args.ApplicationMessage.Payload));
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//private void TeltronikaRouterMessage(string json)
|
||||
//{
|
||||
// //"time":"14/03/2022 10:07:14","LastMonthRX":"303644051"
|
||||
|
||||
// //var result = JsonSerializer.Deserialize<List<KeyValuePair<string, string>>>(json);
|
||||
// var values = JsonSerializer.Deserialize<Dictionary<string, string>>(json);
|
||||
|
||||
// foreach (var pair in values)
|
||||
// {
|
||||
// Debug.WriteLine($"Key:{pair.Key} - value:{pair.Value}");
|
||||
// }
|
||||
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class MqttMessage
|
||||
{
|
||||
public string Topic { get; set; }
|
||||
public string Location { get; set; }
|
||||
public string Device { get; set; }
|
||||
public string Json { get; set; }
|
||||
public Dictionary<string, string> JsonValues { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
|
||||
public MqttMessage(string topic, string json)
|
||||
{
|
||||
Topic = topic;
|
||||
var parts = topic.Split('/');
|
||||
Location = parts[0];
|
||||
Device = parts[1];
|
||||
|
||||
Json = json;
|
||||
|
||||
//{"serialNumber": "B8A44F4A646C", "timestamp": "2022-03-11T22:07:13.581119Z", "connected": true, "description": "Connected"}
|
||||
//{"time":"14/03/2022 11:08:15","LastMonthRX":"303648259"}
|
||||
|
||||
try
|
||||
if (device.Contains("CAM"))
|
||||
{
|
||||
JsonValues = JsonSerializer.Deserialize<Dictionary<string, string>>(json);
|
||||
AxisCamMessage axisCamMessage = AxisCamMessage.Deserialize(Encoding.UTF8.GetString(args.ApplicationMessage.Payload));
|
||||
if (axisCamMessage == null)
|
||||
{
|
||||
_logger.LogError($"Axis cam Mqtt error - {args.ApplicationMessage.Payload}");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
using var dbContext = new MonitorDbContext(_configuration);
|
||||
var existingCam = dbContext.AxisCams.Where(x => x.Location == location && x.Device == device).FirstOrDefault();
|
||||
if (existingCam != null)
|
||||
{
|
||||
if (existingCam.Connected != axisCamMessage.Connected)
|
||||
{
|
||||
await _telegramBot.SendConnectionStatus($"{existingCam.Location} - {existingCam.Device}", axisCamMessage.Connected);
|
||||
}
|
||||
|
||||
//update cam
|
||||
existingCam.SerialNumber = axisCamMessage.SerialNumber;
|
||||
existingCam.Timestamp = axisCamMessage.Timestamp;
|
||||
existingCam.Connected = axisCamMessage.Connected;
|
||||
existingCam.Description = axisCamMessage.Description;
|
||||
dbContext.AxisCams.Update(existingCam);
|
||||
await dbContext.SaveChangesAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
//new cam
|
||||
Models.AxisCam newCam = new()
|
||||
{
|
||||
Location = location,
|
||||
Device = device,
|
||||
SerialNumber = axisCamMessage.SerialNumber,
|
||||
Timestamp = axisCamMessage.Timestamp,
|
||||
Connected = axisCamMessage.Connected,
|
||||
Description = axisCamMessage.Description
|
||||
};
|
||||
dbContext.AxisCams.Add(newCam);
|
||||
await dbContext.SaveChangesAsync();
|
||||
await _telegramBot.Send($"🆕 <b>{newCam.Location} - {newCam.Device}</b> Added");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine(ex.Message);
|
||||
//throw;
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
115
UCS_Status_Monitor/MQTT/TeltonikaMessage.cs
Normal file
115
UCS_Status_Monitor/MQTT/TeltonikaMessage.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace UCS_Status_Monitor
|
||||
{
|
||||
public class TeltonikaMessage
|
||||
{
|
||||
//["Temp":"450","Uptime":"11561053","ThisMonthRX":"244716147","ThisMonthTX":"330139099","RSSI":"-61","LastMonthRX":"953029102","LastMonthTX":"499902102","WanIp":"178,224,90,9"]
|
||||
|
||||
public static TeltonikaMessage Deserialize(string json)
|
||||
{
|
||||
try
|
||||
{
|
||||
json = json.Replace('[', '{');
|
||||
json = json.Replace(']', '}');
|
||||
return JsonSerializer.Deserialize<TeltonikaMessage>(json, new JsonSerializerOptions()
|
||||
{
|
||||
NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private float _temp;
|
||||
public string Temp
|
||||
{
|
||||
get
|
||||
{
|
||||
return $"{_temp}℃";
|
||||
}
|
||||
set
|
||||
{
|
||||
string temp = value.Insert(2, ".");
|
||||
_temp = float.Parse(temp, CultureInfo.InvariantCulture); //use . separator
|
||||
}
|
||||
}
|
||||
public float TempValue()
|
||||
{
|
||||
return _temp;
|
||||
}
|
||||
|
||||
private TimeSpan _uptime;
|
||||
public string Uptime
|
||||
{
|
||||
get
|
||||
{
|
||||
return $"{_uptime.Days} days {_uptime.Hours} hours {_uptime.Minutes} min {_uptime.Seconds} sec";
|
||||
}
|
||||
set
|
||||
{
|
||||
_uptime = TimeSpan.FromSeconds(UInt32.Parse(value));
|
||||
}
|
||||
}
|
||||
public TimeSpan UptimeValue()
|
||||
{
|
||||
return _uptime;
|
||||
}
|
||||
|
||||
//value / 1000000 = MB
|
||||
public UInt32 ThisMonthRX { get; set; }
|
||||
|
||||
//value / 1000000 = MB
|
||||
public UInt32 ThisMonthTX { get; set; }
|
||||
|
||||
//value in dBm
|
||||
public Int32 RSSI { get; set; }
|
||||
|
||||
//value / 1000000 = MB
|
||||
public UInt32 LastMonthRX { get; set; }
|
||||
|
||||
//value / 1000000 = MB
|
||||
public UInt32 LastMonthTX { get; set; }
|
||||
|
||||
private string _wanIP;
|
||||
public string WanIp
|
||||
{
|
||||
get
|
||||
{
|
||||
return _wanIP;
|
||||
}
|
||||
set
|
||||
{
|
||||
_wanIP = value.Replace(',', '.');
|
||||
}
|
||||
}
|
||||
|
||||
//public override string ToString()
|
||||
//{
|
||||
// var sb = new StringBuilder();
|
||||
|
||||
// sb.Append($"Temp = {Temp}");
|
||||
// sb.Append(Environment.NewLine);
|
||||
// sb.Append($"Uptime = {Uptime}");
|
||||
// sb.Append(Environment.NewLine);
|
||||
// sb.Append($"ThisMonthRX = {ThisMonthRX}");
|
||||
// sb.Append(Environment.NewLine);
|
||||
// sb.Append($"ThisMonthTX = {ThisMonthTX}");
|
||||
// sb.Append(Environment.NewLine);
|
||||
// sb.Append($"RSSI = {RSSI} dBm");
|
||||
// sb.Append(Environment.NewLine);
|
||||
// sb.Append($"LastMonthRX = {LastMonthRX}");
|
||||
// sb.Append(Environment.NewLine);
|
||||
// sb.Append($"LastMonthTX = {LastMonthTX}");
|
||||
// sb.Append(Environment.NewLine);
|
||||
// sb.Append($"WanIp = {WanIp}");
|
||||
|
||||
// return sb.ToString();
|
||||
//}
|
||||
}
|
||||
}
|
||||
16
UCS_Status_Monitor/Models/CameraTableModel.cs
Normal file
16
UCS_Status_Monitor/Models/CameraTableModel.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace UCS_Status_Monitor.Models
|
||||
{
|
||||
public class CameraTableModel
|
||||
{
|
||||
public string TableColor { get; set; }
|
||||
|
||||
public string Device { get; set; }
|
||||
public string Location { get; set; }
|
||||
public string SerialNumber { get; set; }
|
||||
public DateTime Timestamp { get; set; }
|
||||
public bool Connected { get; set; }
|
||||
public string Description { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -139,7 +139,7 @@ namespace UCS_Status_Monitor.Models
|
||||
public DateTime Date { get; set; }
|
||||
|
||||
[Display(Name = "Computer name")]
|
||||
public string ComputerName{ get; set; }
|
||||
public string ComputerName { get; set; }
|
||||
|
||||
[Display(Name = "Configfile")]
|
||||
public string Configfile { get; set; }
|
||||
@@ -156,4 +156,62 @@ namespace UCS_Status_Monitor.Models
|
||||
[Display(Name = "Message number")]
|
||||
public Int64 Count { get; set; }
|
||||
}
|
||||
|
||||
public partial class Router
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
[Display(Name = "Location")]
|
||||
public string Location { get; set; }
|
||||
|
||||
[Display(Name = "Device")]
|
||||
public string Device { get; set; }
|
||||
|
||||
[Display(Name = "Temperature")]
|
||||
public float Temperature { get; set; }
|
||||
|
||||
[Display(Name = "Uptime")]
|
||||
public TimeSpan Uptime { get; set; }
|
||||
|
||||
[Display(Name = "This month received")]
|
||||
public UInt32 ThisMonthRX { get; set; }
|
||||
|
||||
[Display(Name = "This month transmitted")]
|
||||
public UInt32 ThisMonthTX { get; set; }
|
||||
|
||||
[Display(Name = "Last month received")]
|
||||
public UInt32 LastMonthRX { get; set; }
|
||||
|
||||
[Display(Name = "Last month transmitted")]
|
||||
public UInt32 LastMonthTX { get; set; }
|
||||
|
||||
[Display(Name = "RSSI")]
|
||||
public Int32 RSSI { get; set; }
|
||||
|
||||
[Display(Name = "Wan ip address")]
|
||||
public string WanIp { get; set; }
|
||||
}
|
||||
|
||||
public partial class AxisCam
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
[Display(Name = "Location")]
|
||||
public string Location { get; set; }
|
||||
|
||||
[Display(Name = "Device")]
|
||||
public string Device { get; set; }
|
||||
|
||||
[Display(Name = "SerialNumber")]
|
||||
public string SerialNumber { get; set; }
|
||||
|
||||
[Display(Name = "Timestamp")]
|
||||
public DateTime Timestamp { get; set; }
|
||||
|
||||
[Display(Name = "Connected")]
|
||||
public bool Connected { get; set; }
|
||||
|
||||
[Display(Name = "Description")]
|
||||
public string Description { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace UCS_Status_Monitor.Models
|
||||
if (sensor.Count.HasValue)
|
||||
{
|
||||
Count = sensor.Count.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsAlarm()
|
||||
@@ -151,4 +151,63 @@ namespace UCS_Status_Monitor.Models
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public partial class Router
|
||||
{
|
||||
public Router() { }
|
||||
|
||||
public Router(TeltonikaMessage message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public string GetTemperature()
|
||||
{
|
||||
return $"{Temperature}℃";
|
||||
}
|
||||
public string GetUptime()
|
||||
{
|
||||
return $"{Uptime.Days} days {Uptime.Hours} hours {Uptime.Minutes} min {Uptime.Seconds} sec";
|
||||
}
|
||||
public string GetThisMonthRX()
|
||||
{
|
||||
return $"{ThisMonthRX / 1000000} MB";
|
||||
}
|
||||
public string GetThisMonthTX()
|
||||
{
|
||||
return $"{ThisMonthTX / 1000000} MB";
|
||||
}
|
||||
public string ThisMonthTotal()
|
||||
{
|
||||
return $"{(ThisMonthTX + ThisMonthRX) / 1000000} MB";
|
||||
}
|
||||
public string GetRSSI()
|
||||
{
|
||||
return $"{RSSI} dBm";
|
||||
}
|
||||
public string GetLastMonthRX()
|
||||
{
|
||||
return $"{LastMonthRX / 1000000} MB";
|
||||
}
|
||||
public string GetLastMonthTX()
|
||||
{
|
||||
return $"{LastMonthTX / 1000000} MB";
|
||||
}
|
||||
public string LastMonthTotal()
|
||||
{
|
||||
return $"{(LastMonthRX + LastMonthTX) / 1000000} MB";
|
||||
}
|
||||
}
|
||||
|
||||
public partial class AxisCam
|
||||
{
|
||||
public String TableColor()
|
||||
{
|
||||
if (this.Connected == true)
|
||||
{
|
||||
return "table-success";
|
||||
}
|
||||
return "table-danger";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,6 +82,12 @@ namespace UCS_Status_Monitor
|
||||
_telegramBotService.Send($"♻️ <b>{system.ComputerName}</b> UCS restarted");
|
||||
}
|
||||
}
|
||||
//TODO check usb stick, send telegram
|
||||
//if (system.USBDisks == "??" && !string.IsNullOrEmpty(telemetry.ComputerInfo.USBDisks))
|
||||
//{
|
||||
|
||||
//}
|
||||
|
||||
system.Update(telemetry);
|
||||
dbContext.UCSSystems.Update(system);
|
||||
}
|
||||
|
||||
@@ -26,16 +26,16 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.3">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.7">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MQTTnet" Version="3.1.2" />
|
||||
<PackageReference Include="MQTTnet.Extensions.ManagedClient" Version="3.1.2" />
|
||||
<PackageReference Include="MQTTnet" Version="4.0.2.221" />
|
||||
<PackageReference Include="MQTTnet.Extensions.ManagedClient" Version="4.0.2.221" />
|
||||
<PackageReference Include="System.DirectoryServices.AccountManagement" Version="6.0.0" />
|
||||
<PackageReference Include="Telegram.Bot" Version="17.0.0" />
|
||||
<PackageReference Include="Telegram.Bot" Version="18.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
33
UCS_Status_Monitor/Views/Home/Cameras.cshtml
Normal file
33
UCS_Status_Monitor/Views/Home/Cameras.cshtml
Normal file
@@ -0,0 +1,33 @@
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$(function () {
|
||||
setInterval(UpdateTable, 1000);
|
||||
UpdateTable();
|
||||
});
|
||||
});
|
||||
function UpdateTable() {
|
||||
$.getJSON("@Url.Action("GetCamerasTable", "Home")", function (data) {
|
||||
$("#cams").empty();
|
||||
$.each(data, function (i, cam) {
|
||||
$("#cams").prepend('<div class="col mb-4">' +
|
||||
'<div class="card ' + cam.tableColor + ' rounded" style="width: 18rem;">'+
|
||||
'<div class="card-body py-1 h-auto" ><h5 class="card-title text-center my-1">' + cam.device + '</h5></div>' +
|
||||
'<ul class="list-group list-group-flush">' +
|
||||
'<li class="list-group-item py-2">' + cam.location + '</li>' +
|
||||
'<li class="list-group-item py-2">Connected: ' + cam.connected + '</li>' +
|
||||
'<li class="list-group-item py-2">Timestamp: ' + cam.timestamp + '</li>' +
|
||||
'</ul>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<div class="container-fluid">
|
||||
<div class="row" id="cams">
|
||||
</div>
|
||||
</div>
|
||||
@@ -32,10 +32,20 @@
|
||||
@Html.ActionLink("Overview", "Overview", "Home", null, new { @class = "nav-link" })
|
||||
</li>
|
||||
}
|
||||
<environment include="Development">
|
||||
@if (User.Identity.IsAuthenticated)
|
||||
{
|
||||
|
||||
<li class="nav-item">
|
||||
@Html.ActionLink("Sensors", "Sensors", "Home", null, new { @class = "nav-link" })
|
||||
</li>
|
||||
|
||||
}
|
||||
</environment>
|
||||
@if (User.Identity.IsAuthenticated)
|
||||
{
|
||||
<li class="nav-item">
|
||||
@Html.ActionLink("Sensors", "Sensors", "Home", null, new { @class = "nav-link" })
|
||||
@Html.ActionLink("Cameras", "Cameras", "Home", null, new { @class = "nav-link" })
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user