271 lines
7.7 KiB
C#
271 lines
7.7 KiB
C#
using System.Text;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
namespace DataCollectorWebApp;
|
|
|
|
public class LoginResponse
|
|
{
|
|
public string Token { get; set; }
|
|
public object User { get; set; } // or a User class if needed
|
|
public bool AccessToSalimax { get; set; }
|
|
public bool AccessToSalidomo { get; set; }
|
|
public bool AccessToSodiohome { get; set; }
|
|
public bool AccessToSodistoreMax { get; set; }
|
|
}
|
|
|
|
|
|
public class Installation
|
|
{
|
|
//Each installation has 2 roles, a read role and a write role.
|
|
//There are 2 keys per role a public key and a secret
|
|
//Product can be 0 or 1, 0 for Salimax, 1 for Salidomo
|
|
public String Name { get; set; }
|
|
public String Location { get; set; }
|
|
public String Region { get; set; } = "";
|
|
public String Country { get; set; } = "";
|
|
public String VpnIp { get; set; } = "";
|
|
public String InstallationName { get; set; } = "";
|
|
|
|
public String S3Region { get; set; } = "sos-ch-dk-2";
|
|
public String S3Provider { get; set; } = "exo.io";
|
|
public String S3WriteKey { get; set; } = "";
|
|
public String S3Key { get; set; } = "";
|
|
public String S3WriteSecret { get; set; } = "";
|
|
public String S3Secret { get; set; } = "";
|
|
public int S3BucketId { get; set; } = 0;
|
|
public String ReadRoleId { get; set; } = "";
|
|
public String WriteRoleId { get; set; } = "";
|
|
public Boolean TestingMode { get; set; } = false;
|
|
public int Status { get; set; } = -1;
|
|
public int Product { get; set; } = 0;
|
|
public int Device { get; set; } = 0;
|
|
public string SerialNumber { get; set; } = "";
|
|
|
|
public String OrderNumbers { get; set; }
|
|
public String VrmLink { get; set; } = "";
|
|
}
|
|
|
|
[Controller]
|
|
public class InstallationsController : Controller
|
|
{
|
|
|
|
|
|
|
|
[HttpGet]
|
|
[Route("/Installations")]
|
|
[Produces("text/html")]
|
|
public async Task<IActionResult> Index()
|
|
{
|
|
const string HtmlHeader = @"
|
|
<html>
|
|
<head>
|
|
<title>Inesco Energy Installations Overview</title>
|
|
<style>
|
|
body {
|
|
font-family: sans-serif;
|
|
margin: 2rem;
|
|
}
|
|
table {
|
|
border-collapse: collapse;
|
|
width: 100%;
|
|
font-size: 0.9rem;
|
|
}
|
|
th, td {
|
|
padding: 0.75rem;
|
|
border: 1px solid rgb(200, 200, 200);
|
|
text-align: left;
|
|
}
|
|
thead th {
|
|
background-color: #f0f0f0;
|
|
font-weight: bold;
|
|
border-bottom: 2px solid #EB9486;
|
|
}
|
|
tbody tr:nth-child(odd) {
|
|
background-color: #f9f9f9;
|
|
}
|
|
a {
|
|
color: #0645AD;
|
|
text-decoration: none;
|
|
}
|
|
a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.status-circle {
|
|
display: inline-block;
|
|
width: 15px;
|
|
height: 15px;
|
|
border-radius: 50%;
|
|
margin-left: 50%;
|
|
}
|
|
.status-0 { background-color: #4CAF50; } /* Green */
|
|
.status-1 { background-color: #FF9800; } /* Orange */
|
|
.status-2 { background-color: #F44336; } /* Red */
|
|
|
|
.centered {
|
|
text-align: center;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.offline-symbol {
|
|
font-size: 1.2rem;
|
|
color: #F44336; /* Gray */
|
|
display: inline-block;
|
|
line-height: 1;
|
|
width: 15px;
|
|
height: 15px;
|
|
border-radius: 50%;
|
|
margin-left: 50%;
|
|
}
|
|
|
|
|
|
.status-cell {
|
|
text-align: center; /* center horizontally */
|
|
vertical-align: middle; /* center vertically */
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Installation Overview</h1>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th class=""centered"">Name</th>
|
|
<th class=""centered"">Product</th>
|
|
<th class=""centered"">Location</th>
|
|
<th class=""centered"">VPN IP</th>
|
|
<th class=""centered"">Status</th>
|
|
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
";
|
|
|
|
const string HtmlFooter = @"
|
|
</tbody>
|
|
</table>
|
|
</body>
|
|
</html>
|
|
";
|
|
|
|
|
|
|
|
string GetProductName(int productId)
|
|
{
|
|
return productId switch
|
|
{
|
|
0 => "Salimax",
|
|
1 => "Salidomo",
|
|
2 => "SodioHome",
|
|
3 => "SodistoreMax",
|
|
};
|
|
}
|
|
|
|
string GetStatusHtml(int status)
|
|
{
|
|
if (status == -1)
|
|
{
|
|
return "<span class='offline-symbol' title='Offline'>×</span>";
|
|
}
|
|
|
|
|
|
var statusClass = $"status-{status}";
|
|
var title = status switch
|
|
{
|
|
0 => "Online",
|
|
1 => "Warning",
|
|
2 => "Error",
|
|
_ => "Unknown"
|
|
};
|
|
|
|
return $"<span class='status-circle {statusClass}' title='{title}'></span>";
|
|
}
|
|
|
|
|
|
string BuildRowHtml(Installation i) => $@"
|
|
<tr>
|
|
<td>{i.Name}</td>
|
|
<td>{GetProductName(i.Product)}</td>
|
|
<td>{i.Location}</td>
|
|
<td>{i.VpnIp}</td>
|
|
<td>{GetStatusHtml(i.Status)}</td>
|
|
</tr>
|
|
";
|
|
|
|
var installations = await FetchInstallationsFromApi();
|
|
|
|
var sb = new StringBuilder();
|
|
sb.Append(HtmlHeader);
|
|
|
|
foreach (var i in installations)
|
|
{
|
|
sb.Append(BuildRowHtml(i));
|
|
}
|
|
|
|
sb.Append(HtmlFooter);
|
|
return Content(sb.ToString(), "text/html");
|
|
}
|
|
|
|
|
|
public async Task<List<Installation>?> FetchInstallationsFromApi()
|
|
{
|
|
|
|
var username = "baumgartner@innov.energy";
|
|
var password = "1234";
|
|
|
|
using var http = new HttpClient { BaseAddress = new Uri("https://monitor.inesco.energy/api/") };
|
|
|
|
// Step 1: Login
|
|
var loginResponse = await http.PostAsync($"Login?username={username}&password={password}", null);
|
|
if (!loginResponse.IsSuccessStatusCode)
|
|
{
|
|
Console.WriteLine("Login failed with status code {StatusCode}", loginResponse.StatusCode);
|
|
return null;
|
|
}
|
|
|
|
var loginData = await loginResponse.Content.ReadFromJsonAsync<LoginResponse>();
|
|
if (loginData?.Token is null)
|
|
{
|
|
Console.WriteLine("Login succeeded but token was missing");
|
|
return null;
|
|
}
|
|
|
|
var token = loginData.Token;
|
|
Console.WriteLine($"Token: {token}");
|
|
var installations = new List<Installation>();
|
|
|
|
var getInstallationsRequestResponse = await http.GetAsync($"GetAllInstallationsFromProduct?product=0&authToken={token}");
|
|
|
|
var newInstallations= await getInstallationsRequestResponse.Content.ReadFromJsonAsync<List<Installation>>();
|
|
if (newInstallations != null)
|
|
{
|
|
installations.AddRange(newInstallations);
|
|
}
|
|
|
|
getInstallationsRequestResponse = await http.GetAsync($"GetAllInstallationsFromProduct?product=1&authToken={token}");
|
|
newInstallations= await getInstallationsRequestResponse.Content.ReadFromJsonAsync<List<Installation>>();
|
|
if (newInstallations != null)
|
|
{
|
|
installations.AddRange(newInstallations);
|
|
}
|
|
|
|
getInstallationsRequestResponse = await http.GetAsync($"GetAllInstallationsFromProduct?product=2&authToken={token}");
|
|
newInstallations= await getInstallationsRequestResponse.Content.ReadFromJsonAsync<List<Installation>>();
|
|
if (newInstallations != null)
|
|
{
|
|
installations.AddRange(newInstallations);
|
|
}
|
|
|
|
getInstallationsRequestResponse = await http.GetAsync($"GetAllInstallationsFromProduct?product=3&authToken={token}");
|
|
newInstallations= await getInstallationsRequestResponse.Content.ReadFromJsonAsync<List<Installation>>();
|
|
if (newInstallations != null)
|
|
{
|
|
installations.AddRange(newInstallations);
|
|
}
|
|
|
|
|
|
//Console.WriteLine("Installations retrieved ",installations);
|
|
return installations;
|
|
}
|
|
|
|
} |